65 lines
4.8 KiB
Python
65 lines
4.8 KiB
Python
"""Execute moving-target flight and safe landing adapters over real geometry."""
|
|
from pathlib import Path
|
|
import subprocess,tempfile
|
|
root=Path(__file__).resolve().parents[2]
|
|
s=(root/'src/server/game/World/ClientlessFlightMgr.cpp').read_text()
|
|
def method(sig):
|
|
a=s.index(sig);b=s.index('{',a);e=b+1;n=1
|
|
while n:n+=(s[e]=='{')-(s[e]=='}');e+=1
|
|
return s[a:e]
|
|
code=r'''
|
|
#include "ClientlessFlightPath.h"
|
|
#include <cassert>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
using uint32=unsigned;using namespace ClientlessFlightPath;
|
|
constexpr int MAX_HEIGHT=100000,MOVEMENTFLAG_FLYING=1,MOVE_FLIGHT=2;
|
|
struct Position{float x=0,y=0,z=0,o=0;void Relocate(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;}};
|
|
Point PointOf(Position const&p){return {p.x,p.y,p.z};}
|
|
namespace Trinity{bool IsValidMapCoord(float x,float y,float z){return std::isfinite(x)&&std::isfinite(y)&&std::isfinite(z);}}
|
|
struct Map{float floor=0;float GetHeight(int,float,float,float,bool,float){return floor;}}map;
|
|
struct Guid{unsigned GetCounter(){return 26;}};
|
|
struct Player:Position{bool spline=false;unsigned launches=0,stops=0;Guid GetGUID(){return {};}bool IsSplineEnabled(){return spline;}void StopMoving(){++stops;spline=false;}void AddUnitMovementFlag(int){}float GetSpeed(int){return 20;}Map*GetMap(){return ↦}int GetPhaseShift(){return 169;}};
|
|
namespace Movement{struct MoveSplineInit{Player*p;Point target;MoveSplineInit(Player*who):p(who){}void MoveTo(float x,float y,float z,bool){target={x,y,z};}void SetFly(){}void SetWalk(bool){}void SetVelocity(float){}int Launch(){++p->launches;p->spline=true;return 1;}};}
|
|
enum class ClientlessFlightState{Mounting,Flying,Arrived,Failed};
|
|
struct Record{
|
|
struct{ClientlessFlightState State=ClientlessFlightState::Flying;bool FollowingPlayer=true;Position Target,Landing;unsigned Segments=0;float Travelled=5000;std::string Detail;}Status;
|
|
bool Returning=false,Moving=false;unsigned Elapsed=1000,TargetUpdated=0,SegmentElapsed=0;Position Segment;
|
|
ClientlessFlightPath::Settings Settings;ClientlessFlightPath::Memory Memory;
|
|
std::shared_ptr<int>Following;std::vector<Position>Breadcrumbs;
|
|
};
|
|
bool clear=true,valid=true;float ceiling=300;
|
|
bool ClearRay(Player*,Point const&,Point const&){return clear;}
|
|
struct ClientlessFlightMgr{
|
|
std::unordered_map<unsigned,Record>_records;unsigned beginnings=0,failures=0;
|
|
Surface Sample(Player*,Record&,float,float){return {map.floor,ceiling,valid};}
|
|
bool Begin(Player*,Position const&,std::string&,bool following){assert(following);++beginnings;return true;}
|
|
void Fail(Player*,Record&r,std::string const&){++failures;r.Status.State=ClientlessFlightState::Failed;}
|
|
bool Follow(Player*,Position const&,std::string&);bool LandFollowing(Player*);bool AdvanceFollowing(Player*,Record&);
|
|
};
|
|
'''
|
|
for sig in ['bool ClientlessFlightMgr::Follow(', 'bool ClientlessFlightMgr::LandFollowing(', 'bool ClientlessFlightMgr::AdvanceFollowing(']:code+=method(sig)+'\n'
|
|
code+=r'''
|
|
int main(){
|
|
ClientlessFlightMgr mgr;Player p;p.z=20;Position target;target.Relocate(100,0,20);std::string error;
|
|
assert(mgr.Follow(&p,target,error) && mgr.beginnings==1);auto&r=mgr._records[26];
|
|
assert(mgr.Follow(&p,target,error));assert(r.TargetUpdated==r.Elapsed && r.Status.Target.x==100);
|
|
assert(mgr.AdvanceFollowing(&p,r));assert(p.launches==1 && r.Segment.x>0 && r.Segment.x<=25 && r.Segment.z==20);
|
|
// Moving the leader updates the destination without inventing a ground landing.
|
|
target.Relocate(110,20,30);r.Elapsed=2000;assert(mgr.Follow(&p,target,error));assert(r.Status.Target.z==30 && r.TargetUpdated==2000);
|
|
clear=false;assert(!mgr.AdvanceFollowing(&p,r));assert(p.stops==1 && r.Status.State==ClientlessFlightState::Flying);
|
|
clear=true;ceiling=25;assert(!mgr.Follow(&p,target,error));ceiling=300;
|
|
p.Relocate(110,20,30);r.Moving=true;assert(mgr.AdvanceFollowing(&p,r));assert(!r.Moving && p.stops==2); // holds in air, never dismounts at moving goal
|
|
assert(mgr.LandFollowing(&p));assert(!r.Status.FollowingPlayer && r.Status.Landing.z==0 && r.Status.Travelled==0);
|
|
assert(!mgr.Follow(&p,target,error)); // landing cannot be replaced by a new pursuit
|
|
r.Status.FollowingPlayer=true;r.Status.State=ClientlessFlightState::Mounting;assert(mgr.LandFollowing(&p) && mgr.failures==1);
|
|
r.Status.State=ClientlessFlightState::Flying;r.Status.FollowingPlayer=true;valid=false;assert(mgr.LandFollowing(&p) && mgr.failures==2);
|
|
}
|
|
'''
|
|
with tempfile.TemporaryDirectory() as d:
|
|
p=Path(d);(p/'test.cpp').write_text(code)
|
|
subprocess.run(['g++','-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('Moving-target flight: bounded phased corridors, obstacle hold, ceiling rejection, aerial formation hold, safe landing and return fallback passed')
|