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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Buffers.Binary;
using System.Globalization;
using System.Text.Json.Nodes;
using static XFEEDToolBox.Plugin.JsonWire;

namespace XFEEDToolBox.Plugin;

internal static unsafe partial class Navigation
{
    // Actual3B1A200's owner flag, not JournalOwnedColony. Its two providers
    // cache the original local CommanderID at+90 through their actual+20
    // methods3B3E4C0/3B3E650. See colonisation-colour/compatibility.json.
    internal sealed record GalaxyColonisationOwnership(ulong localCommanderId,ulong claimCommanderId,byte claimStatus)
    {internal bool own=>localCommanderId==claimCommanderId;}

    static bool GalaxyColonisationOwnershipProvider(nuint provider,nuint expectedImage,nuint cache,nuint localUser,out ulong commander)
    {
        commander=0;if(provider<0x10000||cache<0x10058||localUser<0x10000)return false;
        var vt=Pointer(provider);
        if(vt==expectedImage+0x552D878)
        {if(Pointer(vt+0x20)!=expectedImage+0x3B3E4C0||Pointer(vt+0x50)!=expectedImage+0x3B262F0)return false;}
        else if(vt==expectedImage+0x552D920)
        {if(Pointer(vt+0x20)!=expectedImage+0x3B3E650||Pointer(vt+0x50)!=expectedImage+0x3B26B30)return false;}
        else return false;
        if(Pointer(provider+0x80)!=cache||Pointer(provider+0x88)!=localUser||
            Pointer(localUser)!=expectedImage+0x52A0258||Pointer(expectedImage+0x52A0258+0x38)!=expectedImage+0x26032D0)return false;
        commander=Read<ulong>(provider+0x90);return commander is >0 and <ulong.MaxValue;
    }

    // Exact existing1195EF0/11968D0 hash lookup. Never insert/load/request.
    // An absent entry in this partial cache is unknown, not foreign ownership.
    static bool CopyGalaxyColonisationOwnership(nuint provider,nuint cache,nuint localUser,nuint expectedImage,ulong address,out GalaxyColonisationOwnership? result)
    {
        result=null;if(address==0||address>=1UL<<55)return false;
        try
        {
            if(!GalaxyColonisationOwnershipProvider(provider,expectedImage,cache,localUser,out var commander))return false;
            var manager=cache-0x58;var owner=Pointer(manager+0x10);
            if(owner<0x10000||Pointer(cache)!=expectedImage+0x519DB70||Pointer(manager)!=expectedImage+0x519DA40||
                Pointer(manager+8)!=expectedImage+0x519DA70||Pointer(expectedImage+0x519DB70+0x30)!=expectedImage+0x1196830)return false;
            var map=manager+0x160;var count=Read<ulong>(map+8);var capacity=Read<ulong>(map+0x10);var storage=Pointer(map+0x18);
            if(count==0||count>16384||capacity is <8 or >65536||count>capacity||(capacity&(capacity-1))!=0||storage<0x10000)return false;
            var observed=new List<(nuint at,ulong value)>();var rows=storage+(nuint)(((capacity>>3)+15)&~15UL);
            var slot=GalaxyNavRouteHash(address)&(capacity-1);nuint found=0;
            for(ulong step=0;step<Math.Min(capacity,256UL);step++,slot=(slot+1)&(capacity-1))
            {
                var at=storage+(nuint)(slot>>6)*8;var bits=Read<ulong>(at);observed.Add((at,bits));
                if((bits&(1UL<<(int)(slot&63)))==0)return false;
                at=rows+(nuint)slot*0x110;var key=Read<ulong>(at);observed.Add((at,key));
                if(key==address){found=at;break;}
            }
            if(found==0)return false;
            var row=Platform.ReadBytes(found,0x110);if(row.Length!=0x110)return false;
            var status=row[0x10];var valueAddress=BinaryPrimitives.ReadUInt64LittleEndian(row.AsSpan(0x18));
            var claimCommander=BinaryPrimitives.ReadUInt64LittleEndian(row.AsSpan(0x20));
            if(valueAddress!=address||status>3||claimCommander is 0 or ulong.MaxValue)return false;
            if(!GalaxyColonisationOwnershipProvider(provider,expectedImage,cache,localUser,out var confirmed)||confirmed!=commander||
                Pointer(cache)!=expectedImage+0x519DB70||Pointer(manager)!=expectedImage+0x519DA40||Pointer(manager+8)!=expectedImage+0x519DA70||
                Pointer(manager+0x10)!=owner||Read<ulong>(map+8)!=count||Read<ulong>(map+0x10)!=capacity||Pointer(map+0x18)!=storage||
                observed.Any(v=>Read<ulong>(v.at)!=v.value)||!Platform.ReadBytes(found,0x110).AsSpan().SequenceEqual(row))return false;
            result=new(commander,claimCommander,status);return true;
        }
        catch{result=null;return false;}
    }

