Events

React to what happens in the game, and send messages between resources, the server and players' games. Handlers from Events.on run in the order added. Where an event says "Return false to refuse", one handler returning false is enough to refuse the action.

events.broadcast()

Events.broadcast(...args)

Sends an event to all connected players' games. Client handlers from Events.on get the payload parsed from JSON, up to 32 KB. A string that is JSON text is sent as is, and any other string arrives as that string.

events.emit()

Events.emit(name, ...args)

Raises an event for all resources on this side, the server or this player's game. The promise settles once all handlers have run, and rejects with an AggregateError if any threw.

events.fire()

Events.fire(...args)

Raises a private event, heard only by this resource's listen handlers.

events.fromClient()

Events.fromClient(name, fn)

Listens to an event sent by a player's game with Events.toServer. The handler gets the sender and the payload parsed from JSON. A changed client can send anything, so check the payload.

events.listen()

Events.listen(name, fn)

Listens to an event this resource raises with fire. Other resources can neither hear nor raise it.

events.listenerCount()

Events.listenerCount(...args)

How many handlers this side has for an event.

events.off()

Events.off(name, fn)

Removes a handler added with on or once.

events.offFromClient()

Events.offFromClient(name, fn)

Removes a handler added with fromClient or onceFromClient.

events.on()

Events.on(name, fn)

Runs the handler each time the event happens, for the game's events and your own from Events.emit alike.

events.once()

Events.once(name, fn)

Runs the handler the next time the event happens, then removes it.

events.onceFromClient()

Events.onceFromClient(name, fn)

As fromClient, for the next arrival only.

events.toResource()

Events.toResource(...args)

Raises an event for one resource only, by its name. Other resources do not hear it.

events.toServer()

Events.toServer(...args)

Sends an event from this player's game to the server, where Events.fromClient handlers get it with the sender. The payload goes as JSON, up to 32 KB. A string that is JSON text is sent as is, and any other string arrives as that string.

events.on('actionHintsChanged')

on(event: "actionHintsChanged", cb: () => void): void

Client only. The HUD's hints changed: one appeared or went, its text changed, it was greyed out, or a hold ring moved. ActionHint.shown() reads the new set.

events.on('areaEnter')

on(event: "areaEnter", cb: (area, entity, matchingDimension) => void): void

A player, horse or NPC entered an area, by its shape, in any dimension. The area is the level's, such as a house, interior, private ground or settlement, or a resource's. It also fires when an area is created, moved or enabled around a body.

events.on('areaExit')

on(event: "areaExit", cb: (area, entity, matchingDimension) => void): void

A player, horse or NPC left an area, or the area was destroyed or disabled around it, or the server's map changed.

events.on('bookClosed')

on(event: "bookClosed", cb: (id, reason) => void): void

A book closed.

events.on('bookOpened')

on(event: "bookOpened", cb: (id) => void): void

A Book opened in this player's game.

events.on('bookTextChanged')

on(event: "bookTextChanged", cb: (id, text, reason) => void): void

The text in an open book changed.

events.on('bookWritingEnded')

on(event: "bookWritingEnded", cb: (id, text) => void): void

The player stopped writing in a book.

events.on('cameraShotEnded')

on(event: "cameraShotEnded", cb: (player, reason) => void): void

A Camera.startShot ended by itself. The server's handler gets (player, reason), and the player's game gets (reason).

events.on('cartDestroy')

on(event: "cartDestroy", cb: (cart) => void): void

A cart is being removed, with everyone on it let off first.

events.on('cartEnter')

on(event: "cartEnter", cb: (cart, player, seat) => void): void

A player took a seat on a cart.

events.on('cartEntering')

on(event: "cartEntering", cb: (cart, player, seat) => void): void

A player is about to take a seat on a cart. Return false to refuse.

events.on('cartExit')

on(event: "cartExit", cb: (cart, player, seat) => void): void

A player left a cart's seat.

events.on('cartSpawn')

on(event: "cartSpawn", cb: (cart) => void): void

A cart or wagon was spawned.

events.on('consoleCommand')

on(event: "consoleCommand", cb: (command, parts) => void): void

Someone typed a command in the server console that the server does not handle itself.

events.on('craftingCompleted')

on(event: "craftingCompleted", cb: (player, details) => void): void

A craft gave its product.

events.on('craftingCompleting')

on(event: "craftingCompleting", cb: (player, proposal) => void): void

A craft is about to give its product. Return false to refuse, and the product is taken back.

events.on('craftingEnded')

on(event: "craftingEnded", cb: (player, details) => void): void

A crafting session ended: 'success', 'failed' or 'cancelled'.

events.on('craftingRecipeLearned')

on(event: "craftingRecipeLearned", cb: (player, details) => void): void

A player learned a custom recipe.

events.on('craftingRefunding')

on(event: "craftingRefunding", cb: (player, details, refund) => void): void

