Skip to content

Hook Points & Bus Topics

The two systems answer different questions. Hooks ask permission: handlers run in priority order (default priority 100, ties keep registration order), share one mutable context table, and any false return (or error, unless the point is FailOpen) cancels the action. Bus topics announce facts: handlers get (topic, ...), run independently, and cannot cancel anything. Both registries create points and topics on first use, so your own names cost nothing to add.

The mechanics live on Hooks and Signals & Bus. Everything below is verified against the framework source (Hooks:fire, Bus:publish call sites). Entries marked are fired or published by the source but absent from the README’s central catalog table — each is documented on its owning module’s page.

All server-side.

Point Context Mode Fired
Intent.<Channel> {Name, Player, Session, Args, Seq?} fail-closed Before every intent handler (NetDriver). Validators may rewrite Args (clamp, normalize) — the handler receives the mutated copy
Request.<Channel> {Name, Player, Session, Args} fail-closed Before every request handler (NetDriver); a rejection answers the client with the channel’s RejectValue
Intent.BusPublish.<Topic> {Name, Player, Session, Args} fail-closed Client-to-server bus publish (BusBridge), after the exact-name whitelist and rate limit
Session.Start / Session.End {Session, Player} observational Player join/leave (Sessions). The kernel ignores the verdict, but handlers run synchronously before the matching bus topic — seed per-player state here and bus subscribers already see it
Net.RateLimited {Player, Channel} fail-open A channel’s token bucket rejected a message (Rate limiting)
Net.FloodDetected {Player, Bytes, PayloadBytes, BudgetBytes} fail-open The transport dropped a client that blew its byte budget (Rate limiting)
AntiExploit.MovementViolation {Player, Session, Type, HorizontalSpeed, Displacement, Strikes} fail-open A movement sample failed validation (Movement monitor)
Intent.Interact {Session, Player, Id, Instance, Definition} fail-closed Every prompt trigger (InteractionKit); the kit’s distance/line-of-sight/cooldown gate sits at priority 50

Kit channels are ordinary intents, so their points follow the same shape — Intent.WK_Fire, Intent.SK_Cast, Intent.Checkpoint, Intent.Settings_Set — and you prepend rules at lower priority numbers without forking the kit.

Fail-open policy gates the kits fire before acting on an already-validated request. Fail-open here is deliberate: these carry game rules (tournament locks, safe zones, friendly fire), and a crashing rule handler should not brick the kit’s core loop. Return false to veto.

Point Context Mode Fired
Inventory.CanEquip {Session, Id, SlotName} fail-open Before an equip mutates the bag (InventoryKit)
Inventory.CanUse {Session, Id, SlotIndex} fail-open Before an item’s OnUse runs (InventoryKit)
Craft.CanCraft {Session, RecipeId, Station} fail-open Before inputs are taken — verify the claimed station here (CraftingKit)
Companion.CanSummon {Session, CompanionId} fail-open Before a summon — gate ownership here (CompanionKit)
Party.CanInvite {From, To} fail-open Before an invite is created (PartyKit)
Melee.CanHit {Attacker, Victim, Attack} fail-open On every hit-frame candidate — TeamKit registers friendly-fire vetoes here at priority 40 (MeleeKit)
Weapon.CanDamage {Session, Attacker, Victim, WeaponId, Weapon} fail-open Before a validated shot deals damage — TeamKit plugs friendly-fire policy in here (WeaponKit)

Handlers receive (topic, ...); the args below follow the topic name.

