#pragma semicolon 1 #include #include Database g_hDatabase; int g_iConnectionTime[MAXPLAYERS + 1]; bool g_bPlayerValid[MAXPLAYERS + 1]; public Plugin myinfo = { name = "PlaytimeStats", author = "Dogan", description = "Retreives total playtime on multiple servers for clients", version = "1.1.0", url = "" } public void OnPluginStart() { Database.Connect(SQL_OnDatabaseConnect, "unloze_playtimestats"); RegConsoleCmd("sm_playtime", Command_Time, "retreives total connection time on all connected servers"); RegConsoleCmd("sm_topplaytime", Command_TopTime, "retreives top 12 playtime highscores on all connected servers"); } public Action Command_Time(int client, int args) { int iAuthID = GetSteamAccountID(client); char sQuery[512]; Format(sQuery, sizeof(sQuery), "SELECT time FROM playtime WHERE auth = '%d'", iAuthID); g_hDatabase.Query(SQL_OnQueryCompletedTime, sQuery, GetClientSerial(client)); return Plugin_Handled; } public Action Command_TopTime(int client, int args) { char sQuery[255]; Format(sQuery, sizeof(sQuery), "SELECT * from playtime order by time desc limit 12"); g_hDatabase.Query(SQL_OnQueryCompletedTopTime, sQuery, GetClientSerial(client)); return Plugin_Handled; } public void OnClientAuthorized(int client) { if(IsValidClient(client)) { g_bPlayerValid[client] = true; g_iConnectionTime[client] = GetTime(); } } public void OnClientDisconnect(int client) { if(g_iConnectionTime[client] == 0 || !g_bPlayerValid[client]) return; g_bPlayerValid[client] = false; int iPlayTime = GetTime() - g_iConnectionTime[client]; int iAuthID = GetSteamAccountID(client); if(iAuthID == 0) return; char sName[MAX_NAME_LENGTH]; GetClientName(client, sName, sizeof(sName)); char sSafeName[(2*MAX_NAME_LENGTH)+1]; g_hDatabase.Escape(sName, sSafeName, sizeof(sSafeName)); char sQuery[512]; Format(sQuery, sizeof(sQuery), "INSERT INTO playtime (auth,name,time) VALUES ('%u', '%s', '%d') ON DUPLICATE KEY UPDATE time=time+%d", iAuthID, sSafeName, iPlayTime, iPlayTime); g_hDatabase.Query(SQL_OnQueryCompleted, sQuery, _, DBPrio_Low); } public void SQL_OnDatabaseConnect(Database db, const char[] error, any data) { if(!db || strlen(error)) { LogError("Database error: %s", error); return; } g_hDatabase = db; char sQuery[512]; Format(sQuery, sizeof(sQuery), "CREATE TABLE IF NOT EXISTS playtime (`auth` INTEGER UNSIGNED, `name` varchar(128), `time` INTEGER, PRIMARY KEY (`auth`), INDEX (`time`))"); g_hDatabase.Query(SQL_OnQueryCompleted, sQuery, _, DBPrio_Low); } public void SQL_OnQueryCompleted(Database db, DBResultSet results, const char[] error, any data) { if(!db || strlen(error)) { LogError("Query error: %s", error); return; } } public void SQL_OnQueryCompletedTime(Database db, DBResultSet results, const char[] error, int iSerial) { int client; if ((client = GetClientFromSerial(iSerial)) == 0) return; if(!db || strlen(error)) { LogError("Query error: %s", error); return; } int iTime; if (results.RowCount && results.FetchRow()) { int iFieldNum; results.FieldNameToNum("time", iFieldNum); iTime = results.FetchInt(iFieldNum); } char sTime[64]; int iDays = (iTime/ 86400); int iHours = (iTime / 3600) % 24; int iMinutes = (iTime / 60) % 60; int iSeconds = (iTime % 60); if (iDays) Format(sTime, sizeof(sTime), "%d Days %d Hours %d Minutes %d Seconds", iDays, iHours, iMinutes, iSeconds); else if (iHours) Format(sTime, sizeof(sTime), "%d Hours %d Minutes %d Seconds", iHours, iMinutes, iSeconds); else if (iMinutes) Format(sTime, sizeof(sTime), "%d Minutes %d Seconds", iMinutes, iSeconds); else Format(sTime, sizeof(sTime), "%d Seconds", iSeconds); char sTitle[64]; Format(sTitle, sizeof(sTitle), "[UNLOZE Playtime] Player %N:", client); Panel mSayPanel = new Panel(GetMenuStyleHandle(MenuStyle_Radio)); mSayPanel.SetTitle(sTitle); mSayPanel.DrawItem("", ITEMDRAW_SPACER); mSayPanel.DrawText(sTime); mSayPanel.DrawItem("", ITEMDRAW_SPACER); mSayPanel.DrawText("(Data collected since Octobre 2019)"); mSayPanel.DrawItem("", ITEMDRAW_SPACER); mSayPanel.DrawItem("1. Got it!", ITEMDRAW_RAWLINE); mSayPanel.SetKeys(1023); mSayPanel.Send(client, Handler_Menu, 0); delete mSayPanel; } public void SQL_OnQueryCompletedTopTime(Database db, DBResultSet results, const char[] error, int iSerial) { int client; if ((client = GetClientFromSerial(iSerial)) == 0) return; if (!db || strlen(error)) { LogError("Query error: %s", error); return; } char sName[12][32]; int iTime[12]; char sBuffer[12][128]; Panel mSayPanel = new Panel(GetMenuStyleHandle(MenuStyle_Radio)); mSayPanel.SetTitle("[UNLOZE Playtime] Record Holders:"); mSayPanel.DrawItem("", ITEMDRAW_SPACER); for(int i = 1; i <= 12; i++) { int iFieldNum; if (!results.FetchRow()) break; results.FieldNameToNum("name", iFieldNum); results.FetchString(iFieldNum, sName[i - 1], 32); results.FieldNameToNum("time", iFieldNum); iTime[i - 1] = results.FetchInt(iFieldNum); iTime[i - 1] = iTime[i - 1] / 60; Format(sBuffer[i - 1], 128, "%d. %s - %d Minutes", i, sName[i - 1], iTime[i - 1]); mSayPanel.DrawText(sBuffer[i - 1]); } mSayPanel.DrawItem("", ITEMDRAW_SPACER); mSayPanel.DrawItem("1. Got it!", ITEMDRAW_RAWLINE); mSayPanel.SetKeys(1023); mSayPanel.Send(client, Handler_Menu, 0); delete mSayPanel; } public int Handler_Menu(Menu menu, MenuAction action, int param1, int param2) { switch(action) { case MenuAction_Select, MenuAction_Cancel: delete menu; } } stock bool IsValidClient(int client) { return (client >= 1 && client <= MaxClients && !IsFakeClient(client) && PM_IsPlayerSteam(client)); }