using System.Buffers.Binary;
using System.Globalization;
using System.Text.Json.Nodes;
using static XFEEDToolBox.Plugin.JsonWire;
namespace XFEEDToolBox.Plugin;
internal static unsafe partial class Navigation
{
internal sealed record GalaxyColonisationHighlight(ulong centreSystemAddress,int eligibilityStatus,float distanceSquared,float radiusSquared,float[] rawRgb);
// 3B428E0 subtracts independently decoded float coordinates, not world
// doubles relative to the catalogue origin. Preserve that rounding/order.
static bool GalaxyColonisationRawPosition(byte[] compact,ulong address,out float x,out float y,out float z)
{
x=y=z=0;if(compact.Length!=0x48||address==0||address>=1UL<<55||BinaryPrimitives.ReadUInt64LittleEndian(compact)!=address)return false;
var m=(int)(address&7);
x=(float)((((address>>(30-2*m))<<m)&0x3FFF)*320+BinaryPrimitives.ReadUInt16LittleEndian(compact.AsSpan(0x42)))*.03125f;
y=(float)((((address>>(17-m))<<m)&0x1FFF)*320+BinaryPrimitives.ReadUInt16LittleEndian(compact.AsSpan(0x44)))*.03125f;
z=(float)((((address>>3)<<m)&0x3FFF)*320+BinaryPrimitives.ReadUInt16LittleEndian(compact.AsSpan(0x46)))*.03125f;
return true;
}
static bool CopyGalaxyColonisationHighlight(nuint provider,nuint navigation,nuint candidate,nuint expectedImage,ulong address,int eligibilityStatus,out GalaxyColonisationHighlight? result)
{
result=null;if(provider<0x10000||candidate<0x10000||eligibilityStatus is <0 or >11)return false;
try
{
var table=expectedImage+0x552D920;
if(Pointer(provider)!=table||Pointer(table+0x20)!=expectedImage+0x3B3E650||Pointer(table+0x50)!=expectedImage+0x3B26B30||
Pointer(provider+0x160)!=navigation)return false;
var centreSlot=GalaxyPowerOuterCentreSlot(navigation,expectedImage);if(centreSlot==0)return false;
var centre=Pointer(provider+0x178);
// An absent/pending cached navigation object supplies no verified
// centre. Do not turn its absence into a fabricated galaxy origin.
if(centre<0x10000||Pointer(centreSlot)!=centre||Read<uint>(centre+0x20)!=2||!GalaxyColonisationLoadedObject(candidate,address))return false;
var centreAddress=Read<ulong>(centre+0x28);var centreCompact=Pointer(centre+0x38);var candidateCompact=Pointer(candidate+0x38);
if(centreCompact<0x10000||candidateCompact<0x10000)return false;
var centreBytes=Platform.ReadBytes(centreCompact,0x48);var candidateBytes=Platform.ReadBytes(candidateCompact,0x48);
if(!GalaxyColonisationRawPosition(centreBytes,centreAddress,out var cx,out var cy,out var cz)||
!GalaxyColonisationRawPosition(candidateBytes,address,out var x,out var y,out var z))return false;
var radius=Read<float>(provider+0x1A0);var colour=Platform.ReadBytes(provider+0x11C,12);
if(!float.IsFinite(radius)||radius<0||colour.Length!=12)return false;
var rgb=new float[3];for(var i=0;i<3;i++){rgb[i]=BinaryPrimitives.ReadSingleLittleEndian(colour.AsSpan(i*4));if(!float.IsFinite(rgb[i])||rgb[i]<0)return false;}
var dx=x-cx;var dy=y-cy;var dz=z-cz;var distance=(dx*dx+dy*dy)+dz*dz;
if(!float.IsFinite(distance)||Pointer(provider)!=table||Pointer(provider+0x160)!=navigation||Pointer(provider+0x178)!=centre||
GalaxyPowerOuterCentreSlot(navigation,expectedImage)!=centreSlot||Pointer(centreSlot)!=centre||Read<uint>(centre+0x20)!=2||
Read<ulong>(centre+0x28)!=centreAddress||Pointer(centre+0x38)!=centreCompact||!GalaxyColonisationLoadedObject(candidate,address)||
Pointer(candidate+0x38)!=candidateCompact||Read<float>(provider+0x1A0)!=radius||
!Platform.ReadBytes(provider+0x11C,12).AsSpan().SequenceEqual(colour)||
!Platform.ReadBytes(centreCompact,0x48).AsSpan().SequenceEqual(centreBytes)||
!Platform.ReadBytes(candidateCompact,0x48).AsSpan().SequenceEqual(candidateBytes))return false;
result=new(centreAddress,eligibilityStatus,distance,radius,rgb);return true;
}
catch{result=null;return false;}
}
static bool TryReadGalaxyColonisationHighlight(GalaxyFilterContext context,GalaxyServices services,nuint candidate,ulong address,int eligibilityStatus,out GalaxyColonisationHighlight? result)
{
result=null;
if(context.expectedImage!=image||context.thread==0||context.thread!=owningThread||GetCurrentThreadId()!=context.thread||
GetTickCount64()-context.tick>500||services.registry<0x10000)return false;
try
{
var mainComponent=RegisteredComponent(services.registry,Read<uint>(image+0x5FDB224));
var navigation=RegisteredComponent(services.registry,Read<uint>(image+0x5F05DD4));
if(!CopyGameRouteOptions(mainComponent,image,out var main,out _)||Read<int>(main+0x280)!=-1)return false;
var type=Pointer(main+0x288);if(type<0x10028||Pointer(type)!=image+0x552D788)return false;
var controller=type-0x28;if(Pointer(controller)!=image+0x552D5C0)return false;
var block=Pointer(controller+0x3D0);var provider=Pointer(controller+0x3D8);
if(block<0x10000||Read<int>(block+8)<=0||Read<int>(block+0xC)<=0||
!CopyGalaxyColonisationHighlight(provider,navigation,candidate,image,address,eligibilityStatus,out var copied))return false;
var frame=Current();
if(!frame.valid||frame.entity!=context.entity||(frame.referenceWorld&0x007FFFFFFFFFFFFFUL)!=context.currentSystem||
RegisteredComponent(services.registry,Read<uint>(image+0x5FDB224))!=mainComponent||
RegisteredComponent(services.registry,Read<uint>(image+0x5F05DD4))!=navigation||
!CopyGameRouteOptions(mainComponent,image,out var confirmed,out _)||confirmed!=main||Read<int>(main+0x280)!=-1||
Pointer(main+0x288)!=type||Pointer(type)!=image+0x552D788||Pointer(controller)!=image+0x552D5C0||
Pointer(controller+0x3D0)!=block||Pointer(controller+0x3D8)!=provider||Read<int>(block+8)<=0||Read<int>(block+0xC)<=0)return false;
result=copied;return true;
}
catch{result=null;return false;}
}
static JsonObject? GalaxyColonisationHighlightDescription(GalaxyColonisationHighlight? value)=>value is null?null:Obj(
("source","original-colonisation-highlight"),("centreSystemAddress",value.centreSystemAddress.ToString(CultureInfo.InvariantCulture)),
("eligibilityStatus",value.eligibilityStatus),("distanceSquared",value.distanceSquared),("radiusSquared",value.radiusSquared),
("rawRgb",new JsonArray(value.rawRgb.Select(v=>(JsonNode?)JsonValue.Create(v)).ToArray())));
}
using System.Buffers.Binary;
using System.Globalization;
using System.Text.Json.Nodes;
using static XFEEDToolBox.Plugin.JsonWire;
namespace XFEEDToolBox.Plugin;
internal static unsafe partial class Navigation
{
internal sealed record GalaxyColonisationHighlight(ulong centreSystemAddress,int eligibilityStatus,float distanceSquared,float radiusSquared,float[] rawRgb);
// 3B428E0 subtracts independently decoded float coordinates, not world
// doubles relative to the catalogue origin. Preserve that rounding/order.
static bool GalaxyColonisationRawPosition(byte[] compact,ulong address,out float x,out float y,out float z)
{
x=y=z=0;if(compact.Length!=0x48||address==0||address>=1UL<<55||BinaryPrimitives.ReadUInt64LittleEndian(compact)!=address)return false;
var m=(int)(address&7);
x=(float)((((address>>(30-2*m))<<m)&0x3FFF)*320+BinaryPrimitives.ReadUInt16LittleEndian(compact.AsSpan(0x42)))*.03125f;
y=(float)((((address>>(17-m))<<m)&0x1FFF)*320+BinaryPrimitives.ReadUInt16LittleEndian(compact.AsSpan(0x44)))*.03125f;
z=(float)((((address>>3)<<m)&0x3FFF)*320+BinaryPrimitives.ReadUInt16LittleEndian(compact.AsSpan(0x46)))*.03125f;
return true;
}
static bool CopyGalaxyColonisationHighlight(nuint provider,nuint navigation,nuint candidate,nuint expectedImage,ulong address,int eligibilityStatus,out GalaxyColonisationHighlight? result)
{
result=null;if(provider<0x10000||candidate<0x10000||eligibilityStatus is <0 or >11)return false;
try
{
var table=expectedImage+0x552D920;
if(Pointer(provider)!=table||Pointer(table+0x20)!=expectedImage+0x3B3E650||Pointer(table+0x50)!=expectedImage+0x3B26B30||
Pointer(provider+0x160)!=navigation)return false;
var centreSlot=GalaxyPowerOuterCentreSlot(navigation,expectedImage);if(centreSlot==0)return false;
var centre=Pointer(provider+0x178);
// An absent/pending cached navigation object supplies no verified
// centre. Do not turn its absence into a fabricated galaxy origin.
if(centre<0x10000||Pointer(centreSlot)!=centre||Read<uint>(centre+0x20)!=2||!GalaxyColonisationLoadedObject(candidate,address))return false;
var centreAddress=Read<ulong>(centre+0x28);var centreCompact=Pointer(centre+0x38);var candidateCompact=Pointer(candidate+0x38);
if(centreCompact<0x10000||candidateCompact<0x10000)return false;
var centreBytes=Platform.ReadBytes(centreCompact,0x48);var candidateBytes=Platform.ReadBytes(candidateCompact,0x48);
if(!GalaxyColonisationRawPosition(centreBytes,centreAddress,out var cx,out var cy,out var cz)||
!GalaxyColonisationRawPosition(candidateBytes,address,out var x,out var y,out var z))return false;
var radius=Read<float>(provider+0x1A0);var colour=Platform.ReadBytes(provider+0x11C,12);
if(!float.IsFinite(radius)||radius<0||colour.Length!=12)return false;
var rgb=new float[3];for(var i=0;i<3;i++){rgb[i]=BinaryPrimitives.ReadSingleLittleEndian(colour.AsSpan(i*4));if(!float.IsFinite(rgb[i])||rgb[i]<0)return false;}
var dx=x-cx;var dy=y-cy;var dz=z-cz;var distance=(dx*dx+dy*dy)+dz*dz;
if(!float.IsFinite(distance)||Pointer(provider)!=table||Pointer(provider+0x160)!=navigation||Pointer(provider+0x178)!=centre||
GalaxyPowerOuterCentreSlot(navigation,expectedImage)!=centreSlot||Pointer(centreSlot)!=centre||Read<uint>(centre+0x20)!=2||
Read<ulong>(centre+0x28)!=centreAddress||Pointer(centre+0x38)!=centreCompact||!GalaxyColonisationLoadedObject(candidate,address)||
Pointer(candidate+0x38)!=candidateCompact||Read<float>(provider+0x1A0)!=radius||
!Platform.ReadBytes(provider+0x11C,12).AsSpan().SequenceEqual(colour)||
!Platform.ReadBytes(centreCompact,0x48).AsSpan().SequenceEqual(centreBytes)||
!Platform.ReadBytes(candidateCompact,0x48).AsSpan().SequenceEqual(candidateBytes))return false;
result=new(centreAddress,eligibilityStatus,distance,radius,rgb);return true;
}
catch{result=null;return false;}
}
static bool TryReadGalaxyColonisationHighlight(GalaxyFilterContext context,GalaxyServices services,nuint candidate,ulong address,int eligibilityStatus,out GalaxyColonisationHighlight? result)
{
result=null;
if(context.expectedImage!=image||context.thread==0||context.thread!=owningThread||GetCurrentThreadId()!=context.thread||
GetTickCount64()-context.tick>500||services.registry<0x10000)return false;
try
{
var mainComponent=RegisteredComponent(services.registry,Read<uint>(image+0x5FDB224));
var navigation=RegisteredComponent(services.registry,Read<uint>(image+0x5F05DD4));
if(!CopyGameRouteOptions(mainComponent,image,out var main,out _)||Read<int>(main+0x280)!=-1)return false;
var type=Pointer(main+0x288);if(type<0x10028||Pointer(type)!=image+0x552D788)return false;
var controller=type-0x28;if(Pointer(controller)!=image+0x552D5C0)return false;
var block=Pointer(controller+0x3D0);var provider=Pointer(controller+0x3D8);
if(block<0x10000||Read<int>(block+8)<=0||Read<int>(block+0xC)<=0||
!CopyGalaxyColonisationHighlight(provider,navigation,candidate,image,address,eligibilityStatus,out var copied))return false;
var frame=Current();
if(!frame.valid||frame.entity!=context.entity||(frame.referenceWorld&0x007FFFFFFFFFFFFFUL)!=context.currentSystem||
RegisteredComponent(services.registry,Read<uint>(image+0x5FDB224))!=mainComponent||
RegisteredComponent(services.registry,Read<uint>(image+0x5F05DD4))!=navigation||
!CopyGameRouteOptions(mainComponent,image,out var confirmed,out _)||confirmed!=main||Read<int>(main+0x280)!=-1||
Pointer(main+0x288)!=type||Pointer(type)!=image+0x552D788||Pointer(controller)!=image+0x552D5C0||
Pointer(controller+0x3D0)!=block||Pointer(controller+0x3D8)!=provider||Read<int>(block+8)<=0||Read<int>(block+0xC)<=0)return false;
result=copied;return true;
}
catch{result=null;return false;}
}
static JsonObject? GalaxyColonisationHighlightDescription(GalaxyColonisationHighlight? value)=>value is null?null:Obj(
("source","original-colonisation-highlight"),("centreSystemAddress",value.centreSystemAddress.ToString(CultureInfo.InvariantCulture)),
("eligibilityStatus",value.eligibilityStatus),("distanceSquared",value.distanceSquared),("radiusSquared",value.radiusSquared),
("rawRgb",new JsonArray(value.rawRgb.Select(v=>(JsonNode?)JsonValue.Create(v)).ToArray())));
}