Smooth convoy startup and record Workshop 0.0.153
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -86,15 +86,16 @@ raw=service.read_text()
|
||||
assert raw.index('CaptureMountedStock(supply)') < raw.index('for (int i = 0; i < 8; i++)')
|
||||
assert raw.index('task.MagazinesIssued = true;',raw.index('protected void IssueMagazines')) < raw.index('IssueMountedStock(task, inventory, issued,')
|
||||
assert 'ref array<ref ERR_MountedMagazineSeed> MountedStock' in (D/'ERR_SupplyConvoyTactics.c').read_text()
|
||||
code='\n'.join(body(service,x) for x in ['protected bool MountedStockOwner(', 'protected void CaptureMountedStock(', 'protected int IssueMountedStock(', 'protected void IssueMagazines('])
|
||||
code='\n'.join(body(service,x) for x in ['protected bool MountedStockOwner(', 'protected void CaptureMountedStock(', 'protected int IssueMountedStock(', 'protected bool CargoPending(', 'protected void IssueMagazines('])
|
||||
code=re.sub(r'//[^\n]*','',code).replace('protected ','').replace('null','nullptr').replace('foreach (','for (').replace('array<','Array<')
|
||||
for old,new in {
|
||||
'ERR_HQ.Cast(m_Mode.Command())':'m_Mode->Command()',
|
||||
'InventoryStorageManagerComponent.Cast(task.Vehicles[1].Entity.FindComponent(InventoryStorageManagerComponent))':'task->Vehicles[1]->Entity->inventory',
|
||||
'InventoryStorageManagerComponent.Cast(vehicle.Entity.FindComponent(InventoryStorageManagerComponent))':'vehicle->Entity->inventory',
|
||||
'BaseWeaponComponent.Cast(item.FindComponent(BaseWeaponComponent))':'item->weapon',
|
||||
'existing.FindComponent(BaseMagazineComponent)':'existing->magazine',
|
||||
}.items():code=code.replace(old,new)
|
||||
for typ in ['ERR_SupplyConvoyTask','ERR_HQ','ERR_ConvoyVehicle','ERR_ForceRecord','InventoryStorageManagerComponent','ERR_MountedMagazineSeed','ERR_ConvoyCargoCallback','BaseWeaponComponent','BaseMuzzleComponent']:
|
||||
for typ in ['ERR_SupplyConvoyTask','ERR_HQ','ERR_ConvoyVehicle','ERR_ForceRecord','InventoryStorageManagerComponent','ERR_MountedMagazineSeed','ERR_ConvoyCargoCallback','BaseWeaponComponent','BaseMuzzleComponent','ERR_SupplyConvoyLoad']:
|
||||
code=re.sub(r'\b'+typ+r' (?=\w)',typ+'* ',code)
|
||||
code=code.replace('Array<BaseMuzzleComponent>', 'Array<BaseMuzzleComponent*>')
|
||||
for name in ['m_Mode','task','vehicle','hq','record','inventory','seed','load','operation','item','weaponOperation','weapon','muzzle']:
|
||||
@@ -121,38 +122,57 @@ struct ERR_HQ{static void Event(string,string){}bool ValidateBoundVehicle(Group*
|
||||
struct Mode{Ledger ledger;ERR_HQ hq;Ledger* Forces(){return &ledger;}ERR_HQ* Command(){return &hq;}};
|
||||
struct ERR_ConvoyVehicle{int Index=0;bool Registered=true,Released=false,crew=true;IEntity Entity=nullptr;struct Group* Group=nullptr;bool CrewValid(Mode*){return crew;}};
|
||||
struct Receipt{bool Consumed=true;Array<int>Records={0,1,2,3,4,5};string SourceId="convoy";};
|
||||
struct ERR_ConvoyCargoCallback{string Prefab;bool Finished=true,Succeeded=true;};
|
||||
struct ERR_ConvoyCargoCallback{string Prefab;bool Finished=false,Succeeded=false;};
|
||||
struct ERR_MountedMagazineSeed{IEntity Root=nullptr;int VehicleIndex=0;string Prefab="PKM-box";bool valid=true;bool Current(){return valid;}static inline int captures=0;static void Capture(IEntity,int,Array<ERR_MountedMagazineSeed*>&){captures++;}};
|
||||
struct ERR_SupplyConvoyTask{bool Ready=true,Stopped=false,MagazinesIssued=false,CargoIssued=true;float Deadline=100;struct Receipt receipt;struct Receipt* Receipt=&receipt;Array<ERR_ConvoyVehicle*>Vehicles;Array<ERR_ConvoyCargoCallback*>Cargo;Array<ERR_MountedMagazineSeed*>MountedStock;Array<IEntity>CargoBefore;};
|
||||
struct EStoragePurpose{static const int PURPOSE_DEPOSIT=1;};
|
||||
struct InventoryStorageManagerComponent{IEntity owner=nullptr;Array<IEntity>items;Array<string>requests;bool accept=true,inlineDone=false;Entity spawned;IEntity GetOwner(){return owner;}
|
||||
bool TrySpawnPrefabToStorage(string p,void*,int,int,ERR_ConvoyCargoCallback* cb){requests.Insert(p);cb->Finished=inlineDone;if(inlineDone){spawned.magazine=true;items.Insert(&spawned);}return accept;}};
|
||||
struct InventoryStorageManagerComponent{IEntity owner=nullptr;Array<IEntity>items;Array<string>planned;int nativeCalls=0;bool accept=true,inlineDone=false;Entity spawned;IEntity GetOwner(){return owner;}
|
||||
bool TrySpawnPrefabToStorage(string p,void*,int,int,ERR_ConvoyCargoCallback* cb){nativeCalls++;cb->Finished=inlineDone;if(inlineDone){spawned.magazine=true;items.Insert(&spawned);}return accept;}};
|
||||
struct ERR_Inventory{static void Items(InventoryStorageManagerComponent* i,Array<IEntity>& items){items=i->items;}};
|
||||
struct Service{Mode* m_Mode;
|
||||
struct ERR_SupplyConvoyLoad{ERR_SupplyConvoyTask* Task;ERR_ConvoyCargoCallback* Operation;};
|
||||
struct Service{Mode* m_Mode;Array<ERR_SupplyConvoyLoad*>m_Loads;
|
||||
void QueueCargo(ERR_SupplyConvoyTask* task,InventoryStorageManagerComponent* inventory,ERR_ConvoyCargoCallback* operation){
|
||||
inventory->planned.Insert(operation->Prefab);m_Loads.Insert(new ERR_SupplyConvoyLoad{task,operation});}
|
||||
void CompletePlanned(){for(auto load:m_Loads){load->Operation->Finished=true;load->Operation->Succeeded=true;}m_Loads.Clear();}
|
||||
'''+code+r'''
|
||||
};
|
||||
struct Fixture{Mode mode;Service service{&mode};ERR_SupplyConvoyTask task;InventoryStorageManagerComponent inventory;Array<Entity>roots{6},cargo{8},extra{129};Array<Group>groups{6};Array<ERR_ConvoyVehicle>vehicles{6};Array<BaseWeaponComponent>weapons{8};BaseMuzzleComponent muzzle;Array<ERR_ConvoyCargoCallback>callbacks{8};Array<ERR_MountedMagazineSeed>seeds{9};
|
||||
Fixture(){mode.ledger.records.resize(6);for(int i=0;i<6;i++){groups[i].id=i;groups[i].bound=&roots[i];vehicles[i].Index=i;vehicles[i].Entity=&roots[i];vehicles[i].Group=&groups[i];task.Vehicles.Insert(&vehicles[i]);mode.ledger.records[i].Id=i;}
|
||||
roots[1].inventory=&inventory;inventory.owner=&roots[1];
|
||||
for(int i=0;i<8;i++){cargo[i].prefab.name="weapon"+std::to_string(i);cargo[i].weapon=&weapons[i];weapons[i].muzzles={&muzzle};callbacks[i].Prefab=cargo[i].prefab.name;task.Cargo.Insert(&callbacks[i]);inventory.items.Insert(&cargo[i]);}
|
||||
for(int i=0;i<8;i++){cargo[i].prefab.name="weapon"+std::to_string(i);cargo[i].weapon=&weapons[i];weapons[i].muzzles={&muzzle};callbacks[i].Prefab=cargo[i].prefab.name;callbacks[i].Finished=true;callbacks[i].Succeeded=true;task.Cargo.Insert(&callbacks[i]);inventory.items.Insert(&cargo[i]);}
|
||||
for(int i=0;i<9;i++){seeds[i].Root=&roots[0];seeds[i].Prefab="box"+std::to_string(i);task.MountedStock.Insert(&seeds[i]);}}
|
||||
};
|
||||
int main(){
|
||||
{Fixture f;f.service.IssueMagazines(&f.task,0);assert(f.task.MagazinesIssued&&f.inventory.requests.Count()==64&&f.task.Cargo.Count()==72&&f.task.MountedStock.Count()==0);
|
||||
for(int i=0;i<48;i++)assert(f.inventory.requests[i]=="rifle-mag");for(int i=48;i<64;i++)assert(f.inventory.requests[i]=="box"+std::to_string((i-48)/2));
|
||||
f.service.IssueMagazines(&f.task,99999);assert(f.inventory.requests.Count()==64);}
|
||||
{Fixture f;f.callbacks[0].Finished=false;f.service.IssueMagazines(&f.task,0);assert(!f.task.MagazinesIssued&&f.inventory.requests.Count()==0);f.callbacks[0].Finished=true;f.service.IssueMagazines(&f.task,1);assert(f.inventory.requests.Count()==64);}
|
||||
// Lost cargo authority ends this one-time plan, without stopping escorts or
|
||||
// touching any native inventory. Includes a physically deleted original truck.
|
||||
for(int fault=0;fault<5;fault++){Fixture f;f.task.CargoBefore.Insert(&f.extra[0]);
|
||||
if(fault==0)f.task.Vehicles.resize(5);if(fault==1)f.task.Vehicles[1]=nullptr;
|
||||
if(fault==2)f.vehicles[1].Entity=nullptr;if(fault==3)f.vehicles[1].Released=true;if(fault==4)f.vehicles[1].crew=false;
|
||||
f.service.IssueMagazines(&f.task,0);assert(f.task.MagazinesIssued&&!f.task.Stopped&&f.task.MountedStock.Count()==0&&f.task.CargoBefore.Count()==0&&f.inventory.planned.Count()==0&&f.inventory.nativeCalls==0);
|
||||
f.service.IssueMagazines(&f.task,99999);assert(f.inventory.planned.Count()==0&&!f.task.Stopped);}
|
||||
{Fixture f;f.service.IssueMagazines(nullptr,0);assert(f.inventory.planned.Count()==0);}
|
||||
// Even past the callback deadline, unsent weapon requests block magazine
|
||||
// planning. Another task's pending requests must not block this task.
|
||||
{Fixture f;f.callbacks[0].Finished=false;f.service.QueueCargo(&f.task,&f.inventory,&f.callbacks[0]);
|
||||
f.service.IssueMagazines(&f.task,99999);assert(!f.task.MagazinesIssued&&f.inventory.planned.Count()==1&&f.inventory.nativeCalls==0);
|
||||
f.service.CompletePlanned();f.inventory.planned.Clear();f.service.IssueMagazines(&f.task,100000);assert(f.task.MagazinesIssued&&f.inventory.planned.Count()==64&&f.inventory.nativeCalls==0);}
|
||||
{Fixture f;ERR_SupplyConvoyTask other;ERR_ConvoyCargoCallback operation;f.service.QueueCargo(&other,&f.inventory,&operation);f.inventory.planned.Clear();
|
||||
f.service.IssueMagazines(&f.task,0);assert(f.task.MagazinesIssued&&f.inventory.planned.Count()==64&&f.inventory.nativeCalls==0);}
|
||||
{Fixture f;f.service.IssueMagazines(&f.task,0);assert(f.task.MagazinesIssued&&f.inventory.planned.Count()==64&&f.task.Cargo.Count()==72&&f.task.MountedStock.Count()==0);
|
||||
for(int i=0;i<48;i++)assert(f.inventory.planned[i]=="rifle-mag");for(int i=48;i<64;i++)assert(f.inventory.planned[i]=="box"+std::to_string((i-48)/2));
|
||||
f.service.IssueMagazines(&f.task,99999);assert(f.inventory.planned.Count()==64);}
|
||||
{Fixture f;f.callbacks[0].Finished=false;f.service.IssueMagazines(&f.task,0);assert(!f.task.MagazinesIssued&&f.inventory.planned.Count()==0);f.callbacks[0].Finished=true;f.service.IssueMagazines(&f.task,1);assert(f.inventory.planned.Count()==64);}
|
||||
for(int missing=0;missing<2;missing++){Fixture f;
|
||||
if(missing==0)f.callbacks[0].Finished=false;else f.task.Cargo[0]=nullptr;
|
||||
f.service.IssueMagazines(&f.task,30100);
|
||||
assert(f.task.MagazinesIssued&&f.inventory.requests.Count()==42&&f.task.MountedStock.Count()==0);
|
||||
for(auto request:f.inventory.requests){assert(request=="rifle-mag");}
|
||||
assert(f.task.MagazinesIssued&&f.inventory.planned.Count()==42&&f.task.MountedStock.Count()==0);
|
||||
for(auto request:f.inventory.planned){assert(request=="rifle-mag");}
|
||||
f.callbacks[0].Finished=true;f.task.Cargo[0]=&f.callbacks[0];
|
||||
f.service.IssueMagazines(&f.task,99999);assert(f.inventory.requests.Count()==42);}
|
||||
{Fixture f;f.inventory.accept=false;f.service.IssueMagazines(&f.task,0);assert(f.inventory.requests.Count()==64);for(auto cb:f.task.Cargo){assert(cb->Finished);}f.service.IssueMagazines(&f.task,99999);assert(f.inventory.requests.Count()==64);}
|
||||
{Fixture f;f.inventory.inlineDone=true;f.service.IssueMagazines(&f.task,0);assert(f.inventory.requests.Count()==64);}
|
||||
{Fixture f;f.service.IssueMountedStock(&f.task,&f.inventory,80,8,20);assert(f.inventory.requests.Count()==8);} //96 existing+attempts
|
||||
{Fixture f;int total=f.service.IssueMountedStock(&f.task,&f.inventory,48,0,79);assert(total==49&&f.inventory.requests.Count()==1);} //128allitems
|
||||
f.service.IssueMagazines(&f.task,99999);assert(f.inventory.planned.Count()==42);}
|
||||
{Fixture f;f.inventory.accept=false;f.service.IssueMagazines(&f.task,0);assert(f.inventory.planned.Count()==64);assert(f.inventory.nativeCalls==0);for(int i=8;i<f.task.Cargo.Count();i++){assert(!f.task.Cargo[i]->Finished);}f.service.IssueMagazines(&f.task,99999);assert(f.inventory.planned.Count()==64);}
|
||||
{Fixture f;f.inventory.inlineDone=true;f.service.IssueMagazines(&f.task,0);assert(f.inventory.planned.Count()==64&&f.inventory.nativeCalls==0&&f.inventory.items.Count()==8);}
|
||||
{Fixture f;f.service.IssueMountedStock(&f.task,&f.inventory,80,8,20);assert(f.inventory.planned.Count()==8);} //96 existing+attempts
|
||||
{Fixture f;int total=f.service.IssueMountedStock(&f.task,&f.inventory,48,0,79);assert(total==49&&f.inventory.planned.Count()==1);} //128allitems
|
||||
{Fixture f;f.task.Cargo.resize(127,&f.callbacks[0]);assert(f.service.IssueMountedStock(&f.task,&f.inventory,48,0,8)==49&&f.task.Cargo.Count()==128);}
|
||||
{Fixture f;for(auto& seed:f.seeds){seed.Prefab="same";}assert(f.service.IssueMountedStock(&f.task,&f.inventory,48,0,8)==50);}
|
||||
for(int bad=0;bad<8;bad++){Fixture f;
|
||||
@@ -160,13 +180,13 @@ int main(){
|
||||
if(bad==3)f.task.Ready=false;if(bad==4)f.task.Receipt->Consumed=false;
|
||||
if(bad==5)for(auto& seed:f.seeds)seed.valid=false;
|
||||
if(bad==6)f.task.Vehicles[0]=&f.vehicles[3];if(bad==7)f.groups[0].valid=false;
|
||||
assert(f.service.IssueMountedStock(&f.task,&f.inventory,48,0,8)==48&&f.inventory.requests.Count()==0);}
|
||||
assert(f.service.IssueMountedStock(&f.task,&f.inventory,48,0,8)==48&&f.inventory.planned.Count()==0);}
|
||||
{Fixture f;f.inventory.items.clear();for(auto& e:f.extra){f.inventory.items.Insert(&e);}f.service.IssueMagazines(&f.task,0);
|
||||
assert(f.task.MagazinesIssued&&f.inventory.requests.Count()==0&&f.task.MountedStock.Count()==0&&f.task.CargoBefore.Count()==0);}
|
||||
assert(f.task.MagazinesIssued&&f.inventory.planned.Count()==0&&f.task.MountedStock.Count()==0&&f.task.CargoBefore.Count()==0);}
|
||||
{Fixture f;f.service.CaptureMountedStock(&f.task);assert(ERR_MountedMagazineSeed::captures==6);f.groups[1].valid=false;f.service.CaptureMountedStock(&f.task);assert(ERR_MountedMagazineSeed::captures==6);}
|
||||
}
|
||||
'''.replace(';if(', ';\n if(').replace(';for(', ';\n for('))
|
||||
print('PASS: actual primary-before-mounted one-shot batch, shared96/128 caps, physical snapshot headroom, original ownership, callback refusal and admission pinning')
|
||||
print('PASS: actual primary-before-mounted one-shot planning, shared96/128 caps, physical snapshot headroom, original ownership, pending-weapon barrier and zero native insertions during planning')
|
||||
lookup=body(D/'ERR_HQ.c','bool ValidateBoundVehicle(SCR_AIGroup group, IEntity vehicle)')
|
||||
lookup=lookup.replace('Replication.','Replication::').replace('null','nullptr')
|
||||
for typ in ['SCR_AIGroup','IEntity','ERR_HQUnit']:lookup=re.sub(r'\b'+typ+r' (?=\w)',typ+'* ',lookup)
|
||||
|
||||
Reference in New Issue
Block a user