We consider this base framework experimental and very few plugins use it at the moment. There are of course both advantages and disadvantages with its design. There's absolutely no documentation for it, so I understand if it's hard to learn how it works. I was confused myself when I first saw it, but once I got used to it, everything seems logical. Some documentation would probably help give a quicker and less confusing start with a guided introduction to all its features.
What I really like about this base is its framework (whether its architecture is a single plugin or many plugins doesn't really matter now). Not whether stuff gets modular and independent.
This base is more than just registering modules and forwarding events to them. It's a complete manager that takes care of, or simplifies several tasks. It's a layer of abstraction between SM and our code. Obviously, it's meant to be used in bigger and complex plugins. It's for those who make a mod/game (like ZR or THC RPG) or something bigger than a single feature. Using it for small features would just make it bloated.
In the base, modules can register dependencies so when a module is disabled, its events will be blocked. It's also recursive so dependent modules are also disabled. Events can be prioritized, blocked and filtered for individual modules. This is exactly what we need when developing Zombie:Reloaded. It perfectly suits
our needs.
It would also be possible to put everything in separate plugins. The base would be a management plugin that provides natives for registering modules (plugins) and events. In addition it would need to isolate plugin collections from each other if there are two big collections enabled at once (like ZR and THC RPG), so their event priority and filtering will work properly. It would probably need to introduce some kind of plugin grouping where each module (plugin) have to identify which group it belongs to when calling every native. This design would be pretty interesting. The base is much less complex when it's all compiled to a single plugin binary, compared to dealing with multiple sets of plugins at once - and worst of all; backwards compatibility.
Quote:
Originally Posted by ProdigySim
Maintainability: Some module is exhibiting buggy behavior, or is crashing. The module cannot be isolated from the rest of the code for testing.
|
Actually it can. Everything else can easily be entirely disabled by commenting lines in two places; where they're included, and where the OnPluginStart forward is passed to modules. When the plugin is compiled, disabled modules won't even be compiled.
The module might have dependencies (even complex ones) so it can't function without other stuff, which again may have other dependencies. Though you'd get the same problem if modules were separate plugins depending on other modules.
The only thing I agree with is crashing. If a module in our base throw an error while in a event callback, the entire event chain is killed, so other modules won't get the event. This might cause a crash cascade in worst cases.
Quote:
Originally Posted by ProdigySim
Reusability: If I like a chunk of your code, and want to place it in my project or use it as a standalone plugin, I either have to bring the whole project base with me or spend a lot of time trying to decipher function calls and/or execution flow to make things work on its own.
|
The idea
is to bring the base with you (actually building your entire plugin on the base), so features can be exchanged between such plugins. If made as a separate plugin, deciphering execution flow would be trivial because base events are pretty much equal to real forwards and event hooks. Reading a module's code is essentially the same as reading a simple plugin's code, with forwards/event hooks and other functions.
The exception is custom events within the plugin, but that's a dependency issue we can't get away with no matter what architecture we use. Initially we try to design modules (in ZR) with as few dependencies as possible. Usually the modules have optional dependencies where it detects if another module is available or not so it can function with and without it.
Porting features between plugins on different architectures obviously can't be done with a single copy and paste - but if they're on the same architecture (like both using our base) it would be quite trivial sharing features between plugins.
I don't think this base will be dominating in future SourceMod plugins, but I'm pretty sure it will be a good inspiration for designing a new architecture.
One thing I don't like about separating features in individual plugins is when they need to communicate (through natives and forwards). It's about security. The advantage is that it's very easy to extend features by hooking into their events/forwards and call their natives for commanding them to do stuff. But it's
too easy mess with features like that. What if a two features need to communicate with each other (through natives), and only those two? Other plugins could call those "private" natives and mess with stuff it's not supposed to touch at all, and possibly corrupt states in features. If all features are compiled into a single plugins, it's much easier to protect features by deciding which parts to expose in the public API.
What would be really cool is if we had a common way to organize stuff in plugins so that features from other plugins could be literally copy-pasted and work. As Greyscale is explaining, that's one of the goals with this experimental base. In theory it works great, but in reality it's just not that easy.
(Sorry if I'm a bit detailed. I speak for everyone at any skill level.)
__________________