-
Notifications
You must be signed in to change notification settings - Fork 0
PluginArchitecture
Boostcraft is strongly oriented around the use of plugins to augment, extend, or modify the behavior of the server. A plugin is a set of closely related event callbacks (or delegates) that are loosely coupled with the rest of the system.
Most of the server's game-level logic will be implemented in plugins or plugin-like modules -- the modules will differ from normal plugins only in that they are compiled into the base server for convenience. Plugins operate by connecting their delegates to various event slots which form the core of the Boostcraft system. Many events are raised by the receipt of client packets by Boostcraft's network layer, but plugins and other parts of the system can raise events as well. The firing and handling of events is the primary means of communication between components.
For reference see this badly illustrated diagram:

The section enclosed in the dashed bubble is the "core" of the system; the objects marked "Plugin" could represent either extension plugins or core components that are implemented as modules. Architectural details of the world state currently reside in the Cloud of Mystery.
Event handling is implemented with boost::signals2 and boost::asio. signals2 provides managed, thread-safe callback slots and asio allows asynchronous processing of i/o events in multiple threads.
In boostcraft each plugin is represented at runtime by an object of class Plugin. The Plugin class requires only a very simple interface:
- An
initializemethod for setting up the plugin. - A
destroymethod for performing any needed finalization. - Methods for querying the plugin for information about itself, e.g., name and version info.
The particular plugin's implementation of initialize is responsible for registering whatever callbacks it needs to begin performing its task.
The primary implementation of the Plugin interface will be PythonPlugin, an instance of which acts as the "glue" between Boostcraft and an extension written in Python. PythonPlugin::initialize runs the main .py file for the plugin and then calls a specially-named function in the module (possibly init).
From there it is a matter of the plugin's Python code interacting with the Boostcraft API. The details of this are still hazy, but the goal is to provide a clean, abstracted interface to the game world. "Abstracted" here means that irrelevant details like the existence of chunks, chunk generators, chunk servers, etc. do not bleed into the picture. A plugin should be able to request world.blockAt(x,z,y) and simply receive the block requested.
[Comment: the abstraction may need to be leaky at this point. What if
(x,y) is nowhere near any loaded chunk? A chunk must be fetched, and
possibly generated first. This would incur a small but non-negligible
delay. While the individual plugin may not care if it has to wait an
extra ten milliseconds for the call to world.block(x,y) to complete,
other plugins might: we are still bound by the restriction that only
one thread may be executing Python code at any time. Will a lengthy
call to the C++ API block Python callbacks in other threads?
This question should probably be addressed in general. I suppose it
would be reasonable to implicitly release the intepreter lock during
API calls that might not return instantly. It may be a good idea to
handle such calls asynchronously -- is this possible? That is, can we
suspend the state of a Python->C++ call, return from the C++ function
*without* returning into Python, and then later (once the operation
has completed) return to the Python code that made the call?
TODO: find out exactly how calls from Python to C/C++ extensions work
and to what extent we can manipulate them to "play nice" with multi-
threading.]