Yes, you should use your mod heartbeat, for timestamping. Once you have a timestamping setup, you can use it as a low-impact command-delay mechanism that is much more cpu-efficient than actual delaycommands.
Boot time is recorded on modload:
/* load boot time into the boottime variable */
SQLExecDirect("SELECT UNIX_TIMESTAMP()");
if (SQLFetch() == SQL_SUCCESS) {
string sBootTime = SQLGetData(1);
string sServerAddr = FileReadAll("serveraddr.txt");
string sServerPort = FileReadAll("serverport.txt");
if (StringToInt(sServerPort) < 5000)
sServerPort = "512" + IntToString(nServerNumber % 10);
SetLocalInt(oMod, "boottime", StringToInt(sBootTime));
SetLocalString(oMod, "ServerAddr", sServerAddr);
SetLocalString(oMod, "ServerPort", sServerPort);
SQLExecDirect("REPLACE INTO server_list (srv_id, srv_btime, srv_utime, srv_memory, srv_players, srv_addr, srv_port, srv_last) VALUES ('"
+ sServerNumber + "', " + sBootTime + ", 0, 0, 0, '" + sServerAddr + "', " + sServerPort + ", NOW())");
}
SetLocalInt(oMod, "uptime", 0);
Uptime is then calculated from the mod heartbeat:
SQLExecDirect("SELECT UNIX_TIMESTAMP() - " + sBootTime + ", UTC_TIMESTAMP(), UNIX_TIMESTAMP(), " +
"COUNT(*) FROM user_messages WHERE um_recipient = '*" + sServer + "'");
if (SQLFetch() == SQL_SUCCESS) {
nUptime = StringToInt(SQLGetData(1));
nMessages = StringToInt(SQLGetData(4));
SetLocalInt(oMod, "uptime", nUptime);
SetLocalInt(oMod, "realtime", StringToInt(SQLGetData(3)));
SetLocalString(oMod, "utctime", SQLGetData(2));
SQLExecDirect("UPDATE server_list SET srv_utime = " + IntToString(nUptime) + ", srv_memory = " +
IntToString(nMemory) + ", srv_players = " + IntToString(nPlayers) + " WHERE srv_id = '" + sServer + "'");
SQLExecDirect("SELECT COUNT(*) FROM user_list WHERE u_active > 0");
if (SQLFetch() == SQL_SUCCESS)
SetLocalInt(oMod, "GlobalPlayers", StringToInt(SQLGetData(1)));
SQLExecDirect("SELECT COUNT(*) FROM user_list WHERE u_active > 0 AND u_server_name REGEXP '" + GetStringLeft(sServer, 1) + ".[1-8]'");
if (SQLFetch() == SQL_SUCCESS) {
int nHubPlayers = StringToInt(SQLGetData(1));
SetLocalInt(oMod, "HubPlayers", nHubPlayers);
if (GetStringLeft(sServer, 1) != "1" && GetStringRight(sServer, 1) == "1")
SetNumberOfPlayers(nHubPlayers);
}
}
Much more accurate than simply incrementing. Note that a lot of the above code is linked to our interserver messaging and other functionality - the setting of the time ints is the critical part.
You can then use that to set timestamped events. By way of example, we despawn areas to prevent unkilled critters from lagging up the server, among other reasons, but wanted to prevent abuse. Doing so required tracking times and respawning loot and such only after a set interval, when the encounters would also be back. Done with delaycommands, it would mean hundreds or even thousands of delays running modwide, depending on traffic. Done with timestamps, it means nothing running until it needs to be checked. Our areas are checked when a player enters them, and reset if necessary:
/* respawn loot or other other respawnables */
nSpawns = GetLocalInt(oArea, "Area_Respawns");
if (nSpawns > 0) {
int i, nType, nRespawnTime, nUptime = GetLocalInt(GetModule(), "uptime");
string sKey, sVar;
object oSpawn;
for (i = 1; i <= nSpawns; i++) {
sKey = IntToString(i);
nRespawnTime = GetLocalInt(oArea, "Area_Respawn_" + sKey);
if (nRespawnTime <= 0 ||
nRespawnTime > nUptime ||
GetIsObjectValid(GetLocalObject(oArea, "Area_Respawn_Obj_" + sKey)))
continue;
oSpawn = CreateObject(GetLocalInt(oArea, "Area_Respawn_Type_" + sKey),
GetLocalString(oArea, "Area_Respawn_Res_" + sKey),
GetLocalLocation(oArea, "Area_Respawn_Loc_" + sKey));
SetLocalObject(oArea, "Area_Respawn_Obj_" + sKey, oSpawn);
if ((sVar = GetLocalString(oArea, "Area_Respawn_Var_" + sKey)) != "")
AssignCommand(oArea, DelayCommand(0.0, RestoreLocals(oSpawn, sVar)));
}
}
/* clear despawn setting on area */
if (GetLocalInt(oArea, "DespawnTrack")) {
int nDespawnTime = GetLocalInt(oArea, "DespawnTime");
if (nDespawnTime) {
int nUptime = GetLocalInt(GetModule(), "uptime");
if ((nUptime - 3600) > nDespawnTime) {
DeleteLocalInt(oArea, "DespawnTime");
DeleteLocalInt(oArea, "DespawnCount");
}
}
}
Funky