Files
Viano-Core/tests/clientless/test_instance_group_protection.py
T
Nico 3aa780662e Complete AdventureBot navigation, instance travel and shutdown fixes
Finish capital waiting travel and adaptive flight entry up to 10,000 yards.
Preserve checked vertical climbs, recover blocked ground departures and find
validated dry landings. Retain group routes and Undercity arrival constraints.

Restore defense from native combat references, coordinate instance rendezvous
and browser reentry, finalize clientless sessions before map destruction and
transfer Halaa capture-point ownership safely.

Include the associated regression tests, investigation reports and reusable
diagnostic scripts. Keep generated runtime evidence and server binaries local
through scoped ignore rules. Validation/build/live evidence is recorded in the
session checkpoint and individual reports.
2026-11-05 10:35:34 +01:00

47 lines
3.4 KiB
Python

"""Run the production group-wide instance leave protection predicate."""
from pathlib import Path
import subprocess,tempfile
root=Path(__file__).resolve().parents[2]
s=(root/"src/server/game/World/AdventureBehaviorMgr.cpp").read_text()
a=s.index("bool AdventureBehaviorMgr::ProtectInstanceGroupLeave(")
b=s.index("bool AdventureBehaviorMgr::PauseForLogout",a)
code=r'''
#include "AdventureInstancePolicy.h"
#include <cassert>
#include <unordered_map>
#include <string>
using uint32=unsigned;
namespace GameTime{time_t GetGameTime(){return 1000;}}
struct Group;
struct Map{bool dungeon=false;bool IsDungeon()const{return dungeon;}};
struct Guid{unsigned id;unsigned GetCounter()const{return id;}};
struct Player{unsigned id;Group* group=nullptr;Map map;bool online=true;bool IsInWorld()const{return online;}Group* GetGroup(){return group;}Map* GetMap(){assert(online);return &map;}Guid GetGUID(){return {id};}};
struct Reference{Player* player=nullptr;Reference* following=nullptr;Player* GetSource(){return player;}Reference* next(){return following;}};
struct Group{Reference* first=nullptr;Reference* GetFirstMember(){return first;}};
struct Location{unsigned InstanceMap=671;} location;
struct Locations{Location const* Find(std::string const& key){return key=="instance"?&location:nullptr;}} locations;auto sAdventureLocationMgr=&locations;
struct AdventureBehaviorMgr{struct Record{AdventureInstancePolicy::Visit Instance;std::string Intent,Location;time_t Deadline=0;};std::unordered_map<unsigned,Record> _records;bool ProtectInstanceGroupLeave(Player*)const;};
'''+s[a:b]+r'''
int main(){AdventureBehaviorMgr m;Player late{1},leader{2};assert(!m.ProtectInstanceGroupLeave(&late));
Reference second{&leader,nullptr},first{&late,&second};Group group{&first};late.group=leader.group=&group;
assert(!m.ProtectInstanceGroupLeave(&late));leader.map.dungeon=true;
assert(m.ProtectInstanceGroupLeave(&late)); // human leader inside, no behavior record
leader.online=false;assert(!m.ProtectInstanceGroupLeave(&late));leader.online=true;leader.map.dungeon=false;
auto& r=m._records[2];r.Instance.Active=true;
for(auto phase:{AdventureInstancePolicy::Phase::Travel,AdventureInstancePolicy::Phase::Preparing,AdventureInstancePolicy::Phase::Entering,AdventureInstancePolicy::Phase::Inside,AdventureInstancePolicy::Phase::Returning}){
r.Instance.Stage=phase;assert(m.ProtectInstanceGroupLeave(&late));}
r.Instance.Stage=AdventureInstancePolicy::Phase::Rest;r.Intent="raid";r.Location="instance";r.Deadline=2000;
assert(!m.ProtectInstanceGroupLeave(&late)); // finished visit must not retain protection
r.Instance.Active=false;assert(m.ProtectInstanceGroupLeave(&late)); // pending retry/en-route
r.Intent="instance";assert(m.ProtectInstanceGroupLeave(&late));
r.Deadline=1000;assert(!m.ProtectInstanceGroupLeave(&late));
r.Deadline=2000;r.Location="unknown";assert(!m.ProtectInstanceGroupLeave(&late));
r.Location="instance";r.Intent="profession";assert(!m.ProtectInstanceGroupLeave(&late));
first.following=nullptr;assert(!m.ProtectInstanceGroupLeave(&late));}
'''
with tempfile.TemporaryDirectory(prefix="vcore-instance-group-protection-") as d:
p=Path(d);(p/"test.cpp").write_text(code)
subprocess.run(["c++","-std=c++17","-I"+str(root/"src/server/game/World"),str(p/"test.cpp"),"-o",str(p/"test")],check=True)
subprocess.run([str(p/"test")],check=True)
print("Instance group protection: travel/preparing/entering/inside/return, human leader, offline, retry, expiry and finished visit PASS")