using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using XFEEDToolBox.Core.Galaxy;
using XFEEDToolBox.Core.Navigation;
namespace XFEEDToolBox.ViewModels;
public partial class ToolboxViewModel
{
[ObservableProperty] public partial IReadOnlyList<GalaxyFleetMapTarget> GalaxyFleetTargets {get;set;}=[];
[ObservableProperty] public partial string GalaxyFleetStatus {get;set;}="原游戏飞船发布列表尚未连接。";
private IReadOnlyList<GalaxyFleetItem> galaxyFleetItems=[];
private IReadOnlySet<long> galaxyFleetAddresses=new HashSet<long>();
private string galaxyFleetContext="";
private DateTimeOffset galaxyFleetReadAt;
private void SetGalaxyFleet(IReadOnlyList<GalaxyFleetItem> ships)
{
if(!galaxyFleetItems.SequenceEqual(ships)){galaxyFleetItems=ships;galaxyFleetAddresses=ships.Select(s=>s.SystemAddress).ToHashSet();galaxyNativeFactsVersion++;}
var names=galaxyCache.Values.Where(s=>s.SystemAddress is {} address&&galaxyFleetAddresses.Contains(address)&&s.Position.IsValid).GroupBy(s=>s.SystemAddress!.Value).ToDictionary(g=>g.Key,g=>g.First().Name);
var targets=ships.Select(s=>new GalaxyFleetMapTarget(s.Id,s.ShipId,s.SystemAddress,"飞船 #"+s.ShipId+" · "+(names.GetValueOrDefault(s.SystemAddress)??"地址 "+s.SystemAddress))).ToArray();
if(!GalaxyFleetTargets.SequenceEqual(targets))GalaxyFleetTargets=targets;
}
private async Task ReadGalaxyFleetAsync(CancellationToken token)
{
var context=ThargoidContext();
if(galaxyFleetContext.Length>0&&galaxyFleetContext!=context){SetGalaxyFleet([]);galaxyFleetContext="";galaxyFleetReadAt=default;}
if(DateTimeOffset.UtcNow-galaxyFleetReadAt<TimeSpan.FromSeconds(2))return;galaxyFleetReadAt=DateTimeOffset.UtcNow;
if(context.Length==0||runtime.FlightDriver is not NativeFlightControlDriver{SupportsGalaxyFleet:true} driver)
{SetGalaxyFleet([]);galaxyFleetContext="";GalaxyFleetStatus="原游戏飞船发布列表尚未连接;Journal 停放记录另行保留。";return;}
bool Latest()=>context==ThargoidContext();
try
{
var snapshot=await new NativeGalaxyAccountCatalog(driver.ProcessId).ReadFleetAsync(token);token.ThrowIfCancellationRequested();if(!Latest())return;
galaxyFleetContext=snapshot.Available?context:"";SetGalaxyFleet(snapshot.Available?snapshot.Ships:[]);
GalaxyFleetStatus=snapshot.Available?$"原游戏发布列表 · {snapshot.Ships.Count:N0} 条可定位飞船"+(snapshot.CurrentShipId is {} current?$";当前飞船 #{current} 已按原规则排除。":";当前飞船 ID 未确认。")+"完整性与刷新时效尚未确认。":"原游戏飞船列表尚未就绪;不把空缓存当无停放飞船。";
}
catch(OperationCanceledException)when(!token.IsCancellationRequested)
{if(Latest()){SetGalaxyFleet([]);galaxyFleetContext="";GalaxyFleetStatus="原游戏飞船列表读取超时;旧列表已清除。";}}
catch(Exception error)when(error is IOException or TimeoutException or InvalidDataException or InvalidOperationException or System.Text.Json.JsonException or KeyNotFoundException or FormatException)
{if(Latest()){SetGalaxyFleet([]);galaxyFleetContext="";GalaxyFleetStatus="原游戏飞船列表尚未确认:"+error.Message;}}
}
[RelayCommand] private async Task SelectGalaxyFleetAsync(GalaxyFleetMapTarget? target)
{
if(target is null||galaxyFleetContext.Length==0||galaxyFleetContext!=ThargoidContext())return;
var context=galaxyFleetContext;var request=++galaxyMapTargetSelectionVersion;
bool Latest()=>request==galaxyMapTargetSelectionVersion&&context==ThargoidContext()&&context==galaxyFleetContext&&galaxyFleetItems.Any(s=>s.Id==target.Id&&s.ShipId==target.ShipId&&s.SystemAddress==target.SystemAddress);
if(!Latest())return;
try
{
var system=galaxyCache.Values.FirstOrDefault(s=>s.SystemAddress==target.SystemAddress&&s.Position.IsValid&&!string.IsNullOrWhiteSpace(s.Name));
if(system is null)
{
if(runtime.FlightDriver is not NativeFlightControlDriver{SupportsGalaxyResolveAddress:true}||NativeGalaxy() is not {} catalog)
{GalaxyFleetStatus="已读取飞船实际星系地址,尚未连接精确地址解析。";return;}
system=await catalog.ResolveAddressAsync(target.SystemAddress,lifetime.Token);
}
if(!Latest())return;if(system.SystemAddress!=target.SystemAddress||!system.Position.IsValid)throw new InvalidDataException("飞船地址与实际目录记录不一致。");
system=RememberGalaxy(system);GalaxySelection=system;GalaxyCentre=system.Position;PublishGalaxy();GalaxyFleetStatus=$"已定位原列表飞船 #{target.ShipId} · {system.Name}";
}
catch(OperationCanceledException){ }
catch(Exception error)when(error is IOException or TimeoutException or InvalidDataException or InvalidOperationException or KeyNotFoundException or System.Text.Json.JsonException)
{if(Latest())GalaxyFleetStatus="飞船定位尚未完成:"+error.Message;}
}
}
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using XFEEDToolBox.Core.Galaxy;
using XFEEDToolBox.Core.Navigation;
namespace XFEEDToolBox.ViewModels;
public partial class ToolboxViewModel
{
[ObservableProperty] public partial IReadOnlyList<GalaxyFleetMapTarget> GalaxyFleetTargets {get;set;}=[];
[ObservableProperty] public partial string GalaxyFleetStatus {get;set;}="原游戏飞船发布列表尚未连接。";
private IReadOnlyList<GalaxyFleetItem> galaxyFleetItems=[];
private IReadOnlySet<long> galaxyFleetAddresses=new HashSet<long>();
private string galaxyFleetContext="";
private DateTimeOffset galaxyFleetReadAt;
private void SetGalaxyFleet(IReadOnlyList<GalaxyFleetItem> ships)
{
if(!galaxyFleetItems.SequenceEqual(ships)){galaxyFleetItems=ships;galaxyFleetAddresses=ships.Select(s=>s.SystemAddress).ToHashSet();galaxyNativeFactsVersion++;}
var names=galaxyCache.Values.Where(s=>s.SystemAddress is {} address&&galaxyFleetAddresses.Contains(address)&&s.Position.IsValid).GroupBy(s=>s.SystemAddress!.Value).ToDictionary(g=>g.Key,g=>g.First().Name);
var targets=ships.Select(s=>new GalaxyFleetMapTarget(s.Id,s.ShipId,s.SystemAddress,"飞船 #"+s.ShipId+" · "+(names.GetValueOrDefault(s.SystemAddress)??"地址 "+s.SystemAddress))).ToArray();
if(!GalaxyFleetTargets.SequenceEqual(targets))GalaxyFleetTargets=targets;
}
private async Task ReadGalaxyFleetAsync(CancellationToken token)
{
var context=ThargoidContext();
if(galaxyFleetContext.Length>0&&galaxyFleetContext!=context){SetGalaxyFleet([]);galaxyFleetContext="";galaxyFleetReadAt=default;}
if(DateTimeOffset.UtcNow-galaxyFleetReadAt<TimeSpan.FromSeconds(2))return;galaxyFleetReadAt=DateTimeOffset.UtcNow;
if(context.Length==0||runtime.FlightDriver is not NativeFlightControlDriver{SupportsGalaxyFleet:true} driver)
{SetGalaxyFleet([]);galaxyFleetContext="";GalaxyFleetStatus="原游戏飞船发布列表尚未连接;Journal 停放记录另行保留。";return;}
bool Latest()=>context==ThargoidContext();
try
{
var snapshot=await new NativeGalaxyAccountCatalog(driver.ProcessId).ReadFleetAsync(token);token.ThrowIfCancellationRequested();if(!Latest())return;
galaxyFleetContext=snapshot.Available?context:"";SetGalaxyFleet(snapshot.Available?snapshot.Ships:[]);
GalaxyFleetStatus=snapshot.Available?$"原游戏发布列表 · {snapshot.Ships.Count:N0} 条可定位飞船"+(snapshot.CurrentShipId is {} current?$";当前飞船 #{current} 已按原规则排除。":";当前飞船 ID 未确认。")+"完整性与刷新时效尚未确认。":"原游戏飞船列表尚未就绪;不把空缓存当无停放飞船。";
}
catch(OperationCanceledException)when(!token.IsCancellationRequested)
{if(Latest()){SetGalaxyFleet([]);galaxyFleetContext="";GalaxyFleetStatus="原游戏飞船列表读取超时;旧列表已清除。";}}
catch(Exception error)when(error is IOException or TimeoutException or InvalidDataException or InvalidOperationException or System.Text.Json.JsonException or KeyNotFoundException or FormatException)
{if(Latest()){SetGalaxyFleet([]);galaxyFleetContext="";GalaxyFleetStatus="原游戏飞船列表尚未确认:"+error.Message;}}
}
[RelayCommand] private async Task SelectGalaxyFleetAsync(GalaxyFleetMapTarget? target)
{
if(target is null||galaxyFleetContext.Length==0||galaxyFleetContext!=ThargoidContext())return;
var context=galaxyFleetContext;var request=++galaxyMapTargetSelectionVersion;
bool Latest()=>request==galaxyMapTargetSelectionVersion&&context==ThargoidContext()&&context==galaxyFleetContext&&galaxyFleetItems.Any(s=>s.Id==target.Id&&s.ShipId==target.ShipId&&s.SystemAddress==target.SystemAddress);
if(!Latest())return;
try
{
var system=galaxyCache.Values.FirstOrDefault(s=>s.SystemAddress==target.SystemAddress&&s.Position.IsValid&&!string.IsNullOrWhiteSpace(s.Name));
if(system is null)
{
if(runtime.FlightDriver is not NativeFlightControlDriver{SupportsGalaxyResolveAddress:true}||NativeGalaxy() is not {} catalog)
{GalaxyFleetStatus="已读取飞船实际星系地址,尚未连接精确地址解析。";return;}
system=await catalog.ResolveAddressAsync(target.SystemAddress,lifetime.Token);
}
if(!Latest())return;if(system.SystemAddress!=target.SystemAddress||!system.Position.IsValid)throw new InvalidDataException("飞船地址与实际目录记录不一致。");
system=RememberGalaxy(system);GalaxySelection=system;GalaxyCentre=system.Position;PublishGalaxy();GalaxyFleetStatus=$"已定位原列表飞船 #{target.ShipId} · {system.Name}";
}
catch(OperationCanceledException){ }
catch(Exception error)when(error is IOException or TimeoutException or InvalidDataException or InvalidOperationException or KeyNotFoundException or System.Text.Json.JsonException)
{if(Latest())GalaxyFleetStatus="飞船定位尚未完成:"+error.Message;}
}
}