Commit Graph
45 Commits
Author SHA1 Message Date
AyeZeeBB 4f1f5a882e Launcher: the privacy policy and terms of service, and an "I agree" before playing
Both documents come from the ReSkate backend (GET /api/v1/legal/privacy and /terms, edited on its
Legal page), so a change reaches players without a release. Settings has a button for each, opening
a panel like the changelogs': title, version and date, the Markdown drawn as the README viewer draws
it, and a switch to the other one.

Each launch looks up the current versions (GET /api/v1/legal) in the background. One newer than
the player agreed to, or none agreed to yet, puts up an agreement over the home screen: a short
summary, a way into each document, QUIT and I AGREE, which saves the versions agreed to
(accepted_privacy_version, accepted_terms_version in the launcher's settings). A backend that
cannot be reached holds nobody up. Launches that skip the window (--no-gui, Discord joins) are
not asked.
2026-10-17 18:25:22 -05:00
AyeZeeBB 2ec25df23b Mod merge: costume presets that crash the game's load are repaired, and material rows past the shader programs left out
Master Chief and TASM2 Spider-Man ship appearance presets whose EBX lists a type reference on the
slot of an import, which the game's load reads as a type index and crashes on (Skate.exe+0x3def285
and +0x3def262 in Sentry). The merge now checks every mod's own EBX, including bundles it would pass
through whole, and takes such entries (or a repeated one) out of the copy in the merged patch and of
the copies carried into other mods' bundles; the mod's original still feeds any combine, and the
merge notes say how many per mod and bundle. The check reads only the fixup lists.

A material lookup row pointing past the shader programs the game ships is left out of the merged
lookup, with a note, instead of reaching the shader registry. Tests for both.
2026-10-17 14:27:20 -05:00
zeex64 3aebb38832 Merge pull request #271 from worthlessnorms/merge-carried-once
Mod merge: write each carried asset once, not once per map
2026-10-16 20:10:11 -05:00
AyeZeeBB a2d6daffbc Official mods: Board Break and Road Rash downloaded from Thunderstore and kept at their latest, with an Official tab
The launcher reads the official list from the ReSkate backend (or the last one it read, or its own)
and keeps each mod in Mods/.reskate-official at its latest version; a copy the player installed is
moved in, the deprecated Board Break retired. The game loads them always on and leaves out Mods
folder copies; the browser no longer lists them. The built-in zips are gone (FPV drone too), and
built-in folders no longer carried are removed.
2026-10-16 18:59:41 -05:00
AyeZeeBB 43b998f285 Built-in content: Board Break and Road Rash, replacing their Thunderstore mods, packed with zstd
Fourth Studio's Board Break pack (ten decks and every sound) and Road Rash wounds are built into
ReSkate.dll beside the FPV drone, unpacked under Mods/.reskate-builtin and always on.

- The Thunderstore copies (Fourth_Studio-Board_Break_Pack, Fourth_Studio-Road_Rash and the
  deprecated Fourth_Studio-Board_Break, or the same put in by hand) are moved to the Recycle Bin
  as the launcher starts and dropped from mods.json; the merge leaves them out should one still
  be there, and the Thunderstore browser no longer lists, updates or installs them, a dependency
  on one included.
