47 lines
3.4 KiB
Python
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("void AdventureBehaviorMgr::InterruptForInteraction",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 ↦}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")
|