Sign in to follow this  
EmpireProductions

Server Plugins

Recommended Posts

I am trying to make it possible to add plugins to my server for the different game features (guild plugin, combat plugin, inventory plugin, ect). I would like to be able to add new plugins on the fly with out having to restart the server and I would like to be able to update plugins with out a server restart. what is the best way to go about doing this? I currently have a very basic plugin system in place that doesn't use COM. The one I am currently using I got from here: http://www.abstraction.net/ViewArticle.aspx?articleID=67

Share this post


Link to post
Share on other sites
What language? What OS?

In C++, you can write a .dll or .so, and load it using LoadLibarary()/dlopen(). If you make the magic incantations when building your DLL it can support being unloaded. This means that you could unload the DLL, replace it (on Windows, you can't overwrite a loaded DLL) and then re-load it. It may be possible to do the same thing on Linux, too, although I can't think off-hand of how to do it without leaking address space (effectively loading multiple copies of the same thing).

To actually expose the API from the plug-in, you expose one or more C-callable functions. You can expose the entire API as C-callable functions, and find them by known name. Or you can expose only a single function, and return an instance of a known class (typically, a pure abstract bass class).

// the public API
class MyServer {
public:
virtual void SomeService(void *) = 0;
};

class MyPlugin {
public:
virtual void Start(MyServer *svr) = 0;
virtual void Stop() = 0;
virtual void SomeNotification(char const *) = 0;
};

extern "C" {
// for MSVC, the __ bits are needed
__declspec(dllexport) MyPlugin *MakePlugin();
}


// your plugin implementation
class CPlugin : public MyPlugin
{
public:
...
};

// for MSVC, the __ bits are needed
MyPlugin *MakePlugin()
{
return new CPlugin();
}


There are some other, bigger problems you have to solve, though. For example, what do you do with data structures that the plug-in has already allocated, when the plug-in is unloaded? Do players get disconnected from the guild system? Do mobs stop combat? Do mobs de-spawn, and then re-spawn?

In general, it's probably better to write things at this level using a scripting language that supports dynamic replacement. Re-importing a module in Python, re-loading a script in Lua, etc, would probably be easier to deal with. Also, the duck (late/dynamic) typing of these languages makes it easier to work with a objects in the game created by different versions of a plug-in.

Share this post


Link to post
Share on other sites
Quote:
Original post by ARC inc
wouldn't a COM system work a little better for this?


JVM would work best, since it takes care of dynamic class reloading and all that class loader magic that allows applications to be replaced while running. See JBoss or similar. At least if trying to compromise on "simplicity" and development time.

Otherwise, scripting language. javascript via v8 is a nice alternative to those already mentioned. See also Opera and node.js servers.

Last option involves anything done in C, but is hard to find a reasonable scenario where this would still be justified, there's just so many compelling alternatives available today.


But, as long as the actual data store is reliable enough and bandwidth/startup/shutdown costs are not major concern, running scripts as stateless or transient-state services might be the simplest solution. When you need to upgrade, just start up new ones, and let old ones expire, or terminate them. This is similar to JVM, but is not limited to single process, and can be done in any language, even using different ones for different nodes, as long as data store access is available.


This is one fairly big argument for using ad-hoc key-value stores, which allow structure to be modified as needed. This way, even if structure changes, there is no need to restart database server as would be the case with SQL.

There are different gotchas with such approach, but up to some middle (whatever that means) scale it tends to work adequately.

Share this post


Link to post
Share on other sites
Actually, key/value stores can scale out (wide) better than SQL, because you simply can't write serial processing a la SQL on top of that. Especially if the key/value is really a large tuple, similar to BigTable or SimpleDB. Couple it with a map/reduce implementation, and you can build parallel processing that scales very wide.
The key here is having publicly accessible properties that each is indexed separately. A "dumb" key/value store that has a single key and maps to a serialized blob is not very useful.
However, there are some things you lose being able to do in such an environment. Generally, you'll probably end up also extracting whatever goes into the tuple table and sticking it in a parallel SQL table for those tasks, and have to accept the latency of ETL in that case.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this