Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
58 lines
4.6 KiB
Python
58 lines
4.6 KiB
Python
"""Execute production guards for the 29 September server exceptions."""
|
|
from policy_harness import ROOT, body, run
|
|
core=ROOT/'addons/core/Scripts/Game/ERR/00_Core'
|
|
ai=ROOT/'addons/core/Scripts/Game/ERR/10_AI'
|
|
mark=body(ai/'ERR_EnemyMapMarking.c','override void MarkTarget(')
|
|
mark=mark.replace('override ','').replace('notnull SCR_AITargetInfo targetInfo','Target* targetInfo').replace('notnull SCR_AIGroup spottingGroup','Group* spottingGroup').replace('targetInfo.','targetInfo->').replace('spottingGroup.','spottingGroup->').replace('super.MarkTarget','NativeMark')
|
|
run('''#include <cassert>
|
|
struct Target{void* m_Faction=nullptr;void* m_Entity=nullptr;};
|
|
struct Group{void* leader=nullptr;void* GetLeaderEntity(){return leader;}};
|
|
struct Marking{int marks=0;void NativeMark(Target*,Group*){marks++;}
|
|
'''+mark+'''};
|
|
int main(){Marking m;Target t;Group g;g.leader=&g;t.m_Entity=&t;
|
|
for(int i=0;i<1100;i++){m.MarkTarget(&t,&g);}assert(!m.marks&&!t.m_Faction&&t.m_Entity==&t);
|
|
t.m_Faction=&t;t.m_Entity=nullptr;m.MarkTarget(&t,&g);assert(!m.marks);
|
|
t.m_Entity=&t;g.leader=nullptr;m.MarkTarget(&t,&g);assert(!m.marks);
|
|
g.leader=&g;m.MarkTarget(&t,&g);assert(m.marks==1);}
|
|
''')
|
|
methods='\n'.join(body(core/'ERR_GameMode.c',f'Faction {side}Faction(') for side in ['Player','Enemy'])
|
|
methods=methods.replace('FactionManager manager','Manager* manager').replace('Faction ','Faction* ').replace('GetGame().','GetGame()->').replace('manager.','manager->').replace('m_Factions.','m_Factions->').replace('return null','return nullptr')
|
|
run('''#include <cassert>
|
|
#include <string>
|
|
struct Key:std::string{using std::string::operator=;bool IsEmpty(){return empty();}};
|
|
struct Faction{} player,enemy;
|
|
struct Manager{Faction* GetFactionByKey(Key k){return k=="player"?&player:&enemy;}};
|
|
struct Game{Manager* manager=nullptr;Manager* GetFactionManager(){return manager;}};
|
|
Game* game=nullptr;Game* GetGame(){return game;}
|
|
struct Catalog{int queries=0;Faction* PlayerFaction(){queries++;return &player;}Faction* EnemyFaction(){queries++;return &enemy;}};
|
|
struct Mode{Catalog* m_Factions=nullptr;Key m_SelectedPlayerFaction,m_SelectedEnemyFaction;
|
|
'''+methods+'''};
|
|
int main(){Mode m;Catalog c;Game g;Manager mgr;
|
|
assert(!m.PlayerFaction()&&!m.EnemyFaction());m.m_Factions=&c;
|
|
assert(!m.PlayerFaction()&&!m.EnemyFaction());game=&g;
|
|
assert(!m.PlayerFaction()&&!m.EnemyFaction()&&!c.queries);g.manager=&mgr;
|
|
assert(m.PlayerFaction()==&player&&m.EnemyFaction()==&enemy&&c.queries==2);
|
|
m.m_SelectedPlayerFaction="player";m.m_SelectedEnemyFaction="enemy";
|
|
assert(m.PlayerFaction()==&player&&m.EnemyFaction()==&enemy&&c.queries==2);
|
|
g.manager=nullptr;assert(!m.PlayerFaction()&&!m.EnemyFaction()&&c.queries==2);}
|
|
''')
|
|
# Execute actual deletion callback; capture queries/engine writes must never run
|
|
# in either active-entity deletion or late world teardown.
|
|
delete=body(ai/'ERR_ReconFlightComponent.c','override void OnDelete(')
|
|
delete=delete.replace('override ','').replace('IEntity owner','int owner').replace('Replication.','Replication::').replace('ERR_HQ hq = ERR_HQ.Get();','HQ* hq = HQ::Get();').replace('m_Mode.','m_Mode->').replace('hq.','hq->').replace('Recon().','Recon()->').replace('super.OnDelete','NativeDelete')
|
|
release=body(ai/'ERR_ReconFlightComponent.c','void Release(').replace('ERR_ReconPhase.','Phase::').replace('EntityEvent.SIMULATE','1')
|
|
run('''#include <cassert>
|
|
namespace Phase{enum{CREW,RELEASED};}
|
|
struct Replication{static bool IsServer(){return true;}};
|
|
struct Mode{bool Active(){return true;}};
|
|
struct HQ{int removed=0;static HQ* instance;static HQ* Get(){return instance;}HQ* Recon(){return this;}void Removed(void*){removed++;}};
|
|
HQ* HQ::instance=nullptr;
|
|
struct Flight{int m_Phase=Phase::CREW,queries=0,engines=0,cleared=0,deleted=0;bool m_Aircraft=true,locked=true;Mode* m_Mode=nullptr;
|
|
int GetOwner(){return 1;}void ClearEventMask(int,int){cleared++;}bool Captured(){queries++;return false;}void Engines(bool){engines++;}void Locks(bool v){locked=v;}void NativeDelete(int){deleted++;}
|
|
'''+release+'\n'+delete+'''};
|
|
int main(){Flight teardown;teardown.OnDelete(1);assert(!teardown.queries&&!teardown.engines&&!teardown.locked&&teardown.cleared==1&&teardown.deleted==1);
|
|
HQ hq;HQ::instance=&hq;Mode mode;Flight active;active.m_Mode=&mode;active.OnDelete(1);assert(hq.removed==1&&!active.queries&&!active.engines&&!active.locked);
|
|
Flight normal;normal.Release(false);assert(normal.queries==1&&normal.engines==1&&!normal.locked);normal.Release(false);assert(normal.engines==1&&normal.cleared==1);}
|
|
''')
|
|
print('PASS: factionless/deleted map targets do not abort perception; faction lookup tolerates teardown; deleting helicopter releases without capture/engine access')
|