diff options
Diffstat (limited to 'sourcemod/scripting/gokz-localdb')
| -rw-r--r-- | sourcemod/scripting/gokz-localdb/api.sp | 126 | ||||
| -rw-r--r-- | sourcemod/scripting/gokz-localdb/commands.sp | 199 | ||||
| -rw-r--r-- | sourcemod/scripting/gokz-localdb/db/cache_js.sp | 67 | ||||
| -rw-r--r-- | sourcemod/scripting/gokz-localdb/db/create_tables.sp | 36 | ||||
| -rw-r--r-- | sourcemod/scripting/gokz-localdb/db/helpers.sp | 18 | ||||
| -rw-r--r-- | sourcemod/scripting/gokz-localdb/db/save_js.sp | 291 | ||||
| -rw-r--r-- | sourcemod/scripting/gokz-localdb/db/save_time.sp | 83 | ||||
| -rw-r--r-- | sourcemod/scripting/gokz-localdb/db/set_cheater.sp | 64 | ||||
| -rw-r--r-- | sourcemod/scripting/gokz-localdb/db/setup_client.sp | 99 | ||||
| -rw-r--r-- | sourcemod/scripting/gokz-localdb/db/setup_database.sp | 34 | ||||
| -rw-r--r-- | sourcemod/scripting/gokz-localdb/db/setup_map.sp | 71 | ||||
| -rw-r--r-- | sourcemod/scripting/gokz-localdb/db/setup_map_courses.sp | 45 | ||||
| -rw-r--r-- | sourcemod/scripting/gokz-localdb/db/sql.sp | 406 | ||||
| -rw-r--r-- | sourcemod/scripting/gokz-localdb/db/timer_setup.sp | 167 | ||||
| -rw-r--r-- | sourcemod/scripting/gokz-localdb/options.sp | 90 |
15 files changed, 1796 insertions, 0 deletions
diff --git a/sourcemod/scripting/gokz-localdb/api.sp b/sourcemod/scripting/gokz-localdb/api.sp new file mode 100644 index 0000000..a4bc29c --- /dev/null +++ b/sourcemod/scripting/gokz-localdb/api.sp @@ -0,0 +1,126 @@ +static GlobalForward H_OnDatabaseConnect; +static GlobalForward H_OnClientSetup; +static GlobalForward H_OnMapSetup; +static GlobalForward H_OnTimeInserted; +static GlobalForward H_OnJumpstatPB; + + + +// =====[ FORWARDS ]===== + +void CreateGlobalForwards() +{ + H_OnDatabaseConnect = new GlobalForward("GOKZ_DB_OnDatabaseConnect", ET_Ignore, Param_Cell); + H_OnClientSetup = new GlobalForward("GOKZ_DB_OnClientSetup", ET_Ignore, Param_Cell, Param_Cell, Param_Cell); + H_OnMapSetup = new GlobalForward("GOKZ_DB_OnMapSetup", ET_Ignore, Param_Cell); + H_OnTimeInserted = new GlobalForward("GOKZ_DB_OnTimeInserted", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell); + H_OnJumpstatPB = new GlobalForward("GOKZ_DB_OnJumpstatPB", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell); +} + +void Call_OnDatabaseConnect() +{ + Call_StartForward(H_OnDatabaseConnect); + Call_PushCell(g_DBType); + Call_Finish(); +} + +void Call_OnClientSetup(int client, int steamID, bool cheater) +{ + Call_StartForward(H_OnClientSetup); + Call_PushCell(client); + Call_PushCell(steamID); + Call_PushCell(cheater); + Call_Finish(); +} + +void Call_OnMapSetup() +{ + Call_StartForward(H_OnMapSetup); + Call_PushCell(gI_DBCurrentMapID); + Call_Finish(); +} + +void Call_OnTimeInserted(int client, int steamID, int mapID, int course, int mode, int style, int runTimeMS, int teleportsUsed) +{ + Call_StartForward(H_OnTimeInserted); + Call_PushCell(client); + Call_PushCell(steamID); + Call_PushCell(mapID); + Call_PushCell(course); + Call_PushCell(mode); + Call_PushCell(style); + Call_PushCell(runTimeMS); + Call_PushCell(teleportsUsed); + Call_Finish(); +} + +void Call_OnJumpstatPB(int client, int jumptype, int mode, float distance, int block, int strafes, float sync, float pre, float max, int airtime) +{ + Call_StartForward(H_OnJumpstatPB); + Call_PushCell(client); + Call_PushCell(jumptype); + Call_PushCell(mode); + Call_PushCell(distance); + Call_PushCell(block); + Call_PushCell(strafes); + Call_PushCell(sync); + Call_PushCell(pre); + Call_PushCell(max); + Call_PushCell(airtime); + Call_Finish(); +} + + + +// =====[ NATIVES ]===== + +void CreateNatives() +{ + CreateNative("GOKZ_DB_GetDatabase", Native_GetDatabase); + CreateNative("GOKZ_DB_GetDatabaseType", Native_GetDatabaseType); + CreateNative("GOKZ_DB_IsClientSetUp", Native_IsClientSetUp); + CreateNative("GOKZ_DB_IsMapSetUp", Native_IsMapSetUp); + CreateNative("GOKZ_DB_GetCurrentMapID", Native_GetCurrentMapID); + CreateNative("GOKZ_DB_IsCheater", Native_IsCheater); + CreateNative("GOKZ_DB_SetCheater", Native_SetCheater); +} + +public int Native_GetDatabase(Handle plugin, int numParams) +{ + if (gH_DB == null) + { + return view_as<int>(gH_DB); + } + return view_as<int>(CloneHandle(gH_DB)); +} + +public int Native_GetDatabaseType(Handle plugin, int numParams) +{ + return view_as<int>(g_DBType); +} + +public int Native_IsClientSetUp(Handle plugin, int numParams) +{ + return view_as<int>(gB_ClientSetUp[GetNativeCell(1)]); +} + +public int Native_IsMapSetUp(Handle plugin, int numParams) +{ + return view_as<int>(gB_MapSetUp); +} + +public int Native_GetCurrentMapID(Handle plugin, int numParams) +{ + return gI_DBCurrentMapID; +} + +public int Native_IsCheater(Handle plugin, int numParams) +{ + return view_as<int>(gB_Cheater[GetNativeCell(1)]); +} + +public int Native_SetCheater(Handle plugin, int numParams) +{ + DB_SetCheater(GetNativeCell(1), GetNativeCell(2)); + return 0; +} diff --git a/sourcemod/scripting/gokz-localdb/commands.sp b/sourcemod/scripting/gokz-localdb/commands.sp new file mode 100644 index 0000000..2410fc5 --- /dev/null +++ b/sourcemod/scripting/gokz-localdb/commands.sp @@ -0,0 +1,199 @@ +void RegisterCommands() +{ + RegConsoleCmd("sm_savetimersetup", Command_SaveTimerSetup, "[KZ] Save the current timer setup (virtual buttons and start position)."); + RegConsoleCmd("sm_sts", Command_SaveTimerSetup, "[KZ] Save the current timer setup (virtual buttons and start position)."); + RegConsoleCmd("sm_loadtimersetup", Command_LoadTimerSetup, "[KZ] Load the saved timer setup (virtual buttons and start position)."); + RegConsoleCmd("sm_lts", Command_LoadTimerSetup, "[KZ] Load the saved timer setup (virtual buttons and start position)."); + + RegAdminCmd("sm_setcheater", CommandSetCheater, ADMFLAG_ROOT, "[KZ] Set a SteamID as a cheater. Usage: !setcheater <STEAM_1:X:X>"); + RegAdminCmd("sm_setnotcheater", CommandSetNotCheater, ADMFLAG_ROOT, "[KZ] Set a SteamID as not a cheater. Usage: !setnotcheater <STEAM_1:X:X>"); + RegAdminCmd("sm_deletebestjump", CommandDeleteBestJump, ADMFLAG_ROOT, "[KZ] Remove the top jumpstat of a SteamID. Usage: !deletebestjump <STEAM_1:X:X> <mode> <jump type> <block?>"); + RegAdminCmd("sm_deletealljumps", CommandDeleteAllJumps, ADMFLAG_ROOT, "[KZ] Remove all jumpstats of a SteamID. Usage: !deletealljumps <STEAM_1:X:X>"); + RegAdminCmd("sm_deletejump", CommandDeleteJump, ADMFLAG_ROOT, "[KZ] Remove a jumpstat by it's id. Usage: !deletejump <id>"); + RegAdminCmd("sm_deletetime", CommandDeleteTime, ADMFLAG_ROOT, "[KZ] Remove a time by it's id. Usage: !deletetime <id>"); +} + +public Action Command_SaveTimerSetup(int client, int args) +{ + DB_SaveTimerSetup(client); + return Plugin_Handled; +} + +public Action Command_LoadTimerSetup(int client, int args) +{ + DB_LoadTimerSetup(client, true); + return Plugin_Handled; +} + +public Action CommandSetCheater(int client, int args) +{ + if (args == 0) + { + GOKZ_PrintToChat(client, true, "%t", "No SteamID specified"); + return Plugin_Handled; + } + + char steamID2[64]; + GetCmdArgString(steamID2, sizeof(steamID2)); + int steamAccountID = Steam2ToSteamAccountID(steamID2); + if (steamAccountID == -1) + { + GOKZ_PrintToChat(client, true, "%t", "Invalid SteamID"); + } + else + { + DB_SetCheaterSteamID(client, steamAccountID, true); + } + + return Plugin_Handled; +} + +public Action CommandSetNotCheater(int client, int args) +{ + if (args == 0) + { + GOKZ_PrintToChat(client, true, "%t", "No SteamID specified"); + } + + char steamID2[64]; + GetCmdArgString(steamID2, sizeof(steamID2)); + int steamAccountID = Steam2ToSteamAccountID(steamID2); + if (steamAccountID == -1) + { + GOKZ_PrintToChat(client, true, "%t", "Invalid SteamID"); + } + else + { + DB_SetCheaterSteamID(client, steamAccountID, false); + } + + return Plugin_Handled; +} + +public Action CommandDeleteBestJump(int client, int args) +{ + if (args < 3) + { + GOKZ_PrintToChat(client, true, "%t", "Delete Best Jump Usage"); + return Plugin_Handled; + } + + int steamAccountID, isBlock, mode, jumpType; + char query[1024], split[4][32]; + + // Get arguments + split[3][0] = '\0'; + GetCmdArgString(query, sizeof(query)); + ExplodeString(query, " ", split, 4, 32, false); + + // SteamID32 + steamAccountID = Steam2ToSteamAccountID(split[0]); + if (steamAccountID == -1) + { + GOKZ_PrintToChat(client, true, "%t", "Invalid SteamID"); + return Plugin_Handled; + } + + // Mode + for (mode = 0; mode < MODE_COUNT; mode++) + { + if (StrEqual(split[1], gC_ModeNames[mode]) || StrEqual(split[1], gC_ModeNamesShort[mode], false)) + { + break; + } + } + if (mode == MODE_COUNT) + { + GOKZ_PrintToChat(client, true, "%t", "Invalid Mode"); + return Plugin_Handled; + } + + // Jumptype + for (jumpType = 0; jumpType < JUMPTYPE_COUNT; jumpType++) + { + if (StrEqual(split[2], gC_JumpTypes[jumpType]) || StrEqual(split[2], gC_JumpTypesShort[jumpType], false)) + { + break; + } + } + if (jumpType == JUMPTYPE_COUNT) + { + GOKZ_PrintToChat(client, true, "%t", "Invalid Jumptype"); + return Plugin_Handled; + } + + // Is it a block jump? + isBlock = StrEqual(split[3], "yes", false) || StrEqual(split[3], "true", false) || StrEqual(split[3], "1"); + + DB_DeleteBestJump(client, steamAccountID, jumpType, mode, isBlock); + + return Plugin_Handled; +} + +public Action CommandDeleteAllJumps(int client, int args) +{ + if (args < 1) + { + GOKZ_PrintToChat(client, true, "%t", "Delete All Jumps Usage"); + return Plugin_Handled; + } + + int steamAccountID; + char steamid[32]; + + GetCmdArgString(steamid, sizeof(steamid)); + steamAccountID = Steam2ToSteamAccountID(steamid); + if (steamAccountID == -1) + { + GOKZ_PrintToChat(client, true, "%t", "Invalid SteamID"); + return Plugin_Handled; + } + + DB_DeleteAllJumps(client, steamAccountID); + + return Plugin_Handled; +} + +public Action CommandDeleteJump(int client, int args) +{ + if (args < 1) + { + GOKZ_PrintToChat(client, true, "%t", "Delete Jump Usage"); + return Plugin_Handled; + } + + char buffer[24]; + int jumpID; + GetCmdArgString(buffer, sizeof(buffer)); + if (StringToIntEx(buffer, jumpID) == 0) + { + GOKZ_PrintToChat(client, true, "%t", "Invalid Jump ID"); + return Plugin_Handled; + } + + DB_DeleteJump(client, jumpID); + + return Plugin_Handled; +} + +public Action CommandDeleteTime(int client, int args) +{ + if (args < 1) + { + GOKZ_PrintToChat(client, true, "%t", "Delete Time Usage"); + return Plugin_Handled; + } + + char buffer[24]; + int timeID; + GetCmdArgString(buffer, sizeof(buffer)); + if (StringToIntEx(buffer, timeID) == 0) + { + GOKZ_PrintToChat(client, true, "%t", "Invalid Time ID"); + return Plugin_Handled; + } + + DB_DeleteTime(client, timeID); + + return Plugin_Handled; +} diff --git a/sourcemod/scripting/gokz-localdb/db/cache_js.sp b/sourcemod/scripting/gokz-localdb/db/cache_js.sp new file mode 100644 index 0000000..b0df708 --- /dev/null +++ b/sourcemod/scripting/gokz-localdb/db/cache_js.sp @@ -0,0 +1,67 @@ +/* + Caches the player's personal best jumpstats. +*/ + + + +void DB_CacheJSPBs(int client, int steamID) +{ + ClearCache(client); + + char query[1024]; + + Transaction txn = SQL_CreateTransaction(); + + FormatEx(query, sizeof(query), sql_jumpstats_getpbs, steamID); + txn.AddQuery(query); + + FormatEx(query, sizeof(query), sql_jumpstats_getblockpbs, steamID, steamID); + txn.AddQuery(query); + + SQL_ExecuteTransaction(gH_DB, txn, DB_TxnSuccess_CacheJSPBs, DB_TxnFailure_Generic, GetClientUserId(client), DBPrio_High); +} + +public void DB_TxnSuccess_CacheJSPBs(Handle db, int userID, int numQueries, Handle[] results, any[] queryData) +{ + int client = GetClientOfUserId(userID); + if (client < 1 || client > MaxClients || !IsClientAuthorized(client) || IsFakeClient(client)) + { + return; + } + + int distance, mode, jumpType, block; + + while (SQL_FetchRow(results[0])) + { + distance = SQL_FetchInt(results[0], 0); + mode = SQL_FetchInt(results[0], 1); + jumpType = SQL_FetchInt(results[0], 2); + + gI_PBJSCache[client][mode][jumpType][JumpstatDB_Cache_Distance] = block; + } + + while (SQL_FetchRow(results[1])) + { + distance = SQL_FetchInt(results[1], 0); + mode = SQL_FetchInt(results[1], 1); + jumpType = SQL_FetchInt(results[1], 2); + block = SQL_FetchInt(results[1], 3); + + gI_PBJSCache[client][mode][jumpType][JumpstatDB_Cache_BlockDistance] = distance; + gI_PBJSCache[client][mode][jumpType][JumpstatDB_Cache_Block] = block; + } +} + +void ClearCache(int client) +{ + for (int mode = 0; mode < MODE_COUNT; mode += 1) + { + for (int type = 0; type < JUMPTYPE_COUNT; type += 1) + { + for (int cache = 0; cache < JUMPSTATDB_CACHE_COUNT; cache += 1) + { + gI_PBJSCache[client][mode][type][cache] = 0; + } + } + } +}
\ No newline at end of file diff --git a/sourcemod/scripting/gokz-localdb/db/create_tables.sp b/sourcemod/scripting/gokz-localdb/db/create_tables.sp new file mode 100644 index 0000000..2138830 --- /dev/null +++ b/sourcemod/scripting/gokz-localdb/db/create_tables.sp @@ -0,0 +1,36 @@ +/* + Table creation and alteration. +*/ + + + +void DB_CreateTables() +{ + Transaction txn = SQL_CreateTransaction(); + + switch (g_DBType) + { + case DatabaseType_SQLite: + { + txn.AddQuery(sqlite_players_create); + txn.AddQuery(sqlite_maps_create); + txn.AddQuery(sqlite_mapcourses_create); + txn.AddQuery(sqlite_times_create); + txn.AddQuery(sqlite_jumpstats_create); + txn.AddQuery(sqlite_vbpos_create); + txn.AddQuery(sqlite_startpos_create); + } + case DatabaseType_MySQL: + { + txn.AddQuery(mysql_players_create); + txn.AddQuery(mysql_maps_create); + txn.AddQuery(mysql_mapcourses_create); + txn.AddQuery(mysql_times_create); + txn.AddQuery(mysql_jumpstats_create); + txn.AddQuery(mysql_vbpos_create); + txn.AddQuery(mysql_startpos_create); + } + } + + SQL_ExecuteTransaction(gH_DB, txn, _, DB_TxnFailure_Generic, _, DBPrio_High); +}
\ No newline at end of file diff --git a/sourcemod/scripting/gokz-localdb/db/helpers.sp b/sourcemod/scripting/gokz-localdb/db/helpers.sp new file mode 100644 index 0000000..1eff866 --- /dev/null +++ b/sourcemod/scripting/gokz-localdb/db/helpers.sp @@ -0,0 +1,18 @@ +/* + Database helper functions and callbacks. +*/ + + + +/* Error report callback for failed transactions */ +public void DB_TxnFailure_Generic(Handle db, any data, int numQueries, const char[] error, int failIndex, any[] queryData) +{ + LogError("Database transaction error: %s", error); +} + +/* Error report callback for failed transactions which deletes the DataPack */ +public void DB_TxnFailure_Generic_DataPack(Handle db, DataPack data, int numQueries, const char[] error, int failIndex, any[] queryData) +{ + delete data; + LogError("Database transaction error: %s", error); +} diff --git a/sourcemod/scripting/gokz-localdb/db/save_js.sp b/sourcemod/scripting/gokz-localdb/db/save_js.sp new file mode 100644 index 0000000..1d50754 --- /dev/null +++ b/sourcemod/scripting/gokz-localdb/db/save_js.sp @@ -0,0 +1,291 @@ +/* + Inserts or updates the player's jumpstat into the database. +*/ + + + +public void OnLanding_SaveJumpstat(Jump jump) +{ + int mode = GOKZ_GetCoreOption(jump.jumper, Option_Mode); + + // No tiers given for 'Invalid' jumps. + if (jump.type == JumpType_Invalid || jump.type == JumpType_FullInvalid + || jump.type == JumpType_Fall || jump.type == JumpType_Other + || jump.type != JumpType_LadderJump && jump.offset < -JS_OFFSET_EPSILON + || jump.distance > JS_MAX_JUMP_DISTANCE + || jump.type == JumpType_LadderJump && jump.distance < JS_MIN_LAJ_BLOCK_DISTANCE + || jump.type != JumpType_LadderJump && jump.distance < JS_MIN_BLOCK_DISTANCE) + { + return; + } + + char query[1024]; + DataPack data; + int steamid = GetSteamAccountID(jump.jumper); + int int_dist = RoundToNearest(jump.distance * GOKZ_DB_JS_DISTANCE_PRECISION); + + // Non-block + if (gI_PBJSCache[jump.jumper][mode][jump.type][JumpstatDB_Cache_Distance] == 0 + || int_dist > gI_PBJSCache[jump.jumper][mode][jump.type][JumpstatDB_Cache_Distance]) + { + data = JSRecord_FillDataPack(jump, steamid, mode, false); + Transaction txn_noblock = SQL_CreateTransaction(); + FormatEx(query, sizeof(query), sql_jumpstats_getrecord, steamid, jump.type, mode, 0); + txn_noblock.AddQuery(query); + SQL_ExecuteTransaction(gH_DB, txn_noblock, DB_TxnSuccess_LookupJSRecordForSave, DB_TxnFailure_Generic_DataPack, data, DBPrio_Low); + } + + // Block + if (jump.block > 0 + && (gI_PBJSCache[jump.jumper][mode][jump.type][JumpstatDB_Cache_Block] == 0 + || (jump.block > gI_PBJSCache[jump.jumper][mode][jump.type][JumpstatDB_Cache_Block] + || jump.block == gI_PBJSCache[jump.jumper][mode][jump.type][JumpstatDB_Cache_Block] + && int_dist > gI_PBJSCache[jump.jumper][mode][jump.type][JumpstatDB_Cache_BlockDistance]))) + { + data = JSRecord_FillDataPack(jump, steamid, mode, true); + Transaction txn_block = SQL_CreateTransaction(); + FormatEx(query, sizeof(query), sql_jumpstats_getrecord, steamid, jump.type, mode, 1); + txn_block.AddQuery(query); + SQL_ExecuteTransaction(gH_DB, txn_block, DB_TxnSuccess_LookupJSRecordForSave, DB_TxnFailure_Generic_DataPack, data, DBPrio_Low); + } +} + +static DataPack JSRecord_FillDataPack(Jump jump, int steamid, int mode, bool blockJump) +{ + DataPack data = new DataPack(); + data.WriteCell(jump.jumper); + data.WriteCell(steamid); + data.WriteCell(jump.type); + data.WriteCell(mode); + data.WriteCell(RoundToNearest(jump.distance * GOKZ_DB_JS_DISTANCE_PRECISION)); + data.WriteCell(blockJump ? jump.block : 0); + data.WriteCell(jump.strafes); + data.WriteCell(RoundToNearest(jump.sync * GOKZ_DB_JS_SYNC_PRECISION)); + data.WriteCell(RoundToNearest(jump.preSpeed * GOKZ_DB_JS_PRE_PRECISION)); + data.WriteCell(RoundToNearest(jump.maxSpeed * GOKZ_DB_JS_MAX_PRECISION)); + data.WriteCell(RoundToNearest(jump.duration * GetTickInterval() * GOKZ_DB_JS_AIRTIME_PRECISION)); + return data; +} + +public void DB_TxnSuccess_LookupJSRecordForSave(Handle db, DataPack data, int numQueries, Handle[] results, any[] queryData) +{ + data.Reset(); + int client = data.ReadCell(); + int steamid = data.ReadCell(); + int jumpType = data.ReadCell(); + int mode = data.ReadCell(); + int distance = data.ReadCell(); + int block = data.ReadCell(); + int strafes = data.ReadCell(); + int sync = data.ReadCell(); + int pre = data.ReadCell(); + int max = data.ReadCell(); + int airtime = data.ReadCell(); + + if (!IsValidClient(client)) + { + delete data; + return; + } + + char query[1024]; + int rows = SQL_GetRowCount(results[0]); + if (rows == 0) + { + FormatEx(query, sizeof(query), sql_jumpstats_insert, steamid, jumpType, mode, distance, block > 0, block, strafes, sync, pre, max, airtime); + } + else + { + SQL_FetchRow(results[0]); + int rec_distance = SQL_FetchInt(results[0], JumpstatDB_Lookup_Distance); + int rec_block = SQL_FetchInt(results[0], JumpstatDB_Lookup_Block); + + if (rec_block == 0) + { + gI_PBJSCache[client][mode][jumpType][JumpstatDB_Cache_Distance] = rec_distance; + } + else + { + gI_PBJSCache[client][mode][jumpType][JumpstatDB_Cache_Block] = rec_block; + gI_PBJSCache[client][mode][jumpType][JumpstatDB_Cache_BlockDistance] = rec_distance; + } + + if (block < rec_block || block == rec_block && distance < rec_distance) + { + delete data; + return; + } + + if (rows < GOKZ_DB_JS_MAX_JUMPS_PER_PLAYER) + { + FormatEx(query, sizeof(query), sql_jumpstats_insert, steamid, jumpType, mode, distance, block > 0, block, strafes, sync, pre, max, airtime); + } + else + { + for (int i = 1; i < GOKZ_DB_JS_MAX_JUMPS_PER_PLAYER; i++) + { + SQL_FetchRow(results[0]); + } + int min_rec_id = SQL_FetchInt(results[0], JumpstatDB_Lookup_JumpID); + FormatEx(query, sizeof(query), sql_jumpstats_update, steamid, jumpType, mode, distance, block > 0, block, strafes, sync, pre, max, airtime, min_rec_id); + } + + } + + Transaction txn = SQL_CreateTransaction(); + txn.AddQuery(query); + SQL_ExecuteTransaction(gH_DB, txn, DB_TxnSuccess_SaveJSRecord, DB_TxnFailure_Generic_DataPack, data, DBPrio_Low); +} + +public void DB_TxnSuccess_SaveJSRecord(Handle db, DataPack data, int numQueries, Handle[] results, any[] queryData) +{ + data.Reset(); + int client = data.ReadCell(); + data.ReadCell(); + int jumpType = data.ReadCell(); + int mode = data.ReadCell(); + int distance = data.ReadCell(); + int block = data.ReadCell(); + int strafes = data.ReadCell(); + int sync = data.ReadCell(); + int pre = data.ReadCell(); + int max = data.ReadCell(); + int airtime = data.ReadCell(); + delete data; + + if (!IsValidClient(client) || GOKZ_JS_GetOption(client, JSOption_JumpstatsMaster) == JSToggleOption_Disabled) + { + return; + } + + float distanceFloat = float(distance) / GOKZ_DB_JS_DISTANCE_PRECISION; + float syncFloat = float(sync) / GOKZ_DB_JS_SYNC_PRECISION; + float preFloat = float(pre) / GOKZ_DB_JS_PRE_PRECISION; + float maxFloat = float(max) / GOKZ_DB_JS_MAX_PRECISION; + + if (block == 0) + { + gI_PBJSCache[client][mode][jumpType][JumpstatDB_Cache_Distance] = distance; + GOKZ_PrintToChat(client, true, "%t", "Jump Record", + client, + gC_JumpTypes[jumpType], + distanceFloat, + gC_ModeNamesShort[mode]); + } + else + { + gI_PBJSCache[client][mode][jumpType][JumpstatDB_Cache_Block] = block; + gI_PBJSCache[client][mode][jumpType][JumpstatDB_Cache_BlockDistance] = distance; + GOKZ_PrintToChat(client, true, "%t", "Block Jump Record", + client, + block, + gC_JumpTypes[jumpType], + distanceFloat, + gC_ModeNamesShort[mode], + block); + } + + Call_OnJumpstatPB(client, jumpType, mode, distanceFloat, block, strafes, syncFloat, preFloat, maxFloat, airtime); +} + +public void DB_DeleteBestJump(int client, int steamAccountID, int jumpType, int mode, int isBlock) +{ + DataPack data = new DataPack(); + data.WriteCell(client == 0 ? -1 : GetClientUserId(client)); // -1 if called from server console + data.WriteCell(steamAccountID); + data.WriteCell(jumpType); + data.WriteCell(mode); + data.WriteCell(isBlock); + + char query[1024]; + + FormatEx(query, sizeof(query), sql_jumpstats_deleterecord, steamAccountID, jumpType, mode, isBlock); + + Transaction txn = SQL_CreateTransaction(); + txn.AddQuery(query); + + SQL_ExecuteTransaction(gH_DB, txn, DB_TxnSuccess_BestJumpDeleted, DB_TxnFailure_Generic_DataPack, data, DBPrio_Low); +} + +public void DB_TxnSuccess_BestJumpDeleted(Handle db, DataPack data, int numQueries, Handle[] results, any[] queryData) +{ + char blockString[16] = ""; + + data.Reset(); + int client = GetClientOfUserId(data.ReadCell()); + int steamAccountID = data.ReadCell(); + int jumpType = data.ReadCell(); + int mode = data.ReadCell(); + bool isBlock = data.ReadCell() == 1; + delete data; + + if (isBlock) + { + FormatEx(blockString, sizeof(blockString), "%T ", "Block", client); + } + + ClearCache(client); + + GOKZ_PrintToChatAndLog(client, true, "%t", "Best Jump Deleted", + gC_ModeNames[mode], + blockString, + gC_JumpTypes[jumpType], + steamAccountID & 1, + steamAccountID >> 1); +} + +public void DB_DeleteAllJumps(int client, int steamAccountID) +{ + DataPack data = new DataPack(); + data.WriteCell(client == 0 ? -1 : GetClientUserId(client)); // -1 if called from server console + data.WriteCell(steamAccountID); + + char query[1024]; + + FormatEx(query, sizeof(query), sql_jumpstats_deleteallrecords, steamAccountID); + + Transaction txn = SQL_CreateTransaction(); + txn.AddQuery(query); + + SQL_ExecuteTransaction(gH_DB, txn, DB_TxnSuccess_AllJumpsDeleted, DB_TxnFailure_Generic_DataPack, data, DBPrio_Low); +} + +public void DB_TxnSuccess_AllJumpsDeleted(Handle db, DataPack data, int numQueries, Handle[] results, any[] queryData) +{ + data.Reset(); + int client = GetClientOfUserId(data.ReadCell()); + int steamAccountID = data.ReadCell(); + delete data; + + ClearCache(client); + + GOKZ_PrintToChatAndLog(client, true, "%t", "All Jumps Deleted", + steamAccountID & 1, + steamAccountID >> 1); +} + +public void DB_DeleteJump(int client, int jumpID) +{ + DataPack data = new DataPack(); + data.WriteCell(client == 0 ? -1 : GetClientUserId(client)); // -1 if called from server console + data.WriteCell(jumpID); + + char query[1024]; + FormatEx(query, sizeof(query), sql_jumpstats_deletejump, jumpID); + + Transaction txn = SQL_CreateTransaction(); + txn.AddQuery(query); + + SQL_ExecuteTransaction(gH_DB, txn, DB_TxnSuccess_JumpDeleted, DB_TxnFailure_Generic_DataPack, data, DBPrio_Low); +} + +public void DB_TxnSuccess_JumpDeleted(Handle db, DataPack data, int numQueries, Handle[] results, any[] queryData) +{ + data.Reset(); + int client = GetClientOfUserId(data.ReadCell()); + int jumpID = data.ReadCell(); + delete data; + + GOKZ_PrintToChatAndLog(client, true, "%t", "Jump Deleted", + jumpID); +} diff --git a/sourcemod/scripting/gokz-localdb/db/save_time.sp b/sourcemod/scripting/gokz-localdb/db/save_time.sp new file mode 100644 index 0000000..84589a5 --- /dev/null +++ b/sourcemod/scripting/gokz-localdb/db/save_time.sp @@ -0,0 +1,83 @@ +/* + Inserts the player's time into the database. +*/ + + + +void DB_SaveTime(int client, int course, int mode, int style, float runTime, int teleportsUsed) +{ + if (IsFakeClient(client)) + { + return; + } + + char query[1024]; + int steamID = GetSteamAccountID(client); + int mapID = GOKZ_DB_GetCurrentMapID(); + int runTimeMS = GOKZ_DB_TimeFloatToInt(runTime); + + DataPack data = new DataPack(); + data.WriteCell(GetClientUserId(client)); + data.WriteCell(steamID); + data.WriteCell(mapID); + data.WriteCell(course); + data.WriteCell(mode); + data.WriteCell(style); + data.WriteCell(runTimeMS); + data.WriteCell(teleportsUsed); + + Transaction txn = SQL_CreateTransaction(); + + // Save runTime to DB + FormatEx(query, sizeof(query), sql_times_insert, steamID, mode, style, runTimeMS, teleportsUsed, mapID, course); + txn.AddQuery(query); + + SQL_ExecuteTransaction(gH_DB, txn, DB_TxnSuccess_SaveTime, DB_TxnFailure_Generic_DataPack, data, DBPrio_Normal); +} + +public void DB_TxnSuccess_SaveTime(Handle db, DataPack data, int numQueries, Handle[] results, any[] queryData) +{ + data.Reset(); + int client = GetClientOfUserId(data.ReadCell()); + int steamID = data.ReadCell(); + int mapID = data.ReadCell(); + int course = data.ReadCell(); + int mode = data.ReadCell(); + int style = data.ReadCell(); + int runTimeMS = data.ReadCell(); + int teleportsUsed = data.ReadCell(); + delete data; + + if (!IsValidClient(client)) + { + return; + } + + Call_OnTimeInserted(client, steamID, mapID, course, mode, style, runTimeMS, teleportsUsed); +} + +public void DB_DeleteTime(int client, int timeID) +{ + DataPack data = new DataPack(); + data.WriteCell(client == 0 ? -1 : GetClientUserId(client)); // -1 if called from server console + data.WriteCell(timeID); + + char query[1024]; + FormatEx(query, sizeof(query), sql_times_delete, timeID); + + Transaction txn = SQL_CreateTransaction(); + txn.AddQuery(query); + + SQL_ExecuteTransaction(gH_DB, txn, DB_TxnSuccess_TimeDeleted, DB_TxnFailure_Generic_DataPack, data, DBPrio_Low); +} + +public void DB_TxnSuccess_TimeDeleted(Handle db, DataPack data, int numQueries, Handle[] results, any[] queryData) +{ + data.Reset(); + int client = GetClientOfUserId(data.ReadCell()); + int timeID = data.ReadCell(); + delete data; + + GOKZ_PrintToChatAndLog(client, true, "%t", "Time Deleted", + timeID); +} diff --git a/sourcemod/scripting/gokz-localdb/db/set_cheater.sp b/sourcemod/scripting/gokz-localdb/db/set_cheater.sp new file mode 100644 index 0000000..c63f161 --- /dev/null +++ b/sourcemod/scripting/gokz-localdb/db/set_cheater.sp @@ -0,0 +1,64 @@ +/* + Sets whether player is a cheater in the database. +*/ + + + +void DB_SetCheater(int cheaterClient, bool cheater) +{ + if (gB_Cheater[cheaterClient] == cheater) + { + return; + } + + gB_Cheater[cheaterClient] = cheater; + + DataPack data = new DataPack(); + data.WriteCell(-1); + data.WriteCell(GetSteamAccountID(cheaterClient)); + data.WriteCell(cheater); + + char query[128]; + + Transaction txn = SQL_CreateTransaction(); + + FormatEx(query, sizeof(query), sql_players_set_cheater, cheater ? 1 : 0, GetSteamAccountID(cheaterClient)); + txn.AddQuery(query); + + SQL_ExecuteTransaction(gH_DB, txn, DB_TxnSuccess_SetCheater, DB_TxnFailure_Generic_DataPack, data, DBPrio_High); +} + +void DB_SetCheaterSteamID(int client, int cheaterSteamID, bool cheater) +{ + DataPack data = new DataPack(); + data.WriteCell(client == 0 ? -1 : GetClientUserId(client)); // -1 if called from server console + data.WriteCell(cheaterSteamID); + data.WriteCell(cheater); + + char query[128]; + + Transaction txn = SQL_CreateTransaction(); + + FormatEx(query, sizeof(query), sql_players_set_cheater, cheater ? 1 : 0, cheaterSteamID); + txn.AddQuery(query); + + SQL_ExecuteTransaction(gH_DB, txn, DB_TxnSuccess_SetCheater, DB_TxnFailure_Generic_DataPack, data, DBPrio_High); +} + +public void DB_TxnSuccess_SetCheater(Handle db, DataPack data, int numQueries, Handle[] results, any[] queryData) +{ + data.Reset(); + int client = GetClientOfUserId(data.ReadCell()); + int steamID = data.ReadCell(); + bool cheater = view_as<bool>(data.ReadCell()); + delete data; + + if (cheater) + { + GOKZ_PrintToChatAndLog(client, true, "%t", "Set Cheater", steamID & 1, steamID >> 1); + } + else + { + GOKZ_PrintToChatAndLog(client, true, "%t", "Set Not Cheater", steamID & 1, steamID >> 1); + } +}
\ No newline at end of file diff --git a/sourcemod/scripting/gokz-localdb/db/setup_client.sp b/sourcemod/scripting/gokz-localdb/db/setup_client.sp new file mode 100644 index 0000000..848be87 --- /dev/null +++ b/sourcemod/scripting/gokz-localdb/db/setup_client.sp @@ -0,0 +1,99 @@ +/* + Inserts the player into the database, or else updates their information. +*/ + + + +void DB_SetupClient(int client) +{ + if (IsFakeClient(client)) + { + return; + } + + // Setup Client Step 1 - Upsert them into Players Table + char query[1024], name[MAX_NAME_LENGTH], nameEscaped[MAX_NAME_LENGTH * 2 + 1], clientIP[16], country[45]; + + int steamID = GetSteamAccountID(client); + if (!GetClientName(client, name, MAX_NAME_LENGTH)) + { + LogMessage("Couldn't get name of %L.", client); + name = "Unknown"; + } + SQL_EscapeString(gH_DB, name, nameEscaped, MAX_NAME_LENGTH * 2 + 1); + if (!GetClientIP(client, clientIP, sizeof(clientIP))) + { + LogMessage("Couldn't get IP of %L.", client); + clientIP = "Unknown"; + } + if (!GeoipCountry(clientIP, country, sizeof(country))) + { + LogMessage("Couldn't get country of %L (%s).", client, clientIP); + country = "Unknown"; + } + + DataPack data = new DataPack(); + data.WriteCell(GetClientUserId(client)); + data.WriteCell(steamID); + + Transaction txn = SQL_CreateTransaction(); + + // Insert/Update player into Players table + switch (g_DBType) + { + case DatabaseType_SQLite: + { + // UPDATE OR IGNORE + FormatEx(query, sizeof(query), sqlite_players_update, nameEscaped, country, clientIP, steamID); + txn.AddQuery(query); + // INSERT OR IGNORE + FormatEx(query, sizeof(query), sqlite_players_insert, nameEscaped, country, clientIP, steamID); + txn.AddQuery(query); + } + case DatabaseType_MySQL: + { + // INSERT ... ON DUPLICATE KEY ... + FormatEx(query, sizeof(query), mysql_players_upsert, nameEscaped, country, clientIP, steamID); + txn.AddQuery(query); + } + } + + FormatEx(query, sizeof(query), sql_players_get_cheater, steamID); + txn.AddQuery(query); + + SQL_ExecuteTransaction(gH_DB, txn, DB_TxnSuccess_SetupClient, DB_TxnFailure_Generic_DataPack, data, DBPrio_High); +} + +public void DB_TxnSuccess_SetupClient(Handle db, DataPack data, int numQueries, Handle[] results, any[] queryData) +{ + data.Reset(); + int client = GetClientOfUserId(data.ReadCell()); + int steamID = data.ReadCell(); + delete data; + + if (client == 0 || !IsClientAuthorized(client)) + { + return; + } + + switch (g_DBType) + { + case DatabaseType_SQLite: + { + if (SQL_FetchRow(results[2])) + { + gB_Cheater[client] = SQL_FetchInt(results[2], 0) == 1; + } + } + case DatabaseType_MySQL: + { + if (SQL_FetchRow(results[1])) + { + gB_Cheater[client] = SQL_FetchInt(results[1], 0) == 1; + } + } + } + + gB_ClientSetUp[client] = true; + Call_OnClientSetup(client, steamID, gB_Cheater[client]); +}
\ No newline at end of file diff --git a/sourcemod/scripting/gokz-localdb/db/setup_database.sp b/sourcemod/scripting/gokz-localdb/db/setup_database.sp new file mode 100644 index 0000000..4965541 --- /dev/null +++ b/sourcemod/scripting/gokz-localdb/db/setup_database.sp @@ -0,0 +1,34 @@ +/* + Set up the connection to the local database. +*/ + + + +void DB_SetupDatabase() +{ + char error[255]; + gH_DB = SQL_Connect("gokz", true, error, sizeof(error)); + if (gH_DB == null) + { + SetFailState("Database connection failed. Error: \"%s\".", error); + } + + char databaseType[8]; + SQL_ReadDriver(gH_DB, databaseType, sizeof(databaseType)); + if (strcmp(databaseType, "sqlite", false) == 0) + { + g_DBType = DatabaseType_SQLite; + } + else if (strcmp(databaseType, "mysql", false) == 0) + { + g_DBType = DatabaseType_MySQL; + } + else + { + SetFailState("Incompatible database driver. Use SQLite or MySQL."); + } + + DB_CreateTables(); + + Call_OnDatabaseConnect(); +}
\ No newline at end of file diff --git a/sourcemod/scripting/gokz-localdb/db/setup_map.sp b/sourcemod/scripting/gokz-localdb/db/setup_map.sp new file mode 100644 index 0000000..a02e2d2 --- /dev/null +++ b/sourcemod/scripting/gokz-localdb/db/setup_map.sp @@ -0,0 +1,71 @@ +/* + Inserts the map information into the database. + Retrieves the MapID of the map and stores it in a global variable. +*/ + + + +void DB_SetupMap() +{ + gB_MapSetUp = false; + + char query[1024]; + + char map[PLATFORM_MAX_PATH]; + GetCurrentMapDisplayName(map, sizeof(map)); + + char escapedMap[PLATFORM_MAX_PATH * 2 + 1]; + SQL_EscapeString(gH_DB, map, escapedMap, sizeof(escapedMap)); + + Transaction txn = SQL_CreateTransaction(); + + // Insert/Update map into database + switch (g_DBType) + { + case DatabaseType_SQLite: + { + // UPDATE OR IGNORE + FormatEx(query, sizeof(query), sqlite_maps_update, escapedMap); + txn.AddQuery(query); + // INSERT OR IGNORE + FormatEx(query, sizeof(query), sqlite_maps_insert, escapedMap); + txn.AddQuery(query); + } + case DatabaseType_MySQL: + { + // INSERT ... ON DUPLICATE KEY ... + FormatEx(query, sizeof(query), mysql_maps_upsert, escapedMap); + txn.AddQuery(query); + } + } + // Retrieve mapID of map name + FormatEx(query, sizeof(query), sql_maps_findid, escapedMap, escapedMap); + txn.AddQuery(query); + + SQL_ExecuteTransaction(gH_DB, txn, DB_TxnSuccess_SetupMap, DB_TxnFailure_Generic, 0, DBPrio_High); +} + +public void DB_TxnSuccess_SetupMap(Handle db, any data, int numQueries, Handle[] results, any[] queryData) +{ + switch (g_DBType) + { + case DatabaseType_SQLite: + { + if (SQL_FetchRow(results[2])) + { + gI_DBCurrentMapID = SQL_FetchInt(results[2], 0); + gB_MapSetUp = true; + Call_OnMapSetup(); + } + } + case DatabaseType_MySQL: + { + if (SQL_FetchRow(results[1])) + { + gI_DBCurrentMapID = SQL_FetchInt(results[1], 0); + gB_MapSetUp = true; + Call_OnMapSetup(); + } + } + } +}
\ No newline at end of file diff --git a/sourcemod/scripting/gokz-localdb/db/setup_map_courses.sp b/sourcemod/scripting/gokz-localdb/db/setup_map_courses.sp new file mode 100644 index 0000000..69bb89e --- /dev/null +++ b/sourcemod/scripting/gokz-localdb/db/setup_map_courses.sp @@ -0,0 +1,45 @@ +/* + Inserts the map's courses into the database. +*/ + + + +void DB_SetupMapCourses() +{ + char query[512]; + + Transaction txn = SQL_CreateTransaction(); + + for (int course = 0; course < GOKZ_MAX_COURSES; course++) + { + if (!GOKZ_GetCourseRegistered(course)) + { + continue; + } + + switch (g_DBType) + { + case DatabaseType_SQLite:FormatEx(query, sizeof(query), sqlite_mapcourses_insert, gI_DBCurrentMapID, course); + case DatabaseType_MySQL:FormatEx(query, sizeof(query), mysql_mapcourses_insert, gI_DBCurrentMapID, course); + } + txn.AddQuery(query); + } + + SQL_ExecuteTransaction(gH_DB, txn, INVALID_FUNCTION, DB_TxnFailure_Generic, _, DBPrio_High); +} + +void DB_SetupMapCourse(int course) +{ + char query[512]; + + Transaction txn = SQL_CreateTransaction(); + + switch (g_DBType) + { + case DatabaseType_SQLite:FormatEx(query, sizeof(query), sqlite_mapcourses_insert, gI_DBCurrentMapID, course); + case DatabaseType_MySQL:FormatEx(query, sizeof(query), mysql_mapcourses_insert, gI_DBCurrentMapID, course); + } + txn.AddQuery(query); + + SQL_ExecuteTransaction(gH_DB, txn, INVALID_FUNCTION, DB_TxnFailure_Generic, _, DBPrio_High); +}
\ No newline at end of file diff --git a/sourcemod/scripting/gokz-localdb/db/sql.sp b/sourcemod/scripting/gokz-localdb/db/sql.sp new file mode 100644 index 0000000..46ea5e3 --- /dev/null +++ b/sourcemod/scripting/gokz-localdb/db/sql.sp @@ -0,0 +1,406 @@ +/* + SQL query templates. +*/ + + + +// =====[ PLAYERS ]===== + +char sqlite_players_create[] = "\ +CREATE TABLE IF NOT EXISTS Players ( \ + SteamID32 INTEGER NOT NULL, \ + Alias TEXT, \ + Country TEXT, \ + IP TEXT, \ + Cheater INTEGER NOT NULL DEFAULT '0', \ + LastPlayed TIMESTAMP NULL DEFAULT NULL, \ + Created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, \ + CONSTRAINT PK_Player PRIMARY KEY (SteamID32))"; + +char mysql_players_create[] = "\ +CREATE TABLE IF NOT EXISTS Players ( \ + SteamID32 INTEGER UNSIGNED NOT NULL, \ + Alias VARCHAR(32), \ + Country VARCHAR(45), \ + IP VARCHAR(15), \ + Cheater TINYINT UNSIGNED NOT NULL DEFAULT '0', \ + LastPlayed TIMESTAMP NULL DEFAULT NULL, \ + Created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, \ + CONSTRAINT PK_Player PRIMARY KEY (SteamID32))"; + +char sqlite_players_insert[] = "\ +INSERT OR IGNORE INTO Players (Alias, Country, IP, SteamID32, LastPlayed) \ + VALUES ('%s', '%s', '%s', %d, CURRENT_TIMESTAMP)"; + +char sqlite_players_update[] = "\ +UPDATE OR IGNORE Players \ + SET Alias='%s', Country='%s', IP='%s', LastPlayed=CURRENT_TIMESTAMP \ + WHERE SteamID32=%d"; + +char mysql_players_upsert[] = "\ +INSERT INTO Players (Alias, Country, IP, SteamID32, LastPlayed) \ + VALUES ('%s', '%s', '%s', %d, CURRENT_TIMESTAMP) \ + ON DUPLICATE KEY UPDATE \ + SteamID32=VALUES(SteamID32), Alias=VALUES(Alias), Country=VALUES(Country), \ + IP=VALUES(IP), LastPlayed=VALUES(LastPlayed)"; + +char sql_players_get_cheater[] = "\ +SELECT Cheater \ + FROM Players \ + WHERE SteamID32=%d"; + +char sql_players_set_cheater[] = "\ +UPDATE Players \ + SET Cheater=%d \ + WHERE SteamID32=%d"; + + + +// =====[ MAPS ]===== + +char sqlite_maps_create[] = "\ +CREATE TABLE IF NOT EXISTS Maps ( \ + MapID INTEGER NOT NULL, \ + Name VARCHAR(32) NOT NULL UNIQUE, \ + LastPlayed TIMESTAMP NULL DEFAULT NULL, \ + Created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, \ + CONSTRAINT PK_Maps PRIMARY KEY (MapID))"; + +char mysql_maps_create[] = "\ +CREATE TABLE IF NOT EXISTS Maps ( \ + MapID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, \ + Name VARCHAR(32) NOT NULL UNIQUE, \ + LastPlayed TIMESTAMP NULL DEFAULT NULL, \ + Created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, \ + CONSTRAINT PK_Maps PRIMARY KEY (MapID))"; + +char sqlite_maps_insert[] = "\ +INSERT OR IGNORE INTO Maps (Name, LastPlayed) \ + VALUES ('%s', CURRENT_TIMESTAMP)"; + +char sqlite_maps_update[] = "\ +UPDATE OR IGNORE Maps \ + SET LastPlayed=CURRENT_TIMESTAMP \ + WHERE Name='%s'"; + +char mysql_maps_upsert[] = "\ +INSERT INTO Maps (Name, LastPlayed) \ + VALUES ('%s', CURRENT_TIMESTAMP) \ + ON DUPLICATE KEY UPDATE \ + LastPlayed=CURRENT_TIMESTAMP"; + +char sql_maps_findid[] = "\ +SELECT MapID, Name \ + FROM Maps \ + WHERE Name LIKE '%%%s%%' \ + ORDER BY (Name='%s') DESC, LENGTH(Name) \ + LIMIT 1"; + + + +// =====[ MAPCOURSES ]===== + +char sqlite_mapcourses_create[] = "\ +CREATE TABLE IF NOT EXISTS MapCourses ( \ + MapCourseID INTEGER NOT NULL, \ + MapID INTEGER NOT NULL, \ + Course INTEGER NOT NULL, \ + Created INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP, \ + CONSTRAINT PK_MapCourses PRIMARY KEY (MapCourseID), \ + CONSTRAINT UQ_MapCourses_MapIDCourse UNIQUE (MapID, Course), \ + CONSTRAINT FK_MapCourses_MapID FOREIGN KEY (MapID) REFERENCES Maps(MapID) \ + ON UPDATE CASCADE ON DELETE CASCADE)"; + +char mysql_mapcourses_create[] = "\ +CREATE TABLE IF NOT EXISTS MapCourses ( \ + MapCourseID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, \ + MapID INTEGER UNSIGNED NOT NULL, \ + Course INTEGER UNSIGNED NOT NULL, \ + Created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, \ + CONSTRAINT PK_MapCourses PRIMARY KEY (MapCourseID), \ + CONSTRAINT UQ_MapCourses_MapIDCourse UNIQUE (MapID, Course), \ + CONSTRAINT FK_MapCourses_MapID FOREIGN KEY (MapID) REFERENCES Maps(MapID) \ + ON UPDATE CASCADE ON DELETE CASCADE)"; + +char sqlite_mapcourses_insert[] = "\ +INSERT OR IGNORE INTO MapCourses (MapID, Course) \ + VALUES (%d, %d)"; + +char mysql_mapcourses_insert[] = "\ +INSERT IGNORE INTO MapCourses (MapID, Course) \ + VALUES (%d, %d)"; + + + +// =====[ TIMES ]===== + +char sqlite_times_create[] = "\ +CREATE TABLE IF NOT EXISTS Times ( \ + TimeID INTEGER NOT NULL, \ + SteamID32 INTEGER NOT NULL, \ + MapCourseID INTEGER NOT NULL, \ + Mode INTEGER NOT NULL, \ + Style INTEGER NOT NULL, \ + RunTime INTEGER NOT NULL, \ + Teleports INTEGER NOT NULL, \ + Created INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP, \ + CONSTRAINT PK_Times PRIMARY KEY (TimeID), \ + CONSTRAINT FK_Times_SteamID32 FOREIGN KEY (SteamID32) REFERENCES Players(SteamID32) \ + ON UPDATE CASCADE ON DELETE CASCADE, CONSTRAINT FK_Times_MapCourseID \ + FOREIGN KEY (MapCourseID) REFERENCES MapCourses(MapCourseID) \ + ON UPDATE CASCADE ON DELETE CASCADE)"; + +char mysql_times_create[] = "\ +CREATE TABLE IF NOT EXISTS Times ( \ + TimeID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, \ + SteamID32 INTEGER UNSIGNED NOT NULL, \ + MapCourseID INTEGER UNSIGNED NOT NULL, \ + Mode TINYINT UNSIGNED NOT NULL, \ + Style TINYINT UNSIGNED NOT NULL, \ + RunTime INTEGER UNSIGNED NOT NULL, \ + Teleports SMALLINT UNSIGNED NOT NULL, \ + Created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, \ + CONSTRAINT PK_Times PRIMARY KEY (TimeID), \ + CONSTRAINT FK_Times_SteamID32 FOREIGN KEY (SteamID32) REFERENCES Players(SteamID32) \ + ON UPDATE CASCADE ON DELETE CASCADE, \ + CONSTRAINT FK_Times_MapCourseID FOREIGN KEY (MapCourseID) REFERENCES MapCourses(MapCourseID) \ + ON UPDATE CASCADE ON DELETE CASCADE)"; + +char sql_times_insert[] = "\ +INSERT INTO Times (SteamID32, MapCourseID, Mode, Style, RunTime, Teleports) \ + SELECT %d, MapCourseID, %d, %d, %d, %d \ + FROM MapCourses \ + WHERE MapID=%d AND Course=%d"; + +char sql_times_delete[] = "\ +DELETE FROM Times \ + WHERE TimeID=%d"; + + + +// =====[ JUMPSTATS ]===== + +char sqlite_jumpstats_create[] = "\ +CREATE TABLE IF NOT EXISTS Jumpstats ( \ + JumpID INTEGER NOT NULL, \ + SteamID32 INTEGER NOT NULL, \ + JumpType INTEGER NOT NULL, \ + Mode INTEGER NOT NULL, \ + Distance INTEGER NOT NULL, \ + IsBlockJump INTEGER NOT NULL, \ + Block INTEGER NOT NULL, \ + Strafes INTEGER NOT NULL, \ + Sync INTEGER NOT NULL, \ + Pre INTEGER NOT NULL, \ + Max INTEGER NOT NULL, \ + Airtime INTEGER NOT NULL, \ + Created INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP, \ + CONSTRAINT PK_Jumpstats PRIMARY KEY (JumpID), \ + CONSTRAINT FK_Jumpstats_SteamID32 FOREIGN KEY (SteamID32) REFERENCES Players(SteamID32) \ + ON UPDATE CASCADE ON DELETE CASCADE)"; + +char mysql_jumpstats_create[] = "\ +CREATE TABLE IF NOT EXISTS Jumpstats ( \ + JumpID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, \ + SteamID32 INTEGER UNSIGNED NOT NULL, \ + JumpType TINYINT UNSIGNED NOT NULL, \ + Mode TINYINT UNSIGNED NOT NULL, \ + Distance INTEGER UNSIGNED NOT NULL, \ + IsBlockJump TINYINT UNSIGNED NOT NULL, \ + Block SMALLINT UNSIGNED NOT NULL, \ + Strafes INTEGER UNSIGNED NOT NULL, \ + Sync INTEGER UNSIGNED NOT NULL, \ + Pre INTEGER UNSIGNED NOT NULL, \ + Max INTEGER UNSIGNED NOT NULL, \ + Airtime INTEGER UNSIGNED NOT NULL, \ + Created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, \ + CONSTRAINT PK_Jumpstats PRIMARY KEY (JumpID), \ + CONSTRAINT FK_Jumpstats_SteamID32 FOREIGN KEY (SteamID32) REFERENCES Players(SteamID32) \ + ON UPDATE CASCADE ON DELETE CASCADE)"; + +char sql_jumpstats_insert[] = "\ +INSERT INTO Jumpstats (SteamID32, JumpType, Mode, Distance, IsBlockJump, Block, Strafes, Sync, Pre, Max, Airtime) \ + VALUES (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)"; + +char sql_jumpstats_update[] = "\ +UPDATE Jumpstats \ + SET \ + SteamID32=%d, \ + JumpType=%d, \ + Mode=%d, \ + Distance=%d, \ + IsBlockJump=%d, \ + Block=%d, \ + Strafes=%d, \ + Sync=%d, \ + Pre=%d, \ + Max=%d, \ + Airtime=%d \ + WHERE \ + JumpID=%d"; + +char sql_jumpstats_getrecord[] = "\ +SELECT JumpID, Distance, Block \ + FROM \ + Jumpstats \ + WHERE \ + SteamID32=%d AND \ + JumpType=%d AND \ + Mode=%d AND \ + IsBlockJump=%d \ + ORDER BY Block DESC, Distance DESC"; + +char sql_jumpstats_deleterecord[] = "\ +DELETE \ + FROM \ + Jumpstats \ + WHERE \ + JumpID = \ + ( SELECT * FROM ( \ + SELECT JumpID \ + FROM \ + Jumpstats \ + WHERE \ + SteamID32=%d AND \ + JumpType=%d AND \ + Mode=%d AND \ + IsBlockJump=%d \ + ORDER BY Block DESC, Distance DESC \ + LIMIT 1 \ + ) AS tmp \ + )"; + +char sql_jumpstats_deleteallrecords[] = "\ +DELETE \ + FROM \ + Jumpstats \ + WHERE \ + SteamID32 = %d;"; + +char sql_jumpstats_deletejump[] = "\ +DELETE \ + FROM \ + Jumpstats \ + WHERE \ + JumpID = %d;"; + +char sql_jumpstats_getpbs[] = "\ +SELECT MAX(Distance), Mode, JumpType \ + FROM \ + Jumpstats \ + WHERE \ + SteamID32=%d \ + GROUP BY \ + Mode, JumpType"; + +char sql_jumpstats_getblockpbs[] = "\ +SELECT MAX(js.Distance), js.Mode, js.JumpType, js.Block \ + FROM \ + Jumpstats js \ + INNER JOIN \ + ( \ + SELECT Mode, JumpType, MAX(BLOCK) Block \ + FROM \ + Jumpstats \ + WHERE \ + IsBlockJump=1 AND \ + SteamID32=%d \ + GROUP BY \ + Mode, JumpType \ + ) pb \ + ON \ + js.Mode=pb.Mode AND \ + js.JumpType=pb.JumpType AND \ + js.Block=pb.Block \ + WHERE \ + js.SteamID32=%d \ + GROUP BY \ + js.Mode, js.JumpType, js.Block"; + + + +// =====[ VB POSITIONS ]===== + +char sqlite_vbpos_create[] = "\ +CREATE TABLE IF NOT EXISTS VBPosition ( \ + SteamID32 INTEGER NOT NULL, \ + MapID INTEGER NOT NULL, \ + X REAL NOT NULL, \ + Y REAL NOT NULL, \ + Z REAL NOT NULL, \ + Course INTEGER NOT NULL, \ + IsStart INTEGER NOT NULL, \ + CONSTRAINT PK_VBPosition PRIMARY KEY (SteamID32, MapID, IsStart), \ + CONSTRAINT FK_VBPosition_SteamID32 FOREIGN KEY (SteamID32) REFERENCES Players(SteamID32), \ + CONSTRAINT FK_VBPosition_MapID FOREIGN KEY (MapID) REFERENCES Maps(MapID) \ + ON UPDATE CASCADE ON DELETE CASCADE)"; + +char mysql_vbpos_create[] = "\ +CREATE TABLE IF NOT EXISTS VBPosition ( \ + SteamID32 INTEGER UNSIGNED NOT NULL, \ + MapID INTEGER UNSIGNED NOT NULL, \ + X REAL NOT NULL, \ + Y REAL NOT NULL, \ + Z REAL NOT NULL, \ + Course INTEGER NOT NULL, \ + IsStart INTEGER NOT NULL, \ + CONSTRAINT PK_VBPosition PRIMARY KEY (SteamID32, MapID, IsStart), \ + CONSTRAINT FK_VBPosition_SteamID32 FOREIGN KEY (SteamID32) REFERENCES Players(SteamID32), \ + CONSTRAINT FK_VBPosition_MapID FOREIGN KEY (MapID) REFERENCES Maps(MapID) \ + ON UPDATE CASCADE ON DELETE CASCADE)"; + +char sql_vbpos_upsert[] = "\ +REPLACE INTO VBPosition (SteamID32, MapID, X, Y, Z, Course, IsStart) \ + VALUES (%d, %d, %f, %f, %f, %d, %d)"; + +char sql_vbpos_get[] = "\ +SELECT SteamID32, MapID, Course, IsStart, X, Y, Z \ + FROM \ + VBPosition \ + WHERE \ + SteamID32 = %d AND \ + MapID = %d"; + + + +// =====[ START POSITIONS ]===== + +char sqlite_startpos_create[] = "\ +CREATE TABLE IF NOT EXISTS StartPosition ( \ + SteamID32 INTEGER NOT NULL, \ + MapID INTEGER NOT NULL, \ + X REAL NOT NULL, \ + Y REAL NOT NULL, \ + Z REAL NOT NULL, \ + Angle0 REAL NOT NULL, \ + Angle1 REAL NOT NULL, \ + CONSTRAINT PK_StartPosition PRIMARY KEY (SteamID32, MapID), \ + CONSTRAINT FK_StartPosition_SteamID32 FOREIGN KEY (SteamID32) REFERENCES Players(SteamID32) \ + CONSTRAINT FK_StartPosition_MapID FOREIGN KEY (MapID) REFERENCES Maps(MapID) \ + ON UPDATE CASCADE ON DELETE CASCADE)"; + +char mysql_startpos_create[] = "\ +CREATE TABLE IF NOT EXISTS StartPosition ( \ + SteamID32 INTEGER UNSIGNED NOT NULL, \ + MapID INTEGER UNSIGNED NOT NULL, \ + X REAL NOT NULL, \ + Y REAL NOT NULL, \ + Z REAL NOT NULL, \ + Angle0 REAL NOT NULL, \ + Angle1 REAL NOT NULL, \ + CONSTRAINT PK_StartPosition PRIMARY KEY (SteamID32, MapID), \ + CONSTRAINT FK_StartPosition_SteamID32 FOREIGN KEY (SteamID32) REFERENCES Players(SteamID32), \ + CONSTRAINT FK_StartPosition_MapID FOREIGN KEY (MapID) REFERENCES Maps(MapID) \ + ON UPDATE CASCADE ON DELETE CASCADE)"; + +char sql_startpos_upsert[] = "\ +REPLACE INTO StartPosition (SteamID32, MapID, X, Y, Z, Angle0, Angle1) \ + VALUES (%d, %d, %f, %f, %f, %f, %f)"; + +char sql_startpos_get[] = "\ +SELECT SteamID32, MapID, X, Y, Z, Angle0, Angle1 \ + FROM \ + StartPosition \ + WHERE \ + SteamID32 = %d AND \ + MapID = %d"; diff --git a/sourcemod/scripting/gokz-localdb/db/timer_setup.sp b/sourcemod/scripting/gokz-localdb/db/timer_setup.sp new file mode 100644 index 0000000..b123eeb --- /dev/null +++ b/sourcemod/scripting/gokz-localdb/db/timer_setup.sp @@ -0,0 +1,167 @@ + +// ===== [ SAVE TIMER SETUP ] ===== + +void DB_SaveTimerSetup(int client) +{ + bool txnHasQuery = false; + int course; + float position[3], angles[3]; + + if (!IsValidClient(client)) + { + return; + } + + int steamid = GetSteamAccountID(client); + DataPack data = new DataPack(); + + data.WriteCell(client); + data.WriteCell(steamid); + + char query[1024]; + Transaction txn = SQL_CreateTransaction(); + + if (GOKZ_GetStartPosition(client, position, angles) == StartPositionType_Custom) + { + FormatEx(query, sizeof(query), sql_startpos_upsert, steamid, gI_DBCurrentMapID, position[0], position[1], position[2], angles[0], angles[1]); + txn.AddQuery(query); + txnHasQuery = true; + } + + course = GOKZ_GetVirtualButtonPosition(client, position, true); + if (course != -1) + { + FormatEx(query, sizeof(query), sql_vbpos_upsert, steamid, gI_DBCurrentMapID, position[0], position[1], position[2], course, 1); + txn.AddQuery(query); + txnHasQuery = true; + } + + course = GOKZ_GetVirtualButtonPosition(client, position, false); + if (course != -1) + { + FormatEx(query, sizeof(query), sql_vbpos_upsert, steamid, gI_DBCurrentMapID, position[0], position[1], position[2], course, 0); + txn.AddQuery(query); + txnHasQuery = true; + } + + if (txnHasQuery) + { + SQL_ExecuteTransaction(gH_DB, txn, DB_TxnSuccess_SaveTimerSetup, DB_TxnFailure_Generic_DataPack, data, DBPrio_Low); + } + else + { + delete data; + delete txn; + } +} + +public void DB_TxnSuccess_SaveTimerSetup(Handle db, DataPack data, int numQueries, Handle[] results, any[] queryData) +{ + data.Reset(); + int client = data.ReadCell(); + int steamid = data.ReadCell(); + delete data; + + if (!IsValidClient(client) || steamid != GetSteamAccountID(client)) + { + return; + } + + GOKZ_PrintToChat(client, true, "%t", "Timer Setup Saved"); +} + + + +// ===== [ LOAD TIMER SETUP ] ===== + +void DB_LoadTimerSetup(int client, bool doChatMessage = false) +{ + if (!IsValidClient(client)) + { + return; + } + + int steamid = GetSteamAccountID(client); + + DataPack data = new DataPack(); + data.WriteCell(client); + data.WriteCell(steamid); + data.WriteCell(doChatMessage); + + char query[1024]; + Transaction txn = SQL_CreateTransaction(); + + // Virtual Buttons + FormatEx(query, sizeof(query), sql_vbpos_get, steamid, gI_DBCurrentMapID); + txn.AddQuery(query); + + // Start Position + FormatEx(query, sizeof(query), sql_startpos_get, steamid, gI_DBCurrentMapID); + txn.AddQuery(query); + + SQL_ExecuteTransaction(gH_DB, txn, DB_TxnSuccess_LoadTimerSetup, DB_TxnFailure_Generic_DataPack, data, DBPrio_Normal); +} + +public void DB_TxnSuccess_LoadTimerSetup(Handle db, DataPack data, int numQueries, DBResultSet[] results, any[] queryData) +{ + data.Reset(); + int client = data.ReadCell(); + int steamid = data.ReadCell(); + bool doChatMessage = data.ReadCell(); + delete data; + + if (!IsValidClient(client) || steamid != GetSteamAccountID(client)) + { + return; + } + + int course; + bool isStart, vbSetup = false; + float position[3], angles[3]; + + if (results[0].RowCount > 0 && results[0].FetchRow()) + { + position[0] = results[0].FetchFloat(TimerSetupDB_GetVBPos_PositionX); + position[1] = results[0].FetchFloat(TimerSetupDB_GetVBPos_PositionY); + position[2] = results[0].FetchFloat(TimerSetupDB_GetVBPos_PositionZ); + course = results[0].FetchInt(TimerSetupDB_GetVBPos_Course); + isStart = results[0].FetchInt(TimerSetupDB_GetVBPos_IsStart) == 1; + + GOKZ_SetVirtualButtonPosition(client, position, course, isStart); + vbSetup = true; + } + + if (results[0].RowCount > 1 && results[0].FetchRow()) + { + position[0] = results[0].FetchFloat(TimerSetupDB_GetVBPos_PositionX); + position[1] = results[0].FetchFloat(TimerSetupDB_GetVBPos_PositionY); + position[2] = results[0].FetchFloat(TimerSetupDB_GetVBPos_PositionZ); + course = results[0].FetchInt(TimerSetupDB_GetVBPos_Course); + isStart = results[0].FetchInt(TimerSetupDB_GetVBPos_IsStart) == 1; + + GOKZ_SetVirtualButtonPosition(client, position, course, isStart); + vbSetup = true; + } + + if (results[1].RowCount > 0 && results[1].FetchRow()) + { + position[0] = results[1].FetchFloat(TimerSetupDB_GetStartPos_PositionX); + position[1] = results[1].FetchFloat(TimerSetupDB_GetStartPos_PositionY); + position[2] = results[1].FetchFloat(TimerSetupDB_GetStartPos_PositionZ); + angles[0] = results[1].FetchFloat(TimerSetupDB_GetStartPos_Angle0); + angles[1] = results[1].FetchFloat(TimerSetupDB_GetStartPos_Angle1); + angles[2] = 0.0; + + GOKZ_SetStartPosition(client, StartPositionType_Custom, position, angles); + } + + if (vbSetup) + { + GOKZ_LockVirtualButtons(client); + } + + if (doChatMessage) + { + GOKZ_PrintToChat(client, true, "%t", "Timer Setup Loaded"); + } +} diff --git a/sourcemod/scripting/gokz-localdb/options.sp b/sourcemod/scripting/gokz-localdb/options.sp new file mode 100644 index 0000000..2a8240a --- /dev/null +++ b/sourcemod/scripting/gokz-localdb/options.sp @@ -0,0 +1,90 @@ + +// =====[ OPTIONS ]===== + +void OnOptionsMenuReady_Options() +{ + RegisterOptions(); +} + +void RegisterOptions() +{ + for (DBOption option; option < DBOPTION_COUNT; option++) + { + GOKZ_RegisterOption(gC_DBOptionNames[option], gC_DBOptionDescriptions[option], + OptionType_Int, gI_DBOptionDefaultValues[option], 0, gI_DBOptionCounts[option] - 1); + } +} + + + +// =====[ OPTIONS MENU ]===== + +TopMenu gTM_Options; +TopMenuObject gTMO_CatGeneral; +TopMenuObject gTMO_ItemsDB[DBOPTION_COUNT]; + +void OnOptionsMenuReady_OptionsMenu(TopMenu topMenu) +{ + if (gTM_Options == topMenu) + { + return; + } + + gTM_Options = topMenu; + gTMO_CatGeneral = gTM_Options.FindCategory(GENERAL_OPTION_CATEGORY); + + for (int option = 0; option < view_as<int>(DBOPTION_COUNT); option++) + { + gTMO_ItemsDB[option] = gTM_Options.AddItem(gC_DBOptionNames[option], TopMenuHandler_DB, gTMO_CatGeneral); + } +} + +public void TopMenuHandler_DB(TopMenu topmenu, TopMenuAction action, TopMenuObject topobj_id, int param, char[] buffer, int maxlength) +{ + DBOption option = DBOPTION_COUNT; + for (int i = 0; i < view_as<int>(DBOPTION_COUNT); i++) + { + if (topobj_id == gTMO_ItemsDB[i]) + { + option = view_as<DBOption>(i); + break; + } + } + + if (option == DBOPTION_COUNT) + { + return; + } + + if (action == TopMenuAction_DisplayOption) + { + switch (option) + { + case DBOption_AutoLoadTimerSetup: + { + FormatToggleableOptionDisplay(param, DBOption_AutoLoadTimerSetup, buffer, maxlength); + } + } + } + else if (action == TopMenuAction_SelectOption) + { + GOKZ_CycleOption(param, gC_DBOptionNames[option]); + gTM_Options.Display(param, TopMenuPosition_LastCategory); + } +} + +void FormatToggleableOptionDisplay(int client, DBOption option, char[] buffer, int maxlength) +{ + if (GOKZ_GetOption(client, gC_DBOptionNames[option]) == DBOption_Disabled) + { + FormatEx(buffer, maxlength, "%T - %T", + gC_DBOptionPhrases[option], client, + "Options Menu - Disabled", client); + } + else + { + FormatEx(buffer, maxlength, "%T - %T", + gC_DBOptionPhrases[option], client, + "Options Menu - Enabled", client); + } +} |
