Publish replacement landing targets, bound orphaned trail waits, and plan safe connections from the follower position. Support shared-route regroup landings and preserve catch-up flights after the leader lands. Add geometry, lifecycle and group travel regressions.
62 lines
4.0 KiB
Python
62 lines
4.0 KiB
Python
"""Join a leader trail from a later taxi stop instead of replaying its origin."""
|
|
from pathlib import Path
|
|
import subprocess,tempfile
|
|
root=Path(__file__).resolve().parents[2]
|
|
code=r'''
|
|
#include "ClientlessFlightPath.h"
|
|
#include <cassert>
|
|
#include <iostream>
|
|
using namespace ClientlessFlightPath;
|
|
int main(){Settings cfg;auto flat=[](float,float){return Surface{0,1000,true};};auto clear=[](Point const&,Point const&){return true;};
|
|
SharedTrail trail;trail.LandingReady=true;trail.Complete=true;trail.Landing={1200,0,0};
|
|
trail.Points={{0,0,20},{1025,0,60},{1050,0,60},{1100,0,60},{1200,0,0}};
|
|
SharedJoin join;std::size_t index=0;Point current{1000,0,0};bool connected=false;
|
|
for(unsigned i=0;i<100&&Distance(current,trail.Landing)>.1f;++i){
|
|
auto result=FollowTrail(current,trail.Landing,cfg,trail,index,flat,clear,0,&join);
|
|
assert(!result.Waiting&&result.Step.Valid);assert(result.Step.Next.X>=1000);
|
|
assert(Corridor(current,result.Step.Next,trail.Landing,cfg,flat,clear,true,result.Step.UnderOverhang));
|
|
current=result.Step.Next;if(!join.Active)connected=true;
|
|
}
|
|
assert(connected&&Distance(current,trail.Landing)<.1f&&index>=1);
|
|
// Original Winienwi geometry: the old first point is 2,088 yards behind
|
|
// the taxi stop and its direct segment intersects a raised surface.
|
|
Point taxi{-4170.55f,-4748.93f,126.786f};SharedTrail actual;
|
|
actual.LandingReady=true;actual.Landing={-4905.67f,-4232.75f,827.766f};
|
|
actual.Points={{-4863.52f,-6715.61f,24.22f},{-4850,-4750,540},actual.Landing};
|
|
auto hills=[](float x,float y){float ground=y< -6500?9.f:126.786f;
|
|
if(std::fabs(x+4175.523f)<2.5f&&std::fabs(y+4763.045f)<2.5f)ground=129.25f;
|
|
return Surface{ground,1000,true};};
|
|
assert(!Corridor(taxi,actual.Points[0],actual.Landing,cfg,hills,clear,true));
|
|
join={};index=0;auto connectedTaxi=FollowTrail(taxi,actual.Landing,cfg,actual,index,hills,clear,0,&join);
|
|
assert(connectedTaxi.Step.Valid&&join.Target==1&&connectedTaxi.Step.Next.Z>taxi.Z);
|
|
// Joining an airborne leg above a tower must still go around its platform.
|
|
SharedTrail tower;tower.LandingReady=true;tower.Landing={12,0,200};
|
|
tower.Points={{60,0,210},{12,0,210},tower.Landing};
|
|
auto platform=[](float x,float y){return Surface{std::hypot(x,y)<20?200.f:0.f,500,true,0.f};};
|
|
auto solid=[](Point const&a,Point const&b){for(unsigned i=0;i<=200;++i){auto p=Mix(a,b,i/200.f);if(std::hypot(p.X,p.Y)<20&&p.Z>=199.8f&&p.Z<=200.2f)return false;}return true;};
|
|
current={90,0,80};join={};index=0;
|
|
for(unsigned i=0;i<100&&Distance(current,tower.Landing)>.1f;++i){
|
|
auto step=FollowTrail(current,tower.Landing,cfg,tower,index,platform,solid,0,&join);
|
|
assert(step.Step.Valid&&!step.Waiting);current=step.Step.Next;
|
|
}
|
|
assert(Distance(current,tower.Landing)<.1f);
|
|
// No unvalidated shortcut through a tower or missing terrain.
|
|
join={};index=0;auto blocked=[](Point const&,Point const&){return false;};
|
|
assert(!FollowTrail({1000,0,0},trail.Landing,cfg,trail,index,flat,blocked,0,&join).Step.Valid);
|
|
auto missing=[](float,float){return Surface{};};join={};index=0;
|
|
assert(!FollowTrail({1000,0,0},trail.Landing,cfg,trail,index,missing,clear,0,&join).Step.Valid);
|
|
// A replacement publishes its verified destination immediately, even before
|
|
// any points are flown. Old readers can resolve to this generation.
|
|
auto old=std::make_shared<SharedTrail>();auto next=old->Replace({100,0,0});
|
|
assert(old->Aborted&&old->Replacement==next&&next->LandingReady&&next->Landing.X==100);
|
|
assert(next->Points.empty());next->Points={{25,0,20},{100,0,0}};next->Complete=true;
|
|
join={};index=0;auto step=FollowTrail({0,0,0},next->Landing,cfg,*next,index,flat,clear,0,&join);
|
|
assert(step.Step.Valid&&!step.Waiting);
|
|
std::cout<<"Shared route rejoin after taxi, bounded climb, clear corridor, blocked/missing terrain, replacement publication PASS\n";
|
|
}
|
|
'''
|
|
with tempfile.TemporaryDirectory(prefix="vcore-shared-rejoin-") as directory:
|
|
p=Path(directory);(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)
|