using System.Diagnostics; using System.Text.Json; using XFEEDToolBox.Core.Models; using XFEEDToolBox.Core.Native; using XFEEDToolBox.Core.Navigation; internal static class FlightContextAdmissionAcceptance { private const string Service=NativeSystemFlightControlDriver.OriginalDockingService; private static bool Flag(JsonElement value,string name)=>value.TryGetProperty(name,out var item)&&item.ValueKind==JsonValueKind.True; internal static async Task RunAsync(int pid,string workRoot,string report) { workRoot=Path.GetFullPath(workRoot);report=Path.GetFullPath(report); if(File.Exists(report))throw new IOException("Preserve the previous original Flight admission evidence."); Directory.CreateDirectory(Path.GetDirectoryName(report)!); using var exclusive=new FileStream(Path.Combine(workRoot,"docking-fixture-wait.lock"),FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.None); using var timeout=new CancellationTokenSource(TimeSpan.FromSeconds(12));var token=timeout.Token; using var process=Process.GetProcessById(pid);var started=process.StartTime.ToUniversalTime().Ticks; using var guardian=await PersistentProtectionProcess.StartOrReuseAsync(pid,workRoot,token,allowStart:false); var nav=new NavigationPipeClient(pid);var scope=new NavigationPipeClient(pid,Service); var owner=Guid.NewGuid().ToString("N");var requestId=Guid.NewGuid().ToString("N"); var observations=new List();JsonElement? admission=null,finalDock=null; var armed=false;var releaseSent=false;var passed=false;Exception? failure=null;var phase="preflight"; async Task Save()=>await File.WriteAllTextAsync(report,JsonSerializer.Serialize(new{at=DateTimeOffset.UtcNow,pid,started,phase,passed, owner,requestId,admission,observations,finalDock,failure=failure?.ToString(),inputsSent=0,flightStarted=false,tradeOrdersSent=0, originalContextOnly=true,protectionPid=guardian.ObserverPid},ToolboxSettings.JsonOptions)); void CheckProcess(){process.Refresh();if(process.HasExited||process.StartTime.ToUniversalTime().Ticks!=started)throw new IOException("Game process identity changed.");guardian.RequireReady(pid);} async Task Status() { CheckProcess();var value=await scope.CallAsync(new{op="flight.context.status",owner,requestId},token); observations.Add(value.Clone());return value; } async Task Release() { if(!armed||releaseSent)return;CheckProcess();releaseSent=true; using var cleanup=new CancellationTokenSource(TimeSpan.FromSeconds(2)); observations.Add((await scope.CallAsync(new{op="flight.context.release",owner,requestId},cleanup.Token)).Clone()); } try { CheckProcess();var hello=await scope.CallAsync(new{op="describe"},token); if(hello.GetProperty("processId").GetInt32()!=pid||hello.GetProperty("service").GetString()!=Service ||hello.GetProperty("gameSha256").GetString()!=NativeSystemLocationReader.GameSha256||!Flag(hello,"enabled") ||hello.GetProperty("state").GetString()!="InGame"||hello.GetProperty("nextState").GetString()!="InGame") throw new InvalidDataException("Pinned original Flight context extension is unavailable."); var local=await nav.CallAsync(new{op="local.read"},token);var target=local.GetProperty("target").Clone(); var market=target.GetProperty("marketId").GetUInt32(); var dock=await nav.CallAsync(new{op="commerce.docked.status",marketId=market},token); if(!Flag(dock,"ready")||!Flag(dock,"serviceReady")||!Flag(dock,"healthy")||!Flag(dock,"fresh")||dock.GetProperty("rawDockingState").GetInt32()!=5) throw new InvalidDataException("No-seed admission must remain actually docked and service ready."); var selected=await nav.CallAsync(new{op="local.select",owner,key=target.GetProperty("key").GetInt32(),bodyAddress=target.GetProperty("bodyAddress").GetString(), kind=target.GetProperty("kind").GetUInt32(),marketId=market,name=target.GetProperty("name").GetString()},token); var generation=selected.GetProperty("generation").GetUInt64();var until=DateTimeOffset.UtcNow.AddSeconds(2); while(!Flag(selected,"selected")) { if(!Flag(selected,"pending")||DateTimeOffset.UtcNow>=until)throw new InvalidDataException("Original station selection was not confirmed."); await Task.Delay(10,token);selected=await nav.CallAsync(new{op="local.status",owner,generation},token); } await Save(); var frame=await nav.CallAsync(new{op="read"},token);var deadline=DateTimeOffset.UtcNow.AddMilliseconds(250); phase="original-context-arm";armed=true; admission=await scope.CallAsync(new{op="flight.context.arm",owner,requestId,purpose="stationary-no-seed",selectionGeneration=generation, sequence=frame.GetProperty("sequence").GetUInt64(),ttlMilliseconds=250,expiresAtUnixMilliseconds=deadline.ToUnixTimeMilliseconds()},token); observations.Add(admission.Value.Clone());until=DateTimeOffset.UtcNow.AddSeconds(2); while(true) { var state=await Status(); if(Flag(state,"failed"))throw new InvalidDataException("Original Flight admission refused: "+state.GetProperty("issue").GetString()); if(Flag(state,"activeObserved")) { if(!Flag(state,"created")||!Flag(state,"owned")||!Flag(state,"ownTokenMember")||state.GetProperty("foreignTokens").GetUInt64()!=0 ||state.GetProperty("activeFlag").GetInt32()!=1||state.GetProperty("fixedPriority").GetInt32()!=0) throw new InvalidDataException("No exact original owned Flight layer was observed."); break; } if(DateTimeOffset.UtcNow>=until)throw new TimeoutException("Original Flight activation was not observed."); if(deadline-DateTimeOffset.UtcNowv.GetUInt64()!=0)) throw new InvalidDataException("Original Flight release did not restore the original inactive graph."); foreach(var key in new[]{"accumulator","sourceValue","actualThrottle"}) if(!state.TryGetProperty(key,out var zero)||zero.ValueKind!=JsonValueKind.Number||Math.Abs(zero.GetDouble())>.001) throw new InvalidDataException("No-seed admission changed a real throttle source."); var controller=state.GetProperty("controllerThrottle").GetDouble(); if(!double.IsFinite(controller)||Math.Abs(controller)>.001&&controller!=-100) throw new InvalidDataException("No-seed admission left an unexpected controller override."); break; } if(DateTimeOffset.UtcNow>=until)throw new TimeoutException("Original inactive graph was not observed after release."); await Task.Delay(10,token); } finalDock=await nav.CallAsync(new{op="commerce.docked.status",marketId=market},token); passed=Flag(finalDock.Value,"ready")&&Flag(finalDock.Value,"serviceReady")&&Flag(finalDock.Value,"fresh")&&Flag(finalDock.Value,"healthy"); if(!passed)throw new InvalidDataException("No-seed probe did not finish at the original ready dock.");phase="passed-original-active-release-inactive"; } catch(Exception error){failure=error;phase="failed-original-admission";} finally { try{await Release();}catch(Exception cleanup){failure=failure is null?cleanup:new AggregateException(failure,cleanup);passed=false;} await Save(); } Console.WriteLine(JsonSerializer.Serialize(new{passed,phase,report,inputsSent=0,flightStarted=false})); if(!passed)throw new InvalidOperationException("Original Flight admission did not pass; no flight or seed was attempted.",failure); } }