Commit Graph
268 Commits
Author SHA1 Message Date
AyeZeeBB 2ef8b7b397 Shaders: of two usable custom graphs under an alias-only winner, the higher-priority pack's is kept
The promotion loop went through the edits in the order they were absorbed, lowest priority first,
and kept the first usable graph, so a lower pack's graph won and the higher pack's private rows
were dropped. It now looks from the highest priority down. The archive test covers two custom packs
with their own bytecode and different second programs (it runs with a game root, as the other
archive checks do).
2026-10-25 14:50:36 -05:00
AyeZeeBB d6c8c709d4 Merge pull request #359 from hypnomalice/runtime/custom-material-coexistence
Mods: preserve bundle-owned shader graphs alongside stock material aliases

Conflict with #363 resolved by keeping both: its native variant addition tests and the shader
selection tests in mod_merge_added_assets_tests.cpp, run from one main().
2026-10-25 14:39:12 -05:00
AyeZeeBB 7170938799 Merge pull request #358 from hypnomalice/runtime/declared-board-materials
Plugins: support declared colour inputs on mod-owned board materials

Conflicts with #363 resolved by keeping both: reconcile_variant_additions beside
active_mod_sources in mod_catalog.h, and both test targets in cmake/Apps.cmake.
2026-10-25 14:38:17 -05:00
zeex64 80a9251cc0 Merge pull request #363 from hypnomalice/runtime/variant-additions-cooperation
Mods: permit checked private additions beside opted-in variants
2026-10-25 14:35:48 -05:00
hypnomalice 8f3611e283 Shaders: validate retained graphs and preserve safe aliases 2026-10-25 10:54:20 +00:00
hypnomalice e17aabe37c Materials: refresh declarations only after applied sources or files change 2026-10-25 10:31:57 +00:00
hypnomalice bcee9b0e49 Mods: withdraw stale variant admissions after exclusions and retries 2026-10-25 08:36:19 +00:00
hypnomalice dd74399e8a Shaders: validate retained table bounds before proving stock preservation 2026-10-25 08:23:28 +00:00
AyeZeeBB 788eb98352 Mods: a chunk no list describes gets an owner hash and meta in the merged bundle, instead of an empty record the game reads through null
merge_chunk_metadata gave such a chunk a record with no fields. The game's reader (0x41af080) takes
a record without "h64" as a "g" record and, with no "g" either, reads its guid through null
(Skate.exe+0x15b2c34: computerK-Fingerboard adds its grip texture to a game deck bundle whose list
has no record for it). The record is now an owner hash no resource has, with an empty meta, which
the game passes over.
2026-10-24 22:47:02 -05:00
zeex64 1d80e77b11 Merge pull request #362 from mauwpix/pose-own-values
Fix skater.pose changes being applied twice (jittering avatars)
2026-10-24 21:53:10 -05:00
zeex64 c16facc8eb Merge pull request #361 from Vebjorhk/fix/startup-failure-reason
Launcher: when ReSkate stops while starting, say why instead of blaming anti-virus
2026-10-24 21:52:54 -05:00
hypnomalice 8a2647d7b4 Mods: admit and project native private additions beside an opted-in variant 2026-10-25 01:49:46 +00:00
hypnomalice 42db7a7d38 Mods: read bounded two-sided variant addition declarations 2026-10-25 01:49:46 +00:00
hypnomalice e9233f25f1 Mods: plan opt-in private additions without restoring variant removals 2026-10-25 01:49:46 +00:00
hypnomalice 37bd464576 Mods: keep payload order when a bundle manifest is not first 2026-10-25 01:49:46 +00:00
mauwpixandClaude Opus 5.5 c7457c10a1 Skater: plugin poses apply once a frame instead of twice every third frame
skater.pose changes the skater relative to the game's animation. Some of those changes were applied
twice every third frame, so a posed skater shook in a three-frame rhythm, and their board with them.
The more a plugin changed, the worse it got: an avatar with the hips scaled and offsets on most of
the body needed workarounds in its plugin to hold still. Now every pose is applied exactly once, and
a plugin can give skater.pose the values it means.

Why: ReSkate draws a pose by writing it into the game's bone buffer just before the render, and the
game evaluates the next frame from that same buffer without overwriting all of it. Two of three
frames it resets the buffer itself; in the third the pose drawn was still there and the next pose
went on top of it. Now the game's own values go back as soon as the renderer has its copy, so the
game, the body physics and the next animation update only ever see the game's pose.

