summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett Cox <garrettjcox@gmail.com>2025-11-16 08:10:07 -0600
committerGitHub <noreply@github.com>2025-11-16 08:10:07 -0600
commiteca9eac0cfda9f1f42bf4e6ee323e1bf947d1e42 (patch)
tree602ddce731512e42ae717dc4c1ca2665805c82d8
parent05233487f8b16cec3f6ef13a86ff4cfacd4f92b6 (diff)
Use OE for storing client ID, remove remaining game state touch point in network thread (#5969)
-rw-r--r--soh/soh/Network/Anchor/Anchor.cpp28
-rw-r--r--soh/soh/Network/Anchor/Anchor.h7
-rw-r--r--soh/soh/Network/Anchor/DummyPlayer.cpp22
-rw-r--r--soh/soh/Network/Anchor/HookHandlers.cpp10
-rw-r--r--soh/soh/Network/Anchor/Packets/PlayerUpdate.cpp6
5 files changed, 46 insertions, 27 deletions
diff --git a/soh/soh/Network/Anchor/Anchor.cpp b/soh/soh/Network/Anchor/Anchor.cpp
index bc5614f47..e996ac6a0 100644
--- a/soh/soh/Network/Anchor/Anchor.cpp
+++ b/soh/soh/Network/Anchor/Anchor.cpp
@@ -3,6 +3,7 @@
#include <libultraship/libultraship.h>
#include "soh/OTRGlobals.h"
#include "soh/Enhancements/nametag.h"
+#include "soh/ObjectExtension/ObjectExtension.h"
extern "C" {
#include "variables.h"
@@ -143,6 +144,21 @@ void Anchor::ProcessIncomingPacketQueue() {
// MARK: - Misc/Helpers
// Kills all existing anchor actors and respawns them with the new client data
+
+struct DummyPlayerClientId {
+ uint32_t clientId = 0;
+};
+static ObjectExtension::Register<DummyPlayerClientId> DummyPlayerClientIdRegister;
+
+uint32_t Anchor::GetDummyPlayerClientId(const Actor* actor) {
+ const DummyPlayerClientId* clientId = ObjectExtension::GetInstance().Get<DummyPlayerClientId>(actor);
+ return clientId != nullptr ? clientId->clientId : 0;
+}
+
+void Anchor::SetDummyPlayerClientId(const Actor* actor, uint32_t clientId) {
+ ObjectExtension::GetInstance().Set<DummyPlayerClientId>(actor, DummyPlayerClientId{ clientId });
+}
+
void Anchor::RefreshClientActors() {
if (!IsSaveLoaded()) {
return;
@@ -158,23 +174,21 @@ void Anchor::RefreshClientActors() {
actor = actor->next;
}
- actorIndexToClientId.clear();
- refreshingActors = true;
for (auto& [clientId, client] : clients) {
if (!client.online || client.self) {
continue;
}
- actorIndexToClientId.push_back(clientId);
+ spawningDummyPlayerForClientId = clientId;
// We are using a hook `ShouldActorInit` to override the init/update/draw/destroy functions of the Player we
// spawn We quickly store a mapping of "index" to clientId, then within the init function we use this to get the
// clientId and store it on player->zTargetActiveTimer (unused s32 for the dummy) for convenience
- auto dummy = Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_PLAYER, client.posRot.pos.x,
- client.posRot.pos.y, client.posRot.pos.z, client.posRot.rot.x, client.posRot.rot.y,
- client.posRot.rot.z, actorIndexToClientId.size() - 1, false);
+ auto dummy =
+ Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_PLAYER, client.posRot.pos.x, client.posRot.pos.y,
+ client.posRot.pos.z, client.posRot.rot.x, client.posRot.rot.y, client.posRot.rot.z, 0, false);
client.player = (Player*)dummy;
}
- refreshingActors = false;
+ spawningDummyPlayerForClientId = 0;
}
bool Anchor::IsSaveLoaded() {
diff --git a/soh/soh/Network/Anchor/Anchor.h b/soh/soh/Network/Anchor/Anchor.h
index a5e831153..93c404617 100644
--- a/soh/soh/Network/Anchor/Anchor.h
+++ b/soh/soh/Network/Anchor/Anchor.h
@@ -63,7 +63,8 @@ typedef struct {
class Anchor : public Network {
private:
- bool refreshingActors = false;
+ uint32_t spawningDummyPlayerForClientId = 0;
+ bool shouldRefreshActors = false;
bool justLoadedSave = false;
bool isHandlingUpdateTeamState = false;
bool isProcessingIncomingPacket = false;
@@ -74,6 +75,8 @@ class Anchor : public Network {
nlohmann::json PrepRoomState();
void RegisterHooks();
void RefreshClientActors();
+ void SetDummyPlayerClientId(const Actor* actor, uint32_t clientId);
+
void HandlePacket_AllClientState(nlohmann::json payload);
void HandlePacket_ConsumeAdultTradeItem(nlohmann::json payload);
void HandlePacket_DamagePlayer(nlohmann::json payload);
@@ -125,7 +128,6 @@ class Anchor : public Network {
static Anchor* Instance;
std::map<uint32_t, AnchorClient> clients;
- std::vector<uint32_t> actorIndexToClientId;
RoomState roomState;
void Enable();
@@ -138,6 +140,7 @@ class Anchor : public Network {
void SendJsonToRemote(nlohmann::json packet);
bool IsSaveLoaded();
bool CanTeleportTo(uint32_t clientId);
+ uint32_t GetDummyPlayerClientId(const Actor* actor);
void SendPacket_ClearTeamState(std::string teamId);
void SendPacket_DamagePlayer(u32 clientId, u8 damageEffect, u8 damage);
diff --git a/soh/soh/Network/Anchor/DummyPlayer.cpp b/soh/soh/Network/Anchor/DummyPlayer.cpp
index d0eb58d93..3bc085413 100644
--- a/soh/soh/Network/Anchor/DummyPlayer.cpp
+++ b/soh/soh/Network/Anchor/DummyPlayer.cpp
@@ -12,9 +12,6 @@ void Player_UseItem(PlayState* play, Player* player, s32 item);
void Player_Draw(Actor* actor, PlayState* play);
}
-// Hijacking player->zTargetActiveTimer (unused s32 for the dummy) to store the clientId for convenience
-#define DUMMY_CLIENT_ID player->zTargetActiveTimer
-
static DamageTable DummyPlayerDamageTable = {
/* Deku nut */ DMG_ENTRY(0, DUMMY_PLAYER_HIT_RESPONSE_STUN),
/* Deku stick */ DMG_ENTRY(2, DUMMY_PLAYER_HIT_RESPONSE_NORMAL),
@@ -53,15 +50,14 @@ static DamageTable DummyPlayerDamageTable = {
void DummyPlayer_Init(Actor* actor, PlayState* play) {
Player* player = (Player*)actor;
- uint32_t clientId = Anchor::Instance->actorIndexToClientId[actor->params];
- DUMMY_CLIENT_ID = clientId;
+ uint32_t clientId = Anchor::Instance->GetDummyPlayerClientId(actor);
- if (!Anchor::Instance->clients.contains(DUMMY_CLIENT_ID)) {
+ if (!Anchor::Instance->clients.contains(clientId)) {
Actor_Kill(actor);
return;
}
- AnchorClient& client = Anchor::Instance->clients[DUMMY_CLIENT_ID];
+ AnchorClient& client = Anchor::Instance->clients[clientId];
// Hack to account for usage of gSaveContext in Player_Init
s32 originalAge = gSaveContext.linkAge;
@@ -104,12 +100,14 @@ void Math_Vec3s_Copy(Vec3s* dest, Vec3s* src) {
void DummyPlayer_Update(Actor* actor, PlayState* play) {
Player* player = (Player*)actor;
- if (!Anchor::Instance->clients.contains(DUMMY_CLIENT_ID)) {
+ uint32_t clientId = Anchor::Instance->GetDummyPlayerClientId(actor);
+
+ if (!Anchor::Instance->clients.contains(clientId)) {
Actor_Kill(actor);
return;
}
- AnchorClient& client = Anchor::Instance->clients[DUMMY_CLIENT_ID];
+ AnchorClient& client = Anchor::Instance->clients[clientId];
if (client.sceneNum != gPlayState->sceneNum || !client.online || !client.isSaveLoaded) {
actor->world.pos.x = -9999.0f;
@@ -195,12 +193,14 @@ void DummyPlayer_Update(Actor* actor, PlayState* play) {
void DummyPlayer_Draw(Actor* actor, PlayState* play) {
Player* player = (Player*)actor;
- if (!Anchor::Instance->clients.contains(DUMMY_CLIENT_ID)) {
+ uint32_t clientId = Anchor::Instance->GetDummyPlayerClientId(actor);
+
+ if (!Anchor::Instance->clients.contains(clientId)) {
Actor_Kill(actor);
return;
}
- AnchorClient& client = Anchor::Instance->clients[DUMMY_CLIENT_ID];
+ AnchorClient& client = Anchor::Instance->clients[clientId];
if (client.sceneNum != gPlayState->sceneNum || !client.online || !client.isSaveLoaded) {
return;
diff --git a/soh/soh/Network/Anchor/HookHandlers.cpp b/soh/soh/Network/Anchor/HookHandlers.cpp
index 15886c527..9a4622c29 100644
--- a/soh/soh/Network/Anchor/HookHandlers.cpp
+++ b/soh/soh/Network/Anchor/HookHandlers.cpp
@@ -67,7 +67,9 @@ void Anchor::RegisterHooks() {
COND_ID_HOOK(ShouldActorInit, ACTOR_PLAYER, isConnected, [&](void* actorRef, bool* should) {
Actor* actor = (Actor*)actorRef;
- if (refreshingActors) {
+ if (spawningDummyPlayerForClientId != 0) {
+ SetDummyPlayerClientId(actor, spawningDummyPlayerForClientId);
+
// By the time we get here, the actor was already added to the ACTORCAT_PLAYER list, so we need to move it
Actor_ChangeCategory(gPlayState, &gPlayState->actorCtx, actor, ACTORCAT_NPC);
actor->id = ACTOR_EN_OE2;
@@ -84,6 +86,12 @@ void Anchor::RegisterHooks() {
justLoadedSave = false;
SendPacket_RequestTeamState();
}
+
+ if (shouldRefreshActors) {
+ shouldRefreshActors = false;
+ RefreshClientActors();
+ }
+
SendPacket_PlayerUpdate();
});
diff --git a/soh/soh/Network/Anchor/Packets/PlayerUpdate.cpp b/soh/soh/Network/Anchor/Packets/PlayerUpdate.cpp
index 34bacaf11..a4ee17b76 100644
--- a/soh/soh/Network/Anchor/Packets/PlayerUpdate.cpp
+++ b/soh/soh/Network/Anchor/Packets/PlayerUpdate.cpp
@@ -77,8 +77,6 @@ void Anchor::SendPacket_PlayerUpdate() {
void Anchor::HandlePacket_PlayerUpdate(nlohmann::json payload) {
uint32_t clientId = payload["clientId"].get<uint32_t>();
- bool shouldRefreshActors = false;
-
if (clients.contains(clientId)) {
auto& client = clients[clientId];
@@ -110,8 +108,4 @@ void Anchor::HandlePacket_PlayerUpdate(nlohmann::json payload) {
client.unk_862 = payload["unk_862"].get<s16>();
client.actionVar1 = payload["actionVar1"].get<s8>();
}
-
- if (shouldRefreshActors) {
- RefreshClientActors();
- }
}