57 lines
4.6 KiB
Python
57 lines
4.6 KiB
Python
"""Execute the real stock-preparation loop with native inventory boundaries stubbed."""
|
|
from policy_harness import ROOT, body, run
|
|
p=ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c'
|
|
s=body(p,'protected ERR_PrepareResult PrepareStock(')
|
|
for a,b in [('protected ',''),('int pending, accepted;', 'int pending=0, accepted=0;'),('ERR_PrepareResult.', 'Result::'),('foreach (ERR_StockPlacement placement :', 'for (Placement* placement :'),('array<IEntity> items = {};','Array<IEntity> items;'),('placement.', 'placement->'),('.GetPrefabData()', '->GetPrefabData()'),('.GetPrefabName()', '->GetPrefabName()'),('.GetItems(', '->GetItems('),('.CanInsertItem(', '->CanInsertItem('),('.TryInsertItem(', '->TryInsertItem('),('GetGame().GetWorld().GetWorldTime()', 'now'),('LogLevel.WARNING','0'),('string.Format(', 'string::Format(')]:s=s.replace(a,b)
|
|
run(r'''
|
|
#include <cassert>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
struct string:std::string{using std::string::string;bool IsEmpty(){return empty();}static string Format(string,int,int,string){return "timeout";}};
|
|
template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;bool Contains(T x){return std::find(this->begin(),this->end(),x)!=this->end();}};
|
|
struct Item{string name="item";Item* GetPrefabData(){return this;}string GetPrefabName(){return name;}};using IEntity=Item*;
|
|
struct Inventory{Array<IEntity> contents;bool fits=true,accept=true;int requests=0;
|
|
void GetItems(Array<IEntity>& out){out=contents;}bool CanInsertItem(IEntity){return fits;}bool TryInsertItem(IEntity){requests++;return accept;}};
|
|
struct Placement{IEntity Item=nullptr;struct Inventory* Inventory=nullptr;bool Skipped=false,Accepted=false,Optional=false,OnGround=false;};
|
|
namespace Result{enum{FAILED=-1,PENDING,READY};}using ERR_PrepareResult=int;
|
|
int now=0;void Print(string,int){}
|
|
struct Service{Array<Placement*> m_Placements;int m_Deadline=100,failed=0,dropped=0;Array<IEntity> loose;
|
|
void Fail(string){failed++;}void LeaveStartingItem(Placement* p){dropped++;loose.push_back(p->Item);p->Skipped=true;}
|
|
'''+s+r'''
|
|
};
|
|
int main(){
|
|
Item floor;Inventory room;Placement explicitGround{&floor,&room,false,false,true,true};
|
|
Service direct;direct.m_Placements={&explicitGround};
|
|
assert(direct.PrepareStock()==Result::READY&&direct.dropped==1&&room.requests==0);
|
|
assert(direct.loose[0]==&floor);assert(direct.PrepareStock()==Result::READY&&direct.dropped==1);
|
|
Item map,rifle,pistol;Inventory bag;bag.fits=false;
|
|
Placement big{&rifle,&bag,false,false,true};Service s;s.m_Placements={&big};
|
|
assert(s.PrepareStock()==Result::READY&&s.dropped==1&&s.loose[0]==&rifle&&bag.requests==0);
|
|
assert(s.PrepareStock()==Result::READY&&s.dropped==1); // same item is not repeatedly dropped/spawned
|
|
Inventory good;Placement required{&map,&good},small{&pistol,&good,false,false,true};
|
|
Service mixed;mixed.m_Placements={&required,&small,&big};
|
|
assert(mixed.PrepareStock()==Result::PENDING&&good.requests==2);
|
|
assert(mixed.PrepareStock()==Result::PENDING&&good.requests==2); // async accepted requests are not repeated
|
|
good.contents={&map,&pistol};assert(mixed.PrepareStock()==Result::READY&&mixed.dropped==0);
|
|
Inventory delayed;delayed.fits=false;Placement moving{&rifle,&delayed,false,true,true};
|
|
Service wait;wait.m_Placements={&moving};assert(wait.PrepareStock()==Result::PENDING&&wait.dropped==0);
|
|
delayed.contents={&rifle};assert(wait.PrepareStock()==Result::READY&&wait.dropped==0);
|
|
Placement gone{nullptr,&bag,false,false,true};Service missing;missing.m_Placements={&gone};
|
|
assert(missing.PrepareStock()==Result::READY&&missing.failed==0&&gone.Skipped);
|
|
Placement lostMap{nullptr,&bag};Service broken;broken.m_Placements={&lostMap};
|
|
assert(broken.PrepareStock()==Result::FAILED&&broken.failed==1);
|
|
Inventory refusing;refusing.fits=false;refusing.accept=false;Placement noMap{&map,&refusing};
|
|
Service requiredFailure;requiredFailure.m_Placements={&noMap};
|
|
assert(requiredFailure.PrepareStock()==Result::PENDING);now=101;
|
|
assert(requiredFailure.PrepareStock()==Result::FAILED&&requiredFailure.failed==1);
|
|
Inventory stalled;Placement timeout{&rifle,&stalled,false,true,true};Service optionalTimeout;optionalTimeout.m_Placements={&timeout};
|
|
assert(optionalTimeout.PrepareStock()==Result::READY&&optionalTimeout.dropped==1&&optionalTimeout.failed==0);
|
|
}
|
|
''')
|
|
leave=body(p,'protected void LeaveStartingItem(')
|
|
assert '!item.GetParentSlot()' in leave and 'DryGround(point)' in leave
|
|
assert 'BackpackClearance(point)' in leave and 'TraceMove(access, null)' in leave
|
|
assert 'DeleteSpawned' not in leave and 'Spawn(' not in leave
|
|
print('PASS: native-rejected custom items remain available without startup delay; required map and async insertion safeguards retained')
|