98 Commits
Author SHA1 Message Date
AyeZeeBB 89a97caed7 Plugins: an item grid's own list and marks, items worn on top, keys kept from the game, the menu's category icons
General APIs from pull request 269 (the player's own item tabs and outfit layers), whose tabs,
panels and prompts are now a plugin's (contrib/plugins/item-tabs, kept on this machine):
- reskate.menu.grid_show(keys): a plugin's list in the item grid that has the focus, drawn from
  every grid of the screen; reskate.menu.grid_mark(keys): the game's check on tiles. menu.grid()
  also says whether a list shows, whether it is empty, and where the grid's own prompts end.
- reskate.outfit.on_top(items) and on_top_state(): items worn on top of the outfit in the slots it
  leaves empty, the item given the slot's category, a slot tried and left if the game reports a
  failed load (ReSkate.layer_slots.txt remembers which load where); paid store items refused.
  Part of the shared outfit service, with reskate.outfit.set.
- reskate.input.game_keys(keys): presses the game does not see, by any way it reads the keyboard;
  "Delete" is a key name.
- d:game_image draws the customization menu's 17 category icons ("cas_tops", ...).
dingosdk_plugin_tests skips the test of a contrib plugin that is not on this machine.
2026-10-21 19:18:01 -05:00
AyeZeeBB 913b4ce422 Merge remote-tracking branch 'origin/main' 2026-10-21 19:01:43 -05:00
AyeZeeBB 89fca92f19 Launcher: official mods removed; their packs are mods like any other
Now that features are Luau plugins, nothing needs mods of ReSkate's own:
- The OFFICIAL tab and its rail tile are gone, with Launcher/official_mods (the backend's list, the
  install, update and sync, and Play's wait for them).
- GET MODS lists and updates Board Break, Road Rash and the rest like any other package, and MY
  MODS no longer marks them Official or keeps them out of UPDATE ALL.
- The merge may leave one out over a conflict like any other mod; the version stamp, the on/off
  helpers and the move out of the old .reskate-official folder are gone from builtin_packs.
- Installed copies stay in Mods as ordinary mods. The retired first Board Break is still left out.
2026-10-21 19:00:55 -05:00
zeex64 70fb13f130 Merge pull request #307 from wilu222/map-prompt-file-size
Show a missing map's zip file size on the join prompt before the download starts
2026-10-21 18:49:57 -05:00
AyeZeeBB f352179785 Merge main into plugins: the trainer (PR 300), object unlocks (290), server browser sort (302) and export bitrate (322)
Resolved where main's trainer meets the plugin branch:
- Board Break, the drone, Road Rash, Hall of Meat and Grind Exits are plugins here, so their
  built-in code stays deleted: the trainer no longer hands Board Break's wear values back (the
  plugin does not tune physics), its QUICK SETTINGS list no longer names Grind Exits or Board
  Break, and the drone's debug action and menu are not brought back.
- The trainer's pump power, gravity, revert boost and transition help run beside the plugins'
  pushes and velocities on each physics step; both sides' new declarations are kept.
- The game's own pad reads go through game_pad_read (the gamepad filter, Dark Pop's D-pad hiding,
  the grind sticks) and then the plugin branch's menu and hidden-button handling.
