Per the updated project policy, AI/Claude attribution lives in exactly one NOTICE file per repo and nowhere else -- removed it from the About description, README, wiki, and roadmap.
129 lines
7.7 KiB
Markdown
129 lines
7.7 KiB
Markdown
# Compatibility
|
||
|
||
*Contraband ships zero Harmony patches. It adds defs, subclasses a work-giver, mutates two duty
|
||
trees at startup, and polls. That is why it composes instead of colliding.*
|
||
|
||
## Requires: Institution: Core
|
||
|
||
Contraband declares a hard `modDependency` on **`flan.institution.core`** and loads after it. This
|
||
is not optional — after the split, the entire substrate Contraband reads lives in Core:
|
||
|
||
| Core provides | Contraband uses it for |
|
||
|---|---|
|
||
| `SecuredContext` / `SecuredContexts` / `CanConceal` / `IsHeld` | who counts as a concealer; who can be intaken, whittle, or dig |
|
||
| `Propensity.Would(pawn, base, salt)` | every disposition roll — intake (0.6), improvise (0.10), dig (0.08), all seeded and scaled by nature × nurture |
|
||
| `CriminalRecord` + `GameComponent_CriminalRecords` | `timesSearched`, `timesCaught`, `escapeAttempts`, `contrabandMade` — written by search and acquisition, read by priority |
|
||
|
||
Install Contraband without Core and it will not run. Everything else on this page is optional
|
||
interplay that degrades gracefully when the other mod is absent.
|
||
|
||
## Zero Harmony patches
|
||
|
||
Post-split, the mod's one Harmony patch (the regime that forces Joy for prisoners) moved to
|
||
**Institution: Justice**, so Contraband is Harmony-free again. Instead of patching, it:
|
||
|
||
- **Adds a new `WorkGiver`** (`WorkGiver_Warden_Search`) rather than patching a vanilla one.
|
||
- **Subclasses `WorkGiver_Warden`**, inheriting its behaviour rather than overriding it.
|
||
- **Mutates two `DutyDef` think trees at startup** via `StaticConstructorOnStartup` (not Harmony) —
|
||
an XML patch on a duty think tree silently no-ops in 1.6, so it is done in C#, deterministically.
|
||
- **Polls** every held pawn from a `MapComponent` for intake, improvisation, and tunnels — no hook
|
||
on the capture event is needed because the tick already visits every held pawn.
|
||
|
||
The net effect: the surfaces other prison mods touch are mostly untouched here, so conflicts are the
|
||
exception, not the rule.
|
||
|
||
## Foul Play — the carboy bridge
|
||
|
||
**Foul Play** (the "Piss Nuke" mod) stays its own mod with its own front door, and yet its **carboy
|
||
is a first-class contraband item.** This is the flagship demonstration of Contraband's *"items are
|
||
defs, subsystems are classes, mods are audiences"* principle, and it works through two seams:
|
||
|
||
1. **Cross-assembly worker resolution.** `CompProperties_Contraband`'s `useWorker` / `escapeWorker`
|
||
fields are plain `Type`s, and RimWorld resolves def `Type` fields with
|
||
`GenTypes.GetTypeInAnyAssembly` — searching **every loaded assembly**. So the carboy declares
|
||
`CompProperties_Contraband` and points `useWorker` at a class that lives in *Foul Play's* assembly
|
||
(e.g. a throw-the-carboy worker). Contraband never has to know that class exists.
|
||
2. **The opaque content tag.** A carboy is not just "a jar" — it is a jar *of* a fermented blend, and
|
||
that blend has to survive being concealed. Foul Play sets Contraband's two delegates:
|
||
|
||
```csharp
|
||
ContrabandUtility.ContentTagOf = thing => /* serialise the carboy's blend */;
|
||
ContrabandUtility.ApplyContent = (thing, tag) => /* pour that blend back in on redeem */;
|
||
```
|
||
|
||
When a carboy is intaken or smuggled, Contraband captures the tag blind; on redemption it hands
|
||
the tag back to Foul Play to restore the contents. **Contraband knows nothing about substances or
|
||
fermentation** — that framework lives entirely in Foul Play. If Foul Play is absent, both delegates
|
||
are null, no content is captured, and nothing breaks: a jar is just a jar. See
|
||
[Concealment and Intake](Concealment-and-Intake.md).
|
||
|
||
The dependency runs one way only: Foul Play bridges *to* Contraband (and to Core) if they are
|
||
present; Contraband takes **no** dependency on Foul Play.
|
||
|
||
## Institution: Justice — the record is the shared bus
|
||
|
||
Contraband and **Justice** never call each other. They meet on Core's `CriminalRecord`:
|
||
|
||
```
|
||
Contraband writes ──▶ CriminalRecord ──▶ Justice reads
|
||
timesSearched (in Core) Classification (security grade)
|
||
timesCaught Deterrence (colony-wide signal)
|
||
escapeAttempts Discipline / Parole (reform)
|
||
contrabandMade
|
||
```
|
||
|
||
- **Catching contraband feeds classification.** A prisoner repeatedly caught with shivs or foiled
|
||
mid-tunnel accrues `timesCaught` and `escapeAttempts`, which Justice's classification weighs into a
|
||
higher security grade.
|
||
- **And it feeds back.** Justice's deterrence signal flows *back* through Core's propensity seam
|
||
(`Nurture`), nudging every future intake / improvise / dig roll a Contraband pawn makes. A prison
|
||
that catches and disciplines becomes a prison where fewer prisoners bother trying — without either
|
||
mod referencing the other. Run Contraband alone and the deterrence factor is a neutral 1.0; the
|
||
record fields still route the warden.
|
||
|
||
## Institution: Gangs — the contraband economy
|
||
|
||
**Gangs** depends on Core, **Contraband**, and Justice, because a gang *is* a contraband economy:
|
||
|
||
- Gang smuggling moves contraband through the same public `Conceal` door intake and corruption use.
|
||
- A gang's outside members are the natural caller for the **reach-in corruption** primitive
|
||
(`Corruption.Smuggle`) — paying a bent warden to make a delivery. That primitive is exposed in
|
||
Contraband but has no in-repo trigger; Gangs is what drives it. See [Corruption](Corruption.md).
|
||
- Gang fights route to Justice's crime record, which then raises search priority here. The loop
|
||
closes through Core again.
|
||
|
||
## Prison mods the suite is tested against
|
||
|
||
| Mod | Interaction | Verdict |
|
||
|---|---|---|
|
||
| **Prison Commons** | postfixes `WorkGiver_Warden.ShouldSkip` on the **base** class; Contraband's search subclasses it and does not override, so searches respect prison-commons/allowed areas **for free** | works by inheritance |
|
||
| **Custom Prisoner Interactions** | patches only the *named* vanilla warden givers (`_Chat`, `_Convert`, `_Enslave`, `_ReleasePrisoner`); it cannot see a brand-new giver | no conflict |
|
||
| **Prisoner Realism** | its escapes are for "mood prisoners" mid-break; a tunnel breakout hands off to vanilla `PrisonBreakUtility.StartPrisonBreak`, which Prisoner Realism layers on. Tunnels **complement** it — they let ward patients and slaves who would never mood-break still, patiently, dig out | complementary |
|
||
| **Prison Labor** | prisoners working outside the cell are still held pawns and still tracked; Contraband adds no patches to labor jobs. A work assignment is simply another place a disposed prisoner might come by materials | no conflict |
|
||
| **Prisoner Recreation** | overlaps the *regime* feature — which now lives in **Institution: Justice**, not here, and is written to be idempotent with Prisoner Recreation | not Contraband's concern post-split |
|
||
|
||
## Load order
|
||
|
||
```
|
||
Ludeon.RimWorld
|
||
flan.institution.core ← required, loads before Contraband
|
||
flan.institution.contraband ← this mod
|
||
(Foul Play / Justice / Gangs — any order after Core; each bridges if present)
|
||
```
|
||
|
||
## The general rule
|
||
|
||
If a mod adds prisoner behaviour by **patching vanilla warden givers or the escape duty tree by
|
||
name**, it will not see Contraband's additions, and Contraband will not see its — they pass each
|
||
other. If a mod adds a *new* `WorkGiver` or duty node of its own, it stacks. The one place to watch is
|
||
another mod that *also* rewrites the same two duty think trees (`PrisonerEscape`,
|
||
`PrisonerAssaultColony`) wholesale; Contraband inserts its nodes at a specific anchor and logs a
|
||
warning if that anchor is missing, so a load-order or conflict problem is visible in the log rather
|
||
than silent.
|
||
|
||
---
|
||
|
||
*Part of the **Institution** suite — Core · Contraband · Justice · Gangs, alongside Foul Play and
|
||
Ward. Each stands alone; together they interlock.*
|
||
**
|