"""Production relay authority/leases and delivery, with owner RPC/native data doubled.""" import re from policy_harness import ROOT,body,run p=ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_ObserverPlayerView.c' def adapt(s): s=s.replace('vector geometry; float vignette;', 'vector geometry; float vignette=0;').replace('protected ', '').replace('null','nullptr').replace('array packet', 'Array* packet').replace('packet.Count()', 'packet->Count()').replace('packet[', '(*packet)[') for cls in ['ERR_GameMode','ERR_PlayerLife','SCR_PlayerController','RplComponent']: s=re.sub(r'\b'+cls+r' (\w+)\b',cls+r'* \1',s) for obj in ['mode','life','watcher','source','component']:s=s.replace(obj+'.',obj+'->') s=s.replace('m_ERRViewWatchers[i].','m_ERRViewWatchers[i]->') for cls in ['ERR_ObserverScope','ERR_GameMode','ERR_Actors','ERR_ObserverRules','ERR_ObserverViewRules','Replication','SCR_PlayerController','RplComponent','SCR_FactionManager','RplId','Math','vector']:s=s.replace(cls+'.',cls+'::') s=s.replace('GetGame().','GetGame()->').replace('GetWorld().','GetWorld()->').replace('GetPlayerManager().','GetPlayerManager()->').replace('Players().','Players()->').replace('Get().','Get()->') s=s.replace('actor.FindComponent(RplComponent)', 'actor->FindComponent()') s=s.replace('Rpc(ERR_EnableViewPublisher)', 'SendLease()') return s methods='\n'.join(adapt(body(p,k)) for k in ['bool ERR_ViewRecipient(', 'protected void ERR_RequestPlayerView(', 'void ERR_AddViewWatcher(', 'protected void ERR_EnableViewPublisher(', 'protected void ERR_SubmitPlayerView(', 'protected void ERR_ReceivePlayerView(']) run(r''' #include #include #include #include #include struct vector {float operator[](int i){return i==0?x:(i==1?y:z);}bool operator==(vector b){return x==b.x&&y==b.y&&z==b.z;}static vector Zero;float x=0,y=0,z=0;float LengthSq(){return x*x+y*y+z*z;}static float Dot(vector a,vector b){return a.x*b.x+a.y*b.y+a.z*b.z;}}; vector vector::Zero; namespace Math{float Round(float f){return std::round(f);}float AbsFloat(float a){return fabs(a);}} struct RplId{int value=-1;RplId(int i=-1):value(i){}static RplId Invalid(){return{-1};}bool operator==(RplId b){return value==b.value;}bool operator!=(RplId b){return value!=b.value;}}; struct RplComponent{RplId id{11};RplId Id(){return id;}static RplComponent* Cast(RplComponent* p){return p;}}; struct Actor {bool alive=true,conscious=true;int faction=1;RplComponent replication;RplComponent* FindComponent(){return &replication;}};using IEntity=Actor*; struct ERR_PlayerLife {int ConnectionId=1;bool valid=true;}; struct Roster {std::map lives;ERR_PlayerLife* CurrentActor(IEntity a){auto p=lives.find(a);return p!=lives.end()&&p->second->valid?p->second:nullptr;}}; struct ERR_GameMode {bool active=true;Roster roster;static ERR_GameMode* current;static ERR_GameMode* Get(){return current;}bool Active(){return active;}Roster* Players(){return &roster;}int PlayerFaction(){return 1;}};ERR_GameMode* ERR_GameMode::current; namespace ERR_Actors {bool Alive(IEntity a){return a&&a->alive;}bool CanFight(IEntity a){return Alive(a)&&a->conscious;}} namespace SCR_FactionManager{int SGetFaction(IEntity a){return a?a->faction:0;}} namespace ERR_ObserverReason{int NONE=0,UNCONSCIOUS=4;} struct ERR_ObserverRules {'''+body(ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_Observer.c','static bool View(').replace('ERR_ObserverReason.','ERR_ObserverReason::')+r'''}; templatestruct Array:std::vector{int Count(){return this->size();}bool Contains(T v){return std::find(this->begin(),this->end(),v)!=this->end();}void Insert(T v){this->push_back(v);}void Remove(int i){this->erase(this->begin()+i);}}; struct ERR_ObserverViewRules {'''+adapt(body(p,'static bool Sample('))+adapt(body(p,'static bool Packet('))+r'''}; struct ERR_ObserverScope {'''+adapt(body(ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_ObserverScope.c','static bool Valid('))+r'''}; namespace Replication{bool server=true;bool IsServer(){return server;}} struct SCR_PlayerController; struct Game {float now=1000;SCR_PlayerController* local=nullptr;std::map controllers; Game* GetWorld(){return this;}Game* GetPlayerManager(){return this;}float GetWorldTime(){return now;}SCR_PlayerController* GetPlayerController(){return local;}SCR_PlayerController* GetPlayerController(int id){return controllers[id];}} game; Game* GetGame(){return &game;} struct Buffer{float pipFov=0;int pushes=0,stamp=-1;RplId target;bool Accepts(RplId t,int s){return t!=target||s>stamp;}void Clear(){stamp=-1;target=-1;}void Push(RplId t,int s,float,vector,vector,vector,float,float,RplId,vector,float pf=0,vector g={},float v=0){pushes++;stamp=s;target=t;pipFov=pf;}}; struct SCR_PlayerController { int id=0;IEntity controlled=nullptr,m_ERRServerObserved=nullptr,m_ERRViewSourceBody=nullptr;RplId m_ERRObservedId; int m_ERRObserverReason=1,m_ERRViewInputSequence=0,leases=0,deliveries=0;float m_ERRViewLeaseUntil=-1,m_ERRViewServerRequestAt=-1000,m_ERRViewLeaseSent=-1000,m_ERRViewPublishUntil=-1,m_ERRViewLastPacket=-1000; Array m_ERRViewWatchers;Buffer m_ERRViewBuffer,m_ERREyeBuffer;bool m_ERRHasPIP=false; int GetPlayerId(){return id;}IEntity GetControlledEntity(){return controlled;}static SCR_PlayerController* Cast(SCR_PlayerController* p){return p;} void SendLease(){leases++;} void ERR_DeliverPlayerView(RplId,int,Array*,RplId,vector){deliveries++;} // Legacy scenario call shape only constructs the new on-wire packet. void ERR_SubmitPlayerView(int seq,vector p,vector f,vector u,float fov,float near,RplId weapon,vector data){Array a;a.Insert(p);a.Insert(f);a.Insert(u);a.Insert({fov,near,0});ERR_SubmitPlayerView(seq,&a,weapon,data);} void ERR_ReceivePlayerView(RplId target,int stamp,vector p,vector f,vector u,float fov,float near,RplId weapon,vector data){Array a;a.Insert(p);a.Insert(f);a.Insert(u);a.Insert({fov,near,0});ERR_ReceivePlayerView(target,stamp,&a,weapon,data);} '''+methods+r''' }; int main(){ ERR_GameMode mode;ERR_GameMode::current=&mode;Actor target,dead,revived;dead.alive=false; ERR_PlayerLife sourceLife;mode.roster.lives[&target]=&sourceLife; SCR_PlayerController source,watcher,stranger;source.id=1;watcher.id=2;stranger.id=3; source.controlled=⌖watcher.controlled=&dead;watcher.m_ERRServerObserved=⌖watcher.m_ERRObservedId={11}; game.controllers={{1,&source},{2,&watcher},{3,&stranger}}; assert(!watcher.ERR_ViewRecipient(&target,game.now)); // no lease watcher.ERR_RequestPlayerView();assert(source.m_ERRViewWatchers.Count()==1&&source.leases==1); watcher.ERR_RequestPlayerView();assert(source.leases==1); // bounded requests vector position{0,1.6,0},forward{0,0,1},up{0,1,0}; source.ERR_SubmitPlayerView(1,position,forward,up,60,.0125, -1, {});assert(watcher.deliveries==1); source.ERR_SubmitPlayerView(2,position,forward,up,60,.0125, -1, {});assert(watcher.deliveries==1); // packet rate bound game.now+=50;source.ERR_SubmitPlayerView(1,position,forward,up,60,.0125, -1, {});assert(watcher.deliveries==1); // replay source.ERR_SubmitPlayerView(2,{999,0,0},forward,up,60,.0125, -1, {});assert(watcher.deliveries==1); source.ERR_SubmitPlayerView(2,position,forward,up,60,.0125, -1, {});assert(watcher.deliveries==2); game.now+=50;source.ERR_SubmitPlayerView(3,position,forward,up,12,.0125,22,{99,0,0});assert(watcher.deliveries==2&&source.m_ERRViewInputSequence==2); // malformed scope cannot advance sequence or deliver game.now+=50;watcher.controlled=&revived;source.ERR_SubmitPlayerView(3,position,forward,up,60,.0125, -1, {});assert(watcher.deliveries==2&&source.m_ERRViewWatchers.Count()==0); // no stream to recovered players watcher.controlled=&dead;game.now+=500;watcher.ERR_RequestPlayerView();assert(source.m_ERRViewWatchers.Count()==1); target.faction=2;game.now+=50;source.ERR_SubmitPlayerView(4,position,forward,up,60,.0125, -1, {});assert(watcher.deliveries==2);target.faction=1; game.now+=500;watcher.ERR_RequestPlayerView();game.now+=1600;source.ERR_SubmitPlayerView(5,position,forward,up,60,.0125, -1, {});assert(watcher.deliveries==2&&source.m_ERRViewWatchers.Count()==0); // lease expired watcher.ERR_RequestPlayerView();watcher.m_ERRServerObserved=nullptr;game.now+=50;source.ERR_SubmitPlayerView(6,position,forward,up,60,.0125, -1, {});assert(watcher.deliveries==2); // target switch watcher.m_ERRServerObserved=⌖game.now+=500;watcher.ERR_RequestPlayerView();game.controllers[1]=&stranger;source.ERR_SubmitPlayerView(7,position,forward,up,60,.0125, -1, {});assert(watcher.deliveries==2);game.controllers[1]=&source; sourceLife.valid=false;game.now+=50;source.ERR_SubmitPlayerView(7,position,forward,up,60,.0125, -1, {});assert(watcher.deliveries==2);sourceLife.valid=true; game.local=&watcher;watcher.ERR_ReceivePlayerView({11},1,position,forward,up,60,.0125, -1, {});assert(watcher.m_ERRViewBuffer.pushes==1); watcher.ERR_ReceivePlayerView({22},2,position,forward,up,60,.0125, -1, {});assert(watcher.m_ERRViewBuffer.pushes==1); game.local=&stranger;watcher.ERR_ReceivePlayerView({11},3,position,forward,up,60,.0125, -1, {});assert(watcher.m_ERRViewBuffer.pushes==1); game.local=&watcher;mode.active=false;watcher.ERR_ReceivePlayerView({11},4,position,forward,up,60,.0125, -1, {});assert(watcher.m_ERRViewBuffer.pushes==1); mode.active=true;game.local=&watcher; Array dual;for(vector v:{position,forward,up,vector{12,.02,6},position,forward,up,vector{60,.02,0},vector{0,0,1}})dual.Insert(v); watcher.ERR_ReceivePlayerView(11,20,&dual,22,{1,0,0});assert(watcher.m_ERRHasPIP&&watcher.m_ERREyeBuffer.stamp==20&&watcher.m_ERRViewBuffer.stamp==20&&watcher.m_ERRViewBuffer.pipFov==6); dual[3].z=4;watcher.ERR_ReceivePlayerView(11,19,&dual,22,{1,0,0});assert(watcher.m_ERRViewBuffer.pipFov==6&&watcher.m_ERREyeBuffer.stamp==20); dual[4]={999,0,0};watcher.ERR_ReceivePlayerView(11,21,&dual,22,{1,0,0});assert(watcher.m_ERRViewBuffer.stamp==20);dual[4]=position; watcher.ERR_ReceivePlayerView(11,21,&dual,-1,{});assert(watcher.m_ERRViewBuffer.stamp==20); // PiP requires a scoped weapon watcher.ERR_ReceivePlayerView(11,22,position,forward,up,60,.02,-1,{});assert(!watcher.m_ERRHasPIP&&watcher.m_ERREyeBuffer.stamp==-1&&watcher.m_ERRViewBuffer.stamp==22); dual.pop_back();assert(!ERR_ObserverViewRules::Packet(&dual));assert(!ERR_ObserverViewRules::Packet(nullptr)); mode.active=true;game.local=&source;source.ERR_EnableViewPublisher();assert(source.m_ERRViewPublishUntil==game.now+2000); } ''') print('PASS: actual relay rejects noncanonical sources, live/foreign/stale viewers, invalid/replayed/fast packets; bounds leases and owner-only target delivery')