An unfinished craft is settling. Call refund() to return all materials still held, and otherwise the game's rules apply.

events.on('craftingStarted')

on(event: "craftingStarted", cb: (player, details) => void): void

A player started an alchemy batch, a smithing workpiece or a custom recipe.

events.on('craftingStarting')

on(event: "craftingStarting", cb: (player, proposal) => void): void

A player is about to start crafting. Return false to refuse.

events.on('craftingStationUsed')

on(event: "craftingStationUsed", cb: (player, details) => void): void

A player used a Crafting station with more than one recipe, and your resource chooses what they craft.

events.on('dialogueClosed')

on(event: "dialogueClosed", cb: (session, player, reason) => void): void

A conversation ended.

events.on('dialogueChoice')

on(event: "dialogueChoice", cb: (session, player, option) => void): void

A player chose an option in a conversation from Dialogue.open.

events.on('diceBadge')

on(event: "diceBadge", cb: (event) => void): void

A badge took effect on a throw.

events.on('diceMatchEnd')

on(event: "diceMatchEnd", cb: (match, first, second, winner, reason, firstScore, secondScore) => void): void

A dice match ended.

events.on('diceMatchStart')

on(event: "diceMatchStart", cb: (match, first, second, target) => void): void

A dice match began.

events.on('diceMove')

on(event: "diceMove", cb: (event) => void): void

A player held dice and continued or passed.

events.on('diceRoll')

on(event: "diceRoll", cb: (event) => void): void

Dice were thrown.

events.on('diceTableUse')

on(event: "diceTableUse", cb: (player, table, match) => void): void

A player used a dice table.

events.on('diceTurnEnd')

on(event: "diceTurnEnd", cb: (event) => void): void

A turn ended.

events.on('diceTurnStart')

on(event: "diceTurnStart", cb: (event) => void): void

A player's turn began.

events.on('dogDestroy')

on(event: "dogDestroy", cb: (dog) => void): void

A dog is being removed.

events.on('dogModeChanged')

on(event: "dogModeChanged", cb: (dog, mode) => void): void

A dog's mode changed.

events.on('dogOwnerChanged')

on(event: "dogOwnerChanged", cb: (dog, owner) => void): void

A dog got a new owner, or none.

events.on('dogSpawn')

on(event: "dogSpawn", cb: (dog) => void): void

A dog was spawned.

events.on('doorInteract')

on(event: "doorInteract", cb: (player, door, action, keySide) => void): void

A player is about to open, close, unlock or lockpick a door. Return false to refuse.

events.on('entityStateChange')

on(event: "entityStateChange", cb: (entity, key, value, previous) => void): void

A value in an entity's shared state changed.

events.on('followStarted')

on(event: "followStarted", cb: (target) => void): void

Client only. The local player's scripted follow started.

events.on('followStopped')

on(event: "followStopped", cb: (target, reason) => void): void

Client only. The local player's follow ended.

events.on('gameResolutionChanged')

on(event: "gameResolutionChanged", cb: (width, height) => void): void

Client only. The game's frame changed size, because the player switched between window and full screen or changed resolution. It fires once per change, and not for the first size.

events.on('gateBarChanged')

on(event: "gateBarChanged", cb: (gate, barred) => void): void

A gate's bar was put in or taken out.

events.on('gateChanged')

on(event: "gateChanged", cb: (gate, state) => void): void

A gate moved to another state.

events.on('gatheringHarvest')

on(event: "gatheringHarvest", cb: (player, proposal) => void): void

A player picked a plant and is about to get it. Return false to refuse.

events.on('gatheringHarvested')

on(event: "gatheringHarvested", cb: (player, details) => void): void

A player got what they picked.

events.on('graveDug')

on(event: "graveDug", cb: (player, grave) => void): void

A player dug out a grave with the game's digging. All games show it open from now on.

events.on('groundItemDestroy')

on(event: "groundItemDestroy", cb: (stack) => void): void

A ground item is being removed.

events.on('groundItemPickup')

on(event: "groundItemPickup", cb: (stack, player) => void): void

A player picked up a ground item.

events.on('groundItemResting')

on(event: "groundItemResting", cb: (stack) => void): void

A ground item came to rest where physics laid it. Its position and rotation are that spot on all clients, and `resting` is true. It fires once per stack, and not for a landed arrow or bolt, which rests from the start.

events.on('groundItemSpawn')

on(event: "groundItemSpawn", cb: (stack) => void): void

A stack of items appeared on the ground.

events.on('horseDamage')

on(event: "horseDamage", cb: (horse, attacker, amount, reason) => void): void

A horse lost health.

events.on('horseDeath')

on(event: "horseDeath", cb: (horse, killer, reason) => void): void

A horse died, and only revive() brings it back.

events.on('horseDestroy')

on(event: "horseDestroy", cb: (horse) => void): void

A horse is being removed.

events.on('horseDismount')

on(event: "horseDismount", cb: (horse, player) => void): void

