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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Security.Cryptography;
using System.Text;

namespace XFEEDToolBox.Plugin;

internal static unsafe partial class Navigation
{
    private struct CommunityGoalRequest
    {
        internal ulong generation,entity,epoch,expires,queued,observed;
        internal nuint life,request;
        internal uint market,state,error,kind;
        internal ulong goal;
        internal bool mutationSent;
    }
    private static readonly object communityGoalLock=new();
    private static CommunityGoalRequest communityGoalRequest;
    private static ulong communityGoalGeneration;
    private static string communityGoalBody="";
    private static readonly byte[] communityGoalBuffer=new byte[1024*1024];
    private static readonly Dictionary<string,ulong> communityGoalKeys=new(StringComparer.Ordinal);
    private static string CommunityGoalProof(string body)=>Convert.ToHexStringLower(SHA256.HashData(Encoding.UTF8.GetBytes(body)));
    private static bool CommunityGoalReadProofMatches(in Snapshot frame,in CommunityGoalRequest prior,string? proof,ulong generation,ulong now,string body)
        =>prior.kind==0&&prior.state==3&&prior.generation==generation&&prior.entity==frame.entity&&prior.life==frame.life&&prior.epoch==controllerEpoch
            &&now>=prior.observed&&now-prior.observed<=60000&&string.Equals(proof,CommunityGoalProof(body),StringComparison.Ordinal);

    private static bool FreshCommunityGoalDock(in Snapshot frame,uint market)
        =>Enabled()&&inGame&&frame.valid&&frame.healthValid&&!frame.healthEmergency&&frame.hullFraction>0
            &&GetTickCount64()>=frame.tick&&GetTickCount64()-frame.tick<=200&&market!=0&&CommerceDocked(frame,market);

