mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-17 20:57:08 +02:00
main
8
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
21d9b0d993 |
Profile: cosmetic ownership is a rule, not a list of every item ever seen
With "unlock all cosmetics" (and objects) on, the default, ReSkate wrote every installed item into the profile as owned and never removed one, so every mod a player ever tried stayed in the save: 8765 cosmetics and 520 objects in one profile, past the limit that left a player with no items. What is owned is now worked out from what is installed (installed_item_owned): a paid store copy never, every other item while the kind's unlock option is on, and with it off what the profile saved. The catalog given to the game, the owned list, saved outfits, the player card, the Build object browser and the park editor all ask it. Nothing per item is saved any more, and a profile with an option on drops the rows earlier versions saved, once, on the next start. profile_migration_tests checks that drop on a copy of a real save: the rows stay with the options off, are gone after a restart with them on, and nothing else in the profile changes. |
||
|
|
719cba1166 |
Freezes and crashes: the game's threads no longer wait on ReSkate's slow work
Players reported the game hanging for about a second while skating. A profile showed the memory line in the log walking every heap (HeapSummary) on the client thread, 0.5 to 2 s every two minutes. An audit of everything that runs on the game's update and render threads found more of the same, and Sentry's top crashes had causes of ours. Freezes: - Memory log line: no heap walk or thread snapshot; the GPU part and the write happen on a thread of their own. - Profile database: synchronous=NORMAL in WAL mode. A save is still kept when the game crashes; every play event no longer waits for the disk inside the game's hooks. - ReSkate's own preferences and values (menu clicks, session sliders, Discord) are saved by a background writer in order; reads see a value until it is saved. - Input: the foreground window and the keyboard are sampled on a thread of their own (GetAncestor and GetAsyncKeyState stalled the client tick 40-50 ms when another program held Windows' lock); flight input uses the sample; ClipCursor at most twice a second while a menu has the pointer. - Hooks installed while the game runs go in one transaction per place (HookBatch): throwdowns, remote players, the party, Hall of Meat. - Off the update thread: the host's map package lookup (one table read in the background, not the Mods folder per offer), the trainer's map file and settings save, Board Break's settings save, mod music playlists and their covers, the Spotify station covers. - Off the render thread: the Modding page's and the deck card's Mods folder reads. The overlay's three startup waits share five seconds. - Less work per frame: Steam names reused while one a frame is asked again, 2 friends a tick, steam_api64.dll checked once per process, cosmetic names read in place rather than a system call per character, an outfit load no longer copies the inventory per slot, the throwdown type scan runs at background priority over resident memory, the Board Break deck label is kept a minute. Crashes: - Render-resource pool: the metadata fields are written to the state owner only. The other renderer is 0x2daa00 bytes, and +0x11aae28 is far past its end (store_field crash; heap corruption in every release). - Other players' skateboard effects: a stale skateboard component is no longer followed, and the joint lookup is walked with a bound first (an endless loop in reused memory ended in GameStall). - Launcher: Oodle decodes into the buffer it asks for with corrupt data possible, and its assertions no longer stop the process (heap corruption in the store-copy scan; a breakpoint in oo2core). Timings (Send performance timings): - A frame of half a second or more in a level is sent as game.freeze: where the time went (ReSkate's tick, the game's frame, or outside it), whether the renderer kept presenting, and ReSkate's busiest zones. - Closing the game sends the level session it was in. Music after a connection drop: - Spotify device: an account Spotify could not be reached with is kept and tried again (3 s doubling to a minute); a session that drops is taken up again. Only an account Spotify refuses is asked for anew. - YouTube playlist pictures that could not be fetched are tried again, from 30 s to 10 minutes apart. |
||
|
|
96d44fc8a8 |
Load a saved outfit whose slots differ from the template's
A mod that adds slots to a template made every outfit saved before it fail to load (recipe_template_mismatch / slot_mismatch), and switching the mod off did the same to every outfit saved with it. The preset was blocked, so the player saw the standard skater until the profile database was edited by hand. Match the saved outfit to the template slot by slot instead of by position. A template slot the outfit has no item for starts on the game's default. A saved slot the template does not have is held, like an item from a costume mod that is not installed, and a save writes it back beside the template's slots. Template key, template version, scalar count and recipe count still have to match. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
76330e40bb |
Skater slot, menu and throwdown fixes; MY MODS rework; lobby parties
Skater slot, menu and throwdown fixes; MY MODS rework; lobby parties Saved skaters (Extension/Customization, Extension/Skater) - The selected slot, and slots before it, came up as the standard skater after a start or map change. The game asks for a slot's saved outfit once per level, and that happened before the cosmetics catalog could be read. The first selection now waits for the catalog (60 s at most), and later map changes check against the catalog already read. - The retry from |
||
|
|
a30a8384f3 |
Keep every mod's cosmetics when two presets share a short name
With several cosmetic mods installed the game crashed as soon as an equipped custom item came into view, and so on every launch after it was equipped. Cosmetic presets (Engine/Resource/bundle_ref_table.*) - The character bundle-reference table says which bundle holds each preset, under the preset's full path and under its leaf name, one row per hash. Mods number their presets alike in different folders (cust_tops/1_ap, cust_bottoms/1_ap), so two mods can share a leaf name. Adding the second preset threw "collides with an existing lookup", the merge fell back to the highest-priority mod's copy of the table, and every other cosmetic mod's presets were unregistered. The game then built the skater with a preset it could not find and called through a bad pointer. - A preset whose leaf name is taken is now added under its full path only; the leaf name stays with the preset that had it. Only a clash of full paths still fails. MergedTable::shadowed lists each such preset with the one that holds its name. Merge log (Engine/Vfs/mod_merge_combine.cpp) - Each mod with shadowed presets gets a line naming how many and an example pair, so an item that shows the wrong preset can be traced to the mods that clash. Checked against 39 installed mods, 15 of them cosmetic: the table combines 274 presets where it used to keep one mod's, all reachable by full path and 267 by leaf name, with the game's own 6264 rows unchanged. The seven left without a leaf row are a naming clash between the mods themselves (two Carhartt packs, a Zero tee and deck); whether the game finds those by full path is not known. bundle_ref_table_tests takes an optional second mod and checks that two mods' presets are all added, in either order, and that a shared leaf name is reported with the preset that holds it. |
||
|
|
abdda77946 |
Give each mod archive its own index; unblock launches and saves
Mod archives (Engine/Vfs/mod_merge*) - A free archive index no longer has to sit at or below the highest index the layout already declares. The engine keeps archives in a table keyed by layer, install chunk and a 16-bit index, with no range to stay inside; what it cannot survive is a reference to an archive the layout never declared. Indices are taken lowest first, per package directory. - So a mod that collides takes an index of its own and its file is hard linked rather than concatenated, and no two mods share one archive's 4 GB of addressable bytes. Sharing is left for a mod added while the game runs, which has no declared index to take, and for a directory with no index left. - A placement addresses its payload with a 32-bit offset, so both append paths now refuse to cross 4 GB instead of wrapping round and pointing the game at some other payload: CasStore::write fails with the archive that is full, and the live-apply path checks archive 1's size plus the mod's before appending and asks for a restart, which gives the mod an archive of its own anyway. Injection through a hooked LoadLibraryW (Engine/Core/Platform) - A player could not launch at all: "Child LoadLibraryW entry bytes match neither Windows' kernel32 file nor this process". Anti-virus and overlays hook the entry with a jump to a per-process trampoline, so the bytes differ in the launcher and in the child and neither comparison could match. The guard already allowed the same hook when both processes carried it identically, so it refused on an accident of how the hook was written rather than on intent. - inline_jump_length recognises the forms a hooking engine writes (rel32 jmp or call, push/ret, jmp [rip], mov rax/jmp rax, short jmp). When one is present and every byte after it still matches the clean kernel32 file, the launch goes ahead: the body is Windows' own, and the provider image already matched on timestamp, checksum and size. A wholesale replacement is still refused, and now says so. - The failure names the modules loaded into Skate that came from neither Windows nor the game folder, instead of guessing at "security software". An accepted hook is logged as a warning with the same list. Launching (Launcher/launch.cpp) - Exporting loose scripts is a convenience, and a folder that would not take it was failing the whole launch: fs::create_directories threw and nothing caught it. The export is skipped, RESKATE_LOOSE_FILES goes to 0 so the runtime does not look for files that are not there, and Skate starts. Someone whose install is under Program Files can play; only editing loose scripts is lost. Failures worth reading (Launcher/problem.h) - A hooked LoadLibraryW, a refused write and ERROR_ELEVATION_REQUIRED each explain themselves now. Windows reports the last two in the user's own language -- "Zugriff verweigert", "La operación solicitada requiere elevación" -- so the rules key on the operation names and the error number, which are never translated. Saved skaters (Extension/Customization, Extension/Profile) - Outfits stopped saving and every slot showed the standard skater. The load hook marks a preset blocked on entry and clears it only on a full success, so a load refused for a catalog that was not ready yet left the preset blocked for the session and every later save was refused as previous_load_rejected. The game asks once per level load and does not ask again, so one lost race cost a skater until a restart. Logs show the catalog arriving three seconds after the refused load, at startup and again on a map switch 17 minutes later. - The record is remembered in CosmeticRuntime::pending_loads and applied by retry_pending_cosmetic_loads from the customization pump, which already waits for refresh_cosmetic_catalog. The preset stays blocked until a load really succeeds, so nothing is written over the outfit on disk. - Those records belong to the loadout manager's array, which can be replaced in between, so each pointer is checked against the live array exactly as a save checks one -- manager current, begin/end sane, 0x48 stride, at most 10 records, in range and aligned. A record that no longer belongs is dropped as retry_record_moved rather than written through. |
||
|
|
0b4996e27a |
Fix settings reverting: saves never refreshed the settings caches
Changing a setting in the game's menu did not stick. The camera went
back to high on leaving the menu, grind assist and lean exit stayed at
20 / on, the compass and scoring ticker kept their old state, and the
Experimental tab's "reset to default" returned to whatever was set at
launch.
|
||
|
|
ca1d82f636 | 1.0.0 Release! |