From d327b580e747fce84ac309d8fcd1d7801a9dc457 Mon Sep 17 00:00:00 2001 From: tens0rfl0w Date: Mon, 7 Oct 2024 23:56:18 +0200 Subject: [PATCH] tweak(gamestate/server): Apply routing bucket changes to child attachments This applies routing bucket changes to child attachments of the entity that got its bucket changed. --- .../src/state/ServerGameState_Scripting.cpp | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/code/components/citizen-server-impl/src/state/ServerGameState_Scripting.cpp b/code/components/citizen-server-impl/src/state/ServerGameState_Scripting.cpp index 619d155541..64b5fa580d 100644 --- a/code/components/citizen-server-impl/src/state/ServerGameState_Scripting.cpp +++ b/code/components/citizen-server-impl/src/state/ServerGameState_Scripting.cpp @@ -17,6 +17,78 @@ namespace fx void DisownEntityScript(const fx::sync::SyncEntityPtr& entity); } +namespace +{ + bool IsAttachedToRootEntity(const fx::sync::SyncEntityPtr& entity, + const fx::sync::SyncEntityPtr& rootEntity, + const fwRefContainer& gameState, + std::unordered_set& visitedEntities, + std::unordered_set& rootConnectedEntities) + { + if (rootConnectedEntities.find(entity->handle) != rootConnectedEntities.end()) + { + return true; + } + + if (visitedEntities.find(entity->handle) != visitedEntities.end()) + { + return false; + } + + visitedEntities.insert(entity->handle); + + if (entity->syncTree) + { + const fx::sync::CBaseAttachNodeData* attachment = entity->syncTree->GetAttachment(); + + if (attachment && attachment->attached && attachment->attachedTo) + { + const auto parentEntity = gameState->GetEntity(0, attachment->attachedTo); + + if (parentEntity) + { + if (parentEntity == rootEntity || IsAttachedToRootEntity(parentEntity, rootEntity, gameState, visitedEntities, rootConnectedEntities)) + { + if (entity->type == fx::sync::NetObjEntityType::Player) + { + if (const auto client = entity->GetClient()) + { + auto [lock, clientData] = gameState->ExternalGetClientData(client); + gameState->ClearClientFromWorldGrid(client); + clientData->routingBucket = parentEntity->routingBucket; + } + } + + entity->routingBucket = parentEntity->routingBucket; + + rootConnectedEntities.insert(entity->handle); + + return true; + } + } + } + } + + return false; + } + + void SetRoutingBucketForAttachedEntities(const fx::sync::SyncEntityPtr& rootEntity) + { + const auto resourceManager = fx::ResourceManager::GetCurrent(); + const auto instance = resourceManager->GetComponent()->Get(); + const auto gameState = instance->GetComponent(); + + std::unordered_set visitedEntities; + std::unordered_set rootConnectedEntities; + + std::shared_lock lock(gameState->m_entityListMutex); + for (auto& entity : gameState->m_entityList) + { + IsAttachedToRootEntity(entity, rootEntity, gameState, visitedEntities, rootConnectedEntities); + } + } +} + static void Init() { auto makeEntityFunction = [](auto fn, uintptr_t defaultValue = 0) @@ -1550,6 +1622,7 @@ static void Init() if (playerEntity) { playerEntity->routingBucket = bucket; + SetRoutingBucketForAttachedEntities(playerEntity); } } } @@ -1571,6 +1644,7 @@ static void Init() if (bucket >= 0) { entity->routingBucket = bucket; + SetRoutingBucketForAttachedEntities(entity); } }