64 lines
5.3 KiB
Python
64 lines
5.3 KiB
Python
"""Execute station handover with native manager/world boundaries doubled."""
|
|
from policy_harness import ROOT, body, run
|
|
p=ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainSupportStations.c'
|
|
def cpp(signature):
|
|
s=body(p,signature)
|
|
for a,b in [('int restored;', 'int restored=0;'),('protected ',''),('override ',''),('SCR_SupportStationManagerComponent manager','Manager* manager'),('SCR_SupportStationManagerComponent original','Manager* original'),('array<SCR_BaseSupportStationComponent> stations','Array<Station*>& stations'),('array<SCR_BaseSupportStationComponent> registered','Array<Station*>* registered'),('foreach (SCR_BaseSupportStationComponent station : registered)','for (Station* station : *registered)'),('foreach (SCR_BaseSupportStationComponent station : m_ERRTerrainSupportStations)','for (Station* station : m_ERRTerrainSupportStations)'),('IEntity owner','Owner* owner'),('station.', 'station->'),('manager.', 'manager->'),('original.', 'original->'),('owner.', 'owner->'),('GetGame().', 'GetGame()->'),('EDamageState.DESTROYED','2'),('super.', 'Base::')]: s=s.replace(a,b)
|
|
return s
|
|
run(r'''
|
|
#include <cassert>
|
|
#include <algorithm>
|
|
#include <vector>
|
|
struct Station;struct Manager;struct Game;
|
|
template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;void Clear(){this->clear();}void Insert(T v){this->push_back(v);}bool Contains(T v){return std::find(this->begin(),this->end(),v)!=this->end();}};
|
|
struct World{} world,otherWorld;
|
|
struct Owner{World* world=&::world;World* GetWorld(){return world;}};
|
|
struct Base{int cleaned=0;void OnBeforeWorldCleanup(){cleaned++;}void ERR_TerrainStationRestored(Manager*){}};
|
|
template<class...T>void PrintFormat(T...){}
|
|
struct Game:Base{Array<Station*> m_ERRTerrainSupportStations;World* GetWorld(){return &world;}
|
|
void ERR_CaptureTerrainSupportStations(Manager*);
|
|
void ERR_RestoreTerrainSupportStations(Manager*);
|
|
void OnBeforeWorldCleanup();
|
|
} game;
|
|
Game* current=&game;Game* GetGame(){return current;}
|
|
struct Station:Base{Owner own;Owner* owner=&own;int m_eCurrentDamageState=0;bool ranged=true;
|
|
bool m_ERRItemStationInitialized=true;Manager* m_ERRItemStationManager=nullptr;
|
|
Owner* GetOwner(){return owner;}bool UsesRange(){return ranged;}
|
|
'''+cpp('bool ERR_CanRestoreTerrainStation(')+cpp('override void ERR_TerrainStationRestored(')+r'''
|
|
};
|
|
struct Map{std::vector<Array<Station*>*> lists;int Count(){return lists.size();}Array<Station*>* GetElement(int i){return lists[i];}};
|
|
struct Manager{Map m_mSupportStations;Array<Station*> accepted;void AddSupportStation(Station* s){if(!accepted.Contains(s))accepted.Insert(s);}
|
|
'''+cpp('void ERR_CollectTerrainStations(')+r'''
|
|
};
|
|
'''+cpp('void ERR_CaptureTerrainSupportStations(').replace('void ERR_', 'void Game::ERR_',1)+cpp('void ERR_RestoreTerrainSupportStations(').replace('void ERR_', 'void Game::ERR_',1)+cpp('override protected void OnBeforeWorldCleanup(').replace('void OnBefore','void Game::OnBefore',1)+r'''
|
|
int main(){
|
|
Station pump,item,destroyed,deleted,offWorld,nonRanged;
|
|
Manager old,replacement;
|
|
destroyed.m_eCurrentDamageState=2;deleted.owner=nullptr;offWorld.own.world=&otherWorld;nonRanged.ranged=false;
|
|
pump.m_ERRItemStationManager=&old;item.m_ERRItemStationManager=&old;
|
|
Array<Station*> fuel{&pump,&destroyed,nullptr,&deleted,&offWorld};
|
|
Array<Station*> repair{&item,&pump,&nonRanged};old.m_mSupportStations.lists={&fuel,&repair,nullptr};
|
|
game.ERR_CaptureTerrainSupportStations(&old);assert(game.m_ERRTerrainSupportStations.size()==6);
|
|
// The removed registry can disappear; the captured list is independent.
|
|
fuel.Clear();repair.Clear();
|
|
replacement.AddSupportStation(&item); // initialization races must not duplicate entries
|
|
game.ERR_RestoreTerrainSupportStations(&replacement);
|
|
assert(replacement.accepted.size()==2&&replacement.accepted.Contains(&pump)&&replacement.accepted.Contains(&item));
|
|
assert(pump.m_ERRItemStationManager==&replacement&&item.m_ERRItemStationManager==&replacement);
|
|
assert(game.m_ERRTerrainSupportStations.empty());
|
|
game.ERR_RestoreTerrainSupportStations(&replacement);assert(replacement.accepted.size()==2);
|
|
game.m_ERRTerrainSupportStations.Insert(&pump);game.ERR_RestoreTerrainSupportStations(nullptr);assert(game.m_ERRTerrainSupportStations.size()==1);
|
|
game.OnBeforeWorldCleanup();assert(game.m_ERRTerrainSupportStations.empty()&&game.cleaned==1);
|
|
game.m_ERRTerrainSupportStations.Insert(&pump);game.ERR_CaptureTerrainSupportStations(nullptr);assert(game.m_ERRTerrainSupportStations.empty());
|
|
current=nullptr;assert(!pump.ERR_CanRestoreTerrainStation());current=&game;
|
|
}
|
|
''')
|
|
core=p.parent
|
|
server=body(core/'ERR_TerrainTakeover.c','protected void ERR_StopOriginalTerrainMode(') if 'protected void ERR_StopOriginalTerrainMode(' in (core/'ERR_TerrainTakeover.c').read_text() else (core/'ERR_TerrainTakeover.c').read_text()
|
|
assert server.index('ERR_CaptureTerrainSupportStations(')<server.index('m_ERRTerrainOriginal.OnGameEnd()')
|
|
client=body(core/'ERR_TerrainTakeoverClient.c','void ERR_BeginClientTerrainTakeover(')
|
|
assert client.index('ERR_CaptureTerrainSupportStations(')<client.index('mode.OnGameEnd()')
|
|
init=body(p,'override void OnPostInit(')
|
|
assert 'ERR_TerrainTakeoverMode.Cast(owner) && GetInstance() == this' in init
|
|
print('PASS: support registrations survive takeover on both peers, deduplicate, skip invalid stations, update item cleanup and clear on world teardown')
|