53 lines
4.8 KiB
Python
53 lines
4.8 KiB
Python
"""Execute production starting-supply validation, edits, mode switches and save guards."""
|
|
from policy_harness import ROOT, body, run
|
|
p=ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_StartBackpack.c'
|
|
methods='\n'.join(body(p,n) for n in ['static bool Valid(', 'protected bool Save(', 'bool Custom(', 'bool SetMode(', 'bool Set(', 'bool Remove('])
|
|
methods=methods.replace('protected ','').replace('array<string>', 'Array<string>').replace('set<string> seen = new set<string>();','Array<string> seen;').replace('!records || ', '').replace('ResourceName','string').replace('quantity.ToString()', 'string(std::to_string(quantity))')
|
|
methods=methods.replace('int total;', 'int total = 0;')
|
|
methods=methods.replace('ERR_TerrainCatalog.Key','Key').replace('ERR_ItemPreferences.Guid','Guid').replace('ERR_CommandArguments.Integer','Integer').replace('Replication.IsServer()', 'authority').replace('ERR_ProfileConfig.Save(PATH, json)', 'Persist(json)').replace('JsonSaveContext json = new JsonSaveContext();','JsonSaveContext json;')
|
|
run(r'''
|
|
#include <cassert>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
#include <cstdio>
|
|
struct string;
|
|
template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;using std::vector<T>::operator=;int Count(){return this->size();}bool IsEmpty(){return this->empty();}void Insert(T x){this->push_back(x);}bool Contains(T x){return std::find(this->begin(),this->end(),x)!=this->end();}void Copy(Array<T> x){*this=x;}};
|
|
struct string:std::string{using std::string::string;string(std::string x):std::string(x){}int Length(){return size();}bool EndsWith(string x){return size()>=x.size()&&substr(size()-x.size())==x;}void Split(string delim,Array<string>& out,bool){size_t a=0;while(true){auto b=find(delim,a);out.Insert(substr(a,b==npos?b:b-a));if(b==npos)break;a=b+delim.size();}}};
|
|
bool Guid(string s){return s.size()==16&&s.find_first_not_of("0123456789abcdef")==s.npos;}
|
|
string Key(string s){if(s.size()<18||s[0]!='{'||s[17]!='}')return "";string k=s.substr(1,16);std::transform(k.begin(),k.end(),k.begin(),::tolower);return Guid(k)?k:string("");}
|
|
bool Integer(string s,int& n){try{size_t end;n=std::stoi(s,&end);return end==s.size();}catch(...){return false;}}
|
|
struct JsonSaveContext{Array<string> rows;void EnableTypeDiscriminator(bool){}void WriteValue(string,int){}void WriteValue(string,Array<string> v){rows=v;}};
|
|
struct Supplies{Array<string> m_Records={"default"},disk;bool authority=true,m_ReadOnly=false,fail=false;
|
|
bool Persist(JsonSaveContext json){if(fail)return false;disk=json.rows;return true;}
|
|
'''+methods+r'''
|
|
};
|
|
int main(){
|
|
string a="{AAAAAAAAAAAAAAAA}Prefabs/rifle.et",b="{BBBBBBBBBBBBBBBB}Prefabs/magazine.et";
|
|
Supplies s;assert(!s.Custom());assert(s.Set(a,2)&&s.Set(b,4)&&s.m_Records.size()==3);
|
|
assert(s.SetMode(true)&&s.Custom());assert(s.Set(a,3)&&s.m_Records.size()==3);
|
|
auto saved=s.m_Records;s.fail=true;assert(!s.SetMode(false)&&!s.Remove("aaaaaaaaaaaaaaaa")&&s.m_Records==saved);s.fail=false;
|
|
s.authority=false;assert(!s.Set(a,1)&&!s.SetMode(false)&&s.m_Records==saved);s.authority=true;
|
|
s.m_ReadOnly=true;assert(!s.Set(b,1)&&s.m_Records==saved);s.m_ReadOnly=false;
|
|
assert(!s.Set(a,-1)&&!s.Set(a,49)&&s.m_Records==saved);
|
|
assert(s.Set(a,48));assert(!s.Set(b,48));assert(s.Set(b,16));assert(!s.Set(b,17));
|
|
assert(s.SetMode(false)&&s.m_Records.size()==3);assert(s.SetMode(true)&&s.m_Records.size()==3);
|
|
assert(s.Remove("aaaaaaaaaaaaaaaa")&&s.m_Records.size()==2);assert(!s.Remove("aaaaaaaaaaaaaaaa"));
|
|
assert(s.Set(b,0)&&s.m_Records.size()==1&&s.Custom());
|
|
assert(!Supplies::Valid({})&&!Supplies::Valid({"invalid"}));
|
|
for(string bad:Array<string>{"", "missing-guid.et|1",a+"|0",a+"|-1",a+"|49",a+"|1.2",a+"|1junk",a+"|1|x"})assert(!Supplies::Valid({"custom",bad}));
|
|
assert(!Supplies::Valid({"custom",a+"|1",a+"|2"}));
|
|
for(int i=0;i<32;i++){char buf[128];std::snprintf(buf,sizeof(buf),"{%016x}Prefabs/item.et",i);assert(s.Set(buf,1));}
|
|
assert(!s.Set(a,1));assert(s.disk==s.m_Records);
|
|
}
|
|
''')
|
|
session=ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_AdminSession.c'
|
|
assert body(session,'void Command(').index('if (!Authorize()) return;') < body(session,'void Command(').index('StartBackpackCommand(')
|
|
command=body(session,'protected bool StartBackpackCommand(')
|
|
assert command.index('catalog.Contains(parts[2], parts[3])') < command.index('supplies.Set(item.Prefab, count)')
|
|
stock=(ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c').read_text()
|
|
assert 'spec.Kind == ERR_LocationKind.PRISON && !customStart' in stock
|
|
assert 'placement.Optional && GetGame().GetWorld().GetWorldTime() > m_Deadline' in stock
|
|
assert 'ERR_Actors.DeleteSpawned(placement.Item); placement.Skipped = true;' in stock
|
|
print('PASS: exact starting-stock edits, quantities/type/total limits, duplicate rejection, saved custom/default modes, authority/read-only/save-failure retention and authenticated catalog routing')
|