Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
113 lines
9.1 KiB
Python
113 lines
9.1 KiB
Python
"""Native fixture cleanup and real SiteService admission wrapper, without engine claims."""
|
|
import os,re
|
|
from pathlib import Path
|
|
from policy_harness import ROOT,body,run
|
|
base=Path(os.environ.get('ERR_VEHICLE_NATIVE_ROOT',str(ROOT)))
|
|
source=base/'addons/core/Scripts/Game/ERR/00_Core/ERR_NativeVehicleSecurityProbe.c'
|
|
stop=body(source,'void Stop(').replace('null','nullptr')
|
|
stop=stop.replace('ChimeraCharacter character = ChimeraCharacter.Cast(m_Player);','ChimeraCharacter* character = m_Player;')
|
|
for name in ('m_Damage','m_Mode','character'):stop=stop.replace(name+'.',name+'->')
|
|
stop=stop.replace('m_Mode->Players().','m_Mode->Players()->').replace('ERR_Actors.','ERR_Actors::').replace('CompartmentAccessComponent.','CompartmentAccessComponent::')
|
|
run('''#include <cassert>
|
|
struct Damage {bool enabled=true;int changes=0;void EnableDamageHandling(bool b){enabled=b;changes++;}};
|
|
struct ChimeraCharacter {bool awake=true,aboard=false;int teleports=0;void Teleport(int){teleports++;}};
|
|
struct Roster {ChimeraCharacter* current=nullptr;bool CurrentActor(ChimeraCharacter* e){return current==e;}};
|
|
struct Mode {Roster roster;bool hasRoster=true;Roster* Players(){return hasRoster?&roster:nullptr;}};
|
|
struct ERR_Actors{static bool CanFight(ChimeraCharacter* c){return c&&c->awake;}};
|
|
struct CompartmentAccessComponent {static bool GetVehicleIn(ChimeraCharacter* c){return c&&c->aboard;}};
|
|
struct Probe {bool m_Stopped=false,m_Moved=true,m_DamageChanged=true,m_PreviousDamageEnabled=true;Damage* m_Damage;Mode* m_Mode;ChimeraCharacter* m_Player;int m_Original=0;
|
|
'''+stop+'''
|
|
};
|
|
int main(){
|
|
Damage damage;Mode mode;ChimeraCharacter oldBody,replacement;mode.roster.current=&oldBody;
|
|
Probe p;p.m_Damage=&damage;p.m_Mode=&mode;p.m_Player=&oldBody;
|
|
damage.enabled=false;p.Stop();assert(damage.enabled&&damage.changes==1&&oldBody.teleports==1);
|
|
p.Stop();assert(damage.changes==1&&oldBody.teleports==1); // idempotent
|
|
p.m_Stopped=false;p.m_Moved=true;p.m_Damage=&damage;p.m_DamageChanged=true;p.m_PreviousDamageEnabled=false;mode.roster.current=&replacement;
|
|
p.Stop();assert(!damage.enabled&&damage.changes==2&&replacement.teleports==0&&oldBody.teleports==1); // restore exact old damage state, no stale-body teleport
|
|
p.m_Stopped=false;p.m_Damage=&damage;p.m_DamageChanged=false; // rejected before protection applied
|
|
p.Stop();assert(damage.changes==2);
|
|
p.m_Stopped=false;p.m_Damage=&damage;p.m_DamageChanged=true;p.m_PreviousDamageEnabled=true;mode.roster.current=&oldBody;oldBody.awake=false;
|
|
p.Stop();assert(damage.enabled&&damage.changes==3&&oldBody.teleports==1);
|
|
p.m_Stopped=false;p.m_Damage=&damage;p.m_DamageChanged=true;oldBody.awake=true;oldBody.aboard=true;
|
|
p.Stop();assert(damage.changes==4&&oldBody.teleports==1);
|
|
p.m_Stopped=false;p.m_Damage=&damage;p.m_DamageChanged=true;mode.hasRoster=false;
|
|
p.Stop();assert(damage.changes==5&&oldBody.teleports==1);
|
|
}
|
|
''')
|
|
text=source.read_text();tick=body(source,'int Tick(');inspect=body(source,'protected bool Inspect(')
|
|
assert tick.index('CurrentActor(m_Player)') < tick.index('m_Damage.EnableDamageHandling(false)') < tick.index('Teleport(transform)')
|
|
assert 'ERR_Actors.Spawn(' not in text and 'GetInVehicle(' not in text and 'SetTotalFuel' not in text
|
|
assert 'seats.Count() == 5' in inspect and 'slot.GetGetInAction()' in inspect
|
|
assert 'front == 2 && rear == 3' in inspect and 'doors.Count() == 4' in inspect
|
|
assert 'ERR_VehicleSecurityComponent.Find(action.GetOwner()) == m_Security' in inspect
|
|
assert '!action.CanBePerformedScript(m_Player)' in inspect and 'action.PerformAction(action.GetOwner(), m_Player);' in inspect
|
|
assert '!door.CanBePerformedScript(m_Player)' in inspect and 'door.PerformAction(door.GetOwner(), m_Player);' in inspect
|
|
assert 'm_Security.CanBreach(m_Player, reason)' in tick and '!m_Security.TryBreach(m_Player)' in tick
|
|
assert 'DriverAvailable()' in tick
|
|
assert 'm_DriverAction.CanBePerformedScript(m_Player)' in body(source,'protected bool DriverAvailable(')
|
|
transport=(base/'addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportProbe.c').read_text()
|
|
smoke=(base/'addons/core/Scripts/Game/ERR/00_Core/ERR_NativeBaseSmoke.c').read_text()
|
|
assert 'new ERR_NativeTransportProbe(this, m_ERRBasePlayer)' in smoke and 'if (m_ERRTransportProbe) m_ERRTransportProbe.Stop();' in smoke
|
|
assert transport.index('m_SecurityProbe.Tick(now)') < transport.index('IEntity driver = Character(0)')
|
|
assert 'void Stop() { if (m_SecurityProbe) m_SecurityProbe.Stop(); }' in transport
|
|
print('PASS: actual native-prelude cleanup restores only original changed damage, refuses stale/incapacitated/aboard teleport; bounded five-seat/four-door fixture wiring checked. Native execution remains pending.')
|
|
|
|
# Existing transport tests did not extract CreateTransport. Test its real new
|
|
# Configure hook with native construction/FindComponent calls represented by doubles.
|
|
site=ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c'
|
|
create=body(site,'protected bool CreateTransport(').replace('protected ','').replace('null','nullptr')
|
|
for name in ('ERR_SiteRuntime','ERR_SiteTransport','CarControllerComponent','ERR_VehicleSecurityComponent'):
|
|
create=re.sub(r'\b'+name+r' (\w+)',name+r'* \1',create)
|
|
for name in ('site','spec','controller','security'):create=create.replace(name+'.',name+'->')
|
|
create=create.replace('site->Definition.','site->Definition->').replace('GetGame().GetWorld().GetWorldTime()', '0')
|
|
create=create.replace('ERR_Actors.','ERR_Actors::').replace('ERR_VehicleSecurityComponent.','ERR_VehicleSecurityComponent::')
|
|
create=create.replace('Vehicle.Cast(entity)','CastVehicle(entity)').replace('CarControllerComponent.Cast(site->Transport.FindComponent(CarControllerComponent))','FindController(site->Transport)')
|
|
run('''#include <cassert>
|
|
#include <string>
|
|
#include <vector>
|
|
using string=std::string;using vector=int;
|
|
int Vector(int x,int,int){return x;}
|
|
struct CarControllerComponent {bool parked=false;void SetPersistentHandBrake(bool b){parked=b;}};
|
|
struct Entity;
|
|
struct ERR_VehicleSecurityComponent {CarControllerComponent* controller;bool result=true;int calls=0;bool Configure(){assert(controller&&controller->parked);calls++;return result;}static ERR_VehicleSecurityComponent* Find(Entity* e);};
|
|
struct Entity {bool vehicle=true;CarControllerComponent* controller=nullptr;ERR_VehicleSecurityComponent* security=nullptr;};using IEntity=Entity*;
|
|
ERR_VehicleSecurityComponent* ERR_VehicleSecurityComponent::Find(Entity* e){return e->security;}
|
|
IEntity CastVehicle(IEntity e){return e->vehicle?e:nullptr;}
|
|
CarControllerComponent* FindController(IEntity e){return e->controller;}
|
|
struct ERR_SiteTransport {bool Optional=false;int Offset=0,ClearanceRadius=4,MaximumTerrainRange=1,Prefab=123,Heading=180;};
|
|
struct Definition {ERR_SiteTransport* Transport=nullptr;string Id="supply";};
|
|
struct ERR_SiteRuntime {struct Definition* Definition;IEntity Transport=nullptr,TransportEntity=nullptr;bool TransportAttempted=false,TransportOmitted=false;float TransportDeadline=-1;};
|
|
struct ERR_Actors {static IEntity spawned;static int calls;static int Ground(int p){return p;}static IEntity Spawn(int,int,int){calls++;return spawned;}};IEntity ERR_Actors::spawned=nullptr;int ERR_Actors::calls=0;
|
|
struct Array:std::vector<IEntity>{void Insert(IEntity e){push_back(e);}};
|
|
struct Service{bool clear=true;string failure;Array m_Entities;bool Fail(string s){failure=s;return false;}bool TransportFailure(ERR_SiteRuntime*,string s){return Fail(s);}bool TransportClearance(int,int,int){return clear;}
|
|
'''+create+'''
|
|
};
|
|
int main(){
|
|
{Service service;Definition def;ERR_SiteRuntime site{&def};assert(service.CreateTransport(&site,0)&&ERR_Actors::calls==0&&!site.TransportAttempted);}
|
|
for(int fault=0;fault<6;fault++){
|
|
Service service;Definition def;ERR_SiteRuntime site{&def};ERR_SiteTransport spec;def.Transport=&spec;
|
|
Entity vehicle;CarControllerComponent controller;ERR_VehicleSecurityComponent security;vehicle.controller=&controller;security.controller=&controller;vehicle.security=&security;
|
|
ERR_Actors::spawned=&vehicle;ERR_Actors::calls=0;
|
|
if(fault==0){service.clear=false;}
|
|
if(fault==1){ERR_Actors::spawned=nullptr;}
|
|
if(fault==2){vehicle.vehicle=false;}
|
|
if(fault==3){vehicle.controller=nullptr;}
|
|
if(fault==4){security.result=false;}
|
|
bool success=service.CreateTransport(&site,0);
|
|
assert(success==(fault==5)&&site.TransportAttempted);
|
|
assert(ERR_Actors::calls==(fault==0?0:1));
|
|
if(fault>=2){assert(service.m_Entities.back()==&vehicle&&site.TransportEntity==&vehicle);}
|
|
if(fault>=4){assert(controller.parked&&security.calls==1);}
|
|
if(fault==4){assert(service.failure.find("security configuration")!=string::npos);}
|
|
if(fault==5){assert(site.Transport==&vehicle);assert(service.CreateTransport(&site,0)&&ERR_Actors::calls==1&&security.calls==1);}
|
|
}
|
|
// Ordinary unlocked vehicle preserves the original successful path.
|
|
{Service service;Definition def;ERR_SiteRuntime site{&def};ERR_SiteTransport spec;def.Transport=&spec;
|
|
Entity vehicle;CarControllerComponent controller;vehicle.controller=&controller;ERR_Actors::spawned=&vehicle;
|
|
assert(service.CreateTransport(&site,0)&&controller.parked);}
|
|
|
|
}
|
|
''')
|
|
print('PASS: actual CreateTransport requires successful scoped Configure after handbrake, preserves ordinary vehicles, tracks spawned entity before failures and never treats failed lock registration as ready.')
|