A rider left a horse's saddle, for any reason.

events.on('horseGearChanged')

on(event: "horseGearChanged", cb: (horse, player, gear) => void): void

A horse's tack changed on all clients.

events.on('horseGearChanging')

on(event: "horseGearChanging", cb: (horse, player, gear) => void): void

A horse's owner changed its tack on the inventory screen's Horse tab, before the server takes it. Return false to refuse, so the horse keeps its gear on all clients and no item moves. It does not fire while the horse's gearFixed is set, which refuses first, or for a script's setTack, fitGear or takeOffGear.

events.on('horseIntentDone')

on(event: "horseIntentDone", cb: (horse, status) => void): void

A horse finished a moveTo or patrol order.

events.on('horseKnockedOut')

on(event: "horseKnockedOut", cb: (horse, attacker, reason) => void): void

A horse was knocked out, by a lethal blow when spawned with knockOut, or by knockDown(). Nobody can ride it until wake().

events.on('horseMount')

on(event: "horseMount", cb: (horse, player) => void): void

A player sat in a horse's saddle, by themselves or through player.mount.

events.on('horseMounting')

on(event: "horseMounting", cb: (horse, player) => void): void

A player mounts a horse, before the server accepts it. Handlers run synchronously, and returning false has their client dismount them, with no horseMount or horseDismount.

events.on('horseOwnerChanged')

on(event: "horseOwnerChanged", cb: (horse, owner) => void): void

A horse got a new owner, or none.

events.on('horseRevive')

on(event: "horseRevive", cb: (horse) => void): void

A dead horse was revived.

events.on('horseSpawn')

on(event: "horseSpawn", cb: (horse) => void): void

A horse was spawned.

events.on('horseWake')

on(event: "horseWake", cb: (horse) => void): void

A knocked-out horse got up.

events.on('characterCreatorClosed')

on(event: "characterCreatorClosed", cb: (appearance, reason) => void): void

The character creator closed.

events.on('chatMessage')

on(event: "chatMessage", cb: (message) => void): void

A chat message arrived in this player's game.

events.on('loadingProgress')

on(event: "loadingProgress", cb: (stage, percent) => void): void

Client only. How far the game has loaded, for a server's loading page: stage 'resources', 'level' or 'ready', with a percentage. See LoadingScreen. Scripts do not run yet during 'download', which only the page hears.

events.on('locationDiscovered')

on(event: "locationDiscovered", cb: (locationId) => void): void

The player discovered a map location, such as a town or district. It happens only on a server with revealMap off, since otherwise the whole map starts discovered. Keep the GUID with the character, and mark it again after the next load. Handler promises are not awaited.

events.on('mapClosed')

on(event: "mapClosed", cb: () => void): void

The local player closed the map.

events.on('mapOpened')

on(event: "mapOpened", cb: () => void): void

The local player opened the map.

events.on('mapWaypointCleared')

on(event: "mapWaypointCleared", cb: (position, mapId) => void): void

The local player removed their waypoint.

events.on('mapWaypointSet')

on(event: "mapWaypointSet", cb: (position, mapId, moved) => void): void

The local player set or moved their map waypoint.

events.on('markerEnter')

on(event: "markerEnter", cb: (marker, player) => void): void

A player walked into a trigger marker.

events.on('markerExit')

on(event: "markerExit", cb: (marker, player) => void): void

A player left a trigger marker.

events.on('markerPlace')

on(event: "markerPlace", cb: (marker) => void): void

A marker was placed.

events.on('markerRemove')

on(event: "markerRemove", cb: (marker) => void): void

A marker is being removed.

events.on('monologueSuppressed')

on(event: "monologueSuppressed", cb: (text, textKey) => void): void

KCDS silenced one of the local character's remarks, which the game voices as Henry whoever plays. Hud.setInnerVoice(true) lets them speak. The line is chosen from the remark's pool, as the game would.

events.on('noclipAllowedChanged')

on(event: "noclipAllowedChanged", cb: (allowed) => void): void

The server allowed or forbade NoClip for the local player, through Player.noclipAllowed. A running flight has by then ended with noclipChanged(false, 'notAllowed').

events.on('noclipChanged')

on(event: "noclipChanged", cb: (enabled, reason) => void): void

NoClip went on or off for the local player.

events.on('npcAnimationEnd')

on(event: "npcAnimationEnd", cb: (npc, fragment, reason) => void): void

An animation from npc.playAnimation ended, firing once per request. A looping one ends only by 'refused', 'stopped' or 'replaced'.

events.on('npcDamage')

on(event: "npcDamage", cb: (npc, attacker, amount, bodyPart, reason) => void): void

An NPC lost health.

events.on('npcDeath')

on(event: "npcDeath", cb: (npc, killer) => void): void

An NPC died.

events.on('npcDestroy')

on(event: "npcDestroy", cb: (npc) => void): void

An NPC is being removed.

