UI and content
Register tracked panels, admin tools, phone apps, Toolgun modes, items, NPCs, localization and status effects.
Screen panels
The UI bootstrap creates a dedicated object with ScreenPanel, then calls the attach factory. Z-index is clamped from 0 to 590 so an addon cannot cover the loading screen at 600. A failed factory is retried up to five times, and a half-created object is destroyed.
SetCorePanelEnabled<T> can replace normal HUD surfaces. It cannot hide the loading screen, escape menu, community warning, rules or chat. Multiple addon hides are tracked independently and teardown restores visibility only when no remaining addon hides the panel.
Admin panels and permissions
RegisterAdminPanel adds a page under Addon Tools and declares its addon.<id>.<node> metadata. This controls Admin Console access to the page. It does not authorize a host mutation by itself. A network or RPC handler must still check the same permission on the host.
RegisterPermissionNode adds a discoverable node to rank editing. HasPermission checks that addon-scoped node for a player.
Phone apps
New apps join the native home grid. Input handlers receive Up, Down, Left, Right, Select and Back through LitherarpPhoneAppInputContext. Set Handled when consumed. An unhandled Back returns home.
Core app overrides can replace any combination of label, icon, order, content and input. Layers unwind in activation order. Core app hides are owner-tracked.
Chat commands and autocomplete
RegisterChatCommand always installs the handler on the host. The standard overload also publishes safe metadata for slash autocomplete. When a player types /he, a registered help command can appear beside matching native commands. Tab or a click inserts /help . The !help form remains executable, but autocomplete only opens for a single slash before the first space.
The host sends command metadata through a bounded, chunked snapshot. Handlers never enter that snapshot. A joining player receives the current catalog after activation. Registration, addon disable and re-apply update open chat panels without requiring the player to change the text already entered.
| Option | Default | Contract |
|---|---|---|
AllowWhileRestricted | false | Allows execution while the sender is cuffed or jailed. This is the options equivalent of the boolean overload. |
SuggestInChat | true | Includes command metadata in slash autocomplete. Set it to false when the command must stay out of the public metadata snapshot. |
Usage | /name | Text shown in the suggestion row. A custom value must start with the same slash command name, matched case-insensitively, followed by either the end of the string or a space. |
PermissionNode | empty | Accepts an addon-local node such as support, or the full node for the same addon, with a 160-character full-node limit. The standard client hides the suggestion without it and the host rejects direct execution before the handler. |
Validation and display rules
- Names use lowercase letters, digits, underscore or hyphen and contain at most 24 characters.
- Descriptions are normalized to one line and at most 160 characters. They may be literal text or a localization key registered with
RegisterLocalization. - Usage is normalized to one line and at most 96 characters. Invalid usage rejects registration.
- Each addon can register 64 commands. The host accepts at most 512 commands across all active addons.
- The panel shows at most eight matches. Native commands keep their established order, addon commands follow alphabetically, and names are deduplicated case-insensitively.
- Arguments split on whitespace, have no quoting syntax and are capped at 16. Parse
RawArgsyourself when the command needs a richer grammar. - A permission filter improves the normal UI, but it is not a secrecy boundary because suggested metadata is public. Use
SuggestInChat = falsewhen the name or description must not be published.
Register permission metadata from the client lifecycle so remote administrators can see the node in rank editing. Permission enforcement does not depend on that metadata registration. The host checks addon.<id>.<node> directly before invoking the handler.
Built-in names cannot be shadowed. The first addon to claim another name wins. Every successful registration is removed by context teardown, including disable, failed activation cleanup, re-apply and scene shutdown.
Gameplay content
| Surface | Context members | Notes |
|---|---|---|
| Toolgun | RegisterToolMode, RegisterToolAction | The relay validates owner, registered mode, permission, rate and payload bounds. The handler validates action-specific input, then uses TryAuthorize and Commit around the mutation. |
| Items and consumables | RegisterRuntimeItem, RegisterConsumable | The host owns effects and consumption. Package .item resources are available while their managed package is active. |
| Dealer products | RegisterDealerProduct | Adds an item to a native weed or meth dealer with host-side stack pricing. |
| NPCs | RegisterNpc, RegisterNpcKind, override and decorator methods | Builders return a GameObject or null to suppress. Runtime NPC objects are removed on teardown. |
| Status effects | ApplyStatusEffect, ApplyDamageOverTime | Context methods are the public mutation path. Effect ids are namespaced per addon, reapply refreshes duration and teardown removes active effects. Use an inter-addon service when several addons must coordinate one effect. |
| Chat commands | RegisterChatCommand | Host handlers receive parsed arguments and a reply helper. Handler-free slash suggestions sync to remote clients and disappear on teardown. |
| Localization | RegisterLocalization | Runtime entries override language-pack entries. Between addons, the first owner of a key wins until teardown. |
| Callback payload | Public members |
|---|---|
LitherarpChatCommandInvocation | Player, CommandName, RawArgs, parsed Args, and Reply(message). |
LitherarpAddonConsumableUseContext | Player, Stack, SlotIndex, mutable ConsumeItem, Notice, NoticeIcon and NoticeColor. |
LitherarpAddonToolActionContext | Player, Toolgun, ModeId, Action, raw PayloadJson, parsed Payload, readonly Results, TryAuthorize(target, targets, primaryTrace, secondaryTrace, validatedPayload) and Commit(params GameObject[] results). Treat relay payloads as untrusted. TryAuthorize can run once. Both mutators become inert as soon as the synchronous handler returns, so never retain this context for later work. Returning without authorization and commit is a rejected or no-op action with no post-hook. |
LitherarpToolgunActionContext | Immutable policy data for native and custom actions: nullable Target, captured TargetId and TargetName, readonly Targets, nullable PrimaryTrace and SecondaryTrace, and bounded normalized JSON Payload. |
LitherarpToolgunTrace | Nullable Target, world Position and surface Normal. |
LitherarpPhoneAppInputContext | State, Action and mutable Handled. |