- Board Break's deck list, sounds and deck settings look in the built-in packs too.
- Names with spaces inside them (Board Break's "Body Impact 1.wav") unpack.
- The build makes each zip in assets/builtin into one zstd stream (ReSkateBuiltinPacker,
  Engine/Vfs/builtin_pack_format.h), which the DLL carries: repeated files across a pack cost next
  to nothing. Board Break 15.0 -> 5.4 MB, the drone 6.0 -> 5.4 MB, Road Rash 36.1 -> 34.2 MB;
  ReSkate.dll 86 -> 70 MB. Plain zips still unpack.
- Tests: the mods taken for built-in ones and their retirement, and a pack unpacking to exactly
  its files, refusing one that leaves its folder or is cut short (RESKATE_BUILTIN_PACKS also
  unpacks the packs a build made).
2026-10-16 18:38:46 -05:00
worthlessnorms 89927bf90f Mod merge: an asset carried into many maps is written once
A carried asset was written again for every superbundle that carried it: 1.4 GB of 2.2 GB with 96 mods, which left no room for a live apply. Each one is now written once per install chunk, when its first superbundle settles.
2026-10-16 11:01:57 -05:00
AyeZeeBB 164fdffbd0 Descriptor heaps: dense custom maps no longer overflow the GPU's descriptor heap and crash it
The renderer gives each frame 131,072 shader-visible descriptors past a persistent 120,000, in
heaps of 333,333. Dense custom maps (the Los Santos City sublevels, San Andreas) draw more than
that in a frame, and the renderer wrote past the end of the heap: shaders read garbage
descriptors, which faulted or hung the GPU (page faults at nonsense addresses, in draws, texture
fetches and ray tracing alike). ReSkate now patches the device setup at boot so each heap is
D3D12's 1,000,000 and a frame may use 524,288; heaps are 644,288 descriptors. LS-B2, LS-B3 and
San Andreas (210,000 a frame at its peak) now hold.

Also in this change:
- Memory: perf memory owners/heap/gpu/report, a ledger of who commits the game's RAM; the
  render-resource pool no longer allocates its 115 MB twice; the EadpErrorsData arena is
  capped at 32 MiB (EA's error reporting is blocked anyway).
- Crash reports: tagged with the map, destination, graphics card and driver version (protocol
  v3), so Sentry can group GPU hangs by map and card.
- GPU diagnostics (--gpu-diagnostics): a fuller DRED report, the device-removal and video
  memory watches, a large-draw watch, a record of which game code made and freed each GPU heap
  and resource, checks of every GPU address bound, and a meter of each descriptor heap's use.
- World pools: peak use of entity pages, render instances and spatial blocks in the log.
- dingosdk_mod_mesh_check: checks every MeshSet a mod ships against its geometry; the MeshSet
  reader now knows static meshes' layout.
2026-10-15 13:57:11 -05:00
AyeZeeBB 2e186b9839 Launcher: mod profiles, sharing them by code or file, and Thunderstore dependencies
The Mods page has a third tab, PROFILES. A profile is a saved list of which
mods are on, in what order and at what version; every mod stays installed
once, in the one Mods folder. Loading a profile rewrites mods.json, switches
off what it does not name, and downloads from Thunderstore what it names
that is missing. Profiles live in Mods/profiles.json.

A profile travels the way r2modman's do, so the two managers read each
other's: export.r2x inside a .r2z file, and a code on Thunderstore's
profile service. Config files in an r2modman profile are ignored.

Installing or updating a Thunderstore package now brings the packages it
depends on, needed ones first, leaving out any already installed at a new
enough version. A mod pack is a package that is nothing else.

A kick, by an admin or by a passed vote, used to keep the player out until
the server restarted. "kick_minutes" in the players section of the config
(1-1440; 0, the default, is still until the restart) and the console
command "kick-time <minutes>|restart" now set how long it lasts.

The player is told how long when they are kicked, and how many minutes are
left if they try to join early. A kick keeps the time it was given, so
changing the setting is for later kicks. Bans are unchanged.
2026-10-13 00:55:29 -05:00
Frumpy9 d0985ffcfd fix: anchor Oodle lookup and write portable release ZIPs 2026-10-12 17:14:21 -04:00
AyeZeeBBandClaude Opus 5.5 d2b8e18097 2.0.7 hotfix: map updates, vote bar, ReSkate Admin tag, servers on the newest map version
Map updates
- A map the game already has, being replaced by the host's version,
  could load as soon as the new files were in Mods, while the mods
  were still being applied: it ended on "This map is not loading". The
  session now holds the load while a map is downloading, installing or
  applying, as it waits for one that is missing.
- A player whose version of a map is later than the host's keeps it and
  loads. Only an older one is replaced by the host's. Versions are
  compared number by number (1.10.0 is later than 1.9.2).

Dedicated servers
- maps.latest_versions (off by default): the server asks Thunderstore
  for the newest version of each of its custom maps, at start and every
  maps.latest_check_minutes (5-1440, default 60), and writes it into
  the mod's manifest.json. Nothing is downloaded: the server reads only
  a map's level list and version, and players, who are held to the
  server's version, fetch it as they join. The map being played waits
  until nobody is on it. A folder that is not a Thunderstore package is
  not touched, and the level list is left as it is.
- Console: maps update, maps latest on|off, maps latest every <minutes>.

Overlay
- Vote card: the pass mark is always in the middle of the bar. Green
  grows over the left half up to the yes votes needed and over the
  right half past them, whatever share the vote needs.
- The "Staff" tag is "ReSkate Admin", shimmering from #2500FF to
  #B2F9FF.

No protocol change. Tests cover the version comparison and the
manifest write; the Thunderstore lookup was checked against the site.
The map update flow, the vote bar and the tag were not seen in game,
and the server setting has not run on a live server.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:19:49 -05:00
zeex64 0b28dbd7c9 Merge pull request #163 from moelrobi/server-park-mods
Dedicated server: park mods as server-owned objects
2026-10-11 13:20:30 -05:00
AyeZeeBB c27d6cb053 Word filter: fewer false flags, servers' own word lists; protocol 49
The chat filter matched short listed words anywhere inside a longer one, so
entries like "gger", "spik", "crip" and "coon" in the backend's lists blocked
"bigger", "spike", "script" and "raccoon".

- A listed word of four or five letters now matches inside a longer word only
  when the rest of it is what goes around a swear word ("motherfuckers",
  "bullshit", "shithead", "shitty", "xxfuckxx"). Words of six letters or more
  still match anywhere.
- An ordinary word that equals a listed phrase without its spaces
  ("the rapist" / "therapist") no longer matches.
- bad_words.txt is gone: the filter has no words until the backend's lists
  arrive.

Dedicated servers:
- "use_global_word_filter" (default true) turns the backend's lists off for a
  server. Console: words global on|off.
- data/words_filtered.txt and data/words_blocked.txt hold a server's own
  words, read at start and by "words reload". Blocked words follow
  word_warnings. Filtered words are sent to players (new packet, kind 33),
  whose games star them for players with the chat filter on and drop them on
  leaving.

Multiplayer outfits: a player whose mods add or remove skater or board slots
no longer makes everyone look like the local player. A peer's items are put
in this game's slots by slot hash; slots the peer lacks stay empty and items
in slots this game lacks are left out.
2026-10-11 13:17:28 -05:00
Robin MöllerandClaude Opus 5.5 6909fe3a2e Dedicated server: park mods as server-owned objects
- maps.park_mods binds a Park Editor park mod (Mods/<folder>/parks/<key>.park.json)
  to a name and the map it was built on; maps.park_limits caps the parks and
  objects spawned at once (3 and 512 by default)
- park-mod list | add <name> [<name>...] [minutes] | remove <name> [<name>...] | clear,
  from the console, as /park-mod by admins, and by players through custom votes
- A spawned park is the layout of the server's own SteamID and epoch, sent like a
  player's: games since 1.0.0 already show it, it counts against no player's
  object limit, nobody can move or delete it, and it stays when players leave
- Objects players' games would not take (not Build Kit items, broken values) are
  skipped and logged; a missing or broken park is an error line when spawning
- Optional expiry (1-1440 min) with a warning in chat a minute before; every
  park goes on a map change and none survive a restart
- [parks] log lines name who did it: console, the admin, or "a vote"; a vote's
  refusal reaches chat
- park-mod is reserved for custom commands; README.txt documents the settings,
  commands and a park/unpark vote

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y2G4APEkhHgVs59RDL3XWD
2026-10-11 17:45:49 +00:00
wxndr 4ea92f0258 Add native DirectX 12 graphical server management GUI & live telemetry (Windows)
### Overview
Hey! This PR adds an optional native DirectX 12 graphical interface to the dedicated server (`ReSkateServer.exe`), making it easier to monitor and manage a server without having to rely solely on the raw terminal.

### What's included:
- **DirectX 12 / ImGui Management GUI**:
  - Live console with color coding and command input.
  - Connected players list with real-time ping, position coordinates (click to copy), and kick/ban controls.
  - Live map switcher and world layer manager.
  - Ban list & admin manager.
  - Real-time tick rate / latency graph and live telemetry table.
  - Server configuration & release update checker in Settings.
- **In-Game Badges & Roles**: Synced with official nametags/role badges (`DEVELOPER`, `CREATOR`, `HOMIE`, etc.) just like in-game HUDs.
- **Headless CLI Support**: Kept full compatibility for headless/VPS setups — running with `--headless`, `--cli`, or `--no-gui` (or on Linux) runs standard terminal mode as usual.
- **Thread Safety & Performance**: The GUI runs on the main Win32/DX12 thread while server host/networking ticks run asynchronously on worker threads so tick rate is never blocked.

Tested on Windows Server 2022 with Release x64 builds against local and Steam SDR sessions. Let me know if you'd like any adjustments!
2026-10-10 18:25:29 -04:00
AyeZeeBB 0ae0e71f0f Map downloads on join, faster mod merging, connect cards in the server browser
Map downloader
- A host or dedicated server now tells joiners which Thunderstore package
  its map comes from (the Mods folder name plus manifest.json).
- A player without the map gets a card: icon, name, author, version and
  description, with DOWNLOAD and CANCEL. It works with mouse, keyboard and
  controller.
- Only packages listed as Maps in the ReSkate community are offered, and
  never deprecated, rejected or NSFW ones.
- On yes the package is downloaded, installed into Mods and applied as a
  live mod, then the session loads the map. A small card on the right
  shows the progress, so the player can keep skating.
- The player stays connected while it downloads: the host gives a player
  who says they are fetching the map up to 45 minutes instead of the
  usual load time.
- When the server changes map with the player in it, the card says so.
- Protocol version 47: map package on map_offer and world_state, and a
  "fetching the map" flag on map_request and world_ready.

Joining
- The pause-menu server browser shows a CONNECTING card over the page
  while a join is under way, and a COULDN'T CONNECT card with the reason
  when it does not get in.
- The session and voice tabs no longer show before the player is in.
- Leaving without the map (declined or cancelled download) no longer
  counts towards the failed-join limit, on servers and player hosts.

Input
- A card that asks something holds the game's input until the buttons
  are released.
- Steam's overlay hooks XInput in front of ReSkate and answers the game
  itself, so a controller reached the game behind menus. ReSkate now
  hooks that hook as well.

Mod merging
- Mods are read on several threads, at launch and for live merges. A live
  merge runs below the game's priority.
- The paid-cosmetics check reads the game's files and the mods on several
  threads.
- A live merge reuses the paid-cosmetics verdicts it already has and
  reports its progress and timings.

Launcher
- NSFW mods and their categories are not shown in the mod browser.
2026-10-10 13:15:04 -05:00
AyeZeeBB 94ce8fddd7 Launcher: edit skate.'s own settings (graphics, audio, camera, controls, replay)
Settings has five more pages, under "SKATE. SETTINGS" in the rail, for the
settings the game saves per PC:

- GRAPHICS: window mode, resolution, HDR, brightness, UI brightness, HUD
  display, then the game's graphics options (frame rate limit, VSync,
  dynamic resolution, upscaler and its quality, antialiasing, textures,
  lighting, shadows, mesh, effects, post processing, global illumination,
  ambient occlusion, depth of field, motion blur) with buttons that set
  every low-to-ultra option at once.
- AUDIO: volumes, voice chat, text and voice language, subtitles, party
  menu narration.
- CAMERA: sensitivity, and the on board, off board and climbing options.
- CONTROLS: vibration, trigger force feedback, show controller on HUD,
  highlight indicator, the experimental toggles.
- REPLAY: editor speeds and sensitivity, effects, first-person keyframes.

They are written straight into the game's save containers under
%LOCALAPPDATA%\ReSkate\Game\Skate\data (game_settings.h): a DATA file of
sections and an INDEX naming them, the body one binary object of named
values. Only the values changed are rewritten, in both of the game's
copies; every other byte is kept. A container that cannot be walked whole
is left alone. The first change copies the untouched files to
%LOCALAPPDATA%\ReSkate\game-settings-backup.

Keys, kinds, ranges, steps and choices are the game's own
(DingoUISettingAsset in its data, build 20260929). The labels are ours.
Resolution is saved by the game as a place in the PC's list of display
sizes; the launcher lists Windows' sizes smallest first, which matches the
one PC it was checked on.

A change is stored once the control is let go. The pages are disabled while
a game this launcher started is running, and say so when the game has not
saved its settings on the PC yet.

Not offered: refresh rate, fullscreen monitor and audio devices (places in
lists the game builds at run time), the mobile-only settings, and settings
the game saves to the account rather than the PC.
2026-10-10 02:30:50 -05:00
AyeZeeBB 63955e51ff Launcher changelogs, download total, Discord joins skip the launcher window; Mod Options
Changelogs. The launcher's main screen has a CHANGELOGS tile in the
bottom-left corner. It opens a panel with the newest GitHub release: its
tag, title, date and notes. The notes are the release's description, read
as markdown and drawn like a mod's README (headings, bullets, code, rules).
A release published without a description shows what its GitHub page shows,
the tagged commit's message, taken from the releases feed. Fetched once,
the first time the panel opens; "Open on GitHub" goes to the releases page.

Download total. On GET MODS, the bar for ticked mods now gives the size of
what installing them downloads: "3 mods selected / 1.27 GB to download".
It is the sum of each mod's newest version as Thunderstore lists it.

Discord joins. The command the game registers for Discord to start ReSkate
now passes --no-gui, so pressing Join with the game closed goes straight
into the game instead of stopping at the launcher window.

--no-gui with no other launch flags now starts the game with the launcher's
saved settings (window size, menu and console keys, loose files, GPU
diagnostics, Discord status, offline, log level, extra launch options), as
pressing PLAY does. With flags of its own it behaves as before.

Mod Options. The pause menu's "Custom Stuff" page is renamed "Mod Options",
in the menu, the READMEs and the comments.

Not tested in game: the Discord join with the game closed, and the renamed
page. The changelog panel has only been seen with the earlier API-only
fetch.
2026-10-10 01:42:36 -05:00
AyeZeeBB 70128cf2d7 Chat word lists from the backend, and warnings for words not allowed
The bad-word list now comes from the ReSkate backend's Words page, in
the same /api/v1/steam-ids answer the game and servers already read.
It has two lists: filtered words, and words not allowed in chat at
all. Until the backend has any words the built-in list stays in use;
once it does, its lists replace the built-in one.

Filtered words work as before: masked for players with the chat filter
on, and not allowed in server or lobby names. Words not allowed at all
are filtered the same way, and a chat message with one is not passed
on. Its player is warned each time, and after three warnings the next
one gets them kicked.

Dedicated servers: new players setting word_warnings (default 3, 1 to
10, 0 switches the rule off). The count lasts while the server runs,
so a kicked player who joins again is kicked at their next one. Party
chat and commands are checked too, and each warning and kick is logged
under [words]. The lists are read whenever global bans or word
warnings are on.

Player lobbies: the host's game applies the same rule to its guests,
with three warnings.
2026-10-09 21:54:40 -05:00
Jean-Luc T. e031571e1a Validate DepotDownloader progress output
Reject malformed, non-finite, and out-of-range progress values while preserving them as ordinary messages. Add parser regression tests for progress and QR-code output, and register them with CMake.
2026-10-09 18:14:35 +02:00
AyeZeeBBandClaude Opus 5.5 29c42911ff Merge pull request #130: server admin commands in their own file; one update loop
Conflicts in Server/server_host.cpp: main changed the command code after this
branch moved it to Server/server_commands.cpp. The moved copy now has what
main added since: the "chat-color" command, "park random", and its line in
the help text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 21:24:32 -05:00
zeex64 63ee53382a Merge pull request #63 from northdroplet/feat/gamepad-touchpad
Launcher: controller support and the Steam Deck trackpad as a mouse
2026-10-08 21:04:34 -05:00
AyeZeeBB 7050fad406 Launcher: trucks back on MODS; Thunderstore button reads as a link out
- The MODS tile shows the skate tool again, faded like the wheel on
  SETTINGS. Thunderstore's mark is no longer drawn there
- The mod manager's Thunderstore button is laid out as a link sign, the
  name, then Thunderstore's mark at the far end, so it is plainly a way
  out to a website. The sign is drawn (a box with an arrow leaving its
  corner); the name is no longer in capitals
- It keeps Thunderstore's green on its dark blue and its height
2026-10-07 15:12:35 -05:00
AyeZeeBB 56b687b058 Launcher: Thunderstore's mark on MODS and its button; ask about enabled mods' updates only
- The MODS tile shows Thunderstore's mark in its own green instead of
  the skate tool, which stays as the fallback when the mark is not
  built in
- "Open Thunderstore" in the mod manager is a branded button: the mark
  and name in Thunderstore green on its dark blue, taller than the
  plain buttons beside it
- The mark is a new asset, assets/launcher/icon_thunderstore.png,
  embedded like the other tile icons
- A disabled mod's update is no longer asked about before PLAY or
  counted on the MODS tile, and "UPDATE AND PLAY" no longer installs
  it. A disabled mod does not load, so its update stays on the Mods
  page, where it can still be updated by choice
2026-10-07 15:01:55 -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
zeex64 f787733b5c Merge pull request #87 from DeckardDetribine/feature/music-playback-order
Music: preserve playlist order and add a Shuffle option
2026-10-06 16:49:52 -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
ReSkate local d264ac778c Music: add playlist-order playback toggle 2026-10-06 03:26:37 +01:00
ReSkate local 3db1ef7ca5 Music: release Mods shelf before map unloading 2026-10-06 02:07:26 +01:00
AyeZeeBB 137273e274 carry added assets with a changed list, combine in-place values, list repeats once
Merge: carry added assets with a changed list, combine in-place values, list repeats once

Three merge bugs found by auditing 104 installed mods:

- A changed list (the music playlist) reached every bundle copy that holds
  it, but the songs a mod added beside it only reached copies of the bundle
  the mod added them to. The game keeps the playlist in eight bundles, so
  the other seven named songs they did not hold. Added assets now follow
  the change into whichever bundle copy takes it.
- An entry naming an asset that lost its name to another mod's asset is
  now dropped from the list, both in the merged bundle and in the list
  other mods' copies are given.
- Two mods changing values in place in one asset (lighting) kept one mod's
  copy whole and silently dropped the other's. Plain values are now
  combined, the higher-priority mod winning where both changed one. An
  edit that also moved a reference or resized a list is taken whole or not
  at all, and the merge notes whose changes are missing.
- A reference two mods both append to a list is listed once.
2026-10-05 18:53:51 -05:00
zeex64 2c80bf1b8c Merge branch 'main' into fix/playlist-lookup-crash-guard 2026-10-05 17:00:52 -05:00
zeex64 f6e191cfbd Merge pull request #48 from DeckardDetribine/pr/mod-music-artwork
Music: custom playlist and song cover artwork for mods
2026-10-05 16:57:56 -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
NorthDroplet 360338e6e1 Launcher: controller navigation and the Steam Deck trackpad as a mouse
The launcher read no controller at all. Started from Steam (Desktop or Game
Mode on a Steam Deck), Steam Input applies the game's gamepad layout to it,
where the right trackpad is the right stick and its click is R3, so the
trackpad did nothing; only the touch screen, which arrives as mouse
messages, worked.

- Every XInput pad is merged (Xbox, Steam Input's virtual pad), else a
  DualShock 4 / DualSense is read over HID with the reader the in-game menu
  already uses, now its own library (dingosdk_playstation_input).
- D-pad and left stick move ImGui's focus, outlined in the launcher's blue;
  A / Cross presses. The hand-drawn tiles, switches and menu buttons take
  part in navigation (ImGuiButtonFlags_EnableNav).
- B / Circle closes an open combo or menu and leaves a text field, and is
  Escape otherwise, which the launcher's pages already go back on. Escape
  now also closes the mod overviews and answers Cancel in the uninstall and
  replace confirmations; closing an overview no longer also leaves the page.
- The right stick (the trackpad) moves a pointer that ImGui draws, and R3
  (the trackpad's click) is the left button. The system cursor follows it;
  a mouse move or a touch elsewhere takes the pointer back.
- The ImGui Win32 backend's own gamepad code (slot 0 only) is compiled out
  so it cannot fight the launcher's events; nothing else used it.
2026-10-05 14:27:08 +00:00
ReSkate local 2e6882ede1 Music: guard the playlist lookup against unresolved song entries
The music player's playlist walk loads a song entry, masks it and reads a flag at [rcx+0x14] before it checks the entry's identity. An unresolved or NULL entry makes that read fault and takes the game down while a playlist is built or opened.

Install a 13-byte in-place guard at the reviewed RVA 0x14f80c7 when the music contracts pass. It keeps the original flag test, shrinks the leading mov eax,0 to xor eax,eax, and adds a jrcxz that skips the dereference when the entry is NULL, landing on the loop increment. The site is matched against its contract bytes before anything is written, so an unsupported image is left untouched, and the guard is applied with VirtualProtect and FlushInstructionCache and then made read-only again.

The contract and patch bytes live with the other music contracts in Engine/Game/Build/20260929/local_music.h; the installer is Extension/Music/local_music_safety.{h,cpp}; local_music_ui.cpp invokes it from initialize_music_functions; cmake/Runtime.cmake builds it. A new dingosdk_music_safety_tests (CTest music_safety) pins the contract length, the decoded instructions and the branch target arithmetic without needing the game.
2026-10-05 06:31:13 +01: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
ReSkate local 5a01b1b0de Music: support custom playlist and song cover artwork in mods 2026-10-05 00:09:41 +01:00
zeex64 fb448059cc Merge pull request #36 from DeckardDetribine/pr/music-mod-playlists
Music: let a mod name a playlist for its songs (reskate-music.json)
2026-10-04 13:35:06 -05:00
DeckardDetribineandClaude Opus 5.5 c7f54b7680 Music: let a mod name a playlist for its songs
A mod that adds songs can ship reskate-music.json
({"schema":1,"playlists":[{"name","songs":["artist - title", ...]}]}). Each
playlist is merged into the game's music screen the way a content-cache
station is, under the id "mod:<mod folder>:<name>", with its songs matched
against the songs the game has registered; entries that match nothing are
ignored and a playlist left empty is dropped. A file of the wrong shape is
logged and skipped.

The file is read by parse_music_playlists in Engine/Vfs/mod_music, which a new
test covers (ids, which entries survive, the limits, and that a malformed
document is refused). The format is described in the README.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 18:12:42 +01:00
DeckardDetribineandClaude Sonnet 5.5 dddb91f381 Test the merge on assets a mod adds next to a map's own copy of the bundle
A fixture of a made-up game, a level mod with its own level superbundle holding
a copy of a bundle, and an asset mod that changes one asset to name a new song
and adds the song, its wave, the wave's resource and one asset nothing names.
The merged copy in the map's TOC must gain exactly the three the changed asset
leads to, whichever mod has priority. Against upstream's merge it fails with the
merge's own warning that the mod's additions to the bundle are missing.

The documents are built in the test, so it needs no game files.

A second scenario puts two mods' copies in the adder's own TOC and checks nothing is
carried into it and the merged bundle is just the union.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 17:44:09 +01: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
juan 88fb78aaca Merge upstream/main (v1.0.4): mod install naming, settings cache fix, Proton detect
- Conflict in cmake/Apps.cmake: kept Linux WIN32 guards, took upstream's
  Launcher/problem.h source + dingosdk_mods link.
- Upstream touched Windows-only areas; Linux server closure untouched.
- Verified: Linux configure + build + 8/8 portable ctest green.
2026-10-03 19:15:04 -03:00
AyeZeeBB 201571c225 Merge mods before launch; name the mod that could not be merged
A mod the merge could not use was left out silently. The game started
without it, three minutes into a loading screen, and only ReSkate.log said
which one.

Merging before launch
- PLAY runs the merge the game would have run behind its splash, on the
  launcher's worker, with the step and progress on the STATUS tile
  (Phase::merging). The launcher links dingosdk_mods for it, which costs
  about 600 KB of exe.
- When every mod merges, the launch goes ahead and the game's own
  load_catalog finds the patch already built, so the splash is shorter
  rather than the work being done twice.
- When mods were left out, the launch stops at Phase::mods_broken and a
  dialog names each one and its first problem, with three ways on: switch
  them off and play (which writes mods.json, so the next launch does not
  rediscover it the hard way), open the mod manager, or play anyway.
- Mods built for another game version do not block. They already have
  their own notice and message box, and blocking on them would stop play
  after every Steam update.
- The launcher resolves -dataPath out of the extra-arguments setting, so
  it merges against the root the game will read.

One SDK identity for both binaries
- Two places recorded "which ReSkate did this" as the module the code was
  running in, which is ReSkate.dll in the game and ReSkateLauncher.exe in
  the launcher now that both merge. merge_fingerprint hashes it, so the
  game matched no stamp the launcher wrote and merged everything a second
  time; sdk_identity keys the exclusions file, so each would have called
  the other's exclusions stale.
- Both now name ReSkate.dll beside the running executable. Skate.exe and
  ReSkateLauncher.exe sit beside it and launch.cpp enforces that, so the
  two agree, and unlike the data root it does not move under -dataPath.
  The value is unchanged from what the runtime computed before, so nothing
  re-merges on upgrade.

Naming the mod
- In game, a mod left out of the merge altogether said nothing on screen:
  only a mod that merged partially did, which is the lesser failure. Both
  are named now.
- The MOD MANAGER tile says which mod did not load, in the detail line's
  colour rather than a pill, clipped so a long name cannot run under the
  tile's artwork.
- MY MODS carries a line naming them above the list, and NOT LOADED and
  OUTDATED are badges on the row instead of words at the front of its
  summary.

MY MODS reaches Thunderstore parity
- Rows carry the package's icon, the same one the store shows, through a
  shared mod_icon(); a mod that never came from Thunderstore keeps the
  placeholder.
- An update is a button on the row, not a badge you had to open the mod to
  act on, and every row has Uninstall. Rows grew to fit, and "Remove" is
  "Uninstall" throughout.
- No pill for a mod that is up to date: the absence of an update button
  says it, and eight green pills said nothing eight times.

Fixes
- The install panel was drawn on the Mods page's own draw list after its
  children, and ImGui renders a child after its parent, so it was painted
  behind the mod rows along with its Cancel button: installs ran with no
  sign of it. It is its own window over the page now.
- pump_icons, which uploads decoded icons, only ran on the store page, so
  MY MODS showed placeholders until a visit to GET MODS uploaded them for
  it. The page does it for both lists.
- The merge dialog's closing advice overlapped its buttons.
2026-10-03 17:08:03 -05:00
AyeZeeBB aef269497e Rebuild the launcher's mod manager, settings and status tile
The mod browser was a 960x620 panel inside a 1180x680 window, reached from
a tile the same size as SETTINGS. People could not find it, and once they
did there was room for about six mods.

Window
- The design size is 1440x840. Everything is laid out in design units and
  multiplied by g_scale, which now scales down when that would not fit the
  screen's work area, so a small laptop or a high DPI no longer gets a
  window running off under the taskbar.
- The MODS tile is MOD MANAGER: taller than SETTINGS, directly above PLAY,
  with the pending update count as a pill on its subtitle line.
- background.jpg is 1920x1027, so the bigger window is not upscaling a
  1280x720 photo.

Mod manager, a page rather than a panel
- begin_page fills the window and draws its own minimise and close, since
  it covers the main screen's. BACK or Escape leaves it.
- A nav rail holds MY MODS and GET MODS (count badges, blue for the open
  one), the install actions and BACK. Refresh sits with what it refreshes,
  top right of the content.
- Every mod is a full-width row: icon, name, author, description, version
  and downloads, with a blue INSTALL or UPDATE and a tick box on the right.
  Ticking several installs them in one run.
- Clicking a row opens that mod's overview in a popup, replacing the
  side-by-side details pane that halved the list's width.
- virtual_rows draws only the rows a scrolling child actually shows.
  ImGuiListClipper cannot do this, as it assumes every row is a fixed
  height.
- Installing is a centred panel over a dimmed page with the activity, a
  striped bar and Cancel, instead of a progress bar in the footer.

Settings
- The same page and rail: GAME, DISPLAY, KEYS and ADVANCED are nav tiles
  rather than a row of tab buttons, and the content keeps to a 760 px
  column so the explanations stay a readable measure.
- The Steam sign-in, Steam Guard and QR dialogs stay centred panels. They
  are prompts, not pages.

Status and failures
- The STATUS tile carries its state in a coloured edge and a pill (WORKING,
  READY, ACTION NEEDED, PROBLEM), its headline is 22 pt over muted detail,
  and the standing facts (game build, ReSkate version) sit under a rule
  instead of competing with the live status as equal rows.
- Launcher::fail keeps the raw message for the log, and problem.h turns it
  into a headline and the next thing to try. The injection and PE-identity
  failures ("VirtualAllocEx failed", "Injected ReSkate.dll is not present
  in the child module list") all become "ReSkate could not attach to
  Skate", with the anti-virus and overlay advice that actually fixes it;
  the Steam download, a missing or damaged ReSkate.dll, the content cache
  and a shared menu/console key each get their own. Anything unmatched
  keeps its raw text.
- A failed tile grows Open logs and Copy details. Copy details puts the raw
  message and the versions on the clipboard, ready to paste into Discord.
2026-10-03 16:10:55 -05:00
Juan 9ddbd0c7ce Linux build system: server-only target + portable warnings
- CMakeLists: allow Linux 64-bit, server-only includes, portable tests
- ProjectOptions: MSVC /W4 vs GCC -Wall, version.rc Windows-only
- Core/Dependencies: guard Windows-only libs, OpenSSL for launcher_support
- Apps: launcher/emote Windows-only, server Linux links OpenSSL/dl/pthread
- Fix launcher_support lambda return, cas_codec Oodle guards, steam dlerror crash
2026-10-03 16:57:18 -03:00
AyeZeeBB ca1d82f636 1.0.0 Release! 2026-10-02 14:40:41 -05:00