events.on('npcIntentDone')

on(event: "npcIntentDone", cb: (npc, status) => void): void

An NPC finished a moveTo, a follow or a patrol leg.

events.on('npcInteract')

on(event: "npcInteract", cb: (npc, player) => void): void

A player pressed the use key looking at an NPC with `interactable` on, within 3.5 m of their view. The server also checks that they stand near it.

events.on('npcInventoryChanged')

on(event: "npcInventoryChanged", cb: (npc, change) => void): void

A spawned NPC's stock changed.

events.on('npcLoot')

on(event: "npcLoot", cb: (player, npc, line) => void): void

A player is about to take an item from a dead NPC. Return false to refuse.

events.on('npcLooted')

on(event: "npcLooted", cb: (player, npc, items) => void): void

A player took items from a dead NPC.

events.on('npcRevive')

on(event: "npcRevive", cb: (npc) => void): void

A dead NPC was revived.

events.on('npcSimulatorChange')

on(event: "npcSimulatorChange", cb: (npc, simulator, previous) => void): void

Another player's game now simulates the NPC, moving it and running its fights.

events.on('npcSpawn')

on(event: "npcSpawn", cb: (npc) => void): void

An NPC was spawned.

events.on('npcHarvest')

on(event: "npcHarvest", cb: (player, npc) => void): void

A player finished butchering a carcass and is about to get its harvest. Return false to refuse, or { items: [{ item, amount }] }, up to 16 rows, to replace the harvest table's yield this time. A wrong yield is logged and the table's is given.

events.on('npcHarvested')

on(event: "npcHarvested", cb: (npc, player) => void): void

A player got a carcass's harvest.

events.on('patrolFinished')

on(event: "patrolFinished", cb: (npc, patrol) => void): void

An NPC's patrol ended: done, cancelled or given up.

events.on('patrolWaypoint')

on(event: "patrolWaypoint", cb: (npc, patrol) => void): void

An NPC on patrol reached a waypoint, or a leg failed.

events.on('playerAnimationEnd')

on(event: "playerAnimationEnd", cb: (player, fragment, reason) => void): void

An animation from player.playAnimation ended, firing once per request.

events.on('playerAttack')

on(event: "playerAttack", cb: (player, opponent) => void): void

The server accepted a player's melee swing at another player.

events.on('playerBuffAdded')

on(event: "playerBuffAdded", cb: (player, buff, source) => void): void

A status effect landed on a player.

events.on('playerBuffBlocked')

on(event: "playerBuffBlocked", cb: (player, buff) => void): void

The server's rules stopped the game putting a status effect on a player.

events.on('playerBuffRemoved')

on(event: "playerBuffRemoved", cb: (player, buff, reason) => void): void

A status effect left a player.

events.on('playerCarry')

on(event: "playerCarry", cb: (carrier, carried) => void): void

A player lifted a knocked-out player onto their shoulder.

events.on('playerCarrying')

on(event: "playerCarrying", cb: (carrier, carried) => void): void

A player is about to lift a knocked-out player onto their shoulder. Return false to refuse.

events.on('playerCarryingItem')

on(event: "playerCarryingItem", cb: (player, item, stack) => void): void

A player is about to pick up a carryable item from the ground in their arms. Return false to refuse.

events.on('playerCarryItem')

on(event: "playerCarryItem", cb: (player, item, stack) => void): void

A player now carries an item in their arms.

events.on('playerCombatCancelled')

on(event: "playerCombatCancelled", cb: (player, opponent) => void): void

player.stopFight ended melee combat between two players.

events.on('playerCommand')

on(event: "playerCommand", cb: (player, command, parts) => void): void

A player typed a message starting with /. You get the command without the slash, and the rest split at spaces. Commands never go to other players.

events.on('playerConnect')

on(event: "playerConnect", cb: (player) => void): void

A player joined. Their body and inventory exist while they are still loading, which makes this the place to restore a saved inventory.

events.on('playerConnecting')

on(event: "playerConnecting", cb: (request) => void): void

Someone asks to join, before their connection exists. They get in once all handlers have returned and all returned promises have settled, and a handler that throws or rejects turns them away. `request.reject(reason)` turns them away at once, with up to 512 bytes of text. `request.update(message)` shows up to 256 bytes on their waiting screen and restarts the wait. `nickname`, `steamId`, `epicId`, `store`, `storeAccount`, `discordId`, `deviceId` and `ip` say who it is, as on a player, with `identifiers` listing them as { kind, id, verified } and `getIdentifier(kind)` giving one, or ''. `ticket` is the KCDS Master's join pass, already checked, and a backend can check it again with the Master's public key. `isPending()` says whether it still waits. A player on the KCDS central ban list gets no pass and so never gets this far, nor does one without the server's password, KCDS_SERVER_PASSWORD.

events.on('playerConsumed')

on(event: "playerConsumed", cb: (player, consumed) => void): void

A player ate or drank something.

