Each bone's scale was held to the limit (a server's bone-scale, 2x by
default; 8x on every client), but a bone shows at its own size times its
parents' and the whole skater's. A modified client resized each bone of
a chain to the limit: four neck bones at 2x showed a neck 16 times as
long, within every per-bone check.
- skater_bone_parents.h: the parent of each of the skater rig's 386 bones,
read from the game's data (animbase_default_renderskeleton), which the
pose's skater bones follow.
- limit_bone_scale then holds each bone to what its parents leave of the
limit: the size it shows stays within 1/limit to limit. A single resized
bone (a bigger head) is unchanged; bones past the rig's have no parent
and keep the per-bone limit.
- Servers and clients already hold every pose to their limit with it, so
the combined limit follows each server's bone-scale setting, and every
client's 8x where a server allows more.
- Tests: a neck chain at 2x each shows at 2x; a resized skater's bones are
held to what its own size leaves them.
A hacked game was resizing its skateboard and reporting it at another
player's position, so everyone saw an oversized board riding on them,
and with player collision on it knocked them about.
A skateboard is now held to within 10% of its size, apart from the limit
on resized body parts: on a dedicated server when its scale limit is on,
and in every player's game whatever sent the pose. Another player's
board is solid only within 3 m of its own skater; one further off is
seen and not felt.
Dedicated servers also check for a board kept on another player
(Server/board_check.h): one away from its own skater that stays beside
one other player while that player travels 8 m over at least 3 seconds.
The board is then no longer passed on to the others until it has behaved
for half a minute, and the log and the admins in the game are told who.
New setting anti_cheat.pinned_board and command board-check:
off | warn (default) | kick.
A hacked client could move its skater's bones anywhere and stretch the
skater across the map for everyone: the server limited a bone's scale
but not its place.
Server: new anti_cheat setting bone_reach_limit, default 1 metre (0.5
to 20, 0 for off; console bone-reach <0.5-20>|off). A body or board
bone further than that from its parent is pulled back before the pose
is passed on. On the game's rig these bones never move (the longest, a
thigh, is 0.44 m). The fourteen skater bones that do move by metres
(they follow the board and the body in a fall) are held to 100 m, and
the board's rig to 5 m from the board.
Client: every pose a game is shown is held to 2 m reach and 8x bone
scale, whoever sent it, which covers servers that have not updated and
sessions without a dedicated server. A client used to accept up to
100x scale.
The limits come from two recorded play sessions; the exempt bones are
picked by index for the current build's 395-bone rig. The pose codec
bench now prints each recording's bone reach, and reads recordings made
by earlier versions.
- bone_scale_limit in ReSkateServer.json, and the bone-scale command:
the most a bone may be scaled in the poses the server passes on, 1 to
8, and its inverse the least. 1 shows every skater at the game's own
proportions; 0 (the default, "bone-scale off") is no limit
- A "big head" mod sets one joint's scale in the body's bind pose
(animation/dingo/cas_rsp_body_bind, the head from 1 to 4). The game
applies it to the bone, and the bone's scale travels in every pose,
which is how players without the mod see it. The game's own skeleton
has no scaled joint, so 1 changes nothing for anyone else
- The player with the mod still sees it on their own screen: the server
decides only what the others are sent
- Changing it sends whole states again, so nobody keeps a reference
with the old sizes in it
- Dedicated servers only; a lobby's host has no such setting
Game
- Player distance (Settings > Interface, "player-distance"): how far
away another player is still built as a skater, 50 to 1000 m, default
120. Past it they keep their nametag or dot. All the way up shows
everyone. A player already shown stays until 15% further out, so one
skating along the edge is not built and taken down over and over. The
game ran a full skater for every player on the server wherever they
were, which is most of a frame on a full one
- Nametags are always ReSkate's own. The "ReSkate nametags" toggle, the
"Nametag style" button and the nametag-style command are gone; the
game's own nametags are never shown
- Nametag distance ("nametag-distance"): how far away a name still
shows before it becomes a dot, 10 to 500 m. Default 120, was a fixed
150, so by default the name and the skater go at the same distance
- Nametag dots ("nametag-dots"): off hides the dots for far players and
the ones at the screen's edge for players off screen
- Friends' nametags only ("nametags-friends"): only Steam friends get a
name or dot; chat bubbles still show for everyone
Server
- A player out of sight of another (half as far again as the low rate
starts, 255 m by default) is sent to them once a second instead of
five times. On a full server most players are out of each other's
sight, and at five a second each they were most of what was sent
- Rotations are rounded before a pose is passed on, more coarsely the
further away the recipient is: 0.04 degrees within the full rate's
reach, 0.16 within the half rate's, a third of a degree past that,
about 5 degrees out of sight. The pose is still an ordinary one. A
bone that turned by less than a step is the same bytes as before, so
the difference from the reference leaves it out, and the low bits of
the ones that did turn pack away. By distance only: a player the
crowd limit slowed keeps the fine rotations
- A recipient crossing from one precision to another is sent a whole
state of that player, since a difference from a reference of another
precision would carry every bone again
- "net" shows the size of the poses sent at each precision
Profiler
- A function in ReSkate.dll is reported by its address when the DLL has
no symbols. A release build named every one of ours as the nearest of
three exports, so a report could not say which was slow; the
release's symbols name the address afterwards
- The crowd limit always sends a player the nearest 8 others at the
full rate and the next 12 at ten a second, whatever the budget. It
gave everyone the low rate first and the nearest what was left, and
with enough players on (about 120 at the default budget, fewer at a
lower one) nothing was left: nobody was at the full rate, and since a
skater's sound follows the full rate, nobody was heard either
- Whole pose and sound states are sent every minute instead of every 8
seconds. A whole pose measured 3.7 KB against 0.7 KB for a difference
from one, however old the reference, and at every 8 seconds they were
about a seventh of what a busy server sent
- "net" lists which of Steam's relay locations the connections go
through, and "net <player>" that player's: Steam reports pings of
several hundred ms on a server measured at 55-84 ms directly, and
this says which way the route went
No protocol change: a server built from this still takes 1.1.4 players.
Server: what each player is sent
- A crowd limit: each player is sent at most crowd_budget poses a second
(default 600, 0 for none; "crowd <n>|off"). Everyone at 5 a second at
least, the nearest at the full rate, the next nearest at 10. Before,
everyone within full-rate distance was sent at the full rate, which a
crowd of 40 turned into more than a connection carries
- A skater's sound goes only to players within the full-rate distance,
and in a crowd only from the nearest; it went to everyone
- A player who joins, or arrives after a map change, is shown the others
about seven a second, nearest first, and none while what they were
already sent is still on its way. Before, every outfit and every
stream went at once (and to everyone at once after a map change)
- Whole pose and sound states every 8 seconds instead of 2, on the
source's own clock, and slower pose rates sent on that clock too, so
recipients share one patch and compression (DeltaCache) instead of one
each. The settings survive a map change
- Object updates wait for a connection that is behind
Server: Steam connections
- send_rate (default 900 KB/s, "rate <KB/s>") is set as both Steam's
minimum and maximum, for open connections and each new one. With only
the maximum raised a connection stayed at Steam's 256 KB/s; set high,
what was lost was resent until the connection was full of resends
(about 1.1 MB/s reaches a player through the relays)
- A 4 MB send buffer, and a refused must-arrive message no longer ends
the player's session at once: 15 seconds of refusals do (30 for object
updates). A full queue used to drop everyone who was behind together
Server: seeing what is going on
- "net [player]": every connection's ping, delivery, queue and rate, the
traffic by kind (poses, sound, voice, outfits, objects), who uploads
most, and how busy the server's loop is
- A [network] line in the log every minute
- A leave or failed join says how it ended: closed by the player's game
with Steam's reason, connection lost, or closed by the server and why
- The queue time no longer prints Steam's "unknown" as a number
Server: other
- Reserved slots: reserved_slots and reserved in ReSkateServer.json, and
the "reserved" command; admins always have one
- The speed check flags a game at about 1.5x and over (was 1.06x), and
tells only that player; for the admins it is in the log
Game
- A remote skater with no pose for a second stays where it was for up to
eight seconds instead of being destroyed and rebuilt three seconds
later. On a busy server one slow frame did that to many players at
once, and the rebuilding made the next frames slower still
- Every waiting message is read each frame (at most 128 were)
- On an official server the role tags (Dev, Staff, Homie, Creator) show
for every player, not only the few the game is connected to directly;
community servers keep the old rule
- The server browser searches Steam at most every 15 seconds (45 after an
empty answer) and keeps the last list for 15 minutes when Steam returns
nothing, up from 2
- The game's own connections send at up to 900 KB/s