- The trainer's forced grind settings are noted as the stance like any other value.
2026-10-21 18:26:55 -05:00
zeex64 5b6d9f43d0 Merge pull request #290 from tsullivan13/object-unlocks
Objects: unlock free build-kit objects; Object Browser category icons
2026-10-20 14:17:33 -05:00
AyeZeeBB e6de1dfd64 Plugins: the merge moves plugins' old files out before it deletes its folder
Plugins' files from before Mods/.reskate_plugin_data were still in Mods/.reskate/data, and the
launcher's merge deletes Mods/.reskate before the game ever looks for a plugin's folder: a saved
Deathrace route went at the next launch that rebuilt the merge. mods::keep_plugin_data moves each
plugin's old folder to Mods/.reskate_plugin_data first (whole, or the files a folder there lacks,
its own kept), at the start of every merge; the game still runs it once for a merge that kept its
patch. Checked in the build stamp test.
2026-10-20 14:09:09 -05:00
AyeZeeBB 4d0182eef9 Plugins: a plugin's saved files live in Mods/.reskate_plugin_data, which no merge deletes
reskate.files kept each plugin's folder in Mods/.reskate/data/<plugin>/, inside the merge's own
output, which every full merge deletes: saved Deathrace routes went whenever a mod changed. It is
Mods/.reskate_plugin_data/<plugin>/ now (mod_list.h plugin_data_folder), and what is still in the
old folder moves across the first time the plugin looks for its folder. Deathrace's routes keep
SmokeyDawg58's <map>/<name>.json layout, so routes from his fork copy straight into routes/.
2026-10-20 13:48:21 -05:00
AyeZeeBB af83281b8d Mods: variants, one of several takes on the same game data; Board Break's decks leave the SDK
A mod's reskate-plugin.json can declare "variants" {folder, order, displaces}: each <folder>/<name>/
is a variant, the one chosen (else the first of its order) loads, and every other mod whose layout
lists a displaced bundle is set aside for the run. Choices are kept in
%LOCALAPPDATA%\ReSkate\variants.json. Plugins read and choose their own mod's variants with
reskate.package.variants and reskate.package.choose (permission "variants"), and fit every board
for a deck that is not the game's own with reskate.board.fit {plates, axle}.

