diff --git a/AutoReplayUploader/AutoReplayUploader.vcxproj b/AutoReplayUploader/AutoReplayUploader.vcxproj index a01b2f2..3fc4fab 100644 --- a/AutoReplayUploader/AutoReplayUploader.vcxproj +++ b/AutoReplayUploader/AutoReplayUploader.vcxproj @@ -82,12 +82,13 @@ true true true - K:\bakkesmod\BakkesMod-rewrite\BakkesMod Rewrite;K:\bakkesmod\AutoReplayUploader\Uploader;..\Uploader;%(AdditionalIncludeDirectories) - _WINDLL;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;TOAST + K:\bakkesmod\BakkesMod-rewrite\PluginSDK;K:\bakkesmod\AutoReplayUploader\Uploader;..\Uploader;%(AdditionalIncludeDirectories) + _WINDLL;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;TOAST;WIN32_MEAN_AND_LEAN; MultiThreaded + stdcpp17 - False + true true true BakkesMod.lib;%(AdditionalDependencies) diff --git a/AutoReplayUploader/AutoReplayUploaderPlugin.cpp b/AutoReplayUploader/AutoReplayUploaderPlugin.cpp index 5801107..d49373b 100644 --- a/AutoReplayUploader/AutoReplayUploaderPlugin.cpp +++ b/AutoReplayUploader/AutoReplayUploaderPlugin.cpp @@ -140,8 +140,8 @@ void AutoReplayUploaderPlugin::onLoad() // Initialize notification plugin assets #ifdef TOAST - gameWrapper->LoadToastTexture("calculated_logo", "./bakkesmod/data/assets/calculated_logo.tga"); - gameWrapper->LoadToastTexture("ballchasing_logo", "./bakkesmod/data/assets/ballchasing_logo.tga"); + gameWrapper->LoadToastTexture("calculated_logo", gameWrapper->FixRelativePath("./bakkesmod/data/assets/calculated_logo.tga")); + gameWrapper->LoadToastTexture("ballchasing_logo", gameWrapper->FixRelativePath("./bakkesmod/data/assets/ballchasing_logo.tga")); #endif } @@ -199,10 +199,10 @@ void AutoReplayUploaderPlugin::InitializeVariables() // Path to export replays to cvarManager->registerCvar(CVAR_REPLAY_EXPORT, "0", "Save all replay files to export filepath above.", true, true, 0, true, 1).bindTo(saveReplay); - cvarManager->registerCvar(CVAR_REPLAY_EXPORT_PATH, DEAULT_EXPORT_PATH, "Path to export replays to.").bindTo(exportPath); + cvarManager->registerCvar(CVAR_REPLAY_EXPORT_PATH, DEFAULT_EXPORT_PATH, "Path to export replays to.").bindTo(exportPath); cvarManager->getCvar(CVAR_REPLAY_EXPORT_PATH).addOnValueChanged([this](string oldVal, CVarWrapper cvar) { - if (SanitizeExportPath(exportPath, DEAULT_EXPORT_PATH)) + if (SanitizeExportPath(exportPath, DEFAULT_EXPORT_PATH)) { cvarManager->getCvar(CVAR_REPLAY_EXPORT_PATH).setValue(*exportPath); } @@ -261,41 +261,46 @@ void AutoReplayUploaderPlugin::OnGameComplete(ServerWrapper caller, void * param // If we have a template for the replay name then set the replay name based off that template else use default template string replayName = SetReplayName(caller, soccarReplay); - + cvarManager->log("Exporting replay!"); // Export the replay to a file for upload - string replayPath = ExportReplay(soccarReplay, replayName); - - // If we are saving this with event Function TAGame.GameEvent_Soccar_TA.Destroyed - // the steamID might not be available. Using prestored steamID - string playerSteamID = to_string(gameWrapper->GetSteamID()); - if (playerSteamID.length() < 1) { - playerSteamID = backupPlayerSteamID; - cvarManager->log("Using backup steamId to upload: " + playerSteamID); + std::filesystem::path replayPath = ExportReplay(soccarReplay, replayName); + if (!std::filesystem::exists(replayPath) || std::filesystem::is_directory(replayPath)) + { + cvarManager->log("Failed exporting replay to " + replayPath.string()); + return; + } + + + UniqueIDWrapper playerSteamID = gameWrapper->GetUniqueID(); + std::string uploadID = std::to_string(playerSteamID.GetUID()); + if (uploadID.size() < 1) { + uploadID = playerSteamID.str(); + cvarManager->log("Using backup steamId to upload: " + uploadID); } else { - cvarManager->log("Using steamId to upload: " + playerSteamID); + cvarManager->log("Using steamId to upload: " + uploadID); } // Upload replay if (*uploadToCalculated) { - calculated->UploadReplay(replayPath, playerSteamID); + calculated->UploadReplay(gameWrapper->GetBakkesModPath(), replayPath, uploadID); } if (*uploadToBallchasing) { - ballchasing->UploadReplay(replayPath); + ballchasing->UploadReplay(gameWrapper->GetBakkesModPath(), replayPath); } // If we aren't saving the replay remove it after we've uploaded if (!(*saveReplay)) { - cvarManager->log("Removing replay file: " + replayPath); - remove(replayPath.c_str()); + cvarManager->log("Removing replay file: " + replayPath.string()); + std::filesystem::remove(replayPath); } #ifdef TOAST else if(*showNotifications) { - bool exported = file_exists(replayPath); - string msg = exported ? "Exported replay to: " + replayPath : "Failed to export replay to: " + replayPath; + bool exported = std::filesystem::exists(replayPath); + string msg = exported ? "Exported replay to: " + replayPath.string() : "Failed to export replay to: " + replayPath.string(); gameWrapper->Toast("Autoreplayuploader", msg, "default", 3.5f, exported ? ToastType_OK : ToastType_Error); } #endif @@ -307,7 +312,9 @@ Player ConstructPlayer(PriWrapper wrapper) if (!wrapper.IsNull()) { p.Name = wrapper.GetPlayerName().ToString(); - p.UniqueId = wrapper.GetUniqueId().ID; + p.UniqueId = wrapper.GetUniqueIdWrapper().GetUID(); + p.EpicID = wrapper.GetUniqueIdWrapper().GetEpicAccountID(); + p.Team = wrapper.GetTeamNum(); p.Score = wrapper.GetScore(); p.Goals = wrapper.GetMatchGoals(); @@ -407,6 +414,7 @@ string AutoReplayUploaderPlugin::SetReplayName(ServerWrapper& server, ReplaySocc cvarManager->log("Using prerecorder username for replay: " + backupMatchForReplayName.PrimaryPlayer.Name); match.PrimaryPlayer.Name = backupMatchForReplayName.PrimaryPlayer.Name; match.PrimaryPlayer.UniqueId = backupMatchForReplayName.PrimaryPlayer.UniqueId; + match.PrimaryPlayer.EpicID = backupMatchForReplayName.PrimaryPlayer.EpicID; match.PrimaryPlayer.Team = backupMatchForReplayName.PrimaryPlayer.Team; } @@ -420,6 +428,20 @@ string AutoReplayUploaderPlugin::SetReplayName(ServerWrapper& server, ReplaySocc // Get Team scores match.Team0Score = soccarReplay.GetTeam0Score(); match.Team1Score = soccarReplay.GetTeam1Score(); + + if (auto matchWinner = server.GetMatchWinner(); !matchWinner.IsNull()) + { + match.WinningTeam = matchWinner.GetTeamIndex(); + } + else if (auto gameWinner = server.GetGameWinner(); !gameWinner.IsNull()) + { + match.WinningTeam = gameWinner.GetTeamIndex(); + } + else + { + match.WinningTeam = match.Team0Score > match.Team1Score ? 0 : 1; + } + // Get current Sequence number auto seq = *templateSequence; @@ -440,30 +462,42 @@ string AutoReplayUploaderPlugin::SetReplayName(ServerWrapper& server, ReplaySocc return replayName; } -string AutoReplayUploaderPlugin::ExportReplay(ReplaySoccarWrapper& soccarReplay, string replayName) +std::filesystem::path AutoReplayUploaderPlugin::ExportReplay(ReplaySoccarWrapper& soccarReplay, string replayName) { - string replayPath = CalculateReplayPath(*exportPath, replayName); - + std::filesystem::path replayPath = CalculateReplayPath(*exportPath, replayName); + cvarManager->log("Calculated replay path: " + replayPath.string()); + if (replayPath.is_relative()) + { + cvarManager->log("Path is a relative path, fixing it!"); + replayPath = gameWrapper->FixRelativePath(replayPath); + cvarManager->log("Fixed path: " + replayPath.string()); + } // Remove file if it already exists - if (file_exists(replayPath)) + if (std::filesystem::exists(replayPath)) { - cvarManager->log("Removing duplicate replay file: " + replayPath); - remove(replayPath.c_str()); + cvarManager->log("Removing duplicate replay file: " + replayPath.string()); + if (std::filesystem::is_directory(replayPath)) + { + cvarManager->log("Calculated export path is somehow a directory. " + replayPath.string()); + return replayPath / "err.replay"; + } + std::filesystem::remove(replayPath); + cvarManager->log("File removed."); } // Export Replay soccarReplay.ExportReplay(replayPath); - cvarManager->log("Exported replay to: " + replayPath); + cvarManager->log("Exported replay to: " + replayPath.string()); // Check to see if replay exists, if not then export to default path - if (!file_exists(replayPath)) + if (!std::filesystem::exists(replayPath)) { - cvarManager->log("Export failed to path: " + replayPath + " exporting to default path."); - replayPath = string(DEAULT_EXPORT_PATH) + "autosaved.replay"; + cvarManager->log("Export failed to path: " + replayPath.string() + " exporting to default path."); + replayPath = gameWrapper->GetDataFolder() / "autosaved.replay"; soccarReplay.ExportReplay(replayPath); - cvarManager->log("Exported replay to: " + replayPath); + cvarManager->log("Exported replay to: " + replayPath.string()); } return replayPath; diff --git a/AutoReplayUploader/AutoReplayUploaderPlugin.h b/AutoReplayUploader/AutoReplayUploaderPlugin.h index 0c238b2..b9d897c 100644 --- a/AutoReplayUploader/AutoReplayUploaderPlugin.h +++ b/AutoReplayUploader/AutoReplayUploaderPlugin.h @@ -7,11 +7,11 @@ #include "Ballchasing.h" #include "Calculated.h" -#pragma comment( lib, "bakkesmod.lib" ) +#pragma comment( lib, "pluginsdk.lib" ) using namespace std; -#define DEAULT_EXPORT_PATH "./bakkesmod/data/" +#define DEFAULT_EXPORT_PATH "./bakkesmod/data/" #define DEFAULT_REPLAY_NAME_TEMPLATE "{YEAR}-{MONTH}-{DAY}.{HOUR}.{MIN} {PLAYER} {MODE} {WINLOSS}" // TODO: uncomment or remove #ifdef's when new Bakkes mod API becomes available that has Toast notifications @@ -34,13 +34,13 @@ class AutoReplayUploaderPlugin : public BakkesMod::Plugin::BakkesModPlugin // Export replay variables shared_ptr saveReplay = make_shared(false); - shared_ptr exportPath = make_shared(DEAULT_EXPORT_PATH); + shared_ptr exportPath = make_shared(DEFAULT_EXPORT_PATH); // Initializes all variables from bakkes mod settings menu void InitializeVariables(); string SetReplayName(ServerWrapper& server, ReplaySoccarWrapper& soccarReplay); - string ExportReplay(ReplaySoccarWrapper& soccarReplay, string replayName); + std::filesystem::path ExportReplay(ReplaySoccarWrapper& soccarReplay, string replayName); public: virtual void onLoad(); diff --git a/Uploader/Ballchasing.cpp b/Uploader/Ballchasing.cpp index 80f28a1..139cfd8 100644 --- a/Uploader/Ballchasing.cpp +++ b/Uploader/Ballchasing.cpp @@ -31,7 +31,7 @@ void BallchasingRequestComplete(PostFileRequest* ctx) } ballchasing->NotifyUploadResult(ballchasing->Client, (ctx->Status >= 200 && ctx->Status < 300)); - DeleteFile(ctx->FilePath.c_str()); + std::filesystem::remove(ctx->FilePath); delete ctx; } @@ -50,38 +50,63 @@ void BallchasingRequestComplete(GetRequest* ctx) } } -void Ballchasing::UploadReplay(string replayPath) +void Ballchasing::UploadReplay(std::filesystem::path startPath, std::filesystem::path replayPath) { if (UserAgent.empty() || authKey->empty() || visibility->empty() || replayPath.empty()) { Log(Client, "Ballchasing::UploadReplay Parameters were empty."); Log(Client, "UserAgent: " + UserAgent); - Log(Client, "ReplayPath: " + replayPath); + Log(Client, "ReplayPath: " + replayPath.string()); Log(Client, "AuthKey: " + *authKey); Log(Client, "Visibility: " + *visibility); return; } + try + { + if (!std::filesystem::exists(replayPath)) + { + Log(Client, "Replay path doesn't exist? " + replayPath.string()); + return; + } + std::filesystem::path destPath = startPath / "data/ballchasing/temp.replay"; + std::filesystem::path tempFolder = startPath / "data/ballchasing/"; + if (!std::filesystem::exists(tempFolder)) + { + std::filesystem::create_directory(tempFolder); + } + if (std::filesystem::exists(destPath)) + { + Log(Client, "Destination path exists, removing " + destPath.string()); + std::filesystem::remove(destPath); + } - string destPath = "./bakkesmod/data/ballchasing/temp.replay"; - CreateDirectory("./bakkesmod/data/ballchasing", NULL); - bool resultOfCopy = CopyFile(replayPath.c_str(), destPath.c_str(), FALSE); + std::filesystem::copy(replayPath, destPath); - Log(Client, "ReplayPath: " + replayPath); - Log(Client, "DestPath: " + destPath); - Log(Client, "File copy success: " + std::string(resultOfCopy ? "true" : "false")); + Log(Client, "ReplayPath: " + replayPath.string()); + Log(Client, "DestPath: " + destPath.string()); + Log(Client, "File copy success: " + std::string(std::filesystem::exists(destPath) ? "true" : "false")); - PostFileRequest *request = new PostFileRequest(); - request->Url = AppendGetParams("https://ballchasing.com/api/v2/upload", { {"visibility", *visibility} }); - request->FilePath = destPath; - request->ParamName = "file"; - request->Headers.push_back("Authorization: " + *authKey); - request->Headers.push_back("UserAgent: " + UserAgent); - request->RequestComplete = &BallchasingRequestComplete; - request->RequestId = 1; - request->Requester = this; - request->Message = ""; + PostFileRequest* request = new PostFileRequest(); + request->Url = AppendGetParams("https://ballchasing.com/api/v2/upload", { {"visibility", *visibility} }); + request->FilePath = destPath; + request->ParamName = "file"; + request->Headers.push_back("Authorization: " + *authKey); + request->Headers.push_back("UserAgent: " + UserAgent); + request->RequestComplete = &BallchasingRequestComplete; + request->RequestId = 1; + request->Requester = this; + request->Message = ""; - PostFileAsync(request); + PostFileAsync(request); + } + catch (std::exception e) + { + Log(Client, "AutoreplayUploader ERR: " + std::string(e.what())); + } + catch (...) + { + Log(Client, "BAD AutoreplayUploader ERR!"); + } } /** diff --git a/Uploader/Ballchasing.h b/Uploader/Ballchasing.h index a08f5c5..e5c668a 100644 --- a/Uploader/Ballchasing.h +++ b/Uploader/Ballchasing.h @@ -1,7 +1,7 @@ #pragma once #include - +#include using namespace std; class Ballchasing @@ -22,7 +22,7 @@ class Ballchasing void(*NotifyUploadResult)(void* object, bool result); void* Client; - void UploadReplay(string replayPath); + void UploadReplay(std::filesystem::path startPath, std::filesystem::path replayPath); void TestAuthKey(); }; diff --git a/Uploader/Calculated.cpp b/Uploader/Calculated.cpp index cddf07e..6382769 100644 --- a/Uploader/Calculated.cpp +++ b/Uploader/Calculated.cpp @@ -29,7 +29,7 @@ void CalculatedRequestComplete(PostFileRequest* ctx) } calculated->NotifyUploadResult(calculated->Client, (ctx->Status >= 200 && ctx->Status < 300)); - DeleteFile(ctx->FilePath.c_str()); + std::filesystem::remove(ctx->FilePath); delete ctx; } @@ -37,37 +37,65 @@ void CalculatedRequestComplete(PostFileRequest* ctx) /** * Posts the replay file to Calculated.gg */ -void Calculated::UploadReplay(string replayPath, string playerId) +void Calculated::UploadReplay(std::filesystem::path startPath, std::filesystem::path replayPath, string playerId) { if (UserAgent.empty() || replayPath.empty()) { Log(Client, "Calculated::UploadReplay Parameters were empty."); Log(Client, "UserAgent: " + UserAgent); - Log(Client, "ReplayPath: " + replayPath); + Log(Client, "ReplayPath: " + replayPath.string()); return; } string path = AppendGetParams(CALCULATED_ENDPOINT_URL, { {"player_id", playerId}, {"visibility", *visibility} }); + Log(Client, "ReplayPath: " + replayPath.string()); + + try + { + if (!std::filesystem::exists(replayPath)) + { + Log(Client, "Replay path doesn't exist? " + replayPath.string()); + return; + } + std::filesystem::path destPath = startPath / "data/calculated/temp.replay"; + Log(Client, "DestPath: " + destPath.string()); + std::filesystem::path tempFolder = startPath / "data/calculated/"; + if (!std::filesystem::exists(tempFolder)) + { + std::filesystem::create_directory(tempFolder); + } + + if (std::filesystem::exists(destPath)) + { + Log(Client, "Destination path exists, removing " + destPath.string()); + std::filesystem::remove(destPath); + } + + std::filesystem::copy(replayPath, destPath); + + + Log(Client, "File copy success: " + std::string(std::filesystem::exists(destPath) ? "true" : "false")); + + PostFileRequest *request = new PostFileRequest(); + request->Url = path; + request->FilePath = destPath; + request->ParamName = "replays"; + request->Headers.push_back("UserAgent: " + UserAgent); + request->RequestComplete = &CalculatedRequestComplete; + request->RequestId = 1; + request->Requester = this; + request->Message = ""; - string destPath = "./bakkesmod/data/calculated/temp.replay"; - CreateDirectory("./bakkesmod/data/calculated", NULL); - bool resultOfCopy = CopyFile(replayPath.c_str(), destPath.c_str(), FALSE); - - Log(Client, "ReplayPath: " + replayPath); - Log(Client, "DestPath: " + destPath); - Log(Client, "File copy success: " + std::string(resultOfCopy ? "true" : "false")); - - PostFileRequest *request = new PostFileRequest(); - request->Url = path; - request->FilePath = destPath; - request->ParamName = "replays"; - request->Headers.push_back("UserAgent: " + UserAgent); - request->RequestComplete = &CalculatedRequestComplete; - request->RequestId = 1; - request->Requester = this; - request->Message = ""; - - PostFileAsync(request); + PostFileAsync(request); + } + catch (std::exception e) + { + Log(Client, "AutoreplayUploader ERR: " + std::string(e.what())); + } + catch (...) + { + Log(Client, "BAD AutoreplayUploader ERR!"); + } } Calculated::~Calculated() diff --git a/Uploader/Calculated.h b/Uploader/Calculated.h index 6da5db1..9c7856a 100644 --- a/Uploader/Calculated.h +++ b/Uploader/Calculated.h @@ -1,7 +1,7 @@ #pragma once #include - +#include using namespace std; class Calculated @@ -19,6 +19,6 @@ class Calculated void(*NotifyUploadResult)(void* object, bool result); void* Client; - void UploadReplay(string replayPath, string playerId); + void UploadReplay(std::filesystem::path startPath, std::filesystem::path replayPath, string playerId); }; diff --git a/Uploader/HttpClient.cpp b/Uploader/HttpClient.cpp index 92bc025..0f9bf19 100644 --- a/Uploader/HttpClient.cpp +++ b/Uploader/HttpClient.cpp @@ -46,7 +46,7 @@ long PostFile(PostFileRequest* ctx) request.setOpt(new curlpp::options::SslVerifyPeer(false)); { curlpp::Forms formParts; - formParts.push_back(new curlpp::FormParts::File(ctx->ParamName, ctx->FilePath)); + formParts.push_back(new curlpp::FormParts::File(ctx->ParamName, ctx->FilePath.string())); request.setOpt(new curlpp::options::HttpPost(formParts)); } diff --git a/Uploader/HttpClient.h b/Uploader/HttpClient.h index 1582f22..ec3fc07 100644 --- a/Uploader/HttpClient.h +++ b/Uploader/HttpClient.h @@ -23,6 +23,7 @@ #include #endif +#include using namespace std; @@ -35,7 +36,7 @@ struct PostFileRequest string Url; list Headers; - string FilePath; + std::filesystem::path FilePath; string ParamName; void(*RequestComplete)(PostFileRequest*); diff --git a/Uploader/Match.h b/Uploader/Match.h index 98a3fc3..002d185 100644 --- a/Uploader/Match.h +++ b/Uploader/Match.h @@ -17,7 +17,7 @@ class Match int Team0Score; int Team1Score; - + int WinningTeam; Match(); ~Match(); }; \ No newline at end of file diff --git a/Uploader/Player.cpp b/Uploader/Player.cpp index 4cbabdf..acdee88 100644 --- a/Uploader/Player.cpp +++ b/Uploader/Player.cpp @@ -8,7 +8,7 @@ Player::~Player() { } -bool Player::WonMatch(int team0Score, int team1Score) +bool Player::WonMatch(int winningTeam) { - return Team == 0 ? team0Score > team1Score : team1Score > team0Score; + return Team == winningTeam; } diff --git a/Uploader/Player.h b/Uploader/Player.h index 188bf7d..39e29aa 100644 --- a/Uploader/Player.h +++ b/Uploader/Player.h @@ -9,6 +9,7 @@ class Player public: string Name; unsigned long long UniqueId; + std::string EpicID; int Team; int Score; @@ -21,5 +22,5 @@ class Player Player(); ~Player(); - bool WonMatch(int team0Score, int team1Score); + bool WonMatch(int winningTeam); }; \ No newline at end of file diff --git a/Uploader/Replay.cpp b/Uploader/Replay.cpp index 5b35dff..f11d4aa 100644 --- a/Uploader/Replay.cpp +++ b/Uploader/Replay.cpp @@ -63,7 +63,7 @@ string ApplyNameTemplate(string& nameTemplate, Match& match, int* matchIndex) min.insert(min.begin(), 2 - min.length(), '0'); // Calculate Win/Loss string - auto won = match.PrimaryPlayer.WonMatch(match.Team0Score, match.Team1Score); + auto won = match.PrimaryPlayer.WonMatch(match.WinningTeam); auto winloss = won ? string("Win") : string("Loss"); auto wl = won ? string("W") : string("L"); @@ -73,6 +73,7 @@ string ApplyNameTemplate(string& nameTemplate, Match& match, int* matchIndex) ReplaceAll(name, "{MODE}", match.GameMode); ReplaceAll(name, "{PLAYER}", playerName); ReplaceAll(name, "{UNIQUEID}", to_string(match.PrimaryPlayer.UniqueId)); + ReplaceAll(name, "{EPICID}", match.PrimaryPlayer.EpicID); ReplaceAll(name, "{WINLOSS}", winloss); ReplaceAll(name, "{WL}", wl); ReplaceAll(name, "{YEAR}", year); diff --git a/Uploader/Uploader.vcxproj b/Uploader/Uploader.vcxproj index 2972e38..f2b8f0f 100644 --- a/Uploader/Uploader.vcxproj +++ b/Uploader/Uploader.vcxproj @@ -136,9 +136,10 @@ true true true - _MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;CURL_STATICLIB;CURLPP_STATICLIB + _MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;CURL_STATICLIB;CURLPP_STATICLIB;WIN32_MEAN_AND_LEAN;_HAS_STD_BYTE=0 ;../libs/includes/ MultiThreaded + stdcpp17 true