namespace XFEEDToolBox.Plugin;
internal static unsafe partial class Navigation
{
internal readonly record struct GalaxyRouteStarClassState(nuint mapController,nuint provider,uint mask);
static bool ValidGalaxyRouteStarMask(uint mask)=>(mask&~0xFFFFu)==0;
// Same packed mask as original3B17970, copied without invoking its
// iterator bookkeeping. Fifteen actual rows and the independent final
// route checkbox are required; no future/missing row is guessed.
static bool CopyGalaxyRouteStarClassState(nuint main,nuint expectedImage,out GalaxyRouteStarClassState result)
{
result=default;
try
{
if(main<0x10000||Pointer(main)!=expectedImage+0x551FFC0||
Pointer(expectedImage+0x551FFC0+0x78)!=expectedImage+0x3A68F60||Read<int>(main+0x280)!=-1)return false;
var type=Pointer(main+0x288);if(type<0x10028||Pointer(type)!=expectedImage+0x552D788)return false;
var controller=type-0x28;
if(Pointer(controller)!=expectedImage+0x552D5C0||Pointer(expectedImage+0x552D5C0+0x40)!=expectedImage+0x3B45E30)return false;
// Original3B16B00's case5 shared handle is at owner388/390;
// controller is owner+58, so its members are330/338.
var block=Pointer(controller+0x330);var provider=Pointer(controller+0x338);
if(block<0x10000||Read<int>(block+8)<=0||Read<int>(block+0xC)<=0||provider<0x10000||
Pointer(provider)!=expectedImage+0x552E100||Pointer(expectedImage+0x552E100+0x28)!=expectedImage+0x3B8BA80||
Pointer(expectedImage+0x552E100+0x30)!=expectedImage+0x3B178D0||Read<int>(provider+0x60)!=5||Read<byte>(provider+0x80)!=1)return false;
var count=Read<ulong>(provider+0x90);var capacity=Read<ulong>(provider+0x98);var storage=Pointer(provider+0xA0);
var affects=Read<byte>(provider+0x81);
if(count!=15||capacity is <16 or >256||(capacity&(capacity-1))!=0||storage<0x10000||affects>1)return false;
var values=new List<(nuint at,uint index,byte selected)>();var bitmaps=new List<(nuint at,ulong bits)>();
var rows=storage+(nuint)(((capacity>>3)+7)&~7UL);uint seen=0,mask=0;var occupied=0;
for(ulong bucket=0;bucket<capacity;bucket++)
{
var at=storage+(nuint)(bucket>>6)*8;var bits=Read<ulong>(at);
if((bucket&63)==0)bitmaps.Add((at,bits));
if((bits&(1UL<<(int)(bucket&63)))==0)continue;
var row=rows+(nuint)bucket*0x38;var index=Read<uint>(row+8);var selected=Read<byte>(row+0x30);
if(index>=15||selected>1||(seen&(1u<<(int)index))!=0)return false;
seen|=1u<<(int)index;if(selected!=0)mask|=1u<<(int)index;
values.Add((row,index,selected));occupied++;
}
if(occupied!=15||seen!=0x7FFF||Pointer(main)!=expectedImage+0x551FFC0||Read<int>(main+0x280)!=-1||
Pointer(main+0x288)!=type||Pointer(type)!=expectedImage+0x552D788||Pointer(controller)!=expectedImage+0x552D5C0||
Pointer(controller+0x330)!=block||Pointer(controller+0x338)!=provider||Read<int>(block+8)<=0||Read<int>(block+0xC)<=0||
Pointer(provider)!=expectedImage+0x552E100||Read<int>(provider+0x60)!=5||Read<byte>(provider+0x80)!=1||
Read<byte>(provider+0x81)!=affects||Read<ulong>(provider+0x90)!=count||Read<ulong>(provider+0x98)!=capacity||Pointer(provider+0xA0)!=storage||
bitmaps.Any(v=>Read<ulong>(v.at)!=v.bits)||values.Any(v=>Read<uint>(v.at+8)!=v.index||Read<byte>(v.at+0x30)!=v.selected))return false;
if(affects!=0)mask|=1u<<15;
result=new(controller,provider,mask);return true;
}
catch{return false;}
}
// Called only by the original route queue on its verified owning thread.
// This is the actual original Map UI action, not direct settings writes.
// The display category/checkboxes change just as they do in that UI.
static bool ApplyGalaxyStarClassRouteFilter(Snapshot frame,uint mask)
{
if(!ValidGalaxyRouteStarMask(mask)||!Enabled()||!inGame||!frame.valid||frame.entity==0||
owningThread==0||GetCurrentThreadId()!=owningThread||!FindGalaxyServices(frame,out var services))return false;
try
{
var type=Read<uint>(image+0x5FDB224);var component=RegisteredComponent(services.registry,type);
if(!CopyGameRouteOptions(component,image,out var main,out _)||!CopyGalaxyRouteStarClassState(main,image,out var before))return false;
var current=Current();if(!current.valid||current.entity!=frame.entity||current.referenceWorld!=frame.referenceWorld||
Read<uint>(image+0x5FDB224)!=type||RegisteredComponent(services.registry,type)!=component)return false;
((delegate* unmanaged<nuint,uint,uint,void>)(image+0x3A68F60))(main,5,mask);
current=Current();
return current.valid&¤t.entity==frame.entity&¤t.referenceWorld==frame.referenceWorld&&
Read<uint>(image+0x5FDB224)==type&&RegisteredComponent(services.registry,type)==component&&
CopyGameRouteOptions(component,image,out var afterMain,out _)&&afterMain==main&&
CopyGalaxyRouteStarClassState(main,image,out var after)&&after.mapController==before.mapController&&
after.provider==before.provider&&after.mask==mask;
}
catch{return false;}
}
}
namespace XFEEDToolBox.Plugin;
internal static unsafe partial class Navigation
{
internal readonly record struct GalaxyRouteStarClassState(nuint mapController,nuint provider,uint mask);
static bool ValidGalaxyRouteStarMask(uint mask)=>(mask&~0xFFFFu)==0;
// Same packed mask as original3B17970, copied without invoking its
// iterator bookkeeping. Fifteen actual rows and the independent final
// route checkbox are required; no future/missing row is guessed.
static bool CopyGalaxyRouteStarClassState(nuint main,nuint expectedImage,out GalaxyRouteStarClassState result)
{
result=default;
try
{
if(main<0x10000||Pointer(main)!=expectedImage+0x551FFC0||
Pointer(expectedImage+0x551FFC0+0x78)!=expectedImage+0x3A68F60||Read<int>(main+0x280)!=-1)return false;
var type=Pointer(main+0x288);if(type<0x10028||Pointer(type)!=expectedImage+0x552D788)return false;
var controller=type-0x28;
if(Pointer(controller)!=expectedImage+0x552D5C0||Pointer(expectedImage+0x552D5C0+0x40)!=expectedImage+0x3B45E30)return false;
// Original3B16B00's case5 shared handle is at owner388/390;
// controller is owner+58, so its members are330/338.
var block=Pointer(controller+0x330);var provider=Pointer(controller+0x338);
if(block<0x10000||Read<int>(block+8)<=0||Read<int>(block+0xC)<=0||provider<0x10000||
Pointer(provider)!=expectedImage+0x552E100||Pointer(expectedImage+0x552E100+0x28)!=expectedImage+0x3B8BA80||
Pointer(expectedImage+0x552E100+0x30)!=expectedImage+0x3B178D0||Read<int>(provider+0x60)!=5||Read<byte>(provider+0x80)!=1)return false;
var count=Read<ulong>(provider+0x90);var capacity=Read<ulong>(provider+0x98);var storage=Pointer(provider+0xA0);
var affects=Read<byte>(provider+0x81);
if(count!=15||capacity is <16 or >256||(capacity&(capacity-1))!=0||storage<0x10000||affects>1)return false;
var values=new List<(nuint at,uint index,byte selected)>();var bitmaps=new List<(nuint at,ulong bits)>();
var rows=storage+(nuint)(((capacity>>3)+7)&~7UL);uint seen=0,mask=0;var occupied=0;
for(ulong bucket=0;bucket<capacity;bucket++)
{
var at=storage+(nuint)(bucket>>6)*8;var bits=Read<ulong>(at);
if((bucket&63)==0)bitmaps.Add((at,bits));
if((bits&(1UL<<(int)(bucket&63)))==0)continue;
var row=rows+(nuint)bucket*0x38;var index=Read<uint>(row+8);var selected=Read<byte>(row+0x30);
if(index>=15||selected>1||(seen&(1u<<(int)index))!=0)return false;
seen|=1u<<(int)index;if(selected!=0)mask|=1u<<(int)index;
values.Add((row,index,selected));occupied++;
}
if(occupied!=15||seen!=0x7FFF||Pointer(main)!=expectedImage+0x551FFC0||Read<int>(main+0x280)!=-1||
Pointer(main+0x288)!=type||Pointer(type)!=expectedImage+0x552D788||Pointer(controller)!=expectedImage+0x552D5C0||
Pointer(controller+0x330)!=block||Pointer(controller+0x338)!=provider||Read<int>(block+8)<=0||Read<int>(block+0xC)<=0||
Pointer(provider)!=expectedImage+0x552E100||Read<int>(provider+0x60)!=5||Read<byte>(provider+0x80)!=1||
Read<byte>(provider+0x81)!=affects||Read<ulong>(provider+0x90)!=count||Read<ulong>(provider+0x98)!=capacity||Pointer(provider+0xA0)!=storage||
bitmaps.Any(v=>Read<ulong>(v.at)!=v.bits)||values.Any(v=>Read<uint>(v.at+8)!=v.index||Read<byte>(v.at+0x30)!=v.selected))return false;
if(affects!=0)mask|=1u<<15;
result=new(controller,provider,mask);return true;
}
catch{return false;}
}
// Called only by the original route queue on its verified owning thread.
// This is the actual original Map UI action, not direct settings writes.
// The display category/checkboxes change just as they do in that UI.
static bool ApplyGalaxyStarClassRouteFilter(Snapshot frame,uint mask)
{
if(!ValidGalaxyRouteStarMask(mask)||!Enabled()||!inGame||!frame.valid||frame.entity==0||
owningThread==0||GetCurrentThreadId()!=owningThread||!FindGalaxyServices(frame,out var services))return false;
try
{
var type=Read<uint>(image+0x5FDB224);var component=RegisteredComponent(services.registry,type);
if(!CopyGameRouteOptions(component,image,out var main,out _)||!CopyGalaxyRouteStarClassState(main,image,out var before))return false;
var current=Current();if(!current.valid||current.entity!=frame.entity||current.referenceWorld!=frame.referenceWorld||
Read<uint>(image+0x5FDB224)!=type||RegisteredComponent(services.registry,type)!=component)return false;
((delegate* unmanaged<nuint,uint,uint,void>)(image+0x3A68F60))(main,5,mask);
current=Current();
return current.valid&¤t.entity==frame.entity&¤t.referenceWorld==frame.referenceWorld&&
Read<uint>(image+0x5FDB224)==type&&RegisteredComponent(services.registry,type)==component&&
CopyGameRouteOptions(component,image,out var afterMain,out _)&&afterMain==main&&
CopyGalaxyRouteStarClassState(main,image,out var after)&&after.mapController==before.mapController&&
after.provider==before.provider&&after.mask==mask;
}
catch{return false;}
}
}