Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
REPO Fixes Antispam Latency Fix
Multiplayer fixes for R.E.P.O: late-join errors, error spam and stutter sources, instant grab beam, extra-slot items kept between levels, fewer timeout kicks, and guards for bugs in popular mods. Every fix can be toggled.
| Date uploaded | a week ago |
| Version | 1.2.4 |
| Download link | RicketyWrecked-REPO_Fixes_Antispam_Latency_Fix-1.2.4.zip |
| Downloads | 240 |
| Dependency string | RicketyWrecked-REPO_Fixes_Antispam_Latency_Fix-1.2.4 |
This mod requires the following mods to function
BepInEx-BepInExPack
BepInEx pack for Mono Unity games. Preconfigured and ready to use.
Preferred version: 5.4.2100README
R.E.P.O Fixes+
Small, independent fixes for problems that show up in modded R.E.P.O lobbies - especially big lobbies with late joiners. Every fix has its own on/off switch, and fixes aimed at another mod only switch on if that mod is installed.
What it fixes, in plain terms
Lag and errors
- Late joiners (enemy tracker fix) - Someone joining a match already in progress used to make every enemy throw an error each time it tried to see or track them. Over a long session that adds up to heavy stutter or a stuck loading screen. Fixed.
- Error storms when a level ends - When a level is torn down, some game code keeps running for a moment after the things it reads are gone: grab beams, eye tracking, held melee weapons, the tumble wings upgrade. Each error is a full stack-trace write to the log - thousands of them in a few seconds shows up as a hitch. These are caught quietly now.
- Stuck Slow Walker - If a player left while a Slow Walker (Trudge) was vacuuming them, it got stuck mid-attack and threw an error every frame until the level ended (4,000+ errors from one enemy). It now carries on normally.
- Spewer stuck on your face - If the level changed while a Spewer was latched onto a player, its mouth stayed attached into the next level (the shop) and threw an error every frame. It is now removed the way the game would have removed it.
- Error flood from one player's character - When a character never finishes setting up on your side (seen when someone in the lobby is on a different game version, and with the character preview in menus), the game threw an error for it every frame: 9,000+ in under three minutes. The preview is now linked up properly, and any other broken character is skipped quietly instead.
- Revive finishing properly - Being revived could crash the spectator camera's cleanup, which also skipped the rest of the revive (the short movement lock, crouch/energy reset and heal effect). The cleanup now finishes and the revive completes.
- Leaving a match - The room-lighting and fog code kept looking for your character for a second after you left or were kicked, throwing up to ~170 errors each time. Caught quietly now.
- Stuck revive item - If the downed player the revive item locked onto left the game, it got stuck and spammed errors every frame. It now lets go and looks for someone else.
- Lighter logging - Unity normally captures a full stack trace for every ordinary log line and warning, which creates garbage-collection stutter in heavily modded games. Errors keep their stack traces.
Gameplay
- Instant grab beam - Your own grab beam turns on and off the moment you click instead of visibly lagging behind in multiplayer. Other players don't need the mod.
- Extra inventory slots keep their items - The game only remembers slots 1-3 between levels. With a mod that adds slots (like ExtraSlots), anything in slot 4+ used to be left behind. It now comes with you. (Only the host needs this.)
- Fewer timeout kicks - The game gives up on the connection after 10 seconds without an answer, so a short Wi-Fi or internet blip could kick you - even from your own lobby. This raises it to 30 seconds (adjustable). A long outage still disconnects.
- Joining a late-join lobby that just closed - Hosts with a late-join mod close their lobby for a few seconds while a level loads, so picking it from the server list often failed with "Game closed" (or "Game full") and sent you back to the main menu. The join is now retried every 5 seconds, up to 4 times.
- LateJoinNow keeps your equipped gear - With LateJoinNow, anything in your belt slots used to be deleted on every level change. Equipped gear now survives.
- LateJoinNow voice for players without mods - When someone without LateJoinNow joins mid-level, LateJoinNow tries to send them the other players' voice chat objects, but Photon refused that message every time, so they could be missing voices. It now goes through.
- LateJoinNow in private lobbies - In a private (friends-only) game, LateJoinNow mistook the open lobby for a locked one and re-opened it with Steam every 5 seconds for the whole session. It now only does so when the lobby really was locked.
Map and invisible rooms after joining mid-level? That's a separate mod: LatejoinMapSyncFix.
Fixes for other mods (each only active if that mod is installed)
- Hauler Unlimited Storage - it lets everything into the hauler, and the game then absorbs non-valuables for $0 and deletes them - guns, tools, drones, purchased gear. The hauler only takes valuables again, still with no limit.
- Crouch And Crawl Sprint - with crawl left toggled on (LeftAlt - easy to hit while alt-tabbing), it threw an error every frame during level loading. It now waits until the level is ready.
- Toggle Mute - its MUTED indicator never appeared because it looked for a HUD element before the game had created it. It shows up now. Prefer no on-screen text? Set
ToggleMuteShowIndicatorto off: the text (and Toggle Mute's error about it) goes away and the mute toggle keeps working. - CartSpeedSync - it pushed velocity onto carts this machine doesn't simulate, filling the log with physics warnings that grew every level. Those no-op calls are skipped.
- GameTools - it re-sent a lobby setting to every player every 3 seconds all session, even though it never changed. It only sends when it changes now. It also let any player who has GameTools kill, revive or heal you remotely, and a kill and a revive requested at the same time looped (71 deaths in 7 seconds in one lobby). Now only the lobby host can, and a kill + revive at the same time is ignored. When you host, it works for everyone else as before. And its "revive at extraction point" fired even while an extraction was running, so the revived player was killed again by the tube and the game's own end-of-extraction revive then missed them; it now waits, and the game revives them when the extraction finishes.
- Empress Gameboy Emulator - the host emulated the game and streamed its screen to every player all session, even with nobody playing. It now pauses (screen goes dark) while nobody's at the controls and resumes on E.
Turn any of these off in BepInEx/config/ricketywrecked.repo.fixesplus.cfg, or through REPOConfig in-game. Restart the game after changing.
For the technically curious
Enemy tracker fix (late joiners)
The base game registers each player with every enemy's vision tracking once, when the level's first enemy wave finishes spawning. Anyone who joins after that, or any enemy that spawns after they joined, is never registered, and every vision/on-screen check for that player throws KeyNotFoundException. This registers joining players with every enemy tracker, registers current players with each new tracker, and self-heals EnemyOnScreen.GetOnScreen. It only calls the game's own registration method; nothing polls.
Teardown and grab error guards
PhysGrabBeam.DrawCurve gets the null checks it was missing. PlayerHealth.Update gets a prefix: a menu avatar whose playerAvatar is still null (its Awake read PlayerAvatar.instance before it existed) is linked to the local player once it exists, and skipped until then. A finalizer backs it up for any other avatar that never finished setup, and its warning names the player. SpectateCamera.StopSpectate (called from ReviveRPC) can throw on its second-to-last line when normalTransformPivot is already destroyed, which also aborted the rest of ReviveRPC. A finalizer destroys the spectate camera object itself and lets the revive continue. EnvironmentDirector.AmbientLightLogic gets a finalizer for the frames after the local player is gone. PlayerEyes.LookAtTransform, PlayerEyes.ClosestPhysGrabPoint, PhysGrabObject.PhysicsGrabbingManipulation, PhysGrabber.OverrideDisableGrabLookAt and ItemUpgradePlayerTumbleWingsLogic.FixedUpdate get Harmony finalizers: all are void and run every frame or physics tick, so absorbing an exception from an object that's already gone has no gameplay effect. The mod's own "suppressed" log lines are rate limited (first occurrence, then every 1000th).
Slow Walker
SlowWalkerAttack.SuckInListPlayerUpdate rebuilds its in-range player list each frame and reads each player's PlayerVisionTarget.VisionTransform unguarded. The throw happens partway through StateImplosion, so the state machine never advances and the enemy rethrows forever. A finalizer on the callee returns control to StateImplosion so it keeps going.
Spewer
EnemySlowMouthAttached sits on the player's avatar, which survives level changes. When the enemy is unloaded mid-attach, its Update throws on destroyed eye/particle references before it reaches StateOutro, its only self-destroy. A finalizer swallows that and, once the parent EnemySlowMouth is gone, destroys the jaws and the component the way StateOutro does.
Revive item
ItemReviveItem reads its target's death head rigidbody every frame with no null check. When the target is gone this clears playerTarget/hasTarget and tells other players via the game's own UpdatePlayerTargetRPC(-1).
Instant grab beam
PhysGrabBeamActivate/Deactivate send their RPC to RpcTarget.All, including yourself, so your own beam waits for a network round trip. This runs the RPC body locally and sends the same RPC to RpcTarget.Others. Its prefixes run at low priority so other mods patching the same methods (CustomGrabColor reads physGrabBeamActive to detect a first activation) see the state from before activation.
Extra slots
Vanilla stores held items in StatsManager.playerInventorySpot1/2/3 (steamID → instance-name hash); PlayerInventoryUpdate ignores spot indexes above 2 and PunManager.SetItemNameLOGIC only checks those three when re-equipping spawned items. This keeps host-side records for spot 3+ and re-equips with the same ItemEquippable.RequestEquip(spot, player) vanilla uses, after the slot exists. Cleared where vanilla clears its own (StuffNeedingResetAtTheEndOfAScene, ResetAllStats).
Connection timeout
Photon disconnects when a reliable command is unacknowledged for DisconnectTimeout (default 10 s) or resent more than SentCountAllowance times (PUN sets 9). Both are raised (to the configured seconds and PUN's max of 10) from GameDirector.Start once connected, on this machine only; the initial connect is untouched. Photon's server-side timeout still applies.
Server list join retry
A prefix on NetworkConnect.OnJoinRoomFailed: for joins from the server list (DataDirector.networkJoinServerName) failing with GameClosed (32764) or GameFull (32765), it re-issues PhotonNetwork.JoinRoom on the same room every 5 s (up to 4 times) while connected to the master server, instead of the popup and leave-to-menu. Everything else goes to the game's normal handling.
LateJoinNow private lobbies
LateJoinNow re-checks every 5 s whether the Steam lobby is locked by reading SteamManager.privateLobby, which the game also sets in UnlockLobby(false) for private games. Postfixes on SteamManager.LockLobby/UnlockLobby record the real state, and a prefix on its IsSteamLobbyActuallyLocked answers with it.
LateJoinNow voice for players without mods
In its non-coop late-join path LateJoinNow re-sends each existing player's Voice object as a PUN Instantiation event (code 202) through the public PhotonNetwork.RaiseEvent, which rejects every code of 200 or above. A transpiler on its RefreshOldPlayersForNewJoiner coroutine sends that one event (code 202 with prefab Voice, nothing else) through PUN's internal RaiseEventInternal instead. PhotonNetwork itself is not patched.
LateJoinNow equipped items
LateJoinNow destroys non-persistent networked objects on level change; its keep-list (BuildPlayerPersistentViewIdSet) only covers player avatars. A postfix adds every item whose network-synced ItemEquippable.isEquipped flag is set. Found by name at runtime - no compile-time reference to LateJoinNow.
Other-mod guards
All found by name at runtime and applied only when BepInEx reports the mod loaded:
ItemValuableBox.OnObjectsFoundpostfix (Hauler Unlimited Storage replaces it and lists every object; vanilla's absorb step then destroys anything without aValuableObjectfor $0) - removes non-valuables fromvalidObjectsInBox.- Prefix on CrouchAndCrawlSprint's
PlayerController.Updatepostfix - skipped untilplayerAvatarScript,PlayerCollisionStand.instanceandCameraCrouchPosition.instanceexist (SetCrawldereferences them unguarded). EnergyUI.Startpostfix re-runs Toggle Mute's own HUD setup if itsMutedTextobject doesn't exist yet. WithToggleMuteShowIndicatoroff, a prefix skips that setup instead, keeping only its chat-box lookup (Settings.ChatGameObject, used so typing in chat doesn't toggle mute).- Prefix on CartSpeedSync's
CartSteerpostfix - skipped when not host or the cart rigidbody is kinematic (vanilla guards both). - Prefix on GameTools'
SyncProhibitOthersToRoom- skipped when the room already holds the current value. - Prefix on GameTools'
PlayerDeathHeadupdate postfix - skips its auto revive while the head is in an extraction point whose state isn't Idle/Active (the same rule vanilla's revive item uses), so the extraction revives it after the tube. - Postfix on Photon's
Player.InternalCacheProperties(GameTools only): GameTools obeysGT_ReqKill_/GT_ReqRevive_/GT_ReqHeal_<actor or steamID>found in any player's properties. Requests aimed at this player are dropped from the local cache unless they come from the current master client, and a kill + revive pair is dropped entirely. Requests aimed at other players are untouched. - Prefix on Empress Gameboy's
TickHostEmulator- skips emulation and frame streaming while nobody controls the cabinet; flushes the save, blanks the screen and sends one dark frame when it goes idle.
Logging
Application.SetStackTraceLogType is set to None for Log and Warning; Error/Exception are unchanged.
Settings
| Setting | Default | What it controls |
|---|---|---|
EnemyTrackerFix |
on | Late-joiner enemy tracker fix |
GrabBeamAntispam |
on | Grab beam / eye tracking / held-object error guards |
InstantGrabBeam |
on | Instant local grab beam |
ReviveItemFix |
on | Revive item stuck on a player who left |
LateJoinNowEquippedItemFix |
on | Equipped gear survives level changes (needs LateJoinNow) |
LateJoinNowVoiceFix |
on | Voice objects reach late joiners without mods (needs LateJoinNow) |
LateJoinNowPrivateLobbyFix |
on | No lobby re-open every 5 s in private games (needs LateJoinNow) |
ServerListJoinRetry |
on | Retry "Game closed" / "Game full" joins from the server list |
EnemyAttackFix |
on | Slow Walker stuck mid-attack; Spewer mouth left on a player after a level change |
LevelTeardownErrorGuards |
on | Teardown errors (tumble wings, room lighting and fog after leaving or a kick), per-frame errors from a character that never finished setup, and the revive camera cleanup |
OtherModGuards |
on | Fixes for other installed mods (list above) |
ToggleMuteShowIndicator |
on | Toggle Mute's on-screen MUTED text (off = no text, toggle still works) |
GameboyPauseWhenIdle |
on | Pause Empress Gameboy when nobody's playing |
ConnectionTimeoutSeconds |
30 | Seconds before a connection hiccup disconnects you (10 = game default) |
ExtraSlotsKeepItems |
on | Items in slot 4+ carried to the next level (host) |
NoStackTracesOnInfoAndWarnings |
on | Lighter logging (Performance section) |
If anything about grabbing feels off in your lobby, turn off InstantGrabBeam first.
Good to know
- Grabbed objects can still feel delayed when you're not the host - the host runs physics and streams the result, and this mod doesn't change that.
- A fix that can't apply (for example after a game update) is logged and skipped; the others still load.
- Only needs BepInEx. Built and tested in a heavily modded 10-player profile on R.E.P.O v0.4.4.3.
- Other players don't need this mod, and having it or not doesn't affect who can join.
License
Copyright (c) 2026 RicketyWrecked. All rights reserved. You may download and play with this mod, and list it as a dependency in your own Thunderstore modpack. You may not copy, modify, decompile, reuse or re-upload any of it without written permission - see the included LICENSE file. Permission requests: Discord.
Credits
Made by RicketyWrecked. Not affiliated with the R.E.P.O developers or any of the mods mentioned above.
Questions, bug reports, or suggestions: Discord.
CHANGELOG
Changelog
1.3.2
- New (RepoCasino only,
OtherModGuards, host): the blackjack table no longer stops working after a long session. RepoCasino deals every card as a new network object and only hid old cards between hands, so after about 30 minutes the room ran out of object IDs ("out of 'room' viewIDs") and no new hand could be dealt. The host now deletes a hand's cards when the hand ends. Works for players without the mod.
1.3.1
- New (BetterMap Fixer only,
OtherModGuards): no more lag that builds up and stays. BetterMap Fixer added a new map icon to a player for every revive message, even ones the game ignored: one player's own GameTools sent about 80 a second for 6 minutes, leaving 14,800 icons on them, a 3-second freeze when they were really revived, and about half the frame rate until the level ended. A player now keeps one icon. Its icon removal on death also no longer throws an error.
1.3.0
- New setting
StuckVoiceFix(on): fixes one player's voice going silent for you alone (everyone else still hears them) until they leave and rejoin. When their game restarts its voice stream and the new stream arrives before the old one ends, the new one now takes over, and if someone is talking but nothing has played for 4 seconds, their voice is re-linked. - New (See who is talking only,
OtherModGuards): it shows the right player's name as speaking. It used the voice chat's player number, which drifts apart from the game's as players rejoin.
1.2.9
- New (GameTools only,
OtherModGuards): a host's GameTools heal request heals you once. Its leftover request used to heal you to full 10 times a second for as long as it stayed (960 heals in under 2 minutes in one lobby), which looks like god mode to everyone else and can get you banned.
1.2.8
- New (SoloHUD only,
OtherModGuards): players' name tags show over their heads in levels again. SoloHUD keeps the map switched on for its minimap, and the game hides name tags while the map is open; now only holding the map tool hides them. - New (GameTools only,
OtherModGuards): no more revive flood. When the host revived a player who also has GameTools, GameTools left a "revive yourself" request that player's game answered up to 10 times a second for minutes (48,000+ revives in one session). The host's own revive is used instead, and players with this mod ignore such requests. - New setting
HideKinematicVelocityWarnings(on): hides Unity's "Setting linear/angular velocity of a kinematic body is not supported" warnings that cosmetics (hair, outfit pieces) trigger thousands of times a session.
1.2.7
- New (Repo Admin Menu only,
OtherModGuards): its per-player checks threw when someone joined (Steam ID not known yet), skipping the game's own update for that frame. - New (
LevelTeardownErrorGuards): a player dying before their colours arrived left their body standing (the death stopped halfway with an error); a joiner's grab upgrades weren't applied when their Steam ID wasn't known yet; one error when a player leaves while you turn a held object; and an error every frame on the host after a player left (or was kicked) while holding a door, lever or other fixed object. - New (
SpawnedItemsKeep, host): items spawned by a mod (e.g. Repo Admin Menu) disappeared at the next level and could take the saved name of an item a player already had, mixing the two up. They now get their own name and count as owned, like shop items. - New (
TruckItemsKeep, host, with NoItemSpawnLimit): bought items that don't fit the truck's spots no longer come back outside the truck or in a wall; they go on top of truck spots of their size. - New (XH DamageShow & EnemyHealthBar only,
OtherModGuards): its Chinese welcome popup in the middle of the screen is hidden. - New (
ExtractionSoftlockFix, host): a player joining mid-level after the first extraction was finished could make the host start that finished point again, locking every other extraction point for the rest of the level. The host now only starts a point that is ready.
1.2.6
- New (GameTools only): a player who dies in a cart is no longer revived on the spot by GameTools' cart revive (and killed again a second later); it waits until their head is taken out and put back.
1.2.5
- New: no more red
EnemyDirector.Starterror every time the truck loads (LevelTeardownErrorGuards).
1.2.4
- New: a Spewer latched onto a player when the level changes no longer stays stuck (and erroring every frame) into the next level (
EnemyAttackFix). - New (LateJoinNow only,
LateJoinNowPrivateLobbyFix): in private games LateJoinNow no longer re-opens the Steam lobby every 5 seconds. - New (
ServerListJoinRetry): joining from the server list retries "Game closed" / "Game full" up to 4 times instead of sending you back to the main menu. - The version shown by BepInEx now matches the package (it had stayed at 1.2.1).
- Late-join map sync and level-piece repair, tested in development builds of this mod, ship as their own mod: LatejoinMapSyncFix.
1.2.3
- New option
ToggleMuteShowIndicator(Toggle Mute only, default on): turn it off to drop Toggle Mute's on-screen MUTED text and its "Could not find text to clone" error, while keeping the mute toggle (and its "not while typing in chat" check).
1.2.2
- New (LateJoinNow only,
LateJoinNowVoiceFix): players who join mid-level without LateJoinNow now receive the other players' voice chat objects. LateJoinNow's message for this was refused by Photon every time. - New (GameTools only): its extraction-point auto revive waits while an extraction is running. Before, the revived player was killed again by the tube and then missed by the game's own end-of-extraction revive.
- New: no more error burst from the fog code right after leaving a match or being kicked.
- Added a LICENSE file (all rights reserved; using it and listing it in modpacks is fine).
1.2.1
- New: stops a per-frame error flood from a character that never finished setting up (the character preview in menus, or a player on a different game version). The preview is linked up properly; anything else is skipped quietly and named once in the log.
- New: being revived no longer crashes the spectator camera's cleanup and skips the end of the revive.
- New: no more error burst from the room lighting right after leaving a match.
- New (GameTools only): only the lobby host can remotely kill, revive or heal you, and a kill + revive requested at the same time (which looped) is ignored.
- All of the above are under the existing
LevelTeardownErrorGuardsandOtherModGuardsswitches.
1.2.0
- New: Slow Walker stuck-attack fix (
EnemyAttackFix). - New: more level-teardown error guards -
PlayerEyes.ClosestPhysGrabPoint,PhysGrabObject.PhysicsGrabbingManipulation,PhysGrabber.OverrideDisableGrabLookAt(underGrabBeamAntispam) and the tumble wings upgrade (LevelTeardownErrorGuards). - New: items in extra inventory slots (4+) carried between levels (
ExtraSlotsKeepItems). - New: longer connection timeout, 30 s by default (
ConnectionTimeoutSeconds). - New: lighter logging - no stack traces for ordinary log lines and warnings (
NoStackTracesOnInfoAndWarnings). - New: guards for other mods, only active when installed (
OtherModGuards): Hauler Unlimited Storage no longer destroys non-valuables, Crouch And Crawl Sprint no longer errors during level loading, Toggle Mute's MUTED indicator shows up, CartSpeedSync's no-op physics calls skipped, GameTools' repeated lobby-setting broadcast skipped. - New: Empress Gameboy pauses while nobody is playing (
GameboyPauseWhenIdle). - Instant grab beam now runs after other mods' prefixes on the same methods.
- Optional mods are detected through BepInEx before looking up their code, so missing ones no longer log HarmonyX warnings.
1.1.1
- No functional changes. Fixes the website link (was blank on 1.1.0 due to a CI publishing bug) to point to the Discord.
1.1.0
- New: LateJoinNow equipped-item fix. LateJoinNow's level-change cleanup destroys every player's currently-equipped gear, host included - this adds equipped items to its own keep list so they survive. Has its own setting,
LateJoinNowEquippedItemFix. Requires LateJoinNow; does nothing if it isn't installed.
1.0.3
- New: revive item fix. Stops the revive item getting stuck on a dead player who left the lobby, which threw an error every frame until the level ended. Has its own setting,
ReviveItemFix. - Removed the LateJoinNow and MorePlayers dependencies again, so installing this mod no longer installs them. BepInEx is the only dependency.
1.0.2
- Lists LateJoinNow and MorePlayers as dependencies, so they install alongside this mod and show up as its associated mods. No functional changes.
1.0.1
- Rebuilt without debug metadata, so the DLL carries no build paths. No functional changes.
1.0.0
First combined release. Merges three separate fixes into one mod, each behind its own setting:
- Enemy tracker fix (late joiners): registers joining players with every enemy tracker in the scene, registers current players with each new tracker, and self-heals
EnemyOnScreen.GetOnScreen. - Grab beam antispam: null guards for
PhysGrabBeam.DrawCurveand a catch-all finalizer forPlayerEyes.LookAtTransform. - Instant grab beam: your own beam turns on and off locally without waiting for the network round trip.
New in the combined version:
- Per-fix on/off settings.
- Each patch is applied on its own, so one that can't apply doesn't stop the others.
- Suppression messages are rate limited so the antispam fixes don't spam the log themselves.