Player and inventory hooks

Lifecycle, pawn factory, loadout, jobs, player damage and inventory transactions with explicit authority.

Subscription contract

Gameplay events run synchronously on the process that raises them. Core policy and committed state channels are host-side unless their row says local or exposes IsHostAuthoritative. Higher priorities run first. Equal priorities retain registration order. Track the returned IDisposable so disable removes the handler.

1public void OnHostLoaded( LitherarpAddonContext context )
2{
3 context.Track( LitherarpGameEvents.JobChangeRequested.Subscribe(
4 request =>
5 {
6 if ( request.RequestedJobId == "police" )
7 request.Deny( "Recruitment is closed." );
8 },
9 owner: context.AddonId,
10 priority: 100,
11 subscriptionId: "police-recruitment" ) );
12}
LitherarpGameEvent<T> memberContract
Subscribe(Action<T> handler, string? owner = null)Subscribes at priority zero and returns the teardown handle.
Subscribe(Action<T> handler, string? owner, int priority, string? subscriptionId = null)Subscribes with explicit ordering and a stable diagnostic id.
HasSubscribersRead-only fast-path indicator. Event publication remains internal to LitheraRP.
PriorityClamped from -1000 to 1000. Higher priorities run first; equal priorities retain registration order.
CapacityAt most 4,096 subscriptions per event channel and 256 per normalized owner. An omitted owner uses anonymous and has the same owner cap. A rejected subscription returns an inert disposable and logs one limit warning for that channel.

A LitherarpCancelableRequest exposes IsDenied, DenyReason and Deny(reason). The first denial wins. Recoverable handler failures are isolated; three consecutive failures quarantine that subscription until it is recreated. A handler taking at least 25 ms is rate-limited in diagnostics. Same-event recursion is bounded to a depth of eight. At the limit, a cancelable request is denied and a post notification is suppressed.

Hooks and payloads

