-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Chapter 2: Plugins and Modules
When I was learning the Ogre3D engine, the first concept I learned was the plugin. Everything is a plugin in Ogre's world. The author of Ogre abstracted the important interfaces such as file management, rendering engine, and scene manager into plugins. Users can simply re-implement that interface as a new plugin to replace the default plugin. For instance, you can replace the D3D rendering plugin with an OpenGL plugin to replace the renderer Ogre uses, and hot-swap it without recompiling or restarting the application.
In NoahGameFrame's world, a plugin is a container which organizes modules within it. The NFPluginManager class manages all plugins and modules.
In NoahGameFrame's world, all plugin names will be saved in a file named "Plugin.xml" located in the _Out/NFDataCfg/Debug or _Out/NFDataCfg/Release folders.
Let's look at an example:
<XML>
<GameServer>
<Plugin Name="NFKernelPlugin" />
<Plugin Name="NFConfigPlugin" />
<Plugin Name="NFGameServerPlugin" />
<Plugin Name="NFGameServerNet_ServerPlugin" />
<Plugin Name="NFGameServerNet_ClientPlugin" />
<Plugin Name="NFLogPlugin" />
<ConfigPath Name="../" />
</GameServer>
</XML>When we start the application with the args -d Server=GameServer ID=3, the application will load the plugins from the GameServer section that show above. In this example there are 6 plugins: NFKernelPlugin, NFConfigPlugin, NFGameServerPlugin, NFGameServerNet_ServerPlugin, NFGameServerNet_ClientPlugin and NFLogPlugin.
The arg "-d" means the application is started in daemon mode (Only supported on Linux/mac/Unix), the arg "ID=3" means the application's ID is 3.
So, who will load these plugins?
The NFCPluginManager singleton class handles it all. When the application started, the NFCPluginManager class will be created and starts loading all plugins listed in the "Plugin.xml" file.
Below is the code:
int main(int argc, char* argv[])
{
ProcessParameter(argc, argv);
NFCPluginManager::GetSingletonPtr()->Awake();
NFCPluginManager::GetSingletonPtr()->Init();
NFCPluginManager::GetSingletonPtr()->AfterInit();
NFCPluginManager::GetSingletonPtr()->CheckConfig();
NFCPluginManager::GetSingletonPtr()->ReadyExecute();
while (true)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
NFCPluginManager::GetSingletonPtr()->Execute();
}
NFCPluginManager::GetSingletonPtr()->BeforeShut();
NFCPluginManager::GetSingletonPtr()->Shut();
NFCPluginManager::GetSingletonPtr()->ReleaseInstance();
return 0;
}The function LoadPluginConfig will be called from in function NFCPluginManager::Awake(). LoadPluginConfig loads and parses the XML file. After that, the NFCPluginManager class will create a plugin instance for each plugin.
In Linux/Mac, a plugin is a .so file, but on Windows, it's a .dll file. To begin creating a new plugin for NoahGameFrame's world, we will copy the project from Tutorial1, it's the best and easiest way to start creating a new plugin.
We can know from the Tutorial1 that the simplest plugin includes three classes, the one is a class inheritance NFIModule and the other two are the classes that inherit the class NFIplugin.
The codes are below:
class Tutorial1 : public NFIPlugin
{
public:
Tutorial1(NFIPluginManager* p);
virtual const int GetPluginVersion();
virtual const std::string GetPluginName();
virtual void Install()
{
REGISTER_MODULE(pPluginManager, NFIHelloWorld1, NFCHelloWorld1);
}
virtual void Uninstall();
};
NFIHelloWorld1: public NFIModule
{
};
class NFCHelloWorld1 : public NFIHelloWorld1
{
public:
NFCHelloWorld1(NFIPluginManager* p);
virtual bool Init();
virtual bool AfterInit();
virtual bool Execute();
virtual bool BeforeShut();
virtual bool Shut();
protected:
};People who want to create an instance for one module, it's better to use the Macro REGISTER_MODULE to do this. By the way, if we want to use the other module we can find a module by their interface class's name, such as:
NFCHelloWorld1::AfterInit()
{
m_pKernelModule = pPluginManager->FindModule<NFIKernelModule>();
m_pHelloWorld1 = pPluginManager->FindModule<NFIHelloWorld1>();
};