    private static bool StartCommunityGoalRequest(in Snapshot frame,ref CommunityGoalRequest work)
    {
        var route=GameRoute(frame,out _);var context=route!=0?route-0x50:0;
        if(context==0||Pointer(Pointer(context))!=image+0x541C70||Pointer(context+8)==0)return false;
        var endpoint=work.kind==1?(nuint)0x5247D00:work.kind==2?(nuint)0x529B270:0x52405E0;
        ReadOnlySpan<byte> expected=work.kind==1?"2.0/elite/initiative/optin\0"u8:work.kind==2?"2.0/elite/initiative/commander/list\0"u8:"2.0/elite/initiative/list\0"u8;
        if(!Bytes(image+endpoint,expected)||!Prefix(0x3433030,[0x48,0x8B,0xC4,0x48,0x89,0x58,0x10]))return false;
        var storage=(nuint)Call(image+0x53A690,0xF8);if(storage==0)return false;
        ClearServiceMemory(storage,0xF8);work.request=storage;
        Call(image+0x33FCC50,storage+0xA8,context);
        Call(image+0x99F4F0,storage,work.kind==1?3u:1u,image+endpoint);
        Write(storage,image+0x511F9D0);
        if(work.kind==1){work.mutationSent=true;Call(image+0x3433030,storage,work.goal);}
        else Call(image+0x340E980,storage);
        return true;
    }
    private static void DeleteCommunityGoalRequest(ref CommunityGoalRequest work)
    {
        var request=work.request;
        try{if(request!=0&&Pointer(request)==image+0x511F9D0){var destroy=Pointer(Pointer(request));if(InImage(destroy))Call(destroy,request,1);}}
        catch{}
        work.request=0;
    }
    private static void PollCommunityGoals(in Snapshot frame)
    {
        CommunityGoalRequest work;lock(communityGoalLock)work=communityGoalRequest;
        if(work.generation==0||work.state>=3||GetCurrentThreadId()!=owningThread)return;
        string? body=null;
        try
        {
            work.error=1;
            if(!FreshCommunityGoalDock(frame,work.market)||work.entity!=frame.entity||work.life!=frame.life||work.epoch!=controllerEpoch||work.expires<=GetTickCount64())work.state=4;
            else
            {
                if(work.request==0)
                {
                    work.error=2;
                    if(work.kind==1&&GetTickCount64()-work.queued>250||!StartCommunityGoalRequest(frame,ref work))work.state=4;
                    else work.state=2;
                }
                if(work.state==2)
                {
                    var request=work.request;work.error=0;
                    var pending=Read<uint>(request+0x3C) is 1 or 2;
                    if(!pending||(byte)Call(image+0x9A3250,request)!=0)
                    {
                        if((byte)Call(image+0x9B5480,request)==0){work.error=(uint)Call(image+0x9A8F10,request);work.state=4;}
                        else
                        {
                            nuint text=0;Call(image+0x9A8DC0,request,(ulong)&text);
                            try
                            {
                                var length=text!=0?Read<ulong>(text):0;
                                if(length==0||length>=(ulong)communityGoalBuffer.Length){work.error=3;work.state=4;}
                                else
                                {
                                    fixed(byte* destination=communityGoalBuffer)CopyCommerceMemory(text+0x14,destination,checked((int)length));
                                    body=Encoding.UTF8.GetString(communityGoalBuffer,0,checked((int)length));
                                    work.state=3;work.observed=GetTickCount64();
                                }
                            }
                            finally{if(text!=0)Call(image+0x204010,(ulong)&text);}
                        }
                    }
                }
            }
        }
        catch(Exception error){work.error=CommerceExceptionCode(error);work.state=4;}
        if(work.state>=3)DeleteCommunityGoalRequest(ref work);
        lock(communityGoalLock)
        {
            if(communityGoalRequest.generation!=work.generation)return;
            communityGoalRequest=work;if(body is not null)communityGoalBody=body;
        }
    }
    private static JsonObject CommunityGoalCall(string op,JsonElement request,in Snapshot frame)
    {
        lock(communityGoalLock)
        {
            if(op=="cg.operation.status")
            {
                var lookupKey=request.Required("operationKey").GetString()!;
                if(!CommerceOperationKey(lookupKey))throw new InvalidOperationException("Identified CG operation required");
                if(!communityGoalKeys.TryGetValue(lookupKey,out var generation))return Obj(("known",false));
                return Obj(("known",true),("generation",generation),("receiptAvailable",generation==communityGoalRequest.generation));
            }
            if(op=="cg.status")
            {
                var work=communityGoalRequest;
                if(request.Required("generation").GetUInt64()!=work.generation)throw new InvalidOperationException("CG request generation changed");
                return Obj(("generation",work.generation),("state",work.state),("error",work.error),("kind",work.kind),("goalId",work.goal),
                    ("mutationsSent",work.mutationSent?1:0),("responseBody",work.state==3?communityGoalBody:""),
                    ("proof",work.state==3?CommunityGoalProof(communityGoalBody):""),("fresh",work.state==3&&GetTickCount64()-work.observed<=60000));
            }
            var market=request.Required("marketId").GetUInt32();
            if(!FreshCommunityGoalDock(frame,market))throw new InvalidOperationException("Fresh healthy docking at the requested CG market required");
            var join=op=="cg.join";ulong goal=0;string? key=null;
            if(join)
            {
                key=request.Required("operationKey").GetString()!;
                if(!CommerceOperationKey(key))throw new InvalidOperationException("Identified CG signup required");
                if(communityGoalKeys.TryGetValue(key,out var old))return Obj(("generation",old),("duplicate",true));
                goal=request.Required("goalId").GetUInt64();
                var proof=request.Required("proof").GetString();var prior=communityGoalRequest;
                if(goal==0||goal>uint.MaxValue||communityGoalKeys.Count>=32
                    ||!CommunityGoalReadProofMatches(frame,prior,proof,request.Required("generation").GetUInt64(),GetTickCount64(),communityGoalBody))
                    throw new InvalidOperationException("Current original CG list proof required before signup");
            }
            if(communityGoalRequest.generation!=0&&communityGoalRequest.state<3)throw new InvalidOperationException("Original CG request already pending");
            var next=++communityGoalGeneration;
            communityGoalRequest=new(){generation=next,entity=frame.entity,life=frame.life,epoch=controllerEpoch,expires=GetTickCount64()+30000,queued=GetTickCount64(),
                market=market,state=1,kind=join?1u:op=="cg.read.mine"?2u:0u,goal=goal};communityGoalBody="";
            if(key is not null)communityGoalKeys.Add(key,next);
            return Obj(("generation",next),("queued",true),("mutationsSent",0));
        }
    }
}