Plugin framework?

manu3d

Active Member
Contributor
Architecture
As I go through the Modding Guide, Modding API and Asset System pages I seem to understand that all code of a module or a mod gets loaded at startup. Is there a system to load code at runtime but not earlier? I.e. to allow the user to choose which mod/plugin to load?
 

Josharias

Conjurer of Grimoires
Contributor
World
SpecOps
Manu3d, when you create a world you select the modules you want to enable with the built-in UI. It is only when the world is created that systems inside your module are initialized. This allows a user to switch modules without exiting the game completely.
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
As Josharias says, modules are loaded at runtime, per game, with the selection of modules stored in the game.
 

manu3d

Active Member
Contributor
Architecture
Please pardon my thickness. When a game has been started and the initial selection of modules has been made, can the user still disable a module and/or enable a new one? Or does he need to start a new game for that?
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
A new game. This is partially a menu restriction - you can modify the modules a saved game uses by changing its manifest. The results of removing modules may not be desirable though.

Certainly you cannot enable/disable modules once in a game.
 

manu3d

Active Member
Contributor
Architecture
Is this by design? I mean, of course if a module brings in everything about a particular game mode it would make no sense disabling it while a game has started. But what if a module just brings in a new set of textures, more detailed/better animated mobs, perhaps a different HUD or a different way to render a weather system from the default one. Are this not modules and wouldn't be reasonable to be able to disable/enable them more or less at any time? Are these kind of things perhaps handled by a different system?
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
To be clear, by in game I mean when you have loaded a saved game/created a new game and are in the world. It is by design that modules are not changed at this point. To support this has a number of complexities particularly when you consider multiplayer, because if you are loading and unloading modules ingame you would be forcing clients to pause while they download new module at the very least. It also has implications for various optimisations taking advantage of knowing all the assets/prefabs/componentTypes/etc that may be involved in communications. Worst case is unloading and loading the same module and the hell this means for the class loader (you'ld have two copies of the same class loaded and in use, or even two different versions of the same class). Overall I don't feel there is a strong enough advantage to switching modules ingame compared to the complexity of supporting it.

Fundamentally there's no reason not to allow changing mods used by saved games from the main menu though. Gametypes is probably going too far, like you say. The implications depend on what is in the involved modules - modules that just have asset overrides are harmless to add and remove. Modules that introduce components will cause those components not to load when removed. Prefabs are all store in the game save so if a module introducing a prefab is removed that is no issue (actually, probably is an issue in a network game at the moment, but can be fixed). Blocks are probably the worst, since if the module defining a block is removed that block will be replaced with air wherever it was placed in the world. But changing modules is not dissimilar to updating to new versions of modules overall, and that is supported.

Additionally, for development it is possible to reload individual assets from exploded (not zipped/jarred) modules at runtime. So if you are working on a texture or mesh or UI you can immediately reload it in a running game. Likewise if you are running through an IDE in debug mode you can reload code at runtime, subject to the usual restrictions.
 

manu3d

Active Member
Contributor
Architecture
Thanks Immortius for the detailed reply. Generally speaking I understand and I agree with what you are saying. A few statements that picked my interest:

because if you are loading and unloading modules ingame you would be forcing clients to pause while they download new module at the very least.
Why would a module need to be -downloaded- when loading/unloading a module? I'd normally think a module is normally already downloaded and installed in the right place by the time the user attempts to enable it.

you'ld have two copies of the same class loaded and in use, or even two different versions of the same class
I believe this can be addressed by having one (or more) classloader per module and GC'ing the classloader(s) of a module before a replacement is loaded. OSGI framework implementations need to do this for their bundles lifecycle. But I completely agree with you it wouldn't have to happen in-game. It'd be fancy... but probably just that.

Blocks are probably the worst, since if the module defining a block is removed that block will be replaced with air wherever it was placed in the world.
I'd imagine a module defining new blocks could also be forced to define a default "fallback" block for this occurrence? I.e. a new type of stone could fallback into the default stone block?

So if you are working on a texture or mesh or UI you can immediately reload it in a running game.
That's interesting. How does that happen? Are there objects watching the asset folders or do you need to trigger it somehow? Is this documented somewhere?
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
Why would a module need to be -downloaded- when loading/unloading a module? I'd normally think a module is normally already downloaded and installed in the right place by the time the user attempts to enable it.
Modules are enabled on the server and every client. When a client connects to a server they are sent any modules they are missing that are active on the server, not any inactive modules. If you activate a module midgame, presumably you do that on the server and the enabling of that modules would be pushed to every client. There's no guarantee every client will have the module.

Obviously this is ignoring the possibility of client-side only modules (like skin packs). In theory we could have these, but I'm inclined to have the server determine the look and feel rather than allowing every client to determine their own look and feel and have players seeing different things to each other - this always bothered me in Minecraft. Could add support for this in the future - it would be restricted to codeless modules, because we certainly shouldn't encourage client-side mods with code.


I believe this can be addressed by having one (or more) classloader per module and GC'ing the classloader(s) of a module before a replacement is loaded. OSGI framework implementations need to do this for their bundles lifecycle. But I completely agree with you it wouldn't have to happen in-game. It'd be fancy... but probably just that.
Yeah, I know there are solutions in this space. It gets complex because of module dependencies, but it is theoretically doable. For now I've left it with a single, sandboxing class loader for all modules.


I'd imagine a module defining new blocks could also be forced to define a default "fallback" block for this occurrence? I.e. a new type of stone could fallback into the default stone block?
Yes. Slight complication is that the fallback information would have to be stored in the saved game because it won't be available otherwise, but nothing major blocking this. It is in my longer-term todo list.


That's interesting. How does that happen? Are there objects watching the asset folders or do you need to trigger it somehow? Is this documented somewhere?
At the moment you do it manually, with a console command. Java 7 does have support for watching files for changes, but I haven't pushed it that far yet. There's only commands for a couple of asset types at the moment (reloadSkin, reloadShader, reloadMaterial) but that can easily be addressed. Documented in the ingame console help.

Basically the asset system was designed from the ground up to support this, and it leverages the same core functionality that allows procedural asset creation, multiple filetype support and override support.
 

Marcin Sciesinski

Code ALL the Ages!
Contributor
World
Architecture
Having different assets used to display in the game is, I believe, quite necessary and should be not dictated by the server. Main use case might be - different resolution of textures. When you have a powerful computer, you wouldn't want to default to the worst texture quality to accommodate other players' weaker machines. I think it might be safe to assume, that you should be able to enable/disable "client-side-only" modules at will. These, not necessarily have to be codeless modules, as you might have a module that is reacting to some events that are normally not consumed/consumed by other systems and adds a HUD display based on that.
 

Skaldarnar

Development Lead
Contributor
Art
World
SpecOps
Having different assets used to display in the game is, I believe, quite necessary and should be not dictated by the server. Main use case might be - different resolution of textures. When you have a powerful computer, you wouldn't want to default to the worst texture quality to accommodate other players' weaker machines.
I think this would either need the permission of the server (as in survival/death-match/hide-and-seek gametypes viewwing restrictions by blocks/grass may be essential and shouldn't be easily overriden by clients) or the server itself could provide texture packs in higher-resolution (have resource packs with size suffix, e.g. WoodAndStoneResources32, WoodAndStoneResources128, ...).

I think it might be safe to assume, that you should be able to enable/disable "client-side-only" modules at will. These, not necessarily have to be codeless modules, as you might have a module that is reacting to some events that are normally not consumed/consumed by other systems and adds a HUD display based on that.
Again, for this kind of (additional) information displayed the server's permission should be required. Think of a thief stealing from your pockets (would give some kind of inventory changed event, but not necessarily a HUD notification (which could be added by a client for altering game experience.
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
Having different assets used to display in the game is, I believe, quite necessary and should be not dictated by the server. Main use case might be - different resolution of textures. When you have a powerful computer, you wouldn't want to default to the worst texture quality to accommodate other players' weaker machines. I think it might be safe to assume, that you should be able to enable/disable "client-side-only" modules at will.
Higher quality textures could alternatively be handled by having different qualities for the textures available in the standard modules, side-by-side. That said, quality levels is pretty much the one use case I that makes me consider it. What I do want to avoid is the issue where the server operator has skinned their server for a specific experience, but then connecting users don't get that experience because skins are determined client-side.

These, not necessarily have to be codeless modules, as you might have a module that is reacting to some events that are normally not consumed/consumed by other systems and adds a HUD display based on that.
I disagree with this - I know stopping cheating completely is impossible, but client side mod support makes it too easy. Specifically in the aim bot and informational space. Keeping logic server authoritative should shut down other exploits. But it will be pretty hard to enforce anyway, since someone can just change the code to disable any restrictions we have on modules running client side. Or build their cheat into the engine itself.
 

manu3d

Active Member
Contributor
Architecture
I understand the security concerns Immortius and Skaldarnar mention. However, to my knowledge, what happens on the client (and the way it is modified) is ultimately beyond the developer's control, i.e. mods rendering all blocks except valuable resources transparent. To develop a server-side permission system to prevent client-side mods from being loaded in my opinion will just trigger the creation of modified clients that bypass the server-side permission system.

Concerning the example you make Skaldarnar: no, the client doesn't have to be notified about a thief stealing from your pocket unless the steal action fails. Once the player opens the inventory -then- the server might or might not specifically point out to the player that something is missing. I.e. it could send a new inventory list and it would be up to the player to notice that something is missing. A client-side mod could indeed make a diff with a stored inventory and flag that something is missing. But this could be easily made useless if the server-triggered notification of the theft does occur all the times, but only when the inventory is opened or after a set number of seconds from the theft, whichever is first. Admittedly this is a very concrete and specific example. Perhaps there are situations where these issues would be more difficult to deal with.
 

manu3d

Active Member
Contributor
Architecture
What I do want to avoid is the issue where the server operator has skinned their server for a specific experience, but then connecting users don't get that experience because skins are determined client-side.
I think this could be solved by having the server, upon connection with it, offer the appropriate texture pack(s) for download. The client can compare it with the one in use and those already downloaded. If the appropriate pack is already in use nothing happens. If it is already available on the client it would ask the user if he/she wishes to switch to it. If it hasn't been downloaded yet it would ask the user if it wants to download it and switch to it. I guess the same could be said for other types of assets.
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
I understand the security concerns Immortius and Skaldarnar mention. However, to my knowledge, what happens on the client (and the way it is modified) is ultimately beyond the developer's control, i.e. mods rendering all blocks except valuable resources transparent. To develop a server-side permission system to prevent client-side mods from being loaded in my opinion will just trigger the creation of modified clients that bypass the server-side permission system.
Correct. There's no way to enforce it or stop it. Doesn't mean we should encourage it. Having to use a modified client raises the bar of entry significantly from the "download cheat and drop into modules folder" technique that would otherwise exist.

I think this could be solved by having the server, upon connection with it, offer the appropriate texture pack(s) for download. The client can compare it with the one in use and those already downloaded. If the appropriate pack is already in use nothing happens. If it is already available on the client it would ask the user if he/she wishes to switch to it. If it hasn't been downloaded yet it would ask the user if it wants to download it and switch to it. I guess the same could be said for other types of assets.
Yes. Or to make it smoother, there could be a Use HQ Assets option in the settings, and this determines whether HQ asset modules are downloaded and activated for clients (or just activated in single player games).
 
Top