Client resources
The client side of a resource is downloaded when a player joins, and it runs in their game. The mod has no gamemode of its own built in, so everything a server does in a player's game comes from these files.
What players download
Only a resource's clientScripts, sharedScripts and files are sent. Server scripts, package.json
and other server files never are.
{
"name": "hello",
"kcds": {
"serverScripts": ["server.js"],
"clientScripts": ["client.js"],
"files": ["ui/**"]
}
}The game caches downloads in %LOCALAPPDATA%\KCDS\cache\resources, named by SHA-256, up to 1 GB, and
removes the least recently used files first. Rejoining a server, or joining another with the same
files, reads from this cache. Each file is checked against its hash before use, and a damaged or
changed one downloads again. Changed files download before the new version starts.
What client scripts can use
Client scripts are CommonJS and can require the resource's own .js, .cjs and .json files. They
do not have Node modules, process or disk access. To use an npm library, bundle it into your client
files.
The client side of the API works with this player's game. It includes the HUD and notifications (Hud), key binds (Key), HTML pages over the game (Web), the game's interface (NativeUI), books and letters (Book), the free camera (NoClip) and the character creator (CharacterCreator). See the API overview for more.
Both sides have the math classes, Events, Messages, Imports, Exports and timers.
Sending from client to server
// client kcds.core.Events.on('playerReady', () => { kcds.core.Events.toServer('hello', { message: 'Hello from my game' }); });
// server kcds.core.Events.fromClient('hello', (sender, payload) => { if (!payload || typeof payload.message !== 'string' || payload.message.length > 128) { return; } kcds.core.Chat.sendToPlayer(sender, payload.message); });
The handler receives two things:
sender: the player the connection belongs to. The server determines this, so it cannot be faked.payload: parsed JSON of up to 32 KB. It comes from the client, so check it before your rules use it.
fromClient handlers are kept apart from the rest. A client cannot trigger the server's game events or
its Events.on handlers.
Sending from server to clients
To reach everyone:
// server kcds.core.Events.broadcast('hello:announce', { text: 'The market opens at noon.' });
// client kcds.core.Events.on('hello:announce', (data) => { kcds.ui.Hud.showNotification(data.text); });
To reach one player, use player.emit(name, payload). The client hears it the same way, through
Events.on(name). It returns false if the player has left.
// server kcds.core.Events.fromClient('shop:prices.ask', (player) => { player.emit('shop:prices', { bread: 3, ale: 2 }); });
How data is encoded
toServer and broadcast turn values into JSON. The exception is a string, which is sent unchanged
and must already be valid JSON, such as '{"text":"hi"}'. An event with invalid JSON is dropped, with
a warning in the log.
Starting, stopping and restarting
resourceStart(name) may return a promise, and resources that depend on yours wait for it. Use
resourceStop(name) to clean up. A stopping resource loses its timers, handlers and module cache.
ensure <name> in the server console restarts a resource and its running dependents. Players switch to
the new client part without restarting their game.
If client scripts stop by themselves
If the browser engine running the scripts ends, the game restarts them after two seconds, up to 5 times
per session, and loads all resources again as on joining. The player's log shows runtime started again.
The scripts start with nothing, and playerResourcesReady fires again on the server. So send what a
client needs from that event, not just on the first join:
// server kcds.core.Events.on('playerResourcesReady', (player) => { player.emit('shop:prices', { bread: 4, beer: 2 }); });
Errors on the server
errorBehavior in the manifest sets what an uncaught server error does: stop, restart or
continue. Catch errors in your callbacks and promise chains, because continue does not repair game
state.