using System.Runtime.InteropServices; using System.Text.Json; namespace XFEEDToolBox.Plugin; internal static unsafe partial class Navigation { static uint GalaxyPowerTerritorySelfTest() { uint passed=0; bool Radius(float counter,bool active,bool enabled,float minimum,float expected) =>GalaxyPowerTerritoryRadius(counter,active,enabled,minimum,out var radius)&&Math.Abs(radius-expected)<.00001f; if(Radius(0,false,false,0,5.775f)&&Radius(999,false,false,0,5.775f)&&GalaxyPowerGeometryLinearColour(0)==0&& GalaxyPowerGeometryLinearColour(1)==1&&Math.Abs(GalaxyPowerGeometryLinearColour(.02f)-.0015476f)<.000001f)passed|=1; if(Radius(0,true,false,0,5.775f)&&Radius(.5f,true,false,0,10.5875f)&&Radius(1,true,false,0,15.4f)&& Radius(2.5f,true,false,0,29.8375f))passed|=2; if(Radius(.25f,true,true,.25f,5.775f)&&Radius(.625f,true,true,.25f,10.5875f)&&Radius(1,true,true,1,15.4f)&& !GalaxyPowerTerritoryRadius(float.NaN,true,false,0,out _)&&!GalaxyPowerTerritoryRadius(1,false,true,.1f,out _))passed|=4; var memory=Platform.Allocate(0x10000);if(memory==0)return passed; try { var expectedImage=memory-0x5FDB000;var service=memory+0x1000;var owner=memory+0x6000; var generic=memory+0x5000;var storage=memory+0x7000;var buckets=memory+0x9000;var descriptorNode=memory+0x9200; const ulong address=9007199254740995; Write(service,expectedImage+0x51BB600);Write(service-0x58,expectedImage+0x51BB4D0); Write(service-0x50,expectedImage+0x51BB500);Write(service-0x48,owner); Write(service+0x308,(byte)1);Write(service+0x309,(byte)1);Write(service+0x30A,(byte)1); Write(service+0x3C8,1UL);Write(service+0x3D0,8UL);Write(service+0x3D8,storage); Write(storage,1UL<<5);var node=storage+16+5*0x180;var metadata=node+0x10; Write(node,address);Write(metadata,1UL);Write(metadata+0xC,2);Write(metadata+0x124,.5f); Write(generic,expectedImage+0x551A1B0);var genericMap=generic+0xA8; Write(genericMap,buckets);Write(genericMap+8,17UL);Write(genericMap+0x18,1UL); for(nuint i=0;i<17;i++)Write(buckets+i*8,buckets+i*8); var sentinel=buckets+(nuint)(GalaxyFactHash(address)%17)*8; Write(sentinel,descriptorNode);Write(descriptorNode,sentinel);Write(descriptorNode+8,address); Write(descriptorNode+0x40,memory+0x9800); // generic descriptor+30, real metadata observed. var source=new GalaxyPowerActivityContext{expectedImage=expectedImage,service=service,owner=owner,optionCount=3, indices=new(){{17,0},{9,1},{41,2}}}; var context=new GalaxyPowerTerritoryContext{activity=source,metadata=generic,options=[ new(0,1,17,"Power A",.1f,.2f,.3f),new(1,2,9,"Power B",.4f,.5f,1.5f),new(2,3,41,"Power C",.7f,.8f,.9f)]}; var before=Platform.ReadBytes(memory,0x10000); bool Copy(bool active,bool min,float threshold,out GalaxyPowerTerritoryFact? result) =>CopyGalaxyPowerTerritoryStyle(context,address,active,false,9,5,min,threshold,out result); if(Copy(true,false,0,out var style)&&style is{rawState:2,stateIndex:5,ownerInternalPowerId:9}&& Math.Abs(style.radius-10.5875f)<.00001f&&style.rawRgb.SequenceEqual(new[]{.4f,.5f,1.5f})&&style.opacity==.15f&& Math.Abs(style.linearRgb[0]-.13286832f)<.000001f&&Math.Abs(style.linearRgb[1]-.21404114f)<.000001f&& Math.Abs(style.linearRgb[2]-2.5371552f)<.00001f&& Platform.ReadBytes(memory,0x10000).AsSpan().SequenceEqual(before))passed|=8; if(Copy(true,true,.5f,out style)&&style is not null&&Math.Abs(style.radius-5.775f)<.00001f&& Copy(true,true,.75f,out var hidden)&&hidden is null&&Copy(false,false,0,out style)&&style is not null&&Math.Abs(style.radius-5.775f)<.00001f)passed|=16; Write(metadata+0xC,0);var guarded=Copy(false,false,0,out style)&&style is null; Write(metadata+0xC,3);Write(metadata+0x11,(byte)1); guarded&=Copy(false,false,0,out style)&&style is{stateIndex:7}; Write(metadata+0x11,(byte)0);guarded&=Copy(false,false,0,out style)&&style is{stateIndex:6}; Write(metadata+0xC,2);if(guarded)passed|=32; Write(descriptorNode+0x1E0,(byte)1);Write(descriptorNode+0x170,35); guarded=Copy(false,false,0,out style)&&style is null; Write(descriptorNode+0x170,37);guarded&=Copy(false,false,0,out style)&&style is not null; Write(descriptorNode+0x1E0,(byte)0);Write(memory+0x275,(byte)1);guarded&=!Copy(false,false,0,out _); Write(memory+0x275,(byte)0);Write(memory+0x277,(byte)1);guarded&=!Copy(false,false,0,out _); Write(memory+0x277,(byte)0);if(guarded)passed|=64; Write(metadata,3UL);guarded=!Copy(false,false,0,out _);Write(metadata,1UL); Write(metadata+0x124,1f); guarded&=Copy(true,false,0,out style)&&style is not null&&Math.Abs(style.radius-15.4f)<.00001f; context.options[1]=context.options[1] with{rawRed=float.NaN};guarded&=!Copy(false,false,0,out _); if(guarded)passed|=128; return passed; } finally{Platform.Free(memory);} } static uint GalaxyPowerTerritoryWireSelfTest() { static JsonElement Parse(string json){using var document=JsonDocument.Parse(json);return document.RootElement.Clone();} lock(galaxyFactsMutex) { var savedWork=galaxyFactsWork;var savedGeneration=galaxyFactsGeneration; try { uint passed=0;galaxyFactsWork=new();galaxyFactsGeneration=0; JsonElement Wire(string op,string fields)=>Parse(GalaxyFilterFactsRequest(op,Parse("{"+fields+"}")).ToJsonString()); void Cancel()=>Wire("galaxy.facts.cancel","\"generation\":"+galaxyFactsWork.generation); var initial=Wire("galaxy.facts","\"systemAddresses\":[\"300\"],\"includePowerTerritory\":true"); galaxyFactsWork.items.Add((300,default)); var territory=Wire("galaxy.facts.result","\"generation\":1").GetProperty("items")[0].GetProperty("powerTerritory"); if(initial.GetProperty("items").GetArrayLength()==0&&galaxyFactsWork.includePowerTerritory&&!galaxyFactsWork.territoryActivityEnabled&& !territory.GetProperty("activityEnabled").GetBoolean()&&territory.GetProperty("scope").ValueKind==JsonValueKind.Null&& territory.GetProperty("radius").ValueKind==JsonValueKind.Null&&territory.GetProperty("rawRgb").ValueKind==JsonValueKind.Null)passed|=1; Cancel(); const string activity="\"includePowerActivity\":true,\"powerScope\":\"selected\",\"powerInternalId\":17,\"powerActivityId\":5"; Wire("galaxy.facts","\"systemAddresses\":[\"300\"],\"includePowerTerritory\":true,\"territoryActivityEnabled\":true,"+activity); galaxyFactsWork.items.Add((300,default));galaxyFactsWork.powerTerritory[300]=new(2,5,9,10.5875f,[.4f,.5f,1.5f],[.13286832f,.21404114f,2.5371552f],.15f); territory=Wire("galaxy.facts.result","\"generation\":2").GetProperty("items")[0].GetProperty("powerTerritory"); if(territory.GetProperty("activityEnabled").GetBoolean()&&!territory.GetProperty("minimumEnabled").GetBoolean()&& territory.GetProperty("scope").GetString()=="selected"&&territory.GetProperty("internalPowerId").GetInt32()==17&& territory.GetProperty("actionId").GetInt32()==5&&territory.GetProperty("ownerInternalPowerId").GetInt32()==9&& territory.GetProperty("rawRgb")[2].GetSingle()==1.5f&&territory.GetProperty("linearRgb")[2].GetSingle()>2.5f&&territory.GetProperty("opacity").GetSingle()==.15f)passed|=2; Cancel(); Wire("galaxy.facts","\"systemAddresses\":[\"300\"],\"includePowerTerritory\":true,\"territoryActivityEnabled\":false,"+activity); galaxyFactsWork.items.Add((300,default)); territory=Wire("galaxy.facts.result","\"generation\":3").GetProperty("items")[0].GetProperty("powerTerritory"); if(!territory.GetProperty("activityEnabled").GetBoolean()&&territory.GetProperty("scope").ValueKind==JsonValueKind.Null&& territory.GetProperty("internalPowerId").ValueKind==JsonValueKind.Null&&territory.GetProperty("actionId").ValueKind==JsonValueKind.Null)passed|=4; Cancel(); Wire("galaxy.facts","\"systemAddresses\":[\"300\"],\"includePowerTerritory\":true,\"territoryActivityEnabled\":true,\"territoryMinimumEnabled\":true,\"territoryMinimum\":0.25,\"includePowerActivity\":true,\"powerScope\":\"all\",\"powerActivityId\":4"); galaxyFactsWork.items.Add((300,default)); territory=Wire("galaxy.facts.result","\"generation\":4").GetProperty("items")[0].GetProperty("powerTerritory"); if(territory.GetProperty("minimumEnabled").GetBoolean()&&territory.GetProperty("minimum").GetSingle()==.25f&& territory.GetProperty("scope").GetString()=="all"&&territory.GetProperty("internalPowerId").ValueKind==JsonValueKind.Null&& territory.GetProperty("actionId").GetInt32()==4&&territory.GetProperty("radius").ValueKind==JsonValueKind.Null)passed|=8; Cancel(); var invalid=new[]{"\"includePowerTerritory\":1","\"includePowerTerritory\":true,\"territoryActivityEnabled\":\"true\"", "\"includePowerTerritory\":true,\"territoryMinimumEnabled\":1","\"includePowerTerritory\":true,\"territoryMinimum\":\"0.1\"", "\"includePowerTerritory\":true,\"territoryMinimum\":-0.1","\"includePowerTerritory\":true,\"territoryMinimum\":1.1", "\"includePowerTerritory\":true,\"territoryMinimum\":1e99","\"includePowerTerritory\":true,\"territoryActivityEnabled\":true", "\"includePowerTerritory\":true,\"territoryMinimumEnabled\":true","\"includePowerTerritory\":false,\"territoryMinimum\":0.1", "\"territoryActivityEnabled\":true,"+activity}; var rejected=0;foreach(var bad in invalid)try{Wire("galaxy.facts","\"systemAddresses\":[\"300\"],"+bad);}catch(InvalidDataException){rejected++;} if(rejected==invalid.Length&&galaxyFactsGeneration==4)passed|=16; Wire("galaxy.facts","\"systemAddresses\":[\"300\"],\"includePowerTerritory\":false,\"territoryActivityEnabled\":false,\"territoryMinimumEnabled\":false,\"territoryMinimum\":0"); galaxyFactsWork.items.Add((300,default)); if(Wire("galaxy.facts.result","\"generation\":5").GetProperty("items")[0].GetProperty("powerTerritory").ValueKind==JsonValueKind.Null&& galaxyFactsWork.powerTerritory.Count==0)passed|=32; var old=galaxyFactsWork;Cancel();Wire("galaxy.facts","\"systemAddresses\":[\"301\"],\"includePowerTerritory\":true"); var mismatch=false;try{Wire("galaxy.facts.result","\"generation\":5");}catch(InvalidOperationException){mismatch=true;} if(old.cancelled&&old.done&&mismatch&&galaxyFactsWork.powerTerritory.Count==0&&!galaxyFactsWork.territoryActivityEnabled)passed|=64; galaxyFactsWork.items=Enumerable.Range(0,200).Select(i=>((ulong)i+1,new GalaxyFilterFacts())).ToList(); var page=Wire("galaxy.facts.result","\"generation\":6,\"limit\":9999").GetProperty("items"); // The original96-row limit and48k byte limit both apply. New // explicit-null classifier fields can make the byte limit win. // Check both bounds and consume every row, rather than assuming // this particular payload always packs exactly96 rows. var offset=0;var pagesValid=true;var nextMustExceedBytes=-1; while(offset<200&&pagesValid) { if(offset!=0)page=Wire("galaxy.facts.result","\"generation\":6,\"offset\":"+offset+",\"limit\":9999").GetProperty("items"); var count=page.GetArrayLength();var bytes=page.EnumerateArray().Sum(row=>System.Text.Encoding.UTF8.GetByteCount(row.GetRawText())); if(count is <1 or >96||bytes>48000){pagesValid=false;break;} if(nextMustExceedBytes>=0&&nextMustExceedBytes+System.Text.Encoding.UTF8.GetByteCount(page[0].GetRawText())<=48000) {pagesValid=false;break;} for(var i=0;iRunTest(GalaxyPowerTerritorySelfTest); [UnmanagedCallersOnly(EntryPoint="XFENavigationGalaxyPowerTerritoryWireSelfTest")] internal static uint ExportGalaxyPowerTerritoryWireSelfTest()=>RunTest(GalaxyPowerTerritoryWireSelfTest); #endif }