The board-break plugin, which ships inside the Board Break deck pack, declares the pack's decks as
variants, picks the deck on its own page and with `boardbreak deck`, reads each deck.ini and fits
the boards. Gone from the SDK: breakable_deck, the deck catalog, the MODS page's deck card, the
boarddeck command and the Board_Break_<Name> folder naming.
2026-10-20 01:31:50 -05:00
AyeZeeBB e14064250c Merge: a plugin mod's resident assets stay when a map replaces their bundle, and the merge never writes into a mod's own folder
reskate-plugin.json's "resident" list names the assets a mod's bundles keep (world objects and HUD
widgets the game picks at run time, and their shader block depots), so they survive another mod
replacing that bundle. Scanning now uses lexically_relative, so a mod folder that is a junction no
longer yields ../ paths, and every output path is checked to be inside the merge output. Chunk
metadata audit failures are fixed; the full merge audit passes.
2026-10-20 01:04:37 -05:00
AyeZeeBB 0ff96018d0 Throwdowns: plugin modes on the native Throwdowns page, which is SmokeyDawg58's logo grid
reskate.throwdowns.mode{...} adds a mode to the game's own Throwdowns page: a card on
the picker, the real Spot Battle setup page relabelled with the mode's name, logo,
description, players, timer and rows (sliders, choices, buttons), and the native start
flag. The plugin hears throwdown_mode events (opened, setting, button, placed with the
flag's position and heading, start, leave, cancelled) and runs the mode itself;
release_flag takes the flag down. The flag's queue never starts a Spot Battle: its
waiting card's Start goes to the plugin, MaxPlayers is held at 10 and it is never
relayed as a drop. After SmokeyDawg58's one_up_menu and one_up_placement
(reskate-custom-mods), generalised over a mode registry.

The page is his 4-column logo grid whether or not a plugin has a mode. Its widgets and
grid records, and the game assets it uses that only some levels load, ship in
ReSkate.dll as the throwdown_menu built-in pack, taken from his asset mod's FBMOD
(dingosdk_ebx_pick trims the asset list in place). A mode's logo is a texture path in
its own mod, so no mod edits the shared list. The FPV drone is no longer a built-in pack.

Native menu data: text initialization, change-only writes, retained array publication,
owned-model rollback. Tests: registry and setup helpers, the plugin API, a test plugin
with two modes.
2026-10-19 18:38:10 -05:00
AyeZeeBB 2d3b77701d Plugins: drone, Board Break and Road Rash are plugin mods now; their C++ is gone
The three features are Lua plugins in contrib/plugins (fpv-drone, board-break,
road-rash), built on what this adds to the plugin API: flight input, gamepad and
joystick reads with input capture, a rolled camera, a package's own sounds and a
synthesised motor (plugin_sound, plugin_wave, motor_synth), the skater's physics
events (skater_events), items worn over the outfit (outfit_overlay, skater_items),
the board's bones (board_pose), skater animation (anim_core), plugin images,
throwdowns started for chosen players, and server copies of plugins on a lobby
host and the dedicated server (server_plugins).

Removed from core: Extension/RoadRash, Extension/BoardBreak, the drone's flight,
radio, follow, OSD, beacon, outfit and sound code, its prop models (native_prop),
the DRONE, BOARD BREAK and ROAD RASH menu pages, home tiles and native menu rows,
their console commands, the drone follow debug action, the drone marker packet
(kind 36 stays unused; the roster keeps its byte) and the server's drones setting.

Kept in core, since every board needs it whichever plugins run: the breakable
deck packs (breakable_deck: which deck, its label and wheel spacing, the
boarddeck command and the BREAKABLE DECK card on the Mods page), and board_pose
keeping a deck pack's stretches out of sight, the baseplates on the deck and the
wheels at the deck's spacing on every board.
2026-10-19 16:22:15 -05:00
wilu222 f737e5b51f Show a missing map's zip size on the join prompt before the download starts 2026-10-18 19:17:07 -04:00
AyeZeeBB fffd34ca80 Mods: conflicts resolved in MY MODS, official mods live in Mods, and big maps merge faster
MY MODS: a table with an animated drag for the load order, a conflicts bar with Check conflicts, and a Resolve popup whose choices are kept. The check runs at startup and after changes; conflicts no longer show as problems, block Play, or hold mod files during an update.
Conflicts: only game EBX that cannot be combined, or Lua scripts with different versions; colourways and same-name additions are not conflicts.
Official mods: installed in Mods/<Namespace-Name> and turned on or off through mods.json, so they show in MY MODS; the old .reskate-official folder is moved over.
Merge: a scan cache (Mods/.reskate-scan.txt) keeps each unchanged mod's repair, mesh and texture scans, so big maps are not re-read every merge.
Launcher: an announcement from the backend shows under STATUS, with HIDE.
2026-10-18 16:33:53 -05:00
AyeZeeBB db99ed4d72 Mods: two mods that conflict load only the higher one, found before the merge
Where two mods change one of the game's assets in ways that cannot both be
in the game (a resource or chunk changed differently, an EBX whose changes
cannot be combined, different assets added under one name), the one lower
in the load order is left out whole, so neither loads half its changes.
The merge used to keep the higher copy of each asset and lose the rest of
the lower mod's change silently, which broke Skaterize beside deckorate.

A check before the merge (find_conflicts) reads only the bundles two or
more mods ship and applies the merge's rule: about 2 s for 296 mods, on
several threads, each mod's copy of a bundle by itself. When it finds
conflicts nothing is built, the catalog leaves the losing mods out and
merges once. The merge keeps its own check behind it, tracking per asset
the last change a mod made itself, so a change carried through other mods'
copies is still caught. A conflict is remembered in .reskate-excluded.json
with the mod it lost to, and stays out while both are unchanged and the
winner still loads above it.

The launcher says "Checking the mods" and "Checking the mods for
conflicts" during those steps. Its mod problems screen says MOD CONFLICT
when that is all there is, and the Mod Manager shows a CONFLICT badge, an
N CONFLICTS banner, a Conflicts filter and, on the mod, which mod it lost
to and how to load it instead.
2026-10-18 01:35:31 -05:00
AyeZeeBB ceb21e0b92 Official mods: installed by the player on the OFFICIAL tab instead of downloaded on every launch
The launcher still reads the list at start and looks up each mod's latest
version, moves in a copy installed from Thunderstore and takes away retired
mods, but it downloads nothing by itself. Each card on the OFFICIAL tab says
NOT INSTALLED, INSTALLED, UPDATE AVAILABLE, DOWNLOADING or UPDATING, with an
INSTALL or UPDATE TO vX button (official_mods::install, on a thread of its
own), OPEN FOLDER once installed, and the On / Off switch beside its pills.
The banner counts how many are installed. Play waits for an install under
way.

Board Break and Road Rash start only when their official mod is installed
and on (mods::official_in_use), and say in the log which it is not; the
menus leave them out otherwise, as when turned off.

The live test (RESKATE_OFFICIAL_LIVE) checks that nothing downloads until
asked, then installs each.
2026-10-17 21:39:50 -05:00
tsullivan13andClaude Opus 5.5 86fea38bcd Objects: unlock free build-kit objects; Object Browser category icons
Many free object-dropper objects were treated as store items and hidden from
the Object Browser and the park editor (pole jams, road signs, bleachers, A
frames, quarter pipes, bowl pieces, ...).

- Items whose record names a neighbourhood rank unlock (field 11) are open,
  even when no rank record lists them as a reward (20 objects, 6 cosmetics).
- Build-kit objects that no record offers, sells or grants are open (169).
  Objects with any offer or bundle grant, and brand collabs (field 24), stay
  reserved: 42 of 439 on build 24855063. Cosmetics are unchanged.
- Object Browser categories use their first object's thumbnail as the tab
  icon instead of the game's empty placeholder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:24:17 -07:00
AyeZeeBB 675ad087f2 Official mods: each can be turned off in the launcher, and then the game leaves it and its feature out
The OFFICIAL tab has an on/off switch on each mod's card, with an OFF pill
while it is off. The list of those turned off is
Mods/.reskate-official/official-off.txt, one folder name a line, which the
launcher's sync never removes. A mod turned off stays downloaded and kept
up to date, but official_packs() leaves it out, so nothing merges it, no
deck comes from it and the in-game Mods page does not list it.

Board Break and Road Rash do not start while their official mod is off,
and say so in the log. The menu model carries that as `off`, and the side
rail, the addon tabs and tiles, the home tiles, the pause menu's settings
and the native tools menu leave them out without a gap. category_tabs
takes a list built at run time for that.

Tests: an official mod turned off stays in place and is left out, comes
back when turned on, and only a plain folder name is written.
2026-10-17 20:55:52 -05:00
AyeZeeBB d15e51e558 Custom maps: the mesh pool follows the map's own meshes, coarser LODs when it is short, and old maps' textures stream
The merge measures each custom map's own meshes, every level of detail of every MeshSet in its
level bundles, into Mods/.reskate/reskate-map-meshes.json. A custom map's mesh streaming pool is
the game's 520 MB and half as much again as those meshes, at most half the video memory free (as
before): most maps have 25 to 70 MB of meshes and reserved 1 to 2 GB for them. When the map needs
more than the card has room for, Mesh.GlobalLodScale goes from the quality preset's 1.25 or 1.5
to 1, so coarser levels take over nearer; the game's value comes back for the next map that fits.

