namespace XFEEDToolBox.Plugin;
internal static unsafe partial class Navigation
{
// Current ED5A addresses, paired with the old actual provider ctor and
// typed lookup slots in allegiance-definitions/compatibility.json.
static bool GalaxyAllegianceSource(nuint source,nuint expectedImage)
{
if(source<0x10058)return false;
var table=Pointer(source);
return table==expectedImage+0x51BBA70&&Pointer(source-0x58)==expectedImage+0x51BB940&&
Pointer(source-0x50)==expectedImage+0x51BB970&&Pointer(source+8)==expectedImage+0x51BBB60&&
Pointer(table)==expectedImage+0x140EA90&&Pointer(table+0x18)==expectedImage+0x140F240&&
Pointer(table+0x20)==expectedImage+0x140EC60&&Pointer(table+0x48)==expectedImage+0x1410000&&
Pointer(table+0x50)==expectedImage+0x140FE60;
}
static uint GalaxyAllegianceLegacyHash(uint id)
{
unchecked
{
var hash=id*0x1001;hash=((hash>>22)^hash)*0x11;hash=((hash>>9)^hash)*0x401;
hash=((hash>>2)^hash)*0x81;return hash^(hash>>12);
}
}
static bool GalaxyAllegianceFindLegacy(nuint map,ulong id,out nuint found)
{
found=0;var buckets=Pointer(map);var capacity=Read<ulong>(map+8);var count=Read<ulong>(map+0x18);
if(buckets<0x10000||capacity==0||capacity>1_048_576||count>4_000_000)return false;
if(count>0)
{
var sentinel=buckets+(nuint)(GalaxyAllegianceLegacyHash((uint)id)%capacity)*8;var node=Pointer(sentinel);
var maximum=(int)Math.Min(count,256);var ended=false;
for(var step=0;step<=maximum;step++)
{
if(node==sentinel){ended=true;break;}
if(step==maximum||node<0x10000)return false;
if(Read<uint>(node+8)==(uint)id){found=node;ended=true;break;}
var next=Pointer(node);if(next==node)return false;node=next;
}
if(!ended)return false;
}
return Pointer(map)==buckets&&Read<ulong>(map+8)==capacity&&Read<ulong>(map+0x18)==count;
}
static bool FindGalaxyAllegianceDefinition(nuint source,ulong id,out nuint node)
{
node=0;
foreach(var offset in new nuint[]{0x80,0xA8,0xC8,0xE8,0x108})
{
if(!GalaxyFactFindHash(source+offset,id,out node))return false;
if(node!=0)return true;
}
return GalaxyAllegianceFindLegacy(source+0x128,id,out node);
}
static bool CopyGalaxyAllegianceKey(nuint source,nuint expectedImage,ulong id,out string? key)
{
key=null;
try
{
if(!GalaxyAllegianceSource(source,expectedImage))return false;
// Original3AC56A0 inserts exactly this sentinel under None. Other
// unresolved IDs are never converted to None; 140F320 rejects Max.
if(id==ulong.MaxValue){key="None";return true;}
if(!FindGalaxyAllegianceDefinition(source,id,out var node))return false;
if(node==0)return true;
var control=Pointer(node+0x10);var definition=Pointer(node+0x18);
if(control<0x10000||definition<0x10000||Read<int>(control+0xC)<=0)return true;
var valid=Read<byte>(definition+0x18);if(valid==0||Read<ulong>(definition)!=id)return true;
var text=Pointer(definition+8);if(text<0x10000||Read<int>(text+0x10)<=0)return true;
var length=Read<ulong>(text);var capacity=Read<ulong>(text+8);
if(length is <1 or >64||capacity<length||capacity>1048576||!GalaxyCString(text+20,(int)length+1,out var candidate)||candidate.Length!=(int)length)return true;
// These are the actual authored allegiance filter keys. Other
// faction names may share this service but are not an allegiance.
if(candidate is not("None" or "Federation" or "Empire" or "Alliance" or "Independent"))return true;
if(!GalaxyAllegianceSource(source,expectedImage)||!FindGalaxyAllegianceDefinition(source,id,out var confirmed)||confirmed!=node||
Pointer(node+0x10)!=control||Pointer(node+0x18)!=definition||Read<int>(control+0xC)<=0||
Read<ulong>(definition)!=id||Read<byte>(definition+0x18)!=valid||Pointer(definition+8)!=text||
Read<ulong>(text)!=length||Read<ulong>(text+8)!=capacity||Read<int>(text+0x10)<=0||
!GalaxyCString(text+20,(int)length+1,out var reread)||reread!=candidate)return false;
key=candidate;return true;
}
catch{key=null;return false;}
}
static bool TryReadGalaxyAllegianceKey(GalaxyFilterContext context,nuint registry,ulong id,out string? key)
{
key=null;
if(!Enabled()||!inGame||context.expectedImage!=image||context.thread==0||context.thread!=owningThread||
GetCurrentThreadId()!=context.thread||GetTickCount64()-context.tick>500||registry<0x10000)return false;
var frame=Current();
if(!frame.valid||frame.entity!=context.entity||(frame.referenceWorld&0x007FFFFFFFFFFFFFUL)!=context.currentSystem)return false;
try
{
var type=Read<uint>(image+0x5F05E6C);var source=RegisteredComponent(registry,type);
if(!CopyGalaxyAllegianceKey(source,image,id,out var value))return false;
if(Read<uint>(image+0x5F05E6C)!=type||RegisteredComponent(registry,type)!=source)return false;
var current=Current();if(!current.valid||current.entity!=frame.entity||(current.referenceWorld&0x007FFFFFFFFFFFFFUL)!=context.currentSystem)return false;
key=value;return true;
}
catch{return false;}
}
}
namespace XFEEDToolBox.Plugin;
internal static unsafe partial class Navigation
{
// Current ED5A addresses, paired with the old actual provider ctor and
// typed lookup slots in allegiance-definitions/compatibility.json.
static bool GalaxyAllegianceSource(nuint source,nuint expectedImage)
{
if(source<0x10058)return false;
var table=Pointer(source);
return table==expectedImage+0x51BBA70&&Pointer(source-0x58)==expectedImage+0x51BB940&&
Pointer(source-0x50)==expectedImage+0x51BB970&&Pointer(source+8)==expectedImage+0x51BBB60&&
Pointer(table)==expectedImage+0x140EA90&&Pointer(table+0x18)==expectedImage+0x140F240&&
Pointer(table+0x20)==expectedImage+0x140EC60&&Pointer(table+0x48)==expectedImage+0x1410000&&
Pointer(table+0x50)==expectedImage+0x140FE60;
}
static uint GalaxyAllegianceLegacyHash(uint id)
{
unchecked
{
var hash=id*0x1001;hash=((hash>>22)^hash)*0x11;hash=((hash>>9)^hash)*0x401;
hash=((hash>>2)^hash)*0x81;return hash^(hash>>12);
}
}
static bool GalaxyAllegianceFindLegacy(nuint map,ulong id,out nuint found)
{
found=0;var buckets=Pointer(map);var capacity=Read<ulong>(map+8);var count=Read<ulong>(map+0x18);
if(buckets<0x10000||capacity==0||capacity>1_048_576||count>4_000_000)return false;
if(count>0)
{
var sentinel=buckets+(nuint)(GalaxyAllegianceLegacyHash((uint)id)%capacity)*8;var node=Pointer(sentinel);
var maximum=(int)Math.Min(count,256);var ended=false;
for(var step=0;step<=maximum;step++)
{
if(node==sentinel){ended=true;break;}
if(step==maximum||node<0x10000)return false;
if(Read<uint>(node+8)==(uint)id){found=node;ended=true;break;}
var next=Pointer(node);if(next==node)return false;node=next;
}
if(!ended)return false;
}
return Pointer(map)==buckets&&Read<ulong>(map+8)==capacity&&Read<ulong>(map+0x18)==count;
}
static bool FindGalaxyAllegianceDefinition(nuint source,ulong id,out nuint node)
{
node=0;
foreach(var offset in new nuint[]{0x80,0xA8,0xC8,0xE8,0x108})
{
if(!GalaxyFactFindHash(source+offset,id,out node))return false;
if(node!=0)return true;
}
return GalaxyAllegianceFindLegacy(source+0x128,id,out node);
}
static bool CopyGalaxyAllegianceKey(nuint source,nuint expectedImage,ulong id,out string? key)
{
key=null;
try
{
if(!GalaxyAllegianceSource(source,expectedImage))return false;
// Original3AC56A0 inserts exactly this sentinel under None. Other
// unresolved IDs are never converted to None; 140F320 rejects Max.
if(id==ulong.MaxValue){key="None";return true;}
if(!FindGalaxyAllegianceDefinition(source,id,out var node))return false;
if(node==0)return true;
var control=Pointer(node+0x10);var definition=Pointer(node+0x18);
if(control<0x10000||definition<0x10000||Read<int>(control+0xC)<=0)return true;
var valid=Read<byte>(definition+0x18);if(valid==0||Read<ulong>(definition)!=id)return true;
var text=Pointer(definition+8);if(text<0x10000||Read<int>(text+0x10)<=0)return true;
var length=Read<ulong>(text);var capacity=Read<ulong>(text+8);
if(length is <1 or >64||capacity<length||capacity>1048576||!GalaxyCString(text+20,(int)length+1,out var candidate)||candidate.Length!=(int)length)return true;
// These are the actual authored allegiance filter keys. Other
// faction names may share this service but are not an allegiance.
if(candidate is not("None" or "Federation" or "Empire" or "Alliance" or "Independent"))return true;
if(!GalaxyAllegianceSource(source,expectedImage)||!FindGalaxyAllegianceDefinition(source,id,out var confirmed)||confirmed!=node||
Pointer(node+0x10)!=control||Pointer(node+0x18)!=definition||Read<int>(control+0xC)<=0||
Read<ulong>(definition)!=id||Read<byte>(definition+0x18)!=valid||Pointer(definition+8)!=text||
Read<ulong>(text)!=length||Read<ulong>(text+8)!=capacity||Read<int>(text+0x10)<=0||
!GalaxyCString(text+20,(int)length+1,out var reread)||reread!=candidate)return false;
key=candidate;return true;
}
catch{key=null;return false;}
}
static bool TryReadGalaxyAllegianceKey(GalaxyFilterContext context,nuint registry,ulong id,out string? key)
{
key=null;
if(!Enabled()||!inGame||context.expectedImage!=image||context.thread==0||context.thread!=owningThread||
GetCurrentThreadId()!=context.thread||GetTickCount64()-context.tick>500||registry<0x10000)return false;
var frame=Current();
if(!frame.valid||frame.entity!=context.entity||(frame.referenceWorld&0x007FFFFFFFFFFFFFUL)!=context.currentSystem)return false;
try
{
var type=Read<uint>(image+0x5F05E6C);var source=RegisteredComponent(registry,type);
if(!CopyGalaxyAllegianceKey(source,image,id,out var value))return false;
if(Read<uint>(image+0x5F05E6C)!=type||RegisteredComponent(registry,type)!=source)return false;
var current=Current();if(!current.valid||current.entity!=frame.entity||(current.referenceWorld&0x007FFFFFFFFFFFFFUL)!=context.currentSystem)return false;
key=value;return true;
}
catch{return false;}
}
}