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.
73 lines
5.4 KiB
Python
73 lines
5.4 KiB
Python
"""Exercise actual registration/dispatch bodies without requiring optional addons.
|
|
Native script compilation and authenticated RPC tests remain separate checks.
|
|
"""
|
|
from policy_harness import ROOT, body, run
|
|
core = ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_AdminService.c'
|
|
hq = ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQAdminProvider.c'
|
|
intel = ROOT/'addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelAdminProvider.c'
|
|
source=core.read_text()
|
|
assert 'ERR_HQ' not in source and 'ERR_IntelService' not in source
|
|
assert 'modded class' not in (ROOT/'addons/core/Scripts/Game/ERR/40_Chat/ERR_AdminCommands.c').read_text()
|
|
assert 'Admin().Register(new ERR_HQAdminProvider(hq))' in (ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c').read_text()
|
|
assert 'Admin().Register(new ERR_IntelAdminProvider())' in (ROOT/'addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelService.c').read_text()
|
|
execute=body(core,'void Execute(')
|
|
assert execute.index('if (!Replication.IsServer()') < execute.index('if (!authorized)') < execute.index('Extension(mode, arguments, replies)')
|
|
assert 'arguments = "mission " + arguments' in execute
|
|
|
|
def translate(s):
|
|
return (s.replace('protected ', '').replace('override ', '')
|
|
.replace('array<string>', 'Array<string>&').replace('out int ', 'int& ')
|
|
.replace('ERR_AdminProvider provider', 'Provider* provider').replace('ERR_GameMode mode','Mode* mode')
|
|
.replace('foreach (Provider* provider : m_Providers)', 'for (Provider* provider : m_Providers)')
|
|
.replace('ERR_CommandArguments.CoreSetting(', 'CoreSetting(')
|
|
.replace('provider.', 'provider->').replace('m_Providers[i].', 'm_Providers[i]->')
|
|
.replace('.IsEmpty()', '.empty()').replace('bool handled;', 'bool handled = false;'))
|
|
methods='\n'.join(translate(body(core,sig)) for sig in ('void Register(', 'void Capabilities(', 'int JournalSequence(', 'bool ReadJournal(', 'protected string Setting(', 'protected bool Extension('))
|
|
aliases='struct HQAliases{'+translate(body(hq,'override string Setting('))+'};\nstruct IntelAliases{'+translate(body(intel,'override string Setting('))+'};'
|
|
help_bodies='struct HQHelp{'+translate(body(hq,'override bool Help('))+'};\nstruct IntelHelp{'+translate(body(intel,'override bool Help('))+'};'
|
|
run(r'''
|
|
#include <cassert>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
using string=std::string;
|
|
template<class T> struct Array:std::vector<T>{void Insert(T v){this->push_back(v);}void Clear(){this->clear();}int Count(){return this->size();}};
|
|
struct Mode{};
|
|
string CoreSetting(string section,string option){if(section=="intel"&&option=="reveal")return "intelRevealChancePercent";return "";}
|
|
struct Provider{
|
|
string id;int sequence=-1;int calls=0;bool accepts=false;int reads=0;
|
|
string Id(){return id;}void Capabilities(Array<string>& values){values.Insert("supports="+id);}
|
|
int JournalSequence(){return sequence;}
|
|
bool ReadJournal(int after,Array<string>& lines,int& cursor,int limit=8){if(sequence<0)return false;reads++;cursor=std::min(sequence,after+limit);lines.Insert(id);return true;}
|
|
string Setting(string section,string){return section==id?id+"Setting":"";}
|
|
bool Execute(Mode*,string,Array<string>& replies){calls++;if(accepts)replies.Insert(id);return accepts;}
|
|
};
|
|
struct Admin{Array<Provider*>m_Providers;
|
|
'''+methods+'};\n'+aliases+help_bodies+r'''
|
|
int main(){
|
|
Admin admin;Mode mode;Array<string> lines;int cursor=0;
|
|
assert(admin.JournalSequence()==-1&&!admin.ReadJournal(0,lines,cursor));
|
|
assert(admin.Setting("intel","reveal")=="intelRevealChancePercent"&&admin.Setting("hq","squads").empty());
|
|
admin.Register(nullptr);Provider empty;admin.Register(&empty);assert(admin.m_Providers.empty());
|
|
Provider hq;hq.id="hq";hq.sequence=12;hq.accepts=true;
|
|
Provider intel;intel.id="intel";intel.accepts=true;
|
|
admin.Register(&hq);admin.Register(&hq);admin.Register(&intel);assert(admin.m_Providers.size()==2);
|
|
admin.Capabilities(lines);assert(lines.size()==2&&lines[0]=="supports=hq"&&lines[1]=="supports=intel");
|
|
assert(admin.JournalSequence()==12);assert(admin.ReadJournal(2,lines,cursor,4)&&cursor==6&&lines.size()==1&&lines[0]=="hq");
|
|
assert(hq.reads==1&&intel.reads==0);
|
|
lines.clear();assert(admin.Extension(&mode,"status",lines)&&lines.size()==2&&hq.calls==1&&intel.calls==1);
|
|
lines.clear();assert(admin.Extension(&mode,"hq show",lines)&&lines.size()==1&&hq.calls==2&&intel.calls==1);
|
|
hq.accepts=false;intel.accepts=false;lines.clear();assert(!admin.Extension(&mode,"unknown",lines)&&lines.empty());
|
|
Provider replacement;replacement.id="hq";replacement.sequence=20;
|
|
admin.Register(&replacement);assert(admin.m_Providers.size()==2&&admin.JournalSequence()==20);
|
|
HQAliases ha;IntelAliases ia;
|
|
assert(ha.Setting("hq","interval")=="reportIntervalSeconds"&&ha.Setting("hq","squads")=="supportSquadLimit"&&ha.Setting("hq","radius")=="responseRadiusMetres");
|
|
assert(ha.Setting("intel","carrying").empty()&&ha.Setting("hq","stinger")=="stingerChanceOneIn");
|
|
assert(ia.Setting("intel","chance")=="aiIntelChancePercent"&&ia.Setting("intel","carrying")=="aiIntelChancePercent");
|
|
assert(ia.Setting("hq","chance").empty()&&ia.Setting("intel","spawn").empty());
|
|
HQHelp hh;IntelHelp ih;lines.clear();assert(hh.Help("hq",lines)&&lines.size()<=4);lines.clear();assert(ih.Help("intel",lines)&&lines.size()<=4);
|
|
lines.clear();assert(!hh.Help("unknown",lines)&&!ih.Help("unknown",lines)&&lines.empty());
|
|
}
|
|
''')
|
|
print('PASS: mission provider registration is idempotent, optional dispatch is ordered, status aggregates, journals preserve cursors, aliases stay with their addons and topic help is bounded')
|