


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.
On plugin Awake(), it:
BepInEx/config/isaia.repoblacklist.cfg) defines the menu toggle key (default F3).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.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.SceneManager.sceneLoaded. One frame after each scene loads, runs the runtime filter described below. Also re-runs the filter when the menu is closed.BlockInput == true), the following methods are short-circuited so cursor movement doesn't drive the camera and clicks don't fire weapons:
UnityEngine.Input.GetAxis, GetAxisRaw, GetMouseButton, GetMouseButtonDown, GetMouseButtonUp — return 0f / false.UnityEngine.InputSystem.InputAction.ReadValue<T>() 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.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:
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.MonoBehaviour type seen on first scan, reflects over its public + non-public instance fields once and remembers any whose declared type is List<T>, T[], or Dictionary<K, V> 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.Object.FindObjectsOfType<MonoBehaviour>(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 generic — it does not depend on knowing REPO's specific manager class names — but it does mean a blacklist only takes effect on assets reachable through one of the three supported container shapes. If a future REPO build stores a pool in a more exotic structure (a custom weighted-pool class, for example), the Dump button lists every visited field with counts, which makes the gap obvious.
External assemblies (UnityEngine.*, Unity.*, System.*, mscorlib, netstandard, BepInEx*, 0Harmony, HarmonyX*, Mono.Cecil, Microsoft.*, and the plugin itself) are skipped during type resolution and field discovery.
Thunderstore Mod Manager: click Install. Manual: drop REPOBlacklist.dll into <profile>/BepInEx/plugins/REPOBlacklist/. Requires BepInEx-BepInExPack.
The blacklist file at BepInEx/config/REPOBlacklist.json is shared across every save and every lobby on that BepInEx install. Deleting it resets the blacklist to empty.
UnityEngine.Input (legacy) and UnityEngine.InputSystem.InputAction (new). The runtime filter mutates REPO collection fields via reflection at scene load and on menu close — it does not intercept any REPO method.Resources.FindObjectsOfTypeAll to Object.FindObjectsOfType(true) to skip prefab assets.UnityEngine.InputSystem.InputAction.ReadValue<Vector2/float/Vector3>() so the new InputSystem mouse-look path is also blocked while the menu is open. Bound via reflection.UnityEngine.Input axis and mouse-button reads) so cursor movement no longer drives the camera while the menu is open.Dictionary<,> fields and static fields on game-assembly types, in addition to instance List<T> / T[] fields, and includes DontDestroyOnLoad and inactive objects in the scan. Catches StatsManager-style singleton pools.List<T> and T[] fields on scene MonoBehaviours for Item / ValuableObject / EnemySetup element types.