72 lines
4.5 KiB
Python
72 lines
4.5 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 ', ''), ('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')
|