Commit Graph
35 Commits
Author SHA1 Message Date
AyeZeeBB b229062400 Skater effects on other players: costume and board trails, and contact sparks and dust
Other players' skaters and skateboards showed none of the game's skater
effects: not the trail or fire a costume or deck comes with, and not the
sparks, dust and puffs of a skater touching the world.

Costume and skateboard effects. The game gives another player's skater and
skateboard the right effect sets by itself, but builds them before their
outfit is on, so nothing showed. They are now built again half a second after
the outfit is applied. An always-on effect that a skater's item puts on the
skateboard's wheel joints (the Ghost Skater trail) follows the skater's own
copy of those joints, which only this player's skater keeps up to date: for
other players it is taken out of the skater's sets and built on their
skateboard, which has the same joints.

Contact effects. They come from a skater touching the world, which only
happens in that player's own game. Each game now captures its skater's
contacts (position, velocity, surface normal, surface material) and sends up
to three a tick in a new unreliable packet, PacketKind::effects. Other games
play each through the game's own function, so the effect is still chosen from
the surface and the speed. A contact is shown as late as that player's poses
are, only within 30 m of their skater, and only for a material the level's
table has: the game reads that table without a bound.

Server. A dedicated server relays effects packets to players within 150 m of
the sender, at most one packet a tick from each player. New setting
players.sync_effects (default true), console and admin command
"effects on|off". Off: the server relays none, and the roster tells games
neither to send their contacts nor to build other players' costume and
skateboard effects. Player-hosted lobbies relay through the host and always
share them.

The roster carries one more byte for the setting. Still protocol 45, which
has not been released.

New console command "mp effects": what has been captured and played, and why
the last contact was refused if one was.
2026-10-09 00:10:11 -05:00
AyeZeeBB 9ab985e778 Server: object scaling can be turned off
Server: object scaling can be turned off

A dedicated server can stop players resizing the objects they place.

- "allow_object_scaling" in the config's "players" section (default true),
  and "object-scaling on|off" from the console or an admin. A change is
  saved and applies at once.
- Off: the server shares every player's objects at their own size, whatever
  that player's game sent. Admins can still resize theirs, as with the
  object limit.
- The roster tells each game. In the park editor of a player on such a
  server the SCALE mode is not offered, its Y shortcut does nothing, the
  scale box is disabled with a note saying why, and what is placed or edited
  is its own size.
- An object resized before the setting was turned off is its own size for
  everyone else straight away; its owner sees it resized until they edit it.
2026-10-08 22:21:00 -05:00
AyeZeeBB 5967124f3a Vote card above chat with rebindable Yes and No; fix full servers breaking on extra slots
Votes on a dedicated server show as a card above chat instead of being
followed through chat lines.

- The card has what is voted on, the Yes and No counts, how many are needed,
  a bar of how far Yes has got, and the seconds left. When the vote ends it
  shows Passed, Failed or Cancelled for four seconds.
- Yes and No are two buttons, labelled with the player's binds. The answer
  given is highlighted and can be changed. They can be clicked whenever the
  cursor is free (chat, menu or console open).
- Two new binds, "Vote yes" and "Vote no", in the binds list: F1 and F2
  unless changed, to keys or controller combos like the others. They are
  read only while a vote is running, and not while typing.
- /yes and /no still work and show on the card. The player a kick vote is
  about sees the card and has no vote in it.
- Console: "mp vote yes|no", "bind voteyes <n>", "bind voteno <n>".

Server:
- The roster carries the running vote (id, kind, tally, seconds left,
  starter, target, label) and the one just finished with how it ended.
- A chat line is no longer sent for each change of the tally; the lines for
  a vote starting and ending stay.