    static bool TryReadGalaxyColonisationOwnership(GalaxyFilterContext context,GalaxyServices services,ulong address,out GalaxyColonisationOwnership? result)
    {
        result=null;
        if(!Enabled()||!inGame||context.expectedImage!=image||context.thread==0||context.thread!=owningThread||
            GetCurrentThreadId()!=context.thread||GetTickCount64()-context.tick>500||services.registry<0x10000)return false;
        var frame=Current();
        if(!frame.valid||frame.entity!=context.entity||(frame.referenceWorld&0x007FFFFFFFFFFFFFUL)!=context.currentSystem)return false;
        try
        {
            var mainType=Read<uint>(image+0x5FDB224);var cacheType=Read<uint>(image+0x5F5A820);var userType=Read<uint>(image+0x5F05BAC);
            var mainComponent=RegisteredComponent(services.registry,mainType);var cache=RegisteredComponent(services.registry,cacheType);var user=RegisteredComponent(services.registry,userType);
            if(!CopyGameRouteOptions(mainComponent,image,out var main,out _)||Read<int>(main+0x280)!=-1)return false;
            var type=Pointer(main+0x288);if(type<0x10028||Pointer(type)!=image+0x552D788)return false;
            var controller=type-0x28;if(Pointer(controller)!=image+0x552D5C0)return false;
            var sources=new List<(nuint offset,nuint block,nuint provider,ulong commander)>();GalaxyColonisationOwnership? copied=null;
            // Original owner+418/428 handles, relative to its+58 controller.
            foreach(nuint offset in new nuint[]{0x3C0,0x3D0})
            {
                var block=Pointer(controller+offset);var provider=Pointer(controller+offset+8);
                if(block<0x10000||Read<int>(block+8)<=0||Read<int>(block+0xC)<=0||
                    !GalaxyColonisationOwnershipProvider(provider,image,cache,user,out var commander))continue;
                if(sources.Count>0&&sources[0].commander!=commander)return false;
                sources.Add((offset,block,provider,commander));
                if(copied is null&&CopyGalaxyColonisationOwnership(provider,cache,user,image,address,out var value))copied=value;
            }
            if(copied is null)return false;
            var after=Current();
            if(!after.valid||after.entity!=frame.entity||(after.referenceWorld&0x007FFFFFFFFFFFFFUL)!=context.currentSystem||
                Read<uint>(image+0x5FDB224)!=mainType||Read<uint>(image+0x5F5A820)!=cacheType||Read<uint>(image+0x5F05BAC)!=userType||
                RegisteredComponent(services.registry,mainType)!=mainComponent||RegisteredComponent(services.registry,cacheType)!=cache||
                RegisteredComponent(services.registry,userType)!=user||!CopyGameRouteOptions(mainComponent,image,out var confirmed,out _)||confirmed!=main||
                Read<int>(main+0x280)!=-1||Pointer(main+0x288)!=type||Pointer(type)!=image+0x552D788||Pointer(controller)!=image+0x552D5C0||
                sources.Any(s=>Pointer(controller+s.offset)!=s.block||Pointer(controller+s.offset+8)!=s.provider||Read<int>(s.block+8)<=0||Read<int>(s.block+0xC)<=0||
                    !GalaxyColonisationOwnershipProvider(s.provider,image,cache,user,out var now)||now!=s.commander))return false;
            result=copied;return true;
        }
        catch{result=null;return false;}
    }

    static JsonObject? GalaxyColonisationOwnershipDescription(GalaxyColonisationOwnership? value)=>value is null?null:Obj(
        ("source","original-colonisation-classifier-owner"),("localCommanderId",value.localCommanderId.ToString(CultureInfo.InvariantCulture)),
        ("claimCommanderId",value.claimCommanderId.ToString(CultureInfo.InvariantCulture)),("claimStatus",value.claimStatus),("own",value.own));
}