Files
EscapistsReintroduced/tests/test_spawn_scene_lease.py
T

72 lines
4.6 KiB
Python

"""Exercise production retention lifetime and the post-preload handoff."""
from policy_harness import ROOT, body, run
source = ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnSceneLease.c'
methods = '\n'.join(body(source, key) for key in ('void Start(', 'protected void Check(', 'void Stop('))
for old, new in [
('protected ', ''), ('SCR_PlayerController controller', 'Controller* controller'),
('IEntity actor', 'Actor* actor'), ('vector position', 'float position'),
('array<IEntity> entities', 'Items entities'), ('ERR_GameMode mode = ERR_GameMode.Get()', 'Mode* mode = currentMode'),
('mode.Active()', 'mode->active'), ('m_Controller.GetControlledEntity()', 'm_Controller->actor'),
('vector.DistanceXZ(m_Actor.GetOrigin(), m_Position)', 'std::abs(m_Actor->position - m_Position)'),
('GetGame().GetCallqueue().CallLater(Check, 500, true)', 'starts++'),
('if (GetGame()) GetGame().GetCallqueue().Remove(Check)', 'removes++'),
('foreach (IEntity entity :', 'for (int entity :'), ('null', 'nullptr')]:
methods = methods.replace(old, new)
run(r'''
#include <cassert>
#include <cmath>
#include <vector>
struct Items:std::vector<int>{using std::vector<int>::vector;void Clear(){clear();}void Copy(Items other){assign(other.begin(),other.end());}};
struct Actor{float position=0;};struct Controller{Actor* actor=nullptr;};
struct Mode{bool active=true;}mode;Mode* currentMode=&mode;
struct Lease{
Controller* m_Controller=nullptr;Actor* m_Actor=nullptr;float m_Position=0;Items m_Entities;
int starts=0,removes=0,released=0;void Stream(Controller*,int,bool normal){assert(normal);released++;}
'''+methods+r'''
};
int main(){
Actor actor,other;Controller controller{&actor};Lease lease;
lease.Start(&controller,&actor,0,{11,12,13});
for(int i=0;i<1000;i++){lease.Check();}assert(lease.released==0&&lease.m_Entities.size()==3);
actor.position=120;lease.Check();assert(lease.released==0);
actor.position=121;lease.Check();assert(lease.released==3&&lease.m_Entities.empty());
lease.Stop();assert(lease.released==3);
actor.position=0;lease.Start(&controller,&actor,0,{21});controller.actor=&other;lease.Check();assert(lease.released==4);
controller.actor=&actor;lease.Start(&controller,&actor,0,{22});currentMode=nullptr;lease.Check();assert(lease.released==5);currentMode=&mode;
lease.Start(&controller,&actor,0,{23});mode.active=false;lease.Check();assert(lease.released==6);mode.active=true;
lease.Start(&controller,&actor,0,{24});lease.m_Controller=nullptr;lease.Check();assert(lease.m_Entities.empty());
lease.Start(&controller,&actor,0,{25});lease.Start(&controller,&actor,0,{26});assert(lease.released==8);lease.Stop();assert(lease.released==9);
}
''')
scene = ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnClientScene.c'
verify = body(scene, 'bool ERR_VerifyLoadedScene(')
for old, new in [('ObserversSystem observers', 'Observers* observers'),
('observers.InsertObserverMP', 'observers->InsertObserverMP'),
('GetPlayerController().GetRplIdentity()', '1'), ('null', 'nullptr'),
('Rpc(ERR_ConfirmClientSpawnScene, m_ERRSceneToken)', 'confirms++')]:
verify = verify.replace(old, new)
run(r'''
#include <cassert>
template<typename... T>void PrintFormat(const char*,T...){}
struct Observers{int calls=0;void InsertObserverMP(int,float,float,void*){calls++;}};
struct Probe{
bool m_ERRSceneTimedOut=false,m_ERRScenePreloadRequired=true,m_ERRSceneFinalRequested=false,m_ERRSceneVerified=false,ready=false,preloading=false;
int m_ERRSceneToken=1,confirms=0;float m_ERRScenePosition[3]={1,0,2};Observers observer;
bool ERR_SpawnSceneReady(){return ready;}bool IsPreloading(){return preloading;}
Observers* GetObserversSystem(){return &observer;}bool GetPlayerController(){return true;}int GetPlayerId(){return 1;}
// Releasing nodes here would break dedicated final readiness: intentionally
// no streaming mutator in this adapter. The production method must retain them.
'''+verify+r'''
};
int main(){
Probe p;assert(!p.ERR_VerifyLoadedScene());p.ready=true;assert(!p.ERR_VerifyLoadedScene());
p.m_ERRScenePreloadRequired=false;p.preloading=true;assert(!p.ERR_VerifyLoadedScene());p.preloading=false;
assert(!p.ERR_VerifyLoadedScene()&&p.confirms==1&&p.observer.calls==1);
assert(!p.ERR_VerifyLoadedScene()&&p.confirms==1);p.m_ERRSceneVerified=true;assert(p.ERR_VerifyLoadedScene());
Probe timeout;timeout.m_ERRSceneTimedOut=true;assert(timeout.ERR_VerifyLoadedScene()&&timeout.confirms==0);
}
''')
print('PASS: spawn scene remains held through final acknowledgement and nearby use; leaving, reassignment, disconnect and teardown release it')