REPOBlacklist
BepInEx plugin for R.E.P.O. Host-side blacklist for shop items, level valuables, and enemies via an in-game F3 menu. Strips blacklisted assets from runtime List/Array/Dictionary spawn pools at scene l
About this mod Author’s original text
REPOBlacklist
A BepInEx plugin for R.E.P.O. that lets the host pick which shop items, level valuables, and enemies should never spawn. Selections are made through an in-game IMGUI menu (default hotkey F3) and persist across every save file on the install.
Only the player hosting the lobby's blacklist takes effect — shop, level valuable, and enemy selection all run host-side in REPO and replicate to clients via Photon. Non-hosts can still install the mod and use the menu; their toggles save locally and become active the next time they host.
What the DLL actually does
On plugin Awake(), it:
- Reads its config. A standard BepInEx config file (BepInEx/config/isaia.repoblacklist.cfg) defines the menu toggle key (default F3).
- Loads the blacklist. Reads BepInEx/config/REPOBlacklist.json (created on first save). The file holds three sorted string lists — items, valuables, enemies — keyed by asset name (the Unity Object.name of the underlying asset). Toggles in the menu write through to this file immediately.
- Registers an IMGUI overlay. Adds a MonoBehaviour that draws a windowed menu while open. The menu has three tabs (Items / Valuables / Enemies), a text filter, and Refresh, Dump (logs diagnostic info to the BepInEx console), Close, and a per-tab Clear button with a two-click confirmation step. Each row is a checkbox bound to the JSON store.
- Subscribes to SceneManager.sceneLoaded. One frame after each scene loads, runs the runtime filter described below. Also re-runs the filter when the menu is closed.
- Applies Harmony input-blocking patches. While the menu is open (BlockInput == true), the following methods are short-circuited so cursor movement doesn't drive the camera and clicks don't fire weapons:
- Legacy: UnityEngine.Input.GetAxis, GetAxisRaw, GetMouseButton, GetMouseButtonDown, GetMouseButtonUp — return 0f / false.
- New: UnityEngine.InputSystem.InputAction.ReadValue() for Vector2, float, and Vector3 — return default(T). Bound dynamically via reflection, so the plugin still loads if the new InputSystem assembly is absent.
- Input.GetKey / GetKeyDown / GetKeyUp are deliberately not patched, so the menu hotkey (and any other plugin hotkeys) keep working.
- These patches are always installed but gated on a single static flag — they're inert when the menu is closed.
Runtime filter
The filter does not Harmony-patch any REPO method. It runs once per scene load (one frame deferred) and once on menu close, and removes blacklisted assets from in-memory pool collections that the game's directors read from. Specifically:
- Type resolution (cached once per session). Walks loaded assemblies and resolves the first match for each category: Item for items; ValuableObject then Valuable for valuables; EnemySetup then EnemiesSetup then EnemyParent for enemies. The resolved type names are logged on first use as Resolved types: Item=…, Valuable=…, Enemy=…. If a name can't be resolved (e.g. a future REPO rename), that category is skipped silently.
- Field discovery (cached per Type). For each MonoBehaviour type seen on first scan, reflects over its public + non-public instance fields once and remembers any whose declared type is List, T, or Dictionary where T (or K, or V) is assignable to a resolved category type. The same scan is done once over every type in non-external assemblies for static fields. After this one-time pass, repeat scans skip GetFields entirely.
- Filter pass. Iterates Object.FindObjectsOfType(true) (active scene + DontDestroyOnLoad + inactive, excluding prefab assets) and the cached static-field list. For each matched container, removes any element whose UnityEngine.Object.name (or, for dictionary string keys, the key itself) is present in the blacklist. Lists and dictionaries are mutated in place; arrays are reallocated with the surviving entries and the field reassigned.
The directors then pick from the now-shorter pool, so blacklisted entries are simply never rolled. The approach is intentionally generi
Install & use Install: BepInEx plugin
- The archive from playbuff is the mod itself — usually a BepInEx plugin (a .dll or a plugin folder once unzipped).
- Recommended: use a community mod manager (such as r2modman) — pick this game, import the mod, and the manager sets up BepInEx and its dependencies for you.
- Manual route: install the BepInEx loader in the game folder, then drop the unzipped .dll or plugin folder into BepInEx/plugins/.
- Launch the game — the BepInEx console logs every plugin it loads; seeing this mod in the log means it is installed.
Mods with listed dependencies need those installed too, or they will not load. Options are usually changed in-game or in the plugin's config file.
Install these first, or the mod will not work: