SpongePEAKOptimized
Fixes and optimizations in one mod, each individually toggleable. Includes disconnected-player persistence and rejoin handling.
By SpongeMods
| Last updated | 7 hours ago |
| Total downloads | 61 |
| Total rating | 0 |
| Categories | |
| Dependency string | SpongeMods-SpongePEAKOptimized-1.0.0 |
| Dependants | 1 other package depends on this package |
This mod requires the following mods to function
BepInEx-BepInExPack_PEAK
BepInEx pack for PEAK. Preconfigured and ready to use.
Preferred version: 5.4.75301SpongeMods-SpongePEAKCore
Shared foundation for Sponge PEAK mods: logging, config, reflection caching and patch hosting. Not a standalone mod.
Preferred version: 1.0.0SpongeMods-SpongePEAKLib
Modding API for PEAK, and a Mods tab in the game's own settings menu for toggling any installed mod's features.
Preferred version: 1.0.0README
SpongePEAKOptimized
Fixes and performance work for PEAK, bundled into one mod with a toggle for every feature.
Instead of installing eight single-purpose mods that each patch the game separately, this is one plugin where overlapping behaviour is resolved once and deliberately.
Features
Every feature has its own setting in BepInEx/config/com.sponge.peakoptimized.cfg, so if
one misbehaves you can switch off just that one.
| Feature | Default | What it does |
|---|---|---|
AdaptiveNetwork |
on | Measures each player's connection and lowers the room's send rate when someone is struggling, so weak connections stop rubber-banding. Host decides, clients match. |
AudioFix |
on | Stops audio dropouts by parking silent looping sounds and prioritising voice and nearby audio. |
CarryDisconnectedPlayers |
on | Lets you pick up and carry teammates who disconnected while alive, and marks them (Disconnected). Ghosts cannot be carried. |
DecorationCulling |
on | Hides small decorative meshes beyond a distance, spreading the work across frames. |
DistanceCulling |
on | Skips dynamic-bone secondary motion beyond a distance from the camera, and caps its update rate. |
GrassAllocations |
on | Reuses one MaterialPropertyBlock for grass instead of allocating a new one every frame. |
GrassFrustumCulling |
on | Skips grass chunks outside the camera frustum. Grass casts no shadows, so this cannot change what you see. |
KeepDisconnectedPlayersInWorld |
on | Keeps a disconnected player's character alive and simulated until they rejoin, die, or the timeout expires. Room settings are applied when you host; every client tracks who is away. |
LateJoinFix |
on | Warps players who join mid-run to the party member furthest from the summit, then revives them. |
LightSampleCache |
on | Caches baked light volume samples, which cost a CPU 3D-texture readback per call. |
LobbyJoinFix |
on | Retired. PEAK now defers lobby invites until the session is connected, so this is no longer needed. |
NullGuards |
on | Stops two vanilla per-frame exceptions: pocket updates before a player exists, and particle culling with no observed character. |
PerformanceLOD |
on | Throttles physics updates for distant characters and avoids redundant rigidbody writes. |
PhysicsThrottle |
on | Caches wind shelter raycasts and removes the per-search scene scan from bot vision. |
PlatformTuning |
on | Applies the few engine settings that genuinely differ under Proton/Wine versus native Windows. Does nothing on Windows unless explicitly configured. |
ProximityGating |
on | Skips per-step updates for traps and ambient particle spawners with no player nearby. |
ReconnectCatchup |
on | Warps returning players to the party member furthest from the summit instead of the level start. |
RejoinVoiceFix |
on | Resets Photon Voice when leaving a game so voice chat works in the next lobby. |
RestoreRejoinPosition |
on | Returns a rejoining player to where they disconnected, if the gloom has not risen past it. |
RopeShooterFix |
on | Fixes the vanilla rope cannon refusing to fire: a single frame of lost footing or aim wobble cancelled the whole cast. Also stops spare cannons raycasting every frame. |
SoftDependencyFix |
on | Keeps partially-loaded assemblies usable, so a mod with a missing optional dependency does not hide unrelated console commands. |
Telemetry |
off | Shows frame time and what each optimization is doing, so the effect can be measured. |
VineClimbFix |
on | Stops rubber-banding when climbing vines and chains. |
VisualQuality |
on | Trades visual fidelity for frames: LOD bias, shadow bias and directional shadow tuning. |
ZeroAllocHotPaths |
on | Removes per-frame allocations from falling-rock physics and player proximity checks, reducing GC micro-stutter. |
Disconnected players
The headline feature. Normally a player who drops has their character deleted instantly, so you cannot help them.
With this installed by the host, a disconnected player's character stays in the world: afflictions keep ticking, hazards still affect them, and teammates can pick them up and carry them to safety even though they are not incapacitated. When they rejoin they take their character back. If they die while away they become a normal ghost, and ghosts cannot be carried.
Two things worth knowing:
- The host decides. Room settings come from whoever creates the lobby, so if the host has this mod, every player sees the behaviour, mod or not. If the host does not, it is inactive regardless of what clients have installed.
- An absent player holds a slot until the timeout expires (default 5 minutes, configurable). That is the cost of keeping their character alive.
Compatibility
This mod covers the same ground as several existing mods. Running both means two mods acting on the same thing, so disable these if you have them:
| Mod | Overlap found |
|---|---|
Cryo-PEAK_VineFix |
patches the same method, CharacterVineClimbing.RPCA_SyncVineClimb |
KinTheInfinite-BetterFPS |
patches the same FixedUpdate methods on character physics |
IceMods-PeakLobbyJoinFix |
targets OnLobbyJoinRequested; see the note below |
Sapphire009-LateJoinFix |
sends the same WarpPlayerRPC and RPCA_ReviveAtPosition on join |
Ayzax-Reconnect_Catchup |
sends WarpPlayerRPC on join, and warps every joiner |
PatchNote-PeakAudioFix |
same audio-source prioritisation and pausing behaviour |
PatchNote-RejoinVoiceFix |
both reset the Photon Voice client when leaving a game |
PEAKModding-SoftDependencyFix |
same ReflectionUtility type-loading fix |
reis637-PeakOptimizer |
patches the same ShakyRock, DynamicBone and PlayerHandler hot paths |
LIGHTNING_X-CubeX |
partial: its bundled "Better FPS" patches the same CharacterRagdoll and CenterOfMass methods as PerformanceLOD. The rest of CubeX (its menu and tools) does not conflict. Disable CubeX's Better FPS options, or turn off PerformanceLOD here. |
How this was determined: by comparing the game methods and Photon RPCs each mod touches against the ones this mod patches, using the installed binaries. The first three are direct patch collisions on identical methods. The rest are behavioural: different mechanism, same effect on the same game state.
The worst pairing is LateJoinFix + Reconnect_Catchup, which conflict with each other even without this mod: both warp a joining player, so two warps race for the same character. Resolving that is a large part of why this bundle exists. Here a single arbiter classifies each join once and dispatches to exactly one handler.
Not tested running side by side with these mods in a live session; the overlap above is from binary and behavioural comparison, which is why the guidance is to disable rather than to expect a specific failure.
A note on LobbyJoinFix
Investigated and deliberately not implemented. PEAK's own GameBooter now defers a pending
invite until ConnectedAndReady:
if (!NetCode.Session.IsConnectedAndReady)
NetCode.ConnectionEvents.ConnectedAndReady += JoinLobbyAfterRelayReady;
else if (NetCode.Matchmaking.HasPendingInvite)
NetCode.Matchmaking.ConsumePendingJoin(andJoin: true);
That is the same defer-and-replay the mod added, so reimplementing it would race the game's
own logic. IceMods-PeakLobbyJoinFix also targets SteamLobbyHandler.OnLobbyJoinRequested,
which has since moved to Peak.Network.SteamLobbyAPI.
Prior art
Independent implementation, written against PEAK's own assemblies. The problems it solves were identified by earlier mods listed above, and this bundle exists because those solutions overlapped and sometimes fought each other.
Differences worth noting:
- One arbiter decides how a joining player is handled, so late-join, position-restore and catch-up cannot race.
- Per-feature toggles with failure isolation: a feature whose patches fail to bind is reported by name rather than silently counted as working.
SoftDependencyFixis an IL transpiler over a singleAssembly.GetTypes()call, recovering the types that did load instead of discarding the whole assembly.- Disconnected-player persistence, carrying disconnected teammates, rejoin position restore and the mod handshake have no upstream equivalent.
Adaptive networking
If one player is on a weak connection, everyone feels it as rubber-banding and characters running in place. This measures each player's connection and adapts the room to suit the weakest one.
- No extra traffic. It reads latency, jitter, packet loss and send-backlog counters that Photon already maintains. It does not send ping packets, which would burden exactly the connections that can least afford them.
- Jitter matters more than ping. A steady 250ms connection plays fine; a 90ms one that spikes to 400ms is what actually causes rubber-banding, and that is what this reacts to.
- The host decides one rate and everyone matches it, because the game interpolates other players against the local send rate. A client changing its own rate would cause the very stutter this removes.
- Nothing happens if nobody is struggling, and players without the mod are never counted as bad, so they cannot drag the room down.
- Everyone in the lobby needs the mod for the rate to change. The game interpolates other players against the local send rate, so a vanilla player left at 30Hz while the room sends slower would stutter. If anyone lacks it, the room stays at vanilla 30Hz.
Works for satellite, Starlink, tethered mobile, congested Wi-Fi and long-haul connections.
Turn on Telemetry (F6) to see your own latency and jitter, the room's current send rate, and each player's connection quality, so you can tell whose link is actually struggling.
Proton and Linux
PEAK is a Windows build, so under Proton it reports itself as Windows and ordinary platform
checks cannot tell the difference. This mod detects the real situation (via the wine_get_version
marker that Wine exports and Windows does not) and applies the few settings that genuinely
differ:
- Background loading priority is raised under Proton only, so more DXVK shader-pipeline compilation happens during loading screens instead of stuttering during play.
- Everything else is unchanged, because the rest of the optimizations remove work from hot paths, which helps identically on every platform.
On native Windows this does nothing unless you configure it. The detected platform is written to the log, which is worth including in any performance report.
Requirements
BepInEx, SpongePEAKCore and SpongePEAKLib. r2modman installs these automatically.
Performance features absorbed from PeakOptimizer
| Feature | Default | What it does |
|---|---|---|
| Light sample cache | on | The baked light volume is sampled with a CPU texture readback, every frame, per speaking player and per character in a wind zone. Cached. |
| Physics throttle | on | Wind shelter raycasts are cached (terrain does not move), and bot vision no longer scans the whole scene each search. |
| Decoration culling | on | Small scenery stops drawing at distance. Only small meshes, and only the draw is disabled, so nothing you can stand on ever disappears. |
| Grass allocations | on | Grass allocated a property block every frame; now reuses one. |
| Grass frustum culling | on | Grass behind the camera was still drawn. It casts no shadows, so skipping it cannot change the image. |
| Proximity gating | on | Citadel traps stop raycasting every physics step when nobody is near them. |
| Null guards | on | Fixes two vanilla exceptions thrown every frame: pocket updates before a player exists, and particle culling in menus. |
| Visual quality | off | LOD and shadow tuning. Trades looks for frames, so opt-in. PEAK_Visuals is better at this. |
| Telemetry | off | Frame time and cull counters, so the above can be measured rather than assumed. |
Conflicts with reis637-PeakOptimizer. Both patch the same methods. Run one or the other.
Its experimental GPU occlusion culler is not reimplemented here: it is disabled by default even
in that mod, and marked use-at-your-own-risk. Run PeakOptimizer if you specifically want it.
License
Free to use, stream, and include in modpacks. No attribution needed for any of that.
Attribution is only required if you decompile it and reuse the code. Please do not reupload it elsewhere or sell it.
Full terms in LICENSE.
Keybinds
| Key | Opens | Setting |
|---|---|---|
| F8 | Telemetry overlay (feature is off by default) | TelemetryToggleKey |
All rebindable, in the config file or in Settings > Mods.
Configuration
Every setting is in BepInEx/config/com.sponge.peakoptimized.cfg, or in the game's own
Settings > Mods tab.
AudioFix
| Setting | Type | Default | What it does |
|---|---|---|---|
ScanInterval |
number | 0.5 |
Seconds between audio source scans. Lower reacts faster but costs more CPU; FindObjectsByType is not cheap. |
Diagnostics
| Setting | Type | Default | What it does |
|---|---|---|---|
TelemetryInterval |
number | 0.5 |
Seconds between readout refreshes. |
TelemetryToggleKey |
key | F8 |
Key that shows or hides the readout while the feature is enabled. |
Telemetry |
on/off | false |
Shows frame time and what each optimization is doing, so the effect can be measured. |
Fixes
| Setting | Type | Default | What it does |
|---|---|---|---|
VineClimbFix |
on/off | true |
Stops rubber-banding when climbing vines and chains. |
AudioFix |
on/off | true |
Stops audio dropouts by parking silent looping sounds and prioritising voice and nearby audio. |
RejoinVoiceFix |
on/off | true |
Resets Photon Voice when leaving a game so voice chat works in the next lobby. |
LobbyJoinFix |
on/off | true |
Retired. PEAK now defers lobby invites until the session is connected, so this is no longer needed. |
SoftDependencyFix |
on/off | true |
Keeps partially-loaded assemblies usable, so a mod with a missing optional dependency does not hide unrelated console commands. |
RopeShooterFix |
on/off | true |
Fixes the vanilla rope cannon refusing to fire: a single frame of lost footing or aim wobble cancelled the whole cast. Also stops spare cannons raycasting every frame. (replaces (vanilla bug)) |
NullGuards |
on/off | true |
Stops two vanilla per-frame exceptions: pocket updates before a player exists, and particle culling with no observed character. |
Network
| Setting | Type | Default | What it does |
|---|---|---|---|
AdaptSendRate |
on/off | true |
Lower the room's network send rate when a player's connection cannot keep up. Host decides; clients follow the host so everyone's interpolation matches. Off means always use the vanilla 30Hz. |
SampleIntervalSeconds |
number | 5 |
How often to read connection quality. This costs no packets: it reads counters Photon already maintains, so a short interval is cheap and reacts sooner. |
MinimumSerializationRate |
number | 15 |
Lowest serialisation rate the host may drop to, in Hz. Vanilla is 30. Below about 15 the game's own interpolation starts to look obviously soft. |
LogConnectionQuality |
on/off | true |
Log connection tier changes and rate adjustments. Useful for diagnosing whose connection is actually causing trouble. |
AdaptiveNetwork |
on/off | true |
Measures each player's connection and lowers the room's send rate when someone is struggling, so weak connections stop rubber-banding. Host decides, clients match. (replaces ) |
Performance
| Setting | Type | Default | What it does |
|---|---|---|---|
NearUpdateRate |
number | 60 |
Physics updates per second for nearby remote characters. 0 disables their updates entirely. |
MediumUpdateRate |
number | 30 |
Updates per second for characters past MediumDistance. |
FarUpdateRate |
number | 10 |
Updates per second for characters past FarDistance. |
MediumDistance |
number | 30 |
Distance (metres) at which a character drops to MediumUpdateRate. |
FarDistance |
number | 60 |
Distance (metres) at which a character drops to FarUpdateRate. |
ZeroAlloc_ShakyRock |
on/off | true |
Replaces allocating physics queries and leftover debug logging in falling-rock updates. |
ZeroAlloc_ProximityChecks |
on/off | true |
Uses squared-distance comparison instead of Vector3.Distance for player proximity checks. |
CullDistantDynamicBones |
on/off | true |
Skips dynamic-bone updates beyond DynamicBoneDistance from the camera. Purely visual. |
DynamicBoneDistance |
number | 40 |
Metres from the camera beyond which dynamic bones stop updating. Lower is faster; too low shows stiff foliage nearby. |
CapDynamicBoneUpdateRate |
on/off | true |
Caps dynamic-bone update rate at 30 Hz instead of the default 60. |
LightSampleGridSize |
number | 1 |
World-space cell size for cached light samples, in metres. Smaller is more accurate and hits the cache less often. |
LightSampleCacheEntries |
number | 4096 |
Maximum cached samples. The cache clears wholesale when full, which is cheaper than tracking per-entry age for a value this cheap to recompute. |
WindShelterInterval |
number | 0.1 |
Seconds between wind shelter raycasts per character. Terrain does not move, so this only needs to keep up with the player. |
OptimizeBotVision |
on/off | true |
Replaces the scene scan in bot vision with the list the game already maintains. |
DecorationCullDistance |
number | 90 |
Distance beyond which small decorations stop being drawn. |
DecorationMaxExtent |
number | 1.5 |
Largest bounds extent, in metres, that counts as a decoration. Anything bigger is left alone, so climbable geometry is never hidden. |
DecorationChecksPerFrame |
number | 64 |
How many decorations to test each frame. Lower spreads the cost further. |
TrapActiveDistance |
number | 80 |
Distance within which traps keep updating. Well beyond their own reach, so this cannot stop a trap that could actually hit someone. |
ReportPlatform |
on/off | true |
Log which platform was detected and the evidence for it. Useful when reporting a performance problem, since Proton and Windows behave differently. |
ProtonBackgroundLoadingPriority |
number | 2 |
Proton/Wine only. How much time per frame the engine may spend on background loading, which is when DXVK compiles shader pipelines. 0 leaves the engine default, 1 is low, 2 is normal, 3 is high. Higher trades slightly longer loads for fewer first-encounter stutters. Ignored on native Windows. |
MaxQueuedFrames |
number | -1 |
Frames the CPU may queue ahead of the GPU. -1 leaves the engine default (2). Setting 1 can reduce input latency under DXVK, at some risk to throughput. Applies on any platform, because it is a preference rather than a fix. |
PerformanceLOD |
on/off | true |
Throttles physics updates for distant characters and avoids redundant rigidbody writes. |
ZeroAllocHotPaths |
on/off | true |
Removes per-frame allocations from falling-rock physics and player proximity checks, reducing GC micro-stutter. (replaces reis637-PeakOptimizer (partial)) |
DistanceCulling |
on/off | true |
Skips dynamic-bone secondary motion beyond a distance from the camera, and caps its update rate. (replaces reis637-PeakOptimizer (partial)) |
LightSampleCache |
on/off | true |
Caches baked light volume samples, which cost a CPU 3D-texture readback per call. |
PhysicsThrottle |
on/off | true |
Caches wind shelter raycasts and removes the per-search scene scan from bot vision. |
DecorationCulling |
on/off | true |
Hides small decorative meshes beyond a distance, spreading the work across frames. |
GrassAllocations |
on/off | true |
Reuses one MaterialPropertyBlock for grass instead of allocating a new one every frame. |
GrassFrustumCulling |
on/off | true |
Skips grass chunks outside the camera frustum. Grass casts no shadows, so this cannot change what you see. |
ProximityGating |
on/off | true |
Skips per-step updates for traps and ambient particle spawners with no player nearby. |
PlatformTuning |
on/off | true |
Applies the few engine settings that genuinely differ under Proton/Wine versus native Windows. Does nothing on Windows unless explicitly configured. (replaces ) |
Rejoin
| Setting | Type | Default | What it does |
|---|---|---|---|
LateJoin_AfterWarpDelay |
number | 2 |
Seconds between warping a late joiner and reviving them. Too short and the revive can land at their pre-warp position. |
LateJoin_WarpForwardOffset |
number | 2 |
How far (world forward) to offset the warp from the target player, so the two do not spawn inside each other. |
LateJoin_ReviveHeightOffset |
number | 3 |
How far above the target player to revive the late joiner. |
CatchUp_HeightOffset |
number | 1 |
Metres above the target player's head to place a returning player. |
Restore_FogSafetyMargin |
number | 10 |
Metres of clearance required between the gloom and a player's saved position before restoring them there. |
Restore_MaxAwayTimeSeconds |
number | 300 |
Longest disconnect, in seconds, that still restores the original position. Past this they are caught up to the party instead. |
DisconnectedPlayerTimeoutSeconds |
number | 300 |
How long a disconnected player's character stays in the world before Photon reclaims it. They occupy a player slot for this whole period, so keep it in line with your player cap. Only applies to lobbies you host. |
LateJoinFix |
on/off | true |
Warps players who join mid-run to the party member furthest from the summit, then revives them. |
RestoreRejoinPosition |
on/off | true |
Returns a rejoining player to where they disconnected, if the gloom has not risen past it. (replaces (new behaviour)) |
ReconnectCatchup |
on/off | true |
Warps returning players to the party member furthest from the summit instead of the level start. |
CarryDisconnectedPlayers |
on/off | true |
Lets you pick up and carry teammates who disconnected while alive, and marks them (Disconnected). Ghosts cannot be carried. (replaces (new behaviour)) |
KeepDisconnectedPlayersInWorld |
on/off | true |
Keeps a disconnected player's character alive and simulated until they rejoin, die, or the timeout expires. Room settings are applied when you host; every client tracks who is away. (replaces (new behaviour)) |
Visuals
| Setting | Type | Default | What it does |
|---|---|---|---|
LodBias |
number | 1 |
Level-of-detail bias. Below 1 swaps to simpler meshes sooner: more frames, more visible popping. 1.0 leaves it alone. |
TuneShadowBias |
on/off | true |
Adjusts directional light shadow bias to reduce acne, which allows a lower shadow distance without obvious artefacts. |
ShadowDistance |
number | 0 |
Maximum shadow draw distance in metres. 0 leaves the game's value alone. |
VisualQuality |
on/off | true |
Trades visual fidelity for frames: LOD bias, shadow bias and directional shadow tuning. |