Files
Shiip-of-Hakinian-Espanol/soh/soh/Network/Anchor/Packets/PlayerUpdate.cpp
Garrett Cox 9cd31099e2 Additional Anchor functionality: (#5999)
- Returned support for custom tunic colors
- Ocarina playback now audible
- Fixed movement translation issue when climbing or going through crawlspaces
- Fixed issue preventing some items from being visible in Dummy hands (namely ocarina)
- Fixed stick length not correctly syncing
2025-11-30 18:17:00 -07:00

118 lines
4.5 KiB
C++

#include "soh/Network/Anchor/Anchor.h"
#include "soh/Network/Anchor/JsonConversions.hpp"
#include <nlohmann/json.hpp>
#include <libultraship/libultraship.h>
extern "C" {
#include "macros.h"
#include "variables.h"
extern PlayState* gPlayState;
}
/**
* PLAYER_UPDATE
*
* Contains real-time data necessary to update other clients in the same scene as the player
*
* Sent every frame to other clients within the same scene
*
* Note: This packet is sent _a lot_, so please do not include any unnecessary data in it
*/
void Anchor::SendPacket_PlayerUpdate() {
if (!IsSaveLoaded()) {
return;
}
uint32_t currentPlayerCount = 0;
for (auto& [clientId, client] : clients) {
if (client.sceneNum == gPlayState->sceneNum && client.online && client.isSaveLoaded && !client.self) {
currentPlayerCount++;
}
}
if (currentPlayerCount == 0) {
return;
}
Player* player = GET_PLAYER(gPlayState);
nlohmann::json payload;
payload["type"] = PLAYER_UPDATE;
payload["sceneNum"] = gPlayState->sceneNum;
payload["entranceIndex"] = gSaveContext.entranceIndex;
payload["linkAge"] = gSaveContext.linkAge;
payload["posRot"]["pos"] = player->actor.world.pos;
payload["posRot"]["rot"] = player->actor.shape.rot;
std::vector<int> jointArray;
for (size_t i = 0; i < 24; i++) {
Vec3s joint = player->skelAnime.jointTable[i];
jointArray.push_back(joint.x);
jointArray.push_back(joint.y);
jointArray.push_back(joint.z);
}
payload["prevTransl"] = player->skelAnime.prevTransl;
payload["movementFlags"] = player->skelAnime.movementFlags;
payload["jointTable"] = jointArray;
payload["upperLimbRot"] = player->upperLimbRot;
payload["currentBoots"] = player->currentBoots;
payload["currentShield"] = player->currentShield;
payload["currentTunic"] = player->currentTunic;
payload["stateFlags1"] = player->stateFlags1;
payload["stateFlags2"] = player->stateFlags2;
payload["buttonItem0"] = gSaveContext.equips.buttonItems[0];
payload["itemAction"] = player->itemAction;
payload["heldItemAction"] = player->heldItemAction;
payload["modelGroup"] = player->modelGroup;
payload["invincibilityTimer"] = player->invincibilityTimer;
payload["unk_862"] = player->unk_862;
payload["unk_85C"] = player->unk_85C;
payload["actionVar1"] = player->av1.actionVar1;
payload["quiet"] = true;
for (auto& [clientId, client] : clients) {
if (client.sceneNum == gPlayState->sceneNum && client.online && client.isSaveLoaded && !client.self) {
payload["targetClientId"] = clientId;
SendJsonToRemote(payload);
}
}
}
void Anchor::HandlePacket_PlayerUpdate(nlohmann::json payload) {
uint32_t clientId = payload["clientId"].get<uint32_t>();
if (clients.contains(clientId)) {
auto& client = clients[clientId];
if (client.linkAge != payload["linkAge"].get<s32>()) {
shouldRefreshActors = true;
}
client.sceneNum = payload["sceneNum"].get<s16>();
client.entranceIndex = payload["entranceIndex"].get<s32>();
client.linkAge = payload["linkAge"].get<s32>();
client.posRot = payload["posRot"].get<PosRot>();
std::vector<int> jointArray = payload["jointTable"];
for (int i = 0; i < 24; i++) {
client.jointTable[i].x = jointArray[i * 3];
client.jointTable[i].y = jointArray[i * 3 + 1];
client.jointTable[i].z = jointArray[i * 3 + 2];
}
client.movementFlags = payload["movementFlags"].get<u8>();
client.prevTransl = payload["prevTransl"].get<Vec3s>();
client.upperLimbRot = payload["upperLimbRot"].get<Vec3s>();
client.currentBoots = payload["currentBoots"].get<s8>();
client.currentShield = payload["currentShield"].get<s8>();
client.currentTunic = payload["currentTunic"].get<s8>();
client.stateFlags1 = payload["stateFlags1"].get<u32>();
client.stateFlags2 = payload["stateFlags2"].get<u32>();
client.buttonItem0 = payload["buttonItem0"].get<u8>();
client.itemAction = payload["itemAction"].get<s8>();
client.heldItemAction = payload["heldItemAction"].get<s8>();
client.modelGroup = payload["modelGroup"].get<u8>();
client.invincibilityTimer = payload["invincibilityTimer"].get<s8>();
client.unk_862 = payload["unk_862"].get<s16>();
client.unk_85C = payload["unk_85C"].get<f32>();
client.actionVar1 = payload["actionVar1"].get<s8>();
}
}