From 203644d1d2c7cbf06460e49d7a6f732f7e814e8b Mon Sep 17 00:00:00 2001 From: shavit Date: Wed, 17 Apr 2019 22:57:37 +0300 Subject: [PATCH 01/34] Added prespeed setting 2 which also respect shavit_core_nozaxisspeed. --- addons/sourcemod/configs/shavit-styles.cfg | 2 +- addons/sourcemod/scripting/include/shavit.inc | 2 +- addons/sourcemod/scripting/shavit-core.sp | 8 +++++--- addons/sourcemod/scripting/shavit-misc.sp | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/addons/sourcemod/configs/shavit-styles.cfg b/addons/sourcemod/configs/shavit-styles.cfg index b1770c946..98308b30f 100644 --- a/addons/sourcemod/configs/shavit-styles.cfg +++ b/addons/sourcemod/configs/shavit-styles.cfg @@ -21,7 +21,7 @@ // Jumping settings "autobhop" "1" // Enable autobhopping and +ds? "easybhop" "1" // Enable easybhop (disable stamina reset)? - "prespeed" "0" // Allow prespeeding regardless of the prespeed server setting? + "prespeed" "0" // Allow prespeeding regardless of the prespeed server setting? If set to 2, the value of shavit_core_nozaxisspeed will be respected as well. "velocity_limit" "0.0" // Velocity limit: set to 0.0 for unlimited, 400.00 for 400vel styles etc. "bunnyhopping" "1" // Per-style sv_enablebunnyhopping. Leave as 1 if you want bunnyhopping to maintain player speed. This setting will override _strafe map settings. diff --git a/addons/sourcemod/scripting/include/shavit.inc b/addons/sourcemod/scripting/include/shavit.inc index 093f3f59b..04d8f7d6d 100644 --- a/addons/sourcemod/scripting/include/shavit.inc +++ b/addons/sourcemod/scripting/include/shavit.inc @@ -135,7 +135,7 @@ enum struct stylesettings_t { bool bAutobhop; bool bEasybhop; - bool bPrespeed; + int iPrespeed; float fVelocityLimit; bool bEnableBunnyhopping; float fAiraccelerate; diff --git a/addons/sourcemod/scripting/shavit-core.sp b/addons/sourcemod/scripting/shavit-core.sp index bbc73d0bb..bd85a9d24 100644 --- a/addons/sourcemod/scripting/shavit-core.sp +++ b/addons/sourcemod/scripting/shavit-core.sp @@ -1708,7 +1708,9 @@ void StartTimer(int client, int track) float fSpeed[3]; GetEntPropVector(client, Prop_Data, "m_vecVelocity", fSpeed); - if(!gCV_NoZAxisSpeed.BoolValue || gA_StyleSettings[gA_Timers[client].iStyle].bPrespeed || (fSpeed[2] == 0.0 && SquareRoot(Pow(fSpeed[0], 2.0) + Pow(fSpeed[1], 2.0)) <= 290.0)) + if(!gCV_NoZAxisSpeed.BoolValue || + gA_StyleSettings[gA_Timers[client].iStyle].iPrespeed == 1 || + (fSpeed[2] == 0.0 && (gA_StyleSettings[gA_Timers[client].iStyle].iPrespeed == 2 || SquareRoot(Pow(fSpeed[0], 2.0) + Pow(fSpeed[1], 2.0)) <= 290.0))) { Action result = Plugin_Continue; Call_StartForward(gH_Forwards_Start); @@ -1960,7 +1962,7 @@ bool LoadStyles() gA_StyleSettings[i].bAutobhop = view_as(kv.GetNum("autobhop", 1)); gA_StyleSettings[i].bEasybhop = view_as(kv.GetNum("easybhop", 1)); - gA_StyleSettings[i].bPrespeed = view_as(kv.GetNum("prespeed", 0)); + gA_StyleSettings[i].iPrespeed = view_as(kv.GetNum("prespeed", 0)); gA_StyleSettings[i].fVelocityLimit = kv.GetFloat("velocity_limit", 0.0); gA_StyleSettings[i].fAiraccelerate = kv.GetFloat("airaccelerate", 1000.0); gA_StyleSettings[i].bEnableBunnyhopping = view_as(kv.GetNum("bunnyhopping", 1)); @@ -2641,7 +2643,7 @@ public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3 gA_Timers[client].iGroundTicks = 0; } - if(bInStart && gCV_BlockPreJump.BoolValue && !gA_StyleSettings[gA_Timers[client].iStyle].bPrespeed && (vel[2] > 0 || (buttons & IN_JUMP) > 0)) + if(bInStart && gCV_BlockPreJump.BoolValue && gA_StyleSettings[gA_Timers[client].iStyle].iPrespeed == 0 && (vel[2] > 0 || (buttons & IN_JUMP) > 0)) { vel[2] = 0.0; buttons &= ~IN_JUMP; diff --git a/addons/sourcemod/scripting/shavit-misc.sp b/addons/sourcemod/scripting/shavit-misc.sp index 81fd0e414..0fc0ab425 100644 --- a/addons/sourcemod/scripting/shavit-misc.sp +++ b/addons/sourcemod/scripting/shavit-misc.sp @@ -1014,7 +1014,7 @@ public Action Shavit_OnUserCmdPre(int client, int &buttons, int &impulse, float int iGroundEntity = GetEntPropEnt(client, Prop_Send, "m_hGroundEntity"); // prespeed - if(!bNoclip && !gA_StyleSettings[gI_Style[client]].bPrespeed && Shavit_InsideZone(client, Zone_Start, track)) + if(!bNoclip && gA_StyleSettings[gI_Style[client]].iPrespeed == 0 && Shavit_InsideZone(client, Zone_Start, track)) { if((gCV_PreSpeed.IntValue == 2 || gCV_PreSpeed.IntValue == 3) && gI_GroundEntity[client] == -1 && iGroundEntity != -1 && (buttons & IN_JUMP) > 0) { @@ -2769,7 +2769,7 @@ public Action Command_Specs(int client, int args) public Action Shavit_OnStart(int client) { - if(!gA_StyleSettings[gI_Style[client]].bPrespeed && GetEntityMoveType(client) == MOVETYPE_NOCLIP) + if(gA_StyleSettings[gI_Style[client]].iPrespeed == 0 && GetEntityMoveType(client) == MOVETYPE_NOCLIP) { return Plugin_Stop; } From 202d893802fc1a7c5c81c6dbbbeec643b42ddadc Mon Sep 17 00:00:00 2001 From: shavit Date: Wed, 17 Apr 2019 22:57:50 +0300 Subject: [PATCH 02/34] Fixed error on map finish when there's no "noimprovement" sounds. --- addons/sourcemod/scripting/shavit-sounds.sp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/shavit-sounds.sp b/addons/sourcemod/scripting/shavit-sounds.sp index a4caadb8b..368d8b097 100644 --- a/addons/sourcemod/scripting/shavit-sounds.sp +++ b/addons/sourcemod/scripting/shavit-sounds.sp @@ -188,7 +188,7 @@ public void OnMapStart() public void Shavit_OnFinish(int client, int style, float time, int jumps, int strafes, float sync, int track, float oldtime, float perfs) { - if(oldtime != 0.0 && time > oldtime) + if(oldtime != 0.0 && time > oldtime && gA_NoImprovementSounds.Length != 0) { char sSound[PLATFORM_MAX_PATH]; gA_NoImprovementSounds.GetString(GetRandomInt(0, gA_NoImprovementSounds.Length - 1), sSound, PLATFORM_MAX_PATH); From c2467f4d5268f964cb15557d2f3d669fe3a83bde Mon Sep 17 00:00:00 2001 From: shavit Date: Thu, 18 Apr 2019 05:08:43 +0300 Subject: [PATCH 03/34] Fixed odd behavior when a map has more than 1000 records. --- addons/sourcemod/scripting/shavit-wr.sp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/addons/sourcemod/scripting/shavit-wr.sp b/addons/sourcemod/scripting/shavit-wr.sp index 967b15da9..6d4821dca 100644 --- a/addons/sourcemod/scripting/shavit-wr.sp +++ b/addons/sourcemod/scripting/shavit-wr.sp @@ -649,14 +649,19 @@ public Action Command_Junk(int client, int args) public Action Command_PrintLeaderboards(int client, int args) { - ReplyToCommand(client, "Track: Main - Style: 0"); - ReplyToCommand(client, "Current PB: %f", gF_PlayerRecord[client][0][0]); - ReplyToCommand(client, "Count: %d", gI_RecordAmount[0][0]); - ReplyToCommand(client, "Rank: %d", Shavit_GetRankForTime(0, gF_PlayerRecord[client][0][0], 0)); + char sArg[8]; + GetCmdArg(1, sArg, 8); - for(int i = 0; i < gI_RecordAmount[0][0]; i++) + int iStyle = StringToInt(sArg); + + ReplyToCommand(client, "Track: Main - Style: %d", iStyle); + ReplyToCommand(client, "Current PB: %f", gF_PlayerRecord[client][iStyle][0]); + ReplyToCommand(client, "Count: %d", gI_RecordAmount[iStyle][0]); + ReplyToCommand(client, "Rank: %d", Shavit_GetRankForTime(iStyle, gF_PlayerRecord[client][iStyle][0], iStyle)); + + for(int i = 0; i < gI_RecordAmount[iStyle][0]; i++) { - ReplyToCommand(client, "#%d: %f", i, gA_Leaderboard[0][0].Get(i)); + ReplyToCommand(client, "#%d: %f", i, gA_Leaderboard[iStyle][0].Get(i)); } return Plugin_Handled; @@ -2149,7 +2154,7 @@ public void SQL_OnFinish_Callback(Database db, DBResultSet results, const char[] void UpdateLeaderboards() { char sQuery[192]; - FormatEx(sQuery, 192, "SELECT style, time, track FROM %splayertimes WHERE map = '%s' ORDER BY time ASC, date ASC LIMIT 1000;", gS_MySQLPrefix, gS_Map); + FormatEx(sQuery, 192, "SELECT style, track, time FROM %splayertimes WHERE map = '%s' ORDER BY time ASC, date ASC;", gS_MySQLPrefix, gS_Map); gH_SQL.Query(SQL_UpdateLeaderboards_Callback, sQuery, 0); } @@ -2174,14 +2179,14 @@ public void SQL_UpdateLeaderboards_Callback(Database db, DBResultSet results, co while(results.FetchRow()) { int style = results.FetchInt(0); - int track = results.FetchInt(2); + int track = results.FetchInt(1); if(style >= gI_Styles || gA_StyleSettings[style].bUnranked || track >= TRACKS_SIZE) { continue; } - gA_Leaderboard[style][track].Push(results.FetchFloat(1)); + gA_Leaderboard[style][track].Push(results.FetchFloat(2)); } for(int i = 0; i < gI_Styles; i++) From 55bd4fba1be5a5ed6f92b41d37380506f538a4a8 Mon Sep 17 00:00:00 2001 From: shavit Date: Thu, 18 Apr 2019 22:30:12 +0300 Subject: [PATCH 04/34] Re-persist KZ menu after opening it manually --- addons/sourcemod/scripting/shavit-misc.sp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/addons/sourcemod/scripting/shavit-misc.sp b/addons/sourcemod/scripting/shavit-misc.sp index 0fc0ab425..a126c803e 100644 --- a/addons/sourcemod/scripting/shavit-misc.sp +++ b/addons/sourcemod/scripting/shavit-misc.sp @@ -1676,6 +1676,11 @@ public Action Command_Checkpoints(int client, int args) return Plugin_Handled; } + if(gA_StyleSettings[gI_Style[client]].bKZCheckpoints) + { + gB_ClosedKZCP[client] = false; + } + return OpenCheckpointsMenu(client); } From 67ff423dccbda9162050cc2445858aae43540141 Mon Sep 17 00:00:00 2001 From: shavit Date: Fri, 26 Apr 2019 17:07:54 +0300 Subject: [PATCH 05/34] Fixed recalculations on long map names breaking. --- addons/sourcemod/scripting/shavit-rankings.sp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/sourcemod/scripting/shavit-rankings.sp b/addons/sourcemod/scripting/shavit-rankings.sp index b15b5d04d..0dfba6ed0 100644 --- a/addons/sourcemod/scripting/shavit-rankings.sp +++ b/addons/sourcemod/scripting/shavit-rankings.sp @@ -758,8 +758,8 @@ void RecalculateMap(const char[] map, const int track, const int style) PrintToServer("Recalculating points. (%s, %d, %d)", map, track, style); #endif - char sQuery[192]; - FormatEx(sQuery, 192, "UPDATE %splayertimes SET points = GetRecordPoints(%d, %d, time, '%s', %.1f, %.3f) WHERE style = %d AND track = %d AND map = '%s';", + char sQuery[256]; + FormatEx(sQuery, 256, "UPDATE %splayertimes SET points = GetRecordPoints(%d, %d, time, '%s', %.1f, %.3f) WHERE style = %d AND track = %d AND map = '%s';", gS_MySQLPrefix, style, track, map, gCV_PointsPerTier.FloatValue, gA_StyleSettings[style].fRankingMultiplier, style, track, map); gH_SQL.Query(SQL_Recalculate_Callback, sQuery, 0, DBPrio_High); @@ -789,8 +789,8 @@ void UpdateAllPoints() LogError("DEBUG: 6 (UpdateAllPoints)"); #endif - char sQuery[128]; - FormatEx(sQuery, 128, "UPDATE %susers SET points = GetWeightedPoints(auth) WHERE auth IN (SELECT DISTINCT auth FROM %splayertimes);", + char sQuery[256]; + FormatEx(sQuery, 256, "UPDATE %susers SET points = GetWeightedPoints(auth) WHERE auth IN (SELECT DISTINCT auth FROM %splayertimes);", gS_MySQLPrefix, gS_MySQLPrefix); gH_SQL.Query(SQL_UpdateAllPoints_Callback, sQuery); From bb74e14bcfc3285f71757b2fd674cb6754f7f041 Mon Sep 17 00:00:00 2001 From: shavit Date: Fri, 26 Apr 2019 17:09:28 +0300 Subject: [PATCH 06/34] Fixed SQL issues on table creation when using table prefix. --- addons/sourcemod/scripting/shavit-chat.sp | 8 ++++---- addons/sourcemod/scripting/shavit-wr.sp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/addons/sourcemod/scripting/shavit-chat.sp b/addons/sourcemod/scripting/shavit-chat.sp index 68d88b0eb..7dea3edba 100644 --- a/addons/sourcemod/scripting/shavit-chat.sp +++ b/addons/sourcemod/scripting/shavit-chat.sp @@ -1332,15 +1332,15 @@ void SQL_DBConnect() if(bMySQL) { FormatEx(sQuery, 512, - "CREATE TABLE IF NOT EXISTS `%schat` (`auth` VARCHAR(32) NOT NULL, `name` INT NOT NULL DEFAULT 0, `ccname` VARCHAR(128) COLLATE 'utf8mb4_unicode_ci', `message` INT NOT NULL DEFAULT 0, `ccmessage` VARCHAR(16) COLLATE 'utf8mb4_unicode_ci', PRIMARY KEY (`auth`), CONSTRAINT `ch_auth` FOREIGN KEY (`auth`) REFERENCES `users` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE) ENGINE=INNODB;", - gS_MySQLPrefix); + "CREATE TABLE IF NOT EXISTS `%schat` (`auth` VARCHAR(32) NOT NULL, `name` INT NOT NULL DEFAULT 0, `ccname` VARCHAR(128) COLLATE 'utf8mb4_unicode_ci', `message` INT NOT NULL DEFAULT 0, `ccmessage` VARCHAR(16) COLLATE 'utf8mb4_unicode_ci', PRIMARY KEY (`auth`), CONSTRAINT `ch_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE) ENGINE=INNODB;", + gS_MySQLPrefix, gS_MySQLPrefix); } else { FormatEx(sQuery, 512, - "CREATE TABLE IF NOT EXISTS `%schat` (`auth` VARCHAR(32) NOT NULL, `name` INT NOT NULL DEFAULT 0, `ccname` VARCHAR(128), `message` INT NOT NULL DEFAULT 0, `ccmessage` VARCHAR(16), PRIMARY KEY (`auth`), CONSTRAINT `ch_auth` FOREIGN KEY (`auth`) REFERENCES `users` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE);", - gS_MySQLPrefix); + "CREATE TABLE IF NOT EXISTS `%schat` (`auth` VARCHAR(32) NOT NULL, `name` INT NOT NULL DEFAULT 0, `ccname` VARCHAR(128), `message` INT NOT NULL DEFAULT 0, `ccmessage` VARCHAR(16), PRIMARY KEY (`auth`), CONSTRAINT `ch_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE);", + gS_MySQLPrefix, gS_MySQLPrefix); } gH_SQL.Query(SQL_CreateTable_Callback, sQuery); diff --git a/addons/sourcemod/scripting/shavit-wr.sp b/addons/sourcemod/scripting/shavit-wr.sp index 6d4821dca..4a5f19641 100644 --- a/addons/sourcemod/scripting/shavit-wr.sp +++ b/addons/sourcemod/scripting/shavit-wr.sp @@ -1956,15 +1956,15 @@ void SQL_DBConnect() if(gB_MySQL) { FormatEx(sQuery, 1024, - "CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INT NOT NULL AUTO_INCREMENT, `auth` VARCHAR(32), `map` VARCHAR(128), `time` FLOAT, `jumps` INT, `style` TINYINT, `date` VARCHAR(16), `strafes` INT, `sync` FLOAT, `points` FLOAT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0, `perfs` FLOAT DEFAULT 0, PRIMARY KEY (`id`), INDEX `map` (`map`, `style`, `track`, `time`), INDEX `auth` (`auth`, `date`, `points`), INDEX `time` (`time`), CONSTRAINT `pt_auth` FOREIGN KEY (`auth`) REFERENCES `users` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE) ENGINE=INNODB;", - gS_MySQLPrefix); + "CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INT NOT NULL AUTO_INCREMENT, `auth` VARCHAR(32), `map` VARCHAR(128), `time` FLOAT, `jumps` INT, `style` TINYINT, `date` VARCHAR(16), `strafes` INT, `sync` FLOAT, `points` FLOAT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0, `perfs` FLOAT DEFAULT 0, PRIMARY KEY (`id`), INDEX `map` (`map`, `style`, `track`, `time`), INDEX `auth` (`auth`, `date`, `points`), INDEX `time` (`time`), CONSTRAINT `pt_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE) ENGINE=INNODB;", + gS_MySQLPrefix, gS_MySQLPrefix); } else { FormatEx(sQuery, 1024, - "CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INTEGER PRIMARY KEY, `auth` VARCHAR(32), `map` VARCHAR(128), `time` FLOAT, `jumps` INT, `style` TINYINT, `date` VARCHAR(16), `strafes` INT, `sync` FLOAT, `points` FLOAT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0, `perfs` FLOAT DEFAULT 0);", - gS_MySQLPrefix); + "CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INTEGER PRIMARY KEY, `auth` VARCHAR(32), `map` VARCHAR(128), `time` FLOAT, `jumps` INT, `style` TINYINT, `date` VARCHAR(16), `strafes` INT, `sync` FLOAT, `points` FLOAT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0, `perfs` FLOAT DEFAULT 0, CONSTRAINT `pt_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE);", + gS_MySQLPrefix, gS_MySQLPrefix); } gH_SQL.Query(SQL_CreateTable_Callback, sQuery); From fbe78584ae0c3a8d145dbe532c83a1cf4eff294f Mon Sep 17 00:00:00 2001 From: shavit Date: Sat, 27 Apr 2019 12:54:06 +0300 Subject: [PATCH 07/34] Fixed table creation when using the same database for more than one server. --- addons/sourcemod/scripting/shavit-chat.sp | 8 ++++---- addons/sourcemod/scripting/shavit-wr.sp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/addons/sourcemod/scripting/shavit-chat.sp b/addons/sourcemod/scripting/shavit-chat.sp index 7dea3edba..83b03bd74 100644 --- a/addons/sourcemod/scripting/shavit-chat.sp +++ b/addons/sourcemod/scripting/shavit-chat.sp @@ -1332,15 +1332,15 @@ void SQL_DBConnect() if(bMySQL) { FormatEx(sQuery, 512, - "CREATE TABLE IF NOT EXISTS `%schat` (`auth` VARCHAR(32) NOT NULL, `name` INT NOT NULL DEFAULT 0, `ccname` VARCHAR(128) COLLATE 'utf8mb4_unicode_ci', `message` INT NOT NULL DEFAULT 0, `ccmessage` VARCHAR(16) COLLATE 'utf8mb4_unicode_ci', PRIMARY KEY (`auth`), CONSTRAINT `ch_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE) ENGINE=INNODB;", - gS_MySQLPrefix, gS_MySQLPrefix); + "CREATE TABLE IF NOT EXISTS `%schat` (`auth` VARCHAR(32) NOT NULL, `name` INT NOT NULL DEFAULT 0, `ccname` VARCHAR(128) COLLATE 'utf8mb4_unicode_ci', `message` INT NOT NULL DEFAULT 0, `ccmessage` VARCHAR(16) COLLATE 'utf8mb4_unicode_ci', PRIMARY KEY (`auth`), CONSTRAINT `%sch_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE) ENGINE=INNODB;", + gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix); } else { FormatEx(sQuery, 512, - "CREATE TABLE IF NOT EXISTS `%schat` (`auth` VARCHAR(32) NOT NULL, `name` INT NOT NULL DEFAULT 0, `ccname` VARCHAR(128), `message` INT NOT NULL DEFAULT 0, `ccmessage` VARCHAR(16), PRIMARY KEY (`auth`), CONSTRAINT `ch_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE);", - gS_MySQLPrefix, gS_MySQLPrefix); + "CREATE TABLE IF NOT EXISTS `%schat` (`auth` VARCHAR(32) NOT NULL, `name` INT NOT NULL DEFAULT 0, `ccname` VARCHAR(128), `message` INT NOT NULL DEFAULT 0, `ccmessage` VARCHAR(16), PRIMARY KEY (`auth`), CONSTRAINT `%sch_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE);", + gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix); } gH_SQL.Query(SQL_CreateTable_Callback, sQuery); diff --git a/addons/sourcemod/scripting/shavit-wr.sp b/addons/sourcemod/scripting/shavit-wr.sp index 4a5f19641..d5bcd099e 100644 --- a/addons/sourcemod/scripting/shavit-wr.sp +++ b/addons/sourcemod/scripting/shavit-wr.sp @@ -1956,15 +1956,15 @@ void SQL_DBConnect() if(gB_MySQL) { FormatEx(sQuery, 1024, - "CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INT NOT NULL AUTO_INCREMENT, `auth` VARCHAR(32), `map` VARCHAR(128), `time` FLOAT, `jumps` INT, `style` TINYINT, `date` VARCHAR(16), `strafes` INT, `sync` FLOAT, `points` FLOAT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0, `perfs` FLOAT DEFAULT 0, PRIMARY KEY (`id`), INDEX `map` (`map`, `style`, `track`, `time`), INDEX `auth` (`auth`, `date`, `points`), INDEX `time` (`time`), CONSTRAINT `pt_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE) ENGINE=INNODB;", - gS_MySQLPrefix, gS_MySQLPrefix); + "CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INT NOT NULL AUTO_INCREMENT, `auth` VARCHAR(32), `map` VARCHAR(128), `time` FLOAT, `jumps` INT, `style` TINYINT, `date` VARCHAR(16), `strafes` INT, `sync` FLOAT, `points` FLOAT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0, `perfs` FLOAT DEFAULT 0, PRIMARY KEY (`id`), INDEX `map` (`map`, `style`, `track`, `time`), INDEX `auth` (`auth`, `date`, `points`), INDEX `time` (`time`), CONSTRAINT `%spt_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE) ENGINE=INNODB;", + gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix); } else { FormatEx(sQuery, 1024, - "CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INTEGER PRIMARY KEY, `auth` VARCHAR(32), `map` VARCHAR(128), `time` FLOAT, `jumps` INT, `style` TINYINT, `date` VARCHAR(16), `strafes` INT, `sync` FLOAT, `points` FLOAT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0, `perfs` FLOAT DEFAULT 0, CONSTRAINT `pt_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE);", - gS_MySQLPrefix, gS_MySQLPrefix); + "CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INTEGER PRIMARY KEY, `auth` VARCHAR(32), `map` VARCHAR(128), `time` FLOAT, `jumps` INT, `style` TINYINT, `date` VARCHAR(16), `strafes` INT, `sync` FLOAT, `points` FLOAT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0, `perfs` FLOAT DEFAULT 0, CONSTRAINT `%spt_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE);", + gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix); } gH_SQL.Query(SQL_CreateTable_Callback, sQuery); From 24e8ba76fadbc698d1dc99d2def8a6ad4920f527 Mon Sep 17 00:00:00 2001 From: shavit Date: Wed, 1 May 2019 15:00:47 +0300 Subject: [PATCH 08/34] Added new CS:GO radio commands to block list --- addons/sourcemod/scripting/shavit-misc.sp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/shavit-misc.sp b/addons/sourcemod/scripting/shavit-misc.sp index a126c803e..ce9c31af8 100644 --- a/addons/sourcemod/scripting/shavit-misc.sp +++ b/addons/sourcemod/scripting/shavit-misc.sp @@ -97,7 +97,7 @@ int gI_Ammo = -1; char gS_RadioCommands[][] = { "coverme", "takepoint", "holdpos", "regroup", "followme", "takingfire", "go", "fallback", "sticktog", "getinpos", "stormfront", "report", "roger", "enemyspot", "needbackup", "sectorclear", "inposition", "reportingin", - "getout", "negative", "enemydown", "compliment", "thanks", "cheer" }; + "getout", "negative", "enemydown", "compliment", "thanks", "cheer", "go_a", "go_b", "sorry", "needrop" }; bool gB_Hide[MAXPLAYERS+1]; bool gB_Late = false; From 26d5bfa3ba5e523f00f0fef7a3196caa5e9167c4 Mon Sep 17 00:00:00 2001 From: shavit Date: Fri, 3 May 2019 10:56:56 +0300 Subject: [PATCH 09/34] Split replay version loaders And fixed a bug with old replays where the very first frame wouldn't be loaded. --- addons/sourcemod/scripting/shavit-replay.sp | 272 +++++++++++--------- 1 file changed, 150 insertions(+), 122 deletions(-) diff --git a/addons/sourcemod/scripting/shavit-replay.sp b/addons/sourcemod/scripting/shavit-replay.sp index a0ea08f01..a3da88023 100644 --- a/addons/sourcemod/scripting/shavit-replay.sp +++ b/addons/sourcemod/scripting/shavit-replay.sp @@ -973,169 +973,197 @@ bool DefaultLoadReplay(int style, int track) return LoadReplay(style, track, sPath); } -bool LoadReplay(int style, int track, const char[] path) +bool LoadCurrentReplayFormat(File file, int version, int style, int track) { - if(FileExists(path)) + gA_FrameCache[style][track].iReplayVersion = version; + + // replay file integrity and preframes + if(gA_FrameCache[style][track].iReplayVersion >= 0x03) { - File fFile = OpenFile(path, "rb"); + char sMap[160]; + file.ReadString(sMap, 160); - char sHeader[64]; + int iStyle = 0; + file.ReadUint8(iStyle); - if(!fFile.ReadLine(sHeader, 64)) - { - delete fFile; + int iTrack = 0; + file.ReadUint8(iTrack); + if(!StrEqual(sMap, gS_Map, false) || iStyle != style || iTrack != track) + { + delete file; + return false; } - TrimString(sHeader); - char sExplodedHeader[2][64]; - ExplodeString(sHeader, ":", sExplodedHeader, 2, 64); + // whenever this is implemented + // file.ReadInt32(gA_FrameCache[style][track].iPreframes); + file.Seek(4, SEEK_CUR); + } - // TODO: split this piece of shit to different functions. cbf to keep it like this - if(StrEqual(sExplodedHeader[1], REPLAY_FORMAT_FINAL)) // hopefully, the last of them - { - gA_FrameCache[style][track].iReplayVersion = StringToInt(sExplodedHeader[0]); + int iTemp = 0; + file.ReadInt32(iTemp); + gA_FrameCache[style][track].iFrameCount = iTemp; - // replay file integrity and preframes - if(gA_FrameCache[style][track].iReplayVersion >= 0x03) - { - char sMap[160]; - fFile.ReadString(sMap, 160); + if(gA_Frames[style][track] == null) + { + gA_Frames[style][track] = new ArrayList(CELLS_PER_FRAME); + } - int iStyle = 0; - fFile.ReadUint8(iStyle); + gA_Frames[style][track].Resize(iTemp); - int iTrack = 0; - fFile.ReadUint8(iTrack); + file.ReadInt32(iTemp); + gA_FrameCache[style][track].fTime = view_as(iTemp); - if(!StrEqual(sMap, gS_Map, false) || iStyle != style || iTrack != track) - { - delete fFile; - - return false; - } + char sAuthID[32]; + file.ReadString(sAuthID, 32); - // whenever this is implemented - // fFile.ReadInt32(gA_FrameCache[style][track].iPreframes); - fFile.Seek(4, SEEK_CUR); - } + if(gH_SQL != null) + { + char sQuery[192]; + FormatEx(sQuery, 192, "SELECT name FROM %susers WHERE auth = '%s';", gS_MySQLPrefix, sAuthID); - int iTemp = 0; - fFile.ReadInt32(iTemp); - gA_FrameCache[style][track].iFrameCount = iTemp; + DataPack pack = new DataPack(); + pack.WriteCell(style); + pack.WriteCell(track); - if(gA_Frames[style][track] == null) - { - gA_Frames[style][track] = new ArrayList(CELLS_PER_FRAME); - } + gH_SQL.Query(SQL_GetUserName_Callback, sQuery, pack, DBPrio_High); + } - gA_Frames[style][track].Resize(iTemp); + int cells = CELLS_PER_FRAME; - fFile.ReadInt32(iTemp); - gA_FrameCache[style][track].fTime = view_as(iTemp); + if(gA_FrameCache[style][track].iReplayVersion == 0x01) + { + cells = 6; + } - char sAuthID[32]; - fFile.ReadString(sAuthID, 32); + any[] aReplayData = new any[cells]; - if(gH_SQL != null) + for(int i = 0; i < gA_FrameCache[style][track].iFrameCount; i++) + { + if(file.Read(aReplayData, cells, 4) >= 0) + { + gA_Frames[style][track].Set(i, view_as(aReplayData[0]), 0); + gA_Frames[style][track].Set(i, view_as(aReplayData[1]), 1); + gA_Frames[style][track].Set(i, view_as(aReplayData[2]), 2); + gA_Frames[style][track].Set(i, view_as(aReplayData[3]), 3); + gA_Frames[style][track].Set(i, view_as(aReplayData[4]), 4); + gA_Frames[style][track].Set(i, view_as(aReplayData[5]), 5); + + if(gA_FrameCache[style][track].iReplayVersion >= 0x02) { - char sQuery[192]; - FormatEx(sQuery, 192, "SELECT name FROM %susers WHERE auth = '%s';", gS_MySQLPrefix, sAuthID); + gA_Frames[style][track].Set(i, view_as(aReplayData[6]), 6); + gA_Frames[style][track].Set(i, view_as(aReplayData[7]), 7); + } + } + } - DataPack pack = new DataPack(); - pack.WriteCell(style); - pack.WriteCell(track); + gA_FrameCache[style][track].bNewFormat = true; // not wr-based - gH_SQL.Query(SQL_GetUserName_Callback, sQuery, pack, DBPrio_High); - } + delete file; - int cells = CELLS_PER_FRAME; + return true; +} - // backwards compatibility - if(gA_FrameCache[style][track].iReplayVersion == 0x01) - { - cells = 6; - } +bool LoadV2ReplayFormat(File file, int frames, int style, int track) +{ + int iReplaySize = gA_FrameCache[style][track].iFrameCount = frames; + gA_Frames[style][track].Resize(iReplaySize); - any[] aReplayData = new any[cells]; + gA_FrameCache[style][track].fTime = 0.0; // N/A at this version - for(int i = 0; i < gA_FrameCache[style][track].iFrameCount; i++) - { - if(fFile.Read(aReplayData, cells, 4) >= 0) - { - gA_Frames[style][track].Set(i, view_as(aReplayData[0]), 0); - gA_Frames[style][track].Set(i, view_as(aReplayData[1]), 1); - gA_Frames[style][track].Set(i, view_as(aReplayData[2]), 2); - gA_Frames[style][track].Set(i, view_as(aReplayData[3]), 3); - gA_Frames[style][track].Set(i, view_as(aReplayData[4]), 4); - gA_Frames[style][track].Set(i, view_as(aReplayData[5]), 5); - - if(gA_FrameCache[style][track].iReplayVersion >= 0x02) - { - gA_Frames[style][track].Set(i, view_as(aReplayData[6]), 6); - gA_Frames[style][track].Set(i, view_as(aReplayData[7]), 7); - } - } - } + any[] aReplayData = new any[6]; - gA_FrameCache[style][track].bNewFormat = true; // not wr-based + for(int i = 0; i < iReplaySize; i++) + { + if(file.Read(aReplayData, 6, 4) >= 0) + { + gA_Frames[style][track].Set(i, view_as(aReplayData[0]), 0); + gA_Frames[style][track].Set(i, view_as(aReplayData[1]), 1); + gA_Frames[style][track].Set(i, view_as(aReplayData[2]), 2); + gA_Frames[style][track].Set(i, view_as(aReplayData[3]), 3); + gA_Frames[style][track].Set(i, view_as(aReplayData[4]), 4); + gA_Frames[style][track].Set(i, view_as(aReplayData[5]), 5); } + } - else if(StrEqual(sExplodedHeader[1], REPLAY_FORMAT_V2)) - { - int iReplaySize = gA_FrameCache[style][track].iFrameCount = StringToInt(sExplodedHeader[0]); - gA_Frames[style][track].Resize(iReplaySize); + gA_FrameCache[style][track].bNewFormat = false; + strcopy(gA_FrameCache[style][track].sReplayName, MAX_NAME_LENGTH, "invalid"); - gA_FrameCache[style][track].fTime = 0.0; // N/A at this version + delete file; - any[] aReplayData = new any[6]; + return true; +} - for(int i = 0; i < iReplaySize; i++) - { - if(fFile.Read(aReplayData, 6, 4) >= 0) - { - gA_Frames[style][track].Set(i, view_as(aReplayData[0]), 0); - gA_Frames[style][track].Set(i, view_as(aReplayData[1]), 1); - gA_Frames[style][track].Set(i, view_as(aReplayData[2]), 2); - gA_Frames[style][track].Set(i, view_as(aReplayData[3]), 3); - gA_Frames[style][track].Set(i, view_as(aReplayData[4]), 4); - gA_Frames[style][track].Set(i, view_as(aReplayData[5]), 5); - } - } +bool LoadOldReplayFormat(File file, int style, int track) +{ + char sLine[320]; + char sExplodedLine[6][64]; - gA_FrameCache[style][track].bNewFormat = false; - strcopy(gA_FrameCache[style][track].sReplayName, MAX_NAME_LENGTH, "invalid"); - } + if(!file.Seek(0, SEEK_SET)) + { + delete file; - else // old, outdated and slow - only used for ancient replays + return false; + } + + for(int i = 0; !file.EndOfFile(); i++) + { + file.ReadLine(sLine, 320); + int iStrings = ExplodeString(sLine, "|", sExplodedLine, 6, 64); + + gA_Frames[style][track].Resize(i + 1); + gA_Frames[style][track].Set(i, StringToFloat(sExplodedLine[0]), 0); + gA_Frames[style][track].Set(i, StringToFloat(sExplodedLine[1]), 1); + gA_Frames[style][track].Set(i, StringToFloat(sExplodedLine[2]), 2); + gA_Frames[style][track].Set(i, StringToFloat(sExplodedLine[3]), 3); + gA_Frames[style][track].Set(i, StringToFloat(sExplodedLine[4]), 4); + gA_Frames[style][track].Set(i, (iStrings == 6)? StringToInt(sExplodedLine[5]):0, 5); + } + + gA_FrameCache[style][track].iFrameCount = gA_Frames[style][track].Length; + gA_FrameCache[style][track].fTime = 0.0; // N/A at this version + gA_FrameCache[style][track].bNewFormat = false; // wr-based + strcopy(gA_FrameCache[style][track].sReplayName, MAX_NAME_LENGTH, "invalid"); + + delete file; + + return true; +} + +bool LoadReplay(int style, int track, const char[] path) +{ + if(FileExists(path)) + { + File fFile = OpenFile(path, "rb"); + + char sHeader[64]; + + if(!fFile.ReadLine(sHeader, 64)) { - char sLine[320]; - char sExplodedLine[6][64]; + delete fFile; - for(int i = 0; !fFile.EndOfFile(); i++) - { - fFile.ReadLine(sLine, 320); - int iStrings = ExplodeString(sLine, "|", sExplodedLine, 6, 64); - - gA_Frames[style][track].Resize(i + 1); - gA_Frames[style][track].Set(i, StringToFloat(sExplodedLine[0]), 0); - gA_Frames[style][track].Set(i, StringToFloat(sExplodedLine[1]), 1); - gA_Frames[style][track].Set(i, StringToFloat(sExplodedLine[2]), 2); - gA_Frames[style][track].Set(i, StringToFloat(sExplodedLine[3]), 3); - gA_Frames[style][track].Set(i, StringToFloat(sExplodedLine[4]), 4); - gA_Frames[style][track].Set(i, (iStrings == 6)? StringToInt(sExplodedLine[5]):0, 5); - } + return false; + } - gA_FrameCache[style][track].iFrameCount = gA_Frames[style][track].Length; - gA_FrameCache[style][track].fTime = 0.0; // N/A at this version - gA_FrameCache[style][track].bNewFormat = false; // wr-based - strcopy(gA_FrameCache[style][track].sReplayName, MAX_NAME_LENGTH, "invalid"); + TrimString(sHeader); + char sExplodedHeader[2][64]; + ExplodeString(sHeader, ":", sExplodedHeader, 2, 64); + + if(StrEqual(sExplodedHeader[1], REPLAY_FORMAT_FINAL)) // hopefully, the last of them + { + return LoadCurrentReplayFormat(fFile, StringToInt(sExplodedHeader[0]), style, track); } - delete fFile; + else if(StrEqual(sExplodedHeader[1], REPLAY_FORMAT_V2)) + { + return LoadV2ReplayFormat(fFile, StringToInt(sExplodedHeader[0]), style, track); + } - return true; + else // old, outdated and slow - only used for ancient replays + { + return LoadOldReplayFormat(fFile, style, track); + } } return false; From 44dfa5941e526c1f8271cdb2b26ede80cbf27d5e Mon Sep 17 00:00:00 2001 From: shavit Date: Fri, 3 May 2019 10:57:05 +0300 Subject: [PATCH 10/34] 2.5.5 --- addons/sourcemod/scripting/include/shavit.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/include/shavit.inc b/addons/sourcemod/scripting/include/shavit.inc index 04d8f7d6d..c9669d88d 100644 --- a/addons/sourcemod/scripting/include/shavit.inc +++ b/addons/sourcemod/scripting/include/shavit.inc @@ -23,7 +23,7 @@ #endif #define _shavit_included -#define SHAVIT_VERSION "2.5.4" +#define SHAVIT_VERSION "2.5.5" #define STYLE_LIMIT 256 #define MAX_ZONES 64 #define MAX_NAME_LENGTH_SQL 32 From 7f01ddee4bb62c02b23400b4a465d5f26958bb41 Mon Sep 17 00:00:00 2001 From: shavit Date: Sun, 12 May 2019 04:05:24 +0300 Subject: [PATCH 11/34] Added "shavit_rankings_llrecalc" as a major rankings optimization. --- addons/sourcemod/scripting/shavit-rankings.sp | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/addons/sourcemod/scripting/shavit-rankings.sp b/addons/sourcemod/scripting/shavit-rankings.sp index 0dfba6ed0..348ce8729 100644 --- a/addons/sourcemod/scripting/shavit-rankings.sp +++ b/addons/sourcemod/scripting/shavit-rankings.sp @@ -71,6 +71,7 @@ StringMap gA_MapTiers = null; ConVar gCV_PointsPerTier = null; ConVar gCV_WeightingMultiplier = null; +ConVar gCV_LastLoginRecalculate = null; ranking_t gA_Rankings[MAXPLAYERS+1]; @@ -150,6 +151,7 @@ public void OnPluginStart() gCV_PointsPerTier = CreateConVar("shavit_rankings_pointspertier", "50.0", "Base points to use for per-tier scaling.\nRead the design idea to see how it works: https://github.com/shavitush/bhoptimer/issues/465", 0, true, 1.0); gCV_WeightingMultiplier = CreateConVar("shavit_rankings_weighting", "0.975", "Weighing multiplier. 1.0 to disable weighting.\nFormula: p[1] * this^0 + p[2] * this^1 + p[3] * this^2 + ... + p[n] * this^(n-1)\nRestart server to apply.", 0, true, 0.01, true, 1.0); + gCV_LastLoginRecalculate = CreateConVar("shavit_rankings_llrecalc", "10080", "Maximum amount of time (in minutes) since last login to recalculate points for a player.\nsm_recalcall does not respect this setting.\n0 - disabled, don't filter anyone", 0, true, 0.0); AutoExecConfig(); @@ -708,7 +710,7 @@ public void Trans_OnRecalcSuccess(Database db, any data, int numQueries, DBResul ReplyToCommand(client, "- Finished recalculating all points. Recalculating user points, top 100 and user cache."); - UpdateAllPoints(); + UpdateAllPoints(true); UpdateTop100(); for(int i = 1; i <= MaxClients; i++) @@ -783,15 +785,25 @@ public void SQL_Recalculate_Callback(Database db, DBResultSet results, const cha #endif } -void UpdateAllPoints() +void UpdateAllPoints(bool recalcall = false) { #if defined DEBUG LogError("DEBUG: 6 (UpdateAllPoints)"); #endif char sQuery[256]; - FormatEx(sQuery, 256, "UPDATE %susers SET points = GetWeightedPoints(auth) WHERE auth IN (SELECT DISTINCT auth FROM %splayertimes);", - gS_MySQLPrefix, gS_MySQLPrefix); + + if(recalcall || gCV_LastLoginRecalculate.IntValue == 0) + { + FormatEx(sQuery, 256, "UPDATE %susers SET points = GetWeightedPoints(auth) WHERE auth IN (SELECT DISTINCT auth FROM %splayertimes);", + gS_MySQLPrefix, gS_MySQLPrefix); + } + + else + { + FormatEx(sQuery, 256, "UPDATE %susers SET points = GetWeightedPoints(auth) WHERE %d - lastlogin < %d AND auth IN (SELECT DISTINCT auth FROM %splayertimes);", + gS_MySQLPrefix, GetTime(), (gCV_LastLoginRecalculate.IntValue * 60), gS_MySQLPrefix); + } gH_SQL.Query(SQL_UpdateAllPoints_Callback, sQuery); } From dc11301325f67df566557f8172ec807489f83be7 Mon Sep 17 00:00:00 2001 From: shavit Date: Sun, 12 May 2019 07:53:25 +0300 Subject: [PATCH 12/34] Stopped saving custom chat if it wasn't changed. --- addons/sourcemod/scripting/shavit-chat.sp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/shavit-chat.sp b/addons/sourcemod/scripting/shavit-chat.sp index 83b03bd74..92f085abc 100644 --- a/addons/sourcemod/scripting/shavit-chat.sp +++ b/addons/sourcemod/scripting/shavit-chat.sp @@ -86,6 +86,8 @@ Handle gH_ChatCookie = null; int gI_ChatSelection[MAXPLAYERS+1]; ArrayList gA_ChatRanks = null; +bool gB_ChangedSinceLogin[MAXPLAYERS+1]; + bool gB_NameEnabled[MAXPLAYERS+1]; char gS_CustomName[MAXPLAYERS+1][128]; @@ -707,6 +709,11 @@ public Action Command_CCName(int client, int args) Shavit_PrintToChat(client, "%T", "ChatUpdated", client); + if(!StrEqual(gS_CustomName[client], sArgs)) + { + gB_ChangedSinceLogin[client] = true; + } + gB_NameEnabled[client] = true; strcopy(gS_CustomName[client], 128, sArgs); @@ -752,6 +759,11 @@ public Action Command_CCMessage(int client, int args) Shavit_PrintToChat(client, "%T", "ChatUpdated", client); + if(!StrEqual(gS_CustomMessage[client], sArgs)) + { + gB_ChangedSinceLogin[client] = true; + } + gB_MessageEnabled[client] = true; strcopy(gS_CustomMessage[client], 16, sArgs); @@ -1372,7 +1384,10 @@ public void SQL_CreateTable_Callback(Database db, DBResultSet results, const cha void SaveToDatabase(int client) { - char sAuthID3[32]; + if(!gB_ChangedSinceLogin[client]) + { + return; + } if(!GetClientAuthId(client, AuthId_Steam3, sAuthID3, 32)) { @@ -1441,6 +1456,8 @@ public void SQL_GetChat_Callback(Database db, DBResultSet results, const char[] return; } + gB_ChangedSinceLogin[client] = false; + while(results.FetchRow()) { gB_NameEnabled[client] = view_as(results.FetchInt(0)); From 547f90ef62ae981e39bcf9233e1709e1706113e5 Mon Sep 17 00:00:00 2001 From: shavit Date: Sun, 12 May 2019 07:57:04 +0300 Subject: [PATCH 13/34] Added automatic database migrations and revamped overall database structure. Now I can push database migrations without making the plugin's users do the querying on their own. List of migrations: * **Converted all SteamIDs in the database from SteamID3 to Steam Account ID format. The difference is simply stripping of the [U:1: prefix and ] suffix. This change speeds up the queries and reduces the database's size by a lot.** * Removal of `workshop/` paths from all map names in the database. * Added index to `lastlogin` to speedup the filtering I added to rankings with `shavit_rankings_llrecalc`. * Removed `country` from database. It was completely unnecessary. * Converted IP addresses from plaintext to a single 4 bytes integer. * Converted `date` of records from a string to integer. --- addons/sourcemod/scripting/include/shavit.inc | 38 +- addons/sourcemod/scripting/shavit-chat.sp | 18 +- addons/sourcemod/scripting/shavit-core.sp | 371 ++++++++++++++---- addons/sourcemod/scripting/shavit-misc.sp | 10 +- addons/sourcemod/scripting/shavit-rankings.sp | 20 +- addons/sourcemod/scripting/shavit-replay.sp | 38 +- addons/sourcemod/scripting/shavit-stats.sp | 106 ++--- addons/sourcemod/scripting/shavit-wr.sp | 101 +++-- 8 files changed, 491 insertions(+), 211 deletions(-) diff --git a/addons/sourcemod/scripting/include/shavit.inc b/addons/sourcemod/scripting/include/shavit.inc index c9669d88d..044d66d10 100644 --- a/addons/sourcemod/scripting/include/shavit.inc +++ b/addons/sourcemod/scripting/include/shavit.inc @@ -74,6 +74,21 @@ enum CPR_NotOnGround = (1 << 3) }; +enum +{ + Migration_RemoveWorkshopMaptiers, + Migration_RemoveWorkshopMapzones, + Migration_RemoveWorkshopPlayertimes, + Migration_LastLoginIndex, + Migration_RemoveCountry, + Migration_ConvertIPAddresses, + Migration_ConvertSteamIDsUsers, + Migration_ConvertSteamIDsPlayertimes, + Migration_ConvertSteamIDsChat, + Migration_PlayertimesDateToInt, + MIGRATIONS_END +}; + enum { Zone_Start, @@ -259,6 +274,25 @@ stock bool IsSource2013(EngineVersion ev) return (ev == Engine_CSS || ev == Engine_TF2); } +stock void IPAddressToString(int ip, char[] buffer, int maxlen) +{ + FormatEx(buffer, maxlen, "%d.%d.%d.%d", ((ip >> 24) & 0xFF), ((ip >> 16) & 0xFF), ((ip >> 8) & 0xFF), (ip & 0xFF)); +} + +stock int IPStringToAddress(const char[] ip) +{ + char sExplodedAddress[4][4]; + ExplodeString(ip, ".", sExplodedAddress, 4, 4, false); + + int iIPAddress = + (StringToInt(sExplodedAddress[0]) << 24) | + (StringToInt(sExplodedAddress[1]) << 16) | + (StringToInt(sExplodedAddress[2]) << 8) | + StringToInt(sExplodedAddress[3]); + + return iIPAddress; +} + // time formatting! stock void FormatSeconds(float time, char[] newtime, int newtimesize, bool precise = true) { @@ -1132,10 +1166,10 @@ native int Shavit_ForceHUDUpdate(int client, bool spectators); * Opens the stats menu for a client. * * @param client Client index. - * @param authid Target SteamID3 to use. + * @param steamid Target Steam account ID to use. * @noreturn */ -native void Shavit_OpenStatsMenu(int client, const char[] authid); +native void Shavit_OpenStatsMenu(int client, int steamid); /** * Retrieves the amount of #1 records a player has. diff --git a/addons/sourcemod/scripting/shavit-chat.sp b/addons/sourcemod/scripting/shavit-chat.sp index 92f085abc..694628d1f 100644 --- a/addons/sourcemod/scripting/shavit-chat.sp +++ b/addons/sourcemod/scripting/shavit-chat.sp @@ -1344,14 +1344,14 @@ void SQL_DBConnect() if(bMySQL) { FormatEx(sQuery, 512, - "CREATE TABLE IF NOT EXISTS `%schat` (`auth` VARCHAR(32) NOT NULL, `name` INT NOT NULL DEFAULT 0, `ccname` VARCHAR(128) COLLATE 'utf8mb4_unicode_ci', `message` INT NOT NULL DEFAULT 0, `ccmessage` VARCHAR(16) COLLATE 'utf8mb4_unicode_ci', PRIMARY KEY (`auth`), CONSTRAINT `%sch_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE) ENGINE=INNODB;", + "CREATE TABLE IF NOT EXISTS `%schat` (`auth` INT NOT NULL, `name` INT NOT NULL DEFAULT 0, `ccname` VARCHAR(128) COLLATE 'utf8mb4_unicode_ci', `message` INT NOT NULL DEFAULT 0, `ccmessage` VARCHAR(16) COLLATE 'utf8mb4_unicode_ci', PRIMARY KEY (`auth`), CONSTRAINT `%sch_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE) ENGINE=INNODB;", gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix); } else { FormatEx(sQuery, 512, - "CREATE TABLE IF NOT EXISTS `%schat` (`auth` VARCHAR(32) NOT NULL, `name` INT NOT NULL DEFAULT 0, `ccname` VARCHAR(128), `message` INT NOT NULL DEFAULT 0, `ccmessage` VARCHAR(16), PRIMARY KEY (`auth`), CONSTRAINT `%sch_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE);", + "CREATE TABLE IF NOT EXISTS `%schat` (`auth` INT NOT NULL, `name` INT NOT NULL DEFAULT 0, `ccname` VARCHAR(128), `message` INT NOT NULL DEFAULT 0, `ccmessage` VARCHAR(16), PRIMARY KEY (`auth`), CONSTRAINT `%sch_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE);", gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix); } @@ -1389,7 +1389,9 @@ void SaveToDatabase(int client) return; } - if(!GetClientAuthId(client, AuthId_Steam3, sAuthID3, 32)) + int iSteamID = GetSteamAccountID(client); + + if(iSteamID == 0) { return; } @@ -1404,8 +1406,8 @@ void SaveToDatabase(int client) char sQuery[512]; FormatEx(sQuery, 512, - "REPLACE INTO %schat (auth, name, ccname, message, ccmessage) VALUES ('%s', %d, '%s', %d, '%s');", - gS_MySQLPrefix, sAuthID3, gB_NameEnabled[client], sEscapedName, gB_MessageEnabled[client], sEscapedMessage); + "REPLACE INTO %schat (auth, name, ccname, message, ccmessage) VALUES (%d, %d, '%s', %d, '%s');", + gS_MySQLPrefix, iSteamID, gB_NameEnabled[client], sEscapedName, gB_MessageEnabled[client], sEscapedMessage); gH_SQL.Query(SQL_UpdateUser_Callback, sQuery, 0, DBPrio_Low); } @@ -1427,15 +1429,15 @@ void LoadFromDatabase(int client) return; } - char sAuthID3[32]; + int iSteamID = GetSteamAccountID(client); - if(!GetClientAuthId(client, AuthId_Steam3, sAuthID3, 32)) + if(iSteamID == 0) { return; } char sQuery[256]; - FormatEx(sQuery, 256, "SELECT name, ccname, message, ccmessage FROM %schat WHERE auth = '%s';", gS_MySQLPrefix, sAuthID3); + FormatEx(sQuery, 256, "SELECT name, ccname, message, ccmessage FROM %schat WHERE auth = %d;", gS_MySQLPrefix, iSteamID); gH_SQL.Query(SQL_GetChat_Callback, sQuery, GetClientSerial(client), DBPrio_Low); } diff --git a/addons/sourcemod/scripting/shavit-core.sp b/addons/sourcemod/scripting/shavit-core.sp index bd85a9d24..88fa0655d 100644 --- a/addons/sourcemod/scripting/shavit-core.sp +++ b/addons/sourcemod/scripting/shavit-core.sp @@ -711,16 +711,23 @@ public Action Command_WipePlayer(int client, int args) void DeleteUserData(int client, const char[] sAuthID3) { + char sAuthID[32]; + strcopy(sAuthID, 32, sAuthID3); + ReplaceString(sAuthID, 32, "[U:1:", ""); + ReplaceString(sAuthID, 32, "]", ""); + + int iSteamID = StringToInt(sAuthID); + if(gB_Replay) { char sQueryGetWorldRecords[256]; FormatEx(sQueryGetWorldRecords, 256, - "SELECT map, id, style, track FROM %splayertimes WHERE auth = '%s';", - gS_MySQLPrefix, sAuthID3); + "SELECT map, id, style, track FROM %splayertimes WHERE auth = %d;", + gS_MySQLPrefix, iSteamID); DataPack hPack = new DataPack(); hPack.WriteCell(client); - hPack.WriteString(sAuthID3); + hPack.WriteCell(iSteamID); gH_SQL.Query(SQL_DeleteUserData_GetRecords_Callback, sQueryGetWorldRecords, hPack, DBPrio_High); } @@ -729,14 +736,14 @@ void DeleteUserData(int client, const char[] sAuthID3) { char sQueryDeleteUserTimes[256]; FormatEx(sQueryDeleteUserTimes, 256, - "DELETE FROM %splayertimes WHERE auth = '%s';", - gS_MySQLPrefix, sAuthID3); + "DELETE FROM %splayertimes WHERE auth = %d;", + gS_MySQLPrefix, iSteamID); - DataPack steamPack = new DataPack(); - steamPack.WriteString(sAuthID3); - steamPack.WriteCell(client); + DataPack hSteamPack = new DataPack(); + hSteamPack.WriteCell(iSteamID); + hSteamPack.WriteCell(client); - gH_SQL.Query(SQL_DeleteUserTimes_Callback, sQueryDeleteUserTimes, steamPack, DBPrio_High); + gH_SQL.Query(SQL_DeleteUserTimes_Callback, sQueryDeleteUserTimes, hSteamPack, DBPrio_High); } } @@ -745,9 +752,7 @@ public void SQL_DeleteUserData_GetRecords_Callback(Database db, DBResultSet resu DataPack hPack = view_as(data); hPack.Reset(); int client = hPack.ReadCell(); - - char sAuthID3[32]; - hPack.ReadString(sAuthID3, 32); + int iSteamID = hPack.ReadCell(); delete hPack; if(results == null) @@ -782,19 +787,18 @@ public void SQL_DeleteUserData_GetRecords_Callback(Database db, DBResultSet resu hTransaction.AddQuery(sQueryGetWorldRecordID, hTransPack); } - DataPack steamPack = new DataPack(); - steamPack.WriteString(sAuthID3); - steamPack.WriteCell(client); + DataPack hSteamPack = new DataPack(); + hSteamPack.WriteCell(iSteamID); + hSteamPack.WriteCell(client); - gH_SQL.Execute(hTransaction, Trans_OnRecordCompare, INVALID_FUNCTION, steamPack, DBPrio_High); + gH_SQL.Execute(hTransaction, Trans_OnRecordCompare, INVALID_FUNCTION, hSteamPack, DBPrio_High); } public void Trans_OnRecordCompare(Database db, any data, int numQueries, DBResultSet[] results, any[] queryData) { - DataPack pack = view_as(data); - pack.Reset(); - char sAuthID3[32]; - pack.ReadString(sAuthID3, 32); + DataPack hPack = view_as(data); + hPack.Reset(); + int iSteamID = hPack.ReadCell(); for(int i = 0; i < numQueries; i++) { @@ -821,55 +825,53 @@ public void Trans_OnRecordCompare(Database db, any data, int numQueries, DBResul char sQueryDeleteUserTimes[256]; FormatEx(sQueryDeleteUserTimes, 256, - "DELETE FROM %splayertimes WHERE auth = '%s';", - gS_MySQLPrefix, sAuthID3); + "DELETE FROM %splayertimes WHERE auth = %d;", + gS_MySQLPrefix, iSteamID); - gH_SQL.Query(SQL_DeleteUserTimes_Callback, sQueryDeleteUserTimes, pack, DBPrio_High); + gH_SQL.Query(SQL_DeleteUserTimes_Callback, sQueryDeleteUserTimes, hPack, DBPrio_High); } public void SQL_DeleteUserTimes_Callback(Database db, DBResultSet results, const char[] error, any data) { - DataPack pack = view_as(data); - pack.Reset(); - char sAuthID3[32]; - pack.ReadString(sAuthID3, 32); + DataPack hPack = view_as(data); + hPack.Reset(); + int iSteamID = hPack.ReadCell(); if(results == null) { LogError("Timer error! Failed to wipe user data (wipe | delete user times). Reason: %s", error); - delete pack; + delete hPack; return; } char sQueryDeleteUsers[256]; - FormatEx(sQueryDeleteUsers, 256, "DELETE FROM %susers WHERE auth = '%s';", - gS_MySQLPrefix, sAuthID3); + FormatEx(sQueryDeleteUsers, 256, "DELETE FROM %susers WHERE auth = %d;", + gS_MySQLPrefix, iSteamID); - gH_SQL.Query(SQL_DeleteUserData_Callback, sQueryDeleteUsers, pack, DBPrio_High); + gH_SQL.Query(SQL_DeleteUserData_Callback, sQueryDeleteUsers, hPack, DBPrio_High); } public void SQL_DeleteUserData_Callback(Database db, DBResultSet results, const char[] error, any data) { - DataPack pack = view_as(data); - pack.Reset(); - char sAuthID3[32]; - pack.ReadString(sAuthID3, 32); - int client = pack.ReadCell(); - delete pack; + DataPack hPack = view_as(data); + hPack.Reset(); + int iSteamID = hPack.ReadCell(); + int client = hPack.ReadCell(); + delete hPack; if(results == null) { - LogError("Timer error! Failed to wipe user data (wipe | delete user data, id %s). Reason: %s", error, sAuthID3); + LogError("Timer error! Failed to wipe user data (wipe | delete user data, id [U:1:%d]). Reason: %s", error, iSteamID); return; } Shavit_ReloadLeaderboards(); - Shavit_PrintToChat(client, "Finished wiping timer data for user %s%s%s.", - gS_ChatStrings.sVariable, sAuthID3, gS_ChatStrings.sText); + Shavit_PrintToChat(client, "Finished wiping timer data for user %s[U:1:%d]%s.", + gS_ChatStrings.sVariable, iSteamID, gS_ChatStrings.sText); } public Action Command_AutoBhop(int client, int args) @@ -1870,9 +1872,9 @@ public void OnClientPutInServer(int client) SDKHook(client, SDKHook_PreThinkPost, PreThinkPost); - char sAuthID3[32]; + int iSteamID = GetSteamAccountID(client); - if(!GetClientAuthId(client, AuthId_Steam3, sAuthID3, 32)) + if(iSteamID == 0) { KickClient(client, "%T", "VerificationFailed", client); @@ -1887,15 +1889,9 @@ public void OnClientPutInServer(int client) char[] sEscapedName = new char[iLength]; gH_SQL.Escape(sName, sEscapedName, iLength); - char sIP[64]; - GetClientIP(client, sIP, 64); - - char sCountry[128]; - - if(!GeoipCountry(sIP, sCountry, 128)) - { - strcopy(sCountry, 128, "Local Area Network"); - } + char sIPAddress[64]; + GetClientIP(client, sIPAddress, 64); + int iIPAddress = IPStringToAddress(sIPAddress); int iTime = GetTime(); @@ -1903,12 +1899,16 @@ public void OnClientPutInServer(int client) if(gB_MySQL) { - FormatEx(sQuery, 512, "INSERT INTO %susers (auth, name, country, ip, lastlogin) VALUES ('%s', '%s', '%s', '%s', %d) ON DUPLICATE KEY UPDATE name = '%s', country = '%s', ip = '%s', lastlogin = %d;", gS_MySQLPrefix, sAuthID3, sEscapedName, sCountry, sIP, iTime, sEscapedName, sCountry, sIP, iTime); + FormatEx(sQuery, 512, + "INSERT INTO %susers (auth, name, ip, lastlogin) VALUES (%d, '%s', %d, %d) ON DUPLICATE KEY UPDATE name = '%s', ip = %d, lastlogin = %d;", + gS_MySQLPrefix, iSteamID, sEscapedName, iIPAddress, iTime, sEscapedName, iIPAddress, iTime); } else { - FormatEx(sQuery, 512, "REPLACE INTO %susers (auth, name, country, ip, lastlogin) VALUES ('%s', '%s', '%s', '%s', %d);", gS_MySQLPrefix, sAuthID3, sEscapedName, sCountry, sIP, iTime); + FormatEx(sQuery, 512, + "REPLACE INTO %susers (auth, name, ip, lastlogin) VALUES (%d, '%s', %d, %d);", + gS_MySQLPrefix, iSteamID, sEscapedName, iIPAddress, iTime); } gH_SQL.Query(SQL_InsertUser_Callback, sQuery, GetClientSerial(client)); @@ -2212,30 +2212,210 @@ void SQL_DBConnect() gH_SQL.Driver.GetIdentifier(sDriver, 8); gB_MySQL = StrEqual(sDriver, "mysql", false); - char sQuery[512]; - + // migrations will only exist for mysql. sorry sqlite users if(gB_MySQL) { - FormatEx(sQuery, 512, "CREATE TABLE IF NOT EXISTS `%susers` (`auth` VARCHAR(32) NOT NULL, `name` VARCHAR(32) COLLATE 'utf8mb4_general_ci', `country` VARCHAR(32), `ip` VARCHAR(64), `lastlogin` INT NOT NULL DEFAULT -1, `points` FLOAT NOT NULL DEFAULT 0, PRIMARY KEY (`auth`), INDEX `points` (`points`)) ENGINE=INNODB;", gS_MySQLPrefix); + char sQuery[128]; + FormatEx(sQuery, 128, "CREATE TABLE IF NOT EXISTS `%smigrations` (`code` TINYINT NOT NULL, UNIQUE INDEX `code` (`code`));", gS_MySQLPrefix); + + gH_SQL.Query(SQL_CreateMigrationsTable_Callback, sQuery, 0, DBPrio_High); } - else + CreateUsersTable(); +} + +public void SQL_CreateMigrationsTable_Callback(Database db, DBResultSet results, const char[] error, any data) +{ + if(results == null) { - FormatEx(sQuery, 512, "CREATE TABLE IF NOT EXISTS `%susers` (`auth` VARCHAR(32) NOT NULL PRIMARY KEY, `name` VARCHAR(32), `country` VARCHAR(32), `ip` VARCHAR(64), `lastlogin` INTEGER NOT NULL DEFAULT -1, `points` FLOAT NOT NULL DEFAULT 0);", gS_MySQLPrefix); + LogError("Timer error! Migrations table creation failed. Reason: %s", error); + + return; } - gH_SQL.Query(SQL_CreateTable_Callback, sQuery, 0, DBPrio_High); + char sQuery[128]; + FormatEx(sQuery, 128, "SELECT code FROM %smigrations;", gS_MySQLPrefix); + + gH_SQL.Query(SQL_SelectMigrations_Callback, sQuery, 0, DBPrio_High); } -public void SQL_CreateTable_Callback(Database db, DBResultSet results, const char[] error, any data) +public void SQL_SelectMigrations_Callback(Database db, DBResultSet results, const char[] error, any data) { if(results == null) { - LogError("Timer error! Users' data table creation failed. Reason: %s", error); + LogError("Timer error! Migrations selection failed. Reason: %s", error); return; } + // this is ugly, i know. but it works and is more elegant than previous solutions so.. let it be =) + bool bMigrationApplied[255] = { false, ... }; + + while(results.FetchRow()) + { + bMigrationApplied[results.FetchInt(0)] = true; + } + + for(int i = 0; i < MIGRATIONS_END; i++) + { + if(!bMigrationApplied[i]) + { + PrintToServer("--- Applying database migration %d ---", i); + ApplyMigration(i); + } + } +} + +void ApplyMigration(int migration) +{ + switch(migration) + { + case Migration_RemoveWorkshopMaptiers, Migration_RemoveWorkshopMapzones, Migration_RemoveWorkshopPlayertimes: ApplyMigration_RemoveWorkshopPath(migration); + case Migration_LastLoginIndex: ApplyMigration_LastLoginIndex(); + case Migration_RemoveCountry: ApplyMigration_RemoveCountry(); + case Migration_ConvertIPAddresses: ApplyMigration_ConvertIPAddresses(); + case Migration_ConvertSteamIDsUsers: ApplyMigration_ConvertSteamIDs(); + case Migration_ConvertSteamIDsPlayertimes, Migration_ConvertSteamIDsChat: return; // this is confusing, but the above case handles all of them + case Migration_PlayertimesDateToInt: ApplyMigration_PlayertimesDateToInt(); + } +} + +void ApplyMigration_LastLoginIndex() +{ + char sQuery[128]; + FormatEx(sQuery, 128, "ALTER TABLE `%susers` ADD INDEX `lastlogin` (`lastlogin`);", gS_MySQLPrefix); + gH_SQL.Query(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_LastLoginIndex, DBPrio_High); +} + +void ApplyMigration_RemoveCountry() +{ + char sQuery[128]; + FormatEx(sQuery, 128, "ALTER TABLE `%susers` DROP COLUMN `country`;", gS_MySQLPrefix); + gH_SQL.Query(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_RemoveCountry, DBPrio_High); +} + +void ApplyMigration_PlayertimesDateToInt() +{ + char sQuery[128]; + FormatEx(sQuery, 128, "ALTER TABLE `%splayertimes` CHANGE COLUMN `date` `date` INT;", gS_MySQLPrefix); + gH_SQL.Query(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_PlayertimesDateToInt, DBPrio_High); +} + +public void SQL_TableMigrationSingleQuery_Callback(Database db, DBResultSet results, const char[] error, any data) +{ + InsertMigration(data); + + // i hate hardcoding REEEEEEEE + if(data == Migration_ConvertSteamIDsChat) + { + char sQuery[256]; + FormatEx(sQuery, 256, + "ALTER TABLE `%splayertimes` ADD CONSTRAINT `pt_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE;", + gS_MySQLPrefix, gS_MySQLPrefix); + gH_SQL.Query(SQL_TableMigrationConstraints_Callback, sQuery, 0, DBPrio_High); + + FormatEx(sQuery, 256, + "ALTER TABLE `%schat` ADD CONSTRAINT `ch_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE;", + gS_MySQLPrefix, gS_MySQLPrefix); + gH_SQL.Query(SQL_TableMigrationConstraints_Callback, sQuery, 0, DBPrio_High); + } +} + +void ApplyMigration_ConvertIPAddresses() +{ + char sQuery[128]; + FormatEx(sQuery, 128, "SELECT DISTINCT ip FROM %susers WHERE ip LIKE \"\%%.\%%\";", gS_MySQLPrefix); + gH_SQL.Query(SQL_TableMigrationIPAddresses_Callback, sQuery, 0, DBPrio_High); +} + +public void SQL_TableMigrationIPAddresses_Callback(Database db, DBResultSet results, const char[] error, DataPack data) +{ + if(results == null || results.RowCount == 0) + { + InsertMigration(Migration_ConvertIPAddresses); + + return; + } + + Transaction hTransaction = new Transaction(); + + while(results.FetchRow()) + { + char sIPAddress[32]; + results.FetchString(0, sIPAddress, 32); + + char sExplodedAddress[4][4]; + ExplodeString(sIPAddress, ".", sExplodedAddress, 4, 4, false); + + int iIPAddress = + (StringToInt(sExplodedAddress[0]) << 24) | + (StringToInt(sExplodedAddress[1]) << 16) | + (StringToInt(sExplodedAddress[2]) << 8) | + StringToInt(sExplodedAddress[3]); + + char sQuery[256]; + FormatEx(sQuery, 256, "UPDATE %susers SET ip = %d WHERE ip = '%s';", gS_MySQLPrefix, iIPAddress, sIPAddress); + + hTransaction.AddQuery(sQuery); + } + + gH_SQL.Execute(hTransaction, Trans_IPAddressMigration); +} + +public void Trans_IPAddressMigration(Database db, any data, int numQueries, DBResultSet[] results, any[] queryData) +{ + char sQuery[128]; + FormatEx(sQuery, 128, "ALTER TABLE `%susers` CHANGE COLUMN `ip` `ip` INT;", gS_MySQLPrefix); + gH_SQL.Query(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_ConvertIPAddresses, DBPrio_High); +} + +void ApplyMigration_ConvertSteamIDs() +{ + char sTables[][] = + { + "users", + "playertimes", + "chat" + }; + + char sQuery[128]; + FormatEx(sQuery, 128, "ALTER TABLE `%splayertimes` DROP CONSTRAINT `pt_auth`;", gS_MySQLPrefix); + gH_SQL.Query(SQL_TableMigrationConstraints_Callback, sQuery, 0, DBPrio_High); + + FormatEx(sQuery, 128, "ALTER TABLE `%schat` DROP CONSTRAINT `ch_auth`;", gS_MySQLPrefix); + gH_SQL.Query(SQL_TableMigrationConstraints_Callback, sQuery, 0, DBPrio_High); + + for(int i = 0; i < sizeof(sTables); i++) + { + DataPack hPack = new DataPack(); + hPack.WriteCell(Migration_ConvertSteamIDsUsers + i); + hPack.WriteString(sTables[i]); + + FormatEx(sQuery, 128, "UPDATE %s%s SET auth = REPLACE(REPLACE(auth, \"[U:1:\", \"\"), \"]\", \"\") WHERE auth LIKE '[%%';", sTables[i], gS_MySQLPrefix); + gH_SQL.Query(SQL_TableMigrationSteamIDs_Callback, sQuery, hPack, DBPrio_High); + } +} + +public void SQL_TableMigrationConstraints_Callback(Database db, DBResultSet results, const char[] error, DataPack data) +{ + // nothing +} + +public void SQL_TableMigrationSteamIDs_Callback(Database db, DBResultSet results, const char[] error, DataPack data) +{ + data.Reset(); + int iMigration = data.ReadCell(); + char sTable[16]; + data.ReadString(sTable, 16); + delete data; + + char sQuery[128]; + FormatEx(sQuery, 128, "ALTER TABLE `%s%s` CHANGE COLUMN `auth` `auth` INT;", gS_MySQLPrefix, sTable); + gH_SQL.Query(SQL_TableMigrationSingleQuery_Callback, sQuery, iMigration, DBPrio_High); +} + +void ApplyMigration_RemoveWorkshopPath(int migration) +{ char sTables[][] = { "maptiers", @@ -2245,31 +2425,34 @@ public void SQL_CreateTable_Callback(Database db, DBResultSet results, const cha for(int i = 0; i < sizeof(sTables); i++) { - DataPack dp = new DataPack(); - dp.WriteString(sTables[i]); + DataPack hPack = new DataPack(); + hPack.WriteCell(migration); + hPack.WriteString(sTables[i]); char sQuery[192]; FormatEx(sQuery, 192, "SELECT map FROM %s%s WHERE map LIKE 'workshop%%' GROUP BY map;", gS_MySQLPrefix, sTables[i]); - gH_SQL.Query(SQL_TableMigration_Callback, sQuery, dp, DBPrio_High); + gH_SQL.Query(SQL_TableMigrationWorkshop_Callback, sQuery, hPack, DBPrio_High); } - - Call_StartForward(gH_Forwards_OnDatabaseLoaded); - Call_Finish(); } -public void SQL_TableMigration_Callback(Database db, DBResultSet results, const char[] error, DataPack data) +public void SQL_TableMigrationWorkshop_Callback(Database db, DBResultSet results, const char[] error, DataPack data) { - char sTable[16]; data.Reset(); + int iMigration = data.ReadCell(); + char sTable[16]; data.ReadString(sTable, 16); delete data; if(results == null || results.RowCount == 0) { // no error logging here because not everyone runs the rankings/wr modules + InsertMigration(iMigration); + return; } + Transaction hTransaction = new Transaction(); + while(results.FetchRow()) { char sMap[160]; @@ -2280,18 +2463,62 @@ public void SQL_TableMigration_Callback(Database db, DBResultSet results, const char sQuery[256]; FormatEx(sQuery, 256, "UPDATE %s%s SET map = '%s' WHERE map = '%s';", gS_MySQLPrefix, sTable, sDisplayMap, sMap); - gH_SQL.Query(SQL_AlterTable3_Callback, sQuery, 0, DBPrio_High); + + hTransaction.AddQuery(sQuery); } + + gH_SQL.Execute(hTransaction, Trans_WorkshopMigration, INVALID_FUNCTION, iMigration); } -public void SQL_AlterTable3_Callback(Database db, DBResultSet results, const char[] error, any data) +public void Trans_WorkshopMigration(Database db, any data, int numQueries, DBResultSet[] results, any[] queryData) +{ + InsertMigration(data); +} + +void InsertMigration(int migration) +{ + char sQuery[128]; + FormatEx(sQuery, 128, "INSERT INTO %smigrations (code) VALUES (%d);", gS_MySQLPrefix, migration); + gH_SQL.Query(SQL_MigrationApplied_Callback, sQuery, migration); +} + +public void SQL_MigrationApplied_Callback(Database db, DBResultSet results, const char[] error, any data) +{ + // nothing +} + +void CreateUsersTable() +{ + char sQuery[512]; + + 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;", + 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);", + gS_MySQLPrefix); + } + + gH_SQL.Query(SQL_CreateUsersTable_Callback, sQuery, 0, DBPrio_High); +} + +public void SQL_CreateUsersTable_Callback(Database db, DBResultSet results, const char[] error, any data) { if(results == null) { - LogError("Timer error! Table alteration 3 (core) failed. Reason: %s", error); + LogError("Timer error! Users' data table creation failed. Reason: %s", error); return; } + + Call_StartForward(gH_Forwards_OnDatabaseLoaded); + Call_Finish(); } public void PreThinkPost(int client) diff --git a/addons/sourcemod/scripting/shavit-misc.sp b/addons/sourcemod/scripting/shavit-misc.sp index ce9c31af8..e9fdbfad6 100644 --- a/addons/sourcemod/scripting/shavit-misc.sp +++ b/addons/sourcemod/scripting/shavit-misc.sp @@ -75,7 +75,7 @@ enum struct player_cpcache_t enum struct persistent_data_t { - char sAuthID[32]; + int iSteamID; float fDisconnectTime; float fPosition[3]; float fAngles[3]; @@ -1127,7 +1127,7 @@ void PersistData(int client) if(!IsClientInGame(client) || !IsPlayerAlive(client) || - !GetClientAuthId(client, AuthId_Steam3, aData.sAuthID, 32) || + (aData.iSteamID = GetSteamAccountID((client))) == 0 || Shavit_GetTimerStatus(client) == Timer_Stopped || gCV_PersistData.IntValue == 0) { @@ -1188,11 +1188,11 @@ void DeletePersistentData(int index, persistent_data_t data) public Action Timer_LoadPersistentData(Handle Timer, any data) { - char sAuthID[32]; + int iSteamID = 0; int client = GetClientFromSerial(data); if(client == 0 || - !GetClientAuthId(client, AuthId_Steam3, sAuthID, 32) || + (iSteamID = GetSteamAccountID(client)) == 0 || GetClientTeam(client) < 2 || !IsPlayerAlive(client)) { @@ -1207,7 +1207,7 @@ public Action Timer_LoadPersistentData(Handle Timer, any data) { gA_PersistentData.GetArray(i, aData); - if(StrEqual(sAuthID, aData.sAuthID)) + if(iSteamID == aData.iSteamID) { iIndex = i; diff --git a/addons/sourcemod/scripting/shavit-rankings.sp b/addons/sourcemod/scripting/shavit-rankings.sp index 348ce8729..2c1a2888c 100644 --- a/addons/sourcemod/scripting/shavit-rankings.sp +++ b/addons/sourcemod/scripting/shavit-rankings.sp @@ -312,7 +312,7 @@ public void SQL_CreateTable_Callback(Database db, DBResultSet results, const cha bool bSuccess = true; RunLongFastQuery(bSuccess, "CREATE GetWeightedPoints", - "CREATE FUNCTION GetWeightedPoints(authid VARCHAR(32)) " ... + "CREATE FUNCTION GetWeightedPoints(steamid INT) " ... "RETURNS FLOAT " ... "READS SQL DATA " ... "BEGIN " ... @@ -320,7 +320,7 @@ public void SQL_CreateTable_Callback(Database db, DBResultSet results, const cha "DECLARE total FLOAT DEFAULT 0.0; " ... "DECLARE mult FLOAT DEFAULT 1.0; " ... "DECLARE done INT DEFAULT 0; " ... - "DECLARE cur CURSOR FOR SELECT points FROM %splayertimes WHERE auth = authid AND points > 0.0 ORDER BY points DESC; " ... + "DECLARE cur CURSOR FOR SELECT points FROM %splayertimes WHERE auth = steamid AND points > 0.0 ORDER BY points DESC; " ... "DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; " ... "OPEN cur; " ... "iter: LOOP " ... @@ -610,7 +610,7 @@ public int MenuHandler_Top(Menu menu, MenuAction action, int param1, int param2) if(gB_Stats && !StrEqual(sInfo, "-1")) { - Shavit_OpenStatsMenu(param1, sInfo); + Shavit_OpenStatsMenu(param1, StringToInt(sInfo)); } } @@ -823,15 +823,15 @@ void UpdatePlayerRank(int client, bool first) gA_Rankings[client].iRank = 0; gA_Rankings[client].fPoints = 0.0; - char sAuthID[32]; + int iSteamID = 0; - if(GetClientAuthId(client, AuthId_Steam3, sAuthID, 32)) + if((iSteamID = GetSteamAccountID(client)) != 0) { // if there's any issue with this query, // add "ORDER BY points DESC " before "LIMIT 1" char sQuery[512]; - FormatEx(sQuery, 512, "SELECT u2.points, COUNT(*) FROM %susers u1 JOIN (SELECT points FROM %susers WHERE auth = '%s') u2 WHERE u1.points >= u2.points;", - gS_MySQLPrefix, gS_MySQLPrefix, sAuthID); + FormatEx(sQuery, 512, "SELECT u2.points, COUNT(*) FROM %susers u1 JOIN (SELECT points FROM %susers WHERE auth = %d) u2 WHERE u1.points >= u2.points;", + gS_MySQLPrefix, gS_MySQLPrefix, iSteamID); DataPack hPack = new DataPack(); hPack.WriteCell(GetClientSerial(client)); @@ -936,8 +936,8 @@ public void SQL_UpdateTop100_Callback(Database db, DBResultSet results, const ch break; } - char sAuthID[32]; - results.FetchString(0, sAuthID, 32); + char sSteamID[32]; + results.FetchString(0, sSteamID, 32); char sName[MAX_NAME_LENGTH]; results.FetchString(1, sName, MAX_NAME_LENGTH); @@ -947,7 +947,7 @@ public void SQL_UpdateTop100_Callback(Database db, DBResultSet results, const ch char sDisplay[96]; FormatEx(sDisplay, 96, "#%d - %s (%s)", (++row), sName, sPoints); - gH_Top100Menu.AddItem(sAuthID, sDisplay); + gH_Top100Menu.AddItem(sSteamID, sDisplay); } if(gH_Top100Menu.ItemCount == 0) diff --git a/addons/sourcemod/scripting/shavit-replay.sp b/addons/sourcemod/scripting/shavit-replay.sp index a3da88023..61c241ba5 100644 --- a/addons/sourcemod/scripting/shavit-replay.sp +++ b/addons/sourcemod/scripting/shavit-replay.sp @@ -33,7 +33,7 @@ #define REPLAY_FORMAT_V2 "{SHAVITREPLAYFORMAT}{V2}" #define REPLAY_FORMAT_FINAL "{SHAVITREPLAYFORMAT}{FINAL}" -#define REPLAY_FORMAT_SUBVERSION 0x03 +#define REPLAY_FORMAT_SUBVERSION 0x04 #define CELLS_PER_FRAME 8 // origin[3], angles[2], buttons, flags, movetype #define FRAMES_PER_WRITE 100 // amounts of frames to write per read/write call @@ -1015,19 +1015,32 @@ bool LoadCurrentReplayFormat(File file, int version, int style, int track) file.ReadInt32(iTemp); gA_FrameCache[style][track].fTime = view_as(iTemp); - char sAuthID[32]; - file.ReadString(sAuthID, 32); + int iSteamID = 0; + + if(gA_FrameCache[style][track].iReplayVersion >= 0x04) + { + file.ReadInt32(iSteamID); + } + + else + { + char sAuthID[32]; + file.ReadString(sAuthID, 32); + ReplaceString(sAuthID, 32, "[U:1:", ""); + ReplaceString(sAuthID, 32, "]", ""); + iSteamID = StringToInt(sAuthID); + } if(gH_SQL != null) { char sQuery[192]; - FormatEx(sQuery, 192, "SELECT name FROM %susers WHERE auth = '%s';", gS_MySQLPrefix, sAuthID); + FormatEx(sQuery, 192, "SELECT name FROM %susers WHERE auth = %d;", gS_MySQLPrefix, iSteamID); - DataPack pack = new DataPack(); - pack.WriteCell(style); - pack.WriteCell(track); + DataPack hPack = new DataPack(); + hPack.WriteCell(style); + hPack.WriteCell(track); - gH_SQL.Query(SQL_GetUserName_Callback, sQuery, pack, DBPrio_High); + gH_SQL.Query(SQL_GetUserName_Callback, sQuery, hPack, DBPrio_High); } int cells = CELLS_PER_FRAME; @@ -1169,7 +1182,7 @@ bool LoadReplay(int style, int track, const char[] path) return false; } -bool SaveReplay(int style, int track, float time, char[] authid, char[] name, int preframes = 0) +bool SaveReplay(int style, int track, float time, int steamid, char[] name, int preframes = 0) { char sTrack[4]; FormatEx(sTrack, 4, "_%d", track); @@ -1193,7 +1206,7 @@ bool SaveReplay(int style, int track, float time, char[] authid, char[] name, in int iSize = gA_Frames[style][track].Length; fFile.WriteInt32(iSize); fFile.WriteInt32(view_as(time)); - fFile.WriteString(authid, true); + fFile.WriteInt32(steamid); any aFrameData[CELLS_PER_FRAME]; any aWriteData[CELLS_PER_FRAME * FRAMES_PER_WRITE]; @@ -1599,14 +1612,13 @@ public void Shavit_OnFinish(int client, int style, float time, int jumps, int st delete gA_Frames[style][track]; gA_Frames[style][track] = gA_PlayerFrames[client].Clone(); - char sAuthID[32]; - GetClientAuthId(client, AuthId_Steam3, sAuthID, 32); + int iSteamID = GetSteamAccountID(client); char sName[MAX_NAME_LENGTH]; GetClientName(client, sName, MAX_NAME_LENGTH); ReplaceString(sName, MAX_NAME_LENGTH, "#", "?"); - SaveReplay(style, track, time, sAuthID, sName); + SaveReplay(style, track, time, iSteamID, sName); if(ReplayEnabled(style)) { diff --git a/addons/sourcemod/scripting/shavit-stats.sp b/addons/sourcemod/scripting/shavit-stats.sp index 82c9bcbea..0fad6b762 100644 --- a/addons/sourcemod/scripting/shavit-stats.sp +++ b/addons/sourcemod/scripting/shavit-stats.sp @@ -48,7 +48,7 @@ bool gB_AllowStats[MAXPLAYERS+1]; int gI_MapType[MAXPLAYERS+1]; int gI_Style[MAXPLAYERS+1]; int gI_Track[MAXPLAYERS+1]; -char gS_TargetAuth[MAXPLAYERS+1][32]; +int gI_TargetSteamID[MAXPLAYERS+1]; char gS_TargetName[MAXPLAYERS+1][MAX_NAME_LENGTH]; int gI_WRAmount[MAXPLAYERS+1]; EngineVersion gEV_Type = Engine_Unknown; @@ -282,9 +282,9 @@ void UpdateWRs(int client) return; } - char sAuthID[32]; + int iSteamID = 0; - if(GetClientAuthId(client, AuthId_Steam3, sAuthID, 32)) + if((iSteamID = GetSteamAccountID(client)) != 0) { char sQuery[512]; @@ -292,16 +292,16 @@ void UpdateWRs(int client) if(gCV_MVPRankOnes.IntValue == 2) { FormatEx(sQuery, 512, - "SELECT COUNT(*) FROM %splayertimes a JOIN (SELECT MIN(time) time, map FROM %splayertimes WHERE style = 0 %sGROUP by map, track) b ON a.time = b.time AND a.map = b.map AND style = 0 %sWHERE auth = '%s';", - gS_MySQLPrefix, gS_MySQLPrefix, (gCV_MVPRankOnes_Main.BoolValue)? "AND track = 0 ":"", (gCV_MVPRankOnes_Main.BoolValue)? "AND track = 0 ":"", sAuthID); + "SELECT COUNT(*) FROM %splayertimes a JOIN (SELECT MIN(time) time, map FROM %splayertimes WHERE style = 0 %sGROUP by map, track) b ON a.time = b.time AND a.map = b.map AND style = 0 %sWHERE auth = %d;", + gS_MySQLPrefix, gS_MySQLPrefix, (gCV_MVPRankOnes_Main.BoolValue)? "AND track = 0 ":"", (gCV_MVPRankOnes_Main.BoolValue)? "AND track = 0 ":"", iSteamID); } // all styles else { FormatEx(sQuery, 512, - "SELECT COUNT(*) FROM %splayertimes a JOIN (SELECT MIN(time) time, map, style FROM %splayertimes %sGROUP by map, style, track) b ON a.time = b.time AND a.map = b.map AND a.style = b.style %sWHERE auth = '%s';", - gS_MySQLPrefix, gS_MySQLPrefix, (gCV_MVPRankOnes_Main.BoolValue)? "WHERE track = 0 ":"", (gCV_MVPRankOnes_Main.BoolValue)? "AND track = 0 ":"", sAuthID); + "SELECT COUNT(*) FROM %splayertimes a JOIN (SELECT MIN(time) time, map, style FROM %splayertimes %sGROUP by map, style, track) b ON a.time = b.time AND a.map = b.map AND a.style = b.style %sWHERE auth = %d;", + gS_MySQLPrefix, gS_MySQLPrefix, (gCV_MVPRankOnes_Main.BoolValue)? "WHERE track = 0 ":"", (gCV_MVPRankOnes_Main.BoolValue)? "AND track = 0 ":"", iSteamID); } gH_SQL.Query(SQL_GetWRs_Callback, sQuery, GetClientSerial(client)); @@ -356,7 +356,7 @@ public Action Command_MapsDoneLeft(int client, int args) } } - GetClientAuthId(target, AuthId_Steam3, gS_TargetAuth[client], 32); + gI_TargetSteamID[client] = GetSteamAccountID(target); char sCommand[16]; GetCmdArg(0, sCommand, 16); @@ -472,12 +472,12 @@ public Action Command_Profile(int client, int args) } } - GetClientAuthId(target, AuthId_Steam3, gS_TargetAuth[client], 32); + gI_TargetSteamID[client] = GetSteamAccountID(target); - return OpenStatsMenu(client, gS_TargetAuth[client]); + return OpenStatsMenu(client, gI_TargetSteamID[client]); } -Action OpenStatsMenu(int client, const char[] authid) +Action OpenStatsMenu(int client, int steamid) { // no spam please if(!gB_AllowStats[client]) @@ -490,23 +490,23 @@ Action OpenStatsMenu(int client, const char[] authid) if(gB_Rankings) { - FormatEx(sQuery, 2048, "SELECT a.clears, b.maps, c.wrs, d.name, d.country, d.lastlogin, d.points, e.rank FROM " ... - "(SELECT COUNT(*) clears FROM (SELECT map FROM %splayertimes WHERE auth = '%s' AND track = 0 GROUP BY map) s) a " ... + FormatEx(sQuery, 2048, "SELECT a.clears, b.maps, c.wrs, d.name, d.ip, d.lastlogin, d.points, e.rank FROM " ... + "(SELECT COUNT(*) clears FROM (SELECT map FROM %splayertimes WHERE auth = %d AND track = 0 GROUP BY map) s) a " ... "JOIN (SELECT COUNT(*) maps FROM (SELECT map FROM %smapzones WHERE track = 0 AND type = 0 GROUP BY map) s) b " ... - "JOIN (SELECT COUNT(*) wrs FROM %splayertimes a JOIN (SELECT MIN(time) time, map FROM %splayertimes WHERE style = 0 AND track = 0 GROUP by map, style, track) b ON a.time = b.time AND a.map = b.map AND track = 0 AND style = 0 WHERE auth = '%s') c " ... - "JOIN (SELECT name, country, lastlogin, FORMAT(points, 2) points FROM %susers WHERE auth = '%s') d " ... - "JOIN (SELECT COUNT(*) rank FROM %susers u1 JOIN (SELECT points FROM %susers WHERE auth = '%s') u2 WHERE u1.points >= u2.points) e " ... - "LIMIT 1;", gS_MySQLPrefix, authid, gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix, authid, gS_MySQLPrefix, authid, gS_MySQLPrefix, gS_MySQLPrefix, authid); + "JOIN (SELECT COUNT(*) wrs FROM %splayertimes a JOIN (SELECT MIN(time) time, map FROM %splayertimes WHERE style = 0 AND track = 0 GROUP by map, style, track) b ON a.time = b.time AND a.map = b.map AND track = 0 AND style = 0 WHERE auth = %d) c " ... + "JOIN (SELECT name, ip, lastlogin, FORMAT(points, 2) points FROM %susers WHERE auth = %d) d " ... + "JOIN (SELECT COUNT(*) rank FROM %susers u1 JOIN (SELECT points FROM %susers WHERE auth = %d) u2 WHERE u1.points >= u2.points) e " ... + "LIMIT 1;", gS_MySQLPrefix, steamid, gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix, steamid, gS_MySQLPrefix, steamid, gS_MySQLPrefix, gS_MySQLPrefix, steamid); } else { - FormatEx(sQuery, 2048, "SELECT a.clears, b.maps, c.wrs, d.name, d.country, d.lastlogin FROM " ... - "(SELECT COUNT(*) clears FROM (SELECT map FROM %splayertimes WHERE auth = '%s' AND track = 0 GROUP BY map) s) a " ... + FormatEx(sQuery, 2048, "SELECT a.clears, b.maps, c.wrs, d.name, d.ip, d.lastlogin FROM " ... + "(SELECT COUNT(*) clears FROM (SELECT map FROM %splayertimes WHERE auth = %d AND track = 0 GROUP BY map) s) a " ... "JOIN (SELECT COUNT(*) maps FROM (SELECT map FROM %smapzones WHERE track = 0 AND type = 0 GROUP BY map) s) b " ... - "JOIN (SELECT COUNT(*) wrs FROM %splayertimes a JOIN (SELECT MIN(time) time, map FROM %splayertimes WHERE style = 0 AND track = 0 GROUP by map, style, track) b ON a.time = b.time AND a.map = b.map AND track = 0 AND style = 0 WHERE auth = '%s') c " ... - "JOIN (SELECT name, country, lastlogin FROM %susers WHERE auth = '%s') d " ... - "LIMIT 1;", gS_MySQLPrefix, authid, gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix, authid, gS_MySQLPrefix, authid); + "JOIN (SELECT COUNT(*) wrs FROM %splayertimes a JOIN (SELECT MIN(time) time, map FROM %splayertimes WHERE style = 0 AND track = 0 GROUP by map, style, track) b ON a.time = b.time AND a.map = b.map AND track = 0 AND style = 0 WHERE auth = %d) c " ... + "JOIN (SELECT name, ip, lastlogin FROM %susers WHERE auth = %d) d " ... + "LIMIT 1;", gS_MySQLPrefix, steamid, gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix, steamid, gS_MySQLPrefix, steamid); } gB_AllowStats[client] = false; @@ -541,8 +541,16 @@ public void OpenStatsMenuCallback(Database db, DBResultSet results, const char[] results.FetchString(3, gS_TargetName[client], MAX_NAME_LENGTH); ReplaceString(gS_TargetName[client], MAX_NAME_LENGTH, "#", "?"); + int iIPAddress = results.FetchInt(4); + char sIPAddress[32]; + IPAddressToString(iIPAddress, sIPAddress, 32); + char sCountry[64]; - results.FetchString(4, sCountry, 64); + + if(!GeoipCountry(sIPAddress, sCountry, 64)) + { + strcopy(sCountry, 64, "Local Area Network"); + } int iLastLogin = results.FetchInt(5); char sLastLogin[32]; @@ -582,8 +590,8 @@ public void OpenStatsMenuCallback(Database db, DBResultSet results, const char[] FormatEx(sClearString, 128, "%T: %d/%d (%.01f%%)", "MapCompletions", client, iClears, iTotalMaps, ((float(iClears) / iTotalMaps) * 100.0)); Menu menu = new Menu(MenuHandler_ProfileHandler); - menu.SetTitle("%s's %T. %s\n%T: %s\n%s\n%s\n[%s] %T: %d%s\n", - gS_TargetName[client], "Profile", client, gS_TargetAuth[client], "Country", client, sCountry, sLastLogin, sClearString, + menu.SetTitle("%s's %T. [U:1:%d]\n%T: %s\n%s\n%s\n[%s] %T: %d%s\n", + gS_TargetName[client], "Profile", client, gI_TargetSteamID[client], "Country", client, sCountry, sLastLogin, sClearString, gS_StyleStrings[0].sStyleName, "WorldRecords", client, iWRs, sRankingString); int[] styles = new int[gI_Styles]; @@ -681,7 +689,7 @@ public int MenuHandler_TypeHandler(Menu menu, MenuAction action, int param1, int else if(action == MenuAction_Cancel && param2 == MenuCancel_ExitBack) { - OpenStatsMenu(param1, gS_TargetAuth[param1]); + OpenStatsMenu(param1, gI_TargetSteamID[param1]); } else if(action == MenuAction_End) @@ -721,8 +729,8 @@ void ShowMaps(int client) if(gI_MapType[client] == MAPSDONE) { FormatEx(sQuery, 512, - "SELECT a.map, a.time, a.jumps, a.id, COUNT(b.map) + 1 rank, a.points FROM %splayertimes a LEFT JOIN %splayertimes b ON a.time > b.time AND a.map = b.map AND a.style = b.style AND a.track = b.track WHERE a.auth = '%s' AND a.style = %d AND a.track = %d GROUP BY a.map, a.time, a.jumps, a.id, a.points ORDER BY a.%s;", - gS_MySQLPrefix, gS_MySQLPrefix, gS_TargetAuth[client], gI_Style[client], gI_Track[client], (gB_Rankings)? "points DESC":"map"); + "SELECT a.map, a.time, a.jumps, a.id, COUNT(b.map) + 1 rank, a.points FROM %splayertimes a LEFT JOIN %splayertimes b ON a.time > b.time AND a.map = b.map AND a.style = b.style AND a.track = b.track WHERE a.auth = %d AND a.style = %d AND a.track = %d GROUP BY a.map, a.time, a.jumps, a.id, a.points ORDER BY a.%s;", + gS_MySQLPrefix, gS_MySQLPrefix, gI_TargetSteamID[client], gI_Style[client], gI_Track[client], (gB_Rankings)? "points DESC":"map"); } else @@ -730,15 +738,15 @@ void ShowMaps(int client) if(gB_Rankings) { FormatEx(sQuery, 512, - "SELECT DISTINCT m.map, t.tier FROM %smapzones m LEFT JOIN %smaptiers t ON m.map = t.map WHERE m.type = 0 AND m.track = %d AND m.map NOT IN (SELECT DISTINCT map FROM %splayertimes WHERE auth = '%s' AND style = %d AND track = %d) ORDER BY m.map;", - gS_MySQLPrefix, gS_MySQLPrefix, gI_Track[client], gS_MySQLPrefix, gS_TargetAuth[client], gI_Style[client], gI_Track[client]); + "SELECT DISTINCT m.map, t.tier FROM %smapzones m LEFT JOIN %smaptiers t ON m.map = t.map WHERE m.type = 0 AND m.track = %d AND m.map NOT IN (SELECT DISTINCT map FROM %splayertimes WHERE auth = %d AND style = %d AND track = %d) ORDER BY m.map;", + gS_MySQLPrefix, gS_MySQLPrefix, gI_Track[client], gS_MySQLPrefix, gI_TargetSteamID[client], gI_Style[client], gI_Track[client]); } else { FormatEx(sQuery, 512, - "SELECT DISTINCT map FROM %smapzones WHERE type = 0 AND track = %d AND map NOT IN (SELECT DISTINCT map FROM %splayertimes WHERE auth = '%s' AND style = %d AND track = %d) ORDER BY map;", - gS_MySQLPrefix, gI_Track[client], gS_MySQLPrefix, gS_TargetAuth[client], gI_Style[client], gI_Track[client]); + "SELECT DISTINCT map FROM %smapzones WHERE type = 0 AND track = %d AND map NOT IN (SELECT DISTINCT map FROM %splayertimes WHERE auth = %d AND style = %d AND track = %d) ORDER BY map;", + gS_MySQLPrefix, gI_Track[client], gS_MySQLPrefix, gI_TargetSteamID[client], gI_Style[client], gI_Track[client]); } } @@ -853,7 +861,7 @@ public int MenuHandler_ShowMaps(Menu menu, MenuAction action, int param1, int pa if(StrEqual(sInfo, "nope")) { - OpenStatsMenu(param1, gS_TargetAuth[param1]); + OpenStatsMenu(param1, gI_TargetSteamID[param1]); return 0; } @@ -866,7 +874,7 @@ public int MenuHandler_ShowMaps(Menu menu, MenuAction action, int param1, int pa else if(action == MenuAction_Cancel && param2 == MenuCancel_ExitBack) { - OpenStatsMenu(param1, gS_TargetAuth[param1]); + OpenStatsMenu(param1, gI_TargetSteamID[param1]); } else if(action == MenuAction_End) @@ -893,10 +901,10 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] return; } - Menu menu = new Menu(SubMenu_Handler); + Menu hMenu = new Menu(SubMenu_Handler); char sName[MAX_NAME_LENGTH]; - char sAuthID[32]; + int iSteamID = 0; char sMap[192]; if(results.FetchRow()) @@ -911,20 +919,20 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] char sDisplay[128]; FormatEx(sDisplay, 128, "%T: %s", "Time", client, sTime); - menu.AddItem("-1", sDisplay); + hMenu.AddItem("-1", sDisplay); // 2 - jumps int jumps = results.FetchInt(2); FormatEx(sDisplay, 128, "%T: %d", "Jumps", client, jumps); - menu.AddItem("-1", sDisplay); + hMenu.AddItem("-1", sDisplay); // 3 - style int style = results.FetchInt(3); FormatEx(sDisplay, 128, "%T: %s", "Style", client, gS_StyleStrings[style].sStyleName); - menu.AddItem("-1", sDisplay); + hMenu.AddItem("-1", sDisplay); // 4 - steamid3 - results.FetchString(4, sAuthID, 32); + iSteamID = results.FetchInt(4); // 6 - map results.FetchString(6, sMap, 192); @@ -934,7 +942,7 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] if(gB_Rankings && points > 0.0) { FormatEx(sDisplay, 192, "%T: %.03f", "Points", client, points); - menu.AddItem("-1", sDisplay); + hMenu.AddItem("-1", sDisplay); } // 5 - date @@ -947,7 +955,7 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] } FormatEx(sDisplay, 128, "%T: %s", "Date", client, sDate); - menu.AddItem("-1", sDisplay); + hMenu.AddItem("-1", sDisplay); int strafes = results.FetchInt(7); float sync = results.FetchFloat(8); @@ -955,16 +963,16 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] if(jumps > 0 || strafes > 0) { FormatEx(sDisplay, 128, (sync > 0.0)? "%T: %d (%.02f%%)":"%T: %d", "Strafes", client, strafes, sync, "Strafes", client, strafes); - menu.AddItem("-1", sDisplay); + hMenu.AddItem("-1", sDisplay); } } char sFormattedTitle[256]; - FormatEx(sFormattedTitle, 256, "%s %s\n--- %s:", sName, sAuthID, sMap); + FormatEx(sFormattedTitle, 256, "%s [U:1:%d]\n--- %s:", sName, iSteamID, sMap); - menu.SetTitle(sFormattedTitle); - menu.ExitBackButton = true; - menu.Display(client, 20); + hMenu.SetTitle(sFormattedTitle); + hMenu.ExitBackButton = true; + hMenu.Display(client, 20); } public int SubMenu_Handler(Menu menu, MenuAction action, int param1, int param2) @@ -985,9 +993,9 @@ public int SubMenu_Handler(Menu menu, MenuAction action, int param1, int param2) public int Native_OpenStatsMenu(Handle handler, int numParams) { int client = GetNativeCell(1); - GetNativeString(2, gS_TargetAuth[client], 32); + gI_TargetSteamID[client] = GetNativeCell(2); - OpenStatsMenu(client, gS_TargetAuth[client]); + OpenStatsMenu(client, gI_TargetSteamID[client]); } public int Native_GetWRCount(Handle handler, int numParams) diff --git a/addons/sourcemod/scripting/shavit-wr.sp b/addons/sourcemod/scripting/shavit-wr.sp index d5bcd099e..c320f7b20 100644 --- a/addons/sourcemod/scripting/shavit-wr.sp +++ b/addons/sourcemod/scripting/shavit-wr.sp @@ -426,11 +426,15 @@ public void OnClientPutInServer(int client) void UpdateClientCache(int client) { - char sAuthID[32]; - GetClientAuthId(client, AuthId_Steam3, sAuthID, 32); + int iSteamID = GetSteamAccountID(client); + + if(iSteamID == 0) + { + return; + } char sQuery[256]; - FormatEx(sQuery, 256, "SELECT time, style, track FROM %splayertimes WHERE map = '%s' AND auth = '%s';", gS_MySQLPrefix, gS_Map, sAuthID); + FormatEx(sQuery, 256, "SELECT time, style, track FROM %splayertimes WHERE map = '%s' AND auth = %d;", gS_MySQLPrefix, gS_Map, iSteamID); gH_SQL.Query(SQL_UpdateCache_Callback, sQuery, GetClientSerial(client), DBPrio_High); } @@ -635,10 +639,9 @@ public void SQL_DeleteMap_Callback(Database db, DBResultSet results, const char[ public Action Command_Junk(int client, int args) { char sQuery[256]; - - char sAuth[32]; - GetClientAuthId(client, AuthId_Steam3, sAuth, 32); - FormatEx(sQuery, 256, "INSERT INTO %splayertimes (auth, map, time, jumps, date, style, strafes, sync) VALUES ('%s', '%s', %f, %d, %d, 0, %d, %.02f);", gS_MySQLPrefix, sAuth, gS_Map, GetRandomFloat(10.0, 20.0), GetRandomInt(5, 15), GetTime(), GetRandomInt(5, 15), GetRandomFloat(50.0, 99.99)); + FormatEx(sQuery, 256, + "INSERT INTO %splayertimes (auth, map, time, jumps, date, style, strafes, sync) VALUES (%d, '%s', %f, %d, %d, 0, %d, %.02f);", + gS_MySQLPrefix, GetSteamAccountID(client), gS_Map, GetRandomFloat(10.0, 20.0), GetRandomInt(5, 15), GetTime(), GetRandomInt(5, 15), GetRandomFloat(50.0, 99.99)); SQL_LockDatabase(gH_SQL); SQL_FastQuery(gH_SQL, sQuery); @@ -1125,8 +1128,7 @@ public void GetRecordDetails_Callback(Database db, DBResultSet results, const ch if(results.FetchRow()) { - char sAuthID[32]; - results.FetchString(0, sAuthID, 32); + int iSteamID = results.FetchInt(0); char sName[MAX_NAME_LENGTH]; results.FetchString(1, sName, MAX_NAME_LENGTH); @@ -1150,7 +1152,7 @@ public void GetRecordDetails_Callback(Database db, DBResultSet results, const ch // that's a big datapack ya yeet DataPack hPack = new DataPack(); hPack.WriteCell(GetClientSerial(client)); - hPack.WriteString(sAuthID); + hPack.WriteCell(iSteamID); hPack.WriteString(sName); hPack.WriteString(sMap); hPack.WriteCell(fTime); @@ -1178,9 +1180,7 @@ public void DeleteConfirm_Callback(Database db, DBResultSet results, const char[ hPack.Reset(); int iSerial = hPack.ReadCell(); - - char sAuthID[32]; - hPack.ReadString(sAuthID, 32); + int iSteamID = hPack.ReadCell(); char sName[MAX_NAME_LENGTH]; hPack.ReadString(sName, MAX_NAME_LENGTH); @@ -1234,8 +1234,8 @@ public void DeleteConfirm_Callback(Database db, DBResultSet results, const char[ FormatTime(sDate, 32, "%Y-%m-%d %H:%M:%S", iTimestamp); // above the client == 0 so log doesn't get lost if admin disconnects between deleting record and query execution - Shavit_LogMessage("%L - deleted record. Runner: %s (%s) | Map: %s | Style: %s | Track: %s | Time: %.2f (%s) | Strafes: %d (%.1f%%) | Jumps: %d (%.1f%%) | Run date: %s | Record ID: %d", - client, sName, sAuthID, sMap, gS_StyleStrings[iStyle].sStyleName, sTrack, fTime, (bWRDeleted)? "WR":"not WR", iStrafes, fSync, iJumps, fPerfectJumps, sDate, iRecordID); + Shavit_LogMessage("%L - deleted record. Runner: %s ([U:1:%d]) | Map: %s | Style: %s | Track: %s | Time: %.2f (%s) | Strafes: %d (%.1f%%) | Jumps: %d (%.1f%%) | Run date: %s | Record ID: %d", + client, sName, iSteamID, sMap, gS_StyleStrings[iStyle].sStyleName, sTrack, fTime, (bWRDeleted)? "WR":"not WR", iStrafes, fSync, iJumps, fPerfectJumps, sDate, iRecordID); if(client == 0) { @@ -1448,10 +1448,9 @@ public void SQL_WR_Callback(Database db, DBResultSet results, const char[] error return; } - char sAuth[32]; - GetClientAuthId(client, AuthId_Steam3, sAuth, 32); + int iSteamID = GetSteamAccountID(client); - Menu menu = new Menu(WRMenu_Handler); + Menu hMenu = new Menu(WRMenu_Handler); int iCount = 0; int iMyRank = 0; @@ -1479,14 +1478,13 @@ public void SQL_WR_Callback(Database db, DBResultSet results, const char[] error char sDisplay[128]; FormatEx(sDisplay, 128, "#%d - %s - %s (%d %T)", iCount, sName, sTime, jumps, "WRJumps", client); - menu.AddItem(sID, sDisplay); + hMenu.AddItem(sID, sDisplay); } // check if record exists in the map's top X - char sQueryAuth[32]; - results.FetchString(4, sQueryAuth, 32); + int iQuerySteamID = results.FetchInt(4); - if(StrEqual(sQueryAuth, sAuth)) + if(iQuerySteamID == iSteamID) { iMyRank = iCount; } @@ -1494,13 +1492,13 @@ public void SQL_WR_Callback(Database db, DBResultSet results, const char[] error char sFormattedTitle[256]; - if(menu.ItemCount == 0) + if(hMenu.ItemCount == 0) { - menu.SetTitle("%T", "WRMap", client, sMap); + hMenu.SetTitle("%T", "WRMap", client, sMap); char sNoRecords[64]; FormatEx(sNoRecords, 64, "%T", "WRMapNoRecords", client); - menu.AddItem("-1", sNoRecords); + hMenu.AddItem("-1", sNoRecords); } else @@ -1525,11 +1523,11 @@ public void SQL_WR_Callback(Database db, DBResultSet results, const char[] error GetTrackName(client, track, sTrack, 32); FormatEx(sFormattedTitle, 192, "%T %s: [%s]\n%s", "WRRecordFor", client, sMap, sTrack, sRanks); - menu.SetTitle(sFormattedTitle); + hMenu.SetTitle(sFormattedTitle); } - menu.ExitBackButton = true; - menu.Display(client, 20); + hMenu.ExitBackButton = true; + hMenu.Display(client, 20); } public int WRMenu_Handler(Menu menu, MenuAction action, int param1, int param2) @@ -1722,11 +1720,11 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] return; } - Menu menu = new Menu(SubMenu_Handler); + Menu hMenu = new Menu(SubMenu_Handler); char sFormattedTitle[256]; char sName[MAX_NAME_LENGTH]; - char sAuthID[32]; + int iSteamID = 0; char sTrack[32]; char sMap[192]; @@ -1742,7 +1740,7 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] char sDisplay[128]; FormatEx(sDisplay, 128, "%T: %s", "WRTime", client, sTime); - menu.AddItem("-1", sDisplay); + hMenu.AddItem("-1", sDisplay); // 2 - jumps int style = results.FetchInt(3); @@ -1759,11 +1757,11 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] FormatEx(sDisplay, 128, "%T: %d (%.2f%%)", "WRJumps", client, jumps, perfs); } - menu.AddItem("-1", sDisplay); + hMenu.AddItem("-1", sDisplay); // 3 - style FormatEx(sDisplay, 128, "%T: %s", "WRStyle", client, gS_StyleStrings[style].sStyleName); - menu.AddItem("-1", sDisplay); + hMenu.AddItem("-1", sDisplay); // 6 - map results.FetchString(6, sMap, 192); @@ -1773,11 +1771,11 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] if(gB_Rankings && fPoints > 0.0) { FormatEx(sDisplay, 128, "%T: %.03f", "WRPointsCap", client, fPoints); - menu.AddItem("-1", sDisplay); + hMenu.AddItem("-1", sDisplay); } // 4 - steamid3 - results.FetchString(4, sAuthID, 32); + iSteamID = results.FetchInt(4); // 5 - date char sDate[32]; @@ -1789,7 +1787,7 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] } FormatEx(sDisplay, 128, "%T: %s", "WRDate", client, sDate); - menu.AddItem("-1", sDisplay); + hMenu.AddItem("-1", sDisplay); int strafes = results.FetchInt(7); float sync = results.FetchFloat(8); @@ -1797,25 +1795,25 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] if(jumps > 0 || strafes > 0) { FormatEx(sDisplay, 128, (sync != -1.0)? "%T: %d (%.02f%%)":"%T: %d", "WRStrafes", client, strafes, sync); - menu.AddItem("-1", sDisplay); + hMenu.AddItem("-1", sDisplay); } char sMenuItem[64]; FormatEx(sMenuItem, 64, "%T", "WRPlayerStats", client); char sInfo[32]; - FormatEx(sInfo, 32, "0;%s", sAuthID); + FormatEx(sInfo, 32, "0;%d", iSteamID); if(gB_Stats) { - menu.AddItem(sInfo, sMenuItem); + hMenu.AddItem(sInfo, sMenuItem); } if(CheckCommandAccess(client, "sm_delete", ADMFLAG_RCON)) { FormatEx(sMenuItem, 64, "%T", "WRDeleteRecord", client); FormatEx(sInfo, 32, "1;%d", id); - menu.AddItem(sInfo, sMenuItem); + hMenu.AddItem(sInfo, sMenuItem); } GetTrackName(client, results.FetchInt(11), sTrack, 32); @@ -1825,12 +1823,12 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] { char sMenuItem[64]; FormatEx(sMenuItem, 64, "%T", "DatabaseError", client); - menu.AddItem("-1", sMenuItem); + hMenu.AddItem("-1", sMenuItem); } if(strlen(sName) > 0) { - FormatEx(sFormattedTitle, 256, "%s %s\n--- %s: [%s]", sName, sAuthID, sMap, sTrack); + FormatEx(sFormattedTitle, 256, "%s [U:1:%d]\n--- %s: [%s]", sName, iSteamID, sMap, sTrack); } else @@ -1838,9 +1836,9 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] FormatEx(sFormattedTitle, 256, "%T", "Error", client); } - menu.SetTitle(sFormattedTitle); - menu.ExitBackButton = true; - menu.Display(client, 20); + hMenu.SetTitle(sFormattedTitle); + hMenu.ExitBackButton = true; + hMenu.Display(client, 20); } public int SubMenu_Handler(Menu menu, MenuAction action, int param1, int param2) @@ -1861,7 +1859,7 @@ public int SubMenu_Handler(Menu menu, MenuAction action, int param1, int param2) { case 0: { - Shavit_OpenStatsMenu(param1, sExploded[1]); + Shavit_OpenStatsMenu(param1, StringToInt(sExploded[1])); } case 1: @@ -1956,14 +1954,14 @@ void SQL_DBConnect() if(gB_MySQL) { FormatEx(sQuery, 1024, - "CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INT NOT NULL AUTO_INCREMENT, `auth` VARCHAR(32), `map` VARCHAR(128), `time` FLOAT, `jumps` INT, `style` TINYINT, `date` VARCHAR(16), `strafes` INT, `sync` FLOAT, `points` FLOAT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0, `perfs` FLOAT DEFAULT 0, PRIMARY KEY (`id`), INDEX `map` (`map`, `style`, `track`, `time`), INDEX `auth` (`auth`, `date`, `points`), INDEX `time` (`time`), CONSTRAINT `%spt_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE) ENGINE=INNODB;", + "CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INT NOT NULL AUTO_INCREMENT, `auth` INT, `map` VARCHAR(128), `time` FLOAT, `jumps` INT, `style` TINYINT, `date` INT, `strafes` INT, `sync` FLOAT, `points` FLOAT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0, `perfs` FLOAT DEFAULT 0, PRIMARY KEY (`id`), INDEX `map` (`map`, `style`, `track`, `time`), INDEX `auth` (`auth`, `date`, `points`), INDEX `time` (`time`), CONSTRAINT `%spt_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE) ENGINE=INNODB;", gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix); } else { FormatEx(sQuery, 1024, - "CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INTEGER PRIMARY KEY, `auth` VARCHAR(32), `map` VARCHAR(128), `time` FLOAT, `jumps` INT, `style` TINYINT, `date` VARCHAR(16), `strafes` INT, `sync` FLOAT, `points` FLOAT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0, `perfs` FLOAT DEFAULT 0, CONSTRAINT `%spt_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE);", + "CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INTEGER PRIMARY KEY, `auth` INT, `map` VARCHAR(128), `time` FLOAT, `jumps` INT, `style` TINYINT, `date` INT, `strafes` INT, `sync` FLOAT, `points` FLOAT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0, `perfs` FLOAT DEFAULT 0, CONSTRAINT `%spt_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE);", gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix); } @@ -2077,8 +2075,7 @@ public void Shavit_OnFinish(int client, int style, float time, int jumps, int st if(iOverwrite > 0) { - char sAuthID[32]; - GetClientAuthId(client, AuthId_Steam3, sAuthID, 32); + int iSteamID = GetSteamAccountID(client); char sQuery[512]; @@ -2091,14 +2088,14 @@ public void Shavit_OnFinish(int client, int style, float time, int jumps, int st return; } - FormatEx(sQuery, 512, "INSERT INTO %splayertimes (auth, map, time, jumps, date, style, strafes, sync, points, track, perfs) VALUES ('%s', '%s', %f, %d, %d, %d, %d, %.2f, 0.0, %d, %.2f);", gS_MySQLPrefix, sAuthID, gS_Map, time, jumps, GetTime(), style, strafes, sync, track, perfs); + FormatEx(sQuery, 512, "INSERT INTO %splayertimes (auth, map, time, jumps, date, style, strafes, sync, points, track, perfs) VALUES (%d, '%s', %f, %d, %d, %d, %d, %.2f, 0.0, %d, %.2f);", gS_MySQLPrefix, iSteamID, gS_Map, time, jumps, GetTime(), style, strafes, sync, track, perfs); } else // update { Shavit_PrintToChatAll("%s[%s]%s %T", gS_ChatStrings.sVariable, sTrack, gS_ChatStrings.sText, "NotFirstCompletion", LANG_SERVER, gS_ChatStrings.sVariable2, client, gS_ChatStrings.sText, gS_ChatStrings.sStyle, gS_StyleStrings[style].sStyleName, gS_ChatStrings.sText, gS_ChatStrings.sVariable2, sTime, gS_ChatStrings.sText, gS_ChatStrings.sVariable, iRank, gS_ChatStrings.sText, jumps, strafes, sSync, gS_ChatStrings.sText, gS_ChatStrings.sWarning, sDifference); - FormatEx(sQuery, 512, "UPDATE %splayertimes SET time = %f, jumps = %d, date = %d, strafes = %d, sync = %.02f, points = 0.0, perfs = %.2f WHERE map = '%s' AND auth = '%s' AND style = %d AND track = %d;", gS_MySQLPrefix, time, jumps, GetTime(), strafes, sync, perfs, gS_Map, sAuthID, style, track); + FormatEx(sQuery, 512, "UPDATE %splayertimes SET time = %f, jumps = %d, date = %d, strafes = %d, sync = %.02f, points = 0.0, perfs = %.2f WHERE map = '%s' AND auth = %d AND style = %d AND track = %d;", gS_MySQLPrefix, time, jumps, GetTime(), strafes, sync, perfs, gS_Map, iSteamID, style, track); } gH_SQL.Query(SQL_OnFinish_Callback, sQuery, GetClientSerial(client), DBPrio_High); From 29c57b4fca8bebe0cea7f0cd2dabd71146934c9d Mon Sep 17 00:00:00 2001 From: shavit Date: Sun, 12 May 2019 23:38:00 +0300 Subject: [PATCH 14/34] Fixed workshop migration applying 3 times --- addons/sourcemod/scripting/shavit-core.sp | 26 ++++++----------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/addons/sourcemod/scripting/shavit-core.sp b/addons/sourcemod/scripting/shavit-core.sp index 88fa0655d..18263c173 100644 --- a/addons/sourcemod/scripting/shavit-core.sp +++ b/addons/sourcemod/scripting/shavit-core.sp @@ -2344,17 +2344,8 @@ public void SQL_TableMigrationIPAddresses_Callback(Database db, DBResultSet resu char sIPAddress[32]; results.FetchString(0, sIPAddress, 32); - char sExplodedAddress[4][4]; - ExplodeString(sIPAddress, ".", sExplodedAddress, 4, 4, false); - - int iIPAddress = - (StringToInt(sExplodedAddress[0]) << 24) | - (StringToInt(sExplodedAddress[1]) << 16) | - (StringToInt(sExplodedAddress[2]) << 8) | - StringToInt(sExplodedAddress[3]); - char sQuery[256]; - FormatEx(sQuery, 256, "UPDATE %susers SET ip = %d WHERE ip = '%s';", gS_MySQLPrefix, iIPAddress, sIPAddress); + FormatEx(sQuery, 256, "UPDATE %susers SET ip = %d WHERE ip = '%s';", gS_MySQLPrefix, IPStringToAddress(sIPAddress), sIPAddress); hTransaction.AddQuery(sQuery); } @@ -2423,16 +2414,13 @@ void ApplyMigration_RemoveWorkshopPath(int migration) "playertimes" }; - for(int i = 0; i < sizeof(sTables); i++) - { - DataPack hPack = new DataPack(); - hPack.WriteCell(migration); - hPack.WriteString(sTables[i]); + DataPack hPack = new DataPack(); + hPack.WriteCell(migration); + hPack.WriteString(sTables[migration]); - char sQuery[192]; - FormatEx(sQuery, 192, "SELECT map FROM %s%s WHERE map LIKE 'workshop%%' GROUP BY map;", gS_MySQLPrefix, sTables[i]); - gH_SQL.Query(SQL_TableMigrationWorkshop_Callback, sQuery, hPack, DBPrio_High); - } + char sQuery[192]; + FormatEx(sQuery, 192, "SELECT map FROM %s%s WHERE map LIKE 'workshop%%' GROUP BY map;", gS_MySQLPrefix, sTables[migration]); + gH_SQL.Query(SQL_TableMigrationWorkshop_Callback, sQuery, hPack, DBPrio_High); } public void SQL_TableMigrationWorkshop_Callback(Database db, DBResultSet results, const char[] error, DataPack data) From 1fe119634229976ec484444d8419d5c8b725a95a Mon Sep 17 00:00:00 2001 From: shavit Date: Mon, 13 May 2019 05:36:12 +0300 Subject: [PATCH 15/34] Optimizations to migrations * Deletes invalid times/chat records before adding the new constraints. * Use of `ip` index while converting the IP addresses. * Limit IP conversion transaction to 10k queries to prevent memory leak on large datasets. --- addons/sourcemod/scripting/shavit-core.sp | 60 +++++++++++++++++++---- 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/addons/sourcemod/scripting/shavit-core.sp b/addons/sourcemod/scripting/shavit-core.sp index 18263c173..afbfb9c6a 100644 --- a/addons/sourcemod/scripting/shavit-core.sp +++ b/addons/sourcemod/scripting/shavit-core.sp @@ -2309,23 +2309,41 @@ public void SQL_TableMigrationSingleQuery_Callback(Database db, DBResultSet resu if(data == Migration_ConvertSteamIDsChat) { char sQuery[256]; + // deleting rows that cause data integrity issues + FormatEx(sQuery, 256, + "DELETE t1 FROM %splayertimes t1 LEFT JOIN %susers t2 ON t1.auth = t2.auth WHERE t2.auth IS NULL;", + gS_MySQLPrefix, gS_MySQLPrefix); + gH_SQL.Query(SQL_TableMigrationIndexing_Callback, sQuery, 0, DBPrio_High); + FormatEx(sQuery, 256, "ALTER TABLE `%splayertimes` ADD CONSTRAINT `pt_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE;", gS_MySQLPrefix, gS_MySQLPrefix); - gH_SQL.Query(SQL_TableMigrationConstraints_Callback, sQuery, 0, DBPrio_High); + gH_SQL.Query(SQL_TableMigrationIndexing_Callback, sQuery); + + FormatEx(sQuery, 256, + "DELETE t1 FROM %schat t1 LEFT JOIN %susers t2 ON t1.auth = t2.auth WHERE t2.auth IS NULL;", + gS_MySQLPrefix, gS_MySQLPrefix); + gH_SQL.Query(SQL_TableMigrationIndexing_Callback, sQuery, 0, DBPrio_High); FormatEx(sQuery, 256, "ALTER TABLE `%schat` ADD CONSTRAINT `ch_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE;", gS_MySQLPrefix, gS_MySQLPrefix); - gH_SQL.Query(SQL_TableMigrationConstraints_Callback, sQuery, 0, DBPrio_High); + gH_SQL.Query(SQL_TableMigrationIndexing_Callback, sQuery); } } -void ApplyMigration_ConvertIPAddresses() +void ApplyMigration_ConvertIPAddresses(bool index = true) { char sQuery[128]; - FormatEx(sQuery, 128, "SELECT DISTINCT ip FROM %susers WHERE ip LIKE \"\%%.\%%\";", gS_MySQLPrefix); - gH_SQL.Query(SQL_TableMigrationIPAddresses_Callback, sQuery, 0, DBPrio_High); + + if(index) + { + FormatEx(sQuery, 128, "ALTER TABLE `%susers` ADD INDEX `ip` (`ip`);", gS_MySQLPrefix); + gH_SQL.Query(SQL_TableMigrationIndexing_Callback, sQuery, 0, DBPrio_High); + } + + FormatEx(sQuery, 128, "SELECT DISTINCT ip FROM %susers WHERE ip LIKE '%%.%%';", gS_MySQLPrefix); + gH_SQL.Query(SQL_TableMigrationIPAddresses_Callback, sQuery); } public void SQL_TableMigrationIPAddresses_Callback(Database db, DBResultSet results, const char[] error, DataPack data) @@ -2338,6 +2356,7 @@ public void SQL_TableMigrationIPAddresses_Callback(Database db, DBResultSet resu } Transaction hTransaction = new Transaction(); + int iQueries = 0; while(results.FetchRow()) { @@ -2348,18 +2367,39 @@ public void SQL_TableMigrationIPAddresses_Callback(Database db, DBResultSet resu FormatEx(sQuery, 256, "UPDATE %susers SET ip = %d WHERE ip = '%s';", gS_MySQLPrefix, IPStringToAddress(sIPAddress), sIPAddress); hTransaction.AddQuery(sQuery); + + if(++iQueries >= 10000) + { + break; + } } - gH_SQL.Execute(hTransaction, Trans_IPAddressMigration); + gH_SQL.Execute(hTransaction, Trans_IPAddressMigrationSuccess, Trans_IPAddressMigrationFailed, iQueries); } -public void Trans_IPAddressMigration(Database db, any data, int numQueries, DBResultSet[] results, any[] queryData) +public void Trans_IPAddressMigrationSuccess(Database db, any data, int numQueries, DBResultSet[] results, any[] queryData) { + // too many queries, don't do all at once to avoid server crash due to too many queries in the transaction + if(data >= 10000) + { + ApplyMigration_ConvertIPAddresses(false); + + return; + } + char sQuery[128]; + FormatEx(sQuery, 128, "ALTER TABLE `%susers` DROP INDEX `ip`;", gS_MySQLPrefix); + gH_SQL.Query(SQL_TableMigrationIndexing_Callback, sQuery, 0, DBPrio_High); + FormatEx(sQuery, 128, "ALTER TABLE `%susers` CHANGE COLUMN `ip` `ip` INT;", gS_MySQLPrefix); gH_SQL.Query(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_ConvertIPAddresses, DBPrio_High); } +public void Trans_IPAddressMigrationFailed(Database db, any data, int numQueries, const char[] error, int failIndex, any[] queryData) +{ + LogError("Timer (core) error! IP address migration failed. Reason: %s", error); +} + void ApplyMigration_ConvertSteamIDs() { char sTables[][] = @@ -2371,10 +2411,10 @@ void ApplyMigration_ConvertSteamIDs() char sQuery[128]; FormatEx(sQuery, 128, "ALTER TABLE `%splayertimes` DROP CONSTRAINT `pt_auth`;", gS_MySQLPrefix); - gH_SQL.Query(SQL_TableMigrationConstraints_Callback, sQuery, 0, DBPrio_High); + gH_SQL.Query(SQL_TableMigrationIndexing_Callback, sQuery, 0, DBPrio_High); FormatEx(sQuery, 128, "ALTER TABLE `%schat` DROP CONSTRAINT `ch_auth`;", gS_MySQLPrefix); - gH_SQL.Query(SQL_TableMigrationConstraints_Callback, sQuery, 0, DBPrio_High); + gH_SQL.Query(SQL_TableMigrationIndexing_Callback, sQuery, 0, DBPrio_High); for(int i = 0; i < sizeof(sTables); i++) { @@ -2387,7 +2427,7 @@ void ApplyMigration_ConvertSteamIDs() } } -public void SQL_TableMigrationConstraints_Callback(Database db, DBResultSet results, const char[] error, DataPack data) +public void SQL_TableMigrationIndexing_Callback(Database db, DBResultSet results, const char[] error, DataPack data) { // nothing } From 086b81600ea2b8f2ae74b3fc4f412e1e32781eaf Mon Sep 17 00:00:00 2001 From: shavit Date: Mon, 13 May 2019 05:56:51 +0300 Subject: [PATCH 16/34] Removed pointless string-to-int-to-string conversion --- addons/sourcemod/scripting/shavit-sounds.sp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/addons/sourcemod/scripting/shavit-sounds.sp b/addons/sourcemod/scripting/shavit-sounds.sp index 368d8b097..f6fb75fcc 100644 --- a/addons/sourcemod/scripting/shavit-sounds.sp +++ b/addons/sourcemod/scripting/shavit-sounds.sp @@ -164,10 +164,7 @@ public void OnMapStart() else { - char sRank[8]; - IntToString(StringToInt(sExploded[0]), sRank, 8); - - gSM_RankSounds.SetString(sRank, sExploded[1]); + gSM_RankSounds.SetString(sExploded[0], sExploded[1]); } if(PrecacheSound(sExploded[1], true)) From 058b88b98c984aaa8df05060059ca487b75012e2 Mon Sep 17 00:00:00 2001 From: shavit Date: Tue, 14 May 2019 03:25:15 +0300 Subject: [PATCH 17/34] Added zone flags and data to mapzones table. --- addons/sourcemod/scripting/include/shavit.inc | 1 + addons/sourcemod/scripting/shavit-core.sp | 8 ++++++++ addons/sourcemod/scripting/shavit-zones.sp | 16 +++++++++++++--- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/addons/sourcemod/scripting/include/shavit.inc b/addons/sourcemod/scripting/include/shavit.inc index 044d66d10..ba1ee5849 100644 --- a/addons/sourcemod/scripting/include/shavit.inc +++ b/addons/sourcemod/scripting/include/shavit.inc @@ -86,6 +86,7 @@ enum Migration_ConvertSteamIDsPlayertimes, Migration_ConvertSteamIDsChat, Migration_PlayertimesDateToInt, + Migration_AddZonesFlagsAndData, MIGRATIONS_END }; diff --git a/addons/sourcemod/scripting/shavit-core.sp b/addons/sourcemod/scripting/shavit-core.sp index afbfb9c6a..d78ad7701 100644 --- a/addons/sourcemod/scripting/shavit-core.sp +++ b/addons/sourcemod/scripting/shavit-core.sp @@ -2277,6 +2277,7 @@ void ApplyMigration(int migration) case Migration_ConvertSteamIDsUsers: ApplyMigration_ConvertSteamIDs(); case Migration_ConvertSteamIDsPlayertimes, Migration_ConvertSteamIDsChat: return; // this is confusing, but the above case handles all of them case Migration_PlayertimesDateToInt: ApplyMigration_PlayertimesDateToInt(); + case Migration_AddZonesFlagsAndData: ApplyMigration_AddZonesFlagsAndData(); } } @@ -2301,6 +2302,13 @@ void ApplyMigration_PlayertimesDateToInt() gH_SQL.Query(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_PlayertimesDateToInt, DBPrio_High); } +void ApplyMigration_AddZonesFlagsAndData() +{ + char sQuery[192]; + FormatEx(sQuery, 192, "ALTER TABLE `%smapzones` ADD COLUMN `flags` INT NULL AFTER `track`, ADD COLUMN `data` INT NULL AFTER `flags`;", gS_MySQLPrefix); + gH_SQL.Query(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_AddZonesFlagsAndData, DBPrio_High); +} + public void SQL_TableMigrationSingleQuery_Callback(Database db, DBResultSet results, const char[] error, any data) { InsertMigration(data); diff --git a/addons/sourcemod/scripting/shavit-zones.sp b/addons/sourcemod/scripting/shavit-zones.sp index 9959c4cee..8fb74817a 100644 --- a/addons/sourcemod/scripting/shavit-zones.sp +++ b/addons/sourcemod/scripting/shavit-zones.sp @@ -61,9 +61,11 @@ enum struct zone_cache_t { bool bZoneInitialized; int iZoneType; - int iZoneTrack; // 0 - main, 1 - bonus + int iZoneTrack; // 0 - main, 1 - bonus etc int iEntityID; int iDatabaseID; + int iZoneFlags; + int iZoneData; } enum struct zone_settings_t @@ -767,6 +769,8 @@ void ClearZone(int index) gA_ZoneCache[index].iZoneTrack = -1; gA_ZoneCache[index].iEntityID = -1; gA_ZoneCache[index].iDatabaseID = -1; + gA_ZoneCache[index].iZoneFlags = 0; + gA_ZoneCache[index].iZoneData = 0; } void UnhookEntity(int entity) @@ -851,7 +855,9 @@ void UnloadZones(int zone) void RefreshZones() { char sQuery[512]; - FormatEx(sQuery, 512, "SELECT type, corner1_x, corner1_y, corner1_z, corner2_x, corner2_y, corner2_z, destination_x, destination_y, destination_z, track, %s FROM %smapzones WHERE map = '%s';", (gB_MySQL)? "id":"rowid", gS_MySQLPrefix, gS_Map); + FormatEx(sQuery, 512, + "SELECT type, corner1_x, corner1_y, corner1_z, corner2_x, corner2_y, corner2_z, destination_x, destination_y, destination_z, track, %s, flags, data FROM %smapzones WHERE map = '%s';", + (gB_MySQL)? "id":"rowid", gS_MySQLPrefix, gS_Map); gH_SQL.Query(SQL_RefreshZones_Callback, sQuery, 0, DBPrio_High); } @@ -906,6 +912,8 @@ public void SQL_RefreshZones_Callback(Database db, DBResultSet results, const ch gA_ZoneCache[gI_MapZones].iZoneType = type; gA_ZoneCache[gI_MapZones].iZoneTrack = results.FetchInt(10); gA_ZoneCache[gI_MapZones].iDatabaseID = results.FetchInt(11); + gA_ZoneCache[gI_MapZones].iZoneFlags = results.FetchInt(12); + gA_ZoneCache[gI_MapZones].iZoneData = results.FetchInt(13); gA_ZoneCache[gI_MapZones].iEntityID = -1; gI_MapZones++; @@ -2451,7 +2459,9 @@ void SQL_DBConnect() gB_MySQL = StrEqual(sDriver, "mysql", false); char sQuery[1024]; - FormatEx(sQuery, 1024, "CREATE TABLE IF NOT EXISTS `%smapzones` (`id` INT AUTO_INCREMENT, `map` VARCHAR(128), `type` INT, `corner1_x` FLOAT, `corner1_y` FLOAT, `corner1_z` FLOAT, `corner2_x` FLOAT, `corner2_y` FLOAT, `corner2_z` FLOAT, `destination_x` FLOAT NOT NULL DEFAULT 0, `destination_y` FLOAT NOT NULL DEFAULT 0, `destination_z` FLOAT NOT NULL DEFAULT 0, `track` INT NOT NULL DEFAULT 0, PRIMARY KEY (`id`))%s;", gS_MySQLPrefix, (gB_MySQL)? " ENGINE=INNODB":""); + FormatEx(sQuery, 1024, + "CREATE TABLE IF NOT EXISTS `%smapzones` (`id` INT AUTO_INCREMENT, `map` VARCHAR(128), `type` INT, `corner1_x` FLOAT, `corner1_y` FLOAT, `corner1_z` FLOAT, `corner2_x` FLOAT, `corner2_y` FLOAT, `corner2_z` FLOAT, `destination_x` FLOAT NOT NULL DEFAULT 0, `destination_y` FLOAT NOT NULL DEFAULT 0, `destination_z` FLOAT NOT NULL DEFAULT 0, `track` INT NOT NULL DEFAULT 0, `flags` INT NOT NULL DEFAULT 0, `data` INT NOT NULL DEFAULT 0, PRIMARY KEY (`id`))%s;", + gS_MySQLPrefix, (gB_MySQL)? " ENGINE=INNODB":""); gH_SQL.Query(SQL_CreateTable_Callback, sQuery); } From b6b78f8eab4b28d31091443f218cb0bf0c735793 Mon Sep 17 00:00:00 2001 From: shavit Date: Tue, 14 May 2019 03:44:42 +0300 Subject: [PATCH 18/34] Added flag to force zones to be drawn (#798). --- addons/sourcemod/scripting/shavit-zones.sp | 68 +++++++++++++------ .../translations/shavit-zones.phrases.txt | 5 ++ 2 files changed, 52 insertions(+), 21 deletions(-) diff --git a/addons/sourcemod/scripting/shavit-zones.sp b/addons/sourcemod/scripting/shavit-zones.sp index 8fb74817a..98b50fb83 100644 --- a/addons/sourcemod/scripting/shavit-zones.sp +++ b/addons/sourcemod/scripting/shavit-zones.sp @@ -79,6 +79,11 @@ enum struct zone_settings_t bool bFlatZone; } +enum +{ + ZF_ForceRender = (1 << 0) +}; + int gI_ZoneType[MAXPLAYERS+1]; // 0 - nothing @@ -91,6 +96,8 @@ float gF_Modifier[MAXPLAYERS+1]; int gI_GridSnap[MAXPLAYERS+1]; bool gB_SnapToWall[MAXPLAYERS+1]; bool gB_CursorTracing[MAXPLAYERS+1]; +int gI_ZoneFlags[MAXPLAYERS+1]; +int gI_ZoneData[MAXPLAYERS+1]; // cache float gV_Point1[MAXPLAYERS+1][3]; @@ -1335,6 +1342,8 @@ public int MenuHandler_ZoneEdit(Menu menu, MenuAction action, int param1, int pa gI_ZoneTrack[param1] = gA_ZoneCache[id].iZoneTrack; gV_Teleport[param1] = gV_Destinations[id]; gI_ZoneDatabaseID[param1] = gA_ZoneCache[id].iDatabaseID; + gI_ZoneFlags[param1] = gA_ZoneCache[id].iZoneFlags; + gI_ZoneData[param1] = gA_ZoneCache[id].iZoneData; // to stop the original zone from drawing gA_ZoneCache[id].bZoneInitialized = false; @@ -1589,6 +1598,8 @@ void Reset(int client) gI_GridSnap[client] = 16; gB_SnapToWall[client] = false; gB_CursorTracing[client] = true; + gI_ZoneFlags[client] = 0; + gI_ZoneData[client] = 0; gI_ZoneDatabaseID[client] = -1; for(int i = 0; i < 3; i++) @@ -1895,30 +1906,42 @@ public int CreateZoneConfirm_Handler(Menu menu, MenuAction action, int param1, i { if(action == MenuAction_Select) { - char info[8]; - menu.GetItem(param2, info, 8); + char sInfo[16]; + menu.GetItem(param2, sInfo, 16); - if(StrEqual(info, "yes")) + if(StrEqual(sInfo, "yes")) { InsertZone(param1); gI_MapStep[param1] = 0; + + return 0; } - else if(StrEqual(info, "no")) + else if(StrEqual(sInfo, "no")) { Reset(param1); + + return 0; } - else if(StrEqual(info, "adjust")) + else if(StrEqual(sInfo, "adjust")) { CreateAdjustMenu(param1, 0); + + return 0; } - else if(StrEqual(info, "tpzone")) + else if(StrEqual(sInfo, "tpzone")) { UpdateTeleportZone(param1); - CreateEditMenu(param1); } + + else if(StrEqual(sInfo, "forcerender")) + { + gI_ZoneFlags[param1] ^= ZF_ForceRender; + } + + CreateEditMenu(param1); } else if(action == MenuAction_End) @@ -1977,7 +2000,7 @@ void CreateEditMenu(int client) char sTrack[32]; GetTrackName(client, gI_ZoneTrack[client], sTrack, 32); - Menu menu = new Menu(CreateZoneConfirm_Handler, MENU_ACTIONS_DEFAULT|MenuAction_DisplayItem); + Menu menu = new Menu(CreateZoneConfirm_Handler); menu.SetTitle("%T\n%T\n ", "ZoneEditConfirm", client, "ZoneEditTrack", client, sTrack); char sMenuItem[64]; @@ -2012,6 +2035,9 @@ void CreateEditMenu(int client) FormatEx(sMenuItem, 64, "%T", "ZoneSetAdjust", client); menu.AddItem("adjust", sMenuItem); + FormatEx(sMenuItem, 64, "%T", "ZoneForceRender", client, ((gI_ZoneFlags[client] & ZF_ForceRender) > 0)? 'x':' '); + menu.AddItem("forcerender", sMenuItem); + menu.ExitButton = true; menu.Display(client, 600); } @@ -2096,13 +2122,13 @@ public int ZoneAdjuster_Handler(Menu menu, MenuAction action, int param1, int pa void InsertZone(int client) { - int type = gI_ZoneType[client]; - int index = GetZoneIndex(type, gI_ZoneTrack[client]); - bool insert = (gI_ZoneDatabaseID[client] == -1 && (index == -1 || type >= Zone_Respawn)); + int iType = gI_ZoneType[client]; + int iIndex = GetZoneIndex(iType, gI_ZoneTrack[client]); + bool bInsert = (gI_ZoneDatabaseID[client] == -1 && (iIndex == -1 || iType >= Zone_Respawn)); char sQuery[512]; - if(type == Zone_CustomSpawn) + if(iType == Zone_CustomSpawn) { Shavit_LogMessage("%L - added custom spawn {%.2f, %.2f, %.2f} to map `%s`.", client, gV_Point1[client][0], gV_Point1[client][1], gV_Point1[client][2], gS_Map); @@ -2111,24 +2137,24 @@ void InsertZone(int client) gS_MySQLPrefix, gS_Map, Zone_CustomSpawn, gV_Point1[client][0], gV_Point1[client][1], gV_Point1[client][2], gI_ZoneTrack[client]); } - else if(insert) // insert + else if(bInsert) // insert { - Shavit_LogMessage("%L - added %s to map `%s`.", client, gS_ZoneNames[type], gS_Map); + Shavit_LogMessage("%L - added %s to map `%s`.", client, gS_ZoneNames[iType], gS_Map); FormatEx(sQuery, 512, - "INSERT INTO %smapzones (map, type, corner1_x, corner1_y, corner1_z, corner2_x, corner2_y, corner2_z, destination_x, destination_y, destination_z, track) VALUES ('%s', %d, '%.03f', '%.03f', '%.03f', '%.03f', '%.03f', '%.03f', '%.03f', '%.03f', '%.03f', %d);", - gS_MySQLPrefix, gS_Map, type, gV_Point1[client][0], gV_Point1[client][1], gV_Point1[client][2], gV_Point2[client][0], gV_Point2[client][1], gV_Point2[client][2], gV_Teleport[client][0], gV_Teleport[client][1], gV_Teleport[client][2], gI_ZoneTrack[client]); + "INSERT INTO %smapzones (map, type, corner1_x, corner1_y, corner1_z, corner2_x, corner2_y, corner2_z, destination_x, destination_y, destination_z, track, flags, data) VALUES ('%s', %d, '%.03f', '%.03f', '%.03f', '%.03f', '%.03f', '%.03f', '%.03f', '%.03f', '%.03f', %d, %d, %d);", + gS_MySQLPrefix, gS_Map, iType, gV_Point1[client][0], gV_Point1[client][1], gV_Point1[client][2], gV_Point2[client][0], gV_Point2[client][1], gV_Point2[client][2], gV_Teleport[client][0], gV_Teleport[client][1], gV_Teleport[client][2], gI_ZoneTrack[client], gI_ZoneFlags[client], gI_ZoneData[client]); } else // update { - Shavit_LogMessage("%L - updated %s in map `%s`.", client, gS_ZoneNames[type], gS_Map); + Shavit_LogMessage("%L - updated %s in map `%s`.", client, gS_ZoneNames[iType], gS_Map); if(gI_ZoneDatabaseID[client] == -1) { for(int i = 0; i < gI_MapZones; i++) { - if(gA_ZoneCache[i].bZoneInitialized && gA_ZoneCache[i].iZoneType == type && gA_ZoneCache[i].iZoneTrack == gI_ZoneTrack[client]) + if(gA_ZoneCache[i].bZoneInitialized && gA_ZoneCache[i].iZoneType == iType && gA_ZoneCache[i].iZoneTrack == gI_ZoneTrack[client]) { gI_ZoneDatabaseID[client] = gA_ZoneCache[i].iDatabaseID; } @@ -2136,8 +2162,8 @@ void InsertZone(int client) } FormatEx(sQuery, 512, - "UPDATE %smapzones SET corner1_x = '%.03f', corner1_y = '%.03f', corner1_z = '%.03f', corner2_x = '%.03f', corner2_y = '%.03f', corner2_z = '%.03f', destination_x = '%.03f', destination_y = '%.03f', destination_z = '%.03f', track = %d WHERE %s = %d;", - gS_MySQLPrefix, gV_Point1[client][0], gV_Point1[client][1], gV_Point1[client][2], gV_Point2[client][0], gV_Point2[client][1], gV_Point2[client][2], gV_Teleport[client][0], gV_Teleport[client][1], gV_Teleport[client][2], gI_ZoneTrack[client], (gB_MySQL)? "id":"rowid", gI_ZoneDatabaseID[client]); + "UPDATE %smapzones SET corner1_x = '%.03f', corner1_y = '%.03f', corner1_z = '%.03f', corner2_x = '%.03f', corner2_y = '%.03f', corner2_z = '%.03f', destination_x = '%.03f', destination_y = '%.03f', destination_z = '%.03f', track = %d, flags = %d, data = %d WHERE %s = %d;", + gS_MySQLPrefix, gV_Point1[client][0], gV_Point1[client][1], gV_Point1[client][2], gV_Point2[client][0], gV_Point2[client][1], gV_Point2[client][2], gV_Teleport[client][0], gV_Teleport[client][1], gV_Teleport[client][2], gI_ZoneTrack[client], gI_ZoneFlags[client], gI_ZoneData[client], (gB_MySQL)? "id":"rowid", gI_ZoneDatabaseID[client]); } gH_SQL.Query(SQL_InsertZone_Callback, sQuery, GetClientSerial(client)); @@ -2191,7 +2217,7 @@ public Action Timer_DrawEverything(Handle Timer) int type = gA_ZoneCache[i].iZoneType; int track = gA_ZoneCache[i].iZoneTrack; - if(gA_ZoneSettings[type][track].bVisible) + if(gA_ZoneSettings[type][track].bVisible || (gA_ZoneCache[i].iZoneFlags & ZF_ForceRender) > 0) { DrawZone(gV_MapZones_Visual[i], GetZoneColors(type, track), diff --git a/addons/sourcemod/translations/shavit-zones.phrases.txt b/addons/sourcemod/translations/shavit-zones.phrases.txt index 3c43ce515..8ec0e4326 100644 --- a/addons/sourcemod/translations/shavit-zones.phrases.txt +++ b/addons/sourcemod/translations/shavit-zones.phrases.txt @@ -179,6 +179,11 @@ { "en" "Adjust position" } + "ZoneForceRender" + { + "#format" "{1:c}" + "en" "[{1}] Force zone drawing" + } "ZoneSetNo" { "en" "No" From a7c743cf299a816f5e60b14214880201ad463e50 Mon Sep 17 00:00:00 2001 From: shavit Date: Tue, 14 May 2019 04:27:39 +0300 Subject: [PATCH 19/34] Added custom airaccelerate zones and some natives. (#797) Shavit_GetZoneData, Shavit_GetZoneFlags, and Shavit_InsideZoneGetID --- addons/sourcemod/configs/shavit-zones.cfg | 24 +++++++ addons/sourcemod/scripting/include/shavit.inc | 37 +++++++++- addons/sourcemod/scripting/shavit-core.sp | 40 +++++++++-- addons/sourcemod/scripting/shavit-zones.sp | 68 ++++++++++++++++++- .../translations/shavit-zones.phrases.txt | 9 +++ 5 files changed, 170 insertions(+), 8 deletions(-) diff --git a/addons/sourcemod/configs/shavit-zones.cfg b/addons/sourcemod/configs/shavit-zones.cfg index 1eb9c9707..c22ca60a3 100644 --- a/addons/sourcemod/configs/shavit-zones.cfg +++ b/addons/sourcemod/configs/shavit-zones.cfg @@ -134,6 +134,18 @@ "width" "1.5" } + "Airaccelerate" + { + "visible" "1" + + "red" "118" + "green" "102" + "blue" "173" + + "alpha" "255" + "width" "1.5" + } + "Bonus Start" { "visible" "1" @@ -253,5 +265,17 @@ "alpha" "255" "width" "1.0" } + + "Bonus Airaccelerate" + { + "visible" "1" + + "red" "118" + "green" "102" + "blue" "173" + + "alpha" "255" + "width" "1.0" + } } } diff --git a/addons/sourcemod/scripting/include/shavit.inc b/addons/sourcemod/scripting/include/shavit.inc index ba1ee5849..2c9e461a1 100644 --- a/addons/sourcemod/scripting/include/shavit.inc +++ b/addons/sourcemod/scripting/include/shavit.inc @@ -103,6 +103,7 @@ enum Zone_CustomSpawn, Zone_Easybhop, Zone_Slide, + Zone_Airaccelerate, ZONETYPES_SIZE }; @@ -571,7 +572,7 @@ forward Action Shavit_OnSave(int client); * @param client Client index. * @param type Zone type. * @param track Zone track. - * @param id Zone ID. 0 for native zones. + * @param id Zone ID. * @param entity Zone trigger entity index. * @noreturn */ @@ -583,7 +584,7 @@ forward void Shavit_OnEnterZone(int client, int type, int track, int id, int ent * @param client Client index. * @param type Zone type. * @param track Zone track. - * @param id Zone ID. 0 for native zones. + * @param id Zone ID. * @param entity Zone trigger entity index. * @noreturn */ @@ -979,7 +980,7 @@ native float Shavit_GetTimeForRank(int style, int rank, int track); native bool Shavit_ZoneExists(int type, int track); /** - * Checks if a player is inside a mapzone + * Checks if a player is inside a mapzone. * * @param client Client index. * @param type Mapzone type. @@ -988,6 +989,33 @@ native bool Shavit_ZoneExists(int type, int track); */ native bool Shavit_InsideZone(int client, int type, int track); +/** + * Gets the specified zone's data. + * + * @param zoneid ID of the zone we query the data of. + * @return Zone data. 0 if none is specified. + */ +native int Shavit_GetZoneData(int zoneid); + +/** + * Gets the specified zone's flags. + * + * @param zoneid ID of the zone we query the flags of. + * @return Zone flags. 0 if none is specified. + */ +native int Shavit_GetZoneFlags(int zoneid); + +/** + * Checks if a player is inside a mapzone. + * + * @param client Client index. + * @param type Mapzone type. + * @param track Mapzone track, -1 to ignore track. + * @param zoneid Reference to variable that will hold the zone's ID. + * @return Boolean value. + */ +native bool Shavit_InsideZoneGetID(int client, int type, int track, int &zoneid); + /** * Checks if a player is in the process of creating a mapzone. * @@ -1485,9 +1513,12 @@ public void __pl_shavit_SetNTVOptional() MarkNativeAsOptional("Shavit_GetWRName"); MarkNativeAsOptional("Shavit_GetWRRecordID"); MarkNativeAsOptional("Shavit_GetWRTime"); + MarkNativeAsOptional("Shavit_GetZoneData"); + MarkNativeAsOptional("Shavit_GetZoneFlags"); MarkNativeAsOptional("Shavit_HasStyleAccess"); MarkNativeAsOptional("Shavit_HijackAngles"); MarkNativeAsOptional("Shavit_InsideZone"); + MarkNativeAsOptional("Shavit_InsideZoneGetID"); MarkNativeAsOptional("Shavit_IsClientCreatingZone"); MarkNativeAsOptional("Shavit_IsKZMap"); MarkNativeAsOptional("Shavit_IsPaused"); diff --git a/addons/sourcemod/scripting/shavit-core.sp b/addons/sourcemod/scripting/shavit-core.sp index d78ad7701..0204a6815 100644 --- a/addons/sourcemod/scripting/shavit-core.sp +++ b/addons/sourcemod/scripting/shavit-core.sp @@ -147,6 +147,7 @@ char gS_DeleteMap[MAXPLAYERS+1][160]; char gS_WipePlayerID[MAXPLAYERS+1][32]; char gS_Verification[MAXPLAYERS+1][16]; bool gB_CookiesRetrieved[MAXPLAYERS+1]; +float gF_ZoneAiraccelerate[MAXPLAYERS+1]; // flags int gI_StyleFlag[STYLE_LIMIT]; @@ -2557,11 +2558,37 @@ public void SQL_CreateUsersTable_Callback(Database db, DBResultSet results, cons Call_Finish(); } +public void Shavit_OnEnterZone(int client, int type, int track, int id, int entity) +{ + if(type == Zone_Airaccelerate) + { + gF_ZoneAiraccelerate[client] = float(Shavit_GetZoneData(id)); + + UpdateAiraccelerate(client, gF_ZoneAiraccelerate[client]); + } +} + +public void Shavit_OnLeaveZone(int client, int type, int track, int id, int entity) +{ + if(type == Zone_Airaccelerate) + { + UpdateAiraccelerate(client, view_as(gA_StyleSettings[gA_Timers[client].iStyle].fAiraccelerate)); + } +} + public void PreThinkPost(int client) { if(IsPlayerAlive(client)) { - sv_airaccelerate.FloatValue = view_as(gA_StyleSettings[gA_Timers[client].iStyle].fAiraccelerate); + if(!gB_Zones || !Shavit_InsideZone(client, Zone_Airaccelerate, -1)) + { + sv_airaccelerate.FloatValue = view_as(gA_StyleSettings[gA_Timers[client].iStyle].fAiraccelerate); + } + + else + { + sv_airaccelerate.FloatValue = gF_ZoneAiraccelerate[client]; + } if(sv_enablebunnyhopping != null) { @@ -3003,6 +3030,13 @@ void StopTimer_Cheat(int client, const char[] message) Shavit_PrintToChat(client, "%T", "CheatTimerStop", client, gS_ChatStrings.sWarning, gS_ChatStrings.sText, message); } +void UpdateAiraccelerate(int client, float airaccelerate) +{ + char sAiraccelerate[8]; + FloatToString(airaccelerate, sAiraccelerate, 8); + sv_airaccelerate.ReplicateToClient(client, sAiraccelerate); +} + void UpdateStyleSettings(int client) { if(sv_autobunnyhopping != null) @@ -3015,9 +3049,7 @@ void UpdateStyleSettings(int client) sv_enablebunnyhopping.ReplicateToClient(client, (gA_StyleSettings[gA_Timers[client].iStyle].bEnableBunnyhopping)? "1":"0"); } - char sAiraccelerate[8]; - FloatToString(gA_StyleSettings[gA_Timers[client].iStyle].fAiraccelerate, sAiraccelerate, 8); - sv_airaccelerate.ReplicateToClient(client, sAiraccelerate); + UpdateAiraccelerate(client, view_as(gA_StyleSettings[gA_Timers[client].iStyle].fAiraccelerate)); SetEntityGravity(client, view_as(gA_StyleSettings[gA_Timers[client].iStyle].fGravityMultiplier)); } diff --git a/addons/sourcemod/scripting/shavit-zones.sp b/addons/sourcemod/scripting/shavit-zones.sp index 98b50fb83..105ae249c 100644 --- a/addons/sourcemod/scripting/shavit-zones.sp +++ b/addons/sourcemod/scripting/shavit-zones.sp @@ -54,7 +54,8 @@ char gS_ZoneNames[][] = "Teleport Zone", // teleports to a defined point "SPAWN POINT", // << unused "Easybhop Zone", // forces easybhop whether if the player is in non-easy styles or if the server has different settings - "Slide Zone" // allows players to slide, in order to fix parts like the 5th stage of bhop_arcane + "Slide Zone", // allows players to slide, in order to fix parts like the 5th stage of bhop_arcane + "Custom Airaccelerate" // custom sv_airaccelerate inside this }; enum struct zone_cache_t @@ -98,6 +99,7 @@ bool gB_SnapToWall[MAXPLAYERS+1]; bool gB_CursorTracing[MAXPLAYERS+1]; int gI_ZoneFlags[MAXPLAYERS+1]; int gI_ZoneData[MAXPLAYERS+1]; +bool gB_WaitingForChatInput[MAXPLAYERS+1]; // cache float gV_Point1[MAXPLAYERS+1][3]; @@ -173,7 +175,10 @@ public Plugin myinfo = public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) { // zone natives + CreateNative("Shavit_GetZoneData", Native_GetZoneData); + CreateNative("Shavit_GetZoneFlags", Native_GetZoneFlags); CreateNative("Shavit_InsideZone", Native_InsideZone); + CreateNative("Shavit_InsideZoneGetID", Native_InsideZoneGetID); CreateNative("Shavit_IsClientCreatingZone", Native_IsClientCreatingZone); CreateNative("Shavit_ZoneExists", Native_ZoneExists); CreateNative("Shavit_Zones_DeleteMap", Native_Zones_DeleteMap); @@ -422,11 +427,42 @@ public int Native_ZoneExists(Handle handler, int numParams) return (GetZoneIndex(GetNativeCell(1), GetNativeCell(2)) != -1); } +public int Native_GetZoneData(Handle handler, int numParams) +{ + return gA_ZoneCache[GetNativeCell(1)].iZoneData; +} + +public int Native_GetZoneFlags(Handle handler, int numParams) +{ + return gA_ZoneCache[GetNativeCell(1)].iZoneFlags; +} + public int Native_InsideZone(Handle handler, int numParams) { return InsideZone(GetNativeCell(1), GetNativeCell(2), GetNativeCell(3)); } +public int Native_InsideZoneGetID(Handle handler, int numParams) +{ + int client = GetNativeCell(1); + int iType = GetNativeCell(2); + int iTrack = GetNativeCell(3); + + for(int i = 0; i < MAX_ZONES; i++) + { + if(gB_InsideZoneID[client][i] && + gA_ZoneCache[i].iZoneType == iType && + (gA_ZoneCache[i].iZoneTrack == iTrack || iTrack == -1)) + { + SetNativeCellRef(4, i); + + return true; + } + } + + return false; +} + public int Native_Zones_DeleteMap(Handle handler, int numParams) { char sMap[160]; @@ -1601,6 +1637,7 @@ void Reset(int client) gI_ZoneFlags[client] = 0; gI_ZoneData[client] = 0; gI_ZoneDatabaseID[client] = -1; + gB_WaitingForChatInput[client] = false; for(int i = 0; i < 3; i++) { @@ -1936,6 +1973,16 @@ public int CreateZoneConfirm_Handler(Menu menu, MenuAction action, int param1, i UpdateTeleportZone(param1); } + else if(StrEqual(sInfo, "datafromchat")) + { + gI_ZoneData[param1] = 0; + gB_WaitingForChatInput[param1] = true; + + Shavit_PrintToChat(param1, "%T", "ZoneEnterDataChat", param1); + + return 0; + } + else if(StrEqual(sInfo, "forcerender")) { gI_ZoneFlags[param1] ^= ZF_ForceRender; @@ -1952,6 +1999,19 @@ public int CreateZoneConfirm_Handler(Menu menu, MenuAction action, int param1, i return 0; } +public Action OnClientSayCommand(int client, const char[] command, const char[] sArgs) +{ + if(gB_WaitingForChatInput[client] && gI_MapStep[client] == 3) + { + gI_ZoneData[client] = StringToInt(sArgs); + CreateEditMenu(client); + + return Plugin_Handled; + } + + return Plugin_Continue; +} + void GetTrackName(int client, int track, char[] output, int size) { if(track < 0 || track >= TRACKS_SIZE) @@ -2038,6 +2098,12 @@ void CreateEditMenu(int client) FormatEx(sMenuItem, 64, "%T", "ZoneForceRender", client, ((gI_ZoneFlags[client] & ZF_ForceRender) > 0)? 'x':' '); menu.AddItem("forcerender", sMenuItem); + if(gI_ZoneType[client] == Zone_Airaccelerate) + { + FormatEx(sMenuItem, 64, "%T", "ZoneSetAiraccelerate", client, gI_ZoneData[client]); + menu.AddItem("datafromchat", sMenuItem); + } + menu.ExitButton = true; menu.Display(client, 600); } diff --git a/addons/sourcemod/translations/shavit-zones.phrases.txt b/addons/sourcemod/translations/shavit-zones.phrases.txt index 8ec0e4326..65ba6806b 100644 --- a/addons/sourcemod/translations/shavit-zones.phrases.txt +++ b/addons/sourcemod/translations/shavit-zones.phrases.txt @@ -184,6 +184,15 @@ "#format" "{1:c}" "en" "[{1}] Force zone drawing" } + "ZoneSetAiraccelerate" + { + "#format" "{1:d}" + "en" "Airaccelerate: {1}" + } + "ZoneEnterDataChat" + { + "en" "Input your desired data in chat." + } "ZoneSetNo" { "en" "No" From 26dd2004086abc343806562362327b44036ffa28 Mon Sep 17 00:00:00 2001 From: shavit Date: Tue, 14 May 2019 04:56:26 +0300 Subject: [PATCH 20/34] Changed "No Speed Limit" zones to "Custom Speed Limit" (#797). --- addons/sourcemod/scripting/include/shavit.inc | 2 +- addons/sourcemod/scripting/shavit-core.sp | 20 +++++++++++++---- addons/sourcemod/scripting/shavit-hud.sp | 22 +++++++++++++++++-- addons/sourcemod/scripting/shavit-zones.sp | 10 +++++++-- .../translations/shavit-hud.phrases.txt | 7 +++++- .../translations/shavit-zones.phrases.txt | 5 +++++ 6 files changed, 56 insertions(+), 10 deletions(-) diff --git a/addons/sourcemod/scripting/include/shavit.inc b/addons/sourcemod/scripting/include/shavit.inc index 2c9e461a1..43c7eba80 100644 --- a/addons/sourcemod/scripting/include/shavit.inc +++ b/addons/sourcemod/scripting/include/shavit.inc @@ -98,7 +98,7 @@ enum Zone_Stop, Zone_Slay, Zone_Freestyle, - Zone_NoVelLimit, + Zone_CustomSpeedLimit, Zone_Teleport, Zone_CustomSpawn, Zone_Easybhop, diff --git a/addons/sourcemod/scripting/shavit-core.sp b/addons/sourcemod/scripting/shavit-core.sp index 0204a6815..94cd3c837 100644 --- a/addons/sourcemod/scripting/shavit-core.sp +++ b/addons/sourcemod/scripting/shavit-core.sp @@ -148,6 +148,7 @@ char gS_WipePlayerID[MAXPLAYERS+1][32]; char gS_Verification[MAXPLAYERS+1][16]; bool gB_CookiesRetrieved[MAXPLAYERS+1]; float gF_ZoneAiraccelerate[MAXPLAYERS+1]; +float gF_ZoneSpeedLimit[MAXPLAYERS+1]; // flags int gI_StyleFlag[STYLE_LIMIT]; @@ -2566,6 +2567,11 @@ public void Shavit_OnEnterZone(int client, int type, int track, int id, int enti UpdateAiraccelerate(client, gF_ZoneAiraccelerate[client]); } + + else if(type == Zone_CustomSpeedLimit) + { + gF_ZoneSpeedLimit[client] = float(Shavit_GetZoneData(id)); + } } public void Shavit_OnLeaveZone(int client, int type, int track, int id, int entity) @@ -2940,17 +2946,23 @@ public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3 } // velocity limit - if(iGroundEntity != -1 && view_as(gA_StyleSettings[gA_Timers[client].iStyle].fVelocityLimit > 0.0) && - (!gB_Zones || !Shavit_InsideZone(client, Zone_NoVelLimit, -1))) + if(iGroundEntity != -1 && view_as(gA_StyleSettings[gA_Timers[client].iStyle].fVelocityLimit > 0.0)) { + float fSpeedLimit = view_as(gA_StyleSettings[gA_Timers[client].iStyle].fVelocityLimit); + + if(gB_Zones && Shavit_InsideZone(client, Zone_CustomSpeedLimit, -1)) + { + fSpeedLimit = gF_ZoneSpeedLimit[client]; + } + float fSpeed[3]; GetEntPropVector(client, Prop_Data, "m_vecVelocity", fSpeed); float fSpeed_New = (SquareRoot(Pow(fSpeed[0], 2.0) + Pow(fSpeed[1], 2.0))); - if(fSpeed_New > 0.0) + if(fSpeedLimit != 0.0 && fSpeed_New > 0.0) { - float fScale = view_as(gA_StyleSettings[gA_Timers[client].iStyle].fVelocityLimit) / fSpeed_New; + float fScale = fSpeedLimit / fSpeed_New; if(fScale < 1.0) { diff --git a/addons/sourcemod/scripting/shavit-hud.sp b/addons/sourcemod/scripting/shavit-hud.sp index b7adc4e10..6ac5f8d0b 100644 --- a/addons/sourcemod/scripting/shavit-hud.sp +++ b/addons/sourcemod/scripting/shavit-hud.sp @@ -109,6 +109,7 @@ int gI_Buttons[MAXPLAYERS+1]; float gF_ConnectTime[MAXPLAYERS+1]; bool gB_FirstPrint[MAXPLAYERS+1]; int gI_PreviousSpeed[MAXPLAYERS+1]; +int gI_ZoneSpeedLimit[MAXPLAYERS+1]; bool gB_Late = false; @@ -940,6 +941,15 @@ int GetGradient(int start, int end, int steps) return GetHex(aColorGradient); } +public void Shavit_OnEnterZone(int client, int type, int track, int id, int entity) +{ + if(type == Zone_CustomSpeedLimit) + { + gI_ZoneSpeedLimit[client] = Shavit_GetZoneData(id); + } +} + + int AddHUDToBuffer_Source2013(int client, huddata_t data, char[] buffer, int maxlen) { int iLines = 0; @@ -1090,9 +1100,17 @@ int AddHUDToBuffer_Source2013(int client, huddata_t data, char[] buffer, int max AddHUDLine(buffer, maxlen, sLine, iLines); iLines++; - if(gA_StyleSettings[data.iStyle].fVelocityLimit > 0.0 && Shavit_InsideZone(data.iTarget, Zone_NoVelLimit, -1)) + if(gA_StyleSettings[data.iStyle].fVelocityLimit > 0.0 && Shavit_InsideZone(data.iTarget, Zone_CustomSpeedLimit, -1)) { - FormatEx(sLine, 128, "%T", "HudNoSpeedLimit", client); + if(gI_ZoneSpeedLimit[data.iTarget] == 0) + { + FormatEx(sLine, 128, "%T", "HudNoSpeedLimit", data.iTarget); + } + + else + { + FormatEx(sLine, 128, "%T", "HudCustomSpeedLimit", client, gI_ZoneSpeedLimit[data.iTarget]); + } AddHUDLine(buffer, maxlen, sLine, iLines); iLines++; diff --git a/addons/sourcemod/scripting/shavit-zones.sp b/addons/sourcemod/scripting/shavit-zones.sp index 105ae249c..bcd19ebab 100644 --- a/addons/sourcemod/scripting/shavit-zones.sp +++ b/addons/sourcemod/scripting/shavit-zones.sp @@ -50,7 +50,7 @@ char gS_ZoneNames[][] = "Glitch Zone (Stop Timer)", // stops the player's timer "Slay Player", // slays (kills) players which come to this zone "Freestyle Zone", // ignores style physics when at this zone. e.g. WASD when SWing - "No Speed Limit", // ignores velocity limit in that zone + "Custom Speed Limit", // overwrites velocity limit in the zone "Teleport Zone", // teleports to a defined point "SPAWN POINT", // << unused "Easybhop Zone", // forces easybhop whether if the player is in non-easy styles or if the server has different settings @@ -1278,7 +1278,7 @@ public int MenuHandler_SelectZoneTrack(Menu menu, MenuAction action, int param1, GetTrackName(param1, gI_ZoneTrack[param1], sTrack, 16); Menu submenu = new Menu(MenuHandler_SelectZoneType); - submenu.SetTitle("%T", "ZoneMenuTitle", param1, sTrack); + submenu.SetTitle("%T\n ", "ZoneMenuTitle", param1, sTrack); for(int i = 0; i < sizeof(gS_ZoneNames); i++) { @@ -2104,6 +2104,12 @@ void CreateEditMenu(int client) menu.AddItem("datafromchat", sMenuItem); } + else if(gI_ZoneType[client] == Zone_CustomSpeedLimit) + { + FormatEx(sMenuItem, 64, "%T", "ZoneSetSpeedLimit", client, gI_ZoneData[client]); + menu.AddItem("datafromchat", sMenuItem); + } + menu.ExitButton = true; menu.Display(client, 600); } diff --git a/addons/sourcemod/translations/shavit-hud.phrases.txt b/addons/sourcemod/translations/shavit-hud.phrases.txt index cc53345f8..4083e61f0 100644 --- a/addons/sourcemod/translations/shavit-hud.phrases.txt +++ b/addons/sourcemod/translations/shavit-hud.phrases.txt @@ -81,7 +81,12 @@ } "HudNoSpeedLimit" { - "en" "No Speed Limit" + "en" "(No Speed Limit)" + } + "HudCustomSpeedLimit" + { + "#format" "{1:d}" + "en" "(Speed Limit: {1})" } // ---------- Menus ---------- // "HUDMenuTitle" diff --git a/addons/sourcemod/translations/shavit-zones.phrases.txt b/addons/sourcemod/translations/shavit-zones.phrases.txt index 65ba6806b..34a62176a 100644 --- a/addons/sourcemod/translations/shavit-zones.phrases.txt +++ b/addons/sourcemod/translations/shavit-zones.phrases.txt @@ -189,6 +189,11 @@ "#format" "{1:d}" "en" "Airaccelerate: {1}" } + "ZoneSetSpeedLimit" + { + "#format" "{1:d}" + "en" "Custom speed limit: {1}" + } "ZoneEnterDataChat" { "en" "Input your desired data in chat." From f8e385fda5fb7c96e69cc89c1441cc7d516e8bcf Mon Sep 17 00:00:00 2001 From: shavit Date: Tue, 14 May 2019 05:06:58 +0300 Subject: [PATCH 21/34] Added better indicators for speed limit zone creation. --- addons/sourcemod/scripting/shavit-zones.sp | 13 +++++++++++-- .../sourcemod/translations/shavit-zones.phrases.txt | 7 ++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/addons/sourcemod/scripting/shavit-zones.sp b/addons/sourcemod/scripting/shavit-zones.sp index bcd19ebab..79daa6ea6 100644 --- a/addons/sourcemod/scripting/shavit-zones.sp +++ b/addons/sourcemod/scripting/shavit-zones.sp @@ -2095,7 +2095,7 @@ void CreateEditMenu(int client) FormatEx(sMenuItem, 64, "%T", "ZoneSetAdjust", client); menu.AddItem("adjust", sMenuItem); - FormatEx(sMenuItem, 64, "%T", "ZoneForceRender", client, ((gI_ZoneFlags[client] & ZF_ForceRender) > 0)? 'x':' '); + FormatEx(sMenuItem, 64, "%T", "ZoneForceRender", client, ((gI_ZoneFlags[client] & ZF_ForceRender) > 0)? "+":"-"); menu.AddItem("forcerender", sMenuItem); if(gI_ZoneType[client] == Zone_Airaccelerate) @@ -2106,7 +2106,16 @@ void CreateEditMenu(int client) else if(gI_ZoneType[client] == Zone_CustomSpeedLimit) { - FormatEx(sMenuItem, 64, "%T", "ZoneSetSpeedLimit", client, gI_ZoneData[client]); + if(gI_ZoneData[client] == 0) + { + FormatEx(sMenuItem, 64, "%T", "ZoneSetSpeedLimitUnlimited", client, gI_ZoneData[client]); + } + + else + { + FormatEx(sMenuItem, 64, "%T", "ZoneSetSpeedLimit", client, gI_ZoneData[client]); + } + menu.AddItem("datafromchat", sMenuItem); } diff --git a/addons/sourcemod/translations/shavit-zones.phrases.txt b/addons/sourcemod/translations/shavit-zones.phrases.txt index 34a62176a..dc4e291b5 100644 --- a/addons/sourcemod/translations/shavit-zones.phrases.txt +++ b/addons/sourcemod/translations/shavit-zones.phrases.txt @@ -181,7 +181,7 @@ } "ZoneForceRender" { - "#format" "{1:c}" + "#format" "{1:s}" "en" "[{1}] Force zone drawing" } "ZoneSetAiraccelerate" @@ -194,6 +194,11 @@ "#format" "{1:d}" "en" "Custom speed limit: {1}" } + "ZoneSetSpeedLimitUnlimited" + { + "#format" "{1:d}" + "en" "Custom speed limit: {1} (No Limit)" + } "ZoneEnterDataChat" { "en" "Input your desired data in chat." From 25ca9f72da0e35292974a980e4537c3eef3b6d81 Mon Sep 17 00:00:00 2001 From: shavit Date: Thu, 23 May 2019 22:14:17 +0300 Subject: [PATCH 22/34] Removed gI_RecordAmount for a more elegant solution. --- addons/sourcemod/scripting/shavit-wr.sp | 50 ++++++++++++++----------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/addons/sourcemod/scripting/shavit-wr.sp b/addons/sourcemod/scripting/shavit-wr.sp index c320f7b20..83c36eb48 100644 --- a/addons/sourcemod/scripting/shavit-wr.sp +++ b/addons/sourcemod/scripting/shavit-wr.sp @@ -63,7 +63,6 @@ int gI_ValidMaps = 1; float gF_WRTime[STYLE_LIMIT][TRACKS_SIZE]; int gI_WRRecordID[STYLE_LIMIT][TRACKS_SIZE]; char gS_WRName[STYLE_LIMIT][TRACKS_SIZE][MAX_NAME_LENGTH]; -int gI_RecordAmount[STYLE_LIMIT][TRACKS_SIZE]; ArrayList gA_Leaderboard[STYLE_LIMIT][TRACKS_SIZE]; float gF_PlayerRecord[MAXPLAYERS+1][STYLE_LIMIT][TRACKS_SIZE]; @@ -381,7 +380,6 @@ public void Shavit_OnStyleConfigLoaded(int styles) } gA_Leaderboard[i][j].Clear(); - gI_RecordAmount[i][j] = 0; } else @@ -489,7 +487,7 @@ void UpdateWRCache() gS_MySQLPrefix, gS_MySQLPrefix, gS_Map, gS_MySQLPrefix); } - gH_SQL.Query(SQL_UpdateWRCache_Callback, sQuery, 0, DBPrio_Low); + gH_SQL.Query(SQL_UpdateWRCache_Callback, sQuery); } public void SQL_UpdateWRCache_Callback(Database db, DBResultSet results, const char[] error, any data) @@ -508,7 +506,6 @@ public void SQL_UpdateWRCache_Callback(Database db, DBResultSet results, const c { strcopy(gS_WRName[i][j], MAX_NAME_LENGTH, "invalid"); gF_WRTime[i][j] = 0.0; - gI_RecordAmount[i][j] = 0; } } @@ -583,7 +580,7 @@ public int Native_GetRankForTime(Handle handler, int numParams) public int Native_GetRecordAmount(Handle handler, int numParams) { - return gI_RecordAmount[GetNativeCell(1)][GetNativeCell(2)]; + return GetRecordAmount(GetNativeCell(1), GetNativeCell(2)); } public int Native_GetTimeForRank(Handle handler, int numParams) @@ -593,10 +590,10 @@ public int Native_GetTimeForRank(Handle handler, int numParams) int track = GetNativeCell(3); #if defined DEBUG - Shavit_PrintToChatAll("style %d | rank %d | track %d | amount %d", style, rank, track, gI_RecordAmount[style][track]); + Shavit_PrintToChatAll("style %d | rank %d | track %d | amount %d", style, rank, track, GetRecordAmount(style, track)); #endif - if(rank > gI_RecordAmount[style][track]) + if(rank > GetRecordAmount(style, track)) { return view_as(0.0); } @@ -656,13 +653,14 @@ public Action Command_PrintLeaderboards(int client, int args) GetCmdArg(1, sArg, 8); int iStyle = StringToInt(sArg); + int iRecords = GetRecordAmount(iStyle, Track_Main); ReplyToCommand(client, "Track: Main - Style: %d", iStyle); ReplyToCommand(client, "Current PB: %f", gF_PlayerRecord[client][iStyle][0]); - ReplyToCommand(client, "Count: %d", gI_RecordAmount[iStyle][0]); + ReplyToCommand(client, "Count: %d", iRecords); ReplyToCommand(client, "Rank: %d", Shavit_GetRankForTime(iStyle, gF_PlayerRecord[client][iStyle][0], iStyle)); - for(int i = 0; i < gI_RecordAmount[iStyle][0]; i++) + for(int i = 0; i < iRecords; i++) { ReplyToCommand(client, "#%d: %f", i, gA_Leaderboard[iStyle][0].Get(i)); } @@ -677,7 +675,7 @@ int GetTrackRecordCount(int track) for(int i = 0; i < gI_Styles; i++) { - count += gI_RecordAmount[i][track]; + count += GetRecordAmount(i, track); } return count; @@ -757,9 +755,9 @@ void DeleteSubmenu(int client) IntToString(iStyle, sInfo, 8); char sDisplay[64]; - FormatEx(sDisplay, 64, "%s (%T: %d)", gS_StyleStrings[iStyle].sStyleName, "WRRecord", client, gI_RecordAmount[iStyle][gA_WRCache[client].iLastTrack]); + FormatEx(sDisplay, 64, "%s (%T: %d)", gS_StyleStrings[iStyle].sStyleName, "WRRecord", client, GetRecordAmount(iStyle, gA_WRCache[client].iLastTrack)); - menu.AddItem(sInfo, sDisplay, (gI_RecordAmount[iStyle][gA_WRCache[client].iLastTrack] > 0)? ITEMDRAW_DEFAULT:ITEMDRAW_DISABLED); + menu.AddItem(sInfo, sDisplay, (GetRecordAmount(iStyle, gA_WRCache[client].iLastTrack) > 0)? ITEMDRAW_DEFAULT:ITEMDRAW_DISABLED); } menu.ExitButton = true; @@ -831,7 +829,7 @@ public int MenuHandler_DeleteAll_First(Menu menu, MenuAction action, int param1, IntToString(iStyle, sInfo, 8); - int iRecords = gI_RecordAmount[iStyle][iTrack]; + int iRecords = GetRecordAmount(iStyle, iTrack); if(iRecords > 0) { @@ -1356,7 +1354,7 @@ Action ShowWRStyleMenu(int client, int track) strcopy(sDisplay, 64, gS_StyleStrings[iStyle].sStyleName); } - menu.AddItem(sInfo, sDisplay, (gI_RecordAmount[iStyle][track] > 0 || !StrEqual(gA_WRCache[client].sClientMap, gS_Map))? ITEMDRAW_DEFAULT:ITEMDRAW_DISABLED); + menu.AddItem(sInfo, sDisplay, (GetRecordAmount(iStyle, track) > 0 || !StrEqual(gA_WRCache[client].sClientMap, gS_Map))? ITEMDRAW_DEFAULT:ITEMDRAW_DISABLED); } // should NEVER happen @@ -2045,7 +2043,7 @@ public void Shavit_OnFinish(int client, int style, float time, int jumps, int st int iRank = GetRankForTime(style, time, track); - if(iRank >= gI_RecordAmount[style][track]) + if(iRank >= GetRecordAmount(style, track)) { Call_StartForward(gH_OnWorstRecord); Call_PushCell(client); @@ -2152,7 +2150,7 @@ void UpdateLeaderboards() { char sQuery[192]; FormatEx(sQuery, 192, "SELECT style, track, time FROM %splayertimes WHERE map = '%s' ORDER BY time ASC, date ASC;", gS_MySQLPrefix, gS_Map); - gH_SQL.Query(SQL_UpdateLeaderboards_Callback, sQuery, 0); + gH_SQL.Query(SQL_UpdateLeaderboards_Callback, sQuery); } public void SQL_UpdateLeaderboards_Callback(Database db, DBResultSet results, const char[] error, any data) @@ -2168,7 +2166,6 @@ public void SQL_UpdateLeaderboards_Callback(Database db, DBResultSet results, co { for(int j = 0; j < TRACKS_SIZE; j++) { - gI_RecordAmount[i][j] = 0; gA_Leaderboard[i][j].Clear(); } } @@ -2196,21 +2193,32 @@ public void SQL_UpdateLeaderboards_Callback(Database db, DBResultSet results, co for(int j = 0; j < TRACKS_SIZE; j++) { SortADTArray(gA_Leaderboard[i][j], Sort_Ascending, Sort_Float); - gI_RecordAmount[i][j] = gA_Leaderboard[i][j].Length; } } } +int GetRecordAmount(int style, int track) +{ + if(gA_Leaderboard[style][track] == null) + { + return 0; + } + + return gA_Leaderboard[style][track].Length; +} + int GetRankForTime(int style, float time, int track) { - if(time <= gF_WRTime[style][track] || gI_RecordAmount[style][track] <= 0) + int iRecords = GetRecordAmount(style, track); + + if(time <= gF_WRTime[style][track] || iRecords <= 0) { return 1; } if(gA_Leaderboard[style][track] != null && gA_Leaderboard[style][track].Length > 0) { - for(int i = 0; i < gI_RecordAmount[style][track]; i++) + for(int i = 0; i < iRecords; i++) { if(time <= gA_Leaderboard[style][track].Get(i)) { @@ -2219,7 +2227,7 @@ int GetRankForTime(int style, float time, int track) } } - return (gI_RecordAmount[style][track] + 1); + return (iRecords + 1); } void GuessBestMapName(const char[] input, char[] output, int size) From 3538579ca3588c9d94b93adf593b1209778e12ca Mon Sep 17 00:00:00 2001 From: shavit Date: Fri, 24 May 2019 22:01:45 +0300 Subject: [PATCH 23/34] Added GitHub Sponsor support. (sellout smh) --- .github/FUNDING.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..12af3c0f5 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +github: [shavitush] +custom: https://paypal.me/shavitush From 0b4e82fae4fafdbdb3fb958270a4b48209b0ee21 Mon Sep 17 00:00:00 2001 From: shavit Date: Tue, 28 May 2019 18:02:34 +0300 Subject: [PATCH 24/34] Fixed "weapon %d is not owned by client %d" (#807). --- addons/sourcemod/scripting/shavit-misc.sp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/sourcemod/scripting/shavit-misc.sp b/addons/sourcemod/scripting/shavit-misc.sp index e9fdbfad6..f6116fb9a 100644 --- a/addons/sourcemod/scripting/shavit-misc.sp +++ b/addons/sourcemod/scripting/shavit-misc.sp @@ -3310,11 +3310,11 @@ public Action Command_Drop(int client, const char[] command, int argc) return Plugin_Continue; } - int weapon = GetEntPropEnt(client, Prop_Data, "m_hActiveWeapon"); + int iWeapon = GetEntPropEnt(client, Prop_Data, "m_hActiveWeapon"); - if(weapon != -1 && IsValidEntity(weapon)) + if(iWeapon != -1 && IsValidEntity(iWeapon) && GetEntPropEnt(client, Prop_Data, "m_hOwnerEntity") == client) { - CS_DropWeapon(client, weapon, true); + CS_DropWeapon(client, iWeapon, true); } return Plugin_Handled; From 8cea92406301cf586c23a1a589e48e4c44a9b07e Mon Sep 17 00:00:00 2001 From: shavit Date: Tue, 28 May 2019 18:12:20 +0300 Subject: [PATCH 25/34] Got rid of a ResumeTimer that I don't remember why I added (#806). --- addons/sourcemod/scripting/shavit-misc.sp | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/sourcemod/scripting/shavit-misc.sp b/addons/sourcemod/scripting/shavit-misc.sp index f6116fb9a..040d3af0e 100644 --- a/addons/sourcemod/scripting/shavit-misc.sp +++ b/addons/sourcemod/scripting/shavit-misc.sp @@ -3327,7 +3327,6 @@ void LoadState(int client) Shavit_LoadSnapshot(client, gA_SaveStates[client]); Shavit_SetPracticeMode(client, gB_SaveStatesSegmented[client], false); - Shavit_ResumeTimer(client); if(gB_Replay && gA_SaveFrames[client] != null) { From 70dd8f7c9cbdf067fa83586059fa95823fc06270 Mon Sep 17 00:00:00 2001 From: shavit Date: Tue, 28 May 2019 18:32:24 +0300 Subject: [PATCH 26/34] Added tracking for map completions (#804). --- addons/sourcemod/scripting/include/shavit.inc | 1 + addons/sourcemod/scripting/shavit-core.sp | 8 +++ addons/sourcemod/scripting/shavit-wr.sp | 72 ++++++++++++------- .../translations/shavit-wr.phrases.txt | 4 ++ 4 files changed, 61 insertions(+), 24 deletions(-) diff --git a/addons/sourcemod/scripting/include/shavit.inc b/addons/sourcemod/scripting/include/shavit.inc index 43c7eba80..9a89bb1f1 100644 --- a/addons/sourcemod/scripting/include/shavit.inc +++ b/addons/sourcemod/scripting/include/shavit.inc @@ -87,6 +87,7 @@ enum Migration_ConvertSteamIDsChat, Migration_PlayertimesDateToInt, Migration_AddZonesFlagsAndData, + Migration_AddPlayertimesCompletions, MIGRATIONS_END }; diff --git a/addons/sourcemod/scripting/shavit-core.sp b/addons/sourcemod/scripting/shavit-core.sp index 94cd3c837..c3b9f35da 100644 --- a/addons/sourcemod/scripting/shavit-core.sp +++ b/addons/sourcemod/scripting/shavit-core.sp @@ -2280,6 +2280,7 @@ void ApplyMigration(int migration) case Migration_ConvertSteamIDsPlayertimes, Migration_ConvertSteamIDsChat: return; // this is confusing, but the above case handles all of them case Migration_PlayertimesDateToInt: ApplyMigration_PlayertimesDateToInt(); case Migration_AddZonesFlagsAndData: ApplyMigration_AddZonesFlagsAndData(); + case Migration_AddPlayertimesCompletions: ApplyMigration_AddPlayertimesCompletions(); } } @@ -2311,6 +2312,13 @@ void ApplyMigration_AddZonesFlagsAndData() gH_SQL.Query(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_AddZonesFlagsAndData, DBPrio_High); } +void ApplyMigration_AddPlayertimesCompletions() +{ + char sQuery[192]; + FormatEx(sQuery, 192, "ALTER TABLE `%splayertimes` ADD COLUMN `completions` SMALLINT DEFAULT 1 AFTER `perfs`;", gS_MySQLPrefix); + gH_SQL.Query(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_AddPlayertimesCompletions, DBPrio_High); +} + public void SQL_TableMigrationSingleQuery_Callback(Database db, DBResultSet results, const char[] error, any data) { InsertMigration(data); diff --git a/addons/sourcemod/scripting/shavit-wr.sp b/addons/sourcemod/scripting/shavit-wr.sp index 83c36eb48..fed3ac0ef 100644 --- a/addons/sourcemod/scripting/shavit-wr.sp +++ b/addons/sourcemod/scripting/shavit-wr.sp @@ -1690,7 +1690,9 @@ public int RRMenu_Handler(Menu menu, MenuAction action, int param1, int param2) void OpenSubMenu(int client, int id) { char sQuery[512]; - FormatEx(sQuery, 512, "SELECT u.name, p.time, p.jumps, p.style, u.auth, p.date, p.map, p.strafes, p.sync, p.perfs, p.points, p.track FROM %splayertimes p JOIN %susers u ON p.auth = u.auth WHERE p.id = %d LIMIT 1;", gS_MySQLPrefix, gS_MySQLPrefix, id); + FormatEx(sQuery, 512, + "SELECT u.name, p.time, p.jumps, p.style, u.auth, p.date, p.map, p.strafes, p.sync, p.perfs, p.points, p.track, p.completions FROM %splayertimes p JOIN %susers u ON p.auth = u.auth WHERE p.id = %d LIMIT 1;", + gS_MySQLPrefix, gS_MySQLPrefix, id); DataPack datapack = new DataPack(); datapack.WriteCell(GetClientSerial(client)); @@ -1728,40 +1730,38 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] if(results.FetchRow()) { - // 0 - name results.FetchString(0, sName, MAX_NAME_LENGTH); - // 1 - time - float time = results.FetchFloat(1); + float fTime = results.FetchFloat(1); char sTime[16]; - FormatSeconds(time, sTime, 16); + FormatSeconds(fTime, sTime, 16); char sDisplay[128]; FormatEx(sDisplay, 128, "%T: %s", "WRTime", client, sTime); hMenu.AddItem("-1", sDisplay); - // 2 - jumps - int style = results.FetchInt(3); - int jumps = results.FetchInt(2); - float perfs = results.FetchFloat(9); + int iStyle = results.FetchInt(3); + int iJumps = results.FetchInt(2); + float fPerfs = results.FetchFloat(9); - if(gA_StyleSettings[style].bAutobhop) + if(gA_StyleSettings[iStyle].bAutobhop) { - FormatEx(sDisplay, 128, "%T: %d", "WRJumps", client, jumps); + FormatEx(sDisplay, 128, "%T: %d", "WRJumps", client, iJumps); } else { - FormatEx(sDisplay, 128, "%T: %d (%.2f%%)", "WRJumps", client, jumps, perfs); + FormatEx(sDisplay, 128, "%T: %d (%.2f%%)", "WRJumps", client, iJumps, fPerfs); } hMenu.AddItem("-1", sDisplay); - // 3 - style - FormatEx(sDisplay, 128, "%T: %s", "WRStyle", client, gS_StyleStrings[style].sStyleName); + FormatEx(sDisplay, 128, "%T: %d", "WRCompletions", client, results.FetchInt(12)); + hMenu.AddItem("-1", sDisplay); + + FormatEx(sDisplay, 128, "%T: %s", "WRStyle", client, gS_StyleStrings[iStyle].sStyleName); hMenu.AddItem("-1", sDisplay); - // 6 - map results.FetchString(6, sMap, 192); float fPoints = results.FetchFloat(10); @@ -1772,10 +1772,8 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] hMenu.AddItem("-1", sDisplay); } - // 4 - steamid3 iSteamID = results.FetchInt(4); - // 5 - date char sDate[32]; results.FetchString(5, sDate, 32); @@ -1790,7 +1788,7 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] int strafes = results.FetchInt(7); float sync = results.FetchFloat(8); - if(jumps > 0 || strafes > 0) + if(iJumps > 0 || strafes > 0) { FormatEx(sDisplay, 128, (sync != -1.0)? "%T: %d (%.02f%%)":"%T: %d", "WRStrafes", client, strafes, sync); hMenu.AddItem("-1", sDisplay); @@ -1952,14 +1950,14 @@ void SQL_DBConnect() if(gB_MySQL) { FormatEx(sQuery, 1024, - "CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INT NOT NULL AUTO_INCREMENT, `auth` INT, `map` VARCHAR(128), `time` FLOAT, `jumps` INT, `style` TINYINT, `date` INT, `strafes` INT, `sync` FLOAT, `points` FLOAT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0, `perfs` FLOAT DEFAULT 0, PRIMARY KEY (`id`), INDEX `map` (`map`, `style`, `track`, `time`), INDEX `auth` (`auth`, `date`, `points`), INDEX `time` (`time`), CONSTRAINT `%spt_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE) ENGINE=INNODB;", + "CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INT NOT NULL AUTO_INCREMENT, `auth` INT, `map` VARCHAR(128), `time` FLOAT, `jumps` INT, `style` TINYINT, `date` INT, `strafes` INT, `sync` FLOAT, `points` FLOAT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0, `perfs` FLOAT DEFAULT 0, `completions` SMALLINT DEFAULT 1, PRIMARY KEY (`id`), INDEX `map` (`map`, `style`, `track`, `time`), INDEX `auth` (`auth`, `date`, `points`), INDEX `time` (`time`), CONSTRAINT `%spt_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE) ENGINE=INNODB;", gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix); } else { FormatEx(sQuery, 1024, - "CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INTEGER PRIMARY KEY, `auth` INT, `map` VARCHAR(128), `time` FLOAT, `jumps` INT, `style` TINYINT, `date` INT, `strafes` INT, `sync` FLOAT, `points` FLOAT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0, `perfs` FLOAT DEFAULT 0, CONSTRAINT `%spt_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE);", + "CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INTEGER PRIMARY KEY, `auth` INT, `map` VARCHAR(128), `time` FLOAT, `jumps` INT, `style` TINYINT, `date` INT, `strafes` INT, `sync` FLOAT, `points` FLOAT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0, `perfs` FLOAT DEFAULT 0, `completions` SMALLINT DEFAULT 1, CONSTRAINT `%spt_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE);", gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix); } @@ -2001,11 +1999,13 @@ public void Shavit_OnFinish(int client, int style, float time, int jumps, int st // 0 - no query // 1 - insert // 2 - update + bool bIncrementCompletions = true; int iOverwrite = 0; if(gA_StyleSettings[style].bUnranked || Shavit_IsPracticeMode(client)) { iOverwrite = 0; // ugly way of not writing to database + bIncrementCompletions = false; } else if(gF_PlayerRecord[client][style][track] == 0.0) @@ -2071,10 +2071,10 @@ public void Shavit_OnFinish(int client, int style, float time, int jumps, int st char sSync[32]; // 32 because colors FormatEx(sSync, 32, (sync != -1.0)? " @ %s%.02f%%":"", gS_ChatStrings.sVariable, sync); + int iSteamID = GetSteamAccountID(client); + if(iOverwrite > 0) { - int iSteamID = GetSteamAccountID(client); - char sQuery[512]; if(iOverwrite == 1) // insert @@ -2086,14 +2086,18 @@ public void Shavit_OnFinish(int client, int style, float time, int jumps, int st return; } - FormatEx(sQuery, 512, "INSERT INTO %splayertimes (auth, map, time, jumps, date, style, strafes, sync, points, track, perfs) VALUES (%d, '%s', %f, %d, %d, %d, %d, %.2f, 0.0, %d, %.2f);", gS_MySQLPrefix, iSteamID, gS_Map, time, jumps, GetTime(), style, strafes, sync, track, perfs); + FormatEx(sQuery, 512, + "INSERT INTO %splayertimes (auth, map, time, jumps, date, style, strafes, sync, points, track, perfs) VALUES (%d, '%s', %f, %d, %d, %d, %d, %.2f, 0.0, %d, %.2f);", + gS_MySQLPrefix, iSteamID, gS_Map, time, jumps, GetTime(), style, strafes, sync, track, perfs); } else // update { Shavit_PrintToChatAll("%s[%s]%s %T", gS_ChatStrings.sVariable, sTrack, gS_ChatStrings.sText, "NotFirstCompletion", LANG_SERVER, gS_ChatStrings.sVariable2, client, gS_ChatStrings.sText, gS_ChatStrings.sStyle, gS_StyleStrings[style].sStyleName, gS_ChatStrings.sText, gS_ChatStrings.sVariable2, sTime, gS_ChatStrings.sText, gS_ChatStrings.sVariable, iRank, gS_ChatStrings.sText, jumps, strafes, sSync, gS_ChatStrings.sText, gS_ChatStrings.sWarning, sDifference); - FormatEx(sQuery, 512, "UPDATE %splayertimes SET time = %f, jumps = %d, date = %d, strafes = %d, sync = %.02f, points = 0.0, perfs = %.2f WHERE map = '%s' AND auth = %d AND style = %d AND track = %d;", gS_MySQLPrefix, time, jumps, GetTime(), strafes, sync, perfs, gS_Map, iSteamID, style, track); + FormatEx(sQuery, 512, + "UPDATE %splayertimes SET time = %f, jumps = %d, date = %d, strafes = %d, sync = %.02f, points = 0.0, perfs = %.2f WHERE map = '%s' AND auth = %d AND style = %d AND track = %d;", + gS_MySQLPrefix, time, jumps, GetTime(), strafes, sync, perfs, gS_Map, iSteamID, style, track); } gH_SQL.Query(SQL_OnFinish_Callback, sQuery, GetClientSerial(client), DBPrio_High); @@ -2115,6 +2119,16 @@ public void Shavit_OnFinish(int client, int style, float time, int jumps, int st gF_PlayerRecord[client][style][track] = time; } + if(bIncrementCompletions) + { + char sQuery[256]; + FormatEx(sQuery, 256, + "UPDATE %splayertimes SET completions = completions + 1 WHERE map = '%s' AND auth = %d AND style = %d AND track = %d;", + gS_MySQLPrefix, gS_Map, iSteamID, style, track); + + gH_SQL.Query(SQL_OnIncrementCompletions_Callback, sQuery, 0, DBPrio_Low); + } + else if(iOverwrite == 0 && !gA_StyleSettings[style].bUnranked) { Shavit_PrintToChat(client, "%s[%s]%s %T", gS_ChatStrings.sVariable, sTrack, gS_ChatStrings.sText, "WorseTime", client, gS_ChatStrings.sStyle, gS_StyleStrings[style].sStyleName, gS_ChatStrings.sText, gS_ChatStrings.sVariable2, sTime, gS_ChatStrings.sText, jumps, strafes, sSync, gS_ChatStrings.sText, sDifference); @@ -2126,6 +2140,16 @@ public void Shavit_OnFinish(int client, int style, float time, int jumps, int st } } +public void SQL_OnIncrementCompletions_Callback(Database db, DBResultSet results, const char[] error, any data) +{ + if(results == null) + { + LogError("Timer (WR OnIncrementCompletions) SQL query failed. Reason: %s", error); + + return; + } +} + public void SQL_OnFinish_Callback(Database db, DBResultSet results, const char[] error, any data) { if(results == null) diff --git a/addons/sourcemod/translations/shavit-wr.phrases.txt b/addons/sourcemod/translations/shavit-wr.phrases.txt index 9739f3399..81945de9a 100644 --- a/addons/sourcemod/translations/shavit-wr.phrases.txt +++ b/addons/sourcemod/translations/shavit-wr.phrases.txt @@ -181,6 +181,10 @@ { "en" "Strafes" } + "WRCompletions" + { + "en" "Completions" + } "WRStyle" { "en" "Style" From 487135f85a532490da56f36f40388a1ef5a3d03b Mon Sep 17 00:00:00 2001 From: shavit Date: Tue, 28 May 2019 18:44:28 +0300 Subject: [PATCH 27/34] Allowed using all keys in limited styles after touching ladder (#800). Key restriction is added again after touching the ground. ConVar to disable this is `shavit_core_simplerladders` --- addons/sourcemod/scripting/shavit-core.sp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/shavit-core.sp b/addons/sourcemod/scripting/shavit-core.sp index c3b9f35da..2c3be8d4a 100644 --- a/addons/sourcemod/scripting/shavit-core.sp +++ b/addons/sourcemod/scripting/shavit-core.sp @@ -55,6 +55,7 @@ enum struct playertimer_t int iPerfectJumps; int iGroundTicks; MoveType iMoveType; + bool bCanUseAllKeys; } // game type (CS:S/CS:GO/TF2) @@ -116,6 +117,7 @@ ConVar gCV_NoZAxisSpeed = null; ConVar gCV_VelocityTeleport = null; ConVar gCV_DefaultStyle = null; ConVar gCV_NoChatSound = null; +ConVar gCV_SimplerLadders = null; // cached cvars int gI_DefaultStyle = 0; @@ -326,6 +328,7 @@ public void OnPluginStart() gCV_VelocityTeleport = CreateConVar("shavit_core_velocityteleport", "0", "Teleport the client when changing its velocity? (for special styles)", 0, true, 0.0, true, 1.0); gCV_DefaultStyle = CreateConVar("shavit_core_defaultstyle", "0", "Default style ID.\nAdd the '!' prefix to disable style cookies - i.e. \"!3\" to *force* scroll to be the default style.", 0, true, 0.0); gCV_NoChatSound = CreateConVar("shavit_core_nochatsound", "0", "Disables click sound for chat messages.", 0, true, 0.0, true, 1.0); + gCV_SimplerLadders = CreateConVar("shavit_core_simplerladders", "1", "Allows using all keys on limited styles (such as sideways) after touching ladders\nTouching the ground enables the restriction again.", 0, true, 0.0, true, 1.0); gCV_DefaultStyle.AddChangeHook(OnConVarChanged); @@ -1736,6 +1739,7 @@ void StartTimer(int client, int track) gA_Timers[client].bPracticeMode = false; gA_Timers[client].iMeasuredJumps = 0; gA_Timers[client].iPerfectJumps = 0; + gA_Timers[client].bCanUseAllKeys = false; SetEntityGravity(client, view_as(gA_StyleSettings[gA_Timers[client].iStyle].fGravityMultiplier)); SetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue", view_as(gA_StyleSettings[gA_Timers[client].iStyle].fSpeedMultiplier)); @@ -2787,8 +2791,18 @@ public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3 MoveType mtMoveType = GetEntityMoveType(client); + if(mtMoveType == MOVETYPE_LADDER && gCV_SimplerLadders.BoolValue) + { + gA_Timers[client].bCanUseAllKeys = true; + } + + else if(iGroundEntity != -1) + { + gA_Timers[client].bCanUseAllKeys = false; + } + // key blocking - if(mtMoveType != MOVETYPE_NOCLIP && mtMoveType != MOVETYPE_LADDER && !Shavit_InsideZone(client, Zone_Freestyle, -1)) + if(!gA_Timers[client].bCanUseAllKeys && mtMoveType != MOVETYPE_NOCLIP && mtMoveType != MOVETYPE_LADDER && !Shavit_InsideZone(client, Zone_Freestyle, -1)) { // block E if(gA_StyleSettings[gA_Timers[client].iStyle].bBlockUse && (buttons & IN_USE) > 0) From dca53d61c60191d39fab074205b0f9b5fc25114f Mon Sep 17 00:00:00 2001 From: shavit Date: Wed, 29 May 2019 09:12:54 +0300 Subject: [PATCH 28/34] Reverted the dropall change, doesn't seem like the proper solution. (seems like a csgo issue, let me know if anyone has a fix) --- addons/sourcemod/scripting/shavit-misc.sp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/shavit-misc.sp b/addons/sourcemod/scripting/shavit-misc.sp index 040d3af0e..d6d6960ab 100644 --- a/addons/sourcemod/scripting/shavit-misc.sp +++ b/addons/sourcemod/scripting/shavit-misc.sp @@ -3312,7 +3312,7 @@ public Action Command_Drop(int client, const char[] command, int argc) int iWeapon = GetEntPropEnt(client, Prop_Data, "m_hActiveWeapon"); - if(iWeapon != -1 && IsValidEntity(iWeapon) && GetEntPropEnt(client, Prop_Data, "m_hOwnerEntity") == client) + if(iWeapon != -1 && IsValidEntity(iWeapon)) { CS_DropWeapon(client, iWeapon, true); } From 04e5db54205f7ac3f3bc3eb7f100026f3019d54d Mon Sep 17 00:00:00 2001 From: shavit Date: Thu, 30 May 2019 01:50:20 +0300 Subject: [PATCH 29/34] Fixed the fix for the fix of dropall errors (#807). --- addons/sourcemod/scripting/shavit-misc.sp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/shavit-misc.sp b/addons/sourcemod/scripting/shavit-misc.sp index d6d6960ab..d2232258e 100644 --- a/addons/sourcemod/scripting/shavit-misc.sp +++ b/addons/sourcemod/scripting/shavit-misc.sp @@ -3312,7 +3312,7 @@ public Action Command_Drop(int client, const char[] command, int argc) int iWeapon = GetEntPropEnt(client, Prop_Data, "m_hActiveWeapon"); - if(iWeapon != -1 && IsValidEntity(iWeapon)) + if(iWeapon != -1 && IsValidEntity(iWeapon) && GetEntPropEnt(iWeapon, Prop_Send, "m_hOwnerEntity") == client) { CS_DropWeapon(client, iWeapon, true); } From 9cbb0c3f08a410f67f04f99df3698cdde7ba0b3b Mon Sep 17 00:00:00 2001 From: shavit Date: Fri, 31 May 2019 16:51:41 +0300 Subject: [PATCH 30/34] Fixed rankings querying the database for tiers/recalc more than once per map. The database was being queried 3 times on the first server startup. And during additional map changes, the database was being queried twice instead of once. This caused the biggest query (users points recalculate) to be executed multiple times, and causing the database handle to be locked up. --- addons/sourcemod/scripting/shavit-rankings.sp | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/addons/sourcemod/scripting/shavit-rankings.sp b/addons/sourcemod/scripting/shavit-rankings.sp index 2c1a2888c..1f65a592d 100644 --- a/addons/sourcemod/scripting/shavit-rankings.sp +++ b/addons/sourcemod/scripting/shavit-rankings.sp @@ -60,6 +60,7 @@ Database gH_SQL = null; bool gB_Stats = false; bool gB_Late = false; +bool gB_TierQueried = false; int gI_Tier = 1; // No floating numbers for tiers, sorry. @@ -402,7 +403,8 @@ public void OnClientPostAdminCheck(int client) public void OnMapStart() { - if(gH_SQL == null) + // do NOT keep running this more than once per map, as UpdateAllPoints() is called after this eventually and locks up the database while it is running + if(gH_SQL == null || gB_TierQueried) { return; } @@ -411,8 +413,6 @@ public void OnMapStart() PrintToServer("DEBUG: 1 (OnMapStart)"); #endif - UpdateRankedPlayers(); - GetCurrentMap(gS_Map, 160); GetMapDisplayName(gS_Map, gS_Map, 160); @@ -420,17 +420,11 @@ public void OnMapStart() // I won't repeat the same mistake blacky has done with tier 3 being default.. gI_Tier = 1; - char sDriver[8]; - gH_SQL.Driver.GetIdentifier(sDriver, 8); - - if(!StrEqual(sDriver, "mysql", false)) - { - SetFailState("Rankings will only support MySQL for the moment. Sorry."); - } - char sQuery[256]; FormatEx(sQuery, 256, "SELECT tier FROM %smaptiers WHERE map = '%s';", gS_MySQLPrefix, gS_Map); - gH_SQL.Query(SQL_GetMapTier_Callback, sQuery, 0, DBPrio_Low); + gH_SQL.Query(SQL_GetMapTier_Callback, sQuery); + + gB_TierQueried = true; } public void SQL_GetMapTier_Callback(Database db, DBResultSet results, const char[] error, any data) @@ -533,6 +527,7 @@ void GuessBestMapName(const char[] input, char[] output, int size) public void OnMapEnd() { RecalculateAll(gS_Map); + gB_TierQueried = false; } public Action Command_Tier(int client, int args) @@ -816,6 +811,8 @@ public void SQL_UpdateAllPoints_Callback(Database db, DBResultSet results, const return; } + + UpdateRankedPlayers(); } void UpdatePlayerRank(int client, bool first) From 0650d20effb6853e0daec58b0cf5bf83dc44e27d Mon Sep 17 00:00:00 2001 From: shavit Date: Fri, 31 May 2019 17:03:27 +0300 Subject: [PATCH 31/34] Removed ancient SetPrefix code and put it in a stock function instead. --- addons/sourcemod/scripting/include/shavit.inc | 24 +++++++++++++++ addons/sourcemod/scripting/shavit-chat.sp | 29 ++---------------- addons/sourcemod/scripting/shavit-core.sp | 28 ++--------------- addons/sourcemod/scripting/shavit-rankings.sp | 29 ++---------------- addons/sourcemod/scripting/shavit-replay.sp | 30 ++----------------- addons/sourcemod/scripting/shavit-stats.sp | 29 ++---------------- .../sourcemod/scripting/shavit-timelimit.sp | 28 +---------------- addons/sourcemod/scripting/shavit-wr.sp | 29 ++---------------- addons/sourcemod/scripting/shavit-zones.sp | 29 ++---------------- 9 files changed, 39 insertions(+), 216 deletions(-) diff --git a/addons/sourcemod/scripting/include/shavit.inc b/addons/sourcemod/scripting/include/shavit.inc index 9a89bb1f1..f8e6860fa 100644 --- a/addons/sourcemod/scripting/include/shavit.inc +++ b/addons/sourcemod/scripting/include/shavit.inc @@ -267,6 +267,30 @@ char gS_CSGOColors[][] = }; #endif +// retrieves the table prefix defined in configs/shavit-prefix.txt +stock void GetTimerSQLPrefix(char[] buffer, int maxlen) +{ + char sFile[PLATFORM_MAX_PATH]; + BuildPath(Path_SM, sFile, PLATFORM_MAX_PATH, "configs/shavit-prefix.txt"); + + File fFile = OpenFile(sFile, "r"); + + if(fFile == null) + { + SetFailState("Cannot open \"configs/shavit-prefix.txt\". Make sure this file exists and that the server has read permissions to it."); + } + + char sLine[PLATFORM_MAX_PATH * 2]; + + if(fFile.ReadLine(sLine, PLATFORM_MAX_PATH * 2)) + { + TrimString(sLine); + strcopy(buffer, maxlen, sLine); + } + + delete fFile; +} + stock bool IsValidClient(int client, bool bAlive = false) { return (client >= 1 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client) && !IsClientSourceTV(client) && (!bAlive || IsPlayerAlive(client))); diff --git a/addons/sourcemod/scripting/shavit-chat.sp b/addons/sourcemod/scripting/shavit-chat.sp index 694628d1f..58b9b2a40 100644 --- a/addons/sourcemod/scripting/shavit-chat.sp +++ b/addons/sourcemod/scripting/shavit-chat.sp @@ -163,8 +163,6 @@ public void OnPluginStart() } } } - - SQL_SetPrefix(); } public void OnMapStart() @@ -546,31 +544,6 @@ Action SetSQLInfo() return Plugin_Continue; } -void SQL_SetPrefix() -{ - char sFile[PLATFORM_MAX_PATH]; - BuildPath(Path_SM, sFile, PLATFORM_MAX_PATH, "configs/shavit-prefix.txt"); - - File fFile = OpenFile(sFile, "r"); - - if(fFile == null) - { - SetFailState("Cannot open \"configs/shavit-prefix.txt\". Make sure this file exists and that the server has read permissions to it."); - } - - char sLine[PLATFORM_MAX_PATH*2]; - - while(fFile.ReadLine(sLine, PLATFORM_MAX_PATH*2)) - { - TrimString(sLine); - strcopy(gS_MySQLPrefix, 32, sLine); - - break; - } - - delete fFile; -} - public void OnLibraryAdded(const char[] name) { if(StrEqual(name, "rtler")) @@ -1333,6 +1306,8 @@ int RealRandomInt(int min, int max) void SQL_DBConnect() { + GetTimerSQLPrefix(gS_MySQLPrefix, 32); + if(gH_SQL != null) { char sDriver[8]; diff --git a/addons/sourcemod/scripting/shavit-core.sp b/addons/sourcemod/scripting/shavit-core.sp index 2c3be8d4a..95ce42380 100644 --- a/addons/sourcemod/scripting/shavit-core.sp +++ b/addons/sourcemod/scripting/shavit-core.sp @@ -254,7 +254,6 @@ public void OnPluginStart() } // database connections - SQL_SetPrefix(); SQL_DBConnect(); // hooks @@ -2159,33 +2158,10 @@ bool LoadMessages() return true; } -void SQL_SetPrefix() -{ - char sFile[PLATFORM_MAX_PATH]; - BuildPath(Path_SM, sFile, PLATFORM_MAX_PATH, "configs/shavit-prefix.txt"); - - File fFile = OpenFile(sFile, "r"); - - if(fFile == null) - { - SetFailState("Cannot open \"configs/shavit-prefix.txt\". Make sure this file exists and that the server has read permissions to it."); - } - - char sLine[PLATFORM_MAX_PATH*2]; - - while(fFile.ReadLine(sLine, PLATFORM_MAX_PATH*2)) - { - TrimString(sLine); - strcopy(gS_MySQLPrefix, 32, sLine); - - break; - } - - delete fFile; -} - void SQL_DBConnect() { + GetTimerSQLPrefix(gS_MySQLPrefix, 32); + if(gH_SQL != null) { delete gH_SQL; diff --git a/addons/sourcemod/scripting/shavit-rankings.sp b/addons/sourcemod/scripting/shavit-rankings.sp index 1f65a592d..244374b50 100644 --- a/addons/sourcemod/scripting/shavit-rankings.sp +++ b/addons/sourcemod/scripting/shavit-rankings.sp @@ -163,8 +163,6 @@ public void OnPluginStart() // tier cache gA_ValidMaps = new ArrayList(128); gA_MapTiers = new StringMap(); - - SQL_SetPrefix(); if(gB_Late) { @@ -242,33 +240,10 @@ Action SetSQLInfo() return Plugin_Continue; } -void SQL_SetPrefix() -{ - char sFile[PLATFORM_MAX_PATH]; - BuildPath(Path_SM, sFile, PLATFORM_MAX_PATH, "configs/shavit-prefix.txt"); - - File fFile = OpenFile(sFile, "r"); - - if(fFile == null) - { - SetFailState("Cannot open \"configs/shavit-prefix.txt\". Make sure this file exists and that the server has read permissions to it."); - } - - char sLine[PLATFORM_MAX_PATH*2]; - - while(fFile.ReadLine(sLine, PLATFORM_MAX_PATH*2)) - { - TrimString(sLine); - strcopy(gS_MySQLPrefix, 32, sLine); - - break; - } - - delete fFile; -} - void SQL_DBConnect() { + GetTimerSQLPrefix(gS_MySQLPrefix, 32); + if(gH_SQL != null) { char sDriver[8]; diff --git a/addons/sourcemod/scripting/shavit-replay.sp b/addons/sourcemod/scripting/shavit-replay.sp index 61c241ba5..c3e83d791 100644 --- a/addons/sourcemod/scripting/shavit-replay.sp +++ b/addons/sourcemod/scripting/shavit-replay.sp @@ -297,9 +297,6 @@ public void OnPluginStart() // commands RegAdminCmd("sm_deletereplay", Command_DeleteReplay, ADMFLAG_RCON, "Open replay deletion menu."); RegConsoleCmd("sm_replay", Command_Replay, "Opens the central bot menu. For admins: 'sm_replay stop' to stop the playback."); - - // database - SQL_SetPrefix(); } public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) @@ -711,37 +708,14 @@ Action SetSQLInfo() else { + GetTimerSQLPrefix(gS_MySQLPrefix, 32); + return Plugin_Stop; } return Plugin_Continue; } -void SQL_SetPrefix() -{ - char sFile[PLATFORM_MAX_PATH]; - BuildPath(Path_SM, sFile, PLATFORM_MAX_PATH, "configs/shavit-prefix.txt"); - - File fFile = OpenFile(sFile, "r"); - - if(fFile == null) - { - SetFailState("Cannot open \"configs/shavit-prefix.txt\". Make sure this file exists and that the server has read permissions to it."); - } - - char sLine[PLATFORM_MAX_PATH*2]; - - while(fFile.ReadLine(sLine, PLATFORM_MAX_PATH*2)) - { - TrimString(sLine); - strcopy(gS_MySQLPrefix, 32, sLine); - - break; - } - - delete fFile; -} - public Action Cron(Handle Timer) { if(!gCV_Enabled.BoolValue) diff --git a/addons/sourcemod/scripting/shavit-stats.sp b/addons/sourcemod/scripting/shavit-stats.sp index 0fad6b762..07531174b 100644 --- a/addons/sourcemod/scripting/shavit-stats.sp +++ b/addons/sourcemod/scripting/shavit-stats.sp @@ -129,8 +129,6 @@ public void OnPluginStart() gB_Rankings = LibraryExists("shavit-rankings"); - SQL_SetPrefix(); - if(gB_Late) { for(int i = 1; i <= MaxClients; i++) @@ -229,37 +227,14 @@ Action SetSQLInfo() else { + GetTimerSQLPrefix(gS_MySQLPrefix, 32); + return Plugin_Stop; } return Plugin_Continue; } -void SQL_SetPrefix() -{ - char sFile[PLATFORM_MAX_PATH]; - BuildPath(Path_SM, sFile, PLATFORM_MAX_PATH, "configs/shavit-prefix.txt"); - - File fFile = OpenFile(sFile, "r"); - - if(fFile == null) - { - SetFailState("Cannot open \"configs/shavit-prefix.txt\". Make sure this file exists and that the server has read permissions to it."); - } - - char sLine[PLATFORM_MAX_PATH*2]; - - while(fFile.ReadLine(sLine, PLATFORM_MAX_PATH*2)) - { - TrimString(sLine); - strcopy(gS_MySQLPrefix, 32, sLine); - - break; - } - - delete fFile; -} - public void Player_Event(Event event, const char[] name, bool dontBroadcast) { if(gCV_MVPRankOnes.IntValue == 0) diff --git a/addons/sourcemod/scripting/shavit-timelimit.sp b/addons/sourcemod/scripting/shavit-timelimit.sp index a153efe93..4f392d4e8 100644 --- a/addons/sourcemod/scripting/shavit-timelimit.sp +++ b/addons/sourcemod/scripting/shavit-timelimit.sp @@ -109,8 +109,6 @@ public void OnPluginStart() gCV_ForceMapEnd.AddChangeHook(OnConVarChanged); AutoExecConfig(); - - SQL_SetPrefix(); } public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) @@ -192,6 +190,7 @@ Action SetSQLInfo() else { + GetTimerSQLPrefix(gS_MySQLPrefix, 32); OnMapStart(); return Plugin_Stop; @@ -200,31 +199,6 @@ Action SetSQLInfo() return Plugin_Continue; } -void SQL_SetPrefix() -{ - char sFile[PLATFORM_MAX_PATH]; - BuildPath(Path_SM, sFile, PLATFORM_MAX_PATH, "configs/shavit-prefix.txt"); - - File fFile = OpenFile(sFile, "r"); - - if(fFile == null) - { - SetFailState("Cannot open \"configs/shavit-prefix.txt\". Make sure this file exists and that the server has read permissions to it."); - } - - char sLine[PLATFORM_MAX_PATH*2]; - - while(fFile.ReadLine(sLine, PLATFORM_MAX_PATH*2)) - { - TrimString(sLine); - strcopy(gS_MySQLPrefix, 32, sLine); - - break; - } - - delete fFile; -} - void StartCalculating() { if(gH_SQL != null) diff --git a/addons/sourcemod/scripting/shavit-wr.sp b/addons/sourcemod/scripting/shavit-wr.sp index fed3ac0ef..98d957492 100644 --- a/addons/sourcemod/scripting/shavit-wr.sp +++ b/addons/sourcemod/scripting/shavit-wr.sp @@ -177,8 +177,6 @@ public void OnPluginStart() // cache gA_ValidMaps = new ArrayList(192); - - SQL_SetPrefix(); } public void OnAdminMenuCreated(Handle topmenu) @@ -1914,33 +1912,10 @@ Action SetSQLInfo() return Plugin_Continue; } -void SQL_SetPrefix() -{ - char sFile[PLATFORM_MAX_PATH]; - BuildPath(Path_SM, sFile, PLATFORM_MAX_PATH, "configs/shavit-prefix.txt"); - - File fFile = OpenFile(sFile, "r"); - - if(fFile == null) - { - SetFailState("Cannot open \"configs/shavit-prefix.txt\". Make sure this file exists and that the server has read permissions to it."); - } - - char sLine[PLATFORM_MAX_PATH*2]; - - while(fFile.ReadLine(sLine, PLATFORM_MAX_PATH*2)) - { - TrimString(sLine); - strcopy(gS_MySQLPrefix, 32, sLine); - - break; - } - - delete fFile; -} - void SQL_DBConnect() { + GetTimerSQLPrefix(gS_MySQLPrefix, 32); + char sDriver[8]; gH_SQL.Driver.GetIdentifier(sDriver, 8); gB_MySQL = StrEqual(sDriver, "mysql", false); diff --git a/addons/sourcemod/scripting/shavit-zones.sp b/addons/sourcemod/scripting/shavit-zones.sp index 79daa6ea6..80bd6ba2b 100644 --- a/addons/sourcemod/scripting/shavit-zones.sp +++ b/addons/sourcemod/scripting/shavit-zones.sp @@ -287,8 +287,6 @@ public void OnPluginStart() OnClientPutInServer(i); } } - - SQL_SetPrefix(); } public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) @@ -2532,33 +2530,10 @@ Action SetSQLInfo() return Plugin_Continue; } -void SQL_SetPrefix() -{ - char sFile[PLATFORM_MAX_PATH]; - BuildPath(Path_SM, sFile, PLATFORM_MAX_PATH, "configs/shavit-prefix.txt"); - - File fFile = OpenFile(sFile, "r"); - - if(fFile == null) - { - SetFailState("Cannot open \"configs/shavit-prefix.txt\". Make sure this file exists and that the server has read permissions to it."); - } - - char sLine[PLATFORM_MAX_PATH*2]; - - while(fFile.ReadLine(sLine, PLATFORM_MAX_PATH*2)) - { - TrimString(sLine); - strcopy(gS_MySQLPrefix, 32, sLine); - - break; - } - - delete fFile; -} - void SQL_DBConnect() { + GetTimerSQLPrefix(gS_MySQLPrefix, 32); + if(gH_SQL != null) { char sDriver[8]; From fd121092c819f598445a86b0299b9ee48a8baf6b Mon Sep 17 00:00:00 2001 From: shavit Date: Fri, 31 May 2019 17:32:03 +0300 Subject: [PATCH 32/34] Refactored database handles so that there are multiple instead of a single one. --- addons/sourcemod/scripting/include/shavit.inc | 35 +++++++- addons/sourcemod/scripting/shavit-chat.sp | 85 +++++-------------- addons/sourcemod/scripting/shavit-core.sp | 39 ++------- addons/sourcemod/scripting/shavit-rankings.sp | 72 ++++------------ addons/sourcemod/scripting/shavit-replay.sp | 54 +++--------- addons/sourcemod/scripting/shavit-stats.sp | 79 +++-------------- .../sourcemod/scripting/shavit-timelimit.sp | 65 +++----------- addons/sourcemod/scripting/shavit-wr.sp | 56 ++---------- addons/sourcemod/scripting/shavit-zones.sp | 61 +++---------- 9 files changed, 129 insertions(+), 417 deletions(-) diff --git a/addons/sourcemod/scripting/include/shavit.inc b/addons/sourcemod/scripting/include/shavit.inc index f8e6860fa..c5c8cfd73 100644 --- a/addons/sourcemod/scripting/include/shavit.inc +++ b/addons/sourcemod/scripting/include/shavit.inc @@ -267,6 +267,38 @@ char gS_CSGOColors[][] = }; #endif +// connects synchronously to the bhoptimer database +// calls errors if needed +stock Database GetTimerDatabaseHandle() +{ + Database db = null; + char sError[255]; + + if(SQL_CheckConfig("shavit")) + { + if((db = SQL_Connect("shavit", true, sError, 255)) == null) + { + SetFailState("Timer startup failed. Reason: %s", sError); + } + } + + else + { + db = SQLite_UseDatabase("shavit", sError, 255); + } + + return db +} + +// figures out if the database is a mysql database +stock bool IsMySQLDatabase(Database db) +{ + char sDriver[8]; + db.Driver.GetIdentifier(sDriver, 8); + + return StrEqual(sDriver, "mysql", false); +} + // retrieves the table prefix defined in configs/shavit-prefix.txt stock void GetTimerSQLPrefix(char[] buffer, int maxlen) { @@ -564,7 +596,8 @@ forward void Shavit_OnStyleChanged(int client, int oldstyle, int newstyle, int t forward void Shavit_OnStyleConfigLoaded(int styles); /** - * Called when there's a successful connection to the database. + * Called when there's a successful connection to the database and it is ready to be used. + * Called through shavit-core after migrations have been applied, and after the attempt to create the default `users` table. * * @noreturn */ diff --git a/addons/sourcemod/scripting/shavit-chat.sp b/addons/sourcemod/scripting/shavit-chat.sp index 58b9b2a40..c48248381 100644 --- a/addons/sourcemod/scripting/shavit-chat.sp +++ b/addons/sourcemod/scripting/shavit-chat.sp @@ -112,16 +112,6 @@ public Plugin myinfo = url = "https://github.com/shavitush/bhoptimer" } -public void OnAllPluginsLoaded() -{ - gB_RTLer = LibraryExists("rtler"); - - if(gH_SQL == null) - { - Shavit_OnDatabaseLoaded(); - } -} - public void OnPluginStart() { gEV_Type = GetEngineVersion(); @@ -163,6 +153,10 @@ public void OnPluginStart() } } } + + gB_RTLer = LibraryExists("rtler"); + + SQL_DBConnect(); } public void OnMapStart() @@ -514,36 +508,6 @@ void Frame_SendText(DataPack pack) EndMessage(); } -public void Shavit_OnDatabaseLoaded() -{ - gH_SQL = Shavit_GetDatabase(); - SetSQLInfo(); -} - -public Action CheckForSQLInfo(Handle Timer) -{ - return SetSQLInfo(); -} - -Action SetSQLInfo() -{ - if(gH_SQL == null) - { - gH_SQL = Shavit_GetDatabase(); - - CreateTimer(0.5, CheckForSQLInfo); - } - - else - { - SQL_DBConnect(); - - return Plugin_Stop; - } - - return Plugin_Continue; -} - public void OnLibraryAdded(const char[] name) { if(StrEqual(name, "rtler")) @@ -606,10 +570,7 @@ public void OnClientDisconnect(int client) public void OnClientPostAdminCheck(int client) { - if(gH_SQL != null) - { - LoadFromDatabase(client); - } + LoadFromDatabase(client); } public Action Command_CCHelp(int client, int args) @@ -1307,31 +1268,25 @@ int RealRandomInt(int min, int max) void SQL_DBConnect() { GetTimerSQLPrefix(gS_MySQLPrefix, 32); - - if(gH_SQL != null) - { - char sDriver[8]; - gH_SQL.Driver.GetIdentifier(sDriver, 8); - bool bMySQL = StrEqual(sDriver, "mysql", false); + gH_SQL = GetTimerDatabaseHandle(); - char sQuery[512]; + char sQuery[512]; - if(bMySQL) - { - FormatEx(sQuery, 512, - "CREATE TABLE IF NOT EXISTS `%schat` (`auth` INT NOT NULL, `name` INT NOT NULL DEFAULT 0, `ccname` VARCHAR(128) COLLATE 'utf8mb4_unicode_ci', `message` INT NOT NULL DEFAULT 0, `ccmessage` VARCHAR(16) COLLATE 'utf8mb4_unicode_ci', PRIMARY KEY (`auth`), CONSTRAINT `%sch_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE) ENGINE=INNODB;", - gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix); - } + if(IsMySQLDatabase(gH_SQL)) + { + FormatEx(sQuery, 512, + "CREATE TABLE IF NOT EXISTS `%schat` (`auth` INT NOT NULL, `name` INT NOT NULL DEFAULT 0, `ccname` VARCHAR(128) COLLATE 'utf8mb4_unicode_ci', `message` INT NOT NULL DEFAULT 0, `ccmessage` VARCHAR(16) COLLATE 'utf8mb4_unicode_ci', PRIMARY KEY (`auth`), CONSTRAINT `%sch_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE) ENGINE=INNODB;", + gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix); + } - else - { - FormatEx(sQuery, 512, - "CREATE TABLE IF NOT EXISTS `%schat` (`auth` INT NOT NULL, `name` INT NOT NULL DEFAULT 0, `ccname` VARCHAR(128), `message` INT NOT NULL DEFAULT 0, `ccmessage` VARCHAR(16), PRIMARY KEY (`auth`), CONSTRAINT `%sch_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE);", - gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix); - } - - gH_SQL.Query(SQL_CreateTable_Callback, sQuery); + else + { + FormatEx(sQuery, 512, + "CREATE TABLE IF NOT EXISTS `%schat` (`auth` INT NOT NULL, `name` INT NOT NULL DEFAULT 0, `ccname` VARCHAR(128), `message` INT NOT NULL DEFAULT 0, `ccmessage` VARCHAR(16), PRIMARY KEY (`auth`), CONSTRAINT `%sch_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE);", + gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix); } + + gH_SQL.Query(SQL_CreateTable_Callback, sQuery); } public void SQL_CreateTable_Callback(Database db, DBResultSet results, const char[] error, any data) diff --git a/addons/sourcemod/scripting/shavit-core.sp b/addons/sourcemod/scripting/shavit-core.sp index 95ce42380..f88e74759 100644 --- a/addons/sourcemod/scripting/shavit-core.sp +++ b/addons/sourcemod/scripting/shavit-core.sp @@ -253,9 +253,6 @@ public void OnPluginStart() SetFailState("This plugin was meant to be used in CS:S, CS:GO and TF2 *only*."); } - // database connections - SQL_DBConnect(); - // hooks gB_HookedJump = HookEventEx("player_jump", Player_Jump); HookEvent("player_death", Player_Death); @@ -360,6 +357,9 @@ public void OnPluginStart() gB_Replay = LibraryExists("shavit-replay"); gB_Rankings = LibraryExists("shavit-rankings"); gB_HUD = LibraryExists("shavit-hud"); + + // database connections + SQL_DBConnect(); } public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) @@ -1870,11 +1870,6 @@ public void OnClientPutInServer(int client) CallOnStyleChanged(client, 0, gI_DefaultStyle, false); } - if(gH_SQL == null) - { - return; - } - SDKHook(client, SDKHook_PreThinkPost, PreThinkPost); int iSteamID = GetSteamAccountID(client); @@ -2161,28 +2156,8 @@ bool LoadMessages() void SQL_DBConnect() { GetTimerSQLPrefix(gS_MySQLPrefix, 32); - - if(gH_SQL != null) - { - delete gH_SQL; - } - - char sError[255]; - - if(SQL_CheckConfig("shavit")) // can't be asynced as we have modules that require this database connection instantly - { - gH_SQL = SQL_Connect("shavit", true, sError, 255); - - if(gH_SQL == null) - { - SetFailState("Timer startup failed. Reason: %s", sError); - } - } - - else - { - gH_SQL = SQLite_UseDatabase("shavit", sError, 255); - } + gH_SQL = GetTimerDatabaseHandle(); + gB_MySQL = IsMySQLDatabase(gH_SQL); // support unicode names if(!gH_SQL.SetCharset("utf8mb4")) @@ -2190,10 +2165,6 @@ void SQL_DBConnect() gH_SQL.SetCharset("utf8"); } - char sDriver[8]; - gH_SQL.Driver.GetIdentifier(sDriver, 8); - gB_MySQL = StrEqual(sDriver, "mysql", false); - // migrations will only exist for mysql. sorry sqlite users if(gB_MySQL) { diff --git a/addons/sourcemod/scripting/shavit-rankings.sp b/addons/sourcemod/scripting/shavit-rankings.sp index 244374b50..7c628083e 100644 --- a/addons/sourcemod/scripting/shavit-rankings.sp +++ b/addons/sourcemod/scripting/shavit-rankings.sp @@ -120,16 +120,6 @@ public void OnAllPluginsLoaded() { SetFailState("shavit-wr is required for the plugin to work."); } - - if(gH_SQL == null) - { - Shavit_OnDatabaseLoaded(); - } - - for(int i = 0; i < TRACKS_SIZE; i++) - { - GetTrackName(LANG_SERVER, i, gS_TrackNames[i], 32); - } } public void OnPluginStart() @@ -141,7 +131,7 @@ public void OnPluginStart() RegConsoleCmd("sm_maptier", Command_Tier, "Prints the map's tier to chat. (sm_tier alias)"); RegConsoleCmd("sm_rank", Command_Rank, "Show your or someone else's rank. Usage: sm_rank [name]"); - RegConsoleCmd("sm_top", Command_Top, "Show the top 100 players."); // The rewrite of rankings will not have the ability to show over 100 entries. Dynamic fetching can be exploited and overload the database. + RegConsoleCmd("sm_top", Command_Top, "Show the top 100 players."); RegAdminCmd("sm_settier", Command_SetTier, ADMFLAG_RCON, "Change the map's tier. Usage: sm_settier "); RegAdminCmd("sm_setmaptier", Command_SetTier, ADMFLAG_RCON, "Change the map's tier. Usage: sm_setmaptier (sm_settier alias)"); @@ -168,6 +158,13 @@ public void OnPluginStart() { Shavit_OnChatConfigLoaded(); } + + for(int i = 0; i < TRACKS_SIZE; i++) + { + GetTrackName(LANG_SERVER, i, gS_TrackNames[i], 32); + } + + SQL_DBConnect(); } public void Shavit_OnChatConfigLoaded() @@ -210,55 +207,20 @@ public void OnLibraryRemoved(const char[] name) } } -public void Shavit_OnDatabaseLoaded() -{ - gH_SQL = Shavit_GetDatabase(); - SetSQLInfo(); -} - -public Action CheckForSQLInfo(Handle Timer) -{ - return SetSQLInfo(); -} - -Action SetSQLInfo() -{ - if(gH_SQL == null) - { - gH_SQL = Shavit_GetDatabase(); - - CreateTimer(0.5, CheckForSQLInfo); - } - - else - { - SQL_DBConnect(); - - return Plugin_Stop; - } - - return Plugin_Continue; -} - void SQL_DBConnect() { GetTimerSQLPrefix(gS_MySQLPrefix, 32); - - if(gH_SQL != null) - { - char sDriver[8]; - gH_SQL.Driver.GetIdentifier(sDriver, 8); + gH_SQL = GetTimerDatabaseHandle(); - if(!StrEqual(sDriver, "mysql", false)) - { - SetFailState("MySQL is the only supported database engine for shavit-rankings."); - } + if(!IsMySQLDatabase(gH_SQL)) + { + SetFailState("MySQL is the only supported database engine for shavit-rankings."); + } - char sQuery[256]; - FormatEx(sQuery, 256, "CREATE TABLE IF NOT EXISTS `%smaptiers` (`map` VARCHAR(128), `tier` INT NOT NULL DEFAULT 1, PRIMARY KEY (`map`)) ENGINE=INNODB;", gS_MySQLPrefix); + char sQuery[256]; + FormatEx(sQuery, 256, "CREATE TABLE IF NOT EXISTS `%smaptiers` (`map` VARCHAR(128), `tier` INT NOT NULL DEFAULT 1, PRIMARY KEY (`map`)) ENGINE=INNODB;", gS_MySQLPrefix); - gH_SQL.Query(SQL_CreateTable_Callback, sQuery, 0); - } + gH_SQL.Query(SQL_CreateTable_Callback, sQuery, 0); } public void SQL_CreateTable_Callback(Database db, DBResultSet results, const char[] error, any data) @@ -379,7 +341,7 @@ public void OnClientPostAdminCheck(int client) public void OnMapStart() { // do NOT keep running this more than once per map, as UpdateAllPoints() is called after this eventually and locks up the database while it is running - if(gH_SQL == null || gB_TierQueried) + if(gB_TierQueried) { return; } diff --git a/addons/sourcemod/scripting/shavit-replay.sp b/addons/sourcemod/scripting/shavit-replay.sp index c3e83d791..6244d4d2d 100644 --- a/addons/sourcemod/scripting/shavit-replay.sp +++ b/addons/sourcemod/scripting/shavit-replay.sp @@ -210,11 +210,6 @@ public void OnAllPluginsLoaded() { SetFailState("shavit-wr is required for the plugin to work."); } - - if(gH_SQL == null) - { - Shavit_OnDatabaseLoaded(); - } } public void OnPluginStart() @@ -297,6 +292,10 @@ public void OnPluginStart() // commands RegAdminCmd("sm_deletereplay", Command_DeleteReplay, ADMFLAG_RCON, "Open replay deletion menu."); RegConsoleCmd("sm_replay", Command_Replay, "Opens the central bot menu. For admins: 'sm_replay stop' to stop the playback."); + + // database + GetTimerSQLPrefix(gS_MySQLPrefix, 32); + gH_SQL = GetTimerDatabaseHandle(); } public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) @@ -686,36 +685,6 @@ public int Native_Replay_DeleteMap(Handle handler, int numParams) } } -public void Shavit_OnDatabaseLoaded() -{ - gH_SQL = Shavit_GetDatabase(); - SetSQLInfo(); -} - -public Action CheckForSQLInfo(Handle Timer) -{ - return SetSQLInfo(); -} - -Action SetSQLInfo() -{ - if(gH_SQL == null) - { - gH_SQL = Shavit_GetDatabase(); - - CreateTimer(0.5, CheckForSQLInfo); - } - - else - { - GetTimerSQLPrefix(gS_MySQLPrefix, 32); - - return Plugin_Stop; - } - - return Plugin_Continue; -} - public Action Cron(Handle Timer) { if(!gCV_Enabled.BoolValue) @@ -1005,17 +974,14 @@ bool LoadCurrentReplayFormat(File file, int version, int style, int track) iSteamID = StringToInt(sAuthID); } - if(gH_SQL != null) - { - char sQuery[192]; - FormatEx(sQuery, 192, "SELECT name FROM %susers WHERE auth = %d;", gS_MySQLPrefix, iSteamID); + char sQuery[192]; + FormatEx(sQuery, 192, "SELECT name FROM %susers WHERE auth = %d;", gS_MySQLPrefix, iSteamID); - DataPack hPack = new DataPack(); - hPack.WriteCell(style); - hPack.WriteCell(track); + DataPack hPack = new DataPack(); + hPack.WriteCell(style); + hPack.WriteCell(track); - gH_SQL.Query(SQL_GetUserName_Callback, sQuery, hPack, DBPrio_High); - } + gH_SQL.Query(SQL_GetUserName_Callback, sQuery, hPack, DBPrio_High); int cells = CELLS_PER_FRAME; diff --git a/addons/sourcemod/scripting/shavit-stats.sp b/addons/sourcemod/scripting/shavit-stats.sp index 07531174b..c205a9e0a 100644 --- a/addons/sourcemod/scripting/shavit-stats.sp +++ b/addons/sourcemod/scripting/shavit-stats.sp @@ -39,12 +39,10 @@ bool gB_Rankings = false; // database handle Database gH_SQL = null; - -// table prefix char gS_MySQLPrefix[32]; // cache -bool gB_AllowStats[MAXPLAYERS+1]; +bool gB_CanOpenMenu[MAXPLAYERS+1]; int gI_MapType[MAXPLAYERS+1]; int gI_Style[MAXPLAYERS+1]; int gI_Track[MAXPLAYERS+1]; @@ -95,11 +93,6 @@ public void OnAllPluginsLoaded() { SetFailState("shavit-wr is required for the plugin to work."); } - - if(gH_SQL == null) - { - Shavit_OnDatabaseLoaded(); - } } public void OnPluginStart() @@ -139,6 +132,10 @@ public void OnPluginStart() } } } + + // database + GetTimerSQLPrefix(gS_MySQLPrefix, 32); + gH_SQL = GetTimerDatabaseHandle(); } public void OnMapStart() @@ -184,7 +181,7 @@ public void OnClientPutInServer(int client) return; } - gB_AllowStats[client] = true; + gB_CanOpenMenu[client] = true; gI_WRAmount[client] = 0; UpdateWRs(client); } @@ -205,36 +202,6 @@ public void OnLibraryRemoved(const char[] name) } } -public void Shavit_OnDatabaseLoaded() -{ - gH_SQL = Shavit_GetDatabase(); - SetSQLInfo(); -} - -public Action CheckForSQLInfo(Handle Timer) -{ - return SetSQLInfo(); -} - -Action SetSQLInfo() -{ - if(gH_SQL == null) - { - gH_SQL = Shavit_GetDatabase(); - - CreateTimer(0.5, CheckForSQLInfo); - } - - else - { - GetTimerSQLPrefix(gS_MySQLPrefix, 32); - - return Plugin_Stop; - } - - return Plugin_Continue; -} - public void Player_Event(Event event, const char[] name, bool dontBroadcast) { if(gCV_MVPRankOnes.IntValue == 0) @@ -252,11 +219,6 @@ public void Player_Event(Event event, const char[] name, bool dontBroadcast) void UpdateWRs(int client) { - if(gH_SQL == null) - { - return; - } - int iSteamID = 0; if((iSteamID = GetSteamAccountID(client)) != 0) @@ -455,7 +417,7 @@ public Action Command_Profile(int client, int args) Action OpenStatsMenu(int client, int steamid) { // no spam please - if(!gB_AllowStats[client]) + if(!gB_CanOpenMenu[client]) { return Plugin_Handled; } @@ -484,7 +446,7 @@ Action OpenStatsMenu(int client, int steamid) "LIMIT 1;", gS_MySQLPrefix, steamid, gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix, steamid, gS_MySQLPrefix, steamid); } - gB_AllowStats[client] = false; + gB_CanOpenMenu[client] = false; gH_SQL.Query(OpenStatsMenuCallback, sQuery, GetClientSerial(client), DBPrio_Low); return Plugin_Handled; @@ -493,7 +455,7 @@ Action OpenStatsMenu(int client, int steamid) public void OpenStatsMenuCallback(Database db, DBResultSet results, const char[] error, any data) { int client = GetClientFromSerial(data); - gB_AllowStats[client] = true; + gB_CanOpenMenu[client] = true; if(results == null) { @@ -675,27 +637,10 @@ public int MenuHandler_TypeHandler(Menu menu, MenuAction action, int param1, int return 0; } -public Action Timer_DBFailure(Handle timer, any data) -{ - int client = GetClientFromSerial(data); - - if(client == 0) - { - return Plugin_Stop; - } - - ShowMaps(client); - - return Plugin_Stop; -} - void ShowMaps(int client) { - // database not found, display with a 3 seconds delay - if(gH_SQL == null) + if(!gB_CanOpenMenu[client]) { - CreateTimer(3.0, Timer_DBFailure, GetClientSerial(client)); - return; } @@ -725,6 +670,8 @@ void ShowMaps(int client) } } + gB_CanOpenMenu[client] = false; + gH_SQL.Query(ShowMapsCallback, sQuery, GetClientSerial(client), DBPrio_High); } @@ -744,6 +691,8 @@ public void ShowMapsCallback(Database db, DBResultSet results, const char[] erro return; } + gB_CanOpenMenu[client] = true; + int rows = results.RowCount; char sTrack[32]; diff --git a/addons/sourcemod/scripting/shavit-timelimit.sp b/addons/sourcemod/scripting/shavit-timelimit.sp index 4f392d4e8..918337356 100644 --- a/addons/sourcemod/scripting/shavit-timelimit.sp +++ b/addons/sourcemod/scripting/shavit-timelimit.sp @@ -74,11 +74,6 @@ public void OnAllPluginsLoaded() { SetFailState("shavit-wr is required for the plugin to work."); } - - if(gH_SQL == null) - { - Shavit_OnDatabaseLoaded(); - } } public void OnPluginStart() @@ -109,6 +104,9 @@ public void OnPluginStart() gCV_ForceMapEnd.AddChangeHook(OnConVarChanged); AutoExecConfig(); + + GetTimerSQLPrefix(gS_MySQLPrefix, 32); + gH_SQL = GetTimerDatabaseHandle(); } public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) @@ -147,11 +145,6 @@ public void OnConfigsExecuted() public void OnMapStart() { - if(gH_SQL == null) - { - return; - } - if(gCV_DynamicTimelimits.BoolValue) { StartCalculating(); @@ -168,54 +161,20 @@ public void OnMapStart() } } -public void Shavit_OnDatabaseLoaded() -{ - gH_SQL = Shavit_GetDatabase(); - SetSQLInfo(); -} - -public Action CheckForSQLInfo(Handle Timer) -{ - return SetSQLInfo(); -} - -Action SetSQLInfo() -{ - if(gH_SQL == null) - { - gH_SQL = Shavit_GetDatabase(); - - CreateTimer(0.5, CheckForSQLInfo); - } - - else - { - GetTimerSQLPrefix(gS_MySQLPrefix, 32); - OnMapStart(); - - return Plugin_Stop; - } - - return Plugin_Continue; -} - void StartCalculating() { - if(gH_SQL != null) - { - char sMap[160]; - GetCurrentMap(sMap, 160); - GetMapDisplayName(sMap, sMap, 160); + char sMap[160]; + GetCurrentMap(sMap, 160); + GetMapDisplayName(sMap, sMap, 160); - char sQuery[512]; - FormatEx(sQuery, 512, "SELECT COUNT(*), SUM(t.time) FROM (SELECT r.time, r.style FROM %splayertimes r WHERE r.map = '%s' AND r.track = 0 %sORDER BY r.time LIMIT %d) t;", gS_MySQLPrefix, sMap, (gCV_Style.BoolValue)? "AND style = 0 ":"", gCV_PlayerAmount.IntValue); + char sQuery[512]; + FormatEx(sQuery, 512, "SELECT COUNT(*), SUM(t.time) FROM (SELECT r.time, r.style FROM %splayertimes r WHERE r.map = '%s' AND r.track = 0 %sORDER BY r.time LIMIT %d) t;", gS_MySQLPrefix, sMap, (gCV_Style.BoolValue)? "AND style = 0 ":"", gCV_PlayerAmount.IntValue); - #if defined DEBUG - PrintToServer("%s", sQuery); - #endif + #if defined DEBUG + PrintToServer("%s", sQuery); + #endif - gH_SQL.Query(SQL_GetMapTimes, sQuery, 0, DBPrio_Low); - } + gH_SQL.Query(SQL_GetMapTimes, sQuery, 0, DBPrio_Low); } public void SQL_GetMapTimes(Database db, DBResultSet results, const char[] error, any data) diff --git a/addons/sourcemod/scripting/shavit-wr.sp b/addons/sourcemod/scripting/shavit-wr.sp index 98d957492..b1ff73d19 100644 --- a/addons/sourcemod/scripting/shavit-wr.sp +++ b/addons/sourcemod/scripting/shavit-wr.sp @@ -117,14 +117,6 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max return APLRes_Success; } -public void OnAllPluginsLoaded() -{ - if(gH_SQL == null) - { - Shavit_OnDatabaseLoaded(); - } -} - public void OnPluginStart() { LoadTranslations("shavit-common.phrases"); @@ -177,6 +169,9 @@ public void OnPluginStart() // cache gA_ValidMaps = new ArrayList(192); + + // database + SQL_DBConnect(); } public void OnAdminMenuCreated(Handle topmenu) @@ -280,7 +275,7 @@ public void OnLibraryRemoved(const char[] name) public void OnMapStart() { - if(gH_SQL == null || !gB_Connected) + if(!gB_Connected) { return; } @@ -412,7 +407,7 @@ public void OnClientPutInServer(int client) } } - if(!IsClientConnected(client) || IsFakeClient(client) || gH_SQL == null) + if(!IsClientConnected(client) || IsFakeClient(client)) { return; } @@ -1882,43 +1877,11 @@ public int SubMenu_Handler(Menu menu, MenuAction action, int param1, int param2) return 0; } -public void Shavit_OnDatabaseLoaded() -{ - gH_SQL = Shavit_GetDatabase(); - SetSQLInfo(); -} - -public Action CheckForSQLInfo(Handle Timer) -{ - return SetSQLInfo(); -} - -Action SetSQLInfo() -{ - if(gH_SQL == null) - { - gH_SQL = Shavit_GetDatabase(); - - CreateTimer(0.5, CheckForSQLInfo); - } - - else - { - SQL_DBConnect(); - - return Plugin_Stop; - } - - return Plugin_Continue; -} - void SQL_DBConnect() { GetTimerSQLPrefix(gS_MySQLPrefix, 32); - - char sDriver[8]; - gH_SQL.Driver.GetIdentifier(sDriver, 8); - gB_MySQL = StrEqual(sDriver, "mysql", false); + gH_SQL = GetTimerDatabaseHandle(); + gB_MySQL = IsMySQLDatabase(gH_SQL); char sQuery[1024]; @@ -2056,11 +2019,6 @@ public void Shavit_OnFinish(int client, int style, float time, int jumps, int st { Shavit_PrintToChatAll("%s[%s]%s %T", gS_ChatStrings.sVariable, sTrack, gS_ChatStrings.sText, "FirstCompletion", LANG_SERVER, gS_ChatStrings.sVariable2, client, gS_ChatStrings.sText, gS_ChatStrings.sStyle, gS_StyleStrings[style].sStyleName, gS_ChatStrings.sText, gS_ChatStrings.sVariable2, sTime, gS_ChatStrings.sText, gS_ChatStrings.sVariable, iRank, gS_ChatStrings.sText, jumps, strafes, sSync, gS_ChatStrings.sText); - if(gH_SQL == null) - { - return; - } - FormatEx(sQuery, 512, "INSERT INTO %splayertimes (auth, map, time, jumps, date, style, strafes, sync, points, track, perfs) VALUES (%d, '%s', %f, %d, %d, %d, %d, %.2f, 0.0, %d, %.2f);", gS_MySQLPrefix, iSteamID, gS_Map, time, jumps, GetTime(), style, strafes, sync, track, perfs); diff --git a/addons/sourcemod/scripting/shavit-zones.sp b/addons/sourcemod/scripting/shavit-zones.sp index 80bd6ba2b..fcfc1abc7 100644 --- a/addons/sourcemod/scripting/shavit-zones.sp +++ b/addons/sourcemod/scripting/shavit-zones.sp @@ -191,14 +191,6 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max return APLRes_Success; } -public void OnAllPluginsLoaded() -{ - if(gH_SQL == null) - { - Shavit_OnDatabaseLoaded(); - } -} - public void OnPluginStart() { LoadTranslations("shavit-common.phrases"); @@ -287,6 +279,8 @@ public void OnPluginStart() OnClientPutInServer(i); } } + + SQL_DBConnect(); } public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) @@ -624,7 +618,7 @@ void LoadZoneSettings() public void OnMapStart() { - if(gH_SQL == null || !gB_Connected) + if(!gB_Connected) { return; } @@ -2500,53 +2494,18 @@ void CreateZonePoints(float point[8][3], float offset = 0.0) } } -public void Shavit_OnDatabaseLoaded() -{ - gH_SQL = Shavit_GetDatabase(); - SetSQLInfo(); -} - -public Action CheckForSQLInfo(Handle Timer) -{ - return SetSQLInfo(); -} - -Action SetSQLInfo() -{ - if(gH_SQL == null) - { - gH_SQL = Shavit_GetDatabase(); - - CreateTimer(0.5, CheckForSQLInfo); - } - - else - { - SQL_DBConnect(); - - return Plugin_Stop; - } - - return Plugin_Continue; -} - void SQL_DBConnect() { GetTimerSQLPrefix(gS_MySQLPrefix, 32); - - if(gH_SQL != null) - { - char sDriver[8]; - gH_SQL.Driver.GetIdentifier(sDriver, 8); - gB_MySQL = StrEqual(sDriver, "mysql", false); + gH_SQL = GetTimerDatabaseHandle(); + gB_MySQL = IsMySQLDatabase(gH_SQL); - char sQuery[1024]; - FormatEx(sQuery, 1024, - "CREATE TABLE IF NOT EXISTS `%smapzones` (`id` INT AUTO_INCREMENT, `map` VARCHAR(128), `type` INT, `corner1_x` FLOAT, `corner1_y` FLOAT, `corner1_z` FLOAT, `corner2_x` FLOAT, `corner2_y` FLOAT, `corner2_z` FLOAT, `destination_x` FLOAT NOT NULL DEFAULT 0, `destination_y` FLOAT NOT NULL DEFAULT 0, `destination_z` FLOAT NOT NULL DEFAULT 0, `track` INT NOT NULL DEFAULT 0, `flags` INT NOT NULL DEFAULT 0, `data` INT NOT NULL DEFAULT 0, PRIMARY KEY (`id`))%s;", - gS_MySQLPrefix, (gB_MySQL)? " ENGINE=INNODB":""); + char sQuery[1024]; + FormatEx(sQuery, 1024, + "CREATE TABLE IF NOT EXISTS `%smapzones` (`id` INT AUTO_INCREMENT, `map` VARCHAR(128), `type` INT, `corner1_x` FLOAT, `corner1_y` FLOAT, `corner1_z` FLOAT, `corner2_x` FLOAT, `corner2_y` FLOAT, `corner2_z` FLOAT, `destination_x` FLOAT NOT NULL DEFAULT 0, `destination_y` FLOAT NOT NULL DEFAULT 0, `destination_z` FLOAT NOT NULL DEFAULT 0, `track` INT NOT NULL DEFAULT 0, `flags` INT NOT NULL DEFAULT 0, `data` INT NOT NULL DEFAULT 0, PRIMARY KEY (`id`))%s;", + gS_MySQLPrefix, (gB_MySQL)? " ENGINE=INNODB":""); - gH_SQL.Query(SQL_CreateTable_Callback, sQuery); - } + gH_SQL.Query(SQL_CreateTable_Callback, sQuery); } public void SQL_CreateTable_Callback(Database db, DBResultSet results, const char[] error, any data) From dfcaee5c5b2549f62fe405eb1e960c7ad2247c7f Mon Sep 17 00:00:00 2001 From: shavit Date: Sat, 13 Jul 2019 07:53:18 +0300 Subject: [PATCH 33/34] Fixed HSW sync - thanks Nairda! (#809) --- addons/sourcemod/scripting/shavit-core.sp | 64 ++++++++++++++--------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/addons/sourcemod/scripting/shavit-core.sp b/addons/sourcemod/scripting/shavit-core.sp index f88e74759..426dd6609 100644 --- a/addons/sourcemod/scripting/shavit-core.sp +++ b/addons/sourcemod/scripting/shavit-core.sp @@ -2970,39 +2970,55 @@ public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3 fTempAngle += 360.0; } - float fDirectionAngle = (fTempAngle - fAngles[1]); + TestAngles(client, (fTempAngle - fAngles[1]), fAngle, vel); + } + } - if(fDirectionAngle < 0.0) - { - fDirectionAngle = -fDirectionAngle; - } + gA_Timers[client].iLastButtons = iPButtons; + gA_Timers[client].fLastAngle = angles[1]; - if(fDirectionAngle < 22.5 || fDirectionAngle > 337.5) - { - gA_Timers[client].iTotalMeasures++; + return Plugin_Continue; +} - if((fAngle > 0.0 && vel[1] <= -100.0) || (fAngle < 0.0 && vel[1] >= 100.0)) - { - gA_Timers[client].iGoodGains++; - } - } +void TestAngles(int client, float dirangle, float yawdelta, float vel[3]) +{ + if(dirangle < 0.0) + { + dirangle = -dirangle; + } - else if((fDirectionAngle > 67.5 && fDirectionAngle < 112.5) || (fDirectionAngle > 247.5 && fDirectionAngle < 292.5)) - { - gA_Timers[client].iTotalMeasures++; + // normal + if(dirangle < 22.5 || dirangle > 337.5) + { + gA_Timers[client].iTotalMeasures++; - if(vel[0] <= -100.0 || vel[0] >= 100.0) - { - gA_Timers[client].iGoodGains++; - } - } + if((yawdelta > 0.0 && vel[1] <= -100.0) || (yawdelta < 0.0 && vel[1] >= 100.0)) + { + gA_Timers[client].iGoodGains++; } } - gA_Timers[client].iLastButtons = iPButtons; - gA_Timers[client].fLastAngle = angles[1]; + // hsw (thanks nairda!) + else if((dirangle > 22.5 && dirangle < 67.5)) + { + gA_Timers[client].iTotalMeasures++; - return Plugin_Continue; + if((yawdelta != 0.0) && (vel[0] >= 100.0 || vel[1] >= 100.0) && (vel[0] >= -100.0 || vel[1] >= -100.0)) + { + gA_Timers[client].iGoodGains++; + } + } + + // sw + else if((dirangle > 67.5 && dirangle < 112.5) || (dirangle > 247.5 && dirangle < 292.5)) + { + gA_Timers[client].iTotalMeasures++; + + if(vel[0] <= -100.0 || vel[0] >= 100.0) + { + gA_Timers[client].iGoodGains++; + } + } } void StopTimer_Cheat(int client, const char[] message) From b5ce6322729c1e600b050bf479b1aca3fe45c1e2 Mon Sep 17 00:00:00 2001 From: shavit Date: Sat, 13 Jul 2019 09:34:30 +0300 Subject: [PATCH 34/34] Improvements to how hint text HUD settings is being loaded. --- addons/sourcemod/scripting/shavit-hud.sp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/addons/sourcemod/scripting/shavit-hud.sp b/addons/sourcemod/scripting/shavit-hud.sp index 6ac5f8d0b..512bef961 100644 --- a/addons/sourcemod/scripting/shavit-hud.sp +++ b/addons/sourcemod/scripting/shavit-hud.sp @@ -223,7 +223,7 @@ public void OnPluginStart() // cookies gH_HUDCookie = RegClientCookie("shavit_hud_setting", "HUD settings", CookieAccess_Protected); - gH_HUDCookieMain = RegClientCookie("shavit_hud_settingmain", "HUD settings for main ", CookieAccess_Protected); + gH_HUDCookieMain = RegClientCookie("shavit_hud_settingmain", "HUD settings for hint text.", CookieAccess_Protected); if(gB_Late) { @@ -233,7 +233,7 @@ public void OnPluginStart() { OnClientPutInServer(i); - if(AreClientCookiesCached(i)) + if(AreClientCookiesCached(i) && !IsFakeClient(i)) { OnClientCookiesCached(i); } @@ -410,20 +410,19 @@ public void OnClientCookiesCached(int client) gI_HUDSettings[client] = StringToInt(sHUDSettings); } - char sHUDSettingsMain[8]; - GetClientCookie(client, gH_HUDCookieMain, sHUDSettingsMain, 8); + GetClientCookie(client, gH_HUDCookieMain, sHUDSettings, 8); - if(strlen(sHUDSettingsMain) == 0) + if(strlen(sHUDSettings) == 0) { - IntToString(HUD_DEFAULT2, sHUDSettingsMain, 8); + IntToString(HUD_DEFAULT2, sHUDSettings, 8); - SetClientCookie(client, gH_HUDCookieMain, sHUDSettingsMain); + SetClientCookie(client, gH_HUDCookieMain, sHUDSettings); gI_HUD2Settings[client] = HUD_DEFAULT2; } else { - gI_HUD2Settings[client] = StringToInt(sHUDSettingsMain); + gI_HUD2Settings[client] = StringToInt(sHUDSettings); } }