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.
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 load. Persists globally via JSON file.
By Mentalize
| Last updated | a day ago |
| Total downloads | 175 |
| Total rating | 1 |
| Categories | Tools Server-side AI Generated |
| Dependency string | Mentalize-REPOBlacklist-0.2.2 |
| Dependants | 0 other packages depend on this package |
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
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 (defaultF3). - 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 UnityObject.nameof the underlying asset). Toggles in the menu write through to this file immediately. - Registers an IMGUI overlay. Adds a
MonoBehaviourthat 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— return0f/false. - New:
UnityEngine.InputSystem.InputAction.ReadValue<T>()forVector2,float, andVector3— returndefault(T). Bound dynamically via reflection, so the plugin still loads if the new InputSystem assembly is absent. Input.GetKey/GetKeyDown/GetKeyUpare 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.
- Legacy:
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:
Itemfor items;ValuableObjectthenValuablefor valuables;EnemySetupthenEnemiesSetupthenEnemyParentfor enemies. The resolved type names are logged on first use asResolved 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
MonoBehaviourtype seen on first scan, reflects over its public + non-public instance fields once and remembers any whose declared type isList<T>,T[], orDictionary<K, V>whereT(orK, orV) 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 skipGetFieldsentirely. - Filter pass. Iterates
Object.FindObjectsOfType<MonoBehaviour>(true)(active scene + DontDestroyOnLoad + inactive, excluding prefab assets) and the cached static-field list. For each matched container, removes any element whoseUnityEngine.Object.name(or, for dictionarystringkeys, 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.
Install
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.
Compatibility
- Host-side gameplay effect. Only the host's blacklist filters what spawns. A non-host's blacklist does nothing visible — the host has already chosen what to spawn and replicates it via Photon. (The menu and input-blocking are local to whoever opens them, regardless of host status.)
- No Harmony patches on REPO code. Patches target only
UnityEngine.Input(legacy) andUnityEngine.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. - No Photon / network traffic of its own. The plugin does not send or receive any custom networked messages.
- Per-install config. Blacklist edits affect only your local install. Each host manages their own list.
Changelog
0.2.2
- Removed the 5-second periodic re-apply that was added in 0.2.0; the filter now runs only on scene load and on menu close. Eliminated a recurring stutter.
- Cached per-Type instance-field match info and switched the scene scan from
Resources.FindObjectsOfTypeAlltoObject.FindObjectsOfType(true)to skip prefab assets.
0.2.1
- Added dynamic Harmony patches for
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.
0.2.0
- Added the input-blocking layer (Harmony prefixes on legacy
UnityEngine.Inputaxis and mouse-button reads) so cursor movement no longer drives the camera while the menu is open. - Filter now walks
Dictionary<,>fields and static fields on game-assembly types, in addition to instanceList<T>/T[]fields, and includes DontDestroyOnLoad and inactive objects in the scan. CatchesStatsManager-style singleton pools. - Added Dump button (logs every visited field for diagnostics) and per-tab Clear button (two-click confirmation).
0.1.0
- Initial implementation: F3 IMGUI menu, JSON blacklist file, scene-load filter pass over
List<T>andT[]fields on sceneMonoBehaviours forItem/ValuableObject/EnemySetupelement types.