Files
jakub cab998fb64 Combine Workshop addon and fix prison startup
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.
2026-09-20 16:42:52 +02:00

84 lines
6.0 KiB
Python

"""Actual session authority, transport scope and throttle policies; RPC delivery is native."""
from policy_harness import ROOT, body, run
session=ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_AdminSession.c'
bridge=ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerAdminCommands.c'
client=ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_ChatClient.c'
valid=body(session,'bool Valid(')
server=body(bridge,'protected ERR_AdminSession ERR_ServerSession(')
# Execute the exact admission/token guard prefix, before session allocation.
server=server[:server.index(' if (m_ERRAdminSession && token <')]+ ' return true;\n }'
server=server.replace('protected ERR_AdminSession ERR_ServerSession(', 'bool Admit(').replace('return null;', 'return false;')
command=body(session,'void Command(')
command=command[:command.index(' CheckBody();')]+' accepted++;\n }'
snapshot=body(session,'void Snapshot(')
snapshot=snapshot[:snapshot.index(' array<string> values')]+ ' snapshots++;\n }'
scope=body(client,'int Scope(')
accept=body(client,'bool Accept(')
def adapt(s):
s=s.replace('ERR_GameMode mode','Mode* mode').replace('PlayerManager players','Players* players').replace('ERR_AdminMenu menu','Menu* menu')
for n in ('Replication','ERR_GameMode','SCR_Global','ERR_MissionRules','ERR_AdminMenu'):
s=s.replace(n+'.',n+'::')
for n in ('m_Controller','m_Mode','mode','players','menu'):
s=s.replace(n+'.',n+'->')
s=s.replace('GetGame().','GetGame()->').replace('GetWorld().','GetWorld()->')
s=s.replace('arguments.Length()', 'arguments.size()')
return s
run(r'''
#include <cassert>
#include <string>
using string=std::string;
struct Controller {int id=7;int GetPlayerId(){return id;}};
struct Mode {int phase=1;int Phase(){return phase;}};
struct Players {Controller* owned=nullptr;Controller* GetPlayerController(int id){return owned&&id==owned->id?owned:nullptr;}};
struct Game {Players players;Controller* local=nullptr;float now=0;Players* GetPlayerManager(){return &players;}Controller* GetPlayerController(){return local;}Game* GetWorld(){return this;}float GetWorldTime(){return now;}} game;
Game* gameptr=&game;Game* GetGame(){return gameptr;}
namespace Replication{bool server=true;bool IsServer(){return server;}}
namespace SCR_Global{bool admin=true;bool IsAdmin(int id){return admin&&id==7;}}
namespace ERR_GameMode{Mode* current=nullptr;Mode* Get(){return current;}}
namespace ERR_MissionRules{bool Terminal(int phase){return phase==5;}}
struct Menu {int closes=0;void Close(){closes++;}} menu;
namespace ERR_AdminMenu{Menu* opened=nullptr;Menu* GetOpenMenu(){return opened;}}
struct Authority{bool m_Stopped=false;Controller* m_Controller=nullptr;Mode* m_Mode=nullptr;
'''+adapt(valid)+r'''
};
struct Transport{Mode* m_ERRServerChatMode=nullptr;int m_ERRServerChatToken=0;
'''+adapt(server)+r'''
};
struct Rate{bool allowed=true;float m_LastRequest=-1000,m_LastSnapshot=-1000;int accepted=0,snapshots=0;bool Authorize(){return allowed;}
'''+adapt(command)+adapt(snapshot)+r'''
};
struct Client{bool m_Stopped=false;Controller* m_Controller=nullptr;Mode* m_Mode=nullptr;int m_Token=1;
'''+adapt(scope)+adapt(accept)+r'''
};
int main(){
Controller owner,foreign;foreign.id=8;Mode first,second;game.local=&owner;game.players.owned=&owner;ERR_GameMode::current=&first;
Authority authority{false,&owner,&first};assert(authority.Valid());
SCR_Global::admin=false;assert(!authority.Valid());SCR_Global::admin=true;
Replication::server=false;assert(!authority.Valid());Replication::server=true;
game.players.owned=&foreign;assert(!authority.Valid());game.players.owned=&owner;
ERR_GameMode::current=&second;assert(!authority.Valid());ERR_GameMode::current=&first;
authority.m_Stopped=true;assert(!authority.Valid());authority.m_Stopped=false;
Transport transport;assert(!transport.Admit(0));assert(transport.Admit(1));
assert(transport.Admit(1));assert(!transport.Admit(2));assert(!transport.Admit(999)); // cannot reset session/rate/item state within round
ERR_GameMode::current=&second;assert(!transport.Admit(1));assert(transport.Admit(3));assert(!transport.Admit(2));assert(!transport.Admit(4));assert(transport.Admit(3));
second.phase=5;assert(!transport.Admit(3));second.phase=1;
Replication::server=false;assert(!transport.Admit(3));Replication::server=true;
Rate rate;game.now=0;rate.Command("status",false);assert(rate.accepted==1);rate.Command("status",false);assert(rate.accepted==1);
game.now=249;rate.Command("status",false);assert(rate.accepted==1);game.now=250;rate.Command("status",true);assert(rate.accepted==2);
game.now=1000;rate.Command(string(161,'x'),false);assert(rate.accepted==2);rate.allowed=false;rate.Command("status",false);rate.Snapshot(true);assert(rate.accepted==2&&rate.snapshots==0);rate.allowed=true;
rate.Snapshot();rate.Snapshot();assert(rate.snapshots==1);game.now=1499;rate.Snapshot();assert(rate.snapshots==1);game.now=1500;rate.Snapshot();assert(rate.snapshots==2);
Client client{false,&owner,&second,3};assert(client.Accept(3));assert(!client.Accept(2));
ERR_AdminMenu::opened=&menu;ERR_GameMode::current=&first;assert(!client.Accept(3));assert(client.m_Token==4&&menu.closes==1);assert(client.Accept(4)&&menu.closes==1);
game.local=&foreign;assert(!client.Accept(4));game.local=&owner;client.m_Stopped=true;assert(!client.Accept(4));
}
''')
source=bridge.read_text()
for name in ('ERR_AdminOpenResponse','ERR_AdminReplyResponse','ERR_AdminSnapshotResponse','ERR_AdminLogResponse'):
signature=source.index('protected void '+name+'(')
assert '[RplRpc(RplChannel.Reliable, RplRcver.Owner)]' in source[max(0,signature-65):signature]
assert 'm_ERRChatClient.Accept(token)' in body(bridge,'protected void '+name+'(')
assert 'm_Tools.Stop();' in body(session,'void Stop(')
assert 'm_Tools.Stop();' in body(session,'protected void CheckBody(')
assert body(session,'void Command(').index('if (!Authorize()) return;') < body(session,'void Command(').index('m_Tools.Execute(')
print('PASS: actual current-controller/admin/mode authorization, per-round anti-replay, token-rotation refusal, command/snapshot throttles and client scope; owner-only replies and player-tool cleanup wiring')