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;}
}
}
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;}
}
}