Fix: a dedicated server's roster may list more players than its limit.
The extra slots for reserved players and admins (33 of 32) made a roster the
protocol refused to encode, so with one in use the server logged
"Server error" every pass and stopped part-way through each one until
somebody left. Lobbies hosted by a player are still held to their size.
2026-10-08 21:54:45 -05:00
zeex64 7cdd2eaede Merge pull request #132 from VexFlint/fix/mesh-tests-direct-join
Build the mesh tests again: their fake transport takes the direct address
2026-10-08 21:31:38 -05:00
zeex64 2c90fbec36 Merge pull request #43 from ComputerKWasTaken/codex/random-community-parks
Add random community park loading and launch randomization
2026-10-08 21:20:47 -05:00
VexandClaude Opus 5.5 57c440507a Build the mesh tests again: their fake transport takes the direct address
38d86e1 gave SteamTransport::join a direct IP and port and added
take_direct_notes(), but the fake transport in mesh_tests.cpp kept the old
join and had no take_direct_notes, so the Windows test build failed. The
fake ignores the direct address and has no notes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 22:53:11 -03:00
AyeZeeBB 38d86e1b72 New pose and sound formats for dedicated servers; direct connections; protocol 44
Poses and skater sound between a dedicated server and its players use new
formats. Lobbies and the links between games are unchanged.

Poses (pose_codec.h, pose_batch.h):
- A pose is rounded once (rotations to 0.08 degrees, positions to a
  millimetre) and sent as its differences from a pose of the same player
  the receiver has acknowledged. Several players' poses share one message.
- The receiver acknowledges messages once a tick; the sender builds only on
  acknowledged poses, or on the whole pose it sent reliably. Loss costs the
  poses in that packet and nothing more.
- Fingers are not sent to players further than "finger_distance" (25 m).
- Games upload their own poses the same way, and the server acknowledges.
- About 300 B a pose at full rate against about 660 B before.
- The server no longer rounds rotations by distance: it saved little.

Sound (sound_codec.h):
- Each sample is sent as what changed since the one before, numbers rounded
  to 1/1024. One reliable message a tick carries every skater a player can
  hear. A stream is sent whole at its start and every two seconds.
- About 106 B a message against 368 B before, on a recording of real play.

Direct connections:
- "connection": "relay" (default) or "direct", with "direct_address" and
  "direct_port". A direct server listens on UDP and is listed with its
  address; players still sign in through Steam.
- Games connect straight to servers that offer it and fall back to the
  relays after 5 s. Setting and "mp direct-connections" to turn it off.

Server:
- "bone_scale_limit" is 1 by default: resized body parts are off unless a
  server allows them.
- Logs Steam's relay network status at start-up and in "net", and watches
  the Steam sign-in.
- "pack_ms" (10): how long Steam may hold a message to pack it with others.
- "steam_debug": logs what Steam's networking says, for connection faults.
- "relay_everything": sends poses and sound through the server even between
  games that have linked, for testing with few players.
- "net" shows pose sizes by rate, the share sent without fingers, and whole
  poses sent.

Game:
- Only ReSkate's nametags are shown; the game's own are removed.
- "mp pose-dump <seconds>" records the local skater's poses and sound.

Tests: pose_codec_tests covers exact round trips, chains of differences,
held fingers, damaged input, the sender and receiver over a link that
delays, loses and reorders, and the sound format; with a recording as its
argument it prints sizes on real play.

