diff --git a/CHANGELOG.md b/CHANGELOG.md index ed1695a..bff1032 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ -## Release Notes +## Release Notes +## [2.5.9] + +### Added + +- Checkpoints difference for records is now sent to the Discord Webhook and shown in the embed. + ## [2.5.8] ### Fixed diff --git a/scripting/SurfTimer-discord.sp b/scripting/SurfTimer-discord.sp index f5df74d..7ecedf0 100644 --- a/scripting/SurfTimer-discord.sp +++ b/scripting/SurfTimer-discord.sp @@ -14,7 +14,7 @@ public Plugin myinfo = name = "SurfTimer-Discord", author = "Sarrus", description = "A module for SurfTimer-Official to send Discord Notifications when a new record is set.", - version = "2.5.8", + version = "2.5.9", url = "https://github.com/Sarrus1/SurfTimer-discord" }; @@ -73,6 +73,15 @@ enum struct TOP5_entry{ char szRuntimeDifference[32]; } +enum struct RunCheckpoints +{ + int cpNumber; + int style; + char runtime[32]; + char wrDifference[32]; + char pbDifference[32]; +} + WaitingFor g_iWaitingFor[MAXPLAYERS + 1]; public void OnPluginStart() @@ -206,16 +215,41 @@ public Action CommandDiscordTest(int client, int args) CReplyToCommand(0, "This command is only available in game."); return Plugin_Handled; } + ArrayList testArray; + testArray = new ArrayList(sizeof(RunCheckpoints)); + + RunCheckpoints cpEnum; + cpEnum.cpNumber = 1; + cpEnum.runtime = "01:00.00"; + cpEnum.pbDifference = "-00:00.00"; + cpEnum.wrDifference = "-00:00.00"; + cpEnum.style = 0; + testArray.PushArray(cpEnum, sizeof(RunCheckpoints)); + + cpEnum.cpNumber = 2; + cpEnum.runtime = "02:00.00"; + cpEnum.pbDifference = "-00:00.00"; + cpEnum.wrDifference = "-00:00.00"; + cpEnum.style = 0; + testArray.PushArray(cpEnum, sizeof(RunCheckpoints)); + + cpEnum.cpNumber = 3; + cpEnum.runtime = "03:00.00"; + cpEnum.pbDifference = "-00:00.00"; + cpEnum.wrDifference = "-00:00.00"; + cpEnum.style = 0; + testArray.PushArray(cpEnum, sizeof(RunCheckpoints)); + CReplyToCommand(client, "{blue}[SurfTimer-Discord] {green}Sending main record test message."); - surftimer_OnNewRecord(client, 0, "00:00:00", "-00:00:00", -1); + surftimer_OnNewRecord(client, 0, "00:00:00", "-00:00:00", -1, testArray); CReplyToCommand(client, "{blue}[SurfTimer-Discord] {green}Sending bonus record test message."); - surftimer_OnNewRecord(client, 0, "00:00:00", "-00:00:00", 1); + surftimer_OnNewRecord(client, 0, "00:00:00", "-00:00:00", 1, testArray); CReplyToCommand(client, "{blue}[SurfTimer-Discord] {green}Sending stage record test message."); surftimer_OnNewWRCP(client, 0, "00:00:00", "-00:00:00", 3, 0.0); CReplyToCommand(client, "{blue}[SurfTimer-Discord] {green}Sending {red}styled{green} bonus record test message."); - surftimer_OnNewRecord(client, 5, "00:00:00", "-00:00:00", 1); + surftimer_OnNewRecord(client, 5, "00:00:00", "-00:00:00", 1, testArray); CReplyToCommand(client, "{blue}[SurfTimer-Discord] {green}Sending {red}styled{green} main record test message."); - surftimer_OnNewRecord(client, 5, "00:00:00", "-00:00:00", -1); + surftimer_OnNewRecord(client, 5, "00:00:00", "-00:00:00", -1, testArray); CReplyToCommand(client, "{blue}[SurfTimer-Discord] {green}Sending {red}styled{green} stage record test message."); surftimer_OnNewWRCP(client, 5, "00:00:00", "-00:00:00", 3, 0.0); @@ -245,7 +279,6 @@ public Action CommandDiscordTest(int client, int args) mapchallenge_OnChallengeEnd(client, "surf_beginner", 0, 420, "Mon Jan 1 00:00:00 1969", "Thu Aug 23 14:55:02 2001", szTop5, 666); } - return Plugin_Handled; } @@ -490,20 +523,41 @@ public void OnMapStart() GetConVarString(g_cvSteamWebAPIKey, g_szApiKey, sizeof g_szApiKey); } -public void surftimer_OnNewRecord(int client, int style, char[] time, char[] timeDif, int bonusGroup) +public void surftimer_OnNewRecord(int client, int style, char[] time, char[] timeDif, int bonusGroup, ArrayList checkpoints) { + char cpsFinalString[1100]; + if(checkpoints != null && checkpoints.Length > 0) + { + RunCheckpoints temp; + for(int i = 0; i <= checkpoints.Length-1; i++) + { + checkpoints.GetArray(i, temp, sizeof(temp)); + if(i == 0) + { + Format(cpsFinalString, sizeof(cpsFinalString), "%i. WR: %s | PB: %s | %s", temp.cpNumber, temp.wrDifference, temp.pbDifference, temp.runtime); + } + else + { + Format(cpsFinalString, sizeof(cpsFinalString), "%s\n%i. WR: %s | PB: %s | %s", cpsFinalString, temp.cpNumber, temp.wrDifference, temp.pbDifference, temp.runtime); + } + } + ReplaceString(cpsFinalString, sizeof(cpsFinalString), "00:0", ""); + ReplaceString(cpsFinalString, sizeof(cpsFinalString), "00:", ""); + Format(cpsFinalString, sizeof(cpsFinalString), "```fix\n%s\n```", cpsFinalString); + } + if (strncmp(g_szApiKey, "", 1) != 0) - GetProfilePictureURL(client, style, time, timeDif, bonusGroup, -1); + GetProfilePictureURL(client, style, time, timeDif, bonusGroup, -1, cpsFinalString); else - sendDiscordAnnouncement(client, style, time, timeDif, bonusGroup, -1); + sendDiscordAnnouncement(client, style, time, timeDif, bonusGroup, -1, cpsFinalString); } public void surftimer_OnNewWRCP(int client, int style, char[] time, char[] timeDif, int stage, float fRunTime) { if (strncmp(g_szApiKey, "", 1) != 0) - GetProfilePictureURL(client, style, time, timeDif, -1, stage); + GetProfilePictureURL(client, style, time, timeDif, -1, stage, ""); else - sendDiscordAnnouncement(client, style, time, timeDif, -1, stage); + sendDiscordAnnouncement(client, style, time, timeDif, -1, stage, ""); } public void mapchallenge_OnNewChallenge(int client, char szMapName[32], int style, int points, char szInitial_Timestamp[32], char szFinal_Timestamp[32]){ @@ -727,7 +781,7 @@ public void mapchallenge_OnChallengeEnd(int client, char szMapName[32], int styl delete hook; } -stock void sendDiscordAnnouncement(int client, int style, char[] szTime, char[] szTimeDif, int bonusGroup, int stage) +stock void sendDiscordAnnouncement(int client, int style, char[] szTime, char[] szTimeDif, int bonusGroup, int stage, char[] checkpoints) { // Get the WebHook char webhook[1024], webhookName[1024]; @@ -825,6 +879,19 @@ stock void sendDiscordAnnouncement(int client, int style, char[] szTime, char[] field = new EmbedField("Map Tier", MapTier, true); embed.AddField(field); + /* Add checkpoints to an EmbedField - Limitations https://discord.com/developers/docs/resources/channel#embed-object-embed-field-structure */ + char tempCps[1100]; + StrCat(tempCps, sizeof(tempCps), checkpoints); + ReplaceString(tempCps, sizeof(tempCps), "\n", ""); + ReplaceString(tempCps, sizeof(tempCps), "```fix", ""); + ReplaceString(tempCps, sizeof(tempCps), "```", ""); + ReplaceString(tempCps, sizeof(tempCps), " ", ""); + if(strlen(checkpoints) > 0 && strlen(tempCps) < 1024 && bonusGroup == -1 && stage < 1) + { + field = new EmbedField("Checkpoints", checkpoints, true); + embed.AddField(field); + } + char szUrlMain[1024]; GetConVarString(g_cvMainUrlRoot, szUrlMain, 1024); StrCat(szUrlMain, sizeof szUrlMain, g_szCurrentMap); @@ -905,7 +972,7 @@ stock void sendDiscordAnnouncement(int client, int style, char[] szTime, char[] } } -stock void GetProfilePictureURL(int client, int style, char[] time, char[] timeDif, int bonusGroup, int stage) +stock void GetProfilePictureURL(int client, int style, char[] time, char[] timeDif, int bonusGroup, int stage, char[] checkpoints) { DataPack pack = new DataPack(); pack.WriteCell(client); @@ -914,6 +981,7 @@ stock void GetProfilePictureURL(int client, int style, char[] time, char[] timeD pack.WriteString(timeDif); pack.WriteCell(bonusGroup); pack.WriteCell(stage); + pack.WriteString(checkpoints); pack.Reset(); char szRequestBuffer[1024], szSteamID[64]; @@ -938,6 +1006,8 @@ stock void OnResponseReceived(HTTPResponse response, DataPack pack) ReadPackString(pack, szTimeDif, sizeof szTimeDif); int bonusGroup = pack.ReadCell(); int stage = pack.ReadCell(); + char checkpoints[1100]; + ReadPackString(pack, checkpoints, sizeof(checkpoints)); if (response.Status != HTTPStatus_OK) return; @@ -958,7 +1028,7 @@ stock void OnResponseReceived(HTTPResponse response, DataPack pack) delete Response; delete players; delete player; - sendDiscordAnnouncement(client, style, szTime, szTimeDif, bonusGroup, stage); + sendDiscordAnnouncement(client, style, szTime, szTimeDif, bonusGroup, stage, checkpoints); } stock void RemoveWorkshop(char[] szMapName, int len) @@ -994,18 +1064,25 @@ public void OnWebHookExecuted(HTTPResponse response, int client) { #if defined DEBUG PrintToServer("Processed client n°%d's webhook, status %d", client, response.Status); - if (response.Status != HTTPStatus_NoContent) + if (response.Status != HTTPStatus_OK) { PrintToServer("An error has occured while sending the webhook."); JSONObject objects = view_as(response.Data); char responseMsg[1000]; if (objects.GetString("message", responseMsg, sizeof(responseMsg))) { - PrintToServer("Discord API reply message: %s", responseMsg); - int responseCode = objects.GetInt("code"); - PrintToServer("Discord API reply code: %i", responseCode); + PrintToServer("-- Discord API reply message: %s", responseMsg); + if (StrContains(responseMsg, "rate limited") > -1) + { + float retry = objects.GetFloat("retry_after"); + PrintToServer("-- You are being rate limited, please try again after %f", retry); + } + else + { + int responseCode = objects.GetInt("code"); + PrintToServer("-- Discord API reply code: %i", responseCode); + } } - delete objects; return; } diff --git a/scripting/include/surftimer.inc b/scripting/include/surftimer.inc index a83677e..a613802 100644 --- a/scripting/include/surftimer.inc +++ b/scripting/include/surftimer.inc @@ -101,11 +101,34 @@ native void surftimer_GetPlayerNameColored(int client, char[] str); /** * Retrieves the current map's WR holder and the associated time. * - * @param name String to store the WR holder's name. - * @param time String to store the WR holder's time. + * @param szname String to store the WR holder's name. + * @param sztime String to store the WR holder's time. + * @param time float to store the WR holder's time. * @return The number of players who have finished the current map. */ -native int surftimer_GetMapData(char[] name, char[] time); +native int surftimer_GetMapData(char[] szname, char[] sztime, float& time); + +/** + * Retrieves the wr/pb info regarding the current bonus a players is on + * + * @param client The client's ID. + * @param szWRname String to store the Bonus WR holder's name. + * @param WRtime float to store the Bonus WR holder's time. + * @param pbtime float to store the Bonus PB holder's time. + * @return The number of players who have finished the current bonus. + */ +native int surftimer_GetBonusData(int client, char[] szWRname, float& WRtime, float& PBtime); + +/** + * Retrieves the current map's stage WR holder and the associated times. + * + * @param client The client's ID. + * @param szWRname String to store the stage WR holder's name. + * @param WRtime float to store the stage WR holder's time. + * @param pbtime float to store the stage PB holder's time. + * @return The number of players who have finished the current stage. + */ +native int surftimer_GetStageData(int client, char[] szWRname, float& WRtime, float& PBtime); /** * Retrieves the client's data. @@ -117,7 +140,7 @@ native int surftimer_GetMapData(char[] name, char[] time); * @param countryCode String to store the client's countryCode. * @param continentCode String to store the client's continentCode. */ -native void surftimer_GetPlayerData(int& client, char[] time, int& rank, char[] country, char countryCode[3], char continentCode[3]); +native void surftimer_GetPlayerData(int& client, float& time, int& rank, char[] country, char countryCode[3], char continentCode[3]); /** * Retrieves the client's current info. @@ -130,6 +153,22 @@ native void surftimer_GetPlayerData(int& client, char[] time, int& rank, char[] */ native void surftimer_GetPlayerInfo(int& client, int& iWrcpTimer, int& iPracMode, int& iStage, int& iBonus); +/** + * Retrieves the client's current sync. + * + * @param client The client's ID. + * @return Client's sync. + */ +native float surftimer_GetClientSync(int client); + +/** + * Retrieves the client's current style. + * + * @param client The client's ID. + * @return Current client's style. + */ +native int surftimer_GetClientStyle(int client); + /** * Teleport a client safely, without triggering end touches * and sets the client's location correctly. @@ -145,21 +184,63 @@ native bool surftimer_SafeTeleport(int client, float fDestination[3], float fAng /* FORWARDS */ +/** + * Called when a client map timer starts + * + * @param client Index of the client. + * @param style Style the client is currently in. + */ +forward void surftimer_OnClientTimerStart(int client, int style); + +/** + * Called when a client WRCP timer starts + * + * @param client Index of the client. + * @param style Style the client is currently in. + * @param stage Stage number the client is currently running. + */ +forward void surftimer_OnClientWRCPTimerStart(int client, int style, int stage); + +/** + * Called when a client Bonus timer starts + * + * @param client Index of the client. + * @param style Style the client is currently in. + * @param bonus Bonus number the client is currently running. + */ +forward void surftimer_OnClientBonusTimerStart(int client, int style, int bonus); + +/** + * Called when a client enters Practice mode + * + * @param client Index of the client. + * @param style Style the client is currently in. + * @param locNum Number of the saveloc the client teleported to. + */ +forward void surftimer_OnClientPracTimerStart(int client, int style, int locNum); + /** * Called when a client finishes a map. * * @param client The client's ID. * @return Plugin_Handled, to stop the client from searching. */ -forward Action surftimer_OnMapFinished(int client, float fRunTime, char sRunTime[54], int rank, int total, int style); +forward Action surftimer_OnMapFinished(int client, float fRunTime, char sRunTime[54], float PBDiff, float WRDiff, int rank, int total, int style, ArrayList cps); /** * Called when a player reaches a checkpoint zone or a stage. * * @param client The client's ID. - * @return Plugin_Handled, to stop the client from searching. + * @param fRunTime Run time of the client to the checkpoint in float + * @param sRunTime Run time of the client to the checkpoint + * @param fPbCp Personal best of the client to the checkpoint in float + * @param sPbDiff Personal best difference of the client with current run time + * @param fSrCp Record checkpoint time in float + * @param sSrDiff Record checkpoint time difference of the client with current run time + * @param iCheckpoint Checkpoint number that was just passed + * @return Plugin_Handled, to stop the client from searching. */ -forward Action surftimer_OnCheckpoint(int client, float fRunTime, char sRunTime[54], float fPbCp, char sPbDiff[16], char fSrCp, char sSrDiff[16]); +forward Action surftimer_OnCheckpoint(int client, float fRunTime, char sRunTime[54], float fPbCp, char sPbDiff[16], float fSrCp, char sSrDiff[16], int iCheckpoint); /** @@ -168,7 +249,7 @@ forward Action surftimer_OnCheckpoint(int client, float fRunTime, char sRunTime[ * @param client The client's ID. * @return Plugin_Handled, to stop the player from searching. */ -forward Action surftimer_OnBonusFinished(int client, float fRunTime, char sRunTime[54], int rank, int total, int bonusid); +forward Action surftimer_OnBonusFinished(int client, float fRunTime, char sRunTime[54], float fPBDiff, float fSRDiff, int rank, int total, int bonusid, int style); /** * Called when a client finishes a map in practice mode @@ -185,9 +266,10 @@ forward Action surftimer_OnPracticeFinished(int client, float fRunTime, char sRu * @param style Style index. * @param time Time set by the player. * @param timeDif Time difference with the former record. - * @param bonusGroup Group of the bonus. -1 if the record isn't a bonus. + * @param bonusGroup Group of the bonus. -1 if the record isn't a bonus. + * @param checkpoints Array with checkpoint differences for the run. */ -forward void surftimer_OnNewRecord(int client, int style, char[] time, char[] timeDif, int bonusGroup); +forward void surftimer_OnNewRecord(int client, int style, char[] time, char[] timeDif, int bonusGroup, ArrayList cps); /** * Called when a client sets a new WRCP @@ -201,6 +283,27 @@ forward void surftimer_OnNewRecord(int client, int style, char[] time, char[] ti */ forward void surftimer_OnNewWRCP(int client, int style, char[] time, char[] timeDif, int stage, float fRunTime); +/** + * Called when a client sets a new WRCP + * + * @param client The client's ID. + * @param style Style index. + * @param time Time set by the player. + * @param timeDif Time difference with the former record. + * @param stage The id of the stage of the WRCP. + * @param fRunTime Run time for the WRCP in float. + * @param fClientRunTime Run time for the client of the current stage in float. + */ +forward void surftimer_OnStageFinished(int client, int style, char[] time, char[] timeDif, int stage, float fRunTime, float fClientRunTime); + +/** + * Converts steamid2 (STEAM_X:Y:Z) to the accountid which will returned. + */ +stock int SteamId2ToAccountId(const char[] steamid) +{ + return (StringToInt(steamid[10]) * 2) + (steamid[8] == '1' ? 1 : 0); +} + public SharedPlugin:__pl_surftimer = { name = "surftimer", @@ -223,4 +326,5 @@ public __pl_surftimer_SetNTVOptional() MarkNativeAsOptional("surftimer_GetServerRank"); MarkNativeAsOptional("surftimer_SafeTeleport"); MarkNativeAsOptional("surftimer_OnNewRecord"); + MarkNativeAsOptional("surftimer_OnStageFinished"); }