A map's world textures (texture group Worlds_*) flagged to stream that keep every mip with the
bundle, as an older Studio built them (404 MB of PQS Cordoba's), are made to stream as the game's
own do: the bundle keeps the mip tail from a 64 KB block, both first-mip fields of the header and
the chunk record say so, and the sharper mips stream from the chunk the map's TOC lists in full.
Only in a map's own level bundles (Studio keeps cosmetics whole; changing those left a load at
Starting server), and only for chunks whose guid marks them compressed (the streamer reads any
other as raw pixels and copied past what it read).
2026-10-17 17:04:18 -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
AyeZeeBB ab8c9dc6ae Customization: a mod's item card shows the mod, with its icon, inside the game's item card
A mod's item (or one of the game's own a mod changes) keeps three empty description lines, so
the game's item card, which grows upward from a fixed bottom edge, always has room in the same
place; the overlay draws the mod there: its icon (decoded off the render thread into a fourth
texture slot, the last 32 kept), a MOD or CHANGED BY MOD tag, its name, author, version and how
many items it has. The card is placed as the game places its own, measured at many window sizes:
by the smaller of its scales, a 21:9 frame centred on wider screens (the search bar follows it
too). The warning sign the game's focus script gives any description is taken off that notice
each tick while it shows the reserved lines.