This replaces own_scale, the earlier fix for the same cause (the Filmer's forearm at 0.001 shrinking
to nothing). It covered only scale, and put it back after the game had already run on the posed
values, so rotations and offsets still doubled. The new way covers every part of every joint, for
pose, carry and reach, with nothing to track per joint and nothing to clean up after a pose ends.

Checked in the game: the avatar with the hips at 0.667 and offsets on 48 joints holds still with
only skater.pose (shoulder distance 0.117 m every frame, where it was 0.117 0.117 0.067 ...). The
Filmer 1.0.0's camcorder preview looks and measures as on main, and the skater is back to normal
after it.

Details: the renderer copies the bones in submit_render_pose (0x4c7e7a0), which the render pose
caller (0x2c20d99) calls right after render_pose with the same render data; found with a guard page
on the bone buffer that logged every access with its call stack. native_skater hooks it and, for the
render data the pose override just wrote, calls the new set_pose_override_drawn_listener.
skater_animation keeps what on_render wrote over and puts it back in on_drawn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 02:31:13 +01:00
hypnomalice 00aef90a34 Mods: retain bundle-owned custom programs alongside verified stock aliases 2026-10-25 01:34:24 +01:00
hypnomalice 744ced7209 Tests: audit bundle shader graph ownership and surface excluded material rows 2026-10-25 00:52:57 +01:00
hypnomalice ea13e8c22c Mods: preserve the selected bundle shader graph instead of importing foreign heaps 2026-10-25 00:09:14 +01:00
hypnomalice c29cffdf9b Plugins: enforce declared input ownership and preserve holds through rebuilds 2026-10-25 00:01:46 +01:00
AyeZeeBB 7dabd99a40 Crashes: the Trainer no longer writes into freed memory, throwdown models go before a level unload, and a gone texture draws nothing instead of crashing
From the first 6k Sentry reports of 55a7342 (2026-10-24), whose top sites were all new since 2.1.1:

- Trainer: scale_underflip_bands wrote the underflip rate bands' MinScale and MaxScale every tick on
  every copy it had ever found, checking only that the address was readable. A level's copies go back
  to the game's heap with it, so 1.0 and 0.6 landed in the upper half of whatever the game made there
  next (Skate.exe+0x157f930, +0x12a1549, +0x10084de, +0x11ef49e, +0x3db81ea, +0x12c21ca: about a
  third of the crashes, every dump with a pointer whose high dword is one of those floats). A copy is
  now written only while it still is that band and holds the game's band or the last one written;
  any other is forgotten.
- Throwdowns: models the page released were destroyed 3 s later by the menu tick, which does not run
  while a level loads, so the game's own flush of the unloaded level's types destroyed them after
  their assets were freed (Skate.exe+0x3dc5eaa, 18%). Before a level unload they are destroyed at
  once, as the native menu's own are.
- Textures: the guard's "default for the id" is the entry itself, so for a dead entry resolve gave a
  null texture, and the texture view cache asked it for its key (Skate.exe+0x3e6ddc1, 17%, every
  report with TheVlixOne-Nike_Pack). A stub at the cache insert hands back the empty view the cache
  already built when the texture is null; the guard is on only when that patch applies.
- Physics: the wake guard widens every pass because ReSkate raises the owner pool to 160000; its log
  line now says so once instead of claiming a prevented crash thousands of times a session.

Built; not yet checked in the game.
2026-10-24 17:19:32 -05:00
hypnomalice 4c2b500a99 Plugins: hold declared colour inputs on mod-owned board materials 2026-10-24 22:51:59 +01:00
VebjorhkandClaude Opus 5.5 97f2406bea Launcher: when ReSkate stops while starting, the STATUS tile says why instead of blaming anti-virus
DingoSDKDebugInitialize answers the launcher with a bare TRUE or FALSE. On
FALSE the launcher threw "DingoSDKDebugInitialize returned FALSE", which the
STATUS tile turned into "ReSkate could not attach to Skate" with anti-virus
advice, although the attach had worked and the runtime had logged its reason.

ReSkate.dll now exports DingoSDKStartupFailure, a 1 KB buffer that every
FALSE path fills with its reason (the first one stays). The launcher reads it
out of Skate before closing it. With an older ReSkate.dll it reads the ERROR
lines that Skate process wrote to ReSkate.log during the call instead, and
with neither it says it was not told why. problem.h explains these messages
before the attach rules: a save in use or a folder another game holds says
Skate is already running, hook and overlay failures keep the attach advice,
and anything else leads with the runtime's own reason. Bootstrap and the
local profile hand their reason back, and the profile checks that used to
return false without a word now log one.

