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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
namespace XFEEDToolBox.Plugin;

internal static unsafe partial class Navigation
{
    internal sealed class GalaxyPowerActivityContext
    {
        internal nuint expectedImage,service,owner;
        internal ulong tick,entity,currentSystem;
        internal uint thread;
        internal int optionCount;
        internal Dictionary<int,int> indices=[];
    }

    // Evidence RVAs refer to pinned 6891: 3B1CFA0, 1412900, 14121E0,
    // 1412A90 and 1414100. Current vtables below are verified ED5A addresses
    // from the shared compatibility ledger and existing PowerOptions reader.
    // This port calls no getter: 1414100 writes the original last-key cache.
    static bool GalaxyPowerActivitySource(nuint service,nuint expectedImage,nuint owner)
    {
        try
        {
            return service>=0x10058&&owner>=0x10000&&Pointer(service)==expectedImage+0x51BB600&&
                Pointer(service-0x58)==expectedImage+0x51BB4D0&&Pointer(service-0x50)==expectedImage+0x51BB500&&
                Pointer(service-0x48)==owner&&Read<byte>(service+0x308)==1&&Read<byte>(service+0x309)==1&&
                Read<byte>(service+0x30A)==1&&Read<byte>(service+0x30C)==0;
        }
        catch{return false;}
    }

    static bool TryCreateGalaxyPowerActivityContext(Snapshot frame,GalaxyServices services,out GalaxyPowerActivityContext result)
    {
        result=new();
        if(!Enabled()||!inGame||!frame.valid||frame.entity==0||owningThread==0||GetCurrentThreadId()!=owningThread||services.registry<0x10000)return false;
        try
        {
            var service=RegisteredComponent(services.registry,Read<uint>(image+0x5F3C524));
            if(service<0x10058)return false;
            var owner=Pointer(service-0x48);
            if(!GalaxyPowerActivitySource(service,image,owner)||!CopyGalaxyPowerOptions(service-0x58,owner,image,out var options)||options.Length==0)return false;
            var indices=new Dictionary<int,int>(options.Length);
            foreach(var option in options)if(!indices.TryAdd(option.internalPowerId,option.index))return false;
            if(!GalaxyPowerActivitySource(service,image,owner))return false;
            result=new(){expectedImage=image,service=service,owner=owner,tick=GetTickCount64(),entity=frame.entity,
                currentSystem=frame.referenceWorld&0x007FFFFFFFFFFFFFUL,thread=owningThread,optionCount=options.Length,indices=indices};
            return result.currentSystem!=0;
        }
        catch{return false;}
    }

    static uint GalaxyPowerActivityPairHash(ulong address,uint mode)
    {
        unchecked
        {
            var hash=mode*0x1001;hash=((hash>>22)^hash)*0x11;hash=((hash>>9)^hash)*0x401;
            hash=((hash>>2)^hash)*0x81;hash^=hash>>12;
            return (uint)GalaxyFactHash(address)^(hash<<16|hash>>16);
        }
    }

    // Original open-address layouts: metadata stride180/alignment16;
    // unoccupied counters stride10/alignment8; controlled pairs stride18/alignment8.
    // A valid empty counter table means original getter zero. A missing metadata
    // record remains unknown, even though the game getter has a fallback record.
    static bool GalaxyPowerActivityFind(nuint map,ulong address,int mode,int stride,int alignment,out nuint node)
    {
        node=0;
        try
        {
            var count=Read<ulong>(map+8);var capacity=Read<ulong>(map+0x10);var storage=Pointer(map+0x18);
            if(count>1_048_576||capacity>2_097_152||count>capacity||capacity!=0&&(capacity&(capacity-1))!=0)return false;
            if(count==0)return Read<ulong>(map+8)==0&&Read<ulong>(map+0x10)==capacity&&Pointer(map+0x18)==storage;
            if(capacity==0||storage<0x10000)return false;
            var rows=storage+(nuint)(((capacity>>3)+(ulong)alignment-1)&~((ulong)alignment-1));
            var hash=mode<0?GalaxyFactHash(address):GalaxyPowerActivityPairHash(address,(uint)mode);
            var slot=hash&(capacity-1);var ended=false;
            for(ulong step=0;step<Math.Min(capacity,4096UL);step++)
            {
                var bits=Read<ulong>(storage+(nuint)(slot>>6)*8);
                if((bits&(1UL<<(int)(slot&63)))==0){ended=true;break;}
                var at=rows+(nuint)slot*(nuint)stride;
                if(Read<ulong>(at)==address&&(mode<0||Read<uint>(at+8)==mode)){node=at;ended=true;break;}
                slot=(slot+1)&(capacity-1);
            }
            if(!ended||Read<ulong>(map+8)!=count||Read<ulong>(map+0x10)!=capacity||Pointer(map+0x18)!=storage){node=0;return false;}
            return true;
        }
        catch{node=0;return false;}
    }