events.on('playerConsuming')

on(event: "playerConsuming", cb: (player, consumption) => void): void

A player is about to eat or drink. Return false to refuse.

events.on('playerConsumptionEffects')

on(event: "playerConsumptionEffects", cb: (player, consumption) => void): void

Follows playerConsuming. Return false to stop the game's effects of the food or drink, so your script can apply its own. The item is still used up.

events.on('playerCuffedChange')

on(event: "playerCuffedChange", cb: (player, cuffed) => void): void

player.setCuffed cuffed or uncuffed a player.

events.on('playerCustomBuffApply')

on(event: "playerCustomBuffApply", cb: (player, buff) => void): void

An instance of a Buffs.register buff landed on a player, firing for each stack.

events.on('playerCustomBuffRemove')

on(event: "playerCustomBuffRemove", cb: (player, buff, reason) => void): void

An instance of a Buffs.register buff left a player, whose modifiers no longer apply.

events.on('playerCustomBuffTick')

on(event: "playerCustomBuffTick", cb: (player, buff) => void): void

A tick of a Buffs.register buff with a tickInterval, once per instance and interval.

events.on('playerCustomItemUse')

on(event: "playerCustomItemUse", cb: (player, item, revision) => void): void

A player used a custom item your resource made usable with Items.

events.on('playerDamage')

on(event: "playerDamage", cb: (player, attacker, amount, bodyPart, reason) => void): void

A player's game took health off them.

events.on('playerDied')

on(event: "playerDied", cb: (player, killer, reason) => void): void

A player was knocked out, and stays down until player.revive().

events.on('playerDisconnect')

on(event: "playerDisconnect", cb: (player) => void): void

A player left. The object still has its last values here, so save what you need.

events.on('playerHit')

on(event: "playerHit", cb: (player, attacker, hit) => void): void

Another player's blow, arrow, bolt or ball is about to take a player's health. Set hit.damage for the health it takes, or hit.modifiers (attack, defense, block, health, where 1 changes nothing) to have the game work out the blow again. Return false to refuse. A hit on or by a player in a dice match, or at a smithy, alchemy table or grindstone, is refused before this event.

events.on('playerChat')

on(event: "playerChat", cb: (player, text) => void): void

A player sent a chat message that is not a command. By default it has already gone to everyone. To handle chat yourself, use Chat.setChatRelay(false).

events.on('playerInjured')

on(event: "playerInjured", cb: (player, limb) => void): void

A player's limb was injured.

events.on('playerInjuryHealed')

on(event: "playerInjuryHealed", cb: (player, limb) => void): void

A player's limb injury healed.

events.on('playerInventoryChanged')

on(event: "playerInventoryChanged", cb: (player, change) => void): void

Rows in a player's inventory were added, removed, moved or changed.

events.on('playerInventoryReady')

on(event: "playerInventoryReady", cb: (player) => void): void

A player's game shows the inventory the server holds for them. It fires once.

events.on('playerItemUsed')

on(event: "playerItemUsed", cb: (player, item, kind, amount) => void): void

A player used up units of an item. For eating and drinking, see playerConsumed.

events.on('playerLevelUp')

on(event: "playerLevelUp", cb: (player, track, level, perkPoints) => void): void

A player reached a new level on a skill track.

events.on('playerLoot')

on(event: "playerLoot", cb: (player, victim, line) => void): void

A player is about to take an item from a knocked-out player's body. Return false to refuse.

events.on('playerLooted')

on(event: "playerLooted", cb: (player, victim, items) => void): void

A player took items from a knocked-out player's body.

events.on('playerPerkAdded')

on(event: "playerPerkAdded", cb: (player, perk, source) => void): void

A player got a perk.

events.on('playerPerkLearning')

on(event: "playerPerkLearning", cb: (player, perk) => void): void

A player chooses a perk. Return false to cancel the choice.

events.on('playerPerkRemoved')

on(event: "playerPerkRemoved", cb: (player, perk, source) => void): void

A player lost a perk.

events.on('playerPickpocketCaught')

on(event: "playerPickpocketCaught", cb: (thief, victim) => void): void

A victim caught their pickpocket.

events.on('playerPickpocketed')

on(event: "playerPickpocketed", cb: (thief, victim, items) => void): void

A pickpocketing ended, with the items taken.

events.on('playerPickpocketStart')

on(event: "playerPickpocketStart", cb: (thief, victim) => void): void

A player tries to pickpocket another. Return false to refuse.

events.on('playerPilloryReleased')

on(event: "playerPilloryReleased", cb: (player, reason) => void): void

A player left the pillory.

events.on('playerPoisonAbsorbing')

on(event: "playerPoisonAbsorbing", cb: (player, consumption, poison) => void): void

A player consumed something poisoned and is about to get the poison. Return false to keep it off them.

events.on('playerPrepared')

on(event: "playerPrepared", cb: (player, preparation) => void): void

