Files
Viano-Core/tests/clientless/test_adventure_rest_targets.py
T
Nico e18a416bf4
clang PCH / build (push) Canceled after 0s
GCC PCH / build (push) Canceled after 0s
Add persistent instance visits and validate sleeping spaces
2026-10-27 20:10:13 +01:00

89 lines
4.8 KiB
Python

"""Exercise native sleep-space and candidate adapters with map/object fixtures."""
from pathlib import Path
import subprocess,tempfile
root=Path(__file__).resolve().parents[2]
source=(root/'src/server/game/World/AdventureBehaviorMgr.cpp').read_text()
def function(signature):
start=source.index(signature);body=source.index('{',start);end=body+1;depth=1
while depth:
depth+=(source[end]=='{')-(source[end]=='}');end+=1
return source[start:end]
code=r'''
#include "AdventureRestSpace.h"
#include <vector>
#include <cassert>
#include <cstdint>
using uint32=uint32_t;
#define TC_LOG_INFO(...) ((void)0)
constexpr float INVALID_HEIGHT=-100000;
constexpr int GAMEOBJECT_TYPE_CHAIR=7, LINEOFSIGHT_ALL_CHECKS=0;
namespace VMAP{enum class ModelIgnoreFlags{Nothing};}
struct Position{
float x=0,y=0,z=10,o=0;
Position()=default;Position(float a,float b,float c,float d=0):x(a),y(b),z(c),o(d){}
float GetPositionX()const{return x;}float GetPositionY()const{return y;}
float GetPositionZ()const{return z;}float GetOrientation()const{return o;}
float GetExactDist(float a,float b,float c)const{return std::sqrt((x-a)*(x-a)+(y-b)*(y-b)+(z-c)*(z-c));}
float GetExactDist2d(float a,float b)const{return std::hypot(x-a,y-b);}
};
struct GameObject:Position{
std::string name="Wooden Chair";bool phase=true,spawned=true;int type=7;
bool isSpawned(){return spawned;}auto GetName(){return name;}int GetGoType(){return type;}
float GetObjectScale(){return 1;}
};
struct Creature:Position{bool phase=true;float GetBoundaryRadius(){return 0.5f;}};
struct PositionFullTerrainStatus{bool outdoors=false;};
struct Terrain{
bool outdoors=false;
void GetFullTerrainStatusForPosition(int,int,float,float,float,PositionFullTerrainStatus& t){t.outdoors=outdoors;}
};
struct Map{
Terrain terrain;bool water=false,bed=false;float level=10;
float GetHeight(int,float x,float y,float probe,bool,float){
float h=bed && std::fabs(x-4)<2.1f && std::fabs(y)<0.95f?10.7f:level;
return probe>=h?h:level;
}
float GetWaterLevel(int,float,float){return water?12:-100000;}
bool isInLineOfSight(int,float,float,float,float,float,float,int,VMAP::ModelIgnoreFlags){return true;}
Terrain* GetTerrain(){return &terrain;}
};
struct Player:Position{
bool phase=true;Map map;std::vector<GameObject*> objects;std::vector<Player*> people;std::vector<Creature*> creatures;
struct Guid{uint32 GetCounter(){return 26;}};Guid GetGUID(){return {};}
Map* GetMap(){return &map;}int GetPhaseShift(){return 0;}int GetMapId(){return 0;}
float GetCollisionHeight(){return 2;}
template<class T>bool IsInPhase(T* p){return p->phase;}
void GetGameObjectListWithEntryInGrid(std::vector<GameObject*>& v,int,float){v=objects;}
void GetPlayerListInGrid(std::vector<Player*>& v,float){v=people;}
void GetCreatureListWithEntryInGrid(std::vector<Creature*>& v,int,float){v=creatures;}
};
'''
code+=function(' bool SleepSpace(')+'\n'+function(' std::vector<Position> SleepCandidates(')
code+=r'''
int main(){
Player p;Position anchor(0,0,10);GameObject chair;p.objects={&chair};
assert(!SleepSpace(&p,anchor));
chair.phase=false;assert(SleepSpace(&p,anchor));chair.phase=true;
chair.spawned=false;assert(SleepSpace(&p,anchor));chair.spawned=true;
chair.z=3;assert(SleepSpace(&p,anchor));chair.z=10;
auto candidates=SleepCandidates(&p,anchor,true);
assert(!candidates.empty()); // shift off the chair, rather than merely reject the marker
for(auto const& c:candidates){assert(c.GetExactDist2d(0,0)>1);assert(std::fabs(c.z-10)<0.01f);}
p.map.terrain.outdoors=true;assert(SleepCandidates(&p,anchor,true).empty());p.map.terrain.outdoors=false;
p.map.water=true;assert(SleepCandidates(&p,anchor,true).empty());p.map.water=false;
p.map.level=3;assert(SleepCandidates(&p,anchor,true).empty());p.map.level=10; // not the storey below
p.objects.clear();Player visitor;visitor.x=1;p.people={&visitor};assert(!SleepSpace(&p,anchor));p.people.clear();
Creature npc;npc.x=1;p.creatures={&npc};assert(!SleepSpace(&p,anchor));p.creatures.clear();
GameObject bed;bed.name="Hospital Bed";bed.type=5;bed.x=4;p.objects={&bed};p.map.bed=true;
candidates=SleepCandidates(&p,anchor,true);assert(!candidates.empty());
assert(candidates.front().x==4 && std::fabs(candidates.front().z-10.7f)<0.01f); // real bed before floor
p.objects.clear();candidates=SleepCandidates(&p,anchor,true);assert(!candidates.empty());
assert(std::fabs(candidates.front().z-10.7f)<0.01f); // static raised surface before floor
}
'''
with tempfile.TemporaryDirectory() as tmp:
src=Path(tmp)/'targets.cpp';src.write_text(code);exe=Path(tmp)/'targets'
subprocess.run(['g++','-std=c++17','-Wall','-Wextra','-Werror','-I'+str(root/'src/server/game/World'),str(src),'-o',str(exe)],check=True)
subprocess.run([str(exe)],check=True)
print('Native sleep targets: chair exclusion, phase, despawn, floor search, indoors, water, storey, occupancy, bed/surface preference passed.')