worldbox-observer-mod/.tmp-reflect/DumpPlot/Program.cs
2026-07-17 01:54:59 -05:00

113 lines
4.2 KiB
C#

using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
string path = "/home/dazed/.local/share/Steam/steamapps/common/worldbox/worldbox_Data/Managed/Assembly-CSharp.dll";
using var fs = File.OpenRead(path);
using var pe = new PEReader(fs);
var md = pe.GetMetadataReader();
string DecodeType(ref BlobReader r) {
var code = r.ReadSignatureTypeCode();
switch (code) {
case SignatureTypeCode.GenericTypeInstance:
var gen = DecodeType(ref r);
int arity = r.ReadCompressedInteger();
var args = new string[arity];
for (int i=0;i<arity;i++) args[i]=DecodeType(ref r);
return gen+"<"+string.Join(",", args)+">";
case SignatureTypeCode.SZArray:
return DecodeType(ref r)+"[]";
case SignatureTypeCode.TypeHandle:
var h = r.ReadTypeHandle();
return Resolve(h);
case SignatureTypeCode.Object: return "object";
case SignatureTypeCode.String: return "string";
case SignatureTypeCode.Int32: return "int";
case SignatureTypeCode.Boolean: return "bool";
case SignatureTypeCode.Void: return "void";
default:
return code.ToString();
}
}
string Resolve(EntityHandle h) {
if (h.Kind==HandleKind.TypeDefinition) {
var t=md.GetTypeDefinition((TypeDefinitionHandle)h);
var ns=md.GetString(t.Namespace);
var n=md.GetString(t.Name);
return string.IsNullOrEmpty(ns)?n:ns+"."+n;
}
if (h.Kind==HandleKind.TypeReference) {
var t=md.GetTypeReference((TypeReferenceHandle)h);
var ns=md.GetString(t.Namespace);
var n=md.GetString(t.Name);
return string.IsNullOrEmpty(ns)?n:ns+"."+n;
}
return h.Kind.ToString();
}
foreach (var typeName in new[]{"Plot","Family","War","Army","Clan"}) {
foreach (var th in md.TypeDefinitions) {
var t=md.GetTypeDefinition(th);
if (md.GetString(t.Name)!=typeName) continue;
if (t.BaseType.Kind==HandleKind.TypeSpecification) {
var ts=md.GetTypeSpecification((TypeSpecificationHandle)t.BaseType);
var br=md.GetBlobReader(ts.Signature);
Console.WriteLine(typeName+" : "+DecodeType(ref br));
} else {
Console.WriteLine(typeName+" : "+Resolve(t.BaseType));
}
}
}
// Dump MetaObject members if found by pattern MetaObject*
Console.WriteLine("\nTypes matching MetaObject*:");
foreach (var th in md.TypeDefinitions) {
var t=md.GetTypeDefinition(th);
var n=md.GetString(t.Name);
if (n.StartsWith("MetaObject") || n.Contains("MetaObject")) {
Console.WriteLine(" "+n+" arity?");
// list unit-related
foreach (var fh in t.GetFields()) {
var f=md.GetFieldDefinition(fh);
var fn=md.GetString(f.Name);
if (fn.Contains("unit")||fn.Contains("member")||fn.Contains("list")||fn.Contains("hash")||fn.Contains("actor"))
Console.WriteLine(" field "+fn);
}
foreach (var mh in t.GetMethods()) {
var m=md.GetMethodDefinition(mh);
var mn=md.GetString(m.Name);
if (mn.Contains("unit")||mn.Contains("Unit")||mn.Contains("member")||mn.Contains("Member")||mn=="units" || mn.StartsWith("get_units") || mn.StartsWith("get_"))
if ((m.Attributes & System.Reflection.MethodAttributes.Public)!=0)
Console.WriteLine(" method "+mn);
}
}
}
// Specifically look for getSupporters signature return - decode method sig for Plot.getSupporters
foreach (var th in md.TypeDefinitions) {
var t=md.GetTypeDefinition(th);
if (md.GetString(t.Name)!="Plot") continue;
foreach (var mh in t.GetMethods()) {
var m=md.GetMethodDefinition(mh);
var n=md.GetString(m.Name);
if (n is "getSupporters" or "getAuthor" or "hasSupporter" or "getMaxSupporters" or "getAsset") {
var br=md.GetBlobReader(m.Signature);
// MethodDefSig: callingconv, paramCount, retType, params...
var hdr=br.ReadSignatureHeader();
int pc=br.ReadCompressedInteger();
string ret=DecodeType(ref br);
Console.WriteLine("Plot."+n+" -> "+ret+" (params="+pc+")");
}
}
// field types for targets
foreach (var fh in t.GetFields()) {
var f=md.GetFieldDefinition(fh);
var n=md.GetString(f.Name);
if (n.StartsWith("target_") || n=="_plot_author" || n=="_plot_asset") {
var br=md.GetBlobReader(f.Signature);
var hdr=br.ReadSignatureHeader(); // Field
string ty=DecodeType(ref br);
Console.WriteLine("Plot."+n+" : "+ty);
}
}
}