To make the server extensible without touching the source code of the core logics and also to make some existing logics configurable, we could implement a plugin system. I would like to describe my idea of such a system.
Plugin Points
A plugin point is something which collects all plugins of one defined plugin type.
We have to define several points where we execute all plugins of a defined plugin types of a point.
For some events we could actually define two points - one before with cancel flag, another one after some event happened.
Suggested Plugin Points
-
Chat/Whisper Message received
-
Chat Command received
-
Character created
-
Character deleted
-
Player.PlayerState changed, example cases:
- Player Entered Game
- Player Left Game
- Before saving player data
- Player Authenticated
- Trade finished
-
Object Added To Map
- Includes: Player Entered Map, Item Dropped, Monster added
-
Object Removed From Map
-
Attribute Value Calculation
-
Attribute Value Changed
- Includes: Level up, Stat Attribute increased, etc.
-
Object got killed
-
Object got hit
-
Object moved
-
Player talked to NPC
-
Item consuming/consume/consumed
-
Item sold to NPC
-
Item sold to other player through personal store
-
Item moving/moved
-
Item created
-
Item destroyed
-
Data initialization plugins
-
Network related plugin points:
- Before Send (Apply Encryption, Logging)
- Before Handle Received Messages (Apply Decryption, Logging)
- PacketHandler plugin
Plugin Types
Then we have to define interfaces for these plugin types. Some may have additional event arguments, but most will just need the Player object.
Usage?
It would make sense to have access to the plugin points through the GameContext. Example:
// we're in the CharacterCreateAction and want to call its plugin point, after the character got created:
player.Context.InvokePlugInPoint<ICharacterCreatedPlugIn>(plugIn => plugIn.DoSomething(player, character)); // InvokePlugInPoint iterates through all active plugins.
This is a more open implementation, since the code has direct access to the plugins. This could be hidden, but would be more complex to implement.
PlugIn Registration and Configuration
Another point is the registration and configuration of plugins. My idea is:
- Automatically collecting all available plugins by reflection at the start of the server
- We need a configuration for each plugin (active-flag, order of execution, etc.)
- If a new external plugin was added (no configuration exists), it should be inactive by default to prevent malicious plugins to be executed
- We save this configuration in the database. Configuration could take place over the admin panel interface.
- External plugins / assemblies:
- How to include?
- By adding a configuration for it?
- We could save external plugin assemblies in the database within their configuration
- Bonus: Wouldn't it be nice to have an editor in the admin panel, so we could develop and deploy plugins on-the-fly without restarting the server?
- By dumping an external assembly into a "plugins" folder?
- How to keep them compatible after an update?
- To group plugins by feature we could have a FeaturePlugIn which holds all plugins of a feature together. If a plugin belongs to a feature, its active-flag should also depend on the active-flag of the feature.
Move existing logic to plugins
As a last step, we could move some existing logic to plugins. Of course, core logic should be left alone.
Some ideas:
- generating item drops when monster got killed.
- adding experience to the player(s) when a monster got killed
- drop item from player when it died
- talking to NPCs
- item consume. There are already handlers which are defined in the ItemDefinition. Maybe this could be defined the other way around: A plugin could decide if it can handle the requested consumption of an item.
To make the server extensible without touching the source code of the core logics and also to make some existing logics configurable, we could implement a plugin system. I would like to describe my idea of such a system.
Plugin Points
A plugin point is something which collects all plugins of one defined plugin type.
We have to define several points where we execute all plugins of a defined plugin types of a point.
For some events we could actually define two points - one before with cancel flag, another one after some event happened.
Suggested Plugin Points
Chat/Whisper Message received
Chat Command received
Character created
Character deleted
Player.PlayerState changed, example cases:
Object Added To Map
Object Removed From Map
Attribute Value Calculation
Attribute Value Changed
Object got killed
Object got hit
Object moved
Player talked to NPC
Item consuming/consume/consumed
Item sold to NPC
Item sold to other player through personal store
Item moving/moved
Item created
Item destroyed
Data initialization plugins
Network related plugin points:
Plugin Types
Then we have to define interfaces for these plugin types. Some may have additional event arguments, but most will just need the Player object.
Usage?
It would make sense to have access to the plugin points through the GameContext. Example:
This is a more open implementation, since the code has direct access to the plugins. This could be hidden, but would be more complex to implement.
PlugIn Registration and Configuration
Another point is the registration and configuration of plugins. My idea is:
Move existing logic to plugins
As a last step, we could move some existing logic to plugins. Of course, core logic should be left alone.
Some ideas: