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
This commit is contained in:
jadebenn 2024-12-17 14:06:16 -06:00 committed by GitHub
parent ba364800fe
commit 77b42daca1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 79 additions and 54 deletions

View File

@ -1056,6 +1056,15 @@ void SlashCommandHandler::Startup() {
}; };
RegisterCommand(InstanceInfoCommand); 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 //Commands that are handled by the client
Command faqCommand{ Command faqCommand{

View File

@ -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()))); 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<std::chrono::seconds>(time).count();
ChatPackets::SendSystemMessage(sysAddr, u"Server has been up for " + GeneralUtils::to_u16string(seconds) + u" s");
}
//For client side commands //For client side commands
void ClientHandled(Entity* entity, const SystemAddress& sysAddr, const std::string args) {} void ClientHandled(Entity* entity, const SystemAddress& sysAddr, const std::string args) {}
}; };

View File

@ -15,6 +15,7 @@ namespace GMZeroCommands {
void LeaveZone(Entity* entity, const SystemAddress& sysAddr, const std::string args); void LeaveZone(Entity* entity, const SystemAddress& sysAddr, const std::string args);
void Resurrect(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 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); void ClientHandled(Entity* entity, const SystemAddress& sysAddr, const std::string args);
} }

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <string> #include <string>
#include <chrono>
#include <csignal> #include <csignal>
#include "RakPeerInterface.h" #include "RakPeerInterface.h"
#include "ReplicaManager.h" #include "ReplicaManager.h"
@ -80,6 +81,11 @@ public:
const ServerType GetServerType() const { return mServerType; } const ServerType GetServerType() const { return mServerType; }
[[nodiscard]]
std::chrono::steady_clock::duration GetUptime() const {
return std::chrono::steady_clock::now() - mStartTime;
}
private: private:
bool Startup(); bool Startup();
void Shutdown(); void Shutdown();
@ -114,4 +120,5 @@ protected:
SystemAddress mMasterSystemAddress; SystemAddress mMasterSystemAddress;
std::string mMasterIP; std::string mMasterIP;
int mMasterPort; int mMasterPort;
std::chrono::steady_clock::time_point mStartTime = std::chrono::steady_clock::now();
}; };

View File

