XFEstudio/XFEEDToolBox
Preserve original docking zero across nested input restores and run CG trading continuously
Track durable zero-throttle commits so enclosing reversible input overlays cannot restore the previous SCA throttle. Preserve native ATC, original-input receipts, actual throttle and AI-duty checks, player input, and the two-second failed-handoff exit. Keep the new handoff under live validation. Add a single sequential C# CG workflow with an empty continuous-arrival gate, original quote and reserve-aware batch selection, checkpoint recovery, maintenance, contribution and wallet reconciliation, and stop-file cancellation. No Codex or OS scheduled task is created. Wait only for known post-jump selection readiness and retain terminal ownership refusals. Validation: isolated native builds and 640 original ABI/self-test invocations passed; the deployed shared package passed 688 invocations and the 20-status/3-lifecycle handshake. Four focused Core regressions and the isolated CLI publish passed. The 0.5.9 continuous failure remains recorded; 0.5.10 live acceptance is pending.
c4d8fb6
代码差异
@@ -0,0 +1,25 @@
using XFEEDToolBox.Core.Models;
namespace XFEEDToolBox.Core.Execution;
public sealed record CgBatchQuote(string Commodity,string Label,long Stock,long BuyPrice,long SellPrice);
public static class CgBatchPlanner
{
// Compare total proceeds for this flight, including a partially stocked
// high-margin commodity, rather than always assuming a full uranium hold.
public static TradeOrder Select(IEnumerable<CgBatchQuote> quotes,int capacity,decimal credits,decimal reserve)
{
if(capacity is <1 or >192||credits<0||reserve<0)throw new ArgumentOutOfRangeException(nameof(capacity));
var orders=new List<TradeOrder>();
foreach(var q in quotes)
{
if(!NativeTradeBatchPolicy.Allows(q.Commodity)||q.Stock<=0||q.BuyPrice is <=0 or >100000||q.SellPrice is <=0 or >100000||q.SellPrice<=q.BuyPrice)continue;
var affordable=Math.Max(0,decimal.Floor((credits-reserve)/q.BuyPrice));
var quantity=(int)Math.Min(Math.Min(capacity,q.Stock),affordable);
if(quantity>0)orders.Add(new(q.Commodity,q.Label,quantity,q.BuyPrice,q.SellPrice));
}
return orders.OrderByDescending(x=>(x.SellPrice-x.BuyPrice)*x.Quantity).ThenBy(x=>x.Commodity,StringComparer.Ordinal).FirstOrDefault()
??throw new InvalidOperationException("当前 CG 原始报价、库存或保留资金不足,未提交采购。");
}
}
@@ -49,8 +49,15 @@ public static class NativeDockingInputDiagnostics
return new{address=value.ToString("x"),zero};
}
var originalFsd=Registry(fsdActions);var originalDocking=Registry(dockingActions);
var physics=memory.U64(fsd+0x2A8)-0x58;var inputRoot=memory.U64(physics+0x3B0)-0x60;
if(memory.U64(inputRoot+0x2F8)!=fsdController)throw new InvalidDataException("Original ship input controller differs.");
var dockingThrottle=memory.U64(computer+0x260);
float Float(ulong address)=>BitConverter.ToSingle(memory.Read(address,4));
memory.Validate();if(memory.U64(life+0xB0)!=entity)throw new InvalidDataException("Main ship identity changed.");
return new{entity=entity.ToString(),fsd=fsd.ToString("x"),computer=computer.ToString("x"),sameRegistry=fsdActions==dockingActions,
controllerThrottle=BitConverter.ToSingle(memory.Read(fsdController+0x680,4)),originalFsd,originalDocking,processAccess="QUERY_INFORMATION | VM_READ",mutationsSent=0};
controllerThrottle=Float(fsdController+0x680),controllerDemand=Float(fsdController+0x684),
actualThrottle=Float(inputRoot+0x70),dockingThrottleSource=dockingThrottle.ToString("x"),
dockingThrottle=dockingThrottle>0x10000?Float(dockingThrottle+0x18):float.NaN,
originalFsd,originalDocking,processAccess="QUERY_INFORMATION | VM_READ",mutationsSent=0};
}
}
@@ -58,6 +58,7 @@ public static class NavigationRecovery
"Native thermal or stellar clearance gate refused FSD charging" or
"Supercruise entry requires verified outward full-speed departure"=>FlightRecovery.ReadNextFrame,
"Fresh healthy player ship required for local navigation" or
"Stop flight control before selecting a local destination" or
"Local control frame expired or selection changed"=>FlightRecovery.ReadNextFrame,
"Native target or primary-star envelope changed"=>FlightRecovery.ReselectTarget,
"Native player telemetry unavailable or stale" or
@@ -0,0 +1,26 @@
using XFEEDToolBox.Core.Execution;
using XFEExtension.NetCore.XUnit.Attributes;
namespace XFEEDToolBox.Test;
[TestFixture]
public class CgBatchPlannerTests
{
[Test]public void PartiallyStockedHighMarginCanBeatAFullLowerMarginHold()
{
var order=CgBatchPlanner.Select([new("uranium","Uranium",107,7241,57104),new("liquidoxygen","Liquid oxygen",10000,667,11000)],192,35000000,4427098);
Check.Equal("uranium",order.Commodity);Check.Equal(107,order.Quantity);
}
[Test]public void DepletedUraniumUsesTheActualProfitableAlternative()
{
var order=CgBatchPlanner.Select([new("uranium","Uranium",0,7241,57104),new("polymers","Polymers",10000,139,2448),new("liquidoxygen","Liquid oxygen",10000,667,11000)],192,35000000,4427098);
Check.Equal("liquidoxygen",order.Commodity);Check.Equal(192,order.Quantity);
}
[Test]public void AffordabilityPreservesReserveAndUnprofitableOrUnsupportedQuotesCannotBuy()
{
var order=CgBatchPlanner.Select([new("uranium","Uranium",999,7241,57104)],192,4427098+7241*3,4427098);
Check.Equal(3,order.Quantity);
Check.Throws<InvalidOperationException>(()=>CgBatchPlanner.Select([new("uranium","Uranium",99,60000,57104),new("gold","Gold",99,1,100000)],192,35000000,4427098));
Check.Throws<InvalidOperationException>(()=>CgBatchPlanner.Select([new("uranium","Uranium",999,7241,57104)],192,4427097,4427098));
}
}
@@ -0,0 +1,17 @@
using XFEEDToolBox.Core.Navigation;
using XFEExtension.NetCore.XUnit.Attributes;
namespace XFEEDToolBox.Test;
[TestFixture]
public class LocalSelectionRecoveryTests
{
[Test]public void TransitionReadinessCanWaitButOwnershipAndCancellationRemainTerminal()
{
Check.That(NavigationRecovery.CanRetry(new InvalidOperationException("Stop flight control before selecting a local destination"),CancellationToken.None));
Check.That(!NavigationRecovery.CanRetry(new InvalidOperationException("Another controller owns local navigation"),CancellationToken.None));
Check.That(!NavigationRecovery.CanRetry(new InvalidOperationException("Local control belongs to another controller"),CancellationToken.None));
using var stop=new CancellationTokenSource();stop.Cancel();
Check.That(!NavigationRecovery.CanRetry(new InvalidOperationException("Stop flight control before selecting a local destination"),stop.Token));
}
}
@@ -12,7 +12,9 @@
## 尚未完整通过的路径
首批载货到站时,SCA→自动降落交接触发保护退出,随后正常空间恢复完成交付。因此 `passed` 仅确认货物、维护、CG和钱包已对账,`continuousArrivalAccepted=false` 保留事实。Core现在先释放临时覆盖,再发原始零油门事件;这项连续交接仍需下一程实机验证。不得延长保护时限或降低遥测要求以取得成功标记。
首批载货到站时,SCA→自动降落交接触发保护退出,随后正常空间恢复完成交付。因此 `passed` 仅确认货物、维护、CG和钱包已对账,`continuousArrivalAccepted=false` 保留事实。不得延长保护时限或降低遥测要求以取得成功标记。
0.5.9 的空载复测仍在空管授权后触发两秒保护:控制器为零、原始输入已有回执,但实际油门仍为 .75,原生降落 duty 未接管。0.5.10 补充持久零油门的提交代次,阻止嵌套临时输入恢复再次写回旧值,且只影响这次原始请求确认过的当前主船油门;玩家后续输入与其余轴不会被恢复覆盖。只读遥测提供提交与跳过旧恢复的计数用于实机诊断。新增内存边界及嵌套恢复回归通过;连续交接仍以实际到站报告为准,不能用离线测试替代。
原始返回菜单路径未通过实机;只有插件明确声明 `nativeReturnToMenuVerified=true` 才允许该路径。从已就绪主菜单进入Solo使用独立入口能力。
@@ -24,7 +26,11 @@
先通过 `scripts/Build-Plugin.ps1` 构建原生包,使用游戏插件管理器安装;游戏构建哈希变化后必须重新适配。再构建 `research/NativeAcceptance/NativeAcceptance.csproj`。研究CLI仅在已授权且身份核对过的游戏会话使用,不模拟键鼠。
`cg-cargo-journey <PID> <旅程目录>` 固定验证Corsair/5、192t、Duamta/Polyakov→AD Leonis/Homer的Uranium路线。首次采购前要求本机原1t已完成回执及CG成员证明。买价上限7,241、卖价下限57,104只是限价,执行前仍读原始价格和库存。每站维护与交易均完成才离站,保留实际重购资金;提高后的CG报价不得再乘8。
`auto-cg-trade <PID> <本机跑商工作目录>` 启动实际的顺序 C# 跑商进程。它先要求当前插件版本和游戏构建匹配,并以空舱验证完整 SCA、空管、原生降落交接;同一完整报告通过后才允许下一批采购。之后按实际收购价、供货库存、钱包与重购保留金,在四种 CG 商品和 1–192t 数量中比较每趟差价,循环采购、维护、运输、交付、CG贡献及钱包核对。它不创建 Codex 自动化或操作系统计划任务。
`automatic-trading/runner.lock` 阻止重复控制,`state.json` 记录实际阶段。写入 `automatic-trading/stop` 可取消当前工作流;已接受的金钱请求仍按原操作键完成回执核对。中断后复用原工作目录和旅程检查点,未知订单只能核对,不能重放。原始卖出和已确认费用全部入账后才接受新收益。
`cg-cargo-journey <PID> <旅程目录>` 单独执行或恢复一批 Corsair/5、192t 容量、Duamta/Polyakov→AD Leonis/Homer 的 CG 运输;直接调用时默认 Uranium 192t,已有 `plan.json` 决定恢复的商品、数量和限价。首次采购前要求本机原1t已完成回执及CG成员证明。执行前仍读原始价格和库存。每站维护与交易均完成才离站,保留实际重购资金;提高后的CG报价不得再乘8。
继续已有货物必须复用原目录。原始回执、钱包、会话身份及日志只存本机,不能提交到仓库。`continuousArrivalAccepted` 必须来自同一完整到站报告,不能用正常空间重试替代。未领取CG奖励不计入净利润。
@@ -35,7 +35,7 @@ Require(Call(navigation, "XFENavigationGetAbiVersion") == 1, "Navigation ABI");
var checks = new (string Suffix, uint Expected)[]
{
("CommerceBatch",255),("CommunityGoal",255),("LocalDockingKind",255),
("Observer",7),("CommerceDocked",127),("LocalDockingHandoff",127),("ShipHealth",255),("LocalTargets",255),("LocalEntityDirectory",255),("LocalSelection",255),("LocalDockingAvailability",31),("LocalPlayerIdentity",255),
("Observer",7),("CommerceDocked",127),("LocalDockingHandoff",16777215),("ShipHealth",255),("LocalTargets",255),("LocalEntityDirectory",255),("LocalSelection",255),("LocalDockingAvailability",31),("LocalPlayerIdentity",255),
("OverlayLifetime",31),("ComponentLookup",63),("FsdCancellation",127),("ThrottleControl",255),
("TargetLookup",63),("ActorSelection",63),("FsdReturn",3),("CommitGate",31),("OutwardThrottle",31),
("RouteArguments",31),("StellarSpeed",255),("ReferenceGeometry",8191),("AdaptiveMotion",1023),
@@ -0,0 +1,38 @@
namespace XFEEDToolBox.Plugin;
internal static unsafe partial class Navigation
{
private static nuint dockingZeroAxisRoot;
private static ulong dockingZeroAxisVersion,dockingZeroAxisCommits,dockingZeroAxisRestoresSkipped;
private static void RememberDockingZero(nuint root)
{dockingZeroAxisRoot=root;dockingZeroAxisVersion++;dockingZeroAxisCommits++;}
private static void RestoreOverlayAxis(nuint root,int axis,float previous,float written,ulong version)
{
// FSD can run inside an input-evaluation overlay. A durable original
// zero must also survive restoration of that outer invocation.
if(axis==0&&root==dockingZeroAxisRoot&&version!=dockingZeroAxisVersion)
{dockingZeroAxisRestoresSkipped++;return;}
var address=root+0x70+(nuint)axis*0x10;
if(Read<float>(address)==written)Write(address,previous);
}
// SetSpeedZero updates the original controller, but an SCA exit can leave
// its last .75 value in the newly materialised ship's input buffer. Commit
// the requested zero only after overlays have been released. The caller
// has already checked the current main ship, owner, target and ATC grant.
private static bool CommitOriginalDockingZeroAxis(nuint inputRoot,nuint controller,float sampledThrottle,
bool originalInputConfirmed,bool inputLeaseReleased,out bool committed)
{
committed=false;
if(!originalInputConfirmed||!inputLeaseReleased||inputRoot<0x10000||controller<0x10000
||!float.IsFinite(sampledThrottle)||Math.Abs(sampledThrottle)>1.001f
||Pointer(inputRoot+0x2F8)!=controller||Read<float>(controller+0x680)!=0)return false;
var current=Read<float>(inputRoot+0x70);
if(current==0){RememberDockingZero(inputRoot);return true;}
// A changed sample may be a player input. Never overwrite it.
if(current!=sampledThrottle)return false;
Write(inputRoot+0x70,0f);
committed=Read<float>(inputRoot+0x70)==0;
if(committed)RememberDockingZero(inputRoot);
return committed;
}
}
@@ -166,9 +166,12 @@ internal static unsafe partial class Navigation
try{return Call(originalFsd,(ulong)obj,F32(dt));}catch{return 0;}
finally{
try{if(pulse.applied)FinishFsdPulse(ref pulse);if(selected&&BoundFsd(frame,fsd))ObserveFsd(frame,fsd,pulse);if(selected&&BoundFsd(frame,fsd))PollReferenceGeometry(frame);
if(selected&&BoundFsd(frame,fsd))PollLocalFlight(frame);if(selected&&BoundFsd(frame,fsd))PollLocalAction(frame);if(selected&&BoundFsd(frame,fsd))PollCommerceRead(frame);if(selected&&BoundFsd(frame,fsd))PollCommunityGoals(frame);
if(selected&&BoundFsd(frame,fsd))PollLocalFlight(frame);if(selected&&BoundFsd(frame,fsd))PollCommerceRead(frame);if(selected&&BoundFsd(frame,fsd))PollCommunityGoals(frame);
}catch{try{Expire();}catch{}}
finally{try{if(applied){Restore(ref overlay);inputAppliedAt=GetTickCount64();}}catch{}}
// A persistent original action must not be undone by restoring the
// temporary axes of the FSD invocation that carried it.
try{if(selected&&BoundFsd(frame,fsd))PollLocalAction(frame);}catch{try{Expire();}catch{}}
try{if(selected)PlanGameRoute(frame);if(selected)PollGalaxyCatalogue(frame);}catch{try{Expire();}catch{}}
try{if(selected)PollGalaxyAccount(frame);}catch{}
try{if(selected)PollGalaxyFilterFacts(frame);}catch{}
@@ -14,6 +14,41 @@ internal static unsafe partial class Navigation
if(LocalDockingZeroConfirmed(false,true,0,0))passed|=16;
if(!LocalDockingZeroConfirmed(false,true,0,double.NaN))passed|=32;
if(!LocalDockingZeroConfirmed(false,true,0,double.PositiveInfinity))passed|=64;
var memory=Platform.Allocate(8192);if(memory==0)return passed;
var saved=(dockingZeroAxisRoot,dockingZeroAxisVersion,dockingZeroAxisCommits,dockingZeroAxisRestoresSkipped);
try
{
var root=memory;var controller=memory+4096;
void Reset(){Write(root+0x2F8,controller);Write(root+0x70,.75f);Write(root+0x80,.2f);Write(controller+0x680,0f);}
Reset();if(CommitOriginalDockingZeroAxis(root,controller,.75f,true,true,out var changed)&&changed&&Read<float>(root+0x70)==0&&Read<float>(root+0x80)==.2f)passed|=128;
Reset();Write(root+0x70,.5f);if(!CommitOriginalDockingZeroAxis(root,controller,.75f,true,true,out _)&&Read<float>(root+0x70)==.5f)passed|=256;
Reset();if(!CommitOriginalDockingZeroAxis(root,controller,.75f,false,true,out _)&&Read<float>(root+0x70)==.75f)passed|=512;
Reset();if(!CommitOriginalDockingZeroAxis(root,controller,.75f,true,false,out _)&&Read<float>(root+0x70)==.75f)passed|=1024;
Reset();Write(controller+0x680,.1f);if(!CommitOriginalDockingZeroAxis(root,controller,.75f,true,true,out _)&&Read<float>(root+0x70)==.75f)passed|=2048;
Reset();Write(root+0x2F8,controller+8);if(!CommitOriginalDockingZeroAxis(root,controller,.75f,true,true,out _)&&Read<float>(root+0x70)==.75f)passed|=4096;
Reset();if(!CommitOriginalDockingZeroAxis(root,controller,float.NaN,true,true,out _))passed|=8192;
Reset();Write(root+0x70,0f);if(CommitOriginalDockingZeroAxis(root,controller,.75f,true,true,out changed)&&!changed)passed|=16384;
if(!CommitOriginalDockingZeroAxis(0,controller,0,true,true,out _))passed|=32768;
Reset();var outer=dockingZeroAxisVersion;
CommitOriginalDockingZeroAxis(root,controller,.75f,true,true,out _);
RestoreOverlayAxis(root,0,.75f,0,outer);
if(Read<float>(root+0x70)==0)passed|=65536;
RestoreOverlayAxis(root,0,.75f,0,outer);
if(Read<float>(root+0x70)==0)passed|=131072;
Write(root+0x80,0f);RestoreOverlayAxis(root,1,.2f,0,outer);
if(Read<float>(root+0x80)==.2f)passed|=262144;
Write(root+0x70,.3f);RestoreOverlayAxis(root,0,.75f,0,outer);
if(Read<float>(root+0x70)==.3f)passed|=524288;
Write(root+0x70,0f);RestoreOverlayAxis(root,0,.4f,0,dockingZeroAxisVersion);
if(Read<float>(root+0x70)==.4f)passed|=1048576;
var other=root+256;Write(other+0x70,0f);RestoreOverlayAxis(other,0,.6f,0,outer);
if(Read<float>(other+0x70)==.6f)passed|=2097152;
Reset();Write(root+0x70,0f);outer=dockingZeroAxisVersion;
if(CommitOriginalDockingZeroAxis(root,controller,0,true,true,out changed)&&!changed&&dockingZeroAxisVersion!=outer)passed|=4194304;
RestoreOverlayAxis(root,0,.75f,0,outer);
if(Read<float>(root+0x70)==0)passed|=8388608;
}
finally{(dockingZeroAxisRoot,dockingZeroAxisVersion,dockingZeroAxisCommits,dockingZeroAxisRestoresSkipped)=saved;Platform.Free(memory);}
return passed;
}
#if PLUGIN_NAVIGATION
@@ -422,8 +422,13 @@ internal static unsafe partial class Navigation
if (dock == 0 || computer == 0 || !observed.dockingComputerAvailable || !LocalDockingAvailable(computer) || controller == 0 || Pointer(computer + 0x240) != controller || !observed.dockingVerified || !observed.dockingGranted || observed.inSupercruise || observed.distance > 7500 || Read<uint>(dock + 0x614) != 2 || Read<uint>(dock + 0x4C0) is not (3 or 4) || Read<byte>(dock + 0x4E9) == 255 || Pointer(Pointer(controller) + 0x158) != image + ThrottleSetter) return false;
var station = Pointer(dock + 0x4E0);
if (station == 0 || Read<uint>(station + 0xC0) != 8 || Read<ulong>(station + 0xB0) != observed.target.market) return false;
if (LocalDockingZeroConfirmed((byte)Call(image + 0xED6620, computer) != 0,observed.dockingZeroInputSent,Read<float>(controller + 0x680),observed.throttle)) return true;
return SendOriginalDockingZeroInput(frame, controller, observed.target.market);
var actualThrottle=Read<float>(frame.inputRoot+0x70);
if((byte)Call(image+0xED6620,computer)!=0)return true;
bool released;lock(leaseLock)released=lease.expires<=now&&fsdLease.expires<=now;
if(!released||fsdOwned)return false;
if(!LocalDockingZeroConfirmed(false,observed.dockingZeroInputSent,Read<float>(controller+0x680),actualThrottle)
&&!SendOriginalDockingZeroInput(frame,controller,observed.target.market))return false;
return CommitOriginalDockingZeroAxis(frame.inputRoot,controller,actualThrottle,true,released,out _);
}
if (command.action == 11)
{
@@ -475,6 +480,7 @@ internal static unsafe partial class Navigation
("distanceMetres", value.distance), ("speedMetresPerSecond", value.speed), ("throttle", value.throttle), ("rawDockingState", value.dockingState), ("rawRequestState", value.requestState), ("rawPad", value.pad), ("normalSpeedLimit", value.normalSpeedLimit), ("cruiseSpeedLimit", value.cruiseSpeedLimit), ("accelerationLowerBound", value.accelerationLowerBound),
("safeDisengage", value.safeDisengage), ("safeDropDistance", value.safeDropDistance), ("safeDropSpeed", value.safeDropSpeed), ("cruiseParametersVerified", value.cruiseParametersVerified), ("cruiseApproachSeconds", value.cruiseApproachSeconds), ("cruiseApproachThrottle", value.cruiseApproachThrottle),
("rawFsdState", frame.rawFsdState), ("rawFsdMode", frame.rawFsdMode), ("rawFsdStage", frame.rawFsdStage), ("inSupercruise", value.inSupercruise),
("dockingZeroAxisCommits", dockingZeroAxisCommits), ("dockingZeroAxisRestoresSkipped", dockingZeroAxisRestoresSkipped),
("supercruiseAssist", Obj(("available", value.cruiseAssistAvailable), ("enabled", value.cruiseAssistEnabled), ("engaged", value.cruiseAssistEngaged), ("matchesTarget", value.cruiseAssistMatches), ("obscured", value.cruiseAssistObscured))),
("docking", Obj(("verified", value.dockingVerified), ("computerAvailable", value.dockingComputerAvailable), ("clearanceGranted", value.dockingGranted), ("assistAllowed", value.dockingAssistAllowed), ("assistEnabled", value.dockingAssistEnabled), ("assistEngaged", value.dockingAssistEngaged), ("nativeDutyActive", value.nativeDockingActive), ("nativeLaunchActive", value.nativeLaunchActive), ("nativeLaunchRequested", value.nativeLaunchRequested), ("throttleZero", value.dockingThrottleZero), ("zeroThrottleInputSent", value.dockingZeroInputSent))));
}
@@ -123,7 +123,7 @@ internal static unsafe partial class Navigation
if(!overlay.applied)return;
try{
if(Pointer(overlay.root)!=overlay.vtable||Read<uint>(overlay.life+0xC0)!=8||Read<ulong>(overlay.life+0xB0)!=overlay.entity||Pointer(overlay.physics+0x3B0)!=overlay.root+0x60)return;
for(var i=0;i<6;i++){var axis=overlay.root+0x70+(nuint)i*0x10;if(Read<float>(axis)==overlay.written[i])Write(axis,overlay.previous[i]);}
for(var i=0;i<6;i++)RestoreOverlayAxis(overlay.root,i,overlay.previous[i],overlay.written[i],overlay.throttleCommitVersion);
}catch{}overlay.applied=false;
}
static bool ApplyInput(nuint root,ref InputOverlay overlay)
@@ -139,7 +139,7 @@ internal static unsafe partial class Navigation
if(inputBaseline.epoch!=control.epoch||inputBaseline.root!=root||inputBaseline.entity!=current.entity){inputBaseline=new(){epoch=control.epoch,entity=current.entity,root=root,axes=overlay.previous};for(var i=1;i<6;i++)inputBaseline.axes[i]=0;}
double delta=0;for(var i=0;i<6;i++)delta=Math.Max(delta,Math.Abs(overlay.previous[i]-inputBaseline.axes[i]));var intent=ClassifyInput(delta,now,ref inputBaseline.intent);
if(intent==InputIntent.Takeover){overridden=true;Expire();return false;}if(intent==InputIntent.Transient)return false;
overlay.root=root;overlay.vtable=Pointer(root);overlay.life=current.life;overlay.entity=current.entity;overlay.physics=current.physics;var axes=CommandAxes(control);
overlay.root=root;overlay.vtable=Pointer(root);overlay.life=current.life;overlay.entity=current.entity;overlay.physics=current.physics;overlay.throttleCommitVersion=dockingZeroAxisVersion;var axes=CommandAxes(control);
for(var i=0;i<6;i++){overlay.written[i]=axes[i];Write(root+0x70+(nuint)i*0x10,overlay.written[i]);}overlay.applied=true;return true;
}catch{Expire();return false;}
}