Topic Args Published when
Kernel.SessionStart / Kernel.SessionEnd session Join/leave; SessionEnd fires before the session object is destroyed, so bound state is still readable (Sessions)
Kernel.ProfileLoaded session, profile DataDriver finished loading a player’s profile
Kernel.ProfileRestored session, profile A corrupt or unmigratable record was restored from backup — tell the player, ping your webhook (DataDriver)
Kernel.ScriptError message, trace, source, count ErrorWatch captured (or re-counted) a script error
Kernel.Overload statsSnapshot Diagnostics saw deferred work three windows in a row — the scheduler is saturated (Kernel & boot)
Kernel.SoftShutdown playerCount Update migration is about to teleport everyone out (SoftShutdown)
Commerce.PurchaseGranted player, productId, purchaseId A receipt was processed — exactly once per purchase (Receipts)
Topic Args Published when
Intent.<Channel> session, ...validatedArgs AFTER an accepted intent ran — the observational twin of the hook chain (NetDriver)
Net.IntentRejected player, channelName A validator, missing guard, or crashing handler rejected an intent (NetDriver)
Net.RateLimited player, channelName Token bucket rejection (Rate limiting)
Net.FloodDetected player, bytes, payloadBytes, budgetBytes Transport-level flood drop (Rate limiting)
Topic Args Published when
AntiExploit.MovementViolation player, violationType, strikes A movement strike was recorded (Movement monitor)
Topic Args Published when
Zone.Entered / Zone.Left zoneName, player A player crossed a zone boundary — leaves fire before enters (Zones)
Zone.EntityEntered / Zone.EntityLeft zoneName, entity A tracked entity (NPC, prop, vehicle) crossed a zone boundary (Zones)
Effects.Applied player, effectName, stacks Effect applied or stacked (Effects)
Effects.Expired player, effectName Effect expired or was removed (Effects)
Effects.Blocked player, effectName, byEffect An apply was blocked by a holding Immune ward (Effects)
Effects.Cleansed player, category?, count A cleanse removed count effects (Effects)
Projectile.Hit ownerSession, victim, defId, position A server-simulated projectile landed (Projectiles)
Config.Changed key, value LiveConfig saw a new value (local set or remote poll)
Settings.Changed session, key, value A setting was written — client intent or server set (Player settings)
Matchmaking.Queued / Matchmaking.Dequeued player, queueName Queue membership changed (Matchmaking)
Matchmaking.MatchFound / Matchmaking.TeleportFailed queueName, members Match lifecycle (Matchmaking)
Ragdoll.Started / Ragdoll.Ended model A ragdoll engaged / restored (Ragdoll)
Leaderboard.Updated boardName, entries A board’s cached page refreshed (Leaderboards)
Topic Args Published when
Round.PhaseChanged phaseName, duration RoundKit advanced a phase
Obby.Checkpoint player, stage CheckpointKit accepted a checkpoint
Spell.Cast / Spell.Interrupted session, spellId SpellKit outcome
Weapon.Fired / Weapon.Hit (session, weaponId, origin, direction) / (session, victim, weaponId, position) WeaponKit accepted a shot / landed a hit
Weapon.ShotRejected player, reason WeaponKit refused a shot
Quest.Progress player, questId, objectiveIndex, count, required An objective advanced (QuestKit)
Quest.Completed player, questId Every objective met — Repeatable quests reset after (QuestKit)
Interact.Triggered / Interact.Rejected (session, id, instance) / (player, id) A prompt interaction passed / failed validation (InteractionKit)
Procedural.Spawned / Procedural.Removed archetypeName, model Runtime geometry lifecycle (ProceduralKit)
Procedural.Updated archetypeName, model, appliedParams A parameter batch applied and the model regenerated (ProceduralKit)
Procedural.Rejected archetypeName, param, error A parameter failed validation (ProceduralKit)
Inventory.Granted session, id, granted A grant landed — granted is the count that fit (InventoryKit)
Inventory.Taken session, id, count An all-or-nothing take succeeded (InventoryKit)
Inventory.Equipped / Inventory.Unequipped session, slotName, id An equip slot changed (InventoryKit)
Inventory.Used session, id, slotIndex An OnUse item was consumed (InventoryKit)
Inventory.Changed session Any bag mutation — fires alongside the owner’s INV_Sync push (InventoryKit)
Loot.Rolled tableName, items, session? A table was rolled — session is nil for playerless roll() (LootKit)
Loot.Awarded session, tableName, granted, overflow An award() granted through InventoryKit (LootKit)
Craft.Started session, recipeId, finishAt A timed craft queued (CraftingKit)
Craft.Completed session, recipeId, output A craft finished and the output granted (CraftingKit)
Craft.Cancelled session, recipeId A craft was cancelled — inputs refunded (CraftingKit)
Craft.Overflow session, recipeId, overflow Output that could not fit the bag (CraftingKit)
Shop.Bought session, shopId, itemId, granted, cost A buy granted and charged (ShopKit)
Shop.Sold session, shopId, itemId, count, payout A sell took items and paid out (ShopKit)
Shop.Rejected player, shopId, itemId, reason A buy/sell refused (ShopKit)
Companion.Summoned session, companionId, npc A companion spawned (CompanionKit)
Companion.Dismissed session, companionId Dismissed by the owner or replaced by a new summon (CompanionKit)
Companion.Died session, companionId The companion’s NPC died (CompanionKit)
Party.Created / Party.Disbanded party / partyId A party formed on first accept / hit zero members (PartyKit)
Party.Joined / Party.Left party, player Membership changed (PartyKit)
Party.Kicked / Party.Promoted party, member Leader action — promote also fires on leader inheritance (PartyKit)
Party.Invited from, target An invite was created (PartyKit)
Team.Assigned player, team, previous? A team assignment — auto-balance or explicit assign (TeamKit)
Melee.Hit attacker, victim, attackName, damage A hit frame connected (MeleeKit)
Melee.Blocked victim, attacker, attackName, chippedDamage A block absorbed a hit (MeleeKit)
Melee.GuardBroken victim, attacker, attackName A guard-break shattered a block (MeleeKit)
Melee.Parried parrier, attacker, attackName A timed parry killed the swing (MeleeKit)
Melee.Staggered entity, seconds A stagger applied (MeleeKit)
Melee.Combo entity, chainLength A combo chained through ComboNext (MeleeKit)
Melee.State entity, state A combatant’s state machine changed (MeleeKit)
Move.Used session, name, position MoveKit.server accepted a metered ability use (MoveKit)
Move.Rejected player, name, reason The server’s charge/cooldown books refused ("Charges" or "Cooldown") (MoveKit)
Npc.Spawned / Npc.Died npc NPCKit lifecycle — Died precedes the despawn delay
Npc.Action npc, actionName, target A moveset action executed (NPCKit)
Npc.Heard npc, heardPosition, source? A sound survived range/occlusion for this npc — position pre-blurred by its skill (NPCKit)
Npc.Suspicious npc, target, glimpsedPosition Graded detection reached half charge — the npc glimpsed something (NPCKit)
Npc.Damaged npc, attacker? The npc registered damage — aim suppressed, unseen attackers drop into hearing memory (NPCKit)
Npc.Reload npc, actionName, seconds A magazine emptied and the reload pause started (NPCKit)
Npc.Windup npc, actionName, target, windupSeconds A telegraphed melee windup started — the dodge window (NPCKit)
Npc.Path npc, waypoints A new route was computed (full list, own position first) — hook for path visualization (NPCKit)
Npc.Hitscan npc, origin, hitPosition, victim? A hitscan action fired (hit or miss) — hook for tracers (NPCKit)
Npc.Defense npc, reactionName, success, context A defensive reaction attempt — deflect flash or fumble, hook VFX here (NPCKit)
Npc.Tactic npc, tactic Director/behavior state flip: Pressure/Flank/Suppress/Cover/Peek/Flee — hook client animation polish (NPCKit)

