"""Native chat stays world-owned across server/client terrain handover.""" from policy_harness import ROOT, body, run core = ROOT / 'addons/core/Scripts/Game/ERR/00_Core' server = core / 'ERR_TerrainTakeover.c' client = core / 'ERR_TerrainTakeoverClient.c' managers = core / 'ERR_TerrainTakeoverManagers.c' run('#include \n#include \nusing ResourceName=std::string;\n' + body(server, 'static ResourceName Bootstrap(') + r''' int main(){ assert(Bootstrap(true)=="{9D182739ABEF405C}Prefabs/ERR/TerrainTakeover.et"); assert(Bootstrap(false)=="{DA8E364BC095712F}Prefabs/ERR/TerrainTakeoverWithChat.et"); } ''') retain = body(managers, 'static bool RetainManager(') retain = (retain.replace('IEntity entity', 'IEntity* entity') .replace('IEntity ancestor', 'IEntity* ancestor') .replace('array removed', 'Entities* removed') .replace('RplComponent rpl', 'RplComponent* rpl') .replace('SCR_EntityHelper.', 'SCR_EntityHelper::') .replace('null', 'nullptr')) for value in ('entity', 'ancestor', 'removed', 'rpl', 'GetParent()', 'GetNode()'): retain = retain.replace(value + '.', value + '->') run(r''' #include #include #include struct Node {Node* parent=nullptr;int changes=0;void SetParent(Node* p){parent=p;changes++;}}; struct RplComponent {Node* node=nullptr;Node* GetNode(){return node;}}; struct IEntity { IEntity* parent=nullptr;RplComponent* rpl=nullptr;bool refuseDetach=false;int removals=0; IEntity* GetParent(){return parent;} void RemoveChild(IEntity* child,bool keepWorld){assert(keepWorld&&child->parent==this);removals++;if(!refuseDetach)child->parent=nullptr;} }; struct Entities:std::vector { using std::vector::vector; bool Contains(IEntity* entity){return std::find(begin(),end(),entity)!=end();} }; namespace SCR_EntityHelper {RplComponent* GetEntityRplComponent(IEntity* e){return e->rpl;}} ''' + retain + r''' int main(){ IEntity oldMode,chat,intermediate,unrelated;Entities removed{&oldMode,nullptr}; Node oldNode,chatNode;chatNode.parent=&oldNode;RplComponent chatRpl{&chatNode};chat.rpl=&chatRpl; // Ordinary terrain chat is standalone: no unregister, replacement or reparent. assert(RetainManager(&chat,&removed)&&chat.parent==nullptr&&chatNode.changes==0); // Nested chat is detached before old hierarchy deletion; replication cannot // later remove the retained service with the discarded mode either. intermediate.parent=&oldMode;chat.parent=&intermediate; assert(RetainManager(&chat,&removed)&&chat.parent==nullptr&&intermediate.removals==1); assert(chatNode.parent==nullptr&&chatNode.changes==1); assert(RetainManager(&chat,&removed)&&chatNode.changes==1); chat.parent=&unrelated;assert(RetainManager(&chat,&removed)&&chat.parent==&unrelated&&unrelated.removals==0); assert(!RetainManager(nullptr,&removed)&&!RetainManager(&chat,nullptr)); removed.push_back(&chat);assert(!RetainManager(&chat,&removed)&&chat.parent==&unrelated);removed.pop_back(); oldMode.refuseDetach=true;chat.parent=&oldMode;int changes=chatNode.changes; assert(!RetainManager(&chat,&removed)&&chat.parent==&oldMode&&chatNode.changes==changes); oldMode.refuseDetach=false;chat.rpl=nullptr;assert(RetainManager(&chat,&removed)&&chat.parent==nullptr); } ''') drain = body(server, 'protected void ERR_DrainTerrainMode(') capture = body(client, 'void ERR_ClientCaptureOriginal(') handover = body(client, 'void ERR_BeginClientTerrainTakeover(') assert 'GetChat()' not in drain.split('array managers =', 1)[1].split(';', 1)[0] assert 'm_ERRClientOldManagers.Insert(GetChat())' not in capture assert drain.index('RetainManager(m_ERRTerrainChat, managers)') < drain.index('m_ERRTerrainOriginal.OnGameEnd()') assert handover.index('RetainManager(GetChat(), m_ERRClientOldManagers)') < handover.index('mode.OnGameEnd()') assert 'GetChat() == m_ERRTerrainChat' in body(server, 'protected bool ERR_TerrainRegistrationsEmpty(') assert 'm_ERRTerrainChat = null' in body(server, 'protected void ERR_ResetTerrainTakeover(') preflight = body(server, 'protected bool ERR_PreflightTerrainTakeover(') create = body(server, 'protected void ERR_CreateTerrainMode(') assert 'Bootstrap(GetChat() != null)' in preflight assert 'if (!GetChat())' not in preflight assert 'Bootstrap(m_ERRTerrainChat != null)' in create assert 'Link(mode, !m_ERRTerrainChat)' in create assert 'if (m_ERRTerrainChat && !ERR_TerrainTakeoverReplication.RetainManager' in drain assert 'if (GetChat() && !ERR_TerrainTakeoverReplication.RetainManager' in handover assert '&& m_ERRTerrainChat &&' not in body(server, 'protected bool ERR_TerrainRegistrationsEmpty(') assert 'if (ownsChat && !Parent(GetGame().GetChat(), mode)) return false' in body(managers, 'static bool Link(') prefabs = ROOT / 'addons/core/Prefabs/ERR' assert 'ScriptedChatEntity' not in (prefabs / 'TerrainTakeover.et').read_text() fallback = (prefabs / 'TerrainTakeoverWithChat.et').read_text() assert '"{9D182739ABEF405C}Prefabs/ERR/TerrainTakeover.et"' in fallback assert fallback.count('ScriptedChatEntity Chat') == 1 assert 'Streamable Disabled' in fallback assert '{DA8E364BC095712F}Prefabs/ERR/TerrainTakeoverWithChat.et' in (prefabs / 'TerrainTakeoverWithChat.et.meta').read_text() assert 'ScriptedChatEntity' in (prefabs / 'TerrainConnector.et').read_text() assert 'ScriptedChatEntity' in (ROOT / 'addons/core/Worlds/ERR_Everon_Layers/default.layer').read_text() print('PASS: native chat retained on both peers, nested ownership detached, absent chat supplied by replicated fallback, authored mission chat preserved')