Pryaxis / orion-core

The next generation Terraria Server API.
https://pryaxis.github.io/orion-core
GNU General Public License v3.0
31 stars 12 forks source link

Discussion: Hot plugin loading + reloading #35

Closed hakusaro closed 7 years ago

hakusaro commented 7 years ago

From Slack, #orion-info, there was a discussion with some discrepancy on whether or not plugin hot reloading / reloading would be a part of Orion. According to @ProfessorXZ, @MarioE has stated this isn't going to be a feature, but @Enerdy said that the previous reason why we didn't have hotloading in the API was because of issues loading and reloading assemblies. In addition, @Enerdy pointed out that with injection, we should be able to do something similar to this.

So, @MarioE, and everyone in general (cc @NyxStudios/tshock), what's the status on plugin reloading / hot reloading in Orion as far as development targets go?

QuiCM commented 7 years ago

Anything loaded is added to the appdomain. The only way to truly unload is to kill the appdomain (and thus the process). So technically I believe you can remove bound types from the Ninject kernel (which handles our DI) and re-add modified versions, but any assemblies they came from will remain in the appdomain until it is destroyed. I.e., 'reloading' a plugin would result in multiple instances of it in the appdomain. Attempting to box plugins in their own domain would be infeasible due to Terraria's code architecture.

If any of the above facts are incorrect please correct me :)

tylerjwatson commented 7 years ago

If it got to a point with the SoA that you did not rely on anything in the Terraria namespace then technically all the services could implement MarshalByRefObject and use the .net marshalling proxy to communicate between AppDomain boundaries, and each plugin could run in its own AppDomain, alllowing for its removal at runtime.

The massive caveat is that if a plugin used anything in the Terraria namespace they would get an entirely new copy of the Terraria.Main statics and potentially a new instance of the gameserver.

Each plugin would need strict code review to ensure that its marshal by ref architecture was valid or else no plugin could ever interact with another plugin.

This has been asked a thousand times, and I believe that it's unfeasible because the underlying .NET binding loader just doesn't easily support what we are asking it to do.


Any tidbits that really justifies dynamic reloading could be easily acheived with scripting. I believe that we can add some pretty awesome scripting support so people can do server-based doodads without ever having to compile plugins.

Jist does this, but isn't documented. I had plans on building some sort of scripting support into Orion with a scripting host service.

You could load and unload server scripts at will.

Patrikkk-zz commented 7 years ago

I agree with Tyler. Although I'm not as experienced in the topic as him, I did play around with plugin reloading. I've got the the point where my plugin was completely re-loadable, using MarshalByRefObject. but - as @WhiteXZ already described above - I had issues accessing certain variables and objects from the Terraria namespace. Couldn't access TPlayer objects, due to them not being marked as Serializable, or inheriting MarshalByRefObject. So it is a fact that we cannot achieve it without injecting and modifying Terraria classes. So, in theory it should be possible and If anyone can get plugins to reload that would be Tyler and Luke :P

On the other note, having C# scripting is possible. I do have a plugin which does exactly that, complies plugins from source and reads them into the assembly. I was almost able to reload it too, by simply killing all references to the plugin instance, and simply rebuilding the source and loading it again into the assembly. But I've ran into an issue where it loaded references duplicate. (Didn't look into fixing it yet) I know we wouldn't want this kind of reloading for Orion, due to a server possibly having a lot of plugins and each time they get reloaded it would take space in memory (As White also mentioned) . Just dropping by my experiences regarding the topic.

Ijwu commented 7 years ago

I believe the general consensus on this is that it is too much word/infeasible to attempt to implement this. At first it was thought that Ninject may provide this capability but it was later debunked as there is no unloading of assemblies from an AppDomain and we've already gotten into what using multiple AppDomains means.

tylerjwatson commented 7 years ago

Perhaps we can redirect the conversation towards a scripting engine to go along with the plugin engine? Perhaps in a new issue?

Sent from my iPhone

On 11 Oct. 2016, at 8:25 am, Hussein Farran notifications@github.com<mailto:notifications@github.com> wrote:

I believe the general consensus on this is that it is too much word/infeasible to attempt to implement this. At first it was thought that Ninject may provide this capability but it was later debunked as there is no unloading of assemblies from an AppDomain and we've already gotten into what using multiple AppDomains means.

You are receiving this because you are on a team that was mentioned. Reply to this email directly, view it on GitHubhttps://github.com/NyxStudios/Orion/issues/35#issuecomment-252762499, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AExQwFNtI2Y2X7E8Ix4Pu2j9rsDI-xc8ks5qyrtkgaJpZM4KRcsE.

Ijwu commented 7 years ago

A scripting engine is a big conversation to have. I think redirecting that conversation to a new issue is a good idea, but I don't think it should have equal/more priority over the plugin engine at the moment since that's where we've built our infrastructure towards.

I believe it could be possible to switch gears to a scripting engine over a plugin engine and use that as our main extensiblility platform, but I think that a compiled plugin API offers more benefits. (Such as easier to package binaries and the full features of the IDE)

hakusaro commented 7 years ago

Closing issue and letting discussion happen on #37.