-
Notifications
You must be signed in to change notification settings - Fork 1
LeaderboardPackage
Location: snipe/packages/leaderboard/
This package implements a manager for multiple project-specific leaderboards that will be updated in real-time on events from game servers. The leaderboards are loaded and saved on the cache server with game server API available.
You can include this package into the game server with:
override function initModulesGame()
{
loadModules([
snipe.packages.leaderboard.GameModule,
]);
}
You can include this package into the cache server with:
loadModules([
snipe.packages.leaderboard.CacheModule,
]);
All the leaderboards are sorted by the "points" field of the record and must have a unique "id" field. The record can have any other fields with the limitation that they have to be correctly serializable and deserializable. The records do not have to be linked to users, you can have a clan leaderboard or something similar.
Let"s take a look at the process of using leaderboards.
We begin by initializing a new leaderboard on the cache server in the constructor of one of the project modules:
class TopModuleCache extends ModuleCache<CacheServerTest>
{
public function new(s: CacheServerTest)
{
super(s);
name = "top";
var module: snipe.packages.leaderboard.CacheModule =
server.getModule("packages/leaderboard");
module.init({
id: "user.global",
isDaily: false,
hasYesterday: false,
size: 100,
lowestFirst: false,
maintenanceFunc: null
});
}
// ...
}
You can see the various initialization parameters. A few of the more interesting are:
- "isDaily" will clear the leaderboard at the start of each day.
- "hasYesterday" will store the yesterday"s leaderboard contents separately with API access available.
- "maintenanceFunc" is a maintenance function that will run at the start of each day.
Note that you don"t have to initialize leaderboards during the cache server initialization if you don"t know yet which ones will you need. For example, if you want to have separate leaderboards for every language, you can initialize them on the first event. Subsequent calls to "init()" with the same ID given will result in silent failure.
Now that the leaderboard is ready, you can notify it each time the user rating changes from the game server:
class UserAttributesTest extends UserAttributesCore
{
public function new(s: ServerClass, u: UserTest)
{
super(s, u);
}
// HOOK: post-setting attribute
override function setPost(key: String, oldValue: Dynamic, value: Dynamic)
{
// update cached value
if (key == "rating")
ratingUpdated(value);
}
// rating updated
public function ratingUpdated(value: Int)
{
// update leaderboard
var module: snipe.packages.leaderboard.GameModule =
server.getModule("packages/leaderboard");
var ret = module.update("user.global", {
id: user.id,
level: user.level,
points: value,
name: user.name,
networkid: user.networkid,
networktype: user.networktype,
});
// update() returns true when the record enters the leaderboard
// notify client about it
if (ret)
client.notify({ type: "leaderboard.onEnter" });
}
}
In this part of the example we bind the rating update call to the user attributes post-set hook (assuming that the user rating is stored there). Notice that the user object passed to the "GameModule.update()" method contains more than the minimal "id" and "points" fields. Caching that information allows a quicker and simpler leaderboard access from the client. The "GameModule.update()" method returns true if the user enters the leaderboard, so we can use that to notify the client.
All that"s left now is the client request for receiving leaderboard data:
class TopModule extends Module<Client, ServerTest>
{
public function new(srv: ServerTest)
{
super(srv);
name = "top";
}
// call method from this module
public override function call(client: Client, type: String, params: Params): Dynamic
{
var response = null;
if (type == "top.get")
response = get(client, params);
return response;
}
// CALL: get users top
function get(c: Client, params: Params): Dynamic
{
var list = server.leaderboardModule.get("user.global");
return { errorCode: "ok", list: list };
}
}
The "GameModule.get()" method will return the array containing the leaderboard records. Note that to reduce the server load from leaderboard requests automatic game server caching is used and the leaderboard contents will be cached for a minute.
Also note that we accessed the leaderboard module through the "server.leaderboardModule" property instead of using "server.getModule()" API. For that to work you will have to initialize the "leaderboardModule" property on server start. This is commonly done to simplify and speed-up access to modules API.
This should be enough to get you going.