Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
91 lines
5.7 KiB
Python
91 lines
5.7 KiB
Python
"""Actual scene deadline + finalization; a late remote preload cannot hold an expired ticket."""
|
|
import os
|
|
from pathlib import Path
|
|
from policy_harness import ROOT, body, run
|
|
base = ROOT/'addons/core/Scripts/Game/ERR/00_Core'
|
|
finalizer = Path(os.environ.get('ERR_SPAWN_FINALIZATION_SOURCE', base/'ERR_SpawnFinalization.c'))
|
|
scene = base/'ERR_SpawnClientScene.c'
|
|
request = '\n'.join(body(scene, key) for key in (
|
|
'bool ERR_SpawnSceneReady(', 'bool ERR_SpawnSceneVerified(',
|
|
'bool ERR_SpawnSceneMayFinish(', 'bool ERR_TakeScenePreload('))
|
|
request = request.replace('GetGame().GetWorld().GetWorldTime()', 'worldTime')
|
|
handler = '\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::'),
|
|
('ticket.', 'ticket->'), ('requestComponent.', 'requestComponent->'), ('logic.', 'logic->'), ('super.', 'Native::')]:
|
|
handler = handler.replace(old,new)
|
|
run(r'''
|
|
#include <cassert>
|
|
float worldTime=0;
|
|
template<class...T>void PrintFormat(const char*,T...){}
|
|
enum class SCR_ESpawnResult {OK,SPAWN_NOT_ALLOWED};
|
|
struct Request {
|
|
bool m_ERRScenePending=true,m_ERRSceneAcknowledged=true,m_ERRSceneTimedOut=false;
|
|
bool m_ERRSceneVerified=false,m_ERRScenePreloadRequired=false,nativePreloading=true;
|
|
float m_ERRSceneDeadline=60000,m_ERRSceneStartedAt=0;
|
|
int m_ERRSceneToken=1,ends=0,retained=0;
|
|
bool IsPreloading(){return nativePreloading;}
|
|
int GetPlayerId(){return 1;}
|
|
void ERR_RefreshSceneInventory(){}
|
|
bool ERR_VerifyLoadedScene(){return m_ERRSceneTimedOut||ERR_SpawnSceneVerified();}
|
|
void ERR_EndSpawnScene(){ends++;m_ERRScenePending=false;m_ERRSceneAcknowledged=false;m_ERRSceneTimedOut=false;m_ERRSceneVerified=false;}
|
|
void ERR_RetainSpawnScene(void*){retained++;}
|
|
'''+request+r'''
|
|
};
|
|
struct Data{};struct Actor{};struct Ticket{int releases=0;void ReleaseProtection(){releases++;}};
|
|
struct Mode{static inline bool current=true;static bool Get(){return current;}};
|
|
struct Logic{
|
|
Ticket ticket;bool hasTicket=true,allowed=true;int authorizationChecks=0;
|
|
Ticket* TakeSpawnTicket(Request*,Data*,Actor*){if(!hasTicket)return nullptr;hasTicket=false;return &ticket;}
|
|
bool MayFinalizeSpawn(Ticket*){authorizationChecks++;return allowed;}
|
|
};
|
|
struct Native{
|
|
int assignments=0,preloadStarts=0;
|
|
void OnFinalizeBegin_S(Request* request,Data*,Actor*){preloadStarts++;request->nativePreloading=true;}
|
|
// Exact native SCR_SpawnHandlerComponent contract: no server-side timeout.
|
|
bool CanFinalize_S(Request* request,Data*,Actor*){return !request->IsPreloading();}
|
|
SCR_ESpawnResult FinalizeRequest_S(Request*,Data*,Actor*){assignments++;return SCR_ESpawnResult::OK;}
|
|
};
|
|
struct Handler:Native{
|
|
Logic storage;Logic* logic=&storage;int rejects=0;
|
|
Logic* ERR_AdmissionLogic(){return logic;}
|
|
void ERR_RejectOwnedActor(Request*,Actor*,Data*){rejects++;}
|
|
'''+handler+r'''
|
|
};
|
|
int main(){
|
|
Data data;Actor actor;
|
|
// Scene replication was acknowledged, native asset preload started, but its
|
|
// remote completion is delayed. The server's own deadline must still reject.
|
|
{Request request;Handler h;
|
|
worldTime=59999;assert(!h.CanFinalize_S(&request,&data,&actor));
|
|
assert(!request.m_ERRSceneTimedOut&&h.assignments==0&&h.rejects==0);
|
|
worldTime=60000;assert(h.CanFinalize_S(&request,&data,&actor));
|
|
assert(request.m_ERRSceneTimedOut&&request.nativePreloading&&!request.ERR_SpawnSceneVerified());
|
|
assert(h.FinalizeRequest_S(&request,&data,&actor)==SCR_ESpawnResult::SPAWN_NOT_ALLOWED);
|
|
assert(h.rejects==1&&h.assignments==0&&h.storage.ticket.releases==1&&h.storage.authorizationChecks==0&&request.ends==1&&request.retained==0);
|
|
// A late native completion cannot resurrect the consumed ticket or actor.
|
|
request.nativePreloading=false;
|
|
assert(h.FinalizeRequest_S(&request,&data,&actor)==SCR_ESpawnResult::SPAWN_NOT_ALLOWED);
|
|
assert(h.rejects==1&&h.assignments==0&&request.ends==1);}
|
|
// No scene acknowledgement also expires without starting a native preload.
|
|
{Request request;Handler h;request.m_ERRSceneAcknowledged=false;request.nativePreloading=false;request.m_ERRScenePreloadRequired=true;
|
|
worldTime=59999;assert(!h.CanFinalize_S(&request,&data,&actor));
|
|
worldTime=60000;assert(h.CanFinalize_S(&request,&data,&actor)&&h.preloadStarts==0);
|
|
assert(h.FinalizeRequest_S(&request,&data,&actor)==SCR_ESpawnResult::SPAWN_NOT_ALLOWED&&h.assignments==0);}
|
|
// Before the deadline, ordinary scene and native preload gates still hold.
|
|
{Request request;Handler h;worldTime=1000;request.nativePreloading=false;request.m_ERRScenePreloadRequired=true;
|
|
assert(!h.CanFinalize_S(&request,&data,&actor)&&h.preloadStarts==1);
|
|
request.nativePreloading=false;assert(!h.CanFinalize_S(&request,&data,&actor));
|
|
request.m_ERRSceneVerified=true;assert(h.CanFinalize_S(&request,&data,&actor));
|
|
assert(h.FinalizeRequest_S(&request,&data,&actor)==SCR_ESpawnResult::OK&&h.assignments==1&&request.retained==1&&h.storage.ticket.releases==1);}
|
|
// Invalid server snapshots already marked timed-out also take rejection only.
|
|
{Request request;Handler h;worldTime=1;request.m_ERRSceneTimedOut=true;
|
|
assert(h.CanFinalize_S(&request,&data,&actor));
|
|
assert(h.FinalizeRequest_S(&request,&data,&actor)==SCR_ESpawnResult::SPAWN_NOT_ALLOWED&&h.assignments==0);}
|
|
}
|
|
''')
|
|
print('PASS: actual scene deadline overrides delayed native preload only for rejection; late completion cannot assign, ordinary verified admission preserved')
|