@ -3,104 +3,106 @@
#include "ScriptedActivityComponent.h" #include "ScriptedActivityComponent.h"
#include "GameMessages.h" #include "GameMessages.h"
#include "LeaderboardManager.h" #include "LeaderboardManager.h"
#include "dServer.h"
#include "eMissionTaskType.h" #include "eMissionTaskType.h"
#include "eMissionState.h" #include "eMissionState.h"
#include "MissionComponent.h" #include "MissionComponent.h"
#include <ctime> #include <chrono>
void NpcAgCourseStarter::OnStartup(Entity* self) { void NpcAgCourseStarter::OnStartup(Entity* self) {}
}
void NpcAgCourseStarter::OnUse(Entity* self, Entity* user) { void NpcAgCourseStarter::OnUse(Entity* self, Entity* user) {
auto* scriptedActivityComponent = self->GetComponent<ScriptedActivityComponent>(); auto* const scriptedActivityComponent = self->GetComponent<ScriptedActivityComponent>();
if (!scriptedActivityComponent) return;
if (scriptedActivityComponent == nullptr) { const auto selfId = self->GetObjectID();
return; const auto userId = user->GetObjectID();
} const auto& userSysAddr = user->GetSystemAddress();
if (scriptedActivityComponent->GetActivityPlayerData(user->GetObjectID()) != nullptr) { if (scriptedActivityComponent->GetActivityPlayerData(userId) != nullptr) {
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"exit", 0, 0, LWOOBJID_EMPTY, "", user->GetSystemAddress()); GameMessages::SendNotifyClientObject(selfId, u"exit", 0, 0, LWOOBJID_EMPTY, "", userSysAddr);
} else { } 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) { void NpcAgCourseStarter::OnMessageBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData) {
auto* scriptedActivityComponent = self->GetComponent<ScriptedActivityComponent>(); auto* const scriptedActivityComponent = self->GetComponent<ScriptedActivityComponent>();
if (!scriptedActivityComponent) return;
if (scriptedActivityComponent == nullptr) { const auto selfId = self->GetObjectID();
return; const auto senderId = sender->GetObjectID();
} const auto& senderSysAddr = sender->GetSystemAddress();
if (identifier == u"player_dialog_cancel_course" && button == 1) { if (identifier == u"player_dialog_cancel_course" && button == 1) {
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"stop_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);
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"cancel_timer", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress()); scriptedActivityComponent->RemoveActivityPlayerData(senderId);
scriptedActivityComponent->RemoveActivityPlayerData(sender->GetObjectID());
Game::entityManager->SerializeEntity(self); Game::entityManager->SerializeEntity(self);
} else if (identifier == u"player_dialog_start_course" && button == 1) { } else if (identifier == u"player_dialog_start_course" && button == 1) {
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"start_timer", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress()); GameMessages::SendNotifyClientObject(selfId, u"start_timer", 0, 0, LWOOBJID_EMPTY, "", senderSysAddr);
GameMessages::SendActivityStart(selfId, senderSysAddr);
GameMessages::SendActivityStart(self->GetObjectID(), sender->GetSystemAddress());
auto* data = scriptedActivityComponent->AddActivityPlayerData(sender->GetObjectID());
auto* const data = scriptedActivityComponent->AddActivityPlayerData(senderId);
if (data->values[1] != 0) return; if (data->values[1] != 0) return;
time_t startTime = std::time(0) + 4; // Offset for starting timer const auto raceStartTime = Game::server->GetUptime() + std::chrono::seconds(4); // Offset for starting timer
const auto fRaceStartTime = std::chrono::duration<float, std::ratio<1>>(raceStartTime).count();
data->values[1] = *reinterpret_cast<float*>(&startTime); data->values[1] = fRaceStartTime;
Game::entityManager->SerializeEntity(self); Game::entityManager->SerializeEntity(self);
} else if (identifier == u"FootRaceCancel") { } 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) { if (scriptedActivityComponent->GetActivityPlayerData(senderId) != nullptr) {
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"exit", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress()); GameMessages::SendNotifyClientObject(selfId, u"exit", 0, 0, LWOOBJID_EMPTY, "", senderSysAddr);
} else { } 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) { void NpcAgCourseStarter::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2, int32_t param3) {
auto* scriptedActivityComponent = self->GetComponent<ScriptedActivityComponent>(); auto* const scriptedActivityComponent = self->GetComponent<ScriptedActivityComponent>();
if (scriptedActivityComponent == nullptr) return; if (!scriptedActivityComponent) return;
auto* data = scriptedActivityComponent->GetActivityPlayerData(sender->GetObjectID()); const auto selfId = self->GetObjectID();
if (data == nullptr) return; const auto senderId = sender->GetObjectID();
const auto& senderSysAddr = sender->GetSystemAddress();
auto* const data = scriptedActivityComponent->GetActivityPlayerData(senderId);
if (!data) return;
if (args == "course_cancel") { if (args == "course_cancel") {
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"cancel_timer", 0, 0, GameMessages::SendNotifyClientObject(selfId, u"cancel_timer", 0, 0,
LWOOBJID_EMPTY, "", sender->GetSystemAddress()); LWOOBJID_EMPTY, "", senderSysAddr);
scriptedActivityComponent->RemoveActivityPlayerData(sender->GetObjectID()); scriptedActivityComponent->RemoveActivityPlayerData(senderId);
} else if (args == "course_finish") { } else if (args == "course_finish") {
time_t endTime = std::time(0); const auto raceEndTime = Game::server->GetUptime();
time_t finish = (endTime - *reinterpret_cast<time_t*>(&data->values[1])); const auto fRaceEndTime = std::chrono::duration<float, std::ratio<1>>(raceEndTime).count();
const auto raceTimeElapsed = fRaceEndTime - data->values[1];
data->values[2] = raceTimeElapsed;
data->values[2] = *reinterpret_cast<float*>(&finish); auto* const missionComponent = sender->GetComponent<MissionComponent>();
auto* missionComponent = sender->GetComponent<MissionComponent>();
if (missionComponent != nullptr) { if (missionComponent != nullptr) {
missionComponent->ForceProgressTaskType(1884, 1, 1, false); missionComponent->ForceProgressTaskType(1884, 1, 1, false);
missionComponent->Progress(eMissionTaskType::PERFORM_ACTIVITY, -finish, self->GetObjectID(), missionComponent->Progress(eMissionTaskType::PERFORM_ACTIVITY, -raceTimeElapsed, selfId,
"performact_time"); "performact_time");
} }
Game::entityManager->SerializeEntity(self); Game::entityManager->SerializeEntity(self);
LeaderboardManager::SaveScore(sender->GetObjectID(), scriptedActivityComponent->GetActivityID(), static_cast<float>(finish)); LeaderboardManager::SaveScore(senderId, scriptedActivityComponent->GetActivityID(), raceTimeElapsed);
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"ToggleLeaderBoard", GameMessages::SendNotifyClientObject(selfId, u"ToggleLeaderBoard",
scriptedActivityComponent->GetActivityID(), 0, sender->GetObjectID(), scriptedActivityComponent->GetActivityID(), 0, senderId,
"", sender->GetSystemAddress()); "", senderSysAddr);
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"stop_timer", 1, finish, LWOOBJID_EMPTY, "", GameMessages::SendNotifyClientObject(selfId, u"stop_timer", 1, raceTimeElapsed, LWOOBJID_EMPTY, "",
sender->GetSystemAddress()); senderSysAddr);
scriptedActivityComponent->RemoveActivityPlayerData(sender->GetObjectID()); scriptedActivityComponent->RemoveActivityPlayerData(senderId);
} }
} }

View File

@ -45,6 +45,7 @@
|setannmsg|`/setannmsg <title>`|Sets the message of an announcement.|8| |setannmsg|`/setannmsg <title>`|Sets the message of an announcement.|8|
|setanntitle|`/setanntitle <title>`|Sets the title 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| |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 ## Development Commands