The merge's item list records each mod's version and folder (an older list falls back to the mods
loaded at launch). The item grids now run every client tick instead of at the 500 ms
customization pace, follow the highlight between their 40 ms passes, and let go of a grid as soon
as its screen closes, so the card, the search bar and favorites keep up with the player.
2026-10-17 12:04:38 -05:00
AyeZeeBB 4cbec93a3e Customization: a mod's item says which mod it is from
The merge keeps the items the store-copy check reads in every mod and writes them to
Mods/.reskate/reskate-items.json (highest priority first, so an item two mods ship is the one
whose copy the game uses); a live merge keeps the entries of the mods it did not read again, and a
patch built before the file existed is built again once. The game reads it when it builds its
item catalogue: an item a mod adds says "From: <mod> by <author>" under its name, one of the
game's own that a mod changes "Changed by <mod>", unless it has a description of its own.
2026-10-17 10:53:45 -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
zeex64 7000db22b0 Merge pull request #275 from worthlessnorms/merge-history
Mod merge: a mod's copy equal to the game's is not recorded for combining
2026-10-16 20:06:43 -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
AyeZeeBB 320086381c Paths: the last few written as text go through UTF-8, so a non-ASCII name no longer throws
path::string() uses the ANSI code page and throws on a character it lacks (a Cyrillic folder on
an English Windows). The remaining places it was used now go through path_utf8:

- Mods: a deck folder or a mod folder named outside the code page no longer leaves the Board Break
  decks empty, or the Mods folder ignored altogether.
- Game and mod archives: a file under Win32 with such a name is passed over instead of stopping
  the read.
- pose-dump no longer ends the multiplayer session when the game folder is not ASCII.
- The item browser's status line and a Board Break warning no longer fail on such a path.
- Launcher: system fonts are named to ImGui in UTF-8, which it reads.
2026-10-16 18:12:34 -05:00
worthlessnorms 6e1ba2938d Mod merge: a mod's copy equal to the game's is not recorded for combining
combine() recorded every source's copy of every EBX and resource asset, so that conflicting edits could be combined later. Map mods carry near-complete copies of the game's root-level bundles, so most of those copies are the game's own bytes. A mod's copy equal to the game's first copy of the asset, the copy edits are combined onto, is no longer recorded; the game's copy, recorded first, stands for it. A contribution points at its source's folder instead of copying the path. The merge report counts the copies left out.
2026-10-16 16:48:45 -05:00
worthlessnorms 3854942f96 Tests: a carried payload is in its archive once; the patch is read the way the merge reads it
The tests read the merged patch through CasStore and list_bundle, report a missing archive as a failure, and cover a mod archive numbered like a placeholder.
2026-10-16 14:00:35 -05:00
worthlessnorms 3feeaa3893 Mod merge: placeholder archive indexes are reserved; carry() keeps one list
A mod archive numbered 65534 or 65535 is placed under a free index, so no real placement is read as a placeholder. carry() records every payload in one list (settle() still writes each once per install chunk) and keeps one archive index, as write() does.
2026-10-16 14:00:34 -05:00
worthlessnorms cec00f412e Tests: a carried TOC chunk lands on its audio in every map's TOC
The music mod's song names its audio chunk; each map that takes the song carries the chunk too, and every chunk entry in the patch points at bytes inside its archive.
2026-10-16 12:14:32 -05:00
worthlessnorms 5ef0e64e02 Mod merge: a carried asset with no package fails alone
A carried asset whose install chunk no package names fails when it is carried, and is noted, as it was before it was written once; it no longer fails the whole merge when it settles.
2026-10-16 11:02:15 -05:00
worthlessnorms b981813ec8 Tests: a carried asset's placement holds that asset's bytes 2026-10-16 11:01:57 -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 0dcbcb3a89 Drone: other players' drones shown as a 3D model
A model is spawned at each other player's flying drone and moved every frame. It is the drone's
own model (FPV Drone by PinaPipe, CC BY 4.0, credited on the DRONE page), built by ReSkate Studio
into a pack that ReSkate.dll carries and unpacks into Mods/.reskate-builtin before the merge.
Without the pack the game's traffic cone stands in. dronemodeltest spawns one in front of you.
2026-10-15 22:39:49 -05:00
AyeZeeBB 94a616feb9 Map downloads: one that has begun goes on when the session stops waiting
Follow-up to #225. The session still waits 30 minutes in all for a map
(checking, the two-minute question, download, install, apply, join), and
servers and lobbies still let a player go at 30 minutes. But a download
that has begun is no longer cut off at 27 minutes: a large map on a slow
connection never came at all that way.