Published on the kernel the module is attached to — for these, typically the client.

Topic Args Published when
Input.<Action> state, inputObject Client-side — an InputDriver action changed state
Move.Triggered name, context Client-side — a MoveKit ability passed its context gate and ran
Audio.Cue soundName, cueName, handle Playback crossed a registered cue time, loop-aware (AudioKit)
Audio.Subtitle / Audio.SubtitleEnded (text, duration) / () Dialogue line started / finished — wire your subtitle UI here (AudioKit)
Anim.Marker model, animName, markerName, param An animation marker fired on a rig (AnimKit)
Preload.Started / Preload.Progress / Preload.Done (total) / (loaded, total, assetId, ok) / (loaded, total, failed) Asset warm-up lifecycle — wire your loading screen here (Preload)
Device.Benchmarked result A DeviceBench run completed (cached thereafter)
Device.QualityChanged quality, profile The DeviceBench governor dialed effective quality up or down (DeviceBench)
Hair.Rigged character, meshPart, boneNames HairKit baked a skeleton into a hair mesh

One topic is consumed rather than published: publish AntiExploit.Forgive with (player) right before a legit server-side teleport and the next movement sample is pardoned. MoveKit (abilities with Forgive = true) and TeamKit (spawn pivots) publish it for you. See Movement monitor.