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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Buffers.Binary;

namespace XFEEDToolBox.Plugin;

internal static unsafe partial class Navigation
{
    sealed class GalaxyCommodityPublisherContext(IReadOnlySet<string> names,Func<bool> stable)
    {
        internal IReadOnlySet<string> Names=>names;
        internal bool Stable()=>stable();
    }
    // Original3A2F7A0/1EC2CA0: exact definition name, current original owner
    // and row+28==-1. This never substitutes the commander's FID or Journal.
    static bool CopyGalaxyCommodityCargo(nuint cargo,nuint scope,nuint expectedImage,out GalaxyCommodityPublisherContext? result)
    {
        result=null;
        try
        {
            var copy=new GalaxyCommodityCopy();ulong owner=0;
            if(scope!=0)
            {
                if(scope<0x10058||copy.Ptr(scope)!=expectedImage+0x5292728||copy.Ptr(scope-0x58)!=expectedImage+0x52925F8||copy.Ptr(scope-0x50)!=expectedImage+0x5292628||copy.Ptr(scope-0x48)<0x10000)return false;
                owner=copy.U64(scope+0x160);if(owner==ulong.MaxValue)owner=copy.U64(scope+0x138);if(owner==ulong.MaxValue)owner=0;
            }
            var names=new HashSet<string>(StringComparer.Ordinal);
            if(cargo!=0)
            {
                if(cargo<0x10058||copy.Ptr(cargo)!=expectedImage+0x530B858||copy.Ptr(cargo-0x58)!=expectedImage+0x530B728||copy.Ptr(cargo-0x50)!=expectedImage+0x530B758||copy.Ptr(cargo-0x48)<0x10000)return false;
                var capacity=copy.U64(cargo+0x370);var count=copy.U64(cargo+0x380);var vector=copy.Ptr(cargo+0x388);
                if(count>4096||capacity<count||capacity>65536)return false;
                var rows=count==0?[]:copy.Bytes(vector,checked((int)count*0x60));
                for(var index=0;index<(int)count;index++)
                {
                    var row=rows.AsSpan(index*0x60,0x60);
                    if(BinaryPrimitives.ReadUInt64LittleEndian(row[8..])!=owner||BinaryPrimitives.ReadInt64LittleEndian(row[0x28..])!=-1)continue;
                    var name=(nuint)BinaryPrimitives.ReadUInt64LittleEndian(row[0x18..]);if(name!=0)names.Add(copy.Name(name));
                }
            }
            if(!copy.Stable())return false;result=new(names,copy.Stable);return true;
        }
        catch{return false;}
    }

    static GalaxyCommodityPublisherContext? ReadGalaxyCommodityPublisherContext(nuint registry)
    {
        try
        {
            var actorType=Read<uint>(image+0x5F05BA4);var cargoType=Read<uint>(image+0x5F2F25C);var scopeType=Read<uint>(image+0x5F05E70);
            var actor=RegisteredComponent(registry,actorType);if(actor<0x10058)return null;
            var copy=new GalaxyCommodityCopy();
            if(copy.Ptr(actor)!=image+0x5294CD8||copy.Ptr(actor-0x48)<0x10000)return null;
            var manager=actor-0x58;var count=copy.U64(manager+0x970);var vector=copy.Ptr(manager+0x978);if(count>32)return null;
            var rows=count==0?[]:copy.Bytes(vector,checked((int)count*0x1C0));var index=GalaxyFleetActorIndex(rows);
            bool ActorStable()=>copy.Stable()&&RegisteredComponent(registry,actorType)==actor&&Read<uint>(image+0x5F05BA4)==actorType;
            if(index<0)return new(new HashSet<string>(),ActorStable);
            var life=(nuint)BinaryPrimitives.ReadUInt64LittleEndian(rows.AsSpan(index*0x1C0+0x1A8,8));
            if(life==0)return new(new HashSet<string>(),ActorStable);
            if(copy.Ptr(life)==0||unchecked((int)copy.U32(life+0xC0))<=4)return new(new HashSet<string>(),ActorStable);
            var components=copy.Ptr(life+0xC8);if(components<0x10030)return null;
            var cargo=RegisteredComponent(components-0x30,cargoType);var scope=RegisteredComponent(registry,scopeType);
            if(!CopyGalaxyCommodityCargo(cargo,scope,image,out var context)||context is null)return null;
            bool Stable()=>ActorStable()&&context.Stable()&&RegisteredComponent(components-0x30,cargoType)==cargo&&RegisteredComponent(registry,scopeType)==scope&&Read<uint>(image+0x5F2F25C)==cargoType&&Read<uint>(image+0x5F05E70)==scopeType;
            if(!Stable())return null;return new(context.Names,Stable);
        }
        catch{return null;}
    }
}