- Once the download has begun, the session's deadline is the session's
  alone. The download goes on (up to its own four hours, as before #225),
  installs and is applied, and the player is told to join again; no
  rejoin is tried past the deadline, where the server would turn them
  away. "Map still downloading" says so when the session stops waiting.
- Before the download, the deadline still ends the check and the question.
  Declining or cancelling still stops it and removes the partial file.
- A download whose session has gone is not cancelled by joining another
  session; a new map need is turned away until it is done.
- The 27-minute transfer budget and its completion reserve are gone from
  map_fetch_policy.h, with their tests; the map download tests cover the
  new behaviour.
- The HTTPS timeout test compiles with warnings as errors (a signed and
  unsigned comparison), and get_text's stale-file removal is indented again.
- README: map downloads described as they now are.
2026-10-15 14:23:06 -05:00
zeex64 1094e4dc86 Merge pull request #237 from AlexanderPuglisi/fix/unreadable-script-keeps-toc
Mod merge: an unreadable script no longer drops the rest of its mod's TOC from other mods' copies
2026-10-15 14:14:01 -05:00
zeex64 e7c6df0df6 Merge pull request #225 from Jean-LucTch/dev
Fix multiplayer custom map download and join timeout handling
2026-10-15 14:03:06 -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
Fourth Studio b999f37e7b Board Break: wear and tear, rail snaps, break and body sounds, settings
Boards wear: hard landings, hits onto rails and ledges, grinding and
slams wear the board of the deck in the game, kept per deck. From a fifth
worn it steers lazier and its trucks go soft (the game's own physics
tuning, outside multiplayer sessions only); a worn board breaks from less
and, worn out, can give way under the rider. A board that broke is a new
one once it is whole again, and the game's own board wear is cleared with
it.

A boardslide, lipslide or darkslide that comes down too hard onto a rail
can snap the board, and the rider goes down with it: No Bail can now be
asked for a wipeout, which goes in as a cause before the selector picks.

Sounds play through XAudio2: a crack by the size of the break, metal when
the board broke on metal (the material comes from the game's contact
effects; which are metal is marked in play or listed by a pack), and the
body's hits in a bail by how hard they land.

The settings are a card on the overlay's Skater page, two rows in Mod
Options and console verbs, kept in BoardBreak.settings. A deck may name
itself and set its wheels wider apart in a deck.ini; Old School and Pig
join the decks the feature knows.
2026-10-15 19:22:21 +02:00
AlexandeeerandClaude Fable 5.1 eacfbd72dd Mod merge: an unreadable script no longer drops the rest of its mod's TOC from other mods' copies
Since the mods are read on several threads (0ae0e71), read_mod reads every
script a mod replaces: whether a higher mod's version stands is only known
once the mods are settled. Before, a script a higher mod had replaced was
never read. When such a read fails, the TOC's catch noted it and gave up the
rest of that TOC, so the mod's later changes and additions were left out of
other mods' copies, with a note blaming the mod where nothing used to be read.

The read now has a try of its own. A failure is kept with the script and
settled with the rest: where a higher mod's version stands it goes, note and
all, as if never read; where the script is wanted, the note stands and only
that script is missing, the rest of the TOC having been read on.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VNYF3aYa2q3MkFXc5xYnDd
2026-10-14 06:24:19 +02:00
AyeZeeBB 9f93c3cbb2 Shader tables: mods' are merged as in 2.0.7 again, and the game's song scorer stays within its list
Shader tables
- Reverts a61f82c ("Shader crash fix"). Since 2.0.8 a mod's own shader
  programs were copied into the merged table, and the tables that cosmetic
  bundles carry were merged across mods. Each such bundle then held other
  mods' programs, and the game built them as the bundle loaded, before the
  files with their compiled variants were there. That was 2.0.8's most
  reported crash (Skate.exe+0x3f86da6, some forty machines in ten minutes).
  2.0.9's guard passed such a program over, and the same players then
  crashed a little later in cosmetic loading (+0x3f7bb65, +0x16fe1a6,
  +0x3dc07ed).
- Whatever crash a61f82c fixed comes back with this for the mods that
  needed it.
- The guard stays.

Music
- The game's read of one song for its scorer (0x14f23a0) is replaced by the
  same read with the check it lacks: a place past the end of the playlist
  asset's songs has no song, which the game already answers with 0. 2.0.9's
  check in music_select_next_hook looked at what the queue held before the
  game was asked and did not see these; the game asked for places such as
  0xd570 and crashed reading them (7 reports on 6 machines).
- Said in the log the first eight times.

Not confirmed in game: neither change has been run by a player who was
crashing.
2026-10-13 18:44:15 -05:00
AyeZeeBB 2e40aeb6e2 Game data of another build: the launcher asks for a verify, and mods are looked at again
After Steam updated skate., some installs had the supported Skate.exe over
the new build's data (a copied game, or a download that stopped part-way).
The launcher called that ready, every mod was left out as "made for game
build 29544144, not the installed 29663206; rebuild it with ReSkate Studio",
and the mods stayed out after the game files were put right.
Launcher
- Ready now also needs the game's data to be the supported build, read from
  Data\layout.toc against supported_build::game_data_changelist (29544144).
  Data of another build, or none, reads "Game files need verifying".
- DOWNLOAD in that state checks every file (-validate) instead of fetching
  only what is missing. A download that fails part-way no longer ends on
  ready because Skate.exe arrived.
- Data whose build cannot be read does not block.
Mods
- A mod left out because the game was of another build is no longer
  remembered in .reskate-excluded.json: it is checked on every launch. One
  already remembered for it is looked at again.
- When it is the game that is not the supported build, the mod's message
  says to verify the game files in the launcher, not to rebuild the mod.
2026-10-13 16:31:09 -05:00
Jean-Luc T.andCopilot Autofix powered by AI 573aab4bdb Add cleanup of stale temporary files before download
Remove stale temporary files before downloading.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-10-13 13:41:07 +02:00
copilot-swe-agent[bot]andJean-LucTch 80242c0ec8 Cover deadline boundaries, safe cancellation and fresh join races
Co-authored-by: Jean-LucTch <88255067+Jean-LucTch@users.noreply.github.com>
2026-10-13 11:27:08 +00:00
copilot-swe-agent[bot]andJean-LucTch 8eddcab142 Coordinate custom-map downloads with the multiplayer deadline
Co-authored-by: Jean-LucTch <88255067+Jean-LucTch@users.noreply.github.com>
2026-10-13 11:11:27 +00:00
ReGlitched a61f82c46a Shader crash fix 2026-10-12 11:58:42 -06:00
Fourth Studio 1668488cd0 Board Break: a deck pack brings several decks in one mod folder
The launcher installs one mod folder per package, and the game takes one
mod's deck at a time, so a package could only bring one deck. A mod folder
may now hold a deck in each decks/<name>/, laid out like a mod folder. When
the mods are put together each of them becomes a mod of its own for the run,
listed as <folder>#<name>: it is chosen, set aside and switched like a deck in
a folder of its own. mods.json and the mod list only know the pack, which
counts as loaded when one of its decks is.

A pack's own layout is not one of its decks, whatever the folder is named,
and is set aside like any other deck model. It is what an older ReSkate
loads from the pack: 2.0.6 knows a deck by its folder's name only, so a pack
in a folder named Board_Break_<Name> with a breakable deck as its own layout
breaks boards there with that one deck.
2026-10-12 01:10:33 +02:00
AyeZeeBB e344d585f4 Vote for the next map when a map's time is up
A dedicated server that rotates its maps can now ask players where to
go next instead of taking the pool's next map.

Server
- maps.rotation_vote: when the timer runs out, a vote between three
  maps drawn at random from the pool, "Random map" and "Stay here".
  The most votes wins, a tie is drawn, and with no votes it is the
  pool's next map. It ends early once everyone has voted.
- maps.rotation_vote_seconds (10-120, default 30) and
  maps.rotation_extend_minutes (0-240, default 15; 0 leaves "Stay
  here" out).
- maps.rotation_announce: a card when the map has 10, 5 and 1 minutes
  left.
- The vote's maps are drawn a minute ahead and sent to games
  (PacketKind::next_maps), so their pictures are ready when it opens.
- /vote extend: a built-in vote that gives the map in play
  rotation_extend_minutes more. On by default (votes.extend_map), and
  only runs while the maps are on a timer. "extend" is now a reserved
  vote name.
- Console: rotation vote on|off, rotation announce on|off,
  rotation stay <minutes>|off, rotation extend [minutes],
  votes extend ..., vote extend.

Game
- The vote opens as a popup in the middle of the screen: a tile per
  answer with its picture, name, share of the votes and count. It
  holds input as the map download card does, and works with a
  controller (D-pad, A, B), the keyboard and the mouse.
- Pictures: a mod map's icon from its folder, or from Thunderstore
  when it is not installed; the game's own maps show their loading
  screen picture, cut to its middle square. "Random map", "Stay here"
  and a map without a picture are drawn as shapes.
- Older servers and polls are unchanged: the vote is a poll, so it can
  still be answered with /1, /2... in chat.

Protocol 50: games and servers both need this build.
2026-10-11 17:21:27 -05:00
AyeZeeBB 8351654222 Votes by those who vote, map versions, maps reload, and a crash leaving a map
Votes: a vote is decided by the votes cast, not by everyone on the server. It
passes when yes is its percentage of them, at the end of its time, or sooner
once the players still to vote could not change it. A kick still needs two
yes. The card's bar is yes in green from the left and no in red from the
right, with a mark where yes has to reach. No protocol change.

Map versions: a map installed at another version than the host's is no longer
loaded as it is. The download card offers the host's version (MAP VERSION,
UPDATE), which replaces the installed one and is applied while the game runs.
For that the live merge keeps each mod's fingerprint with where its archives
were placed, and places a mod again when its files have changed since: before,
a mod replaced while the game ran was read where the old one lay. When the
host's version is gone from Thunderstore, or the old one's files are in use,
the player is told and leaves the session.

Dedicated server: "maps reload" reads the Mods folder again, so a map copied
in while the server runs can be switched to at once. The server window reads a
copy of the map list.

Map names: a custom map's level is dingolevel_reskate_<map>, and "reskate" was
left in its name ("/map reskate badlands"). The map's own name is shown and
typed now; the old spelling still finds it.

as a level unloads, the game takes each mesh variation out of its registry by the
entry's mesh and reads it unchecked, and this map's meshes unload before
their databases. A guard on that one function has the read of a mesh that is
gone go on with the next entry, and logs how many were passed over.
2026-10-11 16:12:57 -05:00