Fixes #90, fixes #346.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 23:51:12 +02:00
hypnomalice 0a145850ba Mods: merge independent shader graphs and preserve additive variant bundles 2026-10-24 22:50:36 +01:00
AyeZeeBB 55a7342dc6 Multiplayer: dedicated servers require plugins, and players get them and the map on one card
A server lists Thunderstore packages in plugins.required ("Owner-Name", or "Owner-Name-1.2.3"
for at least that version, at most 16). It checks each on Thunderstore as it starts and leaves
out one not listed as a plugin, and sends the rest with its map offer (protocol 55).

A joining player's game checks them before the server's map loads. Those missing, switched off
or too old go on one card with the map when that is missing too, so the player is asked once.
GET ALL downloads and installs each, switches on any that were off, runs one live merge when
any brings game data, and joins; CANCEL leaves. The game fetches a package only when
Thunderstore lists it as a plugin and it installs as one (a reskate-plugin.json naming Luau
code), whatever a server asks; anything else is taken out again, so a cosmetic can never be
required.

map_download handles a list of packages instead of one map, and the Thunderstore chooser takes
the category it needs. A map alone keeps its card as it was.
2026-10-24 12:00:09 -05:00
AyeZeeBB e2d12a701d Launcher: plugin mods show as Plugin instead of Nothing, and UPDATE sits after the version it brings
The mod list now notices a reskate-plugin.json that names an entry, reskate-objects.json and
reskate-music.json, and mods::mod_contents lists what a mod holds, most telling first. The
launcher's Type column shows the first of them (with "+" when there are more, all of them on
hover), and the in-game Mods page joins them. A reskate-plugin.json with only variants or
resident assets is not a plugin.

The UPDATE button moved from its own spot before the Type column to right after the blue
old -> new version, cutting a long name short rather than pushing into Type.
2026-10-24 11:24:20 -05:00
AyeZeeBB 1b613b0dce Merge pull request #347 from snubroot/feat/mod-object-families
Objects: mods name their Quick Drop objects and group them into families with reskate-objects.json
2026-10-23 16:00:06 -05:00
Robin MoellerandClaude Opus 5.5 4500184b48 Build: the plugin tests build and run on Linux
dingosdk_plugin_tests covers the plugin sandbox and every reskate.* API,
but it only built on Windows, so contributors without Windows could not
run it. Now it builds wherever DINGOSDK_BUILD_PLUGIN_TESTS is on. On
Linux the test target adds plugin_discovery.cpp and mod_list.cpp itself,
because the Linux plugins library leaves out finding plugins among the
mods. The other tests in that group stay Windows only.

mod_list.cpp replaced mods.json and the exclusion list with MoveFileExW.
That code is unchanged under _WIN32. Elsewhere it uses
std::filesystem::rename, which replaces the file in one step on POSIX,
and the error message comes from the error_code.