A preparation playerPreparing allowed is over. It fires once the inventory has been still for a few seconds after the last conversion, and not if nothing converted.

events.on('playerPreparing')

on(event: "playerPreparing", cb: (player, preparing) => void): void

A player's game is about to cook, smoke or dry food at a fire, smokehouse or rack. Return false to refuse, so nothing starts and nothing is taken. The game still plays the player's animation and tells them nothing, so show a message of your own.

events.on('playerProgressionRejected')

on(event: "playerProgressionRejected", cb: (player, reason) => void): void

A player's game reported XP or perks the server did not grant. What happens to the player is up to your resources.

events.on('playerPutDown')

on(event: "playerPutDown", cb: (carrier, carried) => void): void

A carried player was put down.

events.on('playerPutDownItem')

on(event: "playerPutDownItem", cb: (player, item, stack) => void): void

A player stopped carrying an item and set it down.

events.on('playerQueued')

on(event: "playerQueued", cb: (view) => void): void

A player joined a full server's queue.

events.on('playerReady')

on(event: "playerReady", cb: (player) => void): void

Their game has taken down its loading screen, so they can see and play. It fires once per connection, on the server and in the player's own game.

events.on('playerResourcesReady')

on(event: "playerResourcesReady", cb: (player) => void): void

Server only. Their game has downloaded and started the client resources, so events from player.emit and Events.broadcast now reach their client scripts. On a first join, playerReady can come first. It fires again when client resources load anew, and when their game restarts client scripts that stopped by themselves, which it does up to 5 times a session. Those scripts then hold nothing, so send what they need again.

events.on('playerSpawned')

on(event: "playerSpawned", cb: (player) => void): void

The player stands in the loaded world.

events.on('playerSpawning')

on(event: "playerSpawning", cb: (player) => void): void

Their game has loaded and needs a starting place. Give it here with player.spawn(position, rotation).

events.on('playerStatsChanged')

on(event: "playerStatsChanged", cb: (player, changes) => void): void

Stats in a player's report changed, with one event for all changes of a server tick.

events.on('playerTreeFell')

on(event: "playerTreeFell", cb: (player, tree, fall) => void): void

A player's last blow fells a tree. You can change `fall.direction`, which is horizontal and away from the chopper by default, and `fall.seconds`. Return false to keep it standing, and the next blow tries again.

events.on('playerTreeChop')

on(event: "playerTreeChop", cb: (player, tree, blow) => void): void

A player's axe blow on a standing tree counts: axe in hand, within reach, one per swing. Return false to refuse. See Trees.

events.on('playerTrunkCut')

on(event: "playerTrunkCut", cb: (player, tree, items) => void): void

A player's last blow cuts a felled trunk into items, and you can change `items` in place. Return false to refuse, and the next blow tries again. The items go to the inventory or the ground, by Trees.configure's dropTo, and the trunk disappears.

events.on('playerTrunkChop')

on(event: "playerTrunkChop", cb: (player, tree, blow) => void): void

A player's axe blow on a felled trunk counts. Return false to refuse.

events.on('playerUnqueued')

on(event: "playerUnqueued", cb: (view, value) => void): void

A player left the queue.

events.on('playerWeaponHit')

on(event: "playerWeaponHit", cb: (player, hit) => void): void

A swing struck the world and not a character, such as a tree, wall, rock, prop or the ground. It fires once per object per attack, on first contact, from the attacker's client report. The server accepts a report up to 8 m from the player's known position, and up to 16 per second per player. Unarmed attacks never fire it, and hits on players, NPCs and animals are for playerHit and the damage events.

events.on('playerWhistle')

on(event: "playerWhistle", cb: (player) => void): void

A player whistled for their horse, and nearby players hear it.

events.on('playerXpGained')

on(event: "playerXpGained", cb: (player, track, xp) => void): void

A player gained XP on a skill track.

events.on('playerXpGaining')

on(event: "playerXpGaining", cb: (player, track, xp, source) => void): void

A player's game is about to grant XP. Return false to refuse.

events.on('poiDiscovered')

on(event: "poiDiscovered", cb: (poiId) => void): void

The player discovered a point of interest on the map, on a server with revealMap off. Handler promises are not awaited.

events.on('progressionLevelUp')

on(event: "progressionLevelUp", cb: (track, level, perkPoints) => void): void

The local player reached a new level.

events.on('progressionPerkAdded')

on(event: "progressionPerkAdded", cb: (perk) => void): void

The local player got a perk.

events.on('progressionPerkRefused')

on(event: "progressionPerkRefused", cb: (perk, reason) => void): void

The server refused a perk the local player chose.

events.on('progressionPerkRemoved')

on(event: "progressionPerkRemoved", cb: (perk) => void): void

The local player lost a perk.

events.on('progressionXpGained')

on(event: "progressionXpGained", cb: (track, xp) => void): void

The local player gained XP.

events.on('propDestroy')

