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"; 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); } } }