Debugging resources

Finding the logs

Server

Whatever a server script writes with console.log, info, warn, error or debug goes to the server's console window and to the Console tab of KCDS-Admin, labelled with the resource's name:

RESOURCE [hello] started
RESOURCE [hello] Hans asked for the count

Values are joined as text, so an object appears as [object Object]. Convert it to JSON first:

console.info('inventory', JSON.stringify(player.getInventory()));

If a server ends abnormally, by a crash or a killed process, it writes a crash report with the last 200 log lines to crashes/, next to the resources folder. KCDS-Admin lists these. Ctrl+C, systemctl stop and docker stop count as normal stops: resources shut down as usual, and no report is written.

Client

console lines from a client script go to the player's own game log, marked RESOURCE client <text>. The file is client-<process id>.log, next to kcd2s-game-client-v4.dll in the KCDS folder. With the installer, that folder is %LOCALAPPDATA%\Programs\KCDS.

The newest file belongs to the running game. If a problem only happens for one player, ask them to send you theirs.

The launcher's own log is at %LOCALAPPDATA%\KCDS\logs\launcher.log.

What errors do

An uncaught error, or a rejected promise nobody handles, is logged with its stack. What happens next depends on errorBehavior in the manifest:

errorBehaviorResult
stop (default)the resource stops, and everything it registered and spawned is removed
restartthe resource stops and starts again one second later
continuehandlers, timers and exports keep running; what it spawned in the world (NPCs, props, chests, areas and so on) is removed, and nothing else is undone

So catch errors where you can deal with them, especially around await:

kcds.core.Events.fromClient('shop:buy', async (player, payload) => {
  try {
    await buy(player, payload);
  } catch (problem) {
    console.warn(`${player.nickname} could not buy: ${problem.message}`);
    kcds.core.Chat.sendToPlayer(player, 'That did not work.');
  }
});

SDK functions throw TypeError for an argument of the wrong type and RangeError for a value out of range, naming the argument in the message. Each reference page says what its members throw or reject with.

Testing a change without restarting

  1. Save your files.
  2. Enter ensure <resource> or restart <resource> in the server console, or press Restart on the Resources tab of KCDS-Admin.
  3. The resource stops, running its resourceStop handlers. Its files are read again and it starts. Online players download the changed client files and run the new client part.

ensure also starts a resource folder you have just added. refresh only reads new and changed manifests, and starts nothing. See Console commands.

A console command of your own is handy for quick checks:

kcds.core.Events.on('consoleCommand', (command, args) => {
  if (command !== 'where') {
    return;
  }
  for (const player of kcds.players.Player.all()) {
    console.info(`${player.nickname} at ${player.position}`);
  }
});

For a fuller setup, see Trying code quickly.

Common problems

SymptomLikely cause
ensure hello does nothing, not even startedthe console needs the name from package.json, not the folder's name
nothing in the resource runsscripts are missing from serverScripts or clientScripts, or package.json has invalid JSON (see the server log)
ReferenceError: Door is not definedthe type needs its full path, kcds.world.Door
Cannot read properties of undefined on kcds.ui.Huda client type in a server script; each reference page says which side has the type
a client event never reaches the serverthe server used Events.on, but events from players need Events.fromClient
Events.toServer works but the answer never appearsthe server must answer with Events.broadcast or player.emit, and the client listens with Events.on(name)
a command handler runs for every commandplayerCommand gets all commands, so compare command first
an object logs as [object Object]log JSON.stringify(value)
a timer keeps going after a fixthe old code started it; ensure the resource to clear its timers

Next steps