KCDS 0.4.0

Milestone 0.4.0: far more players in one world, wagons you climb onto, women who move as women, and many new tools for servers.

Servers and players both need 0.4.0: a client and a server of different versions refuse each other when joining. The launcher updates itself on the next start; servers update from their update channel or the new packages.

Many players

  • Crowds (#487): remote players stay full bodies, with no limit on how many are drawn. Their movement stays smooth in a crowd of 300, and 800 players in groups across the map hold up too.
  • Less delay (#487): another player's body follows them 50 ms sooner on a steady connection. On an uneven one the delay grows by itself, so movement stays smooth.

Wagons and sitting

  • Climbing on and off (#855): a player walks round the wagon, climbs up from the ground with the game's clip, and moves along the bench to the seat. The reins are taken up and put back in time with the clip. Bodies stay on their seat on slopes and in motion.

Bodies

  • Women (#864, #858): a woman walks straight, a sheathed sword stays in its scabbard as she moves, and running, riding, carrying a basket and sitting on a wagon are hers too.

For servers and scripts

  • Client events: chatKey (the chat key pressed while Chat.setUIVisible(false) hides the game's chat, for your own chat window), cursorVisibilityChanged(visible), and nativeMenuOpened / nativeMenuClosed for the game's Esc menu. No more polling.
  • horse.allowRider(player) and horse.riders: lend a horse. Those players see the plain mount instead of "mount and steal", and the saddlebags stay the owner's.
  • doorDiscovered(door, player): the server meets a level door, once per run, so a script sets its lock or key before anyone uses it, also after a restart, without a timer.
  • player.setGrimeRate(rate) and player.grimeRate: how fast walking dirties a player, from 0 (never) to 100 times the game's rate, through the game's own dirtying, with no status entry. Buffs take the same as the clothDirtying modifier.
  • World.addInteraction({ entity: horse }): a hint on a horse that moves with it, with setPlayers for its owner only.
  • Verified Discord accounts: "requireDiscord": true in server.json admits only players who verified theirs. The others see VERIFY DISCORD, allow KCDS once in the Discord app (or the browser), and the game joins again; from then on discordId comes from the licence pass, with discordVerified true and a verified discord identifier.
  • kcds-launcher.exe --connect <address> --join-token <text>: your own launcher hands the server a text, such as a one-time ticket, read in playerConnecting as request.joinToken. The game sends it to that server only.
  • World.removeLevelItems({ position, radius, item }): the level's items (and their pile looks) gone from one spot for all players, with restore(); setLevelItemsEnabled(false) now hides the pile looks too.
  • World.levelEntitiesAround(player, center, radius): the level's own entities near a point (doors, levers, rack items), each with the levelObject that LevelEdit.apply takes, so one of them can be hidden by its GUID.
  • Client Camera.playPath(keys, { smooth }): a camera flight through up to 64 keys, worked out by the game every frame, with cameraPathFinished at its end.
  • Client Camera.shake({ angle, shift, duration, frequency }): the game's own view shake, such as a kick that tilts the first-person view and lets it settle.
  • player.makePeace() and player.opponents: a player ends every fight they are in, such as on a held key, without waiting out a timer after the last blow.
  • playAnimation props take untilPutDown: held from the start and gone at the animation's own detach or place.
  • playerMissileHit(player, hit): where a player's arrow came to rest and what it struck (surface, entity, model), as their game saw it. No more own ballistics.
  • horse.follow(target, { radius, speed, rope }) and horse.following: a horse led after a player, an NPC or another horse, with rope: true on a lead rope everyone sees from its head to the leader's hand.
  • A player struck by another player while locked on nobody locks on the striker, as against an NPC.
  • horse.dirt, horse.soil(amount) and horse.clean(): a dirty horse everyone sees, on its legs and tack.
  • Resource files download over HTTP on TCP with the game's port number (open 7777 for UDP and TCP); without TCP they still come over the game connection. A server may send 512 MB per file and 4 GB in all (was 8 and 64). Files over 4 MB stay in the player's download cache on disk, not in memory. Only a connected player's game can download them, with its own token, and a resource only gets files from the current server's catalogue, not ones another server left in the cache.
  • A default client folder no longer sends the server scripts' folders, or data and key files (*.sqlite, *.db, *.sql, *.pem, *.key, *.log, package.json, server.json). A files pattern can still name them.
  • A server conversation (Dialogue) is no longer ended by a nearby NPC's line: the game starts none of its own while one is shown.
  • horse.speedScale: a horse slower (down to 0.1) or faster (up to 2) than the game's horses, in every gait, ridden or led.
  • playAnimation(fragment, { target: horse, side }): the game's horse care animations at a horse anywhere, the body put beside it first, as the camp does.
  • Animations.clipLength(name): how long a game clip runs, for timing scenes without reading the game's files.
  • horse.stamina: a horse's current stamina, as the game that runs it reports.
  • playerTeleported(player, position): a player a script moved now stands there, as their own game reports.
  • playerAnimationEnd also for a clip played with an empty fragment: finished, interrupted or refused, with the clip's name as a fourth argument.
  • player.bodyStance on the server: the stance tag the player's own game chose (standing, crouched, sitting and the others), with the event playerStanceChanged(player, stance, previous).
  • A server sends up to 81920 client files of up to 5120 resources (was 4096 and 256). The limits are now in the resources guide, with the 32 KB event payload.
  • Buff modifiers (#947): attackSpeed slows a player's swings (multiply 0.8 is the game's arm wound), and noSprint: true keeps them from sprinting while the buff lasts, as the game's leg wounds do.
  • TypeScript from npm (#249): npm install --save-dev @kcds/[email protected] gives a project the declarations of the version its server runs, with "types": ["@kcds/types/server"] or client for each side. The KCDS-Types zip has the same files.
  • Props without a joint (#938): the props guide and the reference say where such a prop sits: its offset is from the body's origin, on the ground between the feet, turned as the body faces. It follows walking and turning, not the animation, so a prop for the hands goes on a hand joint.
  • Hosting: the server runs on Linux and in Docker; the Windows server package is no longer offered. The game itself still runs on Windows as before.
  • Shooting contests: the game's archery contest table, bottom left, for your own contests: Hud.showShootingContest, updateShootingContest, showShootingHit and hideShootingContest show the names, arrows left, points and where each arrow struck; showHorseContest and the others do the horse race's.
  • diceMatchStarting: an event just before a dice match begins, also when a second player sits down at a table. A script changes its options, such as the points to play to.
  • Spectating dice: Dice.spectate(player, match) gives a player a camera above the dice of a match, so they can read them; Dice.endSpectate(player) ends it.
  • Horse.dragRider (#484): a player pulls the rider out of the saddle, in every game.
  • Travel.canStart (#484): asks the game whether a fast travel could begin now, with the game's own reason when it could not.
  • Interactions (#863): cooking and smoking switch off the game's prompt and key at its fires, smokehouses and drying racks.
  • Custom textures (#908): a resource's replace/ files, such as its own texture for a shop sign, now reach the level's own objects too: a joining player's game puts them in before it loads the world, and joining waits for the server's client resources.
  • Carrying (#862): every item the game can carry is laid as a ground item when put down.
  • Web views (#865): the center anchor keeps a view in the middle, and gameResolutionChanged says when the size changes.
  • Keys (#854): area.lockKey sets the key of an area's doors and chests, door.setKey gives one lock its own, and player.keyBypass opens everything the server holds.
  • The game's own people (levelPeople in server.json, off by default): the level's people with their daily routines, run by one player's game each and the same for all players; another player's game takes them over when that player leaves.
  • Combat marker for one player: player.setCombatMarker(false) hides the crossed swords under the compass for that player alone, over CombatMarker.setEnabled; null gives the server's setting back.
  • The level's people: players cannot talk to them (no Talk, Chat or Reply prompt); a script turns it on for one it adopts with interactable = true.

World Architect

  • Its AI assistant can open the game's closed buildings (open_model): a copy without the boxes that fill them, the black inside painted, with walls and floors of your own. Then you can walk in and furnish it.
  • hide_level_named and show_level hide and show a level object by its file name, even under your own copy.
  • catalogue gives buildings their size. place_many places many at once, and fill_row lines a street with houses facing it.
  • The Details panel scrolls when its rows don't fit, and NAVMESH says on a game map why there is nothing to bake.
  • Fixed: closing World Architect through its AI assistant, or switching the map, left the panels' text over the game.

Fixes

  • Fixed: Horse.spawn with a soul GUID of the game's tables (its named horses) showed no horse in any game. It now spawns that horse with its soul's own coat, mane and tail (look reads null) unless a look is given.

  • Fixed: a Linux server given node without its path started without its resources.

  • Fixed: people who saw a player fight an NPC did not react when another player's game ran them: no scream, no guards (#956). The people within 30 m of a fight now go to the fighting player's game for 45 seconds.

  • Fixed: a server NPC walking (moveTo, flee) went straight through a player standing on its way. It now steps around the player and walks on.

  • Fixed: the game could hang for good while leaving a custom map (World Architect's map switch, a server's custom map): the game's renderer waited on itself while freeing the map's shaders (#962).

  • Fixed: World Architect closed itself when switching away from a map with thousands of objects, and the switch took over a minute. It now takes a few seconds.

  • Fixed: pictures made into textures by World Architect's AI assistant came out pale in the game.

  • Fixed: a fall from a great height left you standing with almost no health. It now knocks you out.

  • Fixed: a player moved by Player.spawn or Player.teleport kept the speed they had, so the first step could fling them off (#945).

  • Fixed: pulling a rider off a horse could crash the game of the player who pulled.

  • Fixed: after you drove a wagon and got off, it went back to where you got on in your own game (#903).

  • Fixed: a server NPC playing dice jumped up and down on its chair in other players' view.

  • Fixed: a server waited for its scripts, so when many players joined at once, those already playing could lose the connection. The server now keeps running while its scripts catch up.

  • Fixed: a server that sent a player a lot at once (a town of props built by a script, or a player joining into one) could stop that player's game from getting any further orders, and props beyond 512 never showed (#779).

  • Fixed: Npc.interactable = false did not reach the games: players could still talk to the NPC.

  • Fixed: walking into a server NPC counted as a blow: the NPC's body was made again under the player, who went through it, and the NPC jumped.

  • Fixed: what a server NPC said on its own reached only one player: others did not hear it, and a line said as a subtitle they did not get at all. Every player near it now hears the same spoken line.

  • Fixed: on a full server client scripts could miss players, because large updates of the player list were lost.

  • Fixed: a woman in a men's top had no legs under its hem. She now wears hose under it, without it showing in her inventory (#858).

  • Fixed: playerPrepared was not raised when food was smoked or dried.

  • Fixed: another player saw only one of the two lockpicks in the hands of a player picking a lock.

  • Fixed: leaving for the main menu while picking a lock kept the lock's screen over the menu.

  • Fixed: a script could leave a player knocked out for good with the game's unconscious buff (#860).

  • Fixed: a web page stayed in the main menu after leaving a server, and pages could not be made after the resource runtime restarted (#861).

  • Fixed: a player could not stand up after a dice game, also when a script ended the match (#856).

  • Fixed: a script's NPC stayed in its chair after a dice match against a player; it now gets up the game's way, as the player does.

  • Fixed: Dice.tables listed the tables of every level, so a match could pick a table of another level; it now lists the level the server runs.

  • Fixed: Crafting.cancel left a player stuck in a smithy's recipe book; the book now closes and the player can walk away.

  • Fixed: the weather was out of sync after reconnecting (#857).

  • Fixed: a door opened with "Unlock and open" stayed shut in every other player's game (#854).

  • Fixed: a locked door opened by a player with player.keyBypass stayed shut in the other players' games; it is open for everyone and locks again once it is closed (#854).