on(event: "propDestroy", cb: (prop) => void): void

A prop is being removed.

events.on('propHit')

on(event: "propHit", cb: (prop, speed, position) => void): void

A rigid prop's body struck something, such as the ground, a wall or another body. The simulating game saw it, moving at 2 m/s or more, slow down with its velocity changing by 2 m/s or more between frames, which gravity alone cannot do. There is at most one hit per prop every 0.3 s, and propRest still follows once it stops.

events.on('propPickedUp')

on(event: "propPickedUp", cb: (player, prop) => void): void

An animation's pickup took a playAnimation prop with fromAnimation into the hand.

events.on('propPlaceCancel')

on(event: "propPlaceCancel", cb: (player, session) => void): void

A player cancelled a placement.

events.on('propPlaceConfirm')

on(event: "propPlaceConfirm", cb: (player, session, placement) => void): void

A player confirmed a placement. Return false to refuse, and propPlaceRejected follows.

events.on('propPlaced')

on(event: "propPlaced", cb: (player, prop) => void): void

An animation put down a playAnimation prop with fromAnimation.

events.on('propPlaceEnd')

on(event: "propPlaceEnd", cb: (player, session) => void): void

A placement session ended.

events.on('propPlaceMove')

on(event: "propPlaceMove", cb: (player, session, placement, valid) => void): void

A player moved a PropPlacer preview, if the placer reports moves.

events.on('propPlaceRejected')

on(event: "propPlaceRejected", cb: (player, session, placement) => void): void

A placement was refused.

events.on('propRest')

on(event: "propRest", cb: (prop, position, rotation) => void): void

A rigid prop came to rest, whatever moved it: a script call such as applyImpulse, setVelocity, wake or sleep, a fall, or a player. The position comes from the client simulating it, the nearest player's at any distance, and other players already see it there. A position over 100 m from the previous resting or spawn point is refused, returning the prop there with no event. resetPhysics fires no event.

events.on('propSpawn')

on(event: "propSpawn", cb: (prop) => void): void

A prop was spawned.

events.on('questTrackingChanged')

on(event: "questTrackingChanged", cb: (quest, player, tracked) => void): void

A player started or stopped tracking a quest in their quest menu.

events.on('resourceStart')

on(event: "resourceStart", cb: (name) => void): void

A resource's scripts have run. Each side raises it for its own resources.

events.on('resourceStop')

on(event: "resourceStop", cb: (name) => void): void

A resource is stopping, and handlers have up to 10 seconds to finish.

events.on('siegeEngineDamage')

on(event: "siegeEngineDamage", cb: (engine, amount, attacker) => void): void

A siege engine took damage.

events.on('siegeEngineDestroy')

on(event: "siegeEngineDestroy", cb: (engine) => void): void

A siege engine is being removed.

events.on('siegeEngineReady')

on(event: "siegeEngineReady", cb: (engine) => void): void

A siege engine finished loading.

events.on('siegeEngineSpawn')

on(event: "siegeEngineSpawn", cb: (engine) => void): void

A siege engine was spawned.

events.on('siegeEngineUse')

on(event: "siegeEngineUse", cb: (player, engine, action) => void): void

A player is about to operate a siege engine. Return false to refuse.

events.on('siegeEngineWreck')

on(event: "siegeEngineWreck", cb: (engine, attacker) => void): void

A siege engine was wrecked.

events.on('siegeFire')

on(event: "siegeFire", cb: (engine, attacker, target) => void): void

A siege engine fired.

events.on('siegeImpact')

on(event: "siegeImpact", cb: (engine, position, attacker) => void): void

A siege engine's shot landed.

events.on('siegeLadderDestroy')

on(event: "siegeLadderDestroy", cb: (ladder) => void): void

A siege ladder is being removed.

events.on('siegeLadderFall')

on(event: "siegeLadderFall", cb: (ladder, pusher) => void): void

A ladder was pushed away and fell.

events.on('siegeLadderRaise')

on(event: "siegeLadderRaise", cb: (ladder) => void): void

A ladder was raised against a wall.

events.on('siegeLadderSpawn')

on(event: "siegeLadderSpawn", cb: (ladder) => void): void

A siege ladder was spawned.

events.on('siegeLadderUse')

on(event: "siegeLadderUse", cb: (player, ladder, action) => void): void

A player is about to push away or raise a ladder. Return false to refuse.

events.on('stashClose')

on(event: "stashClose", cb: (stash, player, reason) => void): void

A player closed a stash.

events.on('stashDestroy')

on(event: "stashDestroy", cb: (stash) => void): void

A stash is being removed.

events.on('stashInteract')

on(event: "stashInteract", cb: (player, stash, action) => void): void

A player is about to open a stash. Return false to refuse.

events.on('stashInventoryChanged')

on(event: "stashInventoryChanged", cb: (stash, player, change) => void): void

A script changed a stash's contents.

events.on('stashOpen')

