Use OE for storing client ID, remove remaining game state touch point in network thread (#5969)
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user