Ran on Linux (Debian trixie, linux-x64 preset with the plugin and
multiplayer tests on): dingosdk_plugin_tests, dingosdk_server and
dingosdk_server_plugin_tests build, and ctest passes plugins ("plugin
tests passed (15 skipped)", the gitignored contrib/plugins) and
server_plugins. The Windows build was not run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Hs7xxJDf6SDcQUaXnzmtL5
2026-10-23 14:19:25 +02:00
snubroot e8031fe8e3 Objects: mods name their Quick Drop objects and group them into families with reskate-objects.json
A mod's objects each got a tile of their own, titled with the raw key, so sizes or colours of one
object could not share a tile and X / Square had nothing to pick from. A reskate-objects.json in the
mod folder now gives them titles, families and categories, read at startup into a mod_objects map
kept apart from the game's own items. It only adds: taken ids and the game's items are left out.
2026-10-23 02:37:51 -04:00
AyeZeeBB e35e33d66d Plugins: board.parameters reads the board's shader values, and set_parameter holds its colours and numbers
Each part of the local board (deck, grip, trucks, wheels) has a material instance with a few
shader values of its own, found in the running game. reskate.board.parameters lists them by key
and type. set_parameter holds a colour or a number there each tick, published until it shows, and
the board's own value comes back when the plugin lets go or stops. Integers and switches pick how
the board is drawn, the store's foil looks among them, so plugins only read those. Only your own
screen changes.
2026-10-22 20:17:09 -05:00
AyeZeeBB 118c489fdb Plugins: what the Filmer needs as a plugin: carry, who sees a pose, a step in the camera cycle
PR 343's Filmer becomes a Luau plugin mod (kept in contrib/plugins/filmer) on general APIs instead of
its own C++:

- reskate.skater.carry: something held out in one or both hands and aimed, the body crouched (feet
  kept) and hunched over it, turned on the spot after it (Extension/Skater/carry.cpp, from the PR's
  filmer_hold.cpp, with tests)
- shown = "everyone" | "others" | "me" on skater.pose, reach and carry: the pose sent to the other
  players and the one drawn here are split when asked
- reskate.camera.cycle and the camera_cycle event: a plugin's camera as the last step of the camera
  height button's cycle, after first person
- reskate.session.nametags(false) holds the names over the other players off
- board.hide(bone, {others = true}) hides it in the board the others are sent too (a sent-pose filter)
- outfit.set takes hand wear slots; input.bind takes an action with no key of its own
2026-10-22 18:46:49 -05:00
AyeZeeBB 45346b122c Plugins: prop hunt APIs, and plugin commands in the console lookup
- reskate.entities.blueprints lists the game's object blueprints (meshes only if asked),
  and reskate.entities.bounds gives a blueprint's box, so a mod can pick a prop by list or at random
- Attached objects take upright, turn and ground (a floor found within reach below), the "root"
  joint, and a 6th options argument with solid; spawned props' bodies are found and ghosted
- reskate.skater.hide, reskate.world.pick, and skater.get gives right and switch
- reskate.console.command takes an optional 4th table of subcommands; the console lookup
  suggests plugin commands word by word, and plugin commands lists the subcommands
- objbody: a test command for finding which body setter takes a prop out of collision
2026-10-22 00:30:06 -05:00
AyeZeeBB 721ed9e64d Plugins: a general launch API in place of grind_exit; grind exits is all Lua, and 701 is a grind
The SDK knew grind exits: reskate.skater.grind_exit took a toe/heel/left/right wish, and C++ worked
out the rail's direction, toe and heel from the stance and facing, the 1.8 m/s and the strength.
That logic is now the grind-exits mod's own Lua (plugin/exits.lua, kept on this machine). What has
to run on the physics thread is general:
- Extension/Skater/launches: every launch of the local skater (ollie, grind, no_comply, boneless),
  classified by its call site and the state before it, with the board's direction of travel; the
  `launch` event for plugins with events.skater; reskate.skater.shape_launch(from, {across, along,
  up}) sets those speeds against the travel, one plugin a kind.
- reskate.skater.get() gains `right` (the root's right axis) and `switch` (the game's stance flag).
- Extension/Skater/pad_hide: reskate.input.hide's pad filter, out of the old grind exit file.
Removed: reskate.skater.grind_exit, the grind_exit event, GrindExitWish and GrindPop.

Physics state 701 is a grind too (the game checks it with 400 in about a dozen places; the
2026-10-11 measurement only reached the 400s): pops out of it were dropped, and skater_state called
it "other". Launches, skater_state ("grinding") and the trainer's grind pop all count it now.
Tests: the grind-exits plugin test drives the new path (11 checks of its own).
2026-10-21 21:41:04 -05:00
AyeZeeBB 48d1e245db Outfit layers: an item worn on top keeps its textures, and the log says what the layers do
The game's skater loader builds each recipe slot with that slot's own function, which puts the
item's appearance preset on a material named for the slot's kind ("Outfit_Top_mat"). An item worn
on top sits in another kind's slot, so its mesh found nothing under its own material ("Bottom_mat")
and drew white. The preset lookup guard's addEsShaderPreset hook now also puts the preset of an item
on top on its own kind's material (layer_materials.h: which presets those are, from each item's
catalog folder and AssetPaths; the five native functions checked by their first bytes).
The outfit service logs what goes on top and where, the slot trials, why an item is not worn and
what it waits for.
2026-10-21 19:49:35 -05:00
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
zeex64 c745d605ae Merge pull request #310 from moelrobi/fix/poll-answer-repeat
Polls: answers no longer refused as repeats, and less chat noise
2026-10-21 18:45:38 -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
AyeZeeBB b67fe93e55 Crashes: guards for 2.1.1's top crash sites, launcher checks, stuck-load reports, quieter logs
From 2.1.1's Sentry reports (60,000 in three days, 2026-10-21):
- Textures: a stale render texture handle takes the game's default texture instead of reading
  through null (Skate.exe+0x3e897fb, a third of all reports, every one with TheVlixOne-Nike_Pack 2.3.x).
- Physics: the wake pass's bitset is made as long as the world's owner list once indices pass
  20000, after long multiplayer sessions (+0x3d99e2f, +0x3d9ee43, +0x3d9ee47).
- Music: more than 1024 candidates are picked by ReSkate; the game's shuffle wrote past its stack table.
- Streaming: a staged read's piece that reaches past its 64 KB buffer is left unfilled (VCRUNTIME memcpy).
- Multiplayer: a remote skater or board whose parent bus link is damaged is left alive instead of
  destroyed (+0x2b94cd0).
