Skip to content
KCKingdoms Connected Scripting APIScripting guides and API
GuideMaintainer authored

Events and handlers

Subscribe to events, write async handlers safely, look up every event the server and client raise, and emit events of your own.

Almost everything a resource does starts in an event handler. Subscribe with Events.on; the arguments are typed from the EventMap. If an event is not in the lists below, the game does not raise it.

// server
Events.on("playerSpawned", (player) => {
Chat.sendToAll(`${player.nickname} rode into town.`);
});
Call Does
Events.on(name, fn) Subscribes. Returns a function that unsubscribes.
Events.once(name, fn) Removes the handler before its first call. Returns nothing.
Events.off(name, fn) Unsubscribes the same name and function.
// server
const stop = Events.on("playerChat", (player, text) => {
console.log(`${player.nickname}: ${text}`);
});
stop();

Handlers are removed when your resource stops; you never need to clean up there. See Resources.

Handlers run in registration order, each up to its first await. The emitter gets a promise that settles when all have; if any throws or rejects, it rejects with an AggregateError. A synchronous throw is also logged with its stack.

Code after an await runs later than the event, so re-check that a player is still connected before acting on them. Some events need an answer in the handler itself:

  • playerSpawning: call player.spawn(...) before any await, or the player lands on the level’s default start point.
  • horseMounting, horseGearChanging, playerPickpocketStart, doorInteract: return false to refuse. An async handler cannot refuse.
  • playerConsuming, playerConsumptionEffects, playerPoisonAbsorbing: return false synchronously to refuse the serving, its native effects, or added pot poison respectively. See Food and potions.

On the client, questTrackingChanged, poiDiscovered and noclipChanged do not await handler promises. Your async handler still runs; nothing waits.

Handles are valid inside the handler. Teardown events (playerDisconnect, npcDestroy and the other ...Destroy events) fire while the handle still reads, so read a name there one last time. To use a subject later, keep its id and look it up again: getById returns null once it is gone.

// server
const inQueue = new Set<number>();
Events.on("playerSpawned", (player) => inQueue.add(player.id));
Events.on("playerDisconnect", (player) => inQueue.delete(player.id));
function announce(text: string): void {
for (const id of inQueue) {
const player = Player.getById(id);
if (player) Chat.sendToPlayer(player, text);
}
}

An argument typed Player | null (noted as attacker?, player? and so on) can be null: check it. The EventMap reference has exact types and every union value.

Guides: Join and spawn, Health and stats, Buffs, Chat.

Event Arguments Fires when
playerConnect player Their body exists, still loading. ready is false.
playerSpawning player Their body needs a place to stand. Answer synchronously.
playerSpawned player They are standing in the loaded world. Give kit here.
playerDisconnect player They are leaving; the handle still reads.
playerHit player, attacker, hit A player hit or NPC melee hit is about to take health. Return false to refuse; change hit.damage to set the amount.
playerDamage player, attacker?, amount, bodyPart?, reason Health came off them, after any playerHit ruling.
playerInjured player, bodyPart A limb becomes injured.
playerInjuryHealed player, bodyPart A limb injury is gone.
playerDied player, killer?, reason A death is accepted. No automatic respawn.
playerChat player, text They submit a plain chat line.
playerCommand player, command, args A / line no built-in command claimed.
playerBuffAdded player, buff, source An effect appears. source is "server" or "native".
playerBuffRemoved player, buff, reason An effect leaves. reason is "server" or "expired".
playerBuffBlocked player, buff The game tried a buff kind you Buffs.claimed.
playerPickpocketStart thief, victim A Rob attempt begins. Return false to refuse.
playerPickpocketed thief, victim, items A theft settled; items is what really moved.
playerPickpocketCaught thief, victim The victim noticed. Nothing was taken.

For playerHit, the attacker can be a player or NPC. The attacker/killer in player damage and death events can also be null. Check the type before using player-only properties. Lowering health from a script raises damage with a null attacker; see Set and restore stats.

Guides: Horses, Dogs.

Event Arguments Fires when
horseSpawn, horseDestroy horse A horse is created, or is being despawned.
horseMounting horse, player A player climbs on. Return false to refuse.
horseMount, horseDismount horse, player? A rider got on or off (including on death or disconnect).
horseDamage horse, attacker?, amount, reason Health came off a horse.
horseDeath horse, killer?, reason A horse dies.
horseGearChanging horse, player?, gear A player changes gear. Return false to refuse.
horseIntentDone horse, status A move or patrol leg reached, was blocked or failed.
horseGearChanged horse, player?, gear Gear changed on every client. player is null for a script.
dogSpawn, dogDestroy dog A dog is created, or is being despawned.
dogOwnerChanged dog, player? A dog is handed over or left masterless.
dogModeChanged dog, mode Its companion mode actually changes.

Guides: Spawn NPCs, Move NPCs, NPC damage and death.

Event Arguments Fires when
npcSpawn, npcDestroy npc An NPC is spawned or adopted, or is being despawned.
npcIntentDone npc, status An order ends: reached, blocked or failed.
npcDamage npc, attacker?, amount Health came off, as agreed by the server.
npcDeath npc, attacker? Its health runs out. The corpse stays.
patrolWaypoint npc, info A waypoint was reached, blocked or failed.
patrolFinished npc, info A patrol completed, failed or was cancelled.
npcRevive npc A dead NPC is brought back.
npcInteract npc, player A player presses use on an interactable NPC.
npcSimulatorChange npc, player? The client running it changes. null means dormant.
npcInventoryReady npc Initial server-owned stock is established.
npcInventoryChanged npc, change Stock changes, including committed loot transfers.
npcHarvested npc, player Animal harvesting completes.

NPC damage and death attackers are Player | Npc | null. Named patrol routes explains the route ID, waypoint index and phase carried in patrol events.

Guides: Time and weather, Doors and gates, Props, Particle effects, Markers, Items.

Event Arguments Fires when
worldResourcesReady none All configured exports loaded. Check WorldResource.ready when starting later.
worldDayChange day The clock crosses midnight. day is the new one.
worldWeatherChange preset, previous, seconds A weather blend starts.
doorInteract player, door, action, keySide A player works a door. Return false to refuse.
propSpawn, propDestroy prop A prop is created, or is being despawned.
vfxSpawn, vfxDestroy vfx An effect is placed, or is being stopped.
markerPlace, markerRemove marker A marker is drawn, or is being removed.
markerEnter, markerExit marker, player A player walks into or out of a trigger marker.
groundItemSpawn, groundItemDestroy groundItem A stack is laid down, or is being removed.
groundItemPickup groundItem, player? A pickup was granted. groundItemDestroy follows.

Guides: Quests, Dialogue, Shops.

Event Arguments Fires when
questTrackingChanged quest, player, tracked A player follows or unfollows a quest. Cannot be refused.
dialogueChoice session, player, optionId A player picks an option.
dialogueClosed session, player, reason A conversation ends.
vendorTrade vendor, player, bought, sold, balance A deal has settled.
vendorClosed vendor, player, reason A trading session ends.
Event Arguments Fires when
resourceStart resourceName Any resource’s scripts have run, just before it counts as running. See Resources.
resourceStop resourceName Any resource is stopping, before cleanup.
entityStateChange entity, key, value, previous A state bag key changes. See State bags.
Event Arguments Fires when Guide
resourceStart, resourceStop resourceName As on the server. Resources
entityStateChange entity, key, value, previous A state write arrives. State bags
questTrackingChanged questKey, tracked This player follows or unfollows a quest. Quests
vendorOpened session, npc The trade screen actually comes up. Shops
vendorClosed session, reason That screen goes away. Shops
poiDiscovered poiId A silent POI discovery is accepted. Map and blips
mapOpened, mapClosed none The map screen opens or closes. Map and blips
mapWaypointSet position, mapId, moved The player drops or moves their map marker. Map and blips
mapWaypointCleared position, mapId The player removes it. Map and blips
followStarted target A queued native follow entered. Following
followStopped target, reason A follow stopped or failed to enter. Following
monologueSuppressed text, textKey A local character remark was suppressed. HUD
noclipChanged active, reason Free camera starts or ends. Camera and noclip
browserCreated, browserLoadingStart, browserDocumentReady, browserLoadingFailed event A web view is created, loads, is ready for Web.emit, or fails. HTML pages
browserNavigate, browserPopup, browserOriginChange, browserResourceBlocked event A view navigates, blocks a popup, changes origin, or blocks a request. HTML pages
browserCursorChange, browserTooltip, browserInputFocusChange, browserConsoleMessage event A view asks for a cursor or tooltip, gains or loses text focus, or logs. Page data bridge

Chat lines from the server arrive through a reserved chatMessage event that the declarations mention but do not type; see Chat and /commands.

Side Event Arguments and purpose
Server playerInventoryReady player: the initial inventory is displayed.
Server playerInventoryChanged player, change: a committed inventory change.
Server playerCustomItemUse player, row, revision: a validated custom use request; no automatic consumption.
Server playerConsuming player, consumption: allow or refuse the serving.
Server playerConsumptionEffects player, consumption: keep or suppress its native effects.
Server playerPoisonAbsorbing player, consumption, buff: allow or block added pot poison.
Server playerConsumed player, consumption: successful native use was confirmed.
Server playerStatsChanged player, changes: stat changes grouped by tick, with previous and current values.
Client bookOpened id: the requested book reached the player’s hands.
Client bookClosed id, reason: reading ended or opening failed; promises are not awaited.

See Inventories, Custom items, Food and potions and Books and letters for timing and failure cases.

Any name that is not native is a custom event on the same bus. Every resource shares it, so prefix names with your resource name.

// server
Events.on("my-mode:round.end", (winner) => {
if (typeof winner !== "string") return; // custom arguments are `unknown`
Chat.sendToAll(`${winner} wins the round.`);
});
Events.emit("my-mode:round.end", "Ravens").catch((error) => {
console.error(`a round.end handler failed: ${String(error)}`);
});

Events.emit returns the promise described in Async handlers. await it or attach a .catch: an unhandled rejection triggers your errorBehavior.

Call Reaches
Events.emit(name, ...args) Every resource’s Events.on handlers.
Events.emitTo(resourceName, name, ...args) Only that resource’s Events.on handlers.
Events.emitLocal(name, ...args) Only your own Events.onLocal handlers. onLocal has no off.
Events.listenerCount(name) Not an emit: counts on and once handlers across resources.

Events between server and client use Events.onClient on the server, a separate table a client cannot use to reach native or resource events. See Send data between server and client.