Adding modding capabilities to my C# game
Here's a somewhat strange question that may just not have an answer.
I'm working on a project where I'd like to have the game be moddable in sorta the same way Minecraft is, where the modder can create a Mixin class of an existing Minecraft class, and then add or replace code of that class. I'd like to go about it in a way that's natively supported by my game, which is also going to be open-source, and I'd prefer to not get an answer that's just "use interfaces and reflection", as that's not very freeing for what the user can actually change about the core game, only allowing additions to aspects of the game that use interfaces, rather than being able to add to or replace any code in the game.
For the record, my game does not use a game engine, so suggestions about MelonLoader for Unity are off the table.
15 Replies
Well, the way Minecraft is modded is via the mod loaders like forge/fabric etc, and they are actual source changes to a decompiled Minecraft
Yes, I know this lol. But it's the same concept.
Sure. So write your own mod loader
Yeah but I'm essentially asking for how I'd do that.
Honestly, take a look at forge or fabrics source to get an idea of the core concepts. You'll want any content in the game to be extendable so any place where you load resources into memory or build lists, it should be possible to add to them externally.
As for how to load externally compiled dlls, that part you do handle with reflection and interfaces. https://github.com/Remora/Remora.Plugins is an example of how you'd do that
You'd only put your mods init functions in the interface, and they'd interact with your built-in modloader within those methods
I was suspecting that they do edit bytecode, and I do have some experience in that front, but I doubt that's a route I can take natively in my app.
Also I specified I didn't wanna take the reflection + interfaces route as it's not very versatile in what the modder could do with it. I'd want the modders to be able to edit anything they want with nearly zero limitations
You misunderstand. You use reflection to load the plugins not what they do,
Still I don't think those are things I can do at runtime.
I see what you mean now, a IPlugin interface that gets 'Assembly.Load'ed, but that doesn't really answer the question on how I'd get the plugins to actually be able to edit anything.
Like say I have 48 characters that all implement a base character class, I'd want to be able to edit that character class, and each character individually.
Also not using Mono lol
Looks like the name MonoMod is kinda misleading, and it does work on framework
Effect on game performance only when mods are enabled sounds like an okay trade-off to me. But idk how easy that would be to use both to account for in my game, and to mod for. So I'll have to look into it.
and I don't really update .NET lol
I'm already limited with the renderer I'm using lol
Stuck on Windows 🙏
Well my game wouldn't really be moddable at all if I went with interfaces
There's zero possibility to do what I'd want with that
Unless I like, did 50 reflection calls every 5 lines of code
But that also wouldn't allow for multiple mods at once if I did the... 50 reflection calls every 5 lines of code lol
Yeah but there's no way to do pre/post method hooks in an elegant way unless your entire codebase is structured specifically around being able to do that. Which doesn't make for a very enjoyable game developing process.
Best you could do is a fuck-load of static eventhandlers everywhere
To be honest, at this point, slapping an MIT license on the source code and just letting it fly seems like the best course of option.
It's a shame though, a mod-loader would've been so much cooler, alongside the ability to have multiple mods at once
Have those characters be in some kind of registry, where they can be removed and replaced by mods. The classes should be open for extensions, probably via virtual methods etc, so a modder can base their replacement on one of the base characters
That's definitely a possibility with how my code is setup, but that's still only a small part of the game. Not very expansive in the grand scheme on things.
I don't think you can have your cake and eat it too
Either design your game from the ground up for modability, or just allow source/binary mods that will have compatibility issues
adding those hooks everywhere is almost guaranteed to be worse for performance than RuntimeDetour is
like I'd just use RuntimeDetour personally
it does pretty much everything you need to with so much less work
all you really lose is being able to (very easily) patch generics, which is a semi-rare want in the first place, and native arm64 support (but emulation still works fine, and that should be fixed at some point™️)
GitHub
GitHub - Reloaded-Project/Reloaded-II: Universal .NET Core Powered ...
Universal .NET Core Powered Modding Framework for any Native Game X86, X64. - Reloaded-Project/Reloaded-II
You make everything interfaces, and let plugins substitute the implementations.
It ain't hard.
The only time people use things like Detours, or Harmony, or other runtime mods, etc, is when the original app isn't built with a plugin model.
:spinthink:
I've never had that problem
I don't even know exceptions are thrown on startup in mm