namespace XFEEDToolBox.Plugin;
internal static unsafe partial class Navigation
{
static JsonArray Vec(Vector value)=>Arr(value.x,value.y,value.z);
static double AmbientHeatUpper(Snapshot frame,FsdObservation fsd,HeatObservation heat)=>frame.rawFsdState==3?Math.Max(heat.idleUpper,heat.inputUpper-fsd.driveHeatBase):heat.idleUpper;
static double ThermalPeak(Snapshot frame,FsdObservation fsd,HeatObservation heat,double charge,double hold)
{
var now=GetTickCount64();if(!heat.valid||heat.entity!=frame.entity||heat.tick==0||now-heat.tick>300||!fsd.coolingActive||!fsd.driveParametersValid||!fsd.coolingConfigurationValid||charge<0||hold<0||charge+hold>120)return double.NaN;
var value=frame.heatPercent;var gain=(AmbientHeatUpper(frame,fsd,heat)+fsd.driveHeatBase+fsd.driveHeatRamp)*100/fsd.heatCapacity;var passive=fsd.coolingPassive*fsd.coolingScale*.99*100/fsd.heatCapacity;var maximum=fsd.coolingMaximum*fsd.coolingScale*.99*100/fsd.heatCapacity;
for(var remaining=charge+hold;remaining>1e-8;){var ratio=Math.Clamp((value*.01-fsd.coolingHeatLower)/(fsd.coolingHeatUpper-fsd.coolingHeatLower),0,1);var slope=gain-(passive+(maximum-passive)*ratio*ratio);if(slope<=0)break;var step=Math.Min(.05,remaining);value+=slope*step;remaining-=step;}return HeatHudPercent(value,frame.heatDisplayScale)+2;
}
static JsonObject GeometryDescription()
{
GeometryObservation value;lock(geometryLock)value=geometry;var frame=Current();var bodies=new JsonArray();
for(var i=0;i<value.bodyCount;i++){var body=value.bodies[i];bodies.Add((JsonNode)Obj(("bodyAddress",body.address.ToString()),("bodyKind",body.kind),("starType",body.starType),("exclusionRadius",body.exclusionRadius),("escapeRadius",body.escapeRadius),("centre",Vec(body.centre))));}
return Obj(("fresh",inGame&&frame.valid&&value.tick!=0&&GetTickCount64()-value.tick<=300&&value.entity==frame.entity&&value.worldAddress==frame.referenceWorld),
("worldAddress",value.worldAddress.ToString()),("bodyAddress",value.bodyAddress.ToString()),("bodyKind",value.bodyKind),("starType",value.starType),("exclusionRadius",value.exclusionRadius),("escapeRadius",value.escapeRadius),("position",Vec(value.position)),
("scoop",Obj(("verified",value.scoop.verified),("active",value.scoop.active),("fullRateRadius",value.scoop.fullRadius),("outerRadius",value.scoop.outerRadius),("maximumRate",value.scoop.maximumRate),("efficiency",value.scoop.efficiency),("fullFacingAngle",value.scoop.fullAngle),("zeroFacingAngle",value.scoop.zeroAngle),("speedWeight",value.scoop.speedWeight))),
("referenceFrameVerified",value.unifiedReference),("referenceBodyKind",value.referenceBodyKind),
("referenceOrigin",Obj(("verified",value.referenceOriginVerified),("worldAddress",value.worldAddress.ToString()),("entityId",value.entity.ToString()),
("observedAtUnixMilliseconds",value.sourceUtcMilliseconds),("position",Vec(value.referenceOrigin)))),
("unverifiedStationEnvelopes",value.unverifiedStationEnvelopes),("stationEnvelopeCoverageComplete",value.unverifiedStationEnvelopes==0),
("referenceFailureStage",referenceFailureStage),("referenceFailureBody",referenceFailureBody.ToString()),("referenceRadiusGetterRva",referenceRadiusGetter),
("right",Vec(value.right)),("up",Vec(value.up)),("forward",Vec(value.forward)),("nearbyBodies",bodies));
}
static JsonObject FsdDescription()
{
var value=CurrentFsd();var frame=Current();
return Obj(("fresh",inGame&&frame.valid&&value.tick!=0&&GetTickCount64()-value.tick<=300&&value.entity==frame.entity&&value.life==frame.life&&value.fsd==frame.fsd),
("entityId",value.entity.ToString()),("ownedCharging",fsdOwned),("generation",value.generation),("hookCalls",fsdEntryCalls),("selectedHookCalls",fsdSelectedCalls),("lastHookThread",fsdEntryThread),("lastHookAgeMilliseconds",fsdEntryAt!=0?GetTickCount64()-fsdEntryAt:0),("lastHookDt",fsdEntryDt),
("appliedGeneration",value.appliedGeneration),("inputPulses",value.pulses),("beginRejected",value.beginRejected),("state",value.state),("mode",value.mode),("stage",value.stage),("clock",value.clock),("duration",value.duration),("rate",value.rate),("elapsed",value.elapsed),
("driveParametersValid",value.driveParametersValid),("driveChargeSeconds",value.driveChargeSeconds),("driveHeatBase",value.driveHeatBase),("driveHeatRamp",value.driveHeatRamp),("heatCapacity",value.heatCapacity),("targetValid",value.targetValid),("targetAddress",value.targetAddress.ToString()),
("targetDirection",Vec(value.targetDirection)),("targetDistance",value.targetDistance),("throttle",value.throttle),("speedFraction",value.speedFraction),("throttleOverride",value.throttleOverride),("coolingConfigurationValid",value.coolingConfigurationValid),("coolingPassive",value.coolingPassive),("coolingMaximum",value.coolingMaximum),("coolingHeatLower",value.coolingHeatLower),("coolingHeatUpper",value.coolingHeatUpper));
}
static JsonObject HeatDescription(Snapshot frame)
{
var fsd=CurrentFsd();var heat=CurrentHeat();GeometryObservation body;lock(geometryLock)body=geometry;var hold=ChargingHoldSeconds(frame,fsd,body);var remaining=fsd.state==3?Math.Max(0.0,fsd.duration-fsd.clock):fsd.driveChargeSeconds;var peak=ThermalPeak(frame,fsd,heat,remaining,hold);
return Obj(("fresh",heat.valid&&heat.entity==frame.entity&&heat.tick!=0&&GetTickCount64()-heat.tick<=300),("inputUpper",heat.inputUpper),("idleInputUpper",AmbientHeatUpper(frame,fsd,heat)),("observedSimulationSeconds",heat.seconds),("buckets",heat.buckets),
("coolingActive",fsd.coolingActive),("coolingActual",fsd.coolingActual),("coolingScale",fsd.coolingScale),("forecastKnown",double.IsFinite(peak)),("fullChargeAndHoldPeak",double.IsFinite(peak)?JsonValue.Create(peak):null),("allowsCharging",double.IsFinite(peak)&&peak<=95),("forecastHoldSeconds",hold),("alignmentRateLowerDegreesPerSecond",4),
("evidence","Owned-ship AddHeat and active radiator curve; live remaining charge and alignment time; outward/tangent charging with delayed inward alignment and native 97-percent cancellation"));
}
static JsonObject Describe()
{
var frame=Current();var fresh=frame.valid&&GetTickCount64()-frame.tick<=300;
return Obj(("schema",1),("name","XFEEDToolBox.Navigation"),("version",Platform.PluginVersion),("processId",Platform.ProcessId),("gameSha256",GameHash),("initialized",initialized),("inGame",inGame),("owningThread",owningThread),("sampleStage",sampleStage),("sampleAttempts",sampleAttempts),("verified",true),("continuousPose",fresh),("continuousHeat",fresh),("continuousShipHealth",true),
("nativeSteering",true),("applicationSteeringAxes",true),("starEnvelopes",true),("referenceGeometry",true),("adaptiveFlightControl",true),("chargeAndCommitInterlock",true),("gameRoutePlanning",true),("gameRouteOptions",true),("gameRouteCancellation",true),("galaxyCatalog",true),("galaxyRegion",true),("galaxyRegionCoverage",true),("galaxyCancellation",true),("galaxyMinimumRadius",.05),("ready",Ready()),
("inputOwnershipObservation",InputOwnershipDescription()),("evidence","Build-pinned local-player identity; original cockpit hull/shield getters; bounded application input; expiring SC jump-commit interlock; original galaxy route calculation and cancellation"));
}
static JsonObject ShipHealth(Snapshot value)=>Obj(("verified",value.healthValid),("sequence",value.sequence),("observedAtUnixMilliseconds",value.utcMilliseconds),("entityId",value.entity.ToString()),("hullFraction",value.healthValid?JsonValue.Create(value.hullFraction):null),("shieldFraction",value.healthValid&&value.shieldKnown?JsonValue.Create(value.shieldFraction):null),("damageObserved",value.healthDamageObserved),("emergency",value.healthEmergency),("source","original-cockpit-player-target"));
internal static JsonNode Handle(JsonElement request)
{
var op=request.Str("op");
if(op=="describe"){
var result=Describe();result["version"]=Platform.PluginVersion;result["localTargets"]=true;result["localNavigationSchema"]=1;result["independentShipHealth"]=true;result["nativeRelog"]=sessionMenuReady;result["nativeSessionStatus"]=true;result["nativeDockingThrottle"]=true;result["localCooldownControls"]=true;result["serviceQuoteSnapshots"]=true;result["nativeDockingSourceZero"]=true;result["normalSpaceBoost"]=true;
// Application-owned expiring axes/FSD entry, independent of the
// separately configured original SCA, docking and SCO extensions.
result["localApplicationFlightControl"]=true;result["localApplicationFlightSchema"]=1;result["physicalInputSourceGuardSchema"]=1;
result["commerceClientProfileRefresh"]=true;result["formalCommodityTrading"]=true;result["marketWalletOptional"]=true;
result["galaxyAccountBookmarks"]=true;result["galaxyResolveAddress"]=true;result["galaxyAccountColonisation"]=true;result["galaxyFilterFacts"]=true;result["galaxyColonisationEligibility"]=true;result["galaxyAccountSocial"]=true;
result["galaxyPowerOptions"]=true;result["galaxyPowerActivityFacts"]=true;result["galaxyPowerOuterFacts"]=true;result["galaxyPowerTerritoryFacts"]=true;result["galaxyPowerStatusFacts"]=true;result["galaxyThargoid"]=true;result["galaxyCommunityGoals"]=true;result["galaxyFleet"]=true;result["galaxyMissions"]=true;result["galaxyCommodityOptions"]=true;result["galaxyCommodityFilterFacts"]=true;
result["galaxyCurrentTradeFlows"]=true;
result["galaxyBasicSystemFacts"]=true;
result["galaxyCellQueries"]=true;result["galaxyCatalogueProfile"]=true;result["galaxyPointOverrides"]=true;result["commerceDockedReadiness"]=true;result["cgCommodityBatches"]=true;result["nativeCommunityGoals"]=true;
result["nativeDockingInputMapper"]=dockingInputMapperReady;result["nativeDockingFixed075Trial"]=dockingInputMapperReady;
result["localCruiseControl"]=false;result["localDockingRequests"]=false;result["localNativeAssists"]=false;result["localDockingPaths"]=false;result["localPlanetaryApproach"]=false;return result;
}
if(op=="session.status")return SessionMenuDescription();
if(op is "session.begin" or "session.read" or "session.action" or "session.end")return SessionMenuRequest(op,request);
if(sessionMenuUntil>GetTickCount64()&&op is "apply" or "local.apply" or "local.action" or "local.select" or "route.plan" or "route.clear" or "commerce.trade" or "commerce.trade.batch" or "commerce.trade.formal" or "cg.join" or "station.services" or "calibrate.axes" or "calibrate.fsd" or "fsd")throw new InvalidOperationException("An explicit session workflow owns the game; stop it before automatic flight or commerce");
if(op=="fsd.describe")return FsdDescription();if(op=="geometry.describe")return GeometryDescription();var current=Current();var now=GetTickCount64();
if(op=="health.read"){
var h=CurrentHealth();if(!HealthFrameReady(healthFlowActive,h,now))throw new InvalidOperationException("Native main-ship health unavailable or stale");
return Obj(("sequence",h.sequence),("observedAtUnixMilliseconds",h.utcMilliseconds),("entityId",h.entity.ToString()),("localPlayerShipVerified",true),("shipHealth",ShipHealth(h)));
}
if(op=="read"){
if(!current.valid||now-current.tick>300)throw new InvalidOperationException("Native player telemetry unavailable or stale");GeometryObservation body;lock(geometryLock)body=geometry;var motion=ObserveMotion(current,body);
return Obj(("sequence",current.sequence),("observedAtUnixMilliseconds",current.utcMilliseconds),("entityId",current.entity.ToString()),("localPlayerShipVerified",true),("shipHealth",ShipHealth(current)),("position",Vec(current.position)),("right",Vec(current.right)),("up",Vec(current.up)),("forward",Vec(current.forward)),
("heatPercent",HeatHudPercent(current)),("heatHudPercent",HeatHudPercent(current)),("internalHeatPercent",current.heatPercent),("heatDisplayPercent",HeatHudPercent(current.heatDisplayPercent,current.heatDisplayScale)),("heatDisplayScale",current.heatDisplayScale),("heatNormalizationVerified",true),("speedMetresPerSecond",current.speed),("referenceWorldAddress",current.referenceWorld.ToString()),
("rawFsdState",current.rawFsdState),("rawFsdMode",current.rawFsdMode),("rawFsdStage",current.rawFsdStage),("rawChargeClock",current.rawChargeClock),("inGame",inGame),("playerOverride",overridden),("controlApplied",current.controlApplied),("inputOwnershipObservation",InputOwnershipDescription()),("adaptiveFlightControl",true),("angularVelocityVerified",current.angularVelocityValid),("angularVelocity",Vec(current.angularVelocityLocal)),("angularSpeedDegreesPerSecond",motion.rateValid?JsonValue.Create(motion.angularSpeed):null),("fsd",FsdDescription()),("geometry",GeometryDescription()),("thermal",HeatDescription(current)));
}
if(op=="local.read")return LocalFlightRead(current);
if(op=="input.physical.read")return PhysicalInputDescription(prepare:request.Bool("prepare"),includeNames:true);
if(op is "commerce.market.read" or "commerce.market.status" or "commerce.inventory" or "commerce.operation.status" or "commerce.docked.status")return CommerceReadCall(op,request,current);
if(op=="commerce.trade")return CommerceTradeCall(request,current);if(op=="station.services.inspect")return OriginalServiceReadCall(request,current);if(op=="station.services.inventory")return OriginalServiceInventoryCall(current);if(op=="station.services")return OriginalServiceMutationCall(request,current);
if(op=="commerce.trade.batch")return CommerceTradeCall(request,current,batch:true);
if(op=="commerce.trade.formal")return CommerceTradeCall(request,current,batch:true,formal:true);
if(op is "cg.read" or "cg.read.mine" or "cg.status" or "cg.operation.status" or "cg.join")return CommunityGoalCall(op,request,current);
if(op=="galaxy.account")return GalaxyAccountDescription(request);
if(op=="galaxy.colonisation")return GalaxyColonisationDescription(request);
if(op=="galaxy.social")return GalaxySocialDescription(request);
if(op=="galaxy.powers")return GalaxyPowerOptionsDescription(request);
if(op=="galaxy.thargoid")return GalaxyThargoidDescription(request);
if(op=="galaxy.communitygoals")return GalaxyCommunityGoalsDescription(request);
if(op=="galaxy.fleet")return GalaxyFleetDescription(request);
if(op=="galaxy.missions")return GalaxyMissionsDescription(request);
if(op=="galaxy.commodities")return GalaxyCommodityOptionsDescription(request);
if(op=="galaxy.tradeflows")return GalaxyCurrentTradeFlowsDescription(request);
if(op is "galaxy.facts" or "galaxy.facts.result" or "galaxy.facts.cancel")return GalaxyFilterFactsRequest(op,request);
if(op is "galaxy.catalogue.profile" or "galaxy.catalogue.profile.result" or "galaxy.catalogue.profile.cancel")return GalaxyCatalogueProfileRequest(op,request);
if(op is "galaxy.lookup" or "galaxy.suggest" or "galaxy.region" or "galaxy.cells" or "galaxy.result" or "galaxy.cancel" or "galaxy.resolve")return GalaxyCatalogueRequest(op,request);if(op=="galaxy.overview")return ExportGalaxyOverview(current);if(op is "galaxy.skybox.capture" or "galaxy.skybox.refresh" or "galaxy.skybox.status")return SkyCapture.Request(op);
lock(clientMutex){
var owner=request.Str("owner");if(owner.Length!=32||owner.Any(c=>!"0123456789abcdef".Contains(c)))throw new InvalidOperationException("An explicit controller owner is required");
if(op is "docking.validation.arm" or "docking.validation.status" or "docking.validation.cancel"){
if(sessionMenuUntil>now)throw new InvalidOperationException("Explicit session workflow owns the game");
return DockingFixtureRequest(op,request,owner,current);
}
if(op is "local.select" or "local.status" or "local.apply" or "local.axes.release" or "local.suspend" or "local.action" or "local.action.status")return LocalFlightRequest(op,request,owner,current);
if(op is "route.plan" or "route.clear" or "route.status"){
var destination=request.Required("destinationSystemAddress").GetUInt64();if(destination==0||destination>=0x80000000000000)throw new InvalidOperationException("A valid galaxy system address is required");RouteRequest wanted;lock(routeLock)wanted=routeRequest;
if(op is "route.plan" or "route.clear"){
if(!Enabled()||!inGame||!current.valid||now-current.tick>200||current.rawFsdState!=2||fsdOwned)throw new InvalidOperationException("Game route planning requires a fresh idle FSD");ulong flightExpiry;lock(leaseLock)flightExpiry=Math.Max(lease.expires,Math.Max(fsdLease.expires,targetLease.expires));
if(flightExpiry>now||wanted.expires>now&&routeConsumed!=wanted.generation)throw new InvalidOperationException("Stop active control before requesting a game route");var route=GameRoute(current,out var pilot);if(route==0)throw new InvalidOperationException("Original player galaxy route interface unavailable");if(op=="route.clear"&&Read<ulong>(route+0x148)!=destination)throw new InvalidOperationException("The game's route destination changed; preserving the new route");
var routeOptions=op=="route.plan"?ParseGameRouteOptions(request):null;
wanted=new(){expires=now+300,generation=++routeGeneration,entity=current.entity,destination=destination,life=current.life,fsd=current.fsd,inputRoot=current.inputRoot,pilotLife=pilot,route=route,clear=op=="route.clear",options=routeOptions};routeOwner=owner;lock(routeLock){routeRequest=wanted;routeObservation=default;}
}else if(routeOwner!=owner||wanted.destination!=destination||request.U64("generation")!=wanted.generation)throw new InvalidOperationException("No matching game route request");
RouteObservation observed;lock(routeLock)observed=routeObservation;routeReadUntil=now+1000;var fsd=CurrentFsd();var applied=routeApplied==wanted.generation;var fresh=observed.generation==wanted.generation&&observed.route==wanted.route&&now>=observed.tick&&now-observed.tick<=200;
return Obj(("generation",wanted.generation),("applied",applied),("pending",!applied&&routeFailed!=wanted.generation&&wanted.expires>now),("failed",routeFailed==wanted.generation||!applied&&wanted.expires<=now),("destinationAddress",(fresh?observed.destination:0).ToString()),("targetAddress",fsd.targetAddress.ToString()),("targetFresh",fsd.tick!=0&&now>=fsd.tick&&now-fsd.tick<=200&&fsd.targetValid),("topologyFresh",fresh&&observed.topologyValid),("waypointCount",observed.count),("routeFingerprint",observed.hash.ToString()));
}
if(op=="release"){
if(clientOwner!=owner&&clientOwner.Length!=0)throw new InvalidOperationException("The lease belongs to another controller");Expire();var pending=fsdOwned||GetTickCount64()-inputAppliedAt<50;if(!pending)clientOwner="";return Obj(("released",!pending),("cancellationPending",pending));
}
if(op is "target.select" or "target.status"){
var target=request.Required("targetSystemAddress").GetUInt64();if(target==0||!Enabled()||!inGame||!current.valid||now-current.tick>200)throw new InvalidOperationException("A fresh active ship and system target are required");ulong expiry;lock(leaseLock)expiry=Math.Max(lease.expires,Math.Max(fsdLease.expires,targetLease.expires));
if(op=="target.select"&&expiry<=now&&!fsdOwned)clientOwner="";if(clientOwner.Length!=0&&clientOwner!=owner)throw new InvalidOperationException("The flight lease belongs to another controller");TargetLease wanted;lock(leaseLock)wanted=targetLease;
if(op=="target.select"){
if(clientOwner.Length==0)overridden=false;var selected=CurrentFsd();var locked=selected.entity==current.entity&&selected.tick!=0&&now-selected.tick<=200&&selected.targetValid&&selected.targetAddress==target;
if(!CanAcknowledgeTarget(current.rawFsdState,locked,fsdOwned)||overridden)throw new InvalidOperationException("Select the destination before starting FSD charging");ClaimController(owner);wanted=new(){expires=now+300,generation=++targetGeneration,entity=current.entity,target=target,life=current.life,fsd=current.fsd,inputRoot=current.inputRoot};lock(leaseLock)targetLease=wanted;
}else if(clientOwner!=owner||wanted.target!=target)throw new InvalidOperationException("No matching target selection request");
var observed=CurrentFsd();var confirmed=targetConfirmed==wanted.generation&&observed.tick!=0&&now-observed.tick<=200&&observed.targetValid&&observed.targetAddress==target;return Obj(("selected",confirmed),("pending",!confirmed&&targetFailed!=wanted.generation&&wanted.expires>now),("targetAddress",observed.targetAddress.ToString()),("generation",wanted.generation));
}
if(op=="apply")return ApplyRequest(request,owner,current,now);
if(op=="calibrate.fsd")return CalibrateFsd(request,owner,current,now);
if(op=="calibrate.axes")return CalibrateAxes(request,owner,current,now);
throw new InvalidOperationException("Unsupported or unverified native navigation operation");
}
}
static void RequireRecoverableFlightHealth(in Snapshot current)
{
if(!current.healthValid)throw new InvalidOperationException("尚未读到飞船状态,请等待读取后重试。");
if(current.hullFraction<=0)throw new InvalidOperationException("飞船当前已无可用船体,无法启动驾驶。");
if(current.healthEmergency)throw new InvalidOperationException("飞船近期仍有新增受损;连续 3 秒无新增受损后可重新启动导航。");
}
static JsonObject ApplyRequest(JsonElement request,string owner,Snapshot current,ulong now)
{
RequireRecoverableFlightHealth(current);if(!Ready()||!inGame||!current.valid||now-current.tick>200||overridden)throw new InvalidOperationException("Native player telemetry unavailable or stale");
var reference=Reference(request.Required("sequence").GetUInt64(),current,now);var deadline=request.Required("expiresAtUnixMilliseconds").GetUInt64();var utc=UtcMilliseconds();if(deadline<=utc||deadline>utc+300)throw new InvalidOperationException("Navigation reference frame expired; read fresh telemetry and retry");
var fsd=CurrentFsd();var heat=CurrentHeat();GeometryObservation body;lock(geometryLock)body=geometry;var target=request.Required("targetSystemAddress").GetUInt64();
if(!fsd.targetValid||fsd.targetAddress!=target||fsd.entity!=current.entity||now-fsd.tick>200||!body.unifiedReference||body.entity!=current.entity||now-body.tick>200||body.bodyKind!=1||body.worldAddress!=current.referenceWorld)throw new InvalidOperationException("Native target or primary-star envelope changed");if(clientOwner.Length!=0&&clientOwner!=owner)throw new InvalidOperationException("Another controller owns the flight lease");
var decision=request.Required("decision");var begin=decision.Required("beginCharging").GetBoolean();var cancel=decision.Required("cancelCharging").GetBoolean();var permit=decision.Required("permitJump").GetBoolean();var supercruiseEntry=decision.Bool("enterSupercruise");var direction=decision.Required("direction");if(direction.ValueKind!=JsonValueKind.Object)throw new InvalidOperationException("A finite native flight direction is required");
var wanted=new Vector(direction.Required("x").GetDouble(),direction.Required("y").GetDouble(),direction.Required("z").GetDouble());var length=Math.Sqrt(Dot(wanted,wanted));if(!Finite(wanted)||length<.9||length>1.1)throw new InvalidOperationException("Invalid native flight direction");wanted=new(wanted.x/length,wanted.y/length,wanted.z/length);
var position=body.unifiedReference?body.position:current.position;var forward=body.unifiedReference?body.forward:current.forward;var right=body.unifiedReference?body.right:current.right;var up=body.unifiedReference?body.up:current.up;var motion=ObserveMotion(current,body);var x=Dot(wanted,right);var y=Dot(wanted,up);var z=Dot(wanted,forward);
var error=Math.Acos(Math.Clamp(z,-1,1))*180/Math.PI;var yaw=Math.Atan2(x,z)*180/Math.PI;var pitch=-Math.Atan2(y,Math.Sqrt(x*x+z*z))*180/Math.PI;var throttle=decision.Required("throttle").GetSingle();if(!float.IsFinite(throttle)||throttle<0||throttle>1)throw new InvalidOperationException("Invalid native throttle");
var radius=Math.Sqrt(Dot(position,position));var targetDot=Dot(position,fsd.targetDirection);var closestSquared=Dot(position,position)-(targetDot<0?targetDot*targetDot:0);var clear=closestSquared>body.exclusionRadius*body.exclusionRadius*1.1025;var escapeClear=radius>body.escapeRadius*1.2;var escape=position;var closestRatio=radius/body.exclusionRadius;
for(var i=0;i<body.bodyCount;i++){var nearby=body.bodies[i];var delta=Subtract(position,nearby.centre);var square=Dot(delta,delta);var projection=Dot(delta,fsd.targetDirection);if(square-(projection<0?projection*projection:0)<=nearby.exclusionRadius*nearby.exclusionRadius*1.1025)clear=false;if(square<=nearby.escapeRadius*nearby.escapeRadius*1.44)escapeClear=false;var ratio=Math.Sqrt(square)/nearby.exclusionRadius;if(ratio<closestRatio){escape=delta;closestRatio=ratio;}}
var remaining=fsd.state==3?Math.Max(0.0,fsd.duration-fsd.clock):supercruiseEntry?5.0:fsd.driveChargeSeconds;var prediction=ThermalPeak(current,fsd,heat,remaining,supercruiseEntry?.5:ChargingHoldSeconds(current,fsd,body));
if((begin||permit)&&(!double.IsFinite(prediction)||prediction>(supercruiseEntry?99:95)||HeatHudPercent(current)>=97||!supercruiseEntry&&!clear||supercruiseEntry&&!escapeClear))throw new InvalidOperationException("Native thermal or stellar clearance gate refused FSD charging");
var nearPrimary=radius<body.exclusionRadius*3&¤t.speed>1000;if(begin&&!supercruiseEntry&&nearPrimary&&Dot(position,forward)<0)throw new InvalidOperationException("Native departure must be outward before FSD charging");if(begin&&supercruiseEntry&&(current.speedFraction<.8||Dot(escape,forward)/Math.Sqrt(Dot(escape,escape))<.99))throw new InvalidOperationException("Supercruise entry requires verified outward full-speed departure");
var aim=Math.Acos(Math.Clamp(Dot(forward,fsd.targetDirection),-1,1))*180/Math.PI;if(permit&&(!fsdOwned||fsd.state!=3||fsd.clock<fsd.duration||aim>1||throttle!=1))throw new InvalidOperationException("Native jump commit requires full charge, alignment and full throttle");
var departing=!supercruiseEntry&&(begin||fsdOwned)&&clear&&(!nearPrimary||Dot(position,forward)>=0);if(!supercruiseEntry)throttle=ChargingThrottle(throttle,begin||fsdOwned,Dot(position,forward)<0,nearPrimary,permit);
if(!supercruiseEntry&&!departing&&!permit&&throttle>0)throttle=AdaptiveCruiseThrottle(throttle,current.speed,radius,body.exclusionRadius,Dot(position,forward)/radius,error,motion.previousThrottle,current.speedFraction);
if(!supercruiseEntry&&!permit&&!departing)for(var i=0;i<body.bodyCount;i++){var nearby=body.bodies[i];var delta=Subtract(position,nearby.centre);var distance=Math.Sqrt(Dot(delta,delta));if(distance>=nearby.exclusionRadius*3)continue;var radialCosine=Dot(delta,forward)/distance;if((begin||fsdOwned)&&radialCosine<0)throttle=0;else if(throttle>0)throttle=AdaptiveCruiseThrottle(throttle,current.speed,distance,nearby.exclusionRadius,radialCosine,error,motion.previousThrottle,current.speedFraction);}
float[] steering;if(request.TryGetProperty("steeringAxes",out var application)&&application.ValueKind!=JsonValueKind.Null)steering=ApplicationSteeringAxes(application);else{var legacy=SmoothSteering(yaw,pitch,motion,now);steering=[legacy[0],legacy[1],0];}
ClaimController(owner);RequirePhysicalInputSources(current,now);var next=new Lease{expires=Math.Min(now+deadline-utc,reference.tick+300),sequence=reference.sequence,inputRoot=current.inputRoot,throttle=throttle,localKey=-1,epoch=controllerEpoch,interlock=!supercruiseEntry,permitJump=permit,target=target,world=body.worldAddress};next.axes[3]=steering[0];next.axes[4]=steering[1];next.axes[5]=steering[2];lock(motionLock)motionObservation.previousThrottle=throttle;
lock(leaseLock){lease=next;if(cancel&&fsdOwned){fsdLease.expires=next.expires;fsdLease.command=2;}else if(begin&&fsd.state==2&&!fsdOwned)fsdLease=new(){expires=next.expires,sequence=reference.sequence,generation=NextFsdGeneration(),entity=current.entity,fsd=current.fsd,inputRoot=current.inputRoot,life=current.life,command=supercruiseEntry?1u:3u,heatCeiling=97,target=target,supercruiseEntry=supercruiseEntry};else if(fsdOwned){fsdLease.expires=next.expires;fsdLease.sequence=reference.sequence;}}
return Obj(("accepted",true),("throttleCommand",throttle),("steering",Arr(next.axes[3],next.axes[4],next.axes[5])),("commitGateOpen",permit),("predictedPeak",double.IsFinite(prediction)?JsonValue.Create(prediction):null));
}
static JsonObject CalibrateFsd(JsonElement request,string owner,Snapshot current,ulong now)
{
RequireRecoverableFlightHealth(current);var expected=request.Required("sequence").GetUInt64();var ttl=request.Required("ttlMilliseconds").GetInt32();var desired=request.Required("desired").GetString();
if(desired is not ("beginSupercruise" or "beginHyperspace" or "keep" or "cancel"))throw new InvalidOperationException("Unsupported original FSD input for calibration");if(!Enabled()||!inGame||!current.valid||now-current.tick>200||ttl<1||ttl>300)throw new InvalidOperationException("FSD calibration frame or deadline is invalid");
var reference=Reference(expected,current,now);var expires=Math.Min(now+(ulong)ttl,reference.tick+300);var ceiling=(float)request.Num("heatCeilingPercent",65);if(!float.IsFinite(ceiling)||ceiling<60||ceiling>90)throw new InvalidOperationException("FSD calibration heat ceiling must be within 60 to 90 percent");if(desired!="cancel"&&HeatHudPercent(current)>=ceiling)throw new InvalidOperationException("FSD calibration heat limit exceeded; cancel the owned charge");
if(desired=="beginSupercruise"&&(current.speed>=1||current.rawFsdState!=2||fsdOwned||overridden))throw new InvalidOperationException("Supercruise calibration requires a stationary idle ship without player override");var requestedTarget=request.U64("targetSystemAddress");if(desired=="beginHyperspace"){var observed=CurrentFsd();if(requestedTarget==0||!observed.targetValid||observed.targetAddress!=requestedTarget||observed.tick==0||now-observed.tick>200||current.rawFsdState!=2||fsdOwned||overridden)throw new InvalidOperationException("Hyperspace calibration requires a matching locked system target and idle FSD");}
ulong expiry;FsdLease next;lock(leaseLock){expiry=Math.Max(lease.expires,fsdLease.expires);next=fsdLease;}if(expiry<=now&&!fsdOwned)clientOwner="";if(clientOwner.Length!=0&&clientOwner!=owner)throw new InvalidOperationException("Another controller owns the flight lease");if(desired=="keep"&&(clientOwner!=owner||next.fsd!=current.fsd||next.entity!=current.entity))throw new InvalidOperationException("No matching FSD lease to renew");
ClaimController(owner);if(desired!="cancel")RequirePhysicalInputSources(current,now);if(desired!="keep")next=new(){expires=expires,sequence=expected,generation=NextFsdGeneration(),entity=current.entity,fsd=current.fsd,inputRoot=current.inputRoot,life=current.life,command=desired=="beginSupercruise"?1u:desired=="beginHyperspace"?3u:2u,heatCeiling=ceiling,target=desired=="beginHyperspace"?requestedTarget:0};else{next.expires=expires;next.sequence=expected;}lock(leaseLock)fsdLease=next;return Obj(("accepted",true),("generation",next.generation),("expiresInMilliseconds",ttl));
}
static JsonObject CalibrateAxes(JsonElement request,string owner,Snapshot current,ulong now)
{
RequireRecoverableFlightHealth(current);var expected=request.Required("sequence").GetUInt64();var ttl=request.Required("ttlMilliseconds").GetInt32();var rawAxes=request.Required("axes");if(rawAxes.ValueKind!=JsonValueKind.Array||rawAxes.GetArrayLength()!=6)throw new InvalidOperationException("Calibration axes, throttle or deadline exceed their bound");Float6 axes=default;for(var i=0;i<6;i++)axes[i]=rawAxes[i].GetSingle();var throttle=(float)request.Num("throttle",-1);
if(!Enabled()||!inGame||!current.valid||now-current.tick>200)throw new InvalidOperationException("Calibration telemetry is stale or not eligible");var reference=Reference(expected,current,now);var invalid=false;for(var i=0;i<6;i++)invalid|=!float.IsFinite(axes[i])||Math.Abs(axes[i])>.6f;
if(ttl<1||ttl>300||!float.IsFinite(throttle)||throttle!=-1&&(throttle<0||throttle>1)||invalid)throw new InvalidOperationException("Calibration axes, throttle or deadline exceed their bound");ulong expiry;lock(leaseLock)expiry=Math.Max(lease.expires,fsdLease.expires);if(expiry<=now&&!fsdOwned)clientOwner="";if(clientOwner.Length!=0&&clientOwner!=owner)throw new InvalidOperationException("Another controller owns the input lease");if(clientOwner.Length==0)overridden=false;
ClaimController(owner);RequirePhysicalInputSources(current,now);var next=new Lease{expires=Math.Min(now+(ulong)ttl,reference.tick+300),sequence=expected,inputRoot=current.inputRoot,axes=axes,throttle=throttle,epoch=controllerEpoch,localKey=-1};lock(leaseLock)lease=next;return Obj(("accepted",true),("expiresInMilliseconds",ttl));
}
}
namespace XFEEDToolBox.Plugin;
internal static unsafe partial class Navigation
{
static JsonArray Vec(Vector value)=>Arr(value.x,value.y,value.z);
static double AmbientHeatUpper(Snapshot frame,FsdObservation fsd,HeatObservation heat)=>frame.rawFsdState==3?Math.Max(heat.idleUpper,heat.inputUpper-fsd.driveHeatBase):heat.idleUpper;
static double ThermalPeak(Snapshot frame,FsdObservation fsd,HeatObservation heat,double charge,double hold)
{
var now=GetTickCount64();if(!heat.valid||heat.entity!=frame.entity||heat.tick==0||now-heat.tick>300||!fsd.coolingActive||!fsd.driveParametersValid||!fsd.coolingConfigurationValid||charge<0||hold<0||charge+hold>120)return double.NaN;
var value=frame.heatPercent;var gain=(AmbientHeatUpper(frame,fsd,heat)+fsd.driveHeatBase+fsd.driveHeatRamp)*100/fsd.heatCapacity;var passive=fsd.coolingPassive*fsd.coolingScale*.99*100/fsd.heatCapacity;var maximum=fsd.coolingMaximum*fsd.coolingScale*.99*100/fsd.heatCapacity;
for(var remaining=charge+hold;remaining>1e-8;){var ratio=Math.Clamp((value*.01-fsd.coolingHeatLower)/(fsd.coolingHeatUpper-fsd.coolingHeatLower),0,1);var slope=gain-(passive+(maximum-passive)*ratio*ratio);if(slope<=0)break;var step=Math.Min(.05,remaining);value+=slope*step;remaining-=step;}return HeatHudPercent(value,frame.heatDisplayScale)+2;
}
static JsonObject GeometryDescription()
{
GeometryObservation value;lock(geometryLock)value=geometry;var frame=Current();var bodies=new JsonArray();
for(var i=0;i<value.bodyCount;i++){var body=value.bodies[i];bodies.Add((JsonNode)Obj(("bodyAddress",body.address.ToString()),("bodyKind",body.kind),("starType",body.starType),("exclusionRadius",body.exclusionRadius),("escapeRadius",body.escapeRadius),("centre",Vec(body.centre))));}
return Obj(("fresh",inGame&&frame.valid&&value.tick!=0&&GetTickCount64()-value.tick<=300&&value.entity==frame.entity&&value.worldAddress==frame.referenceWorld),
("worldAddress",value.worldAddress.ToString()),("bodyAddress",value.bodyAddress.ToString()),("bodyKind",value.bodyKind),("starType",value.starType),("exclusionRadius",value.exclusionRadius),("escapeRadius",value.escapeRadius),("position",Vec(value.position)),
("scoop",Obj(("verified",value.scoop.verified),("active",value.scoop.active),("fullRateRadius",value.scoop.fullRadius),("outerRadius",value.scoop.outerRadius),("maximumRate",value.scoop.maximumRate),("efficiency",value.scoop.efficiency),("fullFacingAngle",value.scoop.fullAngle),("zeroFacingAngle",value.scoop.zeroAngle),("speedWeight",value.scoop.speedWeight))),
("referenceFrameVerified",value.unifiedReference),("referenceBodyKind",value.referenceBodyKind),
("referenceOrigin",Obj(("verified",value.referenceOriginVerified),("worldAddress",value.worldAddress.ToString()),("entityId",value.entity.ToString()),
("observedAtUnixMilliseconds",value.sourceUtcMilliseconds),("position",Vec(value.referenceOrigin)))),
("unverifiedStationEnvelopes",value.unverifiedStationEnvelopes),("stationEnvelopeCoverageComplete",value.unverifiedStationEnvelopes==0),
("referenceFailureStage",referenceFailureStage),("referenceFailureBody",referenceFailureBody.ToString()),("referenceRadiusGetterRva",referenceRadiusGetter),
("right",Vec(value.right)),("up",Vec(value.up)),("forward",Vec(value.forward)),("nearbyBodies",bodies));
}
static JsonObject FsdDescription()
{
var value=CurrentFsd();var frame=Current();
return Obj(("fresh",inGame&&frame.valid&&value.tick!=0&&GetTickCount64()-value.tick<=300&&value.entity==frame.entity&&value.life==frame.life&&value.fsd==frame.fsd),
("entityId",value.entity.ToString()),("ownedCharging",fsdOwned),("generation",value.generation),("hookCalls",fsdEntryCalls),("selectedHookCalls",fsdSelectedCalls),("lastHookThread",fsdEntryThread),("lastHookAgeMilliseconds",fsdEntryAt!=0?GetTickCount64()-fsdEntryAt:0),("lastHookDt",fsdEntryDt),
("appliedGeneration",value.appliedGeneration),("inputPulses",value.pulses),("beginRejected",value.beginRejected),("state",value.state),("mode",value.mode),("stage",value.stage),("clock",value.clock),("duration",value.duration),("rate",value.rate),("elapsed",value.elapsed),
("driveParametersValid",value.driveParametersValid),("driveChargeSeconds",value.driveChargeSeconds),("driveHeatBase",value.driveHeatBase),("driveHeatRamp",value.driveHeatRamp),("heatCapacity",value.heatCapacity),("targetValid",value.targetValid),("targetAddress",value.targetAddress.ToString()),
("targetDirection",Vec(value.targetDirection)),("targetDistance",value.targetDistance),("throttle",value.throttle),("speedFraction",value.speedFraction),("throttleOverride",value.throttleOverride),("coolingConfigurationValid",value.coolingConfigurationValid),("coolingPassive",value.coolingPassive),("coolingMaximum",value.coolingMaximum),("coolingHeatLower",value.coolingHeatLower),("coolingHeatUpper",value.coolingHeatUpper));
}
static JsonObject HeatDescription(Snapshot frame)
{
var fsd=CurrentFsd();var heat=CurrentHeat();GeometryObservation body;lock(geometryLock)body=geometry;var hold=ChargingHoldSeconds(frame,fsd,body);var remaining=fsd.state==3?Math.Max(0.0,fsd.duration-fsd.clock):fsd.driveChargeSeconds;var peak=ThermalPeak(frame,fsd,heat,remaining,hold);
return Obj(("fresh",heat.valid&&heat.entity==frame.entity&&heat.tick!=0&&GetTickCount64()-heat.tick<=300),("inputUpper",heat.inputUpper),("idleInputUpper",AmbientHeatUpper(frame,fsd,heat)),("observedSimulationSeconds",heat.seconds),("buckets",heat.buckets),
("coolingActive",fsd.coolingActive),("coolingActual",fsd.coolingActual),("coolingScale",fsd.coolingScale),("forecastKnown",double.IsFinite(peak)),("fullChargeAndHoldPeak",double.IsFinite(peak)?JsonValue.Create(peak):null),("allowsCharging",double.IsFinite(peak)&&peak<=95),("forecastHoldSeconds",hold),("alignmentRateLowerDegreesPerSecond",4),
("evidence","Owned-ship AddHeat and active radiator curve; live remaining charge and alignment time; outward/tangent charging with delayed inward alignment and native 97-percent cancellation"));
}
static JsonObject Describe()
{
var frame=Current();var fresh=frame.valid&&GetTickCount64()-frame.tick<=300;
return Obj(("schema",1),("name","XFEEDToolBox.Navigation"),("version",Platform.PluginVersion),("processId",Platform.ProcessId),("gameSha256",GameHash),("initialized",initialized),("inGame",inGame),("owningThread",owningThread),("sampleStage",sampleStage),("sampleAttempts",sampleAttempts),("verified",true),("continuousPose",fresh),("continuousHeat",fresh),("continuousShipHealth",true),
("nativeSteering",true),("applicationSteeringAxes",true),("starEnvelopes",true),("referenceGeometry",true),("adaptiveFlightControl",true),("chargeAndCommitInterlock",true),("gameRoutePlanning",true),("gameRouteOptions",true),("gameRouteCancellation",true),("galaxyCatalog",true),("galaxyRegion",true),("galaxyRegionCoverage",true),("galaxyCancellation",true),("galaxyMinimumRadius",.05),("ready",Ready()),
("inputOwnershipObservation",InputOwnershipDescription()),("evidence","Build-pinned local-player identity; original cockpit hull/shield getters; bounded application input; expiring SC jump-commit interlock; original galaxy route calculation and cancellation"));
}
static JsonObject ShipHealth(Snapshot value)=>Obj(("verified",value.healthValid),("sequence",value.sequence),("observedAtUnixMilliseconds",value.utcMilliseconds),("entityId",value.entity.ToString()),("hullFraction",value.healthValid?JsonValue.Create(value.hullFraction):null),("shieldFraction",value.healthValid&&value.shieldKnown?JsonValue.Create(value.shieldFraction):null),("damageObserved",value.healthDamageObserved),("emergency",value.healthEmergency),("source","original-cockpit-player-target"));
internal static JsonNode Handle(JsonElement request)
{
var op=request.Str("op");
if(op=="describe"){
var result=Describe();result["version"]=Platform.PluginVersion;result["localTargets"]=true;result["localNavigationSchema"]=1;result["independentShipHealth"]=true;result["nativeRelog"]=sessionMenuReady;result["nativeSessionStatus"]=true;result["nativeDockingThrottle"]=true;result["localCooldownControls"]=true;result["serviceQuoteSnapshots"]=true;result["nativeDockingSourceZero"]=true;result["normalSpaceBoost"]=true;
// Application-owned expiring axes/FSD entry, independent of the
// separately configured original SCA, docking and SCO extensions.
result["localApplicationFlightControl"]=true;result["localApplicationFlightSchema"]=1;result["physicalInputSourceGuardSchema"]=1;
result["commerceClientProfileRefresh"]=true;result["formalCommodityTrading"]=true;result["marketWalletOptional"]=true;
result["galaxyAccountBookmarks"]=true;result["galaxyResolveAddress"]=true;result["galaxyAccountColonisation"]=true;result["galaxyFilterFacts"]=true;result["galaxyColonisationEligibility"]=true;result["galaxyAccountSocial"]=true;
result["galaxyPowerOptions"]=true;result["galaxyPowerActivityFacts"]=true;result["galaxyPowerOuterFacts"]=true;result["galaxyPowerTerritoryFacts"]=true;result["galaxyPowerStatusFacts"]=true;result["galaxyThargoid"]=true;result["galaxyCommunityGoals"]=true;result["galaxyFleet"]=true;result["galaxyMissions"]=true;result["galaxyCommodityOptions"]=true;result["galaxyCommodityFilterFacts"]=true;
result["galaxyCurrentTradeFlows"]=true;
result["galaxyBasicSystemFacts"]=true;
result["galaxyCellQueries"]=true;result["galaxyCatalogueProfile"]=true;result["galaxyPointOverrides"]=true;result["commerceDockedReadiness"]=true;result["cgCommodityBatches"]=true;result["nativeCommunityGoals"]=true;
result["nativeDockingInputMapper"]=dockingInputMapperReady;result["nativeDockingFixed075Trial"]=dockingInputMapperReady;
result["localCruiseControl"]=false;result["localDockingRequests"]=false;result["localNativeAssists"]=false;result["localDockingPaths"]=false;result["localPlanetaryApproach"]=false;return result;
}
if(op=="session.status")return SessionMenuDescription();
if(op is "session.begin" or "session.read" or "session.action" or "session.end")return SessionMenuRequest(op,request);
if(sessionMenuUntil>GetTickCount64()&&op is "apply" or "local.apply" or "local.action" or "local.select" or "route.plan" or "route.clear" or "commerce.trade" or "commerce.trade.batch" or "commerce.trade.formal" or "cg.join" or "station.services" or "calibrate.axes" or "calibrate.fsd" or "fsd")throw new InvalidOperationException("An explicit session workflow owns the game; stop it before automatic flight or commerce");
if(op=="fsd.describe")return FsdDescription();if(op=="geometry.describe")return GeometryDescription();var current=Current();var now=GetTickCount64();
if(op=="health.read"){
var h=CurrentHealth();if(!HealthFrameReady(healthFlowActive,h,now))throw new InvalidOperationException("Native main-ship health unavailable or stale");
return Obj(("sequence",h.sequence),("observedAtUnixMilliseconds",h.utcMilliseconds),("entityId",h.entity.ToString()),("localPlayerShipVerified",true),("shipHealth",ShipHealth(h)));
}
if(op=="read"){
if(!current.valid||now-current.tick>300)throw new InvalidOperationException("Native player telemetry unavailable or stale");GeometryObservation body;lock(geometryLock)body=geometry;var motion=ObserveMotion(current,body);
return Obj(("sequence",current.sequence),("observedAtUnixMilliseconds",current.utcMilliseconds),("entityId",current.entity.ToString()),("localPlayerShipVerified",true),("shipHealth",ShipHealth(current)),("position",Vec(current.position)),("right",Vec(current.right)),("up",Vec(current.up)),("forward",Vec(current.forward)),
("heatPercent",HeatHudPercent(current)),("heatHudPercent",HeatHudPercent(current)),("internalHeatPercent",current.heatPercent),("heatDisplayPercent",HeatHudPercent(current.heatDisplayPercent,current.heatDisplayScale)),("heatDisplayScale",current.heatDisplayScale),("heatNormalizationVerified",true),("speedMetresPerSecond",current.speed),("referenceWorldAddress",current.referenceWorld.ToString()),
("rawFsdState",current.rawFsdState),("rawFsdMode",current.rawFsdMode),("rawFsdStage",current.rawFsdStage),("rawChargeClock",current.rawChargeClock),("inGame",inGame),("playerOverride",overridden),("controlApplied",current.controlApplied),("inputOwnershipObservation",InputOwnershipDescription()),("adaptiveFlightControl",true),("angularVelocityVerified",current.angularVelocityValid),("angularVelocity",Vec(current.angularVelocityLocal)),("angularSpeedDegreesPerSecond",motion.rateValid?JsonValue.Create(motion.angularSpeed):null),("fsd",FsdDescription()),("geometry",GeometryDescription()),("thermal",HeatDescription(current)));
}
if(op=="local.read")return LocalFlightRead(current);
if(op=="input.physical.read")return PhysicalInputDescription(prepare:request.Bool("prepare"),includeNames:true);
if(op is "commerce.market.read" or "commerce.market.status" or "commerce.inventory" or "commerce.operation.status" or "commerce.docked.status")return CommerceReadCall(op,request,current);
if(op=="commerce.trade")return CommerceTradeCall(request,current);if(op=="station.services.inspect")return OriginalServiceReadCall(request,current);if(op=="station.services.inventory")return OriginalServiceInventoryCall(current);if(op=="station.services")return OriginalServiceMutationCall(request,current);
if(op=="commerce.trade.batch")return CommerceTradeCall(request,current,batch:true);
if(op=="commerce.trade.formal")return CommerceTradeCall(request,current,batch:true,formal:true);
if(op is "cg.read" or "cg.read.mine" or "cg.status" or "cg.operation.status" or "cg.join")return CommunityGoalCall(op,request,current);
if(op=="galaxy.account")return GalaxyAccountDescription(request);
if(op=="galaxy.colonisation")return GalaxyColonisationDescription(request);
if(op=="galaxy.social")return GalaxySocialDescription(request);
if(op=="galaxy.powers")return GalaxyPowerOptionsDescription(request);
if(op=="galaxy.thargoid")return GalaxyThargoidDescription(request);
if(op=="galaxy.communitygoals")return GalaxyCommunityGoalsDescription(request);
if(op=="galaxy.fleet")return GalaxyFleetDescription(request);
if(op=="galaxy.missions")return GalaxyMissionsDescription(request);
if(op=="galaxy.commodities")return GalaxyCommodityOptionsDescription(request);
if(op=="galaxy.tradeflows")return GalaxyCurrentTradeFlowsDescription(request);
if(op is "galaxy.facts" or "galaxy.facts.result" or "galaxy.facts.cancel")return GalaxyFilterFactsRequest(op,request);
if(op is "galaxy.catalogue.profile" or "galaxy.catalogue.profile.result" or "galaxy.catalogue.profile.cancel")return GalaxyCatalogueProfileRequest(op,request);
if(op is "galaxy.lookup" or "galaxy.suggest" or "galaxy.region" or "galaxy.cells" or "galaxy.result" or "galaxy.cancel" or "galaxy.resolve")return GalaxyCatalogueRequest(op,request);if(op=="galaxy.overview")return ExportGalaxyOverview(current);if(op is "galaxy.skybox.capture" or "galaxy.skybox.refresh" or "galaxy.skybox.status")return SkyCapture.Request(op);
lock(clientMutex){
var owner=request.Str("owner");if(owner.Length!=32||owner.Any(c=>!"0123456789abcdef".Contains(c)))throw new InvalidOperationException("An explicit controller owner is required");
if(op is "docking.validation.arm" or "docking.validation.status" or "docking.validation.cancel"){
if(sessionMenuUntil>now)throw new InvalidOperationException("Explicit session workflow owns the game");
return DockingFixtureRequest(op,request,owner,current);
}
if(op is "local.select" or "local.status" or "local.apply" or "local.axes.release" or "local.suspend" or "local.action" or "local.action.status")return LocalFlightRequest(op,request,owner,current);
if(op is "route.plan" or "route.clear" or "route.status"){
var destination=request.Required("destinationSystemAddress").GetUInt64();if(destination==0||destination>=0x80000000000000)throw new InvalidOperationException("A valid galaxy system address is required");RouteRequest wanted;lock(routeLock)wanted=routeRequest;
if(op is "route.plan" or "route.clear"){
if(!Enabled()||!inGame||!current.valid||now-current.tick>200||current.rawFsdState!=2||fsdOwned)throw new InvalidOperationException("Game route planning requires a fresh idle FSD");ulong flightExpiry;lock(leaseLock)flightExpiry=Math.Max(lease.expires,Math.Max(fsdLease.expires,targetLease.expires));
if(flightExpiry>now||wanted.expires>now&&routeConsumed!=wanted.generation)throw new InvalidOperationException("Stop active control before requesting a game route");var route=GameRoute(current,out var pilot);if(route==0)throw new InvalidOperationException("Original player galaxy route interface unavailable");if(op=="route.clear"&&Read<ulong>(route+0x148)!=destination)throw new InvalidOperationException("The game's route destination changed; preserving the new route");
var routeOptions=op=="route.plan"?ParseGameRouteOptions(request):null;
wanted=new(){expires=now+300,generation=++routeGeneration,entity=current.entity,destination=destination,life=current.life,fsd=current.fsd,inputRoot=current.inputRoot,pilotLife=pilot,route=route,clear=op=="route.clear",options=routeOptions};routeOwner=owner;lock(routeLock){routeRequest=wanted;routeObservation=default;}
}else if(routeOwner!=owner||wanted.destination!=destination||request.U64("generation")!=wanted.generation)throw new InvalidOperationException("No matching game route request");
RouteObservation observed;lock(routeLock)observed=routeObservation;routeReadUntil=now+1000;var fsd=CurrentFsd();var applied=routeApplied==wanted.generation;var fresh=observed.generation==wanted.generation&&observed.route==wanted.route&&now>=observed.tick&&now-observed.tick<=200;
return Obj(("generation",wanted.generation),("applied",applied),("pending",!applied&&routeFailed!=wanted.generation&&wanted.expires>now),("failed",routeFailed==wanted.generation||!applied&&wanted.expires<=now),("destinationAddress",(fresh?observed.destination:0).ToString()),("targetAddress",fsd.targetAddress.ToString()),("targetFresh",fsd.tick!=0&&now>=fsd.tick&&now-fsd.tick<=200&&fsd.targetValid),("topologyFresh",fresh&&observed.topologyValid),("waypointCount",observed.count),("routeFingerprint",observed.hash.ToString()));
}
if(op=="release"){
if(clientOwner!=owner&&clientOwner.Length!=0)throw new InvalidOperationException("The lease belongs to another controller");Expire();var pending=fsdOwned||GetTickCount64()-inputAppliedAt<50;if(!pending)clientOwner="";return Obj(("released",!pending),("cancellationPending",pending));
}
if(op is "target.select" or "target.status"){
var target=request.Required("targetSystemAddress").GetUInt64();if(target==0||!Enabled()||!inGame||!current.valid||now-current.tick>200)throw new InvalidOperationException("A fresh active ship and system target are required");ulong expiry;lock(leaseLock)expiry=Math.Max(lease.expires,Math.Max(fsdLease.expires,targetLease.expires));
if(op=="target.select"&&expiry<=now&&!fsdOwned)clientOwner="";if(clientOwner.Length!=0&&clientOwner!=owner)throw new InvalidOperationException("The flight lease belongs to another controller");TargetLease wanted;lock(leaseLock)wanted=targetLease;
if(op=="target.select"){
if(clientOwner.Length==0)overridden=false;var selected=CurrentFsd();var locked=selected.entity==current.entity&&selected.tick!=0&&now-selected.tick<=200&&selected.targetValid&&selected.targetAddress==target;
if(!CanAcknowledgeTarget(current.rawFsdState,locked,fsdOwned)||overridden)throw new InvalidOperationException("Select the destination before starting FSD charging");ClaimController(owner);wanted=new(){expires=now+300,generation=++targetGeneration,entity=current.entity,target=target,life=current.life,fsd=current.fsd,inputRoot=current.inputRoot};lock(leaseLock)targetLease=wanted;
}else if(clientOwner!=owner||wanted.target!=target)throw new InvalidOperationException("No matching target selection request");
var observed=CurrentFsd();var confirmed=targetConfirmed==wanted.generation&&observed.tick!=0&&now-observed.tick<=200&&observed.targetValid&&observed.targetAddress==target;return Obj(("selected",confirmed),("pending",!confirmed&&targetFailed!=wanted.generation&&wanted.expires>now),("targetAddress",observed.targetAddress.ToString()),("generation",wanted.generation));
}
if(op=="apply")return ApplyRequest(request,owner,current,now);
if(op=="calibrate.fsd")return CalibrateFsd(request,owner,current,now);
if(op=="calibrate.axes")return CalibrateAxes(request,owner,current,now);
throw new InvalidOperationException("Unsupported or unverified native navigation operation");
}
}
static void RequireRecoverableFlightHealth(in Snapshot current)
{
if(!current.healthValid)throw new InvalidOperationException("尚未读到飞船状态,请等待读取后重试。");
if(current.hullFraction<=0)throw new InvalidOperationException("飞船当前已无可用船体,无法启动驾驶。");
if(current.healthEmergency)throw new InvalidOperationException("飞船近期仍有新增受损;连续 3 秒无新增受损后可重新启动导航。");
}
static JsonObject ApplyRequest(JsonElement request,string owner,Snapshot current,ulong now)
{
RequireRecoverableFlightHealth(current);if(!Ready()||!inGame||!current.valid||now-current.tick>200||overridden)throw new InvalidOperationException("Native player telemetry unavailable or stale");
var reference=Reference(request.Required("sequence").GetUInt64(),current,now);var deadline=request.Required("expiresAtUnixMilliseconds").GetUInt64();var utc=UtcMilliseconds();if(deadline<=utc||deadline>utc+300)throw new InvalidOperationException("Navigation reference frame expired; read fresh telemetry and retry");
var fsd=CurrentFsd();var heat=CurrentHeat();GeometryObservation body;lock(geometryLock)body=geometry;var target=request.Required("targetSystemAddress").GetUInt64();
if(!fsd.targetValid||fsd.targetAddress!=target||fsd.entity!=current.entity||now-fsd.tick>200||!body.unifiedReference||body.entity!=current.entity||now-body.tick>200||body.bodyKind!=1||body.worldAddress!=current.referenceWorld)throw new InvalidOperationException("Native target or primary-star envelope changed");if(clientOwner.Length!=0&&clientOwner!=owner)throw new InvalidOperationException("Another controller owns the flight lease");
var decision=request.Required("decision");var begin=decision.Required("beginCharging").GetBoolean();var cancel=decision.Required("cancelCharging").GetBoolean();var permit=decision.Required("permitJump").GetBoolean();var supercruiseEntry=decision.Bool("enterSupercruise");var direction=decision.Required("direction");if(direction.ValueKind!=JsonValueKind.Object)throw new InvalidOperationException("A finite native flight direction is required");
var wanted=new Vector(direction.Required("x").GetDouble(),direction.Required("y").GetDouble(),direction.Required("z").GetDouble());var length=Math.Sqrt(Dot(wanted,wanted));if(!Finite(wanted)||length<.9||length>1.1)throw new InvalidOperationException("Invalid native flight direction");wanted=new(wanted.x/length,wanted.y/length,wanted.z/length);
var position=body.unifiedReference?body.position:current.position;var forward=body.unifiedReference?body.forward:current.forward;var right=body.unifiedReference?body.right:current.right;var up=body.unifiedReference?body.up:current.up;var motion=ObserveMotion(current,body);var x=Dot(wanted,right);var y=Dot(wanted,up);var z=Dot(wanted,forward);
var error=Math.Acos(Math.Clamp(z,-1,1))*180/Math.PI;var yaw=Math.Atan2(x,z)*180/Math.PI;var pitch=-Math.Atan2(y,Math.Sqrt(x*x+z*z))*180/Math.PI;var throttle=decision.Required("throttle").GetSingle();if(!float.IsFinite(throttle)||throttle<0||throttle>1)throw new InvalidOperationException("Invalid native throttle");
var radius=Math.Sqrt(Dot(position,position));var targetDot=Dot(position,fsd.targetDirection);var closestSquared=Dot(position,position)-(targetDot<0?targetDot*targetDot:0);var clear=closestSquared>body.exclusionRadius*body.exclusionRadius*1.1025;var escapeClear=radius>body.escapeRadius*1.2;var escape=position;var closestRatio=radius/body.exclusionRadius;
for(var i=0;i<body.bodyCount;i++){var nearby=body.bodies[i];var delta=Subtract(position,nearby.centre);var square=Dot(delta,delta);var projection=Dot(delta,fsd.targetDirection);if(square-(projection<0?projection*projection:0)<=nearby.exclusionRadius*nearby.exclusionRadius*1.1025)clear=false;if(square<=nearby.escapeRadius*nearby.escapeRadius*1.44)escapeClear=false;var ratio=Math.Sqrt(square)/nearby.exclusionRadius;if(ratio<closestRatio){escape=delta;closestRatio=ratio;}}
var remaining=fsd.state==3?Math.Max(0.0,fsd.duration-fsd.clock):supercruiseEntry?5.0:fsd.driveChargeSeconds;var prediction=ThermalPeak(current,fsd,heat,remaining,supercruiseEntry?.5:ChargingHoldSeconds(current,fsd,body));
if((begin||permit)&&(!double.IsFinite(prediction)||prediction>(supercruiseEntry?99:95)||HeatHudPercent(current)>=97||!supercruiseEntry&&!clear||supercruiseEntry&&!escapeClear))throw new InvalidOperationException("Native thermal or stellar clearance gate refused FSD charging");
var nearPrimary=radius<body.exclusionRadius*3&¤t.speed>1000;if(begin&&!supercruiseEntry&&nearPrimary&&Dot(position,forward)<0)throw new InvalidOperationException("Native departure must be outward before FSD charging");if(begin&&supercruiseEntry&&(current.speedFraction<.8||Dot(escape,forward)/Math.Sqrt(Dot(escape,escape))<.99))throw new InvalidOperationException("Supercruise entry requires verified outward full-speed departure");
var aim=Math.Acos(Math.Clamp(Dot(forward,fsd.targetDirection),-1,1))*180/Math.PI;if(permit&&(!fsdOwned||fsd.state!=3||fsd.clock<fsd.duration||aim>1||throttle!=1))throw new InvalidOperationException("Native jump commit requires full charge, alignment and full throttle");
var departing=!supercruiseEntry&&(begin||fsdOwned)&&clear&&(!nearPrimary||Dot(position,forward)>=0);if(!supercruiseEntry)throttle=ChargingThrottle(throttle,begin||fsdOwned,Dot(position,forward)<0,nearPrimary,permit);
if(!supercruiseEntry&&!departing&&!permit&&throttle>0)throttle=AdaptiveCruiseThrottle(throttle,current.speed,radius,body.exclusionRadius,Dot(position,forward)/radius,error,motion.previousThrottle,current.speedFraction);
if(!supercruiseEntry&&!permit&&!departing)for(var i=0;i<body.bodyCount;i++){var nearby=body.bodies[i];var delta=Subtract(position,nearby.centre);var distance=Math.Sqrt(Dot(delta,delta));if(distance>=nearby.exclusionRadius*3)continue;var radialCosine=Dot(delta,forward)/distance;if((begin||fsdOwned)&&radialCosine<0)throttle=0;else if(throttle>0)throttle=AdaptiveCruiseThrottle(throttle,current.speed,distance,nearby.exclusionRadius,radialCosine,error,motion.previousThrottle,current.speedFraction);}
float[] steering;if(request.TryGetProperty("steeringAxes",out var application)&&application.ValueKind!=JsonValueKind.Null)steering=ApplicationSteeringAxes(application);else{var legacy=SmoothSteering(yaw,pitch,motion,now);steering=[legacy[0],legacy[1],0];}
ClaimController(owner);RequirePhysicalInputSources(current,now);var next=new Lease{expires=Math.Min(now+deadline-utc,reference.tick+300),sequence=reference.sequence,inputRoot=current.inputRoot,throttle=throttle,localKey=-1,epoch=controllerEpoch,interlock=!supercruiseEntry,permitJump=permit,target=target,world=body.worldAddress};next.axes[3]=steering[0];next.axes[4]=steering[1];next.axes[5]=steering[2];lock(motionLock)motionObservation.previousThrottle=throttle;
lock(leaseLock){lease=next;if(cancel&&fsdOwned){fsdLease.expires=next.expires;fsdLease.command=2;}else if(begin&&fsd.state==2&&!fsdOwned)fsdLease=new(){expires=next.expires,sequence=reference.sequence,generation=NextFsdGeneration(),entity=current.entity,fsd=current.fsd,inputRoot=current.inputRoot,life=current.life,command=supercruiseEntry?1u:3u,heatCeiling=97,target=target,supercruiseEntry=supercruiseEntry};else if(fsdOwned){fsdLease.expires=next.expires;fsdLease.sequence=reference.sequence;}}
return Obj(("accepted",true),("throttleCommand",throttle),("steering",Arr(next.axes[3],next.axes[4],next.axes[5])),("commitGateOpen",permit),("predictedPeak",double.IsFinite(prediction)?JsonValue.Create(prediction):null));
}
static JsonObject CalibrateFsd(JsonElement request,string owner,Snapshot current,ulong now)
{
RequireRecoverableFlightHealth(current);var expected=request.Required("sequence").GetUInt64();var ttl=request.Required("ttlMilliseconds").GetInt32();var desired=request.Required("desired").GetString();
if(desired is not ("beginSupercruise" or "beginHyperspace" or "keep" or "cancel"))throw new InvalidOperationException("Unsupported original FSD input for calibration");if(!Enabled()||!inGame||!current.valid||now-current.tick>200||ttl<1||ttl>300)throw new InvalidOperationException("FSD calibration frame or deadline is invalid");
var reference=Reference(expected,current,now);var expires=Math.Min(now+(ulong)ttl,reference.tick+300);var ceiling=(float)request.Num("heatCeilingPercent",65);if(!float.IsFinite(ceiling)||ceiling<60||ceiling>90)throw new InvalidOperationException("FSD calibration heat ceiling must be within 60 to 90 percent");if(desired!="cancel"&&HeatHudPercent(current)>=ceiling)throw new InvalidOperationException("FSD calibration heat limit exceeded; cancel the owned charge");
if(desired=="beginSupercruise"&&(current.speed>=1||current.rawFsdState!=2||fsdOwned||overridden))throw new InvalidOperationException("Supercruise calibration requires a stationary idle ship without player override");var requestedTarget=request.U64("targetSystemAddress");if(desired=="beginHyperspace"){var observed=CurrentFsd();if(requestedTarget==0||!observed.targetValid||observed.targetAddress!=requestedTarget||observed.tick==0||now-observed.tick>200||current.rawFsdState!=2||fsdOwned||overridden)throw new InvalidOperationException("Hyperspace calibration requires a matching locked system target and idle FSD");}
ulong expiry;FsdLease next;lock(leaseLock){expiry=Math.Max(lease.expires,fsdLease.expires);next=fsdLease;}if(expiry<=now&&!fsdOwned)clientOwner="";if(clientOwner.Length!=0&&clientOwner!=owner)throw new InvalidOperationException("Another controller owns the flight lease");if(desired=="keep"&&(clientOwner!=owner||next.fsd!=current.fsd||next.entity!=current.entity))throw new InvalidOperationException("No matching FSD lease to renew");
ClaimController(owner);if(desired!="cancel")RequirePhysicalInputSources(current,now);if(desired!="keep")next=new(){expires=expires,sequence=expected,generation=NextFsdGeneration(),entity=current.entity,fsd=current.fsd,inputRoot=current.inputRoot,life=current.life,command=desired=="beginSupercruise"?1u:desired=="beginHyperspace"?3u:2u,heatCeiling=ceiling,target=desired=="beginHyperspace"?requestedTarget:0};else{next.expires=expires;next.sequence=expected;}lock(leaseLock)fsdLease=next;return Obj(("accepted",true),("generation",next.generation),("expiresInMilliseconds",ttl));
}
static JsonObject CalibrateAxes(JsonElement request,string owner,Snapshot current,ulong now)
{
RequireRecoverableFlightHealth(current);var expected=request.Required("sequence").GetUInt64();var ttl=request.Required("ttlMilliseconds").GetInt32();var rawAxes=request.Required("axes");if(rawAxes.ValueKind!=JsonValueKind.Array||rawAxes.GetArrayLength()!=6)throw new InvalidOperationException("Calibration axes, throttle or deadline exceed their bound");Float6 axes=default;for(var i=0;i<6;i++)axes[i]=rawAxes[i].GetSingle();var throttle=(float)request.Num("throttle",-1);
if(!Enabled()||!inGame||!current.valid||now-current.tick>200)throw new InvalidOperationException("Calibration telemetry is stale or not eligible");var reference=Reference(expected,current,now);var invalid=false;for(var i=0;i<6;i++)invalid|=!float.IsFinite(axes[i])||Math.Abs(axes[i])>.6f;
if(ttl<1||ttl>300||!float.IsFinite(throttle)||throttle!=-1&&(throttle<0||throttle>1)||invalid)throw new InvalidOperationException("Calibration axes, throttle or deadline exceed their bound");ulong expiry;lock(leaseLock)expiry=Math.Max(lease.expires,fsdLease.expires);if(expiry<=now&&!fsdOwned)clientOwner="";if(clientOwner.Length!=0&&clientOwner!=owner)throw new InvalidOperationException("Another controller owns the input lease");if(clientOwner.Length==0)overridden=false;
ClaimController(owner);RequirePhysicalInputSources(current,now);var next=new Lease{expires=Math.Min(now+(ulong)ttl,reference.tick+300),sequence=expected,inputRoot=current.inputRoot,axes=axes,throttle=throttle,epoch=controllerEpoch,localKey=-1};lock(leaseLock)lease=next;return Obj(("accepted",true),("expiresInMilliseconds",ttl));
}
}