HookPayload and public membersTiming and effect
ConnectionRequestedLitherarpConnectionRequest
Connection, SteamId, DisplayName, inherited Deny(reason)
Cancelable after server authorization, sanctions and effective whitelist checks, before a pawn exists.
PlayerConnectedLitherarpPlayerConnectedEvent
Connection
Post-event when an accepted connection becomes active on the host.
PlayerDisconnectingLitherarpPlayerDisconnectingEvent
Connection, nullable Player
Post notification before core persistence and pawn cleanup. Leaving cannot be canceled.
PlayerDisconnectedLitherarpPlayerDisconnectedEvent
Connection
Post notification after disconnect. The pawn may already be invalid.
WorldReadyLitherarpWorldReadyEvent
Scene
One host notification after map and persistent-world bootstrap. Hot addons should also use RunWhenWorldReady.
ClientWorldReadyLitherarpClientWorldReadyEvent
Scene
Local-client notification after each successful scene and verified addon snapshot barrier. A hot replacement lowers the barrier and emits again only after the complete snapshot succeeds.
PlayerSpawnRequestedLitherarpPlayerSpawnRequest
Kind, Scene, nullable Connection, nullable ExistingPlayer, JobId, SpawnTransform, PawnPrefabPath, HasCustomSpawnTransform, HasPawnFactory; SetPawnPrefab, SetPawnFactory, SetJobId, SetSpawnTransform, Deny
Cancelable before initial pawn creation or respawn reset. Only an initial spawn can replace the prefab or install the highest-priority pawn factory. A factory object must belong to the requested scene and must not already be network-spawned. A null or invalid result falls back to the selected prefab. Core-required components are still installed and validated.
PlayerPawnCreatedLitherarpPlayerPawnCreatedEvent
Player, Pawn, Connection, PawnPrefabPath, UsedPawnFactory; four-value Deconstruct compatibility overload
Post-event after initial pawn composition, before persistence restore and network spawn. UsedPawnFactory is an optional constructor value and is true only when the final valid pawn came from the factory, in which case PawnPrefabPath is empty. A null or invalid factory result reports false and the fallback prefab path actually used.
PlayerLoadoutRequestedLitherarpPlayerLoadoutRequest
Player, SandboxPlayer, Inventory, Kind, Job, GiveDefaultTools, GiveJobWeapons, ApplyJobKevlar, ApplyJobClothing, ApplySpawnProtection, IsMandatory; SetDefaultToolsEnabled, SetJobWeaponsEnabled, SetJobKevlarEnabled, SetJobClothingEnabled, SetSpawnProtectionEnabled, Deny
Cancelable policy before a normal core loadout. Denial suppresses that core loadout, not the authorized spawn. When IsMandatory is true, handlers may observe but denial and policy changes are ignored for the required system migration.
PlayerLoadoutAppliedLitherarpPlayerLoadoutAppliedEvent
Player, Inventory, Kind, JobId
Post-event after core loadout policy. Add addon-owned equipment here.
PlayerSpawnedLitherarpPlayerSpawnedEvent
Player, JobId, IsRespawn
Post-event when initial spawn or respawn is complete.
JobChangeRequestedLitherarpJobChangeRequest
Player, CurrentJobId, RequestedJobId, Deny
Cancelable before any job-change side effect.
JobChangedLitherarpJobChangedEvent
Player, PreviousJobId, NewJobId
Post-event after the job change committed.
PlayerDamageRequestedLitherarpPlayerDamageRequest
nullable Victim, nullable Attacker, nullable AttackerPlayer, Damage, Tags, DamageTags, Position, Origin; SetDamage, SetAttacker, SetPosition, SetOrigin, SetTags, AddTag, RemoveTag, BuildTagSet, Deny
Hot cancelable path after game filters and hitbox scaling, before armour or health changes. Damage, vectors, attacker references and tags are validated by their mutators.
PlayerDamagedLitherarpPlayerDamagedEvent
nullable Victim, BasePlayer, nullable Attacker, nullable AttackerPlayer, ResolvedDamage, HealthDamageApplied, DamageAbsorbedByArmour, UnappliedHealthDamage, PreviousHealth, CurrentHealth, PreviousArmour, CurrentArmour, Tags, Position, Origin, IsFatal
Host post-event after health and armour commit, including full armour absorption, and before PlayerDied. It separates approved pre-armour damage, real health loss, exact kevlar absorption and clamped lethal overkill.
PlayerDiedLitherarpPlayerDiedEvent
Victim, nullable Killer, Damage, Tags
Post-event after host death state committed.
ItemMoveRequestedLitherarpItemMoveRequest
Player, Kind, FromSlot, ToSlot, ItemId, Quantity, Deny
Compatibility pre-hook for backpack swap, split, equip-to-hotbar and store-from-hotbar requests.
InventoryMutationRequestedLitherarpInventoryMutationRequest
OperationId, Player, Kind, Source, Destination, ItemId, RequestedQuantity, Quantity, Reason, IsHostAuthoritative; SetQuantity, Deny
Cancelable transaction before backpack, hotbar, reserve-ammo or weapon-clip changes. IsHostAuthoritative is true when raised by the host. Core backpack, reserve-ammo and weapon-clip paths are host-authoritative; a custom owner-side caller must inspect this flag before treating the request as authoritative.
InventoryMutatedLitherarpInventoryMutationEvent
OperationId, Player, Kind, Source, Destination, ItemId, RequestedQuantity, AppliedQuantity, Reason
Post-event only after the transaction applies. Match OperationId to the request when authority matters because the post payload does not repeat IsHostAuthoritative.
ItemUseRequestedLitherarpItemUseRequest
Player, ItemId, Kind, Deny
Cancelable before a backpack consumable is consumed.
ItemUsedLitherarpItemUsedEvent
Player, ItemId, Kind
Post-event after one consumable unit is used.
ItemPickedUpLitherarpItemPickedUpEvent
Player, ItemId, Quantity
Post-event after an item enters a backpack from the world.
ItemDroppedLitherarpItemDroppedEvent
Player, ItemId, Quantity, OperationId; three-value Deconstruct compatibility overload
Host post-event only after a world object spawned and the root drop transaction completed. OperationId is an optional constructor value. Published quantities never exceed InventoryMutated.AppliedQuantity. Multiple lots retain their item ids, use deterministic order, omit zero quantities and share the root OperationId. This covers normal and death drops without duplicate publication.

Spawn and inventory enums

TypeValues
LitherarpPlayerSpawnKindInitial, Respawn.
LitherarpItemUseKindFood, Kevlar, Ammo, Addon.
LitherarpItemMoveKindSwap, Split, EquipToHotbar, StoreFromHotbar.
LitherarpInventoryContainerKindNone, Backpack, SafeDeposit, PhoneSlot, Hotbar, EquippedBackpack, StoredAmmo, AmmoReserve, WeaponClip, World, DeathLoot, Persistence.
LitherarpInventoryMutationKindAdd, Remove, Clear, Move, Swap, Split, Merge, Equip, Unequip, Drop, Pickup, Consume, Update, Restore.
LitherarpInventoryLocationContainer and Slot. Slot -1 means no fixed slot.

SetQuantity accepts Add, Remove, Move, Split, Drop, Pickup, Consume and Update. Structural operations keep their fixed cardinality. Synchronous inventory mutations attempted from an inventory hook are rejected to prevent recursion around another addon's decision.

Committed damage and drops

PlayerDamaged.ResolvedDamage is the approved value before kevlar. HealthDamageApplied is the real health delta, DamageAbsorbedByArmour is the exact amount consumed by PlayerKevlar, and UnappliedHealthDamage is lethal overkill that could not be applied below zero health.

Match ItemDropped.OperationId with InventoryMutated.OperationId when a drop creates several world lots. Every emitted lot belongs to the same completed root mutation. No event is raised for a failed spawn, an uncommitted mutation or a zero allocation.