Skip to content

Exporting the collision geometry

The collision geometry is the level as the game’s own physics knows it: every wall, roof, floor, stair, fence, rock and tree trunk, the way arrows and people bump into them. With it the server can shoot rays of its own:

  • a blow or a shot claimed through a wall is caught - [validation] line_of_sight turns the refusal on; the log says what it would refuse either way;
  • a player walking through a wall or a closed door is caught the same way - [validation] no_clip: the step from the last accepted position to the reported one is checked against the geometry and pulled back;
  • the floor under a player - a bridge, a roof, an upper storey - counts as the ground of the terrain check, so the allowance over the terrain can be a storey rather than a tower;
  • a game mode gets RayCast, IsLineOfSight and GetGroundZ - a wall ahead, a shot’s clearance, the floor to put a spawn on.

The doors the server knows are open let a ray through. Players, actors and horses are not part of it, and neither is anything the game lets you push or knock over - crates, barrels, buckets, carts, a brazier: the server could not follow them once moved, so the geometry holds the level as built. Standing on a barrel, GetGroundZ gives the floor under it.

Without it the rays answer nothing, no line of sight is checked and the ground is the terrain’s; HasCollision tells a mode which it is.

Run tools/KcdMp.ExportCollision.exe from the Windows server folder on a machine that has the game and the KCD:MP client (Steam running, the game closed). The geometry lives in the running game, so the tool starts the game once per level through the KCD:MP launcher: it loads the level, waits half a minute for the level’s objects to settle, walks the physics world in a few passes - seconds, on top of the game’s own loading time, which is minutes on the big levels - and closes by itself. The tool prints the progress; leave the game alone while it runs. The file lands in the server folder’s data/collision/.

KcdMp.ExportCollision [--level <name>|all] [--wait <seconds>] [--game <folder>] [--client <folder>]

All three levels by default, one game run each; --level klaster does one. --wait changes the settling time (30 s by default). The game is found through Steam or --game; the KCD:MP client is looked for next to the tool, then --client, then asked for in a dialog. --help prints the same.

The tool puts the files where the server reads them. For a server on Linux, copy them into its data folder under collision/, named after the level (klaster.kcol), and point the configuration at them:

[validation]
collision = "data/collision/{level}.kcol"
line_of_sight = false # true: a hit or shot claimed through a wall is refused
no_clip = false # true: a step through a wall is pulled back

Both rules start off: the server logs what they would have refused, so an owner can watch a few sessions for false alarms (a doorway the geometry has narrower than the game, a fence the horse takes) before turning them on.

The server log confirms the geometry at start (collision: ... parts, ... triangles ...: RayCast and the ground are live ...) or says why it could not use it. Loading a level takes under a second and 150-270 MB of memory (the files are 11-21 MB; the monastery has 280 000 parts, the two big levels 100 000-300 000 parts and 1.2 million triangles each).

One file per level per game build: after a game update, export it again.