Files
institution/Wiki/contraband/Compatibility.md
T
flan 3530100ed5 Aggregate the whole suite wiki onto the Institution page
Wiki/Home.md is the suite's front door; every layer's wiki now mirrors here
under Wiki/<layer>/ (core, contraband, justice, gangs, ward), so the whole
suite reads in one place with the index linking to the local pages. The
layer repos stay canonical -- Tools/sync-wiki.sh refreshes the aggregated
copy on demand. The README's main page points to it.
2026-07-15 20:30:38 +00:00

7.7 KiB
Raw Blame History

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 Types, 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:

    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.

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.
  • 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. Developed with substantial assistance from Claude (Anthropic).