Doors, gates, graves and keys
Doors
Doors belong to the level, so the server does not create them. It learns about a door when the first player's game reports having built it, and from then on the server decides whether it is open or locked. Doors are kept per dimension by the game entity's GUID, and their state is sent only when it changes.
const { Door } = kcds.world; kcds.core.Events.on('doorInteract', (player, door, action, keySide) => { if (door.guid === '00000000000000ab' && action === 'lockpick') { return false; } }); const vaultDoor = Door.find('ab'); if (vaultDoor) { vaultDoor.locked = true; vaultDoor.setOpen(false); }
Finding doors
Door.all()andDoor.getById(id)return the doors the server knows, ornullfor an unknown id.Door.find(guid, dimension?)takes up to sixteen hex digits, with or without0x. It returns the door, ornullif the server does not know it yet.Door.closestTo(player)asks the player's game which door they are at. It returns a promise of{ found, reason, door }, withguidandnamewhen found.
Properties
Read only: id, guid (sixteen lower-case hex digits), name, dimension, lockKey, canBePicked,
builtLocked, position, open, side, lockedByScript.
locked can also be written. Players cannot open a lock a script set.
lockLevel is the lock's difficulty, from 0 (easy) to 1 (hard). A number overrides the level's value for all
players in that dimension, and null restores it.
setOpen(open, side?) opens or closes it with nobody pushing, and opening also unlocks. It returns false if it
was already in that state.
The doorInteract event
doorInteract(player, door, action, keySide) fires when a player uses a door, with the action 'open', 'close',
'unlock' or 'lockpick'. The server first refuses what the game's rules forbid. Returning false refuses the
rest, and all players' copies of the door return to the server's state.
Removing a level door
Door.remove(guid, dimension?) takes a door and its collision out of a dimension for all players there. With no
dimension, it uses the global one, which means all dimensions. door.destroy() does the same in the door's own
dimension.
A removed door is not listed anywhere and cannot be used there. Door.restore(guid, dimension?) puts it back, and
Door.removed(dimension?) lists the removed ones.
const { Door } = kcds.world; const doorway = Door.find('41977678219215de'); Door.remove(doorway.guid, 7); // an open doorway in dimension 7 // Later: Door.restore(doorway.guid, 7);
A removal is a level edit (Level editing). It lasts while the server runs and the resource that made it is started. Remember that the server only knows a door once a player's game has shown it.
Adding a new door
Door.spawn(definition, dimension?) hangs a new door, in the global dimension by default. Players there can open,
close, unlock and pick it, under the same checks as level doors. New doors start closed, and later joiners get them
too.
const guildDoor = kcds.world.Door.spawn({ model: 'lvl1_door_a_left', // from Door.models(), by path or file name position: [1650.5, 2160, 35.4], // the hinge pivot rotation: [0, 0, 0.7071, 0.7071], // optional: x, y, z, w name: 'guild hall', locked: true, lock: 'boltAndKey', // 'none', 'bolt', 'boltAndKey' (default) or 'key' canBePicked: true, lockLevel: 0.8, // 0 to 1; leave out for the game's value }); guildDoor.setOpen(true);
Door.models()lists each leaf used in the shipped levels, as{ path, name, hinge, placements }. The hinge side is part of the mesh.door.spawnedis true for a new door, anddoor.modelgives its leaf. A level door hasmodeltoo.door.toJSON()gives the spawn definition with the current lock state, ornullfor a level door. The server keeps nothing after a restart, so save this and hang the door again at startup.door.destroy()takes it down for good. The resource that hung it owns it, so it also goes when that resource stops.- Its GUID is the server's own,
6b636473plus a number, and stays the same on all machines until the server stops. UseDoor.find(door.guid, dimension)to find it again. - NPCs do not walk through a new door, because the level's navigation has no link for it.
Reference: Door.
Gates
Level gates, such as the drawbridge, portcullises and palisade gates of Trosky and Kuttenberg, are the same for all players. The server owns each gate's state. Players' games move the gate there smoothly, and latecomers see it where it is.
const { Gate } = kcds.world; for (const gate of Gate.all('trosecko')) { console.info(gate.key, gate.states); } const [firstGate] = Gate.all('trosecko'); firstGate.open(); // a barred gate has its bar removed first firstGate.close({ bar: false }); // closes without replacing the bar
- Finding:
Gate.all(level?)andGate.find(key). A gate'skeystays the same across server starts. - State:
state,states,isOpen,moving,secondsTo(state),setState(state),open(),close(). - Bars:
hasBar,barred,removeBar(), andplaceBar(), which leaves the gate shut. - Events:
gateChanged,gateBarChanged.
Reference: Gate.
Graves
The level's graves, where a player digs with a shovel, are also the same for all players. Once dug with the game's digging, a grave is open for everyone, including those joining later. Scripts can dig or refill one.
Players' games tell the server where graves are, so Grave.all() lists the ones in the server's level once a player has
been near them. Nothing is saved, and all graves are full again after a server start.
const { Grave } = kcds.world; kcds.core.Events.on('graveDug', (player, grave) => { kcds.core.Chat.sendToAll(`${player.nickname} dug out a grave.`); setTimeout(() => grave.reset(), 10 * 60 * 1000); // refills after ten minutes }); const closest = Grave.nearest({ x: 3187.1, y: 495.9, z: 40.5 }, 50); if (closest && !closest.dug) { closest.dig(); }
- Static:
Grave.all(near?), nearest first whennearis given,Grave.get(id),Grave.nearest(position, radius?)andGrave.resetAll(). - On a grave:
id(its location in whole centimetres,"x,y,z", stable across starts),position,dug,distanceTo(position),dig(),reset(). - Event:
graveDug.
Reference: Grave.
Keys for a house
area.lockKey makes one key work on all the doors and chests in an area. Whoever carries it gets the game's Unlock
prompt, and a Lock hint on the U key at an unlocked door or chest. The server checks the key on each use.
const house = kcds.world.Area.getById('006588875df00335'); if (house) { house.lockKey = 'key_home'; house.setLocked(true); }
A door or chest can have its own key that takes priority, such as a supervisor's key for one room. Use door.setKey(item)
or stash.keyClass, and null or '' returns to the area's key.
player.keyBypass = true lets one player, such as an admin, open everything the server holds without a key. Their game
shows those locks as unlocked, and nobody else's game changes.