I’ve been playing Ludeon Studios’ RimWorld for the past year or so, my favorite sandbox game since burning out on Minecraft. Thanks to some mod API changes in the latest alpha, I decided to make my first foray into C# programming – and I’m having a blast.
RimWorld is apparently a bit like Dwarf Fortress only not as hardcore, though I never played that. It’s a bit like The Sims meets Dungeon Keeper or something. It’s a city builder survival strategy with really interesting combat (very deep, but also entirely optional if you’re the peaceful) and incredible “story-telling” details that make the game feel so much more organic and realistic – right down to the fact that your colonists can have a toe bitten off, get infected, need the leg to be amputated, then have a nervous breakdown and burn down a building (that actually happened on one of my play-throughs). But I’m not here to review the game, there are plenty of glowing praises out there for this fantastic title.
What I am here to say is that I’ve started modding on it. The game is INCREDIBLY mod-able. Just about every “thing” in the game – animals, walls, items, technology, emotions, etc. is it’s own XML definition – literally called a ThingDef – which has a bunch of properties attached to it. These properties range from the description and texture path to how much heat it generates. What really makes this mod API stand out though is two main things:
- The “comp” (presumably short for components) system which is basically an instruction for the game to attach logic to the thing. This is done by declaring an XML tag named the exact same as a C# class – a CompProperties declaration – that you’ve written, inheriting from a game-provided base class. The CompProperties class reads data from the XML node into it’s class fields for your assembly to work on. All CompProperties classes have at least one Comp class associated with it – but you can define as many as you want (overridden in the XML definition) – this Comp class is where your logic actually happens – every centisecond for example (assuming the game loop is not 100% saturated, which DOES happen in large bases). What makes this system particularly powerful is the ease of browsing and extending the base game code thanks to ILSpy and the capability to hook vanilla methods via the Harmony library.
- The “patch” system. Using xpath syntax, mods can dynamically search and replace (or inject/add and remove) any XML data. The patching
process is done after all of the XML def’s are loaded and flattened, so thanks to the power of xpath it becomes very easy for a mod to,
say, integrate it’s own item as a new fuel type in every thing that accepts fuel, even ones added by mods which you don’t know about. This is because fuel-consuming things are declared through standard XML delcaration thanks to the previously mentioned Comp system – they could just search for the CompProperties_Refuelable node under a certain path, which is specified by the core game, and add their own item def entry to the relevant child node.
These two things in tandem make for some pretty powerful mod capability. After messing around with Minecraft Forge and ASM hacking in Java for so long, I feel spoiled by RimWorld’s modding capability. I had never really looked at C# before either, I started really getting into it this week when I started modding RimWorld – and I don’t ever want to go back to Java. It just feel so much cleaner. And thanks to the tools available to RimWorld modders, I’ve already made some pretty funky progress in a mod that adds coal fuel which is 3x as potent as wood for fuel, and a coal scuttle that acts as a hopper for the fueled generator.
There’s a new game on Steam’s Early Access called Colony Survival that is also written in Unity with C# like RimWorld, and they want to support modding too which I’ve given my feedback on. Hopefully it can be made as easy and powerful as RimWorld.
After learning about how powerful and easy C# is through RimWorld modding I really can’t see myself wanting to go back to Java.