XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using XFEEDToolBox.Core.Galaxy;

namespace XFEEDToolBox.ViewModels;

public partial class ToolboxViewModel
{
    private (int ProcessId,long Epoch,long Address)? galaxyOverrideResolveCursor;

    private Task ResolvePublishedGalaxyOverridesAsync(GalaxyCatalogueSelection selection,NativeGalaxyCatalog native,
        Func<bool> currentSource,CancellationToken token)=>
        ResolvePublishedGalaxyOverridesAsync(selection,native.ProcessId,native.ResolveAddressAsync,currentSource,token);

    private async Task ResolvePublishedGalaxyOverridesAsync(GalaxyCatalogueSelection selection,int processId,
        Func<long,CancellationToken,Task<GalacticSystem>> resolve,Func<bool> currentSource,CancellationToken token)
    {
        using var stop=CancellationTokenSource.CreateLinkedTokenSource(token,lifetime.Token);
        var previous=Interlocked.Exchange(ref galaxyOverrideResolveStop,stop);
        try{previous?.Cancel();}catch(ObjectDisposedException){}
        var epoch=Volatile.Read(ref galaxySourceEpoch);var view=Volatile.Read(ref galaxyViewVersion);
        try
        {
            // Let the initial cell request and the first visible frame proceed first.
            await Task.Yield();
            if(selection.PointOverrides is not{} points||points.ProcessId!=processId)return;
            bool Latest()=>!stop.IsCancellationRequested&&epoch==Volatile.Read(ref galaxySourceEpoch)&&
                view==Volatile.Read(ref galaxyViewVersion)&&currentSource()&&ReferenceEquals(selection,GalaxyCatalogueSelection)&&
                ReferenceEquals(points,GalaxyCatalogueSelection?.PointOverrides);
            if(!Latest())return;

            var rows=points.Overrides.Values.Where(row=>row.Name is null).OrderBy(row=>row.SystemAddress).ToArray();
            if(rows.Length==0)return;
            // Names are immutable catalogue facts. Index exact cached identities once,
            // rather than scanning the entire galaxy cache for every queued address.
            var cached=new HashSet<long>();
            foreach(var system in galaxyCache.Values)
                if(system.SystemAddress is{} address&&points.TryGetOverride(address,out var row)&&row?.Position==system.Position)
                    cached.Add(address);

            var cursor=galaxyOverrideResolveCursor is{} old&&old.ProcessId==processId&&old.Epoch==epoch?old.Address:0;
            var start=Array.FindIndex(rows,row=>row.SystemAddress>cursor);if(start<0)start=0;
            var dirty=false;var published=false;var lastPublish=Environment.TickCount64;
            void Flush()
            {
                if(!dirty||!Latest())return;
                dirty=false;published=true;lastPublish=Environment.TickCount64;
                PublishGalaxy();if(Latest())QueueGalaxyFilterInformation();
            }
            for(var index=0;index<rows.Length;index++)
            {
                if(!Latest())return;
                var row=rows[(start+index)%rows.Length];
                // Advance before awaiting: repeated view changes or an unavailable
                // first address cannot keep all later published objects at the back.
                galaxyOverrideResolveCursor=(processId,epoch,row.SystemAddress);
                if(!cached.Contains(row.SystemAddress))
                {
                    // A single outstanding resolve shares the native catalogue gate.
                    // Never enqueue a batch that would hold up subsequent cell work.
                    await Task.Yield();if(!Latest())return;
                    GalacticSystem? system=null;
                    try{system=await resolve(row.SystemAddress,stop.Token);}
                    catch(Exception error)when(error is IOException or InvalidDataException or TimeoutException or InvalidOperationException or KeyNotFoundException){}
                    if(!Latest())return;
                    if(system is not null&&system.SystemAddress==row.SystemAddress&&system.Position==row.Position&&
                       system.Position.IsValid&&!string.IsNullOrWhiteSpace(system.Name))
                    {
                        RememberGalaxy(system,processId);cached.Add(row.SystemAddress);dirty=true;
                        if(!published||Environment.TickCount64-lastPublish>=100)Flush();
                    }
                }
                if((index+1)%32==0)
                {
                    Flush();await Task.Yield();
                }
            }
            Flush();
        }
        catch(OperationCanceledException){}
        finally{Interlocked.CompareExchange(ref galaxyOverrideResolveStop,null,stop);}
    }
}