On a dedicated server with object scaling off, a loaded park's scaled objects were resized anyway
(and after a refused resize the pose poll saved 1x over their scale), and a scaled paste, set or
undo ended in a resize the server would not take, so the edit waited on it. The placements now
know whether this game may resize (set by the session from the server's setting and the role, the
host and roles that may always build exempt, allowed outside a session): where it may not, objects
stay 1x in the world, nothing waits on a resize, and the layout keeps their scale for when scaling
is allowed again. A transaction test pastes a scaled object with scaling off.
With "unlock all cosmetics" (and objects) on, the default, ReSkate wrote every installed item into
the profile as owned and never removed one, so every mod a player ever tried stayed in the save:
8765 cosmetics and 520 objects in one profile, past the limit that left a player with no items.
What is owned is now worked out from what is installed (installed_item_owned): a paid store copy
never, every other item while the kind's unlock option is on, and with it off what the profile
saved. The catalog given to the game, the owned list, saved outfits, the player card, the Build
object browser and the park editor all ask it. Nothing per item is saved any more, and a profile
with an option on drops the rows earlier versions saved, once, on the next start.
profile_migration_tests checks that drop on a copy of a real save: the rows stay with the options
off, are gone after a restart with them on, and nothing else in the profile changes.
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>
Objects other players place are spawned locally, so the game took every one
for the local player's own: all were solid, and their card offered the
owner's buttons and named the wrong player.
- Other players' objects are ghosts the skater passes through, as in the
game's own sessions. Each player's row in the session menu has an
"Objects: solid / ghost" switch, remembered by Steam ID; a dedicated
server's own objects (its parks) are solid unless switched off.
`mp objects-solid <SteamID64|server> on|off` does the same.
- The card's own Disable and Enable on one object stand over that player's
setting until the setting is changed.
- The card on an object someone else placed no longer offers Edit or
Delete: the game's "is this mine" and "may this be edited" checks answer
for who really placed it. It offers Disable instead.
- The card names the owner of the object it is for, read from the card's
own script, instead of the owner of the object nearest the skater.
- A dedicated server has a player card of its own, "Server", shown on what
it placed.
Server: the Mods folder is kept when the configuration is reloaded. A park
mod was reported as not being in the Mods folder after a reload.
A 30 s profile on a 77-player server had four frames of 20 to 30 ms against a
usual 7.8 ms, from two things:
- The Park Editor read every mod's manifest every five seconds to list park
mods, on the game's thread and whether or not its list was showing (the
switch for that is never set): about 11 ms each time. The look every few
seconds now runs on a thread of its own and is taken up when it is done;
the one after making, renaming or removing a park is still at once.
- Connecting to a player asked Steam for their name, and waited on the Steam
client for 7 to 10 ms each time a player came into reach. The link takes
the name already read, if any: it only labels the link in diagnostics.
Profiler: a release ReSkate.dll has no symbols, and its functions were all
named after the nearest export. The check for that looked at the symbol's
size, but DbgHelp gives an export a size up to the next one. It now asks
whether the module's own symbols were loaded, and writes ReSkate.dll+0x<offset>
when they were not, to be named from the release's symbols afterwards
Limit how many objects each player can place (protocol 43)
- Servers and lobby hosts set how many objects each player may have
placed: object_limit in ReSkateServer.json and the "objects" command,
"Objects per player" in the host options. Default 100; 0 is no limit
- The host and a server's admins are not limited
- At the limit a player's game refuses another object, from the native
object tool and the park editor, and the menu shows how many they have
placed
- Enforced by the host or server, which shows everyone no more than the
limit of each player's layout; objects already shown keep their place
- The limit travels in the roster, which takes the protocol to version
43: builds before this cannot join sessions with builds after it
- The protocol tests link again (the server browser needs the identity
lists since the official servers change)
Each built its text with path::string(), which throws for a character outside the ANSI code page, so the real error or message was replaced by a code-page error.
Cap outfit packets and stop dropping recipients when a relay cannot be
built. Add per-player relay limits for outfits, skater sound and voice,
and a back-off for Steam IDs that keep failing to join.
Throwdowns: only participants can write rows, turns and scores; a copy
that fails to spawn no longer blocks the others.
Throttle remote skater and skateboard re-creation, cap remote objects
per session, and show developer and friend marks only for identities
Steam vouches for. Route all connections through Steam's relays.
Dedicated server: validate map changes, clean player names, keep vote
cooldowns across reconnects, and cut ban labels on a character boundary.