refactor: activity game messages as structs

Converts ActivityEnter, ActivityExit, ActivityStart, ActivityStop,
ActivityPause, StartActivityTime, RequestActivityEnter,
RequestActivityExit and ShowActivityCountdown to NetGameMsgs in
ActivityMessages.{h,cpp}, switches their callers (racing, shooting
gallery, survival, waves, AG course, NT combat challenge) and deletes
the old GameMessages::Send* / HandleRequestActivityExit functions.
REQUEST_ACTIVITY_EXIT is registered in GameMessageHandler's map.

No wire change. Verified by comparing every struct byte for byte with a
frozen verbatim copy of the old functions (tests/.../Legacy) over a
grid of inputs, both to one client and as a broadcast (a temporary test
proved the copy matched production before it was deleted), plus hand
computed golden bytes, round trips and a deliberate field mutation that
made the tests fail. Layouts confirmed against the 1.10.64 client in
Ghidra. Only difference: a broadcast no longer makes
the extra Send(UNASSIGNED, false) that RakNet already rejected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-26 10:32:32 -05:00
parent ac858dd1e2
commit 7fb75f0484
15 changed files with 589 additions and 145 deletions

View File

@@ -2,6 +2,7 @@
#include "EntityManager.h"
#include "ScriptedActivityComponent.h"
#include "GameMessages.h"
#include "ActivityMessages.h"
#include "LeaderboardManager.h"
#include "dServer.h"
#include "eMissionTaskType.h"
@@ -43,7 +44,9 @@ void NpcAgCourseStarter::OnMessageBoxResponse(Entity* self, Entity* sender, int3
Game::entityManager->SerializeEntity(self);
} else if (identifier == u"player_dialog_start_course" && button == 1) {
GameMessages::SendNotifyClientObject(selfId, u"start_timer", 0, 0, LWOOBJID_EMPTY, "", senderSysAddr);
GameMessages::SendActivityStart(selfId, senderSysAddr);
GameMessages::ActivityStart activityStart;
activityStart.target = selfId;
activityStart.Send(senderSysAddr);
const auto score = scriptedActivityComponent->GetActivityValue(senderId, 1);
if (score != 0 && score != -1.0f) return;

View File

@@ -1,5 +1,6 @@
#include "NtCombatChallengeServer.h"
#include "GameMessages.h"
#include "ActivityMessages.h"
#include "EntityManager.h"
#include "EntityInfo.h"
#include "InventoryComponent.h"
@@ -58,7 +59,9 @@ void NtCombatChallengeServer::OnMessageBoxResponse(Entity* self, Entity* sender,
self->AddTimer("start_delay", 2.0f);
GameMessages::SendShowActivityCountdown(self->GetObjectID(), false, false, u"", 0, sender->GetSystemAddress());
GameMessages::ShowActivityCountdown countdown;
countdown.target = self->GetObjectID();
countdown.Send(sender->GetSystemAddress());
self->SetNetworkVar(u"toggle", true);
} else if (identifier == u"CloseButton") {

View File

@@ -1,5 +1,6 @@
#include "BaseSurvivalServer.h"
#include "GameMessages.h"
#include "ActivityMessages.h"
#include "DestroyableComponent.h"
#include "EntityManager.h"
#include "dZoneManager.h"
@@ -278,7 +279,9 @@ void BaseSurvivalServer::PlayerAccepted(Entity* self, LWOOBJID playerID) {
}
void BaseSurvivalServer::StartWaves(Entity* self) {
GameMessages::SendActivityStart(self->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS);
GameMessages::ActivityStart activityStart;
activityStart.target = self->GetObjectID();
activityStart.Send(UNASSIGNED_SYSTEM_ADDRESS);
self->SetVar<bool>(PlayersReadyVariable, true);
self->SetVar<uint32_t>(BaseMobSetIndexVariable, 0);

View File

@@ -1,5 +1,6 @@
#include "BaseWavesServer.h"
#include "GameMessages.h"
#include "ActivityMessages.h"
#include "DestroyableComponent.h"
#include "EntityManager.h"
#include "dZoneManager.h"
@@ -273,7 +274,9 @@ void BaseWavesServer::PlayerAccepted(Entity* self, LWOOBJID playerID) {
// Done
void BaseWavesServer::StartWaves(Entity* self) {
GameMessages::SendActivityStart(self->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS);
GameMessages::ActivityStart activityStart;
activityStart.target = self->GetObjectID();
activityStart.Send(UNASSIGNED_SYSTEM_ADDRESS);
self->SetNetworkVar<std::string>(WatchingIntroVariable, "");
self->SetVar<bool>(PlayersReadyVariable, true);

View File

@@ -1,6 +1,7 @@
#include "SGCannon.h"
#include "EntityManager.h"
#include "GameMessages.h"
#include "ActivityMessages.h"
#include "dZoneManager.h"
#include "Character.h"
#include "ShootingGalleryComponent.h"
@@ -83,7 +84,9 @@ void SGCannon::OnActivityStateChangeRequest(Entity* self, LWOOBJID senderID, int
if (player != nullptr) {
LOG("Player is ready");
GameMessages::SendActivityEnter(self->GetObjectID(), player->GetSystemAddress());
GameMessages::ActivityEnter activityEnter;
activityEnter.target = self->GetObjectID();
activityEnter.Send(player->GetSystemAddress());
auto* shootingGalleryComponent = self->GetComponent<ShootingGalleryComponent>();
@@ -186,10 +189,16 @@ void SGCannon::SpawnWaveTimerFunc(Entity* self) {
if (player != nullptr) {
GameMessages::SendPlayFXEffect(player->GetObjectID(), -1, u"SG-start", "");
GameMessages::SendStartActivityTime(self->GetObjectID(), timeLimit, player->GetSystemAddress());
GameMessages::StartActivityTime startActivityTime;
startActivityTime.target = self->GetObjectID();
startActivityTime.startTime = timeLimit;
startActivityTime.Send(player->GetSystemAddress());
LOG("Sending ActivityPause false");
GameMessages::SendActivityPause(self->GetObjectID(), false, player->GetSystemAddress());
GameMessages::ActivityPause activityPause;
activityPause.target = self->GetObjectID();
activityPause.bPause = false;
activityPause.Send(player->GetSystemAddress());
}
}
}
@@ -199,8 +208,12 @@ void SGCannon::EndWaveTimerFunc(Entity* self) {
TimerToggle(self);
RecordPlayerScore(self);
GameMessages::ActivityPause activityPause;
activityPause.target = self->GetObjectID();
activityPause.bPause = true;
if (self->GetVar<uint32_t>(ThisWaveVariable) >= 2) {
GameMessages::SendActivityPause(self->GetObjectID(), true);
activityPause.Send(UNASSIGNED_SYSTEM_ADDRESS);
ActivityTimerStart(self, GameOverTimer, 0.1, 0.1);
return;
}
@@ -220,7 +233,7 @@ void SGCannon::EndWaveTimerFunc(Entity* self) {
LOG("Sending ActivityPause true");
GameMessages::SendActivityPause(self->GetObjectID(), true);
activityPause.Send(UNASSIGNED_SYSTEM_ADDRESS);
if (self->GetVar<bool>(SuperChargeActiveVariable) && !self->GetVar<bool>(SuperChargePausedVariable)) {
PauseChargeCannon(self);
}
@@ -231,7 +244,10 @@ void SGCannon::GameOverTimerFunc(Entity* self) {
if (player != nullptr) {
LOG_DEBUG("Sending ActivityPause true");
GameMessages::SendActivityPause(self->GetObjectID(), true, player->GetSystemAddress());
GameMessages::ActivityPause activityPause;
activityPause.target = self->GetObjectID();
activityPause.bPause = true;
activityPause.Send(player->GetSystemAddress());
ActivityTimerStart(self, EndGameBufferTimer, 1, 1);
@@ -342,7 +358,9 @@ void SGCannon::StartGame(Entity* self) {
// The client cant accept more than 10 results.
GetLeaderboardData(self, player->GetObjectID(), GetConstants().activityID, 10);
LOG("Sending ActivityStart");
GameMessages::SendActivityStart(self->GetObjectID(), player->GetSystemAddress());
GameMessages::ActivityStart activityStart;
activityStart.target = self->GetObjectID();
activityStart.Send(player->GetSystemAddress());
GameMessages::SendPlayFXEffect(self->GetObjectID(), -1, u"start", "");
@@ -602,7 +620,11 @@ void SGCannon::StopGame(Entity* self, bool cancel) {
self->SetNetworkVar<std::u16string>(u"UI_Rewards", GeneralUtils::ASCIIToUTF16(stream.str()));
}
GameMessages::SendActivityStop(self->GetObjectID(), false, cancel, player->GetSystemAddress());
GameMessages::ActivityStop activityStop;
activityStop.target = self->GetObjectID();
activityStop.bExit = false;
activityStop.bUserCancel = cancel;
activityStop.Send(player->GetSystemAddress());
self->SetVar<bool>(GameStartedVariable, false);
ActivityTimerStopAllTimers(self);