Injecting .NET into an embedded Python intepreter
If you are anything like myself then you probably often find yourself curious about testing crazy ideas out.
I enjoy gaming, simulation is a huge passion of mine. I've loved The Sims games since discovering the one in the 90s. I was curious to see what I could achieve in terms of modding the game.
In The Sims 4 you can extend game functionality via scripting. Unfortunately, the language in question is Python; which I loathe with every fibre of my being.
This initially dissuaded me from wanting to get involved, Python is in that group of languages to me that are popular but I have no idea why. Everything about its syntax, structure and style I detest. I just couldn't bring myself to script in it, I'd feel like I'm selling my soul.
After pondering this for a few hours I wondered if it might be possible to bypass Python. By using DLL injection; I can hook into the functionality exposed within Python itself.
It was at this point I decided to try inject a .NET Framework DLL into the process and use detours/hooking to intercept the Python function calls. (For a guidance on how to do this, check out this article on CodeProject Injecting .NET Assemblies Into Unmanaged Processes
I used the Windows API function GetProcAddress to obtain the offset to the functions needed in memory. From this, I was able to successfully intercept the Python initialisation procedure.
This provided me the ability to extend the scope of functionality available in the scripting API for The Sims 4 and also build a wrapper around game functionality to enable its use in C# and .NET.
The question anyone familiar with modding The Sims 4 might ask is, why bother? The answer; extensibility and my distaste for Python, I want to write mods in C# and .NET.
Once I had successfully extended the functionality of the scripting API I stumbled across a library which shook things up quite a bit!
It is a project under the MIT license which enables you to seamlessly integrate Python and .NET without IronPython . As in; it works with native C Python. This was key for me as I had no control over the Python version due to it being an existing runtime I am injecting into.
I assume the Python .NET project was never intended to be injected into processes; rather, you would use it to embed your own Python instance. To my luck though, through a gnawing curiosity; I was able to use it with my injected DLL.
I discovered that if I intercepted the Python initialisation of The Sims 4 and prevented the call from executing; I could simply plug Python .NET right in. And you know what? It worked!!
Now instead of merely hooking into Python and extending it with my own functions, I can execute anything within the .NET library in Python as well as use the well-built interfaces of Python .NET to write Sims 4 scripting API calls directly in the C# .NET application.
I have decided to work towards releasing this as some sort of Sims 4 scripting extender. The possibilities are endless in terms of how much we could extend capability and enrich mods for the game.
From making the graphics better, to changing hard-coded defaults like the eight person household limit and even introduce user-created worlds. The only requirement is knowledge of disassembly and the patience to reverse engineer these core game functions outside of the Python interpreter.
I plan to get a prototype finished for the scripting extender but until then, if you want to follow this project, keep an eye on the blog! There will be further posts with GitHub details when ready. Until then, I hope you found this subject fascinating!
Welcome to my blog! I'm a computer programmer, I develop software, games, make music. I write about various aspects relating to the development process, be it art, coding or even design.