SpongePEAKOptimized
Fixes and optimizations in one mod, each individually toggleable. Includes disconnected-player persistence and rejoin handling.
By SpongeMods
CHANGELOG
Changelog
1.0.0
First public release. Nothing before this was ever published, so everything below is new rather than a change from a version anyone has installed. The entries are kept in the detail they were written in, because most of them explain a real bug in the game or in these mods and that reasoning is worth more than a one-line summary.
-
Three of the four example items were cloning an item that does not exist. They named their source
"Banana". PEAK's fruit is a Berrynana, and each colour is a separate prefab, so the lookup correctly found nothing and those clones were dropped. Only Nuclear Dynamite ever appeared, which is why the spawner said "1 custom".Source names refer to prefab assets rather than code, so a wrong one compiles fine and passes every assembly-level test. Two things now close that gap:
tools/extract-item-names.pyderives the real item list from the game's own asset files, andtools/check-item-sources.pyfails the build if any clone names a source that does not exist, suggesting near matches. A clone can also declare fallback source names now, so a game update renaming a prefab degrades instead of silently deleting the item.The lookup also now ignores spaces and underscores, because PEAK's prefab and display names disagree about them constantly ("Airplane Food" versus "Airline Food").
-
Custom items were being lost to a load-order race. Three of the four example clones never got built, and the item spawner reported "1 custom" instead of 4.
BepInEx loads plugins alphabetically, so SpongePEAKCheats initialises before SpongePEAKQOL. The clone builder ran as soon as
ItemDatabase.Instancewas non-null, which Cheats triggered with an empty queue, marking the build as done. Every later registration then built immediately, at plugin-load time, when the database object exists but its item lookup is still empty. Every source item resolved as missing, and the warning blamed the item name rather than the timing.Building now waits for the lookup to actually contain items, and a failed lookup lists similarly-named items so a genuine typo is obvious instead of looking like this bug.
-
The lobby browser's "YOUR LOBBY" heading rendered as a vertical column of letters. The label helper sizes for a stretched anchor, where the width is an inset from the panel edges, and the heading re-anchored to a point without setting its own width. The inset then became a literal negative width, so the text wrapped at one character per line.
-
Nuclear Dynamite is 200x, and its force on objects now actually works. The blast, damage, knockback and object force are all 200x vanilla, up from 20x. Radius 5 becomes 1000 world units; expect a visible hitch on the frame it detonates, which is affordable because
AOE.Exploderuns its overlap query once at detonation rather than every frame.Two bugs were also hiding behind each other. The game computes an object's impulse as
(dir * knockback + up * verticalKnockback) * factor * itemKnockbackMultiplier, soknockbackis already in the product; scaling the item multiplier by the requested force as well multiplied the two, which at these numbers would have been 40000x. The knockback is divided back out, so the item-force number means the force on objects relative to vanilla.Meanwhile none of it did anything unless
AOE.canLaunchItemsis true, which vanilla leaves false on some explosions, silently discarding every force value. It is enabled when a force above 1x is requested. -
Everything is on by default now, except two things.
VisualQualityandLobbyJoinFixwere the last features shipping disabled. VisualQuality is on because trading a little fidelity for frames is what an optimisation mod is for, and its defaults are mild with every knob exposed. LobbyJoinFix is on because it installs no patches at all any more, so there is nothing left for it to race; enabling it is a no-op.The two deliberate exceptions: Telemetry, which draws a diagnostic overlay over the game, and listing your lobby publicly, which makes you visible to strangers.
-
The lobby browser works on the main menu, and has a button there. A LOBBY BROWSER entry now sits beside the vanilla menu buttons, and F6 works there too. The menu is where you are choosing a game to join, so it is the browser's most useful location; joining takes a Steam lobby ID and never depended on being in a run.
-
The mushroom effect list stays blank outside a run, unavoidably.
MushroomManageris a level generation step, so which mushroom does what is randomised when the level is built. Before a run there is no table to show, and showing the last run's would be confidently wrong. Its hotkey is ignored on the menu so it cannot be toggled into a state that surprises you when the run starts. -
Telemetry moved from F6 to F8. F6 was bound twice, by Telemetry and the lobby browser, so one key did two things. It was only latent because Telemetry shipped disabled; making it enable-able exposed it. F7 was already taken by the mushroom readout.
-
SpongePEAKAll, a modpack. One install that pulls in all seven mods at matching versions, so nobody has to add them one at a time or work out the dependency order. It ships no code of its own, only dependencies; a modpack that also shipped a DLL would install that DLL twice. -
Custom items now actually appear. They were registered at startup and then never built, so the item spawner listed none and reported "no custom items: enable them in Mods settings" even though the feature was enabled. The build step hung off a Harmony patch on
ItemDatabase.LoadItems, which exists, is public, and patches cleanly, but has an empty body and is never called by the game. Nothing reported an error because nothing was wrong at the patching level; the postfix simply never ran.Clones now build from
ItemDatabase.OnLoaded, which the asset singleton really does invoke, with a direct build on startup as well in case the database was already resolved. The spawner's message now distinguishes "registered but not built" from "none registered", so those two very different problems can no longer look identical.A new gate rejects any Harmony patch whose target method has an empty body, which catches this exact class of silently-dead patch. It was confirmed to fail on the original bug before being kept.
-
SpongePEAKOptimized: the rope cannon fires again. This is
RopeShooter, the cannon that shoots an anchor at a wall, not the rope spool you unwind by hand.RopeShooter.Updaterecomputes item usability from a raycast every frame, and the game cancels an in-progress cast the moment usability goes false, resetting cast progress to zero. Since the check requires bothisGroundedand a terrain hit, and both flicker for a frame on slopes, steps, and ordinary mouse movement, the cast kept restarting. Usability is now latched for the duration of a cast; placement still re-validates your aim, so nothing can be placed where vanilla would refuse.Not confirmed in a live run. The mechanism comes from the decompiled game, but the report that prompted it was about the rope spool, which is a different item and is unaffected.
The same fix removes a per-frame physics raycast for every rope cannon in the world, including ones nobody is holding, which vanilla paid for every frame.
-
All mod windows now use PEAK's own UI, and the mouse cursor works. Previously every window was drawn with Unity's IMGUI and set the cursor itself, which never worked reliably:
CursorHandlerre-locks the pointer every frame unless the game believes a menu is open, so the game and the mod each wrote the cursor every frame and the game usually won. The windows appeared and could not be clicked.The item spawner, run rules, name prompt, and lobby browser are now built from PEAK's own button and slider prefabs, inherit the game's fonts, and register as real
MenuWindows so the game grants the cursor through its own path and stops routing clicks to the held item. They also look like the rest of the game rather than like a debug overlay. -
Settings lists that are too long now scroll. PEAK's settings UI has no scroll view at all, because vanilla tabs never overflow, so a mod adding enough entries simply pushed them off the bottom of the screen where they could not be reached. Our tab now builds its own viewport and scroll view.
-
Run rules are reachable in-game. A RUN RULES button in the pause menu opens the host settings; clients see the values greyed out with a note that the host controls them.
-
Renaming yourself no longer overlaps the passport number. The rename control sits beside your name instead of on top of the number.
-
SpongePEAKLobby: a new mod. A lobby browser with lock codes. PEAK only ever creates friends-only or private Steam lobbies, so a browser mod is what makes a lobby publicly listable at all. That is normally all-or-nothing. A lock code is the setting in between: set one on your lobby and it disappears from every lobby browser, including this one, while staying joinable by Steam invite, from your friends list, and by anyone who types the code. So a friend can bring a friend and nobody browsing a public list ever finds you.
It hides for a real reason rather than a cosmetic one: Steam does the filtering on its own servers, so a browser searching for public lobbies never receives a locked one. Codes ignore case and surrounding spaces, and are stored hashed rather than in plain text. If the host leaves, the promoted host re-asserts the lock so the lobby does not quietly become visible.
"Hidden" means hidden from browsers, not invisible to your own Steam friends, and it is obfuscation rather than security. The mod says so plainly instead of implying otherwise.
-
SpongePEAKQOL: rope swinging, pushing, and rope cutting. All three are host-controlled, because opting out of being pushed is not something a client can decide for itself, so the host decides once for the lobby.
All three are on by default, like everything else in the family. Everyone in a lobby installed the same pack on purpose, so the opt-out is choosing not to play with that group, and shoving your friends off a mountain is the point rather than a hazard. Where a real accident is possible it is prevented in code instead: cutting refuses a rope that someone is currently on. The host can still switch any of them off for the lobby.
Swinging raises the rope angle limit the game uses to drop you, and deliberately adds no force of its own: the momentum is the one the game's physics already produce. Pushing sends the game's own force RPC on the target's view, so their client applies it and authority stays where the game put it. Cutting requests Photon ownership before destroying, since a non-owner's destroy is simply refused, and it refuses ropes with someone on them unless you turn that off.
-
SpongePEAKTweaked: campfire safe zone. Near a lit campfire, stamina stops draining, and optionally one resting player is enough to hold the gloom back rather than requiring the whole group, so a scout going ahead does not restart the timer for everyone at camp. Host-controlled and on by default: it only ever helps, and it helps everyone equally.
Note that the game already stops hunger and already pauses the gloom at a campfire, so this deliberately adds only the parts that were genuinely missing rather than reimplementing behaviour that ships with PEAK.
-
SpongePEAKOptimized: adaptive networking. Measures every player's connection quality from telemetry Photon already maintains (latency, jitter, retransmissions, send backlog) without sending any probe packets, and lowers the room's send rate when someone cannot keep up, so a struggling player stops rubber-banding for everyone. The host decides one rate and clients match it, because the game interpolates remote players against the local serialisation rate. Nothing changes when nobody is struggling, players without the mod are never counted as the weakest link, and the rate only moves when every player in the room has the mod, so nobody is left interpolating against a rate they cannot follow.
-
SpongePEAKOptimized: Proton/Wine aware tuning. PEAK is a Windows build, so under Proton it reports itself as Windows and normal platform checks cannot tell. Detection now uses the
ntdll!wine_get_versionmarker (read via the MonoMod that BepInEx already ships, so no native interop is added). Under Proton, background loading priority is raised so more shader pipeline compilation happens during loads rather than as first-encounter stutter. On native Windows nothing changes unless configured. -
SpongePEAKLib: a "Mods" tab in the game's own settings menu. Lists the on/off settings of every installed BepInEx mod, rendered with the game's own settings rows rather than a custom window. Changes write to each mod's own config file. Rows changed this session are marked "restart to apply", because mods install their patches at startup. Core and Lib are marked "required" and cannot be disabled from the panel, since Lib draws it.
-
SpongePEAKTweaked: change your in-game name from the passport. A
[ change name ]control sits under your name on the passport; the passport number updates with it. The name persists across restarts and is visible to players without the mod. On by default but inert: until you choose a name your Steam name is used, untouched. Per-player rather than host-controlled.
Foundations
- Three-tier split: Core (shared foundation), Lib (modding API), Optimized (fixes bundle).
- Eleven independently toggleable features in SpongePEAKOptimized.
- Disconnected players stay in the world, can be carried to safety while alive, and are restored on rejoin when the gloom has not risen past where they left.
- Single join arbiter so late-join, position-restore and catch-up never race.
- Mod handshake over Photon player properties for host/client capability checks.