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
{
    // Pinned 6891F70A image only. 1414DF0 registers base+58 as 5F3C524;
    // 1401E60 installs these vtables. 1411EE0/1411FD0 prove the ready flags,
    // vector and 260-byte definition stride. No original method is called.
    const int GalaxyPowerOptionMaximum=128;
    internal sealed record GalaxyPowerOption(int index,int uiPowerId,int internalPowerId,string name,float rawRed,float rawGreen,float rawBlue,
        ulong? headquartersSystemAddress=null);
    internal sealed record GalaxyPowerOptions(ulong tick,ulong entity,GalaxyPowerOption[] items)
    {
        // Completeness refers only to the currently ready definition table,
        // not systems, territories or player-specific activity eligibility.
        internal bool optionsComplete=>true;
        internal string source=>"original-power-definition-table";
    }

    static bool CopyGalaxyPowerOptions(nuint manager,nuint owner,nuint expectedImage,out GalaxyPowerOption[] items)
    {
        items=[];
        try
        {
            if(manager<0x10000||owner<0x10000||Pointer(manager)!=expectedImage+0x51BB4D0||
               Pointer(manager+8)!=expectedImage+0x51BB500||Pointer(manager+0x58)!=expectedImage+0x51BB600||Pointer(manager+0x10)!=owner)return false;
            var service=manager+0x58;
            if(Read<byte>(service+0x308)!=1||Read<byte>(service+0x309)!=1)return false;
            var count=Read<ulong>(service+0x330);var vector=Pointer(service+0x338);
            if(count>GalaxyPowerOptionMaximum||count!=0&&vector<0x10000)return false;
            var result=new GalaxyPowerOption[(int)count];HashSet<int> ids=[];
            for(nuint index=0;index<(nuint)count;index++)
            {
                var address=vector+index*0x260;var row=Platform.ReadBytes(address,0x260);
                var id=BinaryPrimitives.ReadInt32LittleEndian(row);var namePointer=(nuint)BinaryPrimitives.ReadUInt64LittleEndian(row.AsSpan(0x18));
                float Colour(int offset)=>BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(row.AsSpan(offset)));
                var r=Colour(0x60);var g=Colour(0x64);var b=Colour(0x68);
                if(id<0||id>=GalaxyPowerOptionMaximum||!ids.Add(id)||namePointer<0x10000||
                   !GalaxyAccountString(namePointer,out var name)||string.IsNullOrWhiteSpace(name)||
                   !float.IsFinite(r)||!float.IsFinite(g)||!float.IsFinite(b))return false;
                if(!Platform.ReadBytes(address,0x260).AsSpan().SequenceEqual(row)||
                   !GalaxyAccountString(namePointer,out var confirmedName)||confirmedName!=name)return false;
                // 3AA1840 supplies index+1 to the UI, separately from the
                // definition's actual first integer. Neither is list order
                // inferred from a public website. RGB stays raw, unclamped.
                // Original OnPowerHeadquartersSelect ->46C6440 ->map UI
                // vfunc3A0/3A6CF20 selects this exact definition+70 address.
                // Zero or a sentinel/out-of-system address remains unknown;
                // the name is never used to manufacture a headquarters.
                var headquarters=BinaryPrimitives.ReadUInt64LittleEndian(row.AsSpan(0x70));
                result[(int)index]=new((int)index,(int)index+1,id,name,r,g,b,
                    headquarters>0&&headquarters<0x80000000000000UL?headquarters:null);
            }
            if(Read<byte>(service+0x308)!=1||Read<byte>(service+0x309)!=1||Read<ulong>(service+0x330)!=count||Pointer(service+0x338)!=vector||
               Pointer(manager+0x10)!=owner||Pointer(manager)!=expectedImage+0x51BB4D0||Pointer(manager+8)!=expectedImage+0x51BB500||Pointer(service)!=expectedImage+0x51BB600)return false;
            items=result;return true;
        }
        catch{items=[];return false;}
    }

    static bool TryReadGalaxyPowerOptions(Snapshot frame,out GalaxyPowerOptions result)
    {
        result=new(0,0,[]);
        if(!Enabled()||!inGame||!frame.valid||frame.physics==0||owningThread==0||GetCurrentThreadId()!=owningThread)return false;
        try
        {
            if(!TryGetGalaxyAccountRegistry(frame,out var registry))return false;
            var service=RegisteredComponent(registry,Read<uint>(image+0x5F3C524));
            if(service<0x10058||Pointer(service)!=image+0x51BB600)return false;
            var manager=service-0x58;var owner=Pointer(manager+0x10);
            if(!CopyGalaxyPowerOptions(manager,owner,image,out var items)||!TryGetGalaxyAccountRegistry(frame,out var currentRegistry)||currentRegistry!=registry||
               RegisteredComponent(registry,Read<uint>(image+0x5F3C524))!=service||Current().entity!=frame.entity)return false;
            result=new(frame.tick,frame.entity,items);return true;
        }
        catch{return false;}
    }
}