Coder Social home page Coder Social logo

reloader's Introduction

RimWorld Reloader

A mod add-on for RimWorld that allows you to develop and patch code while the game is running

Reloader is a dll for developers. It was created with the frustration in mind that comes up if things don't work your way and you end up restarting RimWorld too many times.

So what do you need to do to get hot code reloading? The following steps are necessary to get started:

1) Clone/download this repo

All you need is the file 0Reloader.dll

Your mods directory

Reloader works its magic when you put the 0Reloader.dll into the same Assemblies folder as your own dll. You can either copy it in there and reference it from your project or you have it somewhere else and let the project copy it over to the Assemblies folder. It doesn't matter which way you choose.

Its job is to watch the Assemblies directory and search for changes in any of the dlls. When it detects that a dll has changed (time stamp AND dll version number must be different) it loads the dll in and patches the original methods with their new copies.

IDE Setup

To allow Reloader change your methods, you annotate the methods that you want to change with the Attribute ReloadMethod:

[ReloadMethod]
public void SomeMethod()

To do this, you need to import a reference to the Reloader.dll into the patch project. Not for any functionality, but only for the attribute.

Important: Before you go and build project, you need one last step. .NET will not load a dll if it has the same version number as a earlier dll it has loaded. So unless you increment your version every time you deploy you won't see any changes. So I recommend strongly to automate this in your project by using an extension (For Visual Studio, i.e. "Build Version Increment Add-in") or by following the steps in this Gist: https://gist.github.com/pardeike/c36c4007b2855bc85950b59ade935bac for the free Visual Studio Community edition.

Once you rebuild your mod (I recommend building right inside the Mods directory), Reloader will pick up the changes and patch the designated method in the running mod and you will see the effect immediately. You can even edit methods without loosing their state.

Once you are satisfied with your changes just remove the Reloader.dll, the reference to it and the method attributes. You should NOT ship any final mod with Reloader still in it!

TODO

I tried to get real AppDomain load/unloading to work but failed because if you do so, all communication with the second AppDomain has to be serializable and that means that a lot of method parameters and return types would could not be supported. It's simply too much hassle. Instead, Reloader simply loads more and more dlls into memory and uses Detours to point the original method to method1, method2, etc until you run out of memory.


Feedback

If you feel that you want to contribute, please go ahead and send me pull requests, file bugs or send suggestions. I want this to be a help to everyone in the community.


License

Free. As in free beer. Copy, learn and be respectful.

If you like what I do, please consider becoming a supporter at: https://www.patreon.com/bePatron?c=937205


Contact

Andreas Pardeike Email: [email protected] Steam: pardeike Twitter: @pardeike

reloader's People

Contributors

doctorvangogh avatar pardeike avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

reloader's Issues

Exception on load in version 1.2.2723, compiled Aug 11 2020

RimWorld 1.2.2723 rev661
Verse.Log:Message(String, Boolean)
RimWorld.VersionControl:LogVersionNumber()
Verse.Root:CheckGlobalInit()
Verse.Root:Start()
Verse.Root_Entry:Start()

Error while instantiating a mod of type Reloader.Reloader: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.MissingMethodException: void Verse.LongEventHandler.QueueLongEvent(System.Action,string,bool,System.Action`1<System.Exception>)
at (wrapper managed-to-native) System.Reflection.MonoCMethod.InternalInvoke(System.Reflection.MonoCMethod,object,object[],System.Exception&)
at System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters) [0x00002] in <567df3e0919241ba98db88bec4c6696f>:0
--- End of inner exception stack trace ---
at System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters) [0x00014] in <567df3e0919241ba98db88bec4c6696f>:0
at System.Reflection.MonoCMethod.DoInvoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x0007a] in <567df3e0919241ba98db88bec4c6696f>:0
at System.Reflection.MonoCMethod.Invoke (System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <567df3e0919241ba98db88bec4c6696f>:0
at System.RuntimeType.CreateInstanceImpl (System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Object[] args, System.Globalization.CultureInfo culture, System.Object[] activationAttributes, System.Threading.StackCrawlMark& stackMark) [0x00213] in <567df3e0919241ba98db88bec4c6696f>:0
at System.Activator.CreateInstance (System.Type type, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Object[] args, System.Globalization.CultureInfo culture, System.Object[] activationAttributes) [0x00095] in <567df3e0919241ba98db88bec4c6696f>:0
at System.Activator.CreateInstance (System.Type type, System.Object[] args) [0x00000] in <567df3e0919241ba98db88bec4c6696f>:0
at Verse.LoadedModManager.CreateModClasses () [0x00076] in <7b345446a85d4ed599f9c604ae61854b>:0
Verse.Log:Error(String, Boolean)
Verse.LoadedModManager:CreateModClasses()
Verse.LoadedModManager:LoadAllActiveMods()
Verse.PlayDataLoader:DoPlayLoad()
Verse.PlayDataLoader:LoadAllPlayData(Boolean)
Verse.<>c:b__6_1()
Verse.LongEventHandler:RunEventFromAnotherThread(Action)
Verse.<>c:b__27_0()
System.Threading.ThreadHelper:ThreadStart_Context(Object)
System.Threading.ExecutionContext:RunInternal(ExecutionContext, ContextCallback, Object, Boolean)
System.Threading.ExecutionContext:Run(ExecutionContext, ContextCallback, Object, Boolean)
System.Threading.ExecutionContext:Run(ExecutionContext, ContextCallback, Object)
System.Threading.ThreadHelper:ThreadStart()

Patching freezes game

I got the reloader to build by updating it to .NET 4.7.2 to match the Rimworld version, which fixes an missing reference caused by attempting to build against 3.5.

The reloader loads correctly (I see the logs in-game). When I try to reload my method, the game freezes and has to be killed.

I went back into the Reloader code and tried to fix the patching method by changing the Memory.cs class to the newer Harmony 2 Memory.cs, taking out all methods apart from WriteJump and GetMethodStart which are the only ones used in this project. I then had to add a reference to Mono.Ceil because that's what Harmony uses.

I compiled again, and exact same result. It imports and loads correctly into Rimworld, but patching freezes the game when calling WriteJump.

Do you know how I can fix this, or what is happening? I'm sure this project is not your focus, but if you could point me in the right direction I could try to fix this and create a pull request.

Edit:
More specifically, the entire game freezes permanently after the line
DetourHelper.Native.Apply(data);

in WriteJump in Memory.cs (taken from Harmony, here)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.