    static int GalaxyPowerActivityCounterMode(int action,bool allPowers,ulong ownerIndex,int selectedIndex)
        =>allPowers?action==2?0:1:(ownerIndex==(ulong)selectedIndex)==(action!=4)?0:1;

    static bool CopyGalaxyPowerActivityCounter(nuint service,nuint expectedImage,nuint owner,ulong address,
        bool allPowers,int selectedIndex,int optionCount,int actionId,out float? recentActivity)
    {
        recentActivity=null;
        if(address==0||address>=0x80000000000000UL||actionId is <1 or >5||optionCount is <1 or >128||
           !allPowers&&(selectedIndex<0||selectedIndex>=optionCount)||!GalaxyPowerActivitySource(service,expectedImage,owner))return false;
        try
        {
            if(!GalaxyPowerActivityFind(service+0x3C0,address,-1,0x180,16,out var node))return false;
            if(node==0)return true;
            var metadata=node+0x10;var ownerIndex=Read<ulong>(metadata);var state=Read<int>(metadata+0xC);
            if(state<0||state>65535||state!=0&&ownerIndex>=(ulong)optionCount)return false;
            float value;
            if(actionId==5)value=Read<float>(metadata+0x124);
            else if(state==0)
            {
                if(!GalaxyPowerActivityFind(service+0x3218,address,-1,0x10,8,out var counter))return false;
                value=counter==0?0:Read<float>(counter+8);
            }
            else
            {
                var mode=GalaxyPowerActivityCounterMode(actionId,allPowers,ownerIndex,selectedIndex);
                if(!GalaxyPowerActivityFind(service+0x3240,address,mode,0x18,8,out var counter))return false;
                value=counter==0?0:Read<float>(counter+0x14);
            }
            if(!float.IsFinite(value)||value<0||!GalaxyPowerActivitySource(service,expectedImage,owner)||
               Read<ulong>(node)!=address||Read<ulong>(metadata)!=ownerIndex||Read<int>(metadata+0xC)!=state)return false;
            recentActivity=value;return true;
        }
        catch{return false;}
    }

    static bool TryReadGalaxyPowerActivityCounter(GalaxyPowerActivityContext context,ulong address,
        bool allPowers,int actualInternalId,int actionId,out float? recentActivity)
    {
        recentActivity=null;
        if(!Enabled()||!inGame||context.thread==0||context.thread!=owningThread||GetCurrentThreadId()!=context.thread||
           GetTickCount64()-context.tick>500||context.expectedImage!=image)return false;
        var frame=Current();
        if(!frame.valid||frame.entity!=context.entity||(frame.referenceWorld&0x007FFFFFFFFFFFFFUL)!=context.currentSystem)return false;
        var index=-1;
        if(allPowers?actualInternalId!=-1:!context.indices.TryGetValue(actualInternalId,out index))return false;
        return CopyGalaxyPowerActivityCounter(context.service,context.expectedImage,context.owner,address,
            allPowers,index,context.optionCount,actionId,out recentActivity);
    }
}