- Mesh pool: on an integrated GPU its budget is capped by the RAM and page file free; the Memory
  line says what the PC has left.
Launcher:
- A folder with non-ASCII letters is a hard stop (the boot crash +0x18df4cf came after "Start anyway").
- The game's data files are checked against the supported build's sizes (from Steam's manifest);
  missing, cut-short or online-only files send the player to verifying.
- One game per folder: the launcher will not merge or start while one runs there, and ReSkate.dll
  holds the folder's mutex.
- Advice on the ready screen for PCs short of RAM and page file; reports carry pc.ram_gb and
  pc.commit_free_gb.
Stuck loads:
- A load in one stage for two minutes sends a stuck-load report (every thread's stack and the log,
  error.type stall, load.stage, load.seconds) while the game goes on (crash protocol 6).
- A load the player closes sends its timing with the stage it was in.
Logs: the PanelTrace diagnostics and the neighborhood unlock override's observation lines are gone.
2026-10-21 18:10:58 -05:00
AyeZeeBB 41b5973896 Plugins: the character room and typing into a drawn field, and Animator Studio on both
- reskate.room.open, leave and state, with the room permission: ReSkate walks the game's menu to the Skaters page (its navigation events and RB on an internal scripted pad, as PR 297 and PR 230 did), draws the local skater on the room's floor and hides the room's own skater and board; other players are not sent the room. Extension/World/character_room, the room placement and hiding in skater_animation, and post_native_ui_event made general.
- reskate.input.text: what is typed while the plugin's screen is open; while it types, Esc is the plugin's.
- Animator Studio opens in its room (the Studio room setting, as the PR's), under its loading screen, or where the skater is when the walk fails; its card's name, trick and numbers are typed into in place.
2026-10-20 17:43:40 -05:00
AyeZeeBB 805cd0d6f5 Plugins: Animator Studio's screen 1:1, on general drawing, screen and pose APIs
- The studio plugin draws PR 297's screen itself: skate.'s Trick List menu and card, the joint timeline with key rows, dragging joints on the skater, keyboard and pad controls with their prompts, the unsaved-changes card, the recording strip and the loading screen. It lists a trick library made with tools/make_trick_library.py (the PR's, here beside it), and checks itself with studio test.
- Drawing: d:rough_rect, d:halftone, d:scribble, d:clip, d:measure, a text wrap width, the title_large font, text up to 400, and the loading screen's kickflipping board as d:game_image("loading_board") with a frame.
- reskate.ui.screen with panel = false: input taken, nothing drawn, the plugin draws it.
- reskate.skater.joint gives each joint's parent; reskate.skater.pose takes an offset.
2026-10-20 17:22:19 -05:00
AyeZeeBB cf43231b3e Plugins: reskate.tricks.label and record_as, and Rock to Fakie as a mod on them
Two general trick APIs on the hooks TheRealEJR found for his Rock to Fakie mod (pull request 285):
- tricks.label(from, to) ("hud"): the trick ticker shows `to` where the game's label is exactly
  `from`, on the ticker's own call route and in its own buffer only, when it has room; 16 labels a
  plugin, given back when it stops.
- tricks.record_as(from, to, within_ms) ("skater.control"): the next trick the recorder gets whose
  id is one of `from`, within the window, is recorded as `to`, through a changed copy of the packet.
  One ask a plugin, used once; refused while a throwdown runs, as trick replacements are.
The hooks pass everything on unchanged while no plugin asks.

contrib/plugins/rock-to-fakie is his feature in Lua: while the physics state holds a stall (400 or
401) the ticker shows Rock to Fakie for a Board Stall or a Lip Stall, and B pressed in it asks that
the stall be recorded as the game's fakie_rock (187). Off until `rocktofakie on`. Checked in the
plugin tests, with the new functions' permissions.
2026-10-20 14:26:04 -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
zeex64 f365914dfe Merge pull request #322 from DreadHeadHippy/default-export-bitrate
Replay export: use the export dialog's 8/12/18 Mbps choices instead of forcing 100 Mbps
2026-10-20 14:15:04 -05:00
zeex64 80747e9b89 Merge pull request #300 from andrewnakas/physics-210
0.8.1 Sandbox physics trainer
2026-10-20 14:14:29 -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
waguandClaude Opus 5.5 cd36529865 Merge plugins into server-lua-api
The new services and throwdown kit API files use add_functions and the shared
helpers; add_functions opens a read-only parent for reskate.throwdowns.flag.
throwdowns.release_flag stays removed, as plugins has it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 12:13:19 -04:00