Protocol 44: servers and games must both update.
2026-10-07 23:10:13 -05:00
AyeZeeBB 91c939ea4f Server: limit how far a mod may resize part of a skater for other players
- 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
2026-10-07 19:42:48 -05:00
AyeZeeBB 7ee82b2771 Player distance and nametag settings; far players sent less and more coarsely; profiler addresses
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
2026-10-07 16:43:18 -05:00
AyeZeeBB d04920c793 Server: the nearest players always at the full rate; whole states once a minute; relay routes in net
- 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
2026-10-07 16:02:26 -05:00
AyeZeeBB c98c3f3207 Keep busy dedicated servers playable; hold stale skaters instead of rebuilding them
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
2026-10-07 14:43:45 -05:00
ComputerKWasTaken fbad6a1609 Merge remote-tracking branch 'origin/main' into codex/random-community-parks 2026-10-07 11:23:01 -05:00
AyeZeeBB 07fef3820d Limit how many objects each player can place (protocol 43)
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)
2026-10-07 10:03:54 -05:00
AyeZeeBB 101e1af6e4 Official, staff and friends in the server browser; server tokens; Linux self-update
Server browser
- Official servers (the backend's "official_servers") sort first and are
  drawn in ReSkate blue
- Servers Steam friends are skating in sort next, drawn in green with the
  friends' names; searching a friend's name finds their server
- A player in a session they joined can join another server straight from
  the list; hosts still end their session first, and a Steam friend's join
  offer never replaces a session
- Joining a dedicated server from the list records it as the player's
  public session, so friends see it and the row shows HERE
- Blocked servers (the backend's "blocked_servers") are hidden and cannot
  be joined, by code either
- When the backend sets "server_tokens_required", dedicated servers that
  signed in without a login token are hidden, except on the player's own
  network
- A search that gets no internet list from Steam keeps the last list for
  two minutes, and waits six seconds before treating it as empty
Roles
- New Staff tag from the backend's "staff" list: green name, badge and
  item animation, ranked after Dev
- Staff can pick a rainbow for their items on the Special page; it is sent
  as a solid colour older builds can show, so the protocol is unchanged
Dedicated server
- steam_token: sign in with a Steam game server login token and keep the
  same Steam ID every start; empty signs in anonymously as before
- A listed server without a token says so at startup, and when the token
  rule starts or stops hiding it
- Linux servers update themselves from the release's "server_linux"
  tarball, with the machine's curl and tar, pinned by SHA-256, and carry
  on in the same process
Launcher
- Only create the MiniDumpWriteDump API-set shim under Wine/Proton
2026-10-07 00:19:56 -05:00
ComputerKWasTaken 8aaa4b75fc Merge main and preserve random park command help 2026-10-06 16:40:56 -05:00
AyeZeeBB 2cdc5ee8df Fix costume merging, restrict server names, add Centrix tag
- Mod merge: rebuild a merged bundle's chunk metadata the way the game
  writes it (one record per chunk, in chunk GUID order), so costumes
  from different mods built on the same game costume keep their
  textures and meshes
- Merge audit checks that layout, and there is a new unit test for it
- Server names: only letters, numbers, spaces and - _ [ ] ( ),
  1 to 64 characters; the server browser hides servers with other names
- New Centrix tag from the backend's "centrix" list: blue and white
  name, badge and item animation, ranked after Dev and before Creator
2026-10-05 23:39:16 -05:00
Juan 23151496f1 Add chat bubbles above each skater
A player's recent chat lines show as speech bubbles above their skater: newest nearest the head, older lines stacking upward, each popping in with a slight overshoot before it fades. Emotes render as their images, a message that is nothing but a few emotes shows them jumbo, and a message longer than a handful of lines is cut with an ellipsis so one line can never wall the screen off.

Local display options live under Settings > Interface > Multiplayer (on/off, own messages, distance, duration and how many recent lines stack) and the console gains mp chat-bubbles, chat-bubbles-own, chat-bubbles-distance, chat-bubbles-duration and chat-bubbles-history.

The chat panel and the bubbles now share one rich-text module (chat_rich), and a filtered message keeps its emote names: the bad-word mask is applied, but emote tokens are put back from the original before they are parsed.
2026-10-05 22:46:40 -03:00
zeex64 022900d9fc Merge pull request #74 from xThrasherrr/feat/server-map-pool
Let server hosts choose the map pool and rotate through it
2026-10-05 16:53:52 -05:00
AyeZeeBB de631ad9e6 leave out mods that copy store items, chat badge check
- Mods that add copies of store items under new names are no longer
  loaded. The launcher, mod manager and game say why.
- A chat line passed on by the host only shows a Dev/Creator/Homie
  badge when the player's own copy of it arrives too, so a host
  can't put one on a line that player never wrote.
2026-10-05 16:29:37 -05:00
xThrasherrr 7007ad0389 Name the missing map when leaving a session over it
The host sends the map's name with map offers and changes, since a player without the map's mod has no manifest to name it from.
2026-10-05 15:09:30 -06:00
ComputerKWasTaken 1715dd38d0 Add controller park randomization and cancel guest startup rolls 2026-10-05 15:44:58 -05:00
xThrasherrr 206885fa62 Add a map pool card to the Multiplayer menu for server admins
The server now sends admins its pool and rotation with the map list, which bumps the protocol to 42: players and servers need this build to connect.
2026-10-05 14:43:12 -06:00
AyeZeeBB 5bfe4f7bfa tag preview, separate switches and per-item colors
- Split the single switch into "Show my tag" and "Show my items", and
  show the tag as chat and nametags draw it.
- Color whatever is equipped instead of the one hoodie and pink board:
  top, bottoms, shoes, socks, hat, glasses, outfit, costume, deck, grip
  tape, trucks and wheels, each set on its own.
- Each item can use its list's animation (rainbow, red or gold), a
  gradient between two picked colors, one solid color, or be off.
- The choices travel with the player's appearance so everyone sees them.
  Protocol version 41.
2026-10-05 00:00:45 -05:00
AyeZeeBB c930b512e6 Backend lists for tags, cosmetics and bans
- Read Dev / Creator / Homie Steam IDs from api.reskate.dev instead of the hardcoded list
- Creator (red) and Homie (gold) tags and hoodie/board colours; Admin tag is now pink
- Global bans: lobby hosts and dedicated servers turn banned players away
  ("global_bans": false in ReSkateServer.json opts a server out)
- SPECIAL menu page for listed players to hide their own tag and items
- Fix hoodie and board keeping the animated colour after the animation turns off
- Multiplayer protocol 39 -> 40
2026-10-04 22:33:57 -05:00
AyeZeeBB ecb083f417 Don't drop every player after the server is held up 2026-10-04 17:56:24 -05:00
AyeZeeBB 30f3f84120 Merge branch 'main' of https://github.com/Dingo-Shenanigans/ReSkate 2026-10-04 16:07:51 -05:00
zeex64 aead3ebd03 Merge pull request #39 from xThrasherrr/fix/server-browser-name-last-letter
Keep a non-ASCII last letter in the server browser's tag name
2026-10-04 14:59:54 -05:00
AyeZeeBB c157d01286 add tuning enforce to allowed session commands 2026-10-04 14:32:41 -05:00
xThrasherrr 5e557d184e Keep a non-ASCII last letter in the server browser's tag name
tag_text dropped a trailing lead byte even when its character was whole, so
"Skate Café" was listed as "Skate Caf". The browser shows the tag name until
the server answers a query, so hosts without a forwarded query port kept it.
2026-10-04 13:27:55 -06:00
AyeZeeBB 3fddd1433a Trainer: quiet by default, host's setup for guests; drop the out-of-view cut
Follow-ups to the trainer (PR 37), and one multiplayer change.

Off until asked for (Extension/Trainer)
- The jump read-out and the LB+RB controller shortcuts start off. Jumps
  are logged only while the read-out or telemetry recording is on, and
  trick launches only when the trainer scaled them. A saved trainer.json
  keeps what the player chose.

Memory search on demand (trainer.cpp, trainer_classes.cpp)
- The search for the game's tuning classes reads all writable memory.
  It ran for every player after a level loaded, and up to seven times
  when it found nothing. It now runs only when a class value or the flip
  speed is not the game's own (the player's, or a host's they skate
  with) or the EVERYTHING list is open, and at most three times a level.
- For those players it runs again on each level, which brings fresh
  copies; a search from an earlier level used to count as done.

Guests under enforced physics
- A guest is locked by the session's enforce setting, from the moment
  of joining (Engine/Game/Multiplayer/session_physics.h), not by whether
  the enforcement status text was set yet.
- A guest's class values no longer come back after a map change.

The host's whole setup reaches its guests (protocol 39)
- Only Gameplay/SkatePhysicsTuning travelled, so a host could push,
  sprint or jump further than the guests it held to the game's own.
- New packet physics_extras (30): the host's class values, trick
  multipliers and auto push (trainer_session.h), sent when they change
  and to players who join later, taken from the host only. A dedicated
  server's are the game's own and it ignores the packet.
- Under enforcement a guest's own trick multipliers stand down for the
  host's, whatever the boosts switch says. With enforcement off nothing
  changes.
- A guest refuses bytes that are not an encoding, holds values to the
  trainer's own ranges, and leaves out class values written for another
  game build's table.
- protocol_version 38 -> 39: released versions disconnect from a peer
  that sends a packet they cannot decode.

Out-of-view players are posed every frame again (Session/session.cpp)
- Players outside the camera's view and past 8 m were sampled at 20 Hz
  (b763631). The game's replays record each skater as it stood every
  frame and their camera looks anywhere, so those players moved at
  20 Hz in replays. Removed; the distance rule (20 Hz past 200 m, 10 Hz
  past 350 m) stays. This gives back the client-tick time it saved on
  busy servers.
2026-10-04 14:19:30 -05:00
AyeZeeBB a7d95057ac Harden multiplayer against disruptive and spoofed traffic
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.
2026-10-04 13:49:11 -05:00
AyeZeeBB 76330e40bb Skater slot, menu and throwdown fixes; MY MODS rework; lobby parties
Skater slot, menu and throwdown fixes; MY MODS rework; lobby parties

Saved skaters (Extension/Customization, Extension/Skater)
- The selected slot, and slots before it, came up as the standard
  skater after a start or map change. The game asks for a slot's saved
  outfit once per level, and that happened before the cosmetics catalog
  could be read. The first selection now waits for the catalog (60 s at
  most), and later map changes check against the catalog already read.
- The retry from abdda77 is removed: the record it wrote to is a
  temporary on the game's stack, so it could never work.

Pause menu (Extension/UI/NativeMenu)
- ReSkate's entries stopped working after enough map changes: each
  level change took new slots in a fixed table of 1024 for the same
  buttons. A button now keeps its slot, and a full table hands out the
  slot that has gone longest unused.

Throwdowns (Extension/Throwdowns, Runtime/runtime_init.cpp)
- Multiplayer crashed when someone placed a throwdown after a map
  change. The event types are freed with the level but were cached for
  the process. They are now cleared when a level is left, checked
  before use, and looked for again in each level.

MY MODS (Launcher/gui_mods.cpp, gui.cpp)
- Search, a filter and an order; a switch per mod; a menu per row.
- Multi-select with tick boxes, Shift-click and Ctrl+A, and a bar to
  enable, disable, move, update or uninstall everything ticked.

Lobby parties (Extension/Multiplayer/Session)
- A lobby is no longer one party. Its host keeps parties the way a
  dedicated server does: invite, accept, join, leave, kick, promote,
  open and close, with "/p" party chat. The "Lobby party" switch is
  gone. Protocol version unchanged (38).

Mod merge (Engine/Vfs), follow-ups to e715b9b
- Files rewritten into the merged patch are tracked by position, so
  another mod's added assets no longer shift the lookup.
- Two mods adding different assets under one name is now noted, with
  whose copy the maps get.
- mod_merge_unshift_tests compiles with the launcher tests on.
2026-10-04 13:27:21 -05:00
lennyblk 47b9ff92c5 Check that a refused host leaves its reason in the status 2026-10-04 11:47:00 +02:00
AyeZeeBBandworthlessnorms 04e50f7dee Read a mod's copy from the archive block it is in; link the lobby and mesh tests
Two fixes taken from worthlessnorms' pull request 16. The bug it was
opened for, rewritten copies read back from the mod's folder, was fixed
separately in 6fd3845.

Mod merge (Engine/Vfs/mod_merge_cas_store.cpp, mod_merge_combine.cpp)
- To combine two mods' edits the merge reads each mod's copy from the
  mod's own folder, which means turning its placement in the merged
  patch back into the mod's archive and offset. It took the first of the
  mod's blocks in that patch archive. A mod added while the game runs
  has all its archives appended to the patch's archive 1, so a copy in
  its second archive was looked for in its first, the read failed, and
  the asset kept the highest-priority copy.
- unshift() picks the block the offset falls in. Of two blocks that
  start at the same byte the later one is used: the earlier is an empty
  archive.
- Reproduced with a cosmetic mod rebuilt as two archives and added to a
  running merge: cas_main_bundlereftable "could not be combined (Cannot
  read ...\cas_01.cas)" before, "combined 2 edits (101 preset(s))"
  after. A launch merge gives every archive an index of its own and was
  not affected; 40 installed mods merge exactly as before.
- mod_merge_unshift_tests covers an archive with its own index, three
  appended blocks, bytes before the first block, and an empty archive.

Tests (CMakeLists.txt, Extension/Multiplayer/Test/mesh_tests.cpp)
- multiplayer_lobbies did not link: steam_lobbies.cpp calls
  contains_bad_words and the target did not link dingosdk_word_filter.
- multiplayer_mesh did not link: four functions the session code calls
  had no stub. Two are the ones the pull request adds
  (update_developer_hoodie, remote_skater_generation); the developer
  board has since added update_developer_board and remote_board_entity.
- Both targets build and their tests pass.

Co-authored-by: worthlessnorms <110003169+worthlessnorms@users.noreply.github.com>
2026-10-04 00:27:03 -05:00
AyeZeeBB ca1d82f636 1.0.0 Release! 2026-10-02 14:40:41 -05:00