-
Notifications
You must be signed in to change notification settings - Fork 0
SlaveServerModules
Slave server modules will contain the majority of game logic for any project. Slave server modules are bound to a specific type of slave server. Apart from some special cases the module code will run in the main thread of a slave server. Therefore it should run fast enough not to clog this thread. Any client requests that may have a long execution time should be made asynchronous with work pushed to separate threads. In general, the slave server module API closely resembles cache server module API and the contents of this page mimic the Cache Server Modules page. The functionality provided by the core modules will be described in the sections for proper game modules.
Two additional APIs are not described on this page: module subscriptions and editor notifications. They are described in detail on Subscriptions and Editor Notifications pages.
The first thing you need to do is create a module class. It should extend the parametric Module
class supplying your client and slave server classes as parameters. Nothing is required beyond that. Here is the minimal example:
package modules;
import snipe.lib.Params;
class TestModule extends snipe.slave.Module<ClientTest, ServerTest>
{
public function new(srv: ServerTest)
{
super(srv);
name = "test";
}
}
The most important thing here is the module name. All client requests are routed using module name, more on that below in the call()
section.
Now we need to add a call to load the module into the server during initialization. This is done in initModules()
method with this call:
public override function initModules()
{
loadModules([ modules.TestModule ]);
}
Note that project modules are initialized after the core modules so all functionality from core modules is available to them.
Also note that in case of game server you should override initModulesGame()
instead.
If your module requires the loading of some external data like database tables, you can do it in loadTables()
hook like this (just as an example):
var _list: Map<String, TestType>;
override function loadTables()
{
_list = new Map<String, TestType>();
var res = server.query("SELECT * FROM TestTable ORDER BY ID");
for (row in res)
{
var obj = {
id: row.id,
data: row.data,
};
_list.set('' + row.id, obj);
}
}
loadTables()
method is called in the constructor for Module
class. If you want to have a module that does some initialization that depends on the data loaded in another module, you cannot do this in loadTables()
because the other module may not be loaded at that point. For that you can use the initPost()
hook.
public override function initPost()
{
// some additional initialization
}
The internal call order of slave server initialization is this:
initCoreModules();
initModules(); // game server calls initModulesGame() in the end
for (m in _modules)
m.initPost();
Note that each slave server thread in a metaserver will initialize separately from others.
Handling client requests will require using call()
hook. Each time the client sends a request to slave server, the request handler decides what module to pass the message to by the module name and calls the call()
method of this module with message parameters as an argument. The request type format is "<module>.<name>".
Example slave server code to handle requests:
public override function call(client: ClientTest, type: String, params: Params): Dynamic
{
var responce = null;
if (type == "test.call1")
responce = call1(client, params);
return responce;
}
public function call1(c: ClientTest, params: Params)
{
var var1 = params.getInt('var1');
// request handling
return { errorCode: "ok" };
}
}
Sometimes you need to make some of the module methods a part of your internal project API. There are two ways to get access to module as a variable. The first method is to simply use server.getModule()
call each time you need to make an API call, which is not that convenient:
var testModule: modules.TestModule = server.getModule('test');
var ret = testModule.apiCall();
The second method involves setting up global module links in the server class itself in the initModules()
(or initModulesGame()
in case of game server) method:
import snipe.slave.Server;
class ServerTest extends Server
{
// ...
public var testModule(default, null): modules.TestModule;
public override function initModules()
{
loadModules([ modules.TestModule ]);
testModule = getModule('test');)
}
// ...
}
Now that the link is set up, you can call public methods like this:
var ret = server.testModule.apiCall();
You can note that Server
and ServerGame
classes have a lot of links to core modules that provide API.