From 77b42daca1b280ceacd3a122006d56330bf51005 Mon Sep 17 00:00:00 2001 From: jadebenn Date: Tue, 17 Dec 2024 14:06:16 -0600 Subject: [PATCH] feat: Remove reinterpret_casts from AG race timer script and add method and chat command to get current server uptime (#1673) * use steady_clock race timer * formatting and const * improve time interface * added uptime chat command * fix bug and update documentation * inrease /uptime GM level requirement * update GM level for /uptime (again) * made changes according to feedback --- dGame/dUtilities/SlashCommandHandler.cpp | 9 ++ .../SlashCommands/GMZeroCommands.cpp | 9 +- .../dUtilities/SlashCommands/GMZeroCommands.h | 1 + dNet/dServer.h | 7 ++ .../02_server/Map/AG/NpcAgCourseStarter.cpp | 106 +++++++++--------- docs/Commands.md | 1 + 6 files changed, 79 insertions(+), 54 deletions(-) diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index 2e93060e6..becdcdd4e 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -1056,6 +1056,15 @@ void SlashCommandHandler::Startup() { }; RegisterCommand(InstanceInfoCommand); + Command ServerUptimeCommand{ + .help = "Display the time the current world server has been active", + .info = "Display the time the current world server has been active", + .aliases = { "uptime" }, + .handle = GMZeroCommands::ServerUptime, + .requiredLevel = eGameMasterLevel::DEVELOPER + }; + RegisterCommand(ServerUptimeCommand); + //Commands that are handled by the client Command faqCommand{ diff --git a/dGame/dUtilities/SlashCommands/GMZeroCommands.cpp b/dGame/dUtilities/SlashCommands/GMZeroCommands.cpp index 6c9811c24..51fa6e15b 100644 --- a/dGame/dUtilities/SlashCommands/GMZeroCommands.cpp +++ b/dGame/dUtilities/SlashCommands/GMZeroCommands.cpp @@ -225,8 +225,13 @@ namespace GMZeroCommands { ChatPackets::SendSystemMessage(sysAddr, u"Map: " + (GeneralUtils::to_u16string(zoneId.GetMapID())) + u"\nClone: " + (GeneralUtils::to_u16string(zoneId.GetCloneID())) + u"\nInstance: " + (GeneralUtils::to_u16string(zoneId.GetInstanceID()))); } + // Display the server uptime + void ServerUptime(Entity* entity, const SystemAddress& sysAddr, const std::string args) { + const auto time = Game::server->GetUptime(); + const auto seconds = std::chrono::duration_cast(time).count(); + ChatPackets::SendSystemMessage(sysAddr, u"Server has been up for " + GeneralUtils::to_u16string(seconds) + u" s"); + } + //For client side commands void ClientHandled(Entity* entity, const SystemAddress& sysAddr, const std::string args) {} - }; - diff --git a/dGame/dUtilities/SlashCommands/GMZeroCommands.h b/dGame/dUtilities/SlashCommands/GMZeroCommands.h index d3f6753d0..00824bf86 100644 --- a/dGame/dUtilities/SlashCommands/GMZeroCommands.h +++ b/dGame/dUtilities/SlashCommands/GMZeroCommands.h @@ -15,6 +15,7 @@ namespace GMZeroCommands { void LeaveZone(Entity* entity, const SystemAddress& sysAddr, const std::string args); void Resurrect(Entity* entity, const SystemAddress& sysAddr, const std::string args); void InstanceInfo(Entity* entity, const SystemAddress& sysAddr, const std::string args); + void ServerUptime(Entity* entity, const SystemAddress& sysAddr, const std::string args); void ClientHandled(Entity* entity, const SystemAddress& sysAddr, const std::string args); } diff --git a/dNet/dServer.h b/dNet/dServer.h index f958fc408..a577d191f 100644 --- a/dNet/dServer.h +++ b/dNet/dServer.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include #include "RakPeerInterface.h" #include "ReplicaManager.h" @@ -80,6 +81,11 @@ class dServer { const ServerType GetServerType() const { return mServerType; } + [[nodiscard]] + std::chrono::steady_clock::duration GetUptime() const { + return std::chrono::steady_clock::now() - mStartTime; + } + private: bool Startup(); void Shutdown(); @@ -114,4 +120,5 @@ class dServer { SystemAddress mMasterSystemAddress; std::string mMasterIP; int mMasterPort; + std::chrono::steady_clock::time_point mStartTime = std::chrono::steady_clock::now(); }; diff --git a/dScripts/02_server/Map/AG/NpcAgCourseStarter.cpp b/dScripts/02_server/Map/AG/NpcAgCourseStarter.cpp index 515603a0f..fc724fb9e 100644 --- a/dScripts/02_server/Map/AG/NpcAgCourseStarter.cpp +++ b/dScripts/02_server/Map/AG/NpcAgCourseStarter.cpp @@ -3,104 +3,106 @@ #include "ScriptedActivityComponent.h" #include "GameMessages.h" #include "LeaderboardManager.h" +#include "dServer.h" #include "eMissionTaskType.h" #include "eMissionState.h" #include "MissionComponent.h" -#include +#include -void NpcAgCourseStarter::OnStartup(Entity* self) { - -} +void NpcAgCourseStarter::OnStartup(Entity* self) {} void NpcAgCourseStarter::OnUse(Entity* self, Entity* user) { - auto* scriptedActivityComponent = self->GetComponent(); + auto* const scriptedActivityComponent = self->GetComponent(); + if (!scriptedActivityComponent) return; - if (scriptedActivityComponent == nullptr) { - return; - } + const auto selfId = self->GetObjectID(); + const auto userId = user->GetObjectID(); + const auto& userSysAddr = user->GetSystemAddress(); - if (scriptedActivityComponent->GetActivityPlayerData(user->GetObjectID()) != nullptr) { - GameMessages::SendNotifyClientObject(self->GetObjectID(), u"exit", 0, 0, LWOOBJID_EMPTY, "", user->GetSystemAddress()); + if (scriptedActivityComponent->GetActivityPlayerData(userId) != nullptr) { + GameMessages::SendNotifyClientObject(selfId, u"exit", 0, 0, LWOOBJID_EMPTY, "", userSysAddr); } else { - GameMessages::SendNotifyClientObject(self->GetObjectID(), u"start", 0, 0, LWOOBJID_EMPTY, "", user->GetSystemAddress()); + GameMessages::SendNotifyClientObject(selfId, u"start", 0, 0, LWOOBJID_EMPTY, "", userSysAddr); } } void NpcAgCourseStarter::OnMessageBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData) { - auto* scriptedActivityComponent = self->GetComponent(); + auto* const scriptedActivityComponent = self->GetComponent(); + if (!scriptedActivityComponent) return; - if (scriptedActivityComponent == nullptr) { - return; - } + const auto selfId = self->GetObjectID(); + const auto senderId = sender->GetObjectID(); + const auto& senderSysAddr = sender->GetSystemAddress(); if (identifier == u"player_dialog_cancel_course" && button == 1) { - GameMessages::SendNotifyClientObject(self->GetObjectID(), u"stop_timer", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress()); - - GameMessages::SendNotifyClientObject(self->GetObjectID(), u"cancel_timer", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress()); + GameMessages::SendNotifyClientObject(selfId, u"stop_timer", 0, 0, LWOOBJID_EMPTY, "", senderSysAddr); + GameMessages::SendNotifyClientObject(selfId, u"cancel_timer", 0, 0, LWOOBJID_EMPTY, "", senderSysAddr); - scriptedActivityComponent->RemoveActivityPlayerData(sender->GetObjectID()); + scriptedActivityComponent->RemoveActivityPlayerData(senderId); Game::entityManager->SerializeEntity(self); } else if (identifier == u"player_dialog_start_course" && button == 1) { - GameMessages::SendNotifyClientObject(self->GetObjectID(), u"start_timer", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress()); - - GameMessages::SendActivityStart(self->GetObjectID(), sender->GetSystemAddress()); - - auto* data = scriptedActivityComponent->AddActivityPlayerData(sender->GetObjectID()); + GameMessages::SendNotifyClientObject(selfId, u"start_timer", 0, 0, LWOOBJID_EMPTY, "", senderSysAddr); + GameMessages::SendActivityStart(selfId, senderSysAddr); + auto* const data = scriptedActivityComponent->AddActivityPlayerData(senderId); if (data->values[1] != 0) return; - time_t startTime = std::time(0) + 4; // Offset for starting timer - - data->values[1] = *reinterpret_cast(&startTime); + const auto raceStartTime = Game::server->GetUptime() + std::chrono::seconds(4); // Offset for starting timer + const auto fRaceStartTime = std::chrono::duration>(raceStartTime).count(); + data->values[1] = fRaceStartTime; Game::entityManager->SerializeEntity(self); } else if (identifier == u"FootRaceCancel") { - GameMessages::SendNotifyClientObject(self->GetObjectID(), u"stop_timer", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress()); + GameMessages::SendNotifyClientObject(selfId, u"stop_timer", 0, 0, LWOOBJID_EMPTY, "", senderSysAddr); - if (scriptedActivityComponent->GetActivityPlayerData(sender->GetObjectID()) != nullptr) { - GameMessages::SendNotifyClientObject(self->GetObjectID(), u"exit", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress()); + if (scriptedActivityComponent->GetActivityPlayerData(senderId) != nullptr) { + GameMessages::SendNotifyClientObject(selfId, u"exit", 0, 0, LWOOBJID_EMPTY, "", senderSysAddr); } else { - GameMessages::SendNotifyClientObject(self->GetObjectID(), u"start", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress()); + GameMessages::SendNotifyClientObject(selfId, u"start", 0, 0, LWOOBJID_EMPTY, "", senderSysAddr); } - scriptedActivityComponent->RemoveActivityPlayerData(sender->GetObjectID()); + scriptedActivityComponent->RemoveActivityPlayerData(senderId); } } void NpcAgCourseStarter::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2, int32_t param3) { - auto* scriptedActivityComponent = self->GetComponent(); - if (scriptedActivityComponent == nullptr) return; + auto* const scriptedActivityComponent = self->GetComponent(); + if (!scriptedActivityComponent) return; - auto* data = scriptedActivityComponent->GetActivityPlayerData(sender->GetObjectID()); - if (data == nullptr) return; + const auto selfId = self->GetObjectID(); + const auto senderId = sender->GetObjectID(); + const auto& senderSysAddr = sender->GetSystemAddress(); + + auto* const data = scriptedActivityComponent->GetActivityPlayerData(senderId); + if (!data) return; if (args == "course_cancel") { - GameMessages::SendNotifyClientObject(self->GetObjectID(), u"cancel_timer", 0, 0, - LWOOBJID_EMPTY, "", sender->GetSystemAddress()); - scriptedActivityComponent->RemoveActivityPlayerData(sender->GetObjectID()); + GameMessages::SendNotifyClientObject(selfId, u"cancel_timer", 0, 0, + LWOOBJID_EMPTY, "", senderSysAddr); + scriptedActivityComponent->RemoveActivityPlayerData(senderId); } else if (args == "course_finish") { - time_t endTime = std::time(0); - time_t finish = (endTime - *reinterpret_cast(&data->values[1])); - - data->values[2] = *reinterpret_cast(&finish); + const auto raceEndTime = Game::server->GetUptime(); + const auto fRaceEndTime = std::chrono::duration>(raceEndTime).count(); + const auto raceTimeElapsed = fRaceEndTime - data->values[1]; + data->values[2] = raceTimeElapsed; - auto* missionComponent = sender->GetComponent(); + auto* const missionComponent = sender->GetComponent(); if (missionComponent != nullptr) { missionComponent->ForceProgressTaskType(1884, 1, 1, false); - missionComponent->Progress(eMissionTaskType::PERFORM_ACTIVITY, -finish, self->GetObjectID(), + missionComponent->Progress(eMissionTaskType::PERFORM_ACTIVITY, -raceTimeElapsed, selfId, "performact_time"); } Game::entityManager->SerializeEntity(self); - LeaderboardManager::SaveScore(sender->GetObjectID(), scriptedActivityComponent->GetActivityID(), static_cast(finish)); + LeaderboardManager::SaveScore(senderId, scriptedActivityComponent->GetActivityID(), raceTimeElapsed); - GameMessages::SendNotifyClientObject(self->GetObjectID(), u"ToggleLeaderBoard", - scriptedActivityComponent->GetActivityID(), 0, sender->GetObjectID(), - "", sender->GetSystemAddress()); - GameMessages::SendNotifyClientObject(self->GetObjectID(), u"stop_timer", 1, finish, LWOOBJID_EMPTY, "", - sender->GetSystemAddress()); + GameMessages::SendNotifyClientObject(selfId, u"ToggleLeaderBoard", + scriptedActivityComponent->GetActivityID(), 0, senderId, + "", senderSysAddr); + GameMessages::SendNotifyClientObject(selfId, u"stop_timer", 1, raceTimeElapsed, LWOOBJID_EMPTY, "", + senderSysAddr); - scriptedActivityComponent->RemoveActivityPlayerData(sender->GetObjectID()); + scriptedActivityComponent->RemoveActivityPlayerData(senderId); } } diff --git a/docs/Commands.md b/docs/Commands.md index 222abe344..a0272c224 100644 --- a/docs/Commands.md +++ b/docs/Commands.md @@ -45,6 +45,7 @@ |setannmsg|`/setannmsg `|Sets the message of an announcement.|8| |setanntitle|`/setanntitle <title>`|Sets the title of an announcement.|8| |shutdownuniverse|`/shutdownuniverse`|Sends a shutdown message to the master server. This will send an announcement to all players that the universe will shut down in 10 minutes.|9| +|uptime|`/uptime`|Displays the time the current world server has been active.|8| ## Development Commands