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.
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
"""Run production readiness/ack/timeout bodies with delayed replication adapters."""
|
||||
from policy_harness import ROOT, body, run
|
||||
|
||||
source = ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnClientScene.c'
|
||||
keys = ('bool ERR_SpawnSceneReady(', 'bool ERR_SpawnSceneMayFinish(',
|
||||
'protected void ERR_AcknowledgeSpawnScene(',
|
||||
'protected void ERR_ClearClientSpawnScene(',
|
||||
'protected void ERR_CheckClientSpawnScene(',
|
||||
'protected void ERR_CancelClientSpawnScene(')
|
||||
methods = '\n'.join(body(source, key) for key in keys)
|
||||
methods = methods.replace('protected ', '').replace('Replication.IsServer()', 'Replication::IsServer()')
|
||||
methods = methods.replace('ERR_GameMode.Get()', 'Mode::Get()')
|
||||
methods = methods.replace('RplComponent component = RplComponent.Cast(Replication.FindItem(id));', 'RplComponent* component = Replication::FindItem(id);')
|
||||
methods = methods.replace('component.GetEntity()', 'component->GetEntity()')
|
||||
methods = methods.replace('foreach (RplId id :', 'for (RplId id :')
|
||||
methods = methods.replace('GetGame().GetWorld().GetWorldTime()', 'game.now')
|
||||
methods = methods.replace('GetGame().GetCallqueue().Remove(ERR_CheckClientSpawnScene)', 'game.removes++')
|
||||
methods = methods.replace('Rpc(ERR_AcknowledgeSpawnScene, token)', 'SendAck(token)')
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
using RplId=int;
|
||||
struct RplComponent{bool entity=true;bool GetEntity(){return entity;}};
|
||||
namespace Replication{bool server=true;std::map<int,RplComponent*> items;bool IsServer(){return server;}RplComponent* FindItem(int id){return items.count(id)?items[id]:nullptr;}}
|
||||
struct Mode{static bool present;static bool Get(){return present;}};bool Mode::present=true;
|
||||
struct Game{float now=0;int removes=0;}game;Game* GetGame(){return &game;}
|
||||
struct Nodes:std::vector<int>{using std::vector<int>::operator=;void Clear(){clear();}int Count(){return size();}};
|
||||
template<typename... T>void PrintFormat(const char*,T...){}
|
||||
struct Probe{
|
||||
int m_ERRSceneToken=4,m_ERRClientSceneToken=4,acks=0,lastAck=0;
|
||||
bool m_ERRScenePending=false,m_ERRSceneAcknowledged=false,m_ERRSceneTimedOut=false,m_ERRClientScenePending=false;
|
||||
float m_ERRSceneDeadline=1000;Nodes m_ERRClientSceneNodes;
|
||||
int GetPlayerId(){return 1;}void SendAck(int token){acks++;lastAck=token;}
|
||||
'''+methods+r'''
|
||||
};
|
||||
int main(){
|
||||
Probe server;assert(!server.ERR_SpawnSceneReady());
|
||||
server.ERR_AcknowledgeSpawnScene(4);assert(!server.m_ERRSceneAcknowledged);
|
||||
server.m_ERRScenePending=true;assert(!server.ERR_SpawnSceneMayFinish());
|
||||
server.ERR_AcknowledgeSpawnScene(3);assert(!server.ERR_SpawnSceneReady());
|
||||
Replication::server=false;server.ERR_AcknowledgeSpawnScene(4);assert(!server.ERR_SpawnSceneReady());Replication::server=true;
|
||||
server.ERR_AcknowledgeSpawnScene(4);assert(server.ERR_SpawnSceneReady()&&server.ERR_SpawnSceneMayFinish());
|
||||
server.m_ERRSceneAcknowledged=false;game.now=999;assert(!server.ERR_SpawnSceneMayFinish());
|
||||
game.now=1000;assert(server.ERR_SpawnSceneMayFinish()&&server.m_ERRSceneTimedOut&&!server.ERR_SpawnSceneReady());
|
||||
server.ERR_AcknowledgeSpawnScene(4);assert(!server.ERR_SpawnSceneReady());
|
||||
Probe client;client.m_ERRClientScenePending=true;client.m_ERRClientSceneNodes={11,22,33};
|
||||
RplComponent root,wall,gate;Replication::items[11]=&root;
|
||||
for(int i=0;i<100;i++){client.ERR_CheckClientSpawnScene();}assert(client.acks==0&&client.m_ERRClientScenePending);
|
||||
Replication::items[22]=&wall;client.ERR_CheckClientSpawnScene();assert(client.acks==0);
|
||||
gate.entity=false;Replication::items[33]=&gate;client.ERR_CheckClientSpawnScene();assert(client.acks==0);
|
||||
gate.entity=true;client.ERR_CheckClientSpawnScene();assert(client.acks==1&&client.lastAck==4&&!client.m_ERRClientScenePending&&client.m_ERRClientSceneNodes.empty());
|
||||
client.ERR_CheckClientSpawnScene();assert(client.acks==1);
|
||||
client.m_ERRClientScenePending=true;client.m_ERRClientSceneToken=5;client.m_ERRClientSceneNodes={99};
|
||||
client.ERR_CancelClientSpawnScene(4);assert(client.m_ERRClientScenePending);
|
||||
client.ERR_CancelClientSpawnScene(5);assert(!client.m_ERRClientScenePending&&client.m_ERRClientSceneNodes.empty());
|
||||
client.m_ERRClientScenePending=true;Mode::present=false;client.ERR_CheckClientSpawnScene();assert(!client.m_ERRClientScenePending&&client.acks==1);
|
||||
}
|
||||
''')
|
||||
finalizer = ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnFinalization.c'
|
||||
methods = '\n'.join(body(finalizer, key) for key in ('override bool CanFinalize_S(', 'override SCR_ESpawnResult FinalizeRequest_S('))
|
||||
for old, new in [('override ', ''), ('SCR_SpawnRequestComponent requestComponent', 'Request* requestComponent'),
|
||||
('SCR_SpawnData data', 'Data* data'), ('IEntity entity', 'Actor* entity'),
|
||||
('ERR_SpawnLogic logic', 'Logic* logic'), ('ERR_SpawnTicket ticket', 'Ticket* ticket'),
|
||||
('ERR_GameMode.Get()', 'Mode::Get()'), ('SCR_ESpawnResult.', 'SCR_ESpawnResult::'),
|
||||
('requestComponent.', 'requestComponent->'), ('logic.', 'logic->'), ('super.', 'Native::')]:
|
||||
methods = methods.replace(old, new)
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
enum class SCR_ESpawnResult{OK,SPAWN_NOT_ALLOWED,CANNOT_ASSIGN};
|
||||
struct Request{bool ready=false,mayFinish=false;int ends=0;bool ERR_SpawnSceneReady(){return ready;}bool ERR_SpawnSceneMayFinish(){return mayFinish;}void ERR_EndSpawnScene(){ends++;}};
|
||||
struct Data{};struct Actor{};struct Ticket{};
|
||||
struct Mode{static bool current;static bool Get(){return current;}};bool Mode::current=true;
|
||||
struct Logic{Ticket ticket;bool hasTicket=true,allowed=true;Ticket* TakeSpawnTicket(Request*,Data*,Actor*){return hasTicket?&ticket:nullptr;}bool MayFinalizeSpawn(Ticket*){return allowed;}};
|
||||
struct Native{bool preloadReady=false;int assignments=0;SCR_ESpawnResult result=SCR_ESpawnResult::OK;bool CanFinalize_S(Request*,Data*,Actor*){return preloadReady;}SCR_ESpawnResult FinalizeRequest_S(Request*,Data*,Actor*){assignments++;return result;}};
|
||||
struct Handler:Native{Logic storage;Logic* logic=&storage;int rejects=0;Logic* ERR_AdmissionLogic(){return logic;}void ERR_RejectOwnedActor(Request*,Actor*,Data*){rejects++;}
|
||||
'''+methods+r'''
|
||||
};
|
||||
int main(){
|
||||
Request request;Data data;Actor actor;Handler h;
|
||||
h.preloadReady=true;assert(!h.CanFinalize_S(&request,&data,&actor));
|
||||
request.mayFinish=true;h.preloadReady=false;assert(!h.CanFinalize_S(&request,&data,&actor));
|
||||
h.preloadReady=true;assert(h.CanFinalize_S(&request,&data,&actor));
|
||||
// Timeout can end the pending request, but cannot assign an actor.
|
||||
assert(h.FinalizeRequest_S(&request,&data,&actor)==SCR_ESpawnResult::SPAWN_NOT_ALLOWED&&h.assignments==0&&h.rejects==1&&request.ends==1);
|
||||
request.ready=true;h.storage.allowed=false;
|
||||
assert(h.FinalizeRequest_S(&request,&data,&actor)==SCR_ESpawnResult::SPAWN_NOT_ALLOWED&&h.assignments==0&&h.rejects==2);
|
||||
h.storage.allowed=true;assert(h.FinalizeRequest_S(&request,&data,&actor)==SCR_ESpawnResult::OK&&h.assignments==1&&request.ends==3);
|
||||
h.storage.hasTicket=false;assert(h.FinalizeRequest_S(&request,&data,&actor)==SCR_ESpawnResult::SPAWN_NOT_ALLOWED&&h.assignments==1&&h.rejects==2);
|
||||
Mode::current=false;h.logic=nullptr;assert(h.FinalizeRequest_S(&request,&data,&actor)==SCR_ESpawnResult::OK&&h.assignments==2);
|
||||
}
|
||||
''')
|
||||
print('PASS: delayed wall/gate replication withholds assignment; native preload, identity checks, stale replies, cancellation and timeout remain enforced')
|
||||
Reference in New Issue
Block a user