Files
EscapistsReintroduced/tests/test_infantry_ammo_transfer.py
T
jakub cab998fb64 Combine Workshop addon and fix prison startup
Merge owned systems into one addon while preserving resource identities. Gate player admission on the replicated prison scene, restore the original framed door, and hold enemy AI until escape. Correct scenario branding and author metadata, include publishing assets, and retain regression and native verification evidence.
2026-09-20 16:42:52 +02:00

226 lines
24 KiB
Python

"""Execute the actual finite native magazine transaction; engine behavior remains separate."""
from pathlib import Path
import os,re
from policy_harness import ROOT,run,body
p=Path(os.environ.get('ERR_INFANTRY_TRANSFER_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoTransfer.c'))
s=p.read_text()
for forbidden in ('TrySpawn','DeleteEntity','SetOrigin','SetTransform','TryInsert','TryRemove','SetAmmoCount'):
assert forbidden not in s,forbidden
callback=s[s.index('class ERR_InfantryAmmoCallback'):s.index('// One exact physical')]
code=s[s.index('class ERR_InfantryAmmoTransfer\n'):]
code=re.sub(r'//[^\n]*','',code).replace('protected ','').replace('class ','struct ')
for src,dst in {
'BaseMagazineComponent.Cast(exactMagazine.FindComponent(BaseMagazineComponent))':'exactMagazine->magazine',
'BaseWeaponManagerComponent.Cast(actor.FindComponent(BaseWeaponManagerComponent))':'actor->weapons',
'BaseWeaponComponent.Cast(rifle.FindComponent(BaseWeaponComponent))':'rifle->weapon',
'InventoryItemComponent.Cast(entity.FindComponent(InventoryItemComponent))':'entity->item',
'InventoryItemComponent.Cast(m_Magazine.FindComponent(InventoryItemComponent))':'m_Magazine->item',
'SCR_AIVehicleUsageComponent.Cast(m_Donor.FindComponent(SCR_AIVehicleUsageComponent))':'m_Donor->usage',
'InventoryStorageManagerComponent.Cast(m_Donor.FindComponent(InventoryStorageManagerComponent))':'m_Donor->inventory',
'InventoryStorageManagerComponent.Cast(m_Recipient.FindComponent(InventoryStorageManagerComponent))':'m_Recipient->inventory',
}.items():code=code.replace(src,dst)
code=code.replace('ref ERR_InfantryAmmoCallback','ERR_InfantryAmmoCallback*').replace('array<','Array<').replace('foreach (','for (').replace('null','nullptr')
code=re.sub(r'\bERR_GameMode (?=\w)','ERR_GameMode* ',code)
code=code.replace('void ERR_InfantryAmmoTransfer(','ERR_InfantryAmmoTransfer(').replace('EWeaponType kind','int kind').replace('EMuzzleType muzzleKind','int muzzleKind')
for name in ('ERR_InfantryAmmoTransferState','ERR_InfantryAmmoAccess','ERR_GameMode','ERR_EnemyEquipmentRules','ERR_ForceRules','Replication','SCR_Global','ERR_Actors','SCR_FactionManager','ERR_ConvoyRules','CompartmentAccessComponent','EWeaponType','EMuzzleType','EStoragePurpose','vector'):
code=code.replace(name+'.',name+'::')
for name in ('m_Mode','m_Donor','m_DonorGroup','m_Recipient','m_RecipientGroup','m_Source','m_Destination','m_Storage','m_Callback','magazine','manager','weapon','muzzle','entity','item','storage','inventory','donorRecord','recipientRecord','utility','usage','physics'):
code=re.sub(r'\b'+name+r'\.',name+'->',code)
code=code.replace('GetMagazineWell().','GetMagazineWell()->').replace('GetParentSlot().','GetParentSlot()->').replace('Forces().','Forces()->').replace('m_VehicleMgr.','m_VehicleMgr->').replace('GetPilotCompartmentSlot().','GetPilotCompartmentSlot()->')
code=re.sub(r'\b(bool|int|Vehicle|IEntity|SCR_AIGroup|ERR_ForceRecord|InventoryStorageManagerComponent|BaseInventoryStorageComponent|ERR_GameMode\*|ERR_InfantryAmmoCallback\*) (\w+);',r'\1 \2{};',code)
code=code.replace('\n}\n','\n};\n')
callback=callback.replace('class ERR_InfantryAmmoCallback : ScriptedInventoryOperationCallback','').strip()[1:-1]
callbacks=[]
for name in ('OnComplete','OnFailed','OnAllComplete','OnAllFailed'):
m=re.search(r'protected override void '+name+r'\(\) (\{[^\n]+\})',callback)
callbacks.append('void ERR_InfantryAmmoCallback::'+name+'() '+m[1].replace('Transfer.','Transfer->'))
# Integrate the actual coordinator transfer selector with this actual leaf.
coordinator_path=Path(os.environ.get('ERR_INFANTRY_RESUPPLY_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c'))
transfer=body(coordinator_path,'protected void Transfer(float now)').replace('protected ','').replace('null','nullptr').replace('foreach (','for (')
transfer=transfer.replace('ERR_HQAmmoSnapshot local','ERR_HQAmmoSnapshot* local')
for name in ('ERR_Actors','ERR_HQAmmoSampler','ERR_InfantryAmmoTransfer','vector'):
transfer=transfer.replace(name+'.',name+'::')
for name in ('m_Move','actor','m_Truck','m_Recipient','local'):
transfer=transfer.replace(name+'.',name+'->')
transfer=transfer.replace('Entity.GetOrigin()', 'Entity->GetOrigin()')
pre=r'''
#include <cassert>
#include <cmath>
#include <string>
#include <vector>
#include <algorithm>
#include <limits>
#include <functional>
using string=std::string;
template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;int Count(){return this->size();}bool IsEmpty(){return this->empty();}void Insert(T t){this->push_back(t);}void RemoveItem(T t){this->erase(std::remove(this->begin(),this->end(),t),this->end());}bool Contains(T t){return std::find(this->begin(),this->end(),t)!=this->end();}};
struct vector{float x=0,y=0,z=0;float Length(){return std::sqrt(x*x+y*y+z*z);}static float DistanceXZ(vector a,vector b){return std::hypot(a.x-b.x,a.z-b.z);}static float Distance(vector a,vector b){return vector{a.x-b.x,a.y-b.y,a.z-b.z}.Length();}};
struct Entity;struct Group;struct Inventory;struct Storage;struct Item;struct Slot;struct Magazine;struct Weapon;struct Muzzle;struct Manager;struct Utility;struct Usage;struct Physics_;struct Record;
using IEntity=Entity*;using Vehicle=Entity*;using SCR_AIGroup=Group*;using ERR_ForceRecord=Record*;
using InventoryStorageManagerComponent=Inventory*;using BaseInventoryStorageComponent=Storage*;using InventoryItemComponent=Item*;using BaseMagazineComponent=Magazine*;
using BaseWeaponManagerComponent=Manager*;using BaseWeaponComponent=Weapon*;using BaseMuzzleComponent=Muzzle*;
using SCR_AIGroupUtilityComponent=Utility*;using SCR_AIVehicleUsageComponent=Usage*;using Physics=Physics_*;
enum ERR_InfantryAmmoTransferState{FAILED=-1,PENDING,SUCCEEDED};
struct ERR_InfantryAmmoTransfer;
struct ScriptedInventoryOperationCallback{virtual void OnComplete(){}virtual void OnFailed(){}virtual void OnAllComplete(){}virtual void OnAllFailed(){}virtual ~ScriptedInventoryOperationCallback()=default;};
struct ERR_InfantryAmmoCallback:ScriptedInventoryOperationCallback{ERR_InfantryAmmoTransfer*Transfer=nullptr;void OnComplete()override;void OnFailed()override;void OnAllComplete()override;void OnAllFailed()override;};
struct EWeaponType{static const int WT_RIFLE=1,WT_SNIPERRIFLE=2,WT_MACHINEGUN=3,WT_HANDGUN=4,WT_GRENADELAUNCHER=5,WT_ROCKETLAUNCHER=6;};
struct EMuzzleType{static const int MT_BaseMuzzle=0,MT_UGLMuzzle=1,MT_RPGMuzzle=2;};struct EStoragePurpose{static const int PURPOSE_DEPOSIT=1;};
struct Well{int type=1,parent=0;int Type(){return type;}bool IsInherited(int t){return type==t||parent==t;}};
struct Magazine{Well*well=nullptr;int rounds=30,capacity=30;Well*GetMagazineWell(){return well;}int GetAmmoCount(){return rounds;}int GetMaxAmmoCount(){return capacity;}};
struct Muzzle{Well*well=nullptr;int kind=0;Well*GetMagazineWell(){return well;}int GetMuzzleType(){return kind;}};
struct Weapon{IEntity owner=nullptr;Array<Muzzle*>muzzles;int kind=1;IEntity GetOwner(){return owner;}int GetWeaponType(){return kind;}void GetMuzzlesList(Array<Muzzle*>&a){a=muzzles;}};
struct Manager{Array<IEntity>weapons;void GetWeaponsList(Array<IEntity>&a){a=weapons;}};
struct Storage{IEntity owner=nullptr;IEntity GetOwner(){return owner;}};
struct Slot{Storage*storage=nullptr;IEntity occupant=nullptr;Storage*GetStorage(){return storage;}IEntity GetOccupant(){return occupant;}};
struct Item{Slot*slot=nullptr;Slot*GetParentSlot(){return slot;}};
struct Physics_{vector velocity,angular;vector GetVelocity(){return velocity;}vector GetAngularVelocity(){return angular;}};
struct Usage{Slot*pilot=nullptr;Slot*GetPilotCompartmentSlot(){return pilot;}};
struct VehicleManager{IEntity vehicle=nullptr;IEntity FindVehicle(IEntity v){return vehicle==v?v:nullptr;}};
struct Utility{VehicleManager*m_VehicleMgr=nullptr;bool military=true;bool IsMilitary(){return military;}};
struct Group{int faction=1,players=0;bool slave=false;Utility*utility=nullptr;int GetPlayerCount(bool){return players;}int GetFaction(){return faction;}bool IsSlave(){return slave;}Utility*GetGroupUtilityComponent(){return utility;}};
struct Entity{bool alive=true,awake=true,player=false,captured=false;int faction=1;Group*group=nullptr;IEntity vehicle=nullptr,parent=nullptr;
Inventory*inventory=nullptr;Magazine*magazine=nullptr;Manager*weapons=nullptr;Weapon*weapon=nullptr;Item*item=nullptr;Usage*usage=nullptr;Physics_*physics=nullptr;vector position;
IEntity GetParent(){return parent;}Physics_*GetPhysics(){return physics;}vector GetOrigin(){return position;}};
struct Record{SCR_AIGroup Group=nullptr;bool Physical=true,Eliminated=false;};
struct Ledger{Array<Record*>records;Record*FindGroup(SCR_AIGroup g){for(auto*r:records)if(r->Group==g)return r;return nullptr;}};
struct ERR_GameMode{inline static ERR_GameMode*current=nullptr;bool active=true;Ledger*ledger=nullptr;static ERR_GameMode*Get(){return current;}bool Active(){return active;}Ledger*Forces(){return ledger;}int EnemyFaction(){return 1;}};
struct Replication{inline static bool server=true;static bool IsServer(){return server;}};
struct SCR_Global{inline static bool editor=false;static bool IsEditMode(){return editor;}};
struct ERR_Actors{static bool CanFight(IEntity a){return a&&a->alive&&a->awake;}static bool Alive(IEntity a){return a&&a->alive;}};
struct SCR_FactionManager{static int SGetFaction(IEntity a){return a?a->faction:-1;}};
struct CompartmentAccessComponent{static IEntity GetVehicleIn(IEntity a){return a?a->vehicle:nullptr;}};
struct ERR_ConvoyRules{static bool Captured(Vehicle v,SCR_AIGroup g){return v->captured||g->players>0;}static bool PartOf(IEntity a,IEntity root){return a==root;}};
struct ERR_EnemyEquipmentRules{static bool Eligible(ERR_GameMode*m,SCR_AIGroup g,IEntity a){return m&&g&&a&&a->alive&&a->awake&&!a->player&&a->group==g&&g->players==0&&g->faction==m->EnemyFaction()&&g->utility&&g->utility->military;}};
struct ERR_ForceRules{static bool Finite(float n){return std::isfinite(n);}};
struct ERR_InfantryAmmoAccess{static inline bool clear=true;static inline int checks=0;static bool Clear(Vehicle donor,IEntity recipient){assert(donor&&recipient);checks++;return clear;}};
struct Inventory{IEntity owner=nullptr;Array<IEntity>items;Array<Storage*>storages;Storage*selected=nullptr;bool allow=true,accept=true;int calls=0,callback=0;ScriptedInventoryOperationCallback*last=nullptr;std::function<void()> effect;
IEntity GetOwner(){return owner;}void GetItems(Array<IEntity>&a,int purpose){assert(purpose==1);a=items;}void GetStorages(Array<Storage*>&a,int purpose){assert(purpose==1);a=storages;}
Storage*FindStorageForItem(IEntity,int purpose){assert(purpose==1);return selected;}
bool CanMoveItemToStorage(IEntity,Storage*,int slot){assert(slot==-1);return allow;}
bool TryMoveItemToStorage(IEntity,Storage*,int slot,ScriptedInventoryOperationCallback*cb){assert(slot==-1);calls++;last=cb;if(effect)effect();if(callback==1){cb->OnComplete();}if(callback==2){cb->OnFailed();}return accept;}};
'''
main=r'''
struct Fixture{ERR_GameMode mode;Ledger ledger;Group donorGroup,recipientGroup,otherGroup;Record donorRecord,recipientRecord;Entity truck,recipient,driver,spareDriver,magEntity,rifle,foreign;
VehicleManager vehicleManager;Utility donorUtility,recipientUtility;Physics_ physics;Usage usage;Slot pilot,fromSlot,toSlot;Storage sourceStorage,targetStorage;Inventory source,destination;Item item;Magazine magazine;Manager weapons;Weapon weapon;Muzzle muzzle;Well well;
Fixture(){ERR_GameMode::current=&mode;mode.ledger=&ledger;donorRecord.Group=&donorGroup;recipientRecord.Group=&recipientGroup;ledger.records={&donorRecord,&recipientRecord};
donorGroup.utility=&donorUtility;recipientGroup.utility=&recipientUtility;donorUtility.m_VehicleMgr=&vehicleManager;vehicleManager.vehicle=&truck;
truck.physics=&physics;truck.usage=&usage;usage.pilot=&pilot;pilot.occupant=&driver;driver.group=&donorGroup;driver.vehicle=&truck;spareDriver.group=&donorGroup;spareDriver.vehicle=&truck;
recipient.group=&recipientGroup;recipient.position.x=4;truck.inventory=&source;source.owner=&truck;recipient.inventory=&destination;destination.owner=&recipient;
sourceStorage.owner=&truck;targetStorage.owner=&recipient;source.storages={&sourceStorage};destination.storages={&targetStorage};destination.selected=&targetStorage;
source.items={&magEntity};magEntity.item=&item;item.slot=&fromSlot;fromSlot.storage=&sourceStorage;toSlot.storage=&targetStorage;magEntity.magazine=&magazine;magazine.well=&well;
recipient.weapons=&weapons;weapons.weapons={&rifle};rifle.weapon=&weapon;weapon.owner=&rifle;weapon.muzzles={&muzzle};muzzle.well=&well;}
ERR_InfantryAmmoTransfer Job(){return ERR_InfantryAmmoTransfer(&mode,&truck,&donorGroup,&recipient,&recipientGroup,&magEntity);}
void Move(){source.items.clear();destination.items={&magEntity};item.slot=&toSlot;}
};
struct ERR_HQAmmoSnapshot{bool Complete=true,LauncherComplete=true;int SmallArmsMuzzles=1,SmallArmsRounds=0,SmallArmsChambers=0;};
struct ERR_HQAmmoSampler{static void Inspect(IEntity actor,SCR_AIGroup group,ERR_HQAmmoSnapshot* stock){assert(actor&&actor->group==group&&stock);}};
struct SupplyTruck{IEntity Entity;SCR_AIGroup Group;};
struct SupplyRecipient{SCR_AIGroup Group;};
struct Coordinator{ERR_GameMode* m_Mode;SupplyTruck* m_Truck;SupplyRecipient* m_Recipient;
ERR_InfantryAmmoTransfer* m_Move=nullptr;Array<IEntity>m_Members,m_Stock,m_Spent,m_Served;IEntity m_Receiving=nullptr;
int m_Delivered=0,m_TripDelivered=0,finishes=0,audits=0;
void Finish(string){finishes++;if(m_Move)m_Move->Stop();}
void Audit(string){audits++;}
bool Contains(IEntity owner,IEntity item){return owner&&owner->inventory&&owner->inventory->items.Count()<=128&&owner->inventory->items.Contains(item);}
'''+transfer+r'''
};
struct SupplyFixture:Fixture{SupplyTruck supplyTruck;SupplyRecipient supplyRecipient;Coordinator c;
SupplyFixture():supplyTruck{&truck,&donorGroup},supplyRecipient{&recipientGroup}{
c.m_Mode=&mode;c.m_Truck=&supplyTruck;c.m_Recipient=&supplyRecipient;c.m_Members={&recipient};c.m_Stock={&magEntity};}
};
int main(){
// XZ approach can precede valid vertical reach, stopped state, capacity or clear access.
// None of those no-submission outcomes consumes cargo or ends the trip; the same exact item can later submit once.
for(int obstruction=0;obstruction<5;obstruction++){SupplyFixture f;
if(obstruction==0){f.recipient.position.y=3;}if(obstruction==1){f.physics.velocity.x=1;}
if(obstruction==2){f.destination.selected=nullptr;}if(obstruction==3){f.source.allow=false;}
if(obstruction==4){ERR_InfantryAmmoAccess::clear=false;}
for(int tick=0;tick<3;tick++){f.c.Transfer(tick*1000);assert(f.source.calls==0&&f.c.m_Spent.IsEmpty()&&!f.c.m_Move&&!f.c.m_Receiving&&f.c.finishes==0);}
f.recipient.position.y=0;f.physics.velocity.x=0;f.destination.selected=&f.targetStorage;f.source.allow=true;ERR_InfantryAmmoAccess::clear=true;
f.c.Transfer(3000);assert(f.source.calls==1&&f.c.m_Spent.Count()==1&&f.c.m_Move&&f.c.m_Move->Submitted());
f.Move();f.source.last->OnComplete();f.c.Transfer(4000);assert(f.c.m_Delivered==1&&f.c.m_Served.Contains(&f.recipient)&&f.source.calls==1&&f.c.m_Spent.Count()==1);
}
// A capacity-blocked first member cannot prevent another original member from receiving this magazine.
{SupplyFixture f;Fixture second;ERR_GameMode::current=&f.mode;
second.recipient.group=&f.recipientGroup;second.recipientRecord.Group=&f.recipientGroup;
f.c.m_Members.Insert(&second.recipient);f.destination.selected=nullptr;
f.c.Transfer(0);assert(f.source.calls==1&&f.c.m_Receiving==&second.recipient&&f.c.m_Spent.Count()==1&&f.c.finishes==0);
f.source.items.clear();second.destination.items={&f.magEntity};f.item.slot=&second.toSlot;f.source.last->OnComplete();
f.c.Transfer(1000);assert(f.c.m_Delivered==1&&f.c.m_Served.Contains(&second.recipient)&&!f.c.m_Served.Contains(&f.recipient));}
// A native API may complete both physical movement and callback inline. Account once on the next slow tick.
{SupplyFixture f;f.source.callback=1;f.source.effect=[&](){f.Move();};f.c.Transfer(0);
assert(f.source.calls==1&&f.c.m_Move&&f.c.m_Move->Submitted()&&f.c.m_Delivered==0&&f.c.m_Spent.Count()==1);
f.c.Transfer(1000);f.c.Transfer(2000);assert(f.c.m_Delivered==1&&f.c.m_Served.Count()==1&&f.source.calls==1&&f.c.finishes==0);}
// Crossing the native submission boundary burns the exact identity even if native refusal is synchronous.
for(int refusal=0;refusal<2;refusal++){SupplyFixture f;if(refusal==0){f.source.accept=false;}else{f.source.callback=2;}
f.c.Transfer(0);assert(f.source.calls==1&&f.c.m_Spent.Count()==1&&f.c.m_Move->Submitted());
f.c.Transfer(1000);assert(f.c.finishes==1&&f.c.m_Spent.Count()==1&&f.source.calls==1);
}
// Accepted but unresolved loss stays retained/spent; changing geometry cannot cause a second native move.
{SupplyFixture f;f.c.Transfer(0);f.recipient.position.x=8;f.c.Transfer(1000);
assert(f.c.finishes==1&&f.c.m_Move&&f.c.m_Move->Unresolved()&&f.c.m_Spent.Count()==1&&f.source.calls==1);}
// Several equivalent magazines do not multiply a blocked actor's expensive preflight work on one slow tick.
{SupplyFixture f;Entity another=f.magEntity;f.source.items.Insert(&another);f.c.m_Stock.Insert(&another);
ERR_InfantryAmmoAccess::clear=false;ERR_InfantryAmmoAccess::checks=0;f.c.Transfer(0);
assert(ERR_InfantryAmmoAccess::checks==1&&f.source.calls==0&&f.c.m_Spent.IsEmpty());ERR_InfantryAmmoAccess::clear=true;}
// A blocked native access check happens before submission and is terminal.
{Fixture f;auto t=f.Job();ERR_InfantryAmmoAccess::clear=false;ERR_InfantryAmmoAccess::checks=0;
assert(t.Tick(0)==FAILED&&!t.Submitted()&&!t.Unresolved()&&f.source.calls==0&&ERR_InfantryAmmoAccess::checks==1);
ERR_InfantryAmmoAccess::clear=true;assert(t.Tick(1)==FAILED&&f.source.calls==0&&ERR_InfantryAmmoAccess::checks==1);}
// Once native move is accepted, later geometry cannot cause a second operation or pretend cancellation.
{Fixture f;auto t=f.Job();ERR_InfantryAmmoAccess::checks=0;assert(t.Tick(0)==PENDING&&ERR_InfantryAmmoAccess::checks==1);
ERR_InfantryAmmoAccess::clear=false;assert(t.Tick(1)==PENDING&&t.Unresolved()&&f.source.calls==1&&ERR_InfantryAmmoAccess::checks==1);
f.Move();f.source.last->OnComplete();assert(t.Tick(2)==SUCCEEDED);ERR_InfantryAmmoAccess::clear=true;}
// Read-only selection follows the native inherited-well direction, excluding launcher muzzles and weapons.
{Fixture f;assert(ERR_InfantryAmmoTransfer::Compatible(&f.recipient,&f.magEntity));Well derived;derived.type=2;derived.parent=1;f.magazine.well=&derived;assert(ERR_InfantryAmmoTransfer::Compatible(&f.recipient,&f.magEntity));
f.magazine.well=&f.well;f.muzzle.well=&derived;assert(!ERR_InfantryAmmoTransfer::Compatible(&f.recipient,&f.magEntity));
f.muzzle.well=&f.well;f.muzzle.kind=EMuzzleType::MT_UGLMuzzle;assert(!ERR_InfantryAmmoTransfer::Compatible(&f.recipient,&f.magEntity));
f.muzzle.kind=0;f.weapon.kind=EWeaponType::WT_ROCKETLAUNCHER;assert(!ERR_InfantryAmmoTransfer::Compatible(&f.recipient,&f.magEntity));}
// Exactly one source move; neither a callback alone nor physical movement alone is a successful transaction.
{Fixture f;auto t=f.Job();assert(t.Tick(100)==PENDING&&f.source.calls==1&&t.Unresolved());f.source.last->OnComplete();assert(t.Tick(101)==PENDING&&t.Unresolved());
f.Move();assert(t.Tick(102)==SUCCEEDED&&!t.Unresolved());t.Stop();assert(t.Tick(103)==SUCCEEDED&&f.source.calls==1);}
{Fixture f;auto t=f.Job();t.Tick(100);f.Move();assert(t.Tick(101)==PENDING&&t.Unresolved());f.source.last->OnAllComplete();assert(t.Tick(102)==SUCCEEDED);}
// Exact destination slot and known donor absence are mandatory even after success callback.
{Fixture f;auto t=f.Job();t.Tick(100);f.Move();f.item.slot=&f.fromSlot;f.source.last->OnComplete();assert(t.Tick(101)==PENDING&&t.Unresolved());
f.item.slot=&f.toSlot;for(int i=0;i<513;i++)f.source.items.Insert(&f.foreign);assert(t.Tick(102)==PENDING&&t.Unresolved());}
// Late callbacks resolve retained reservations after Stop without Tick or further operations; the stopped task stays failed.
{Fixture f;auto t=f.Job();t.Tick(0);t.Stop();assert(t.Unresolved());f.Move();f.source.last->OnAllComplete();assert(!t.Unresolved());assert(t.Tick(2)==FAILED&&f.source.calls==1);}
{Fixture f;auto t=f.Job();t.Tick(0);t.Stop();f.source.last->OnAllFailed();assert(!t.Unresolved());assert(t.Tick(1)==FAILED&&f.source.calls==1);}
{Fixture f;auto t=f.Job();t.Tick(0);f.source.last->OnComplete();f.source.last->OnFailed();assert(t.Unresolved());f.Move();assert(!t.Unresolved()&&t.Tick(1)==SUCCEEDED);}
// Failure/rejection and the 8s deadline never submit a second move.
for(int failure=0;failure<3;failure++){Fixture f;if(failure==0)f.source.accept=false;if(failure==1)f.source.callback=2;auto t=f.Job();t.Tick(100);
if(failure==2){assert(t.Tick(8100)==FAILED&&t.Unresolved());}else assert(t.Tick(101)==FAILED&&!t.Unresolved());
for(int i=0;i<10;i++)t.Tick(8200+i);assert(f.source.calls==1);}
// Invalid physical state before submission spends no native action; the terminal object cannot revive.
for(int invalid=0;invalid<25;invalid++){Fixture f;auto t=f.Job();
if(invalid==0)Replication::server=false;if(invalid==1)SCR_Global::editor=true;if(invalid==2)f.mode.active=false;
if(invalid==3)f.truck.alive=false;if(invalid==4)f.recipient.alive=false;if(invalid==5)f.recipient.awake=false;if(invalid==6)f.recipient.player=true;
if(invalid==7)f.recipient.vehicle=&f.truck;if(invalid==8)f.truck.captured=true;if(invalid==9)f.donorGroup.players=1;
if(invalid==10)f.recipient.group=&f.otherGroup;if(invalid==11)f.donorRecord.Physical=false;if(invalid==12)f.recipientRecord.Eliminated=true;
if(invalid==13)f.vehicleManager.vehicle=&f.foreign;if(invalid==14)f.driver.alive=false;if(invalid==15)f.driver.vehicle=nullptr;
if(invalid==16)f.physics.velocity.x=.251f;if(invalid==17)f.physics.angular.x=.101f;if(invalid==18)f.recipient.position.x=4.001f;
if(invalid==19)f.truck.faction=2;if(invalid==20)f.driver.faction=2;if(invalid==21)f.recipientGroup.slave=true;
if(invalid==22)f.magazine.rounds=0;if(invalid==23)f.magazine.rounds=31;if(invalid==24)f.physics.velocity.x=std::numeric_limits<float>::quiet_NaN();
assert(t.Tick(100)==FAILED&&f.source.calls==0&&!t.Unresolved());Replication::server=true;SCR_Global::editor=false;assert(t.Tick(200)==FAILED&&f.source.calls==0);}
// Native stock/storage identity and capacity guards reject shared, foreign, oversized and inaccessible inventory.
for(int invalid=0;invalid<9;invalid++){Fixture f;auto t=f.Job();if(invalid==0)f.source.items.clear();if(invalid==1)f.destination.items={&f.magEntity};
if(invalid==2)f.fromSlot.storage=&f.targetStorage;if(invalid==3)f.sourceStorage.owner=&f.foreign;if(invalid==4)f.destination.selected=nullptr;
if(invalid==5)f.targetStorage.owner=&f.foreign;if(invalid==6)f.source.allow=false;if(invalid==7)f.destination.storages.clear();if(invalid==8){for(int i=0;i<65;i++)f.destination.storages.Insert(&f.targetStorage);}
assert(t.Tick(0)==FAILED&&f.source.calls==0);}
// Conditions and original native driver/ledger identities remain strict while an accepted move is pending.
for(int changed=0;changed<4;changed++){Fixture f;auto t=f.Job();t.Tick(100);Record replacement=f.recipientRecord;
if(changed==0)f.pilot.occupant=&f.spareDriver;if(changed==1)f.ledger.records[1]=&replacement;if(changed==2)f.physics.velocity.x=1;if(changed==3)f.recipient.position.x=8;
assert(t.Tick(101)==FAILED&&t.Unresolved());f.source.last->OnFailed();assert(!t.Unresolved()&&f.source.calls==1);}
{Fixture f;auto t=f.Job();t.Tick(100);assert(t.Tick(99)==FAILED&&t.Unresolved());}
// Clothing storage ownership follows native inventory slots and bounds cycles.
{Fixture f;Entity vest;Item vestItem;Slot vestSlot;Storage body;body.owner=&f.recipient;vestSlot.storage=&body;vestItem.slot=&vestSlot;vest.item=&vestItem;f.targetStorage.owner=&vest;
auto t=f.Job();assert(t.Tick(0)==PENDING);f.Move();f.source.last->OnComplete();assert(t.Tick(1)==SUCCEEDED);
vestSlot.storage=&f.targetStorage;assert(!ERR_InfantryAmmoTransfer::StoredUnder(&vest,&f.recipient));}
}
'''
# Brace tiny fixture statements to retain -Werror without suppressing useful compiler diagnostics.
main=re.sub(r'if\((invalid|changed|failure)==(\d+)\)([^;{}]+);',r'if(\1==\2){\3;}',main)
main=main.replace('for(int i=0;i<10;i++)t.Tick(8200+i);','for(int i=0;i<10;i++){t.Tick(8200+i);}')
run(pre+code+'\n'.join(callbacks)+main)
print('PASS: actual single-item transfer, physical ownership/native callback proof, stop quarantine, compatibility and strict original actor/vehicle boundaries')