using System.Globalization;
using System.Text.Json.Nodes;
using static XFEEDToolBox.Plugin.JsonWire;
namespace XFEEDToolBox.Plugin;
internal static unsafe partial class Navigation
{
static readonly int[] GalaxyRouteChoiceCategories=[2,3,4,6,7,8,10];
internal sealed record GalaxyRouteCategoryChoices(int categoryId,GalaxyRouteCheckboxChoice[]? choices,bool? affectsRoutePlotting);
internal sealed record GalaxyRouteChoices(ulong tick,ulong contextSystemAddress,GalaxyRouteCategoryChoices[] categories);
sealed partial record GalaxyCatalogueProfile {internal GalaxyRouteChoices? routeFilterChoices {get;init;}}
static GalaxyRouteChoices? CopyGalaxyCatalogueRouteChoices(Snapshot frame,GalaxyServices services)
{
try
{
if(!Enabled()||!inGame||!frame.valid||frame.entity==0||owningThread==0||GetCurrentThreadId()!=owningThread)return null;
var type=Read<uint>(image+0x5FDB224);var component=RegisteredComponent(services.registry,type);
if(!CopyGameRouteOptions(component,image,out var main,out _))return null;
var controller=Pointer(main+0x288);var result=new List<GalaxyRouteCategoryChoices>(7);
foreach(var category in GalaxyRouteChoiceCategories)
{
var copied=DiscoverGalaxyRouteCheckboxState(main,image,category,out var state)&&state is not null;
result.Add(new(category,copied?state!.choices:null,copied?state!.actualAffects:null));
}
var current=Current();
if(!current.valid||current.entity!=frame.entity||current.referenceWorld!=frame.referenceWorld||
Read<uint>(image+0x5FDB224)!=type||RegisteredComponent(services.registry,type)!=component||
!CopyGameRouteOptions(component,image,out var confirmed,out _)||confirmed!=main||Pointer(main+0x288)!=controller)return null;
return new(GetTickCount64(),frame.referenceWorld&0x007FFFFFFFFFFFFFUL,result.ToArray());
}
catch{return null;}
}
static JsonObject? GalaxyRouteChoicesDescription(GalaxyRouteChoices? source)
{
if(source is null)return null;
var categories=new JsonArray();var bytes=0;
foreach(var category in source.categories)
{
var rows=category.choices is null?null:new JsonArray(category.choices.Select(c=>(JsonNode?)Obj(("index",c.index),("settingsName",c.settingsName),("key",c.key),("selected",c.selected))).ToArray());
var row=Obj(("categoryId",category.categoryId),("choices",rows),("affectsRoutePlotting",category.affectsRoutePlotting));
var length=System.Text.Encoding.UTF8.GetByteCount(row.ToJsonString());
// Optional choices cannot overflow the profile's36k point page or
// defer basic LOD. A whole oversized category remains unknown.
if(bytes+length>12000)row=Obj(("categoryId",category.categoryId),("choices",null),("affectsRoutePlotting",null));
bytes+=System.Text.Encoding.UTF8.GetByteCount(row.ToJsonString());categories.Add((JsonNode)row);
}
return Obj(("scope","current-original-route-filter-choices"),("capturedAtTick",source.tick.ToString(CultureInfo.InvariantCulture)),
("contextSystemAddress",source.contextSystemAddress.ToString(CultureInfo.InvariantCulture)),("categories",categories));
}
}
using System.Globalization;
using System.Text.Json.Nodes;
using static XFEEDToolBox.Plugin.JsonWire;
namespace XFEEDToolBox.Plugin;
internal static unsafe partial class Navigation
{
static readonly int[] GalaxyRouteChoiceCategories=[2,3,4,6,7,8,10];
internal sealed record GalaxyRouteCategoryChoices(int categoryId,GalaxyRouteCheckboxChoice[]? choices,bool? affectsRoutePlotting);
internal sealed record GalaxyRouteChoices(ulong tick,ulong contextSystemAddress,GalaxyRouteCategoryChoices[] categories);
sealed partial record GalaxyCatalogueProfile {internal GalaxyRouteChoices? routeFilterChoices {get;init;}}
static GalaxyRouteChoices? CopyGalaxyCatalogueRouteChoices(Snapshot frame,GalaxyServices services)
{
try
{
if(!Enabled()||!inGame||!frame.valid||frame.entity==0||owningThread==0||GetCurrentThreadId()!=owningThread)return null;
var type=Read<uint>(image+0x5FDB224);var component=RegisteredComponent(services.registry,type);
if(!CopyGameRouteOptions(component,image,out var main,out _))return null;
var controller=Pointer(main+0x288);var result=new List<GalaxyRouteCategoryChoices>(7);
foreach(var category in GalaxyRouteChoiceCategories)
{
var copied=DiscoverGalaxyRouteCheckboxState(main,image,category,out var state)&&state is not null;
result.Add(new(category,copied?state!.choices:null,copied?state!.actualAffects:null));
}
var current=Current();
if(!current.valid||current.entity!=frame.entity||current.referenceWorld!=frame.referenceWorld||
Read<uint>(image+0x5FDB224)!=type||RegisteredComponent(services.registry,type)!=component||
!CopyGameRouteOptions(component,image,out var confirmed,out _)||confirmed!=main||Pointer(main+0x288)!=controller)return null;
return new(GetTickCount64(),frame.referenceWorld&0x007FFFFFFFFFFFFFUL,result.ToArray());
}
catch{return null;}
}
static JsonObject? GalaxyRouteChoicesDescription(GalaxyRouteChoices? source)
{
if(source is null)return null;
var categories=new JsonArray();var bytes=0;
foreach(var category in source.categories)
{
var rows=category.choices is null?null:new JsonArray(category.choices.Select(c=>(JsonNode?)Obj(("index",c.index),("settingsName",c.settingsName),("key",c.key),("selected",c.selected))).ToArray());
var row=Obj(("categoryId",category.categoryId),("choices",rows),("affectsRoutePlotting",category.affectsRoutePlotting));
var length=System.Text.Encoding.UTF8.GetByteCount(row.ToJsonString());
// Optional choices cannot overflow the profile's36k point page or
// defer basic LOD. A whole oversized category remains unknown.
if(bytes+length>12000)row=Obj(("categoryId",category.categoryId),("choices",null),("affectsRoutePlotting",null));
bytes+=System.Text.Encoding.UTF8.GetByteCount(row.ToJsonString());categories.Add((JsonNode)row);
}
return Obj(("scope","current-original-route-filter-choices"),("capturedAtTick",source.tick.ToString(CultureInfo.InvariantCulture)),
("contextSystemAddress",source.contextSystemAddress.ToString(CultureInfo.InvariantCulture)),("categories",categories));
}
}