mirror of
https://github.com/shavitush/bhoptimer.git
synced 2025-12-07 10:28:26 +00:00
add playtime tracking
This commit is contained in:
parent
6818151c4b
commit
670f220b76
@ -88,17 +88,18 @@ enum
|
||||
Migration_RemoveWorkshopPlayertimes,
|
||||
Migration_LastLoginIndex,
|
||||
Migration_RemoveCountry,
|
||||
Migration_ConvertIPAddresses,
|
||||
Migration_ConvertIPAddresses, // 5
|
||||
Migration_ConvertSteamIDsUsers,
|
||||
Migration_ConvertSteamIDsPlayertimes,
|
||||
Migration_ConvertSteamIDsChat,
|
||||
Migration_PlayertimesDateToInt,
|
||||
Migration_AddZonesFlagsAndData,
|
||||
Migration_AddZonesFlagsAndData, // 10
|
||||
Migration_AddPlayertimesCompletions,
|
||||
Migration_AddCustomChatAccess,
|
||||
Migration_AddPlayertimesExactTimeInt,
|
||||
Migration_FixOldCompletionCounts, // old completions accidentally started at 2
|
||||
Migration_AddPrebuiltToMapZonesTable,
|
||||
Migration_AddPrebuiltToMapZonesTable, // 15
|
||||
Migration_AddPlaytime,
|
||||
MIGRATIONS_END
|
||||
};
|
||||
|
||||
|
||||
@ -3101,6 +3101,7 @@ void ApplyMigration(int migration)
|
||||
case Migration_AddPlayertimesExactTimeInt: ApplyMigration_AddPlayertimesExactTimeInt();
|
||||
case Migration_FixOldCompletionCounts: ApplyMigration_FixOldCompletionCounts();
|
||||
case Migration_AddPrebuiltToMapZonesTable: ApplyMigration_AddPrebuiltToMapZonesTable();
|
||||
case Migration_AddPlaytime: ApplyMigration_AddPlaytime();
|
||||
}
|
||||
}
|
||||
|
||||
@ -3167,6 +3168,21 @@ void ApplyMigration_AddPrebuiltToMapZonesTable()
|
||||
gH_SQL.Query(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_AddPrebuiltToMapZonesTable, DBPrio_High);
|
||||
}
|
||||
|
||||
// double up on this migration because some people may have used shavit-playtime which uses INT but I want FLOAT
|
||||
void ApplyMigration_AddPlaytime()
|
||||
{
|
||||
char sQuery[192];
|
||||
FormatEx(sQuery, 192, "ALTER TABLE `%susers` MODIFY COLUMN `playtime` FLOAT NOT NULL DEFAULT 0;", gS_MySQLPrefix);
|
||||
gH_SQL.Query(SQL_Migration_AddPlaytime2222222_Callback, sQuery, Migration_AddPlaytime, DBPrio_High);
|
||||
}
|
||||
|
||||
public void SQL_Migration_AddPlaytime2222222_Callback(Database db, DBResultSet results, const char[] error, any data)
|
||||
{
|
||||
char sQuery[192];
|
||||
FormatEx(sQuery, 192, "ALTER TABLE `%susers` ADD COLUMN `playtime` FLOAT NOT NULL DEFAULT 0 AFTER `points`;", gS_MySQLPrefix);
|
||||
gH_SQL.Query(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_AddPlaytime, DBPrio_High);
|
||||
}
|
||||
|
||||
public void SQL_TableMigrationSingleQuery_Callback(Database db, DBResultSet results, const char[] error, any data)
|
||||
{
|
||||
InsertMigration(data);
|
||||
@ -3393,14 +3409,14 @@ void CreateUsersTable()
|
||||
if(gB_MySQL)
|
||||
{
|
||||
FormatEx(sQuery, 512,
|
||||
"CREATE TABLE IF NOT EXISTS `%susers` (`auth` INT NOT NULL, `name` VARCHAR(32) COLLATE 'utf8mb4_general_ci', `ip` INT, `lastlogin` INT NOT NULL DEFAULT -1, `points` FLOAT NOT NULL DEFAULT 0, PRIMARY KEY (`auth`), INDEX `points` (`points`), INDEX `lastlogin` (`lastlogin`)) ENGINE=INNODB;",
|
||||
"CREATE TABLE IF NOT EXISTS `%susers` (`auth` INT NOT NULL, `name` VARCHAR(32) COLLATE 'utf8mb4_general_ci', `ip` INT, `lastlogin` INT NOT NULL DEFAULT -1, `points` FLOAT NOT NULL DEFAULT 0, `playtime` FLOAT NOT NULL DEFAULT 0, PRIMARY KEY (`auth`), INDEX `points` (`points`), INDEX `lastlogin` (`lastlogin`)) ENGINE=INNODB;",
|
||||
gS_MySQLPrefix);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
FormatEx(sQuery, 512,
|
||||
"CREATE TABLE IF NOT EXISTS `%susers` (`auth` INT NOT NULL PRIMARY KEY, `name` VARCHAR(32), `ip` INT, `lastlogin` INTEGER NOT NULL DEFAULT -1, `points` FLOAT NOT NULL DEFAULT 0);",
|
||||
"CREATE TABLE IF NOT EXISTS `%susers` (`auth` INT NOT NULL PRIMARY KEY, `name` VARCHAR(32), `ip` INT, `lastlogin` INTEGER NOT NULL DEFAULT -1, `points` FLOAT NOT NULL DEFAULT 0, `playtime` FLOAT NOT NULL DEFAULT 0);",
|
||||
gS_MySQLPrefix);
|
||||
}
|
||||
|
||||
|
||||
@ -51,6 +51,13 @@ int gI_Track[MAXPLAYERS+1];
|
||||
int gI_TargetSteamID[MAXPLAYERS+1];
|
||||
char gS_TargetName[MAXPLAYERS+1][MAX_NAME_LENGTH];
|
||||
|
||||
// playtime things
|
||||
float gF_PlaytimeStart[MAXPLAYERS+1];
|
||||
float gF_PlaytimeStyleStart[MAXPLAYERS+1];
|
||||
int gI_CurrentStyle[MAXPLAYERS+1];
|
||||
float gF_PlaytimeStyleSum[MAXPLAYERS+1][STYLE_LIMIT];
|
||||
bool gB_HavePlaytimeOnStyle[MAXPLAYERS+1][STYLE_LIMIT];
|
||||
|
||||
bool gB_Late = false;
|
||||
|
||||
// timer settings
|
||||
@ -60,6 +67,8 @@ stylestrings_t gS_StyleStrings[STYLE_LIMIT];
|
||||
// chat settings
|
||||
chatstrings_t gS_ChatStrings;
|
||||
|
||||
Convar gCV_SavePlaytime = null;
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "[shavit] Player Stats",
|
||||
@ -103,7 +112,8 @@ public void OnPluginStart()
|
||||
LoadTranslations("shavit-common.phrases");
|
||||
LoadTranslations("shavit-stats.phrases");
|
||||
|
||||
//Convar.AutoExecConfig();
|
||||
gCV_SavePlaytime = new Convar("shavit_stats_saveplaytime", "1", "Whether to save a player's playtime (total & per-style).", 0, true, 0.0, true, 1.0);
|
||||
Convar.AutoExecConfig();
|
||||
|
||||
gB_Rankings = LibraryExists("shavit-rankings");
|
||||
|
||||
@ -120,12 +130,37 @@ public void OnPluginStart()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CreateTimer(2.5 * 60.0, Timer_SavePlaytime, 0, TIMER_REPEAT);
|
||||
}
|
||||
|
||||
public void Shavit_OnDatabaseLoaded()
|
||||
{
|
||||
GetTimerSQLPrefix(gS_MySQLPrefix, 32);
|
||||
gH_SQL = view_as<Database2>(Shavit_GetDatabase());
|
||||
|
||||
char sQuery[512];
|
||||
FormatEx(sQuery, sizeof(sQuery),
|
||||
"CREATE TABLE IF NOT EXISTS `%sstyleplaytime` (`auth` INT NOT NULL, `style` INT NOT NULL, `playtime` FLOAT NOT NULL, PRIMARY KEY (`auth`, `style`));",
|
||||
gS_MySQLPrefix);
|
||||
gH_SQL.Query(SQL_CreateStylePlaytimeTable_Callback, sQuery, 0, DBPrio_Normal);
|
||||
}
|
||||
|
||||
public void SQL_CreateStylePlaytimeTable_Callback(Database db, DBResultSet results, const char[] error, any data)
|
||||
{
|
||||
if (results == null)
|
||||
{
|
||||
LogError("Timer (styleplaytime table creation) SQL query failed. Reason: %s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
if (IsClientConnected(i) && !IsFakeClient(i) && IsClientAuthorized(i))
|
||||
{
|
||||
OnClientAuthorized(i, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Shavit_OnStyleConfigLoaded(int styles)
|
||||
@ -143,9 +178,105 @@ public void Shavit_OnChatConfigLoaded()
|
||||
Shavit_GetChatStringsStruct(gS_ChatStrings);
|
||||
}
|
||||
|
||||
public void OnClientConnected(int client)
|
||||
{
|
||||
gF_PlaytimeStart[client] = 0.0;
|
||||
gF_PlaytimeStyleStart[client] = 0.0;
|
||||
any empty[STYLE_LIMIT];
|
||||
gF_PlaytimeStyleSum[client] = empty;
|
||||
gB_HavePlaytimeOnStyle[client] = empty;
|
||||
}
|
||||
|
||||
public void OnClientPutInServer(int client)
|
||||
{
|
||||
gB_CanOpenMenu[client] = true;
|
||||
|
||||
float now = GetEngineTime();
|
||||
gF_PlaytimeStart[client] = now;
|
||||
gF_PlaytimeStyleStart[client] = now;
|
||||
}
|
||||
|
||||
public void OnClientAuthorized(int client)
|
||||
{
|
||||
if (gH_SQL == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char sQuery[512];
|
||||
FormatEx(sQuery, sizeof(sQuery),
|
||||
"SELECT style FROM %sstyleplaytime WHERE auth = %d;",
|
||||
gS_MySQLPrefix, GetSteamAccountID(client));
|
||||
gH_SQL.Query(SQL_QueryStylePlaytime_Callback, sQuery, GetClientSerial(client), DBPrio_Normal);
|
||||
}
|
||||
|
||||
public void SQL_QueryStylePlaytime_Callback(Database db, DBResultSet results, const char[] error, any data)
|
||||
{
|
||||
if (results == null)
|
||||
{
|
||||
LogError("Timer (style playtime) SQL query failed. Reason: %s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
int client = GetClientFromSerial(data);
|
||||
|
||||
if (client < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (results.FetchRow())
|
||||
{
|
||||
int style = results.FetchInt(0);
|
||||
gB_HavePlaytimeOnStyle[client][style] = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnClientDisconnect(int client)
|
||||
{
|
||||
if (gH_SQL == null || IsFakeClient(client) || !IsClientAuthorized(client) || !gCV_SavePlaytime.BoolValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Transaction2 trans = null;
|
||||
SavePlaytime(client, GetEngineTime(), trans);
|
||||
|
||||
if (trans != null)
|
||||
{
|
||||
gH_SQL.Execute(trans, Trans_SavePlaytime_Success, Trans_SavePlaytime_Failure);
|
||||
}
|
||||
}
|
||||
|
||||
public void Shavit_OnStyleChanged(int client, int oldstyle, int newstyle, int track, bool manual)
|
||||
{
|
||||
if (IsFakeClient(client))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gI_CurrentStyle[client] = newstyle;
|
||||
|
||||
if (!IsClientConnected(client) || !IsClientInGame(client))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float now = GetEngineTime();
|
||||
|
||||
if (gF_PlaytimeStyleStart[client] == 0.0)
|
||||
{
|
||||
gF_PlaytimeStyleStart[client] = now;
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldstyle == newstyle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gF_PlaytimeStyleSum[client][oldstyle] += (now - gF_PlaytimeStyleStart[client]);
|
||||
gF_PlaytimeStyleStart[client] = now;
|
||||
}
|
||||
|
||||
public void OnLibraryAdded(const char[] name)
|
||||
@ -164,6 +295,122 @@ public void OnLibraryRemoved(const char[] name)
|
||||
}
|
||||
}
|
||||
|
||||
void SavePlaytime222(int client, float now, Transaction2 &trans, int style, int iSteamID)
|
||||
{
|
||||
char sQuery[512];
|
||||
|
||||
if (style == -1) // regular playtime
|
||||
{
|
||||
if (gF_PlaytimeStart[client] <= 0.0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float diff = now - gF_PlaytimeStart[client];
|
||||
gF_PlaytimeStart[client] = now;
|
||||
|
||||
if (diff <= 0.0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FormatEx(sQuery, sizeof(sQuery),
|
||||
"UPDATE `%susers` SET playtime = playtime + %f WHERE auth = %d;",
|
||||
gS_MySQLPrefix, diff, iSteamID);
|
||||
}
|
||||
else
|
||||
{
|
||||
float diff = gF_PlaytimeStyleSum[client][style];
|
||||
|
||||
if (gI_CurrentStyle[client] == style)
|
||||
{
|
||||
diff += now - gF_PlaytimeStyleStart[client];
|
||||
gF_PlaytimeStyleStart[client] = now;
|
||||
}
|
||||
|
||||
gF_PlaytimeStyleSum[client][style] = 0.0;
|
||||
|
||||
if (diff <= 0.0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (gB_HavePlaytimeOnStyle[client][style])
|
||||
{
|
||||
FormatEx(sQuery, sizeof(sQuery),
|
||||
"UPDATE `%sstyleplaytime` SET playtime = playtime + %f WHERE auth = %d AND style = %d;",
|
||||
gS_MySQLPrefix, diff, iSteamID, style);
|
||||
}
|
||||
else
|
||||
{
|
||||
gB_HavePlaytimeOnStyle[client][style] = true;
|
||||
FormatEx(sQuery, sizeof(sQuery),
|
||||
"INSERT INTO `%sstyleplaytime` (`auth`, `style`, `playtime`) VALUES (%d, %d, %f);",
|
||||
gS_MySQLPrefix, iSteamID, style, diff);
|
||||
}
|
||||
}
|
||||
|
||||
if (trans == null)
|
||||
{
|
||||
trans = view_as<Transaction2>(new Transaction());
|
||||
}
|
||||
|
||||
trans.AddQuery(sQuery);
|
||||
}
|
||||
|
||||
public void Trans_SavePlaytime_Success(Database db, any data, int numQueries, DBResultSet[] results, any[] queryData)
|
||||
{
|
||||
}
|
||||
|
||||
public void Trans_SavePlaytime_Failure(Database db, any data, int numQueries, const char[] error, int failIndex, any[] queryData)
|
||||
{
|
||||
LogError("Timer (stats save playtime) SQL query %d/%d failed. Reason: %s", failIndex, numQueries, error);
|
||||
}
|
||||
|
||||
void SavePlaytime(int client, float now, Transaction2 &trans)
|
||||
{
|
||||
int iSteamID = GetSteamAccountID(client);
|
||||
|
||||
if (iSteamID == 0)
|
||||
{
|
||||
// how HOW HOW
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = -1 /* yes */; i < gI_Styles; i++)
|
||||
{
|
||||
SavePlaytime222(client, now, trans, i, iSteamID);
|
||||
}
|
||||
}
|
||||
|
||||
public Action Timer_SavePlaytime(Handle timer, any data)
|
||||
{
|
||||
if (gH_SQL == null || !gCV_SavePlaytime.BoolValue)
|
||||
{
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
Transaction2 trans = null;
|
||||
float now = GetEngineTime();
|
||||
|
||||
for (int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
if (!IsValidClient(i) || !IsClientAuthorized(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
SavePlaytime(i, now, trans);
|
||||
}
|
||||
|
||||
if (trans != null)
|
||||
{
|
||||
gH_SQL.Execute(trans, Trans_SavePlaytime_Success, Trans_SavePlaytime_Failure);
|
||||
}
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
public Action Command_MapsDoneLeft(int client, int args)
|
||||
{
|
||||
if(client == 0)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user