Imported from HunYuan2333/rimworld-mod-engineering-skills (
rimworld-mod-engineering-en/SKILL.md). Install upstream withnpx skills add HunYuan2333/rimworld-mod-engineering-skills --skill rimworld-mod-engineering-en. Copyright stays with the author.
RimWorld Mod Engineering
Treat a RimWorld mod as software running inside a shared, stateful, heavily modded process. Scale the process to the change: a two-Def content tweak does not need an enterprise architecture, while a combat overhaul or framework needs explicit boundaries, compatibility ownership, migrations, and staged validation.
Start with evidence
Before proposing or changing code:
- Read repository instructions and the project’s design/developer documents.
- Inspect
About/About.xml,LoadFolders.xml, version folders, project files, assembly references, build scripts, and packaging layout. - Identify the target RimWorld build, Unity player version, target framework, DLC matrix, required dependencies, optional integrations, and supported save lifecycle.
- Separate verified facts from inference. If source is absent, inspect XML, metadata, package layout, and logs, then state what remains unknown.
- Ask the user only when an unresolved choice changes public behavior, compatibility, save format, destructive migration, or architecture.
Read references/fundamentals.md when establishing the environment or project baseline.
Classify the task
Choose the smallest applicable profile, then read only the linked references.
- Architecture, refactoring, boundaries, coupling, or design review: references/engineering-philosophy.md
- XML/content, recipes, research, weapons, apparel, buildings: references/content-xml.md
- Runtime components, jobs, needs, maps, quests, world state, saves: references/runtime-save.md
- Harmony or cross-mod integration: references/harmony-compat.md
- Settings that change runtime behavior or global Def rewriting: references/configuration-def-transforms.md
- UI, tick cost, allocation, threading, networking: references/performance-ui-threading.md
- Logging, diagnostics, support bundles, or developer tools: references/observability-developer-tools.md
- Architecture or project planning: references/mod-archetypes.md
- Review or high-intrusion assessment: references/engineering-review.md
- Tests, packaging, release, or update support: references/testing-release.md
- Framework/infrastructure core or an extension targeting it: references/framework-profile.md
Use this workflow
1. Define the change contract
Write down:
- player-visible outcome and explicit non-goals;
- affected Defs, types, methods, saves, maps, factions, and integrations;
- required versus optional dependencies;
- behavior when an optional dependency is absent, outdated, or fails;
- whether adding, updating, disabling, or removing the mod is supported on an existing save.
Also identify the authoritative state, derived state, invariants that must survive every path, and the lifecycle phase in which the change becomes valid. Do this before selecting classes or patterns.
2. Choose the least-coupled extension point
Prefer, in order when they can express the same behavior:
- new Defs and inheritance;
- conditional XML patches;
ModExtension,ThingComp,HediffComp,GameComponent,MapComponent, or documented framework API;- a narrow Harmony postfix or prefix that preserves the original contract;
- private-member reflection, reverse patches, or transpilers only with a stated reason and compatibility tests.
This is a decision order, not a ban. A necessary deep patch is acceptable when its blast radius and failure behavior are explicit.
3. Design boundaries before mechanics
- Keep Def/schema, domain logic, game adapters, integrations, UI, and persistence distinguishable.
- Put optional integrations behind adapters and conditional load folders or assemblies.
- Use direct references for declared required dependencies; do not hide required contracts behind reflection.
- Use stable identifiers in persisted data. Treat renamed Defs, types, fields, and package IDs as migrations.
- Make ownership and lifetime explicit for events, caches, subscriptions, background work, and native resources.
- Make initialization dependencies explicit; do not use incidental assembly, reflection, patch, or callback order as architecture.
- Give each mutable fact one authority. Treat caches, indexes, UI models, and rewritten Def views as derived state with an invalidation or rebuild rule.
- Do not introduce an abstraction until there are multiple implementations, a volatile boundary, or a test seam that justifies it.
4. Implement in vertical slices
For each slice, complete Def/schema, behavior, persistence, compatibility, UI, localization, and validation together. Do not accumulate a large untested compatibility phase at the end.
5. Validate in widening rings
Run the narrowest useful checks first:
- compile and static/XML checks;
- clean startup and Def-resolution checks;
- focused developer-mode scenario;
- save/load and migration checks;
- supported DLC/dependency combinations;
- representative mod-stack compatibility;
- performance measurement for hot paths;
- packaged artifact test, not only source-tree test.
Do not claim a test passed unless it ran. Report skipped checks and why.
Engineering rules
- Preserve named invariants across success, rejection, cancellation, exception, save/load, and compatibility paths.
- Preserve vanilla and upstream contracts unless the feature explicitly replaces them.
- Keep patches idempotent where practical and avoid duplicate registration on reload or reinitialization.
- Pair acquisition with release and registration with deregistration. Verify the less-visible exits: map removal, return to menu, dependency failure, canceled jobs, expired world objects, and partial activation.
- Validate nullable game state, destroyed/despawned objects, absent maps, unresolved Defs, and partial saves at boundaries.
- Log actionable context once; avoid silent catches and per-tick log floods.
- Do not mutate Unity or Verse objects from background threads. Marshal results through a project-proven main-thread boundary.
- Measure hot paths. Avoid blanket rules such as “never allocate” or “never use LINQ”; optimize confirmed per-frame/per-tick pressure.
- For batch operations, decide explicitly whether semantics are atomic, retryable, or best-effort.
- Keep balancing policy separate from infrastructure and compatibility mechanics where feasible.
- Record deliberate boundary violations with scope, reason, owner, tests, and a removal or reassessment trigger. A compatibility exception is controlled debt, not an invisible precedent.
- Never infer code quality, intent, or authorship ethics from balance choices or patch count alone.
- Write the deliverable in the user’s language unless the repository requires another language.
Deliverables
When planning or reviewing, return:
- verified environment and assumptions;
- selected mod profile and affected surfaces;
- design and dependency direction;
- save/compatibility/performance risks;
- implementation slices;
- validation matrix;
- unresolved decisions requiring the user.
When editing, also summarize changed files, checks actually run, and remaining limitations.