on(event: "stashOpen", cb: (stash, player) => void): void

A player opened a stash.

events.on('stashSpawn')

on(event: "stashSpawn", cb: (stash) => void): void

A stash, meaning a chest, container or searchable body, was created.

events.on('stashUnlocked')

on(event: "stashUnlocked", cb: (stash, player, method) => void): void

A player unlocked a locked stash.

events.on('stoneImpact')

on(event: "stoneImpact", cb: (pile, position, player) => void): void

A thrown stone landed, hurting anyone near.

events.on('stonePileDestroy')

on(event: "stonePileDestroy", cb: (pile) => void): void

A stone pile is being removed.

events.on('stonePileSpawn')

on(event: "stonePileSpawn", cb: (pile) => void): void

A stone pile was spawned.

events.on('stonePileThrow')

on(event: "stonePileThrow", cb: (player, pile) => void): void

A player threw a stone from a pile.

events.on('storyCutsceneSuppressed')

on(event: "storyCutsceneSuppressed", cb: (cutscene) => void): void

Client only. KCDS stopped a quest's story cutscene playing on this machine. The player stays in control, the world clock runs on, and the quest continues as if it had played. Hud.setCutscenes(true) lets them play.

events.on('tradeClosed')

on(event: "tradeClosed", cb: (seller, player, reason) => void): void

A trade ended.

events.on('tradeDone')

on(event: "tradeDone", cb: (seller, buyer, boughtLines, soldLines, balance) => void): void

A basket went through, and both inventories changed.

events.on('tradeItem')

on(event: "tradeItem", cb: (seller, buyer, boughtLines, soldLines, balance) => void): void

The buyer confirmed a basket. Return false to refuse.

events.on('tradeOpen')

on(event: "tradeOpen", cb: (seller, buyer) => void): void

A trade between two players is about to open. Return false to refuse.

events.on('treeFalling')

on(event: "treeFalling", cb: (tree, fall) => void): void

Client only. A tree in this dimension starts to fall, for `fall.seconds` along `fall.direction`, a good moment for a sound or dust. Handler promises are not awaited.

events.on('treeFelled')

on(event: "treeFelled", cb: (tree) => void): void

A felled trunk came to rest, and lies as a static prop to be cut. See Trees. It fires on the server and, for players of its dimension, in client scripts.

events.on('treeChop')

on(event: "treeChop", cb: (tree, blow) => void): void

Client only. Any player's counted axe blow on a standing tree in this dimension. Handler promises are not awaited.

events.on('treeRegrow')

on(event: "treeRegrow", cb: (tree) => void): void

A felled or cut tree is about to grow back, with its time up and nobody close. Return false to delay it by a minute.

events.on('treeRegrown')

on(event: "treeRegrown", cb: (tree) => void): void

A felled tree stands again as in the level. See Trees. It fires on the server and, for players of its dimension, in client scripts.

events.on('trunkCut')

on(event: "trunkCut", cb: (tree, items) => void): void

Client only. A felled trunk in this dimension was cut into items. Handler promises are not awaited.

events.on('tutorialHintClosed')

on(event: "tutorialHintClosed", cb: (id, reason) => void): void

A tutorial hint in the corner of the screen closed.

events.on('vendorClosed')

on(event: "vendorClosed", cb: (vendor, player, reason) => void): void

A shop screen closed. The server's handler gets (vendorId, player, reason), and the player's game gets (session, reason).

events.on('vendorOpened')

on(event: "vendorOpened", cb: (session, npc) => void): void

A server vendor's shop screen opened in this player's game.

events.on('vendorTrade')

on(event: "vendorTrade", cb: (vendorId, player, bought, sold, balance) => void): void

A player traded with a vendor.

events.on('vfxDestroy')

on(event: "vfxDestroy", cb: (vfx) => void): void

A visual effect is being removed.

events.on('vfxSpawn')

on(event: "vfxSpawn", cb: (vfx) => void): void

A visual effect was spawned.

events.on('weaponHit')

on(event: "weaponHit", cb: (hit) => void): void

The local player's weapon struck the world and not a character, such as a tree, wall, rock, prop or the ground. It fires once per object per attack, on first contact, and not again while the blade stays against it. Unarmed attacks never fire it, and hits on players, NPCs and animals are for playerHit and the damage events. The server's event is playerWeaponHit. Handler promises are not awaited.

events.on('worldDayChange')

on(event: "worldDayChange", cb: (day) => void): void

The world's clock reached a new day.

events.on('worldItemPickup')

on(event: "worldItemPickup", cb: (player, item) => void): void

A player is about to pick up an item the level placed. Return false to refuse.

events.on('worldResourcesReady')

on(event: "worldResourcesReady", cb: () => void): void

All world resources, the level edits and their exports, have loaded.

events.on('worldWeatherChange')

on(event: "worldWeatherChange", cb: (preset, previous, seconds) => void): void

World.setWeather started changing the weather.