Switching time of day could load the new layer while the old one was
still loaded: the apply loop goes through the layers in catalog order
and sends one event a pass, so going to an earlier time (WeatherDay ->
Evening) sent the load first, and nothing waited for an unload to finish.
Two times of day at once carry both times' lights, and a level with many
lights overflowed the engine's light tables.
A time-of-day layer is now asked to load only once every sibling time of
day that is to be off reports requested and loaded both false; until then
its row says "Waiting for the old time of day".
An unload is no longer sent while the engine is still loading the layer
itself. The engine ignored it, so at a level load the level's own time of
day could stay loaded beside the saved one, and with the wait above the
saved one never loaded.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sets: save a selection under a name and place it again anywhere, on any map.
- The library gets an OBJECTS / SETS switch. SETS saves the selected
objects as a set and lists the saved sets to place or delete (Delete asks
for a second press).
- A set is a park file in <profile>/object_sets/<name>.park.json, so it
shares the park format, its 2 MB limit and its name rules. Positions are
relative to the set's anchor: the middle of its footprint, at its lowest
origin.
- Placing follows the cursor as one wire cube per object, on surfaces or
the grid plane; the mouse wheel turns it by the angle step. A click
pastes the whole set: one undo step, under the paste path's object and
session limits. Sets with objects missing from the catalog cannot be
placed.
- A placed or pasted group is then selected with the move gizmo.
Editing groups:
- Local axes work for multi-selections. A placed set's axes are the
rotation it was placed with, plus every later turn; any other group uses
its last selected object's rotation. Applying a moved group does not snap
its own rotation to the angle grid.
- Duplicate (button or Ctrl+D) copies every selected object at its saved
position, rotation and scale, one grid step along X, as one paste.
- On a server with object scaling off, pastes (sets, duplicates, Ctrl+V)
are made at 1x.
Tests cover set storage (anchor, round trip, replace, names, damaged files,
delete), saving and placing a set through the UI (surface, wheel, one
paste, no live preview), selecting it with its own axes, moving it along
them, and duplicating with and without scaling.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes in the stock park editor that a multi-object edit (a paste, an undo,
a loaded park mod) runs into:
- Pasted objects lost their world link. A paste creates its objects one by
one and saves them when the whole edit completes, but the placements
runtime reconciles after every create and unlinked rows whose id was not
saved yet. Every create unlinked the ones before it: only the last pasted
object could be selected, moved or deleted, and deleting the others
removed them from the layout but left them standing in the world. The
reconcile now counts the editor's pending layout as saved.
- Scale was lost on paste, undo and park-mod load. The native create recipe
has no scale lane, so a created object spawns at 1x. Only the placement
preview resized it afterwards; a create step with a scale now becomes a
move, verified by the server tick's readback like any move.
- Scale was lost on level reload. Restored objects spawn at 1x and the
pose poll then saved 1x over the saved scale. Restores with a scale are
resized on the next server tick, and the poll leaves them alone until the
resize is read back.
- Delete did nothing with several objects selected. Delete (key or button)
now removes the whole selection as one edit and one undo step.
Tests: the transaction fixture's create now spawns at 1x like the game and
reconciles after every create like placement_finish_batch; new checks
cover pasting a scaled group, every pasted object keeping its link, moving
and rotating a pasted group, and multi-delete with undo.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Votes: a vote is decided by the votes cast, not by everyone on the server. It
passes when yes is its percentage of them, at the end of its time, or sooner
once the players still to vote could not change it. A kick still needs two
yes. The card's bar is yes in green from the left and no in red from the
right, with a mark where yes has to reach. No protocol change.
Map versions: a map installed at another version than the host's is no longer
loaded as it is. The download card offers the host's version (MAP VERSION,
UPDATE), which replaces the installed one and is applied while the game runs.
For that the live merge keeps each mod's fingerprint with where its archives
were placed, and places a mod again when its files have changed since: before,
a mod replaced while the game ran was read where the old one lay. When the
host's version is gone from Thunderstore, or the old one's files are in use,
the player is told and leaves the session.
Dedicated server: "maps reload" reads the Mods folder again, so a map copied
in while the server runs can be switched to at once. The server window reads a
copy of the map list.
Map names: a custom map's level is dingolevel_reskate_<map>, and "reskate" was
left in its name ("/map reskate badlands"). The map's own name is shown and
typed now; the old spelling still finds it.
as a level unloads, the game takes each mesh variation out of its registry by the
entry's mesh and reads it unchecked, and this map's meshes unload before
their databases. A guard on that one function has the read of a mesh that is
gone go on with the next entry, and logs how many were passed over.
Player list. A player on the developer, staff or homie list sees each
player's Steam ID in the overlay's PLAYERS list for the session they are
in, after "Host" / "Guest" and the distance, on their own row too. A click
copies it. The lists are the backend's, the same ones the tags come from;
every client in a session already knew the IDs, so this changes who is
shown them and nothing else.
Custom scripts. Nothing in scripts/Custom is read or run any more, whatever
the launcher's "Loose files" setting says: nothing used them, and a mod was
using the folder to load a DLL into the game (package.loadlib from its
init.lua). The loader is kept behind one switch (custom_scripts_enabled in
custom_script_loader.cpp) for the day they come back.
For that day, the loader now also takes Lua's ways of running native code
away before the first custom script runs: package.loadlib, require through
the two C searchers and package.cpath, os.execute and io.popen. If that
does not hold, no custom script runs.
The overlay's Mods page no longer has the INSTALLED / SCRIPTS tabs; it is
the installed mods. Editing the game's own Lua and config through loose
files is unchanged.