From c126275d7395e57cf827e90b7a88d7afd0c86126 Mon Sep 17 00:00:00 2001 From: Deathemonic Date: Sat, 10 Jan 2026 19:11:24 +0800 Subject: [PATCH 1/9] refactor: improve logging --- Helpers/Logger.cs | 33 +++++++-------------------------- MemoryPackDumper.csproj | 1 + MemoryPackDumper.slnx | 3 +++ 3 files changed, 11 insertions(+), 26 deletions(-) create mode 100644 MemoryPackDumper.slnx diff --git a/Helpers/Logger.cs b/Helpers/Logger.cs index 0d067ff..149b6f6 100644 --- a/Helpers/Logger.cs +++ b/Helpers/Logger.cs @@ -23,11 +23,15 @@ public static ILogger Global private static void EnsureInitialized() { if (_isInitialized) return; + Initialize(LogLevel.Information); + } + private static void Initialize(LogLevel minLevel) + { _loggerFactory = LoggerFactory.Create(logging => { logging.ClearProviders(); - logging.SetMinimumLevel(LogLevel.Information); + logging.SetMinimumLevel(minLevel); logging.AddZLoggerConsole(options => { @@ -45,7 +49,7 @@ private static void EnsureInitialized() }); }); - _logger = _loggerFactory.CreateLogger("FbsDumper"); + _logger = _loggerFactory.CreateLogger("MemoryPackDumper"); _isInitialized = true; } @@ -98,30 +102,7 @@ public static void Debug(string message) public static void EnableDebugLogging() { if (_isInitialized) Shutdown(); - - _loggerFactory = LoggerFactory.Create(logging => - { - logging.ClearProviders(); - logging.SetMinimumLevel(LogLevel.Debug); - - logging.AddZLoggerConsole(options => - { - options.UsePlainTextFormatter(formatter => - { - formatter.SetPrefixFormatter($"{0} {1} ", - (in template, in info) => - { - var timestamp = Chalk.Gray + info.Timestamp.Local.ToString("HH:mm:ss"); - var logLevel = GetColoredLogLevel(info.LogLevel); - template.Format(timestamp, logLevel); - }); - }); - options.LogToStandardErrorThreshold = LogLevel.Error; - }); - }); - - _logger = _loggerFactory.CreateLogger("FbsDumper"); - _isInitialized = true; + Initialize(LogLevel.Debug); } public static void Shutdown() diff --git a/MemoryPackDumper.csproj b/MemoryPackDumper.csproj index d140e96..61dde35 100644 --- a/MemoryPackDumper.csproj +++ b/MemoryPackDumper.csproj @@ -18,6 +18,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all + diff --git a/MemoryPackDumper.slnx b/MemoryPackDumper.slnx new file mode 100644 index 0000000..6871a09 --- /dev/null +++ b/MemoryPackDumper.slnx @@ -0,0 +1,3 @@ + + + From c81c8623c9a37d51fee513e04e57eb7bed692b53 Mon Sep 17 00:00:00 2001 From: Deathemonic Date: Sat, 10 Jan 2026 20:09:02 +0800 Subject: [PATCH 2/9] feat: migrate to dnlib --- .gitignore | 4 +- Assembly/AttributeExtractor.cs | 19 +++--- Assembly/MemberParser.cs | 72 ++++++++++--------- Assembly/MemoryPackTypes.cs | 12 ++-- Assembly/TypeHelper.cs | 114 +++++++++++++++++++++---------- Assembly/TypeReferenceTracker.cs | 10 +-- Assembly/TypeStringConverter.cs | 47 +++++++++---- CLI/Parser.cs | 30 ++++---- MemoryPackDumper.csproj | 7 +- 9 files changed, 192 insertions(+), 123 deletions(-) diff --git a/.gitignore b/.gitignore index 76de6e2..76f7124 100644 --- a/.gitignore +++ b/.gitignore @@ -403,4 +403,6 @@ GameAssembly.dll libil2cpp.so *.fbs -.idea \ No newline at end of file +.idea + +_DONT/ \ No newline at end of file diff --git a/Assembly/AttributeExtractor.cs b/Assembly/AttributeExtractor.cs index edb3d72..087aafc 100644 --- a/Assembly/AttributeExtractor.cs +++ b/Assembly/AttributeExtractor.cs @@ -1,12 +1,11 @@ -using Mono.Cecil; -using Mono.Collections.Generic; +using dnlib.DotNet; using ZLinq; namespace MemoryPackDumper.Assembly; public static class AttributeExtractor { - public static void ExtractClassAttributes(TypeDefinition typeDef, MemoryPackClass memoryPackClass) + public static void ExtractClassAttributes(TypeDef typeDef, MemoryPackClass memoryPackClass) { foreach (var attr in typeDef.CustomAttributes) switch (attr.AttributeType.Name) @@ -38,8 +37,8 @@ private static void ExtractMemoryPackableAttribute(CustomAttribute attr, MemoryP } else { - var layoutProp = attr.Properties.FirstOrDefault(p => p.Name == "SerializeLayout"); - if (layoutProp.Argument.Value != null) + var layoutProp = attr.NamedArguments.FirstOrDefault(p => p.Name == "SerializeLayout"); + if (layoutProp != null && layoutProp.Argument.Value != null) memoryPackClass.SerializeLayout = EnumMapper.MapSerializeLayout(layoutProp.Argument.Value.ToString()!); } } @@ -49,11 +48,11 @@ private static void ExtractMemoryPackUnionAttribute(CustomAttribute attr, Memory if (attr.ConstructorArguments.Count < 2) return; var tag = Convert.ToInt32(attr.ConstructorArguments[0].Value); - if (attr.ConstructorArguments[1].Value is TypeReference typeRef) - memoryPackClass.Unions.Add(new MemoryPackUnion(tag, typeRef.Name)); + if (attr.ConstructorArguments[1].Value is TypeSig typeSig) + memoryPackClass.Unions.Add(new MemoryPackUnion(tag, typeSig.ReflectionName)); } - public static void ExtractMemberAttributes(Collection attributes, MemoryPackMember member) + public static void ExtractMemberAttributes(CustomAttributeCollection attributes, MemoryPackMember member) { foreach (var attr in attributes) switch (attr.AttributeType.Name) @@ -94,11 +93,11 @@ public static void ExtractMemberAttributes(Collection attribute } } - public static void ExtractMethodAttributes(MethodDefinition methodDef, MemoryPackMethod method) + public static void ExtractMethodAttributes(MethodDef methodDef, MemoryPackMethod method) { foreach (var attr in methodDef.CustomAttributes.AsValueEnumerable()) { - var attrName = attr.AttributeType.Name; + var attrName = attr.AttributeType.Name.String; if (attrName is "TokenAttribute" or "AddressAttribute" or "FieldOffsetAttribute") continue; diff --git a/Assembly/MemberParser.cs b/Assembly/MemberParser.cs index 66a5b39..a7c27d6 100644 --- a/Assembly/MemberParser.cs +++ b/Assembly/MemberParser.cs @@ -1,12 +1,12 @@ using MemoryPackDumper.Helpers; -using Mono.Cecil; +using dnlib.DotNet; using ZLinq; namespace MemoryPackDumper.Assembly; public static class MemberParser { - public static MemoryPackClass TypeToMemoryPackClass(TypeDefinition typeDef, HashSet discoveredTypes) + public static MemoryPackClass TypeToMemoryPackClass(TypeDef typeDef, HashSet discoveredTypes) { var className = GetClassName(typeDef); var typeKeyword = TypeHelper.GetTypeKeyword(typeDef); @@ -29,9 +29,9 @@ public static MemoryPackClass TypeToMemoryPackClass(TypeDefinition typeDef, Hash return memoryPackClass; } - private static string GetClassName(TypeDefinition typeDef) + private static string GetClassName(TypeDef typeDef) { - var name = typeDef.Name; + var name = typeDef.Name.String; if (!typeDef.HasGenericParameters) return name; @@ -39,18 +39,18 @@ private static string GetClassName(TypeDefinition typeDef) if (name.Contains('`')) name = name[..name.IndexOf('`')]; - var genericParams = typeDef.GenericParameters.AsValueEnumerable().Select(p => p.Name).JoinToString(", "); + var genericParams = typeDef.GenericParameters.AsValueEnumerable().Select(p => p.Name.String).JoinToString(", "); return $"{name}<{genericParams}>"; } - private static bool IsRecordType(TypeDefinition typeDef) + private static bool IsRecordType(TypeDef typeDef) { return typeDef.CustomAttributes.AsValueEnumerable().Any(a => a.AttributeType.FullName == "System.Runtime.CompilerServices.CompilerGeneratedAttribute") || - typeDef.BaseType?.Name == "Record"; + (typeDef.BaseType != null && typeDef.BaseType.Name == "Record"); } - private static void ProcessProperties(TypeDefinition typeDef, MemoryPackClass memoryPackClass, + private static void ProcessProperties(TypeDef typeDef, MemoryPackClass memoryPackClass, HashSet discoveredTypes) { foreach (var property in typeDef.Properties) @@ -66,7 +66,7 @@ private static void ProcessProperties(TypeDefinition typeDef, MemoryPackClass me } } - private static void ProcessFields(TypeDefinition typeDef, MemoryPackClass memoryPackClass, + private static void ProcessFields(TypeDef typeDef, MemoryPackClass memoryPackClass, HashSet discoveredTypes) { foreach (var field in typeDef.Fields.AsValueEnumerable().Where(f => !f.IsStatic && !f.IsLiteral)) @@ -100,7 +100,7 @@ private static void SortMembersByOrder(MemoryPackClass memoryPackClass) }); } - private static void ProcessMethods(TypeDefinition typeDef, MemoryPackClass memoryPackClass) + private static void ProcessMethods(TypeDef typeDef, MemoryPackClass memoryPackClass) { foreach (var method in typeDef.Methods) { @@ -112,31 +112,31 @@ private static void ProcessMethods(TypeDefinition typeDef, MemoryPackClass memor } } - private static bool IsMemoryPackMethod(MethodDefinition method) + private static bool IsMemoryPackMethod(MethodDef method) { return IsMemoryPackConstructor(method) || IsCallbackMethod(method) || IsStaticConstructor(method) || IsOverrideMethod(method); } - private static bool IsOverrideMethod(MethodDefinition method) + private static bool IsOverrideMethod(MethodDef method) { if (method is not { IsVirtual: true, IsNewSlot: false, IsGetter: false, IsSetter: false }) return false; - if (method.Name is "Serialize" or "Deserialize") + if (method.Name == "Serialize" || method.Name == "Deserialize") return false; return true; } - private static bool IsMemoryPackConstructor(MethodDefinition method) + private static bool IsMemoryPackConstructor(MethodDef method) { return method.IsConstructor && method.CustomAttributes.AsValueEnumerable() .Any(a => a.AttributeType.Name == "MemoryPackConstructorAttribute"); } - private static bool IsCallbackMethod(MethodDefinition method) + private static bool IsCallbackMethod(MethodDef method) { return method.CustomAttributes.AsValueEnumerable().Any(a => a.AttributeType.Name == "MemoryPackOnSerializingAttribute" || @@ -145,14 +145,15 @@ private static bool IsCallbackMethod(MethodDefinition method) a.AttributeType.Name == "MemoryPackOnDeserializedAttribute"); } - private static bool IsStaticConstructor(MethodDefinition method) + private static bool IsStaticConstructor(MethodDef method) { - return method is { IsStatic: true, Name: "StaticConstructor" } && + return method is { IsStatic: true } && + method.Name.String == "StaticConstructor" && method.ReturnType.FullName == "System.Void" && method.Parameters.Count == 0; } - private static MemoryPackMethod CreateMethodFromDefinition(MethodDefinition methodDef) + private static MemoryPackMethod CreateMethodFromDefinition(MethodDef methodDef) { var returnType = TypeStringConverter.TypeToString(methodDef.ReturnType); var visibility = GetMethodVisibility(methodDef); @@ -167,14 +168,16 @@ private static MemoryPackMethod CreateMethodFromDefinition(MethodDefinition meth foreach (var param in methodDef.Parameters) { - var paramType = TypeStringConverter.TypeToString(param.ParameterType); + if (param.IsHiddenThisParameter) continue; + + var paramType = TypeStringConverter.TypeToString(param.Type); method.Parameters.Add((paramType, param.Name)); } return method; } - private static string GetMethodVisibility(MethodDefinition methodDef) + private static string GetMethodVisibility(MethodDef methodDef) { if (methodDef.IsPublic) return "public"; if (methodDef.IsFamily) return "protected"; @@ -184,10 +187,10 @@ private static string GetMethodVisibility(MethodDefinition methodDef) return "private"; } - private static MemoryPackMember CreateMemberFromProperty(PropertyDefinition property) + private static MemoryPackMember CreateMemberFromProperty(PropertyDef property) { var accessorMethod = property.GetMethod ?? property.SetMethod; - var member = new MemoryPackMember(property.Name, property.PropertyType, false) + var member = new MemoryPackMember(property.Name, property.PropertySig.RetType, false) { IsPublic = accessorMethod?.IsPublic ?? false }; @@ -195,7 +198,7 @@ private static MemoryPackMember CreateMemberFromProperty(PropertyDefinition prop return member; } - private static MemoryPackMember CreateMemberFromField(FieldDefinition field) + private static MemoryPackMember CreateMemberFromField(FieldDef field) { var member = new MemoryPackMember(field.Name, field.FieldType, true) { @@ -205,7 +208,7 @@ private static MemoryPackMember CreateMemberFromField(FieldDefinition field) return member; } - public static MemoryPackEnum TypeToEnum(TypeDefinition typeDef) + public static MemoryPackEnum TypeToEnum(TypeDef typeDef) { var underlyingType = GetEnumUnderlyingType(typeDef); var memoryPackEnum = new MemoryPackEnum(underlyingType, typeDef.Name) @@ -215,23 +218,26 @@ public static MemoryPackEnum TypeToEnum(TypeDefinition typeDef) foreach (var fieldDef in typeDef.Fields.AsValueEnumerable().Where(f => f.HasConstant)) { - var enumField = new MemoryPackEnumField(fieldDef.Name, Convert.ToInt64(fieldDef.Constant)); + var enumField = new MemoryPackEnumField(fieldDef.Name, Convert.ToInt64(fieldDef.Constant.Value)); memoryPackEnum.Fields.Add(enumField); } return memoryPackEnum; } - private static TypeDefinition GetEnumUnderlyingType(TypeDefinition typeDef) + private static TypeDef GetEnumUnderlyingType(TypeDef typeDef) { - var underlyingType = typeDef.Fields.FirstOrDefault(f => f.Name == "value__")?.FieldType.Resolve(); + var underlyingType = typeDef.Fields.FirstOrDefault(f => f.Name == "value__")?.FieldType.TryGetTypeDef(); if (underlyingType != null) return underlyingType; Log.Warning($"Could not determine underlying type for enum {typeDef.FullName}"); - return typeDef.Module.TypeSystem.Int32.Resolve(); + // dnlib doesn't have a direct TypeSystem accessor from ModuleDef in the same way, need access to a known type or context. + // Assuming int32 as fallback if not found. + // But ModuleDef has CorLibTypes. + return typeDef.Module.CorLibTypes.Int32.TypeDefOrRef.ResolveTypeDef(); } - private static void ProcessNestedTypes(TypeDefinition typeDef, MemoryPackClass memoryPackClass, + private static void ProcessNestedTypes(TypeDef typeDef, MemoryPackClass memoryPackClass, HashSet discoveredTypes) { if (!typeDef.HasNestedTypes) return; @@ -249,16 +255,16 @@ private static void ProcessNestedTypes(TypeDefinition typeDef, MemoryPackClass m } } - private static bool IsAutoGeneratedFormatter(TypeDefinition nestedType, string parentClassName) + private static bool IsAutoGeneratedFormatter(TypeDef nestedType, string parentClassName) { if (nestedType.BaseType == null) return false; - var baseTypeName = nestedType.BaseType.Name; + var baseTypeName = nestedType.BaseType.Name.String; if (!baseTypeName.StartsWith("MemoryPackFormatter")) return false; - if (nestedType.BaseType is GenericInstanceType genericBase && genericBase.GenericArguments.Count > 0) + if (nestedType.BaseType is TypeSpec typeSpec && typeSpec.TypeSig is GenericInstSig genericBase && genericBase.GenericArguments.Count > 0) { - var formattedTypeName = genericBase.GenericArguments[0].Name; + var formattedTypeName = genericBase.GenericArguments[0].TypeName; var parentBaseName = parentClassName.Contains('<') ? parentClassName[..parentClassName.IndexOf('<')] : parentClassName; diff --git a/Assembly/MemoryPackTypes.cs b/Assembly/MemoryPackTypes.cs index b4f40cb..bc33e6b 100644 --- a/Assembly/MemoryPackTypes.cs +++ b/Assembly/MemoryPackTypes.cs @@ -1,4 +1,4 @@ -using Mono.Cecil; +using dnlib.DotNet; namespace MemoryPackDumper.Assembly; @@ -17,7 +17,7 @@ public class MemoryPackClass(string className, string baseClassName, string type public readonly List Methods = []; public readonly string TypeKeyword = typeKeyword; public readonly List Unions = []; - public TypeReference? BaseTypeReference = null; + public ITypeDefOrRef? BaseTypeReference = null; public string? GenerateType = null; public bool IsRecord = false; public List NestedClasses = []; @@ -42,12 +42,12 @@ public class MemoryPackUnion(int tag, string typeName) public readonly string TypeName = typeName; } -public class MemoryPackMember(string name, TypeReference type, bool isField) +public class MemoryPackMember(string name, TypeSig type, bool isField) { public readonly List CustomFormatters = []; public readonly bool IsField = isField; public readonly string Name = name; - public readonly TypeReference Type = type; + public readonly TypeSig Type = type; public bool AllowSerialize = false; public bool IsIgnored = false; public bool IsInclude = false; @@ -59,11 +59,11 @@ public class MemoryPackMember(string name, TypeReference type, bool isField) public bool SuppressDefaultInitialization = false; } -public class MemoryPackEnum(TypeDefinition valueType, string enumName) +public class MemoryPackEnum(TypeDef valueType, string enumName) { public readonly string EnumName = enumName; public readonly List Fields = []; - public readonly TypeDefinition Type = valueType; + public readonly TypeDef Type = valueType; public string OriginalNamespace = ""; } diff --git a/Assembly/TypeHelper.cs b/Assembly/TypeHelper.cs index 7d6794a..b10ec94 100644 --- a/Assembly/TypeHelper.cs +++ b/Assembly/TypeHelper.cs @@ -1,18 +1,18 @@ using MemoryPackDumper.CLI; -using Mono.Cecil; +using dnlib.DotNet; using ZLinq; namespace MemoryPackDumper.Assembly; internal static class TypeHelper { - public static List GetAllMemoryPackableTypes(ModuleDefinition module) + public static List GetAllMemoryPackableTypes(ModuleDef module) { - List ret = + List ret = [ .. module.GetTypes().AsValueEnumerable().Where(t => t.CustomAttributes.AsValueEnumerable().Any(a => a.AttributeType.Name == "MemoryPackableAttribute") || - t.Interfaces.AsValueEnumerable().Any(i => i.InterfaceType.Name == "IMemoryPackFormatterRegister") + t.Interfaces.AsValueEnumerable().Any(i => i.Interface.Name == "IMemoryPackFormatterRegister") ).ToArray() ]; @@ -24,7 +24,7 @@ .. module.GetTypes().AsValueEnumerable().Where(t => [ .. ret.AsValueEnumerable().Where(t => t.Name == Parser.Type2LookFor || - t.BaseType.Name == Parser.Type2LookFor || + (t.BaseType != null && t.BaseType.Name == Parser.Type2LookFor) || IsSubTypeOf(t, Parser.Type2LookFor) ).ToArray() ]; @@ -35,7 +35,7 @@ .. ret.AsValueEnumerable().Where(t => return ret; } - public static string GetTypeKeyword(TypeDefinition typeDef) + public static string GetTypeKeyword(TypeDef typeDef) { if (typeDef.IsInterface) return "interface"; @@ -48,57 +48,78 @@ public static string GetTypeKeyword(TypeDefinition typeDef) return ""; } - public static string GetBaseType(TypeDefinition typeDef) + public static string GetBaseType(TypeDef typeDef) { if (typeDef.BaseType == null || typeDef.BaseType.FullName == "System.Object" || typeDef.BaseType.FullName == "System.ValueType" || typeDef.BaseType.FullName == "System.Enum") return ""; - if (typeDef.BaseType is GenericInstanceType genericBase) - return TypeStringConverter.TypeToString(genericBase); + + if (typeDef.BaseType is TypeSpec typeSpec && typeSpec.TypeSig is GenericInstSig genericSig) + return TypeStringConverter.TypeToString(genericSig); - var baseName = typeDef.BaseType.Name; + var baseName = typeDef.BaseType.Name.String; if (baseName.Contains('`')) baseName = baseName[..baseName.IndexOf('`')]; return baseName; } - public static void CollectNamespaces(TypeReference typeRef, HashSet namespaces) + public static void CollectNamespaces(TypeSig typeSig, HashSet namespaces) { - switch (typeRef) + switch (typeSig) { - case GenericInstanceType genericType: + case GenericInstSig genericType: { - var elementType = genericType.ElementType.Resolve(); + var elementType = genericType.GenericType.ToTypeDefOrRef().ResolveTypeDef(); AddNamespaceIfNeeded(elementType, namespaces); foreach (var arg in genericType.GenericArguments) CollectNamespaces(arg, namespaces); break; } - case ArrayType arrayType: - CollectNamespaces(arrayType.ElementType, namespaces); + case SZArraySig szArrayType: + CollectNamespaces(szArrayType.Next, namespaces); + break; + case ArraySig arrayType: + CollectNamespaces(arrayType.Next, namespaces); break; default: { - var resolved = typeRef.Resolve(); + var resolved = typeSig.TryGetTypeDef(); AddNamespaceIfNeeded(resolved, namespaces); break; } } } - private static void AddNamespaceIfNeeded(TypeDefinition? typeDef, HashSet namespaces) + public static void CollectNamespaces(ITypeDefOrRef? typeRef, HashSet namespaces) + { + if (typeRef == null) return; + + if (typeRef is TypeSpec typeSpec) + { + CollectNamespaces(typeSpec.TypeSig, namespaces); + return; + } + + var resolved = typeRef.ResolveTypeDef(); + AddNamespaceIfNeeded(resolved, namespaces); + } + + private static void AddNamespaceIfNeeded(TypeDef? typeDef, HashSet namespaces) { - if (typeDef?.Namespace == null) return; + if (typeDef == null) return; + var ns = typeDef.Namespace?.String; + if (string.IsNullOrEmpty(ns)) return; - if (typeDef.Namespace.StartsWith("System.")) + if (ns.StartsWith("System.")) { - namespaces.Add(typeDef.Namespace); + namespaces.Add(ns); return; } - if (typeDef.Namespace != "UnityEngine") return; - switch (typeDef.Name) + if (ns != "UnityEngine") return; + var name = typeDef.Name?.String; + switch (name) { case "Vector2": case "Vector3": @@ -110,48 +131,67 @@ private static void AddNamespaceIfNeeded(TypeDefinition? typeDef, HashSet namespaces, + public static void CollectNamespacesForSplitFile(TypeSig typeSig, HashSet namespaces, string currentFileNamespace) { - switch (typeRef) + switch (typeSig) { - case GenericInstanceType genericType: + case GenericInstSig genericType: { - var elementType = genericType.ElementType.Resolve(); + var elementType = genericType.GenericType.ToTypeDefOrRef().ResolveTypeDef(); AddNamespaceForSplitFile(elementType, namespaces, currentFileNamespace); foreach (var arg in genericType.GenericArguments) CollectNamespacesForSplitFile(arg, namespaces, currentFileNamespace); break; } - case ArrayType arrayType: - CollectNamespacesForSplitFile(arrayType.ElementType, namespaces, currentFileNamespace); + case SZArraySig szArrayType: + CollectNamespacesForSplitFile(szArrayType.Next, namespaces, currentFileNamespace); + break; + case ArraySig arrayType: + CollectNamespacesForSplitFile(arrayType.Next, namespaces, currentFileNamespace); break; default: { - var resolved = typeRef.Resolve(); + var resolved = typeSig.TryGetTypeDef(); AddNamespaceForSplitFile(resolved, namespaces, currentFileNamespace); break; } } } - private static void AddNamespaceForSplitFile(TypeDefinition? typeDef, HashSet namespaces, + public static void CollectNamespacesForSplitFile(ITypeDefOrRef? typeRef, HashSet namespaces, + string currentFileNamespace) + { + if (typeRef == null) return; + + if (typeRef is TypeSpec typeSpec) + { + CollectNamespacesForSplitFile(typeSpec.TypeSig, namespaces, currentFileNamespace); + return; + } + + var resolved = typeRef.ResolveTypeDef(); + AddNamespaceForSplitFile(resolved, namespaces, currentFileNamespace); + } + + private static void AddNamespaceForSplitFile(TypeDef? typeDef, HashSet namespaces, string currentFileNamespace) { - if (typeDef?.Namespace == null) return; + if (typeDef == null) return; + var ns = typeDef.Namespace?.String; + if (string.IsNullOrEmpty(ns)) return; - if (typeDef.Namespace == "System" || typeDef.Namespace.StartsWith("System.") || - typeDef.Namespace == "UnityEngine") + if (ns == "System" || ns.StartsWith("System.") || ns == "UnityEngine") { AddNamespaceIfNeeded(typeDef, namespaces); return; } - if (typeDef.Namespace != currentFileNamespace) namespaces.Add(typeDef.Namespace); + if (ns != currentFileNamespace) namespaces.Add(ns); } - private static bool IsSubTypeOf(TypeDefinition typeToCheck, string ancestorTypeName) + private static bool IsSubTypeOf(TypeDef typeToCheck, string ancestorTypeName) { var currentBaseRef = typeToCheck.BaseType; @@ -160,7 +200,7 @@ private static bool IsSubTypeOf(TypeDefinition typeToCheck, string ancestorTypeN if (currentBaseRef.Name == ancestorTypeName) return true; - var currentBaseDef = currentBaseRef.Resolve(); + var currentBaseDef = currentBaseRef.ResolveTypeDef(); if (currentBaseDef == null) break; diff --git a/Assembly/TypeReferenceTracker.cs b/Assembly/TypeReferenceTracker.cs index 4fe31c0..b138449 100644 --- a/Assembly/TypeReferenceTracker.cs +++ b/Assembly/TypeReferenceTracker.cs @@ -1,14 +1,14 @@ using MemoryPackDumper.CLI; -using Mono.Cecil; +using dnlib.DotNet; using ZLinq; namespace MemoryPackDumper.Assembly; public static class TypeReferenceTracker { - public static void TrackReferencedType(TypeReference typeRef, HashSet discoveredTypes) + public static void TrackReferencedType(TypeSig typeSig, HashSet discoveredTypes) { - var typeDef = typeRef.Resolve(); + var typeDef = typeSig.TryGetTypeDef(); if (typeDef == null) return; @@ -20,12 +20,12 @@ public static void TrackReferencedType(TypeReference typeRef, HashSet di if (IsMemoryPackable(typeDef)) discoveredTypes.Add(typeDef.FullName); - if (typeRef is not GenericInstanceType genericInstance) return; + if (typeSig is not GenericInstSig genericInstance) return; foreach (var genericArg in genericInstance.GenericArguments.AsValueEnumerable()) TrackReferencedType(genericArg, discoveredTypes); } - private static bool IsMemoryPackable(TypeDefinition typeDef) + private static bool IsMemoryPackable(TypeDef typeDef) { return typeDef.CustomAttributes.AsValueEnumerable().Any(a => a.AttributeType.Name == "MemoryPackableAttribute"); } diff --git a/Assembly/TypeStringConverter.cs b/Assembly/TypeStringConverter.cs index 9c87bbb..283598a 100644 --- a/Assembly/TypeStringConverter.cs +++ b/Assembly/TypeStringConverter.cs @@ -1,5 +1,5 @@ +using dnlib.DotNet; using MemoryPackDumper.Helpers; -using Mono.Cecil; using ZLinq; namespace MemoryPackDumper.Assembly; @@ -23,23 +23,42 @@ public static class TypeStringConverter ["System.Decimal"] = "decimal" }; - public static string TypeToString(TypeReference typeRef) + public static string TypeToString(TypeSig typeSig) { - if (typeRef is GenericInstanceType genericInstance) return ConvertGenericType(genericInstance); + if (typeSig == null) return "void"; - if (typeRef.IsArray) + if (typeSig is GenericInstSig genericInstance) return ConvertGenericType(genericInstance); + + if (typeSig is SZArraySig szArray) + { + return TypeToString(szArray.Next) + "[]"; + } + + if (typeSig is ArraySig array) { - var arrayType = typeRef as ArrayType; - return TypeToString(arrayType!.ElementType) + "[]"; + return TypeToString(array.Next) + "[]"; } - var typeDef = typeRef.Resolve(); - return typeDef != null ? SystemToStringType(typeDef) : typeRef.Name; + var typeDef = typeSig.TryGetTypeDef(); + return typeDef != null ? SystemToStringType(typeDef) : CheckSystemType(typeSig); } - private static string ConvertGenericType(GenericInstanceType genericInstance) + private static string CheckSystemType(TypeSig typeSig) { - var baseType = genericInstance.ElementType.Name; + if (TypeMap.TryGetValue(typeSig.FullName, out var type)) + return type; + + var name = typeSig.TypeName; + var ns = typeSig.Namespace ?? ""; + if (ns.StartsWith("System")) + Log.Global.LogUnknownSystemType(name); + + return name; + } + + private static string ConvertGenericType(GenericInstSig genericInstance) + { + var baseType = genericInstance.GenericType.TypeName; if (baseType.Contains('`')) baseType = baseType[..baseType.IndexOf('`')]; @@ -47,14 +66,16 @@ private static string ConvertGenericType(GenericInstanceType genericInstance) return $"{baseType}<{genericArgs}>"; } - public static string SystemToStringType(TypeDefinition typeDef) + public static string SystemToStringType(TypeDef typeDef) { var fullName = typeDef.FullName; if (TypeMap.TryGetValue(fullName, out var type)) return type; - var name = typeDef.Name; - if (name.StartsWith("System.")) + var name = typeDef.Name.String; + var ns = typeDef.Namespace?.String ?? ""; + + if (ns.StartsWith("System")) Log.Global.LogUnknownSystemType(name); return name; diff --git a/CLI/Parser.cs b/CLI/Parser.cs index 92b8a5b..8fbe110 100644 --- a/CLI/Parser.cs +++ b/CLI/Parser.cs @@ -2,7 +2,7 @@ using MemoryPackDumper.Context; using MemoryPackDumper.Helpers; using MemoryPackDumper.Services; -using Mono.Cecil; +using dnlib.DotNet; using ZLinq; namespace MemoryPackDumper.CLI; @@ -15,7 +15,7 @@ public static class Parser private static bool _splitClass; public static string? NameSpace2LookFor; public static string? Type2LookFor; - public static readonly List MemoryPackEnumsToAdd = []; + public static readonly List MemoryPackEnumsToAdd = []; public static bool SuppressWarnings; public static void Execute(string dummyDll, string outputFile, string nameSpace, @@ -41,12 +41,10 @@ public static void Execute(string dummyDll, string outputFile, string nameSpace, Environment.Exit(1); } - var resolver = new DefaultAssemblyResolver(); - resolver.AddSearchDirectory(_dummyAssemblyDir); - var readerParameters = new ReaderParameters - { - AssemblyResolver = resolver - }; + var assemblyResolver = new AssemblyResolver(); + assemblyResolver.PreSearchPaths.Add(_dummyAssemblyDir); + var moduleContext = new ModuleContext(assemblyResolver); + var readerParameters = new ModuleCreationOptions(moduleContext); Log.Info("Reading game assemblies..."); @@ -81,15 +79,15 @@ .. Directory.GetFiles(_dummyAssemblyDir, "*.dll") Log.Info($"Processing {dllPaths.Count} DLLs from directory"); } - var assemblies = new List(); - var allMemoryPackableTypes = new List(); + var modules = new List(); + var allMemoryPackableTypes = new List(); foreach (var dllPath in dllPaths) try { - var assembly = AssemblyDefinition.ReadAssembly(dllPath, readerParameters); - assemblies.Add(assembly); - var types = TypeHelper.GetAllMemoryPackableTypes(assembly.MainModule); + var module = ModuleDefMD.Load(dllPath, readerParameters); + modules.Add(module); + var types = TypeHelper.GetAllMemoryPackableTypes(module); allMemoryPackableTypes.AddRange(types); if (verbose) Log.Debug($"Found {types.Count} MemoryPackable types in {Path.GetFileName(dllPath)}"); } @@ -111,10 +109,10 @@ .. Directory.GetFiles(_dummyAssemblyDir, "*.dll") if (!processedTypes.Add(typeFullName)) continue; - TypeDefinition? typeDef = null; - foreach (var assembly in assemblies) + TypeDef? typeDef = null; + foreach (var module in modules) { - typeDef = assembly.MainModule.GetTypes().AsValueEnumerable() + typeDef = module.GetTypes().AsValueEnumerable() .FirstOrDefault(t => t.FullName == typeFullName); if (typeDef != null) break; } diff --git a/MemoryPackDumper.csproj b/MemoryPackDumper.csproj index 61dde35..05a8c84 100644 --- a/MemoryPackDumper.csproj +++ b/MemoryPackDumper.csproj @@ -1,4 +1,4 @@ - + Exe @@ -21,10 +21,13 @@ - + + + + From c9c8342f084e9754d0e4d7aebdd3c6b40aa7cce3 Mon Sep 17 00:00:00 2001 From: Deathemonic Date: Sat, 10 Jan 2026 20:12:42 +0800 Subject: [PATCH 3/9] fix: enums not parsing --- Assembly/TypeReferenceTracker.cs | 37 ++++++++++++++++++++++++-------- CLI/Parser.cs | 3 +-- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/Assembly/TypeReferenceTracker.cs b/Assembly/TypeReferenceTracker.cs index b138449..31546f2 100644 --- a/Assembly/TypeReferenceTracker.cs +++ b/Assembly/TypeReferenceTracker.cs @@ -8,21 +8,40 @@ public static class TypeReferenceTracker { public static void TrackReferencedType(TypeSig typeSig, HashSet discoveredTypes) { - var typeDef = typeSig.TryGetTypeDef(); - if (typeDef == null) - return; + switch (typeSig) + { + case GenericInstSig genericSig: + foreach (var genericArg in genericSig.GenericArguments.AsValueEnumerable()) + TrackReferencedType(genericArg, discoveredTypes); + TrackTypeDefOrRef(genericSig.GenericType?.TypeDefOrRef, discoveredTypes); + break; + case SZArraySig szArraySig: + TrackReferencedType(szArraySig.Next, discoveredTypes); + break; + case ArraySig arraySig: + TrackReferencedType(arraySig.Next, discoveredTypes); + break; + default: + TrackTypeDefOrRef(typeSig.ToTypeDefOrRef(), discoveredTypes); + break; + } + } - if (typeDef.IsEnum && !Parser.MemoryPackEnumsToAdd.Contains(typeDef)) + private static void TrackTypeDefOrRef(ITypeDefOrRef? typeDefOrRef, HashSet discoveredTypes) + { + if (typeDefOrRef == null) return; + + var typeDef = typeDefOrRef.ResolveTypeDef(); + if (typeDef == null) return; + + if (typeDef.IsEnum && !Parser.MemoryPackEnumsToAdd.AsValueEnumerable().Any(e => e.FullName == typeDef.FullName)) { Parser.MemoryPackEnumsToAdd.Add(typeDef); return; } - if (IsMemoryPackable(typeDef)) discoveredTypes.Add(typeDef.FullName); - - if (typeSig is not GenericInstSig genericInstance) return; - foreach (var genericArg in genericInstance.GenericArguments.AsValueEnumerable()) - TrackReferencedType(genericArg, discoveredTypes); + if (IsMemoryPackable(typeDef)) + discoveredTypes.Add(typeDef.FullName); } private static bool IsMemoryPackable(TypeDef typeDef) diff --git a/CLI/Parser.cs b/CLI/Parser.cs index 8fbe110..d7d4216 100644 --- a/CLI/Parser.cs +++ b/CLI/Parser.cs @@ -112,8 +112,7 @@ .. Directory.GetFiles(_dummyAssemblyDir, "*.dll") TypeDef? typeDef = null; foreach (var module in modules) { - typeDef = module.GetTypes().AsValueEnumerable() - .FirstOrDefault(t => t.FullName == typeFullName); + typeDef = module.Find(typeFullName, false); if (typeDef != null) break; } From 577c71b35afcd26f032b3cedbc9e6350f9b66057 Mon Sep 17 00:00:00 2001 From: Deathemonic Date: Sat, 10 Jan 2026 20:32:25 +0800 Subject: [PATCH 4/9] fix: enum underlying type --- Assembly/MemberParser.cs | 32 +++++++++++++++++---------- Assembly/MemoryPackTypes.cs | 4 ++-- Assembly/TypeHelper.cs | 41 +++++++++++++++++++++++------------ Services/CodeWriterService.cs | 3 +-- 4 files changed, 51 insertions(+), 29 deletions(-) diff --git a/Assembly/MemberParser.cs b/Assembly/MemberParser.cs index a7c27d6..87c7d36 100644 --- a/Assembly/MemberParser.cs +++ b/Assembly/MemberParser.cs @@ -210,8 +210,8 @@ private static MemoryPackMember CreateMemberFromField(FieldDef field) public static MemoryPackEnum TypeToEnum(TypeDef typeDef) { - var underlyingType = GetEnumUnderlyingType(typeDef); - var memoryPackEnum = new MemoryPackEnum(underlyingType, typeDef.Name) + var underlyingTypeName = GetEnumUnderlyingTypeName(typeDef); + var memoryPackEnum = new MemoryPackEnum(underlyingTypeName, typeDef.Name) { OriginalNamespace = typeDef.Namespace ?? "" }; @@ -225,16 +225,26 @@ public static MemoryPackEnum TypeToEnum(TypeDef typeDef) return memoryPackEnum; } - private static TypeDef GetEnumUnderlyingType(TypeDef typeDef) + private static string GetEnumUnderlyingTypeName(TypeDef typeDef) { - var underlyingType = typeDef.Fields.FirstOrDefault(f => f.Name == "value__")?.FieldType.TryGetTypeDef(); - if (underlyingType != null) return underlyingType; - - Log.Warning($"Could not determine underlying type for enum {typeDef.FullName}"); - // dnlib doesn't have a direct TypeSystem accessor from ModuleDef in the same way, need access to a known type or context. - // Assuming int32 as fallback if not found. - // But ModuleDef has CorLibTypes. - return typeDef.Module.CorLibTypes.Int32.TypeDefOrRef.ResolveTypeDef(); + var valueField = typeDef.Fields.FirstOrDefault(f => f.Name == "value__"); + if (valueField != null) + { + return valueField.FieldType.FullName switch + { + "System.Byte" => "byte", + "System.SByte" => "sbyte", + "System.Int16" => "short", + "System.UInt16" => "ushort", + "System.Int32" => "int", + "System.UInt32" => "uint", + "System.Int64" => "long", + "System.UInt64" => "ulong", + _ => "int" + }; + } + + return "int"; } private static void ProcessNestedTypes(TypeDef typeDef, MemoryPackClass memoryPackClass, diff --git a/Assembly/MemoryPackTypes.cs b/Assembly/MemoryPackTypes.cs index bc33e6b..1c5b125 100644 --- a/Assembly/MemoryPackTypes.cs +++ b/Assembly/MemoryPackTypes.cs @@ -59,11 +59,11 @@ public class MemoryPackMember(string name, TypeSig type, bool isField) public bool SuppressDefaultInitialization = false; } -public class MemoryPackEnum(TypeDef valueType, string enumName) +public class MemoryPackEnum(string underlyingType, string enumName) { public readonly string EnumName = enumName; public readonly List Fields = []; - public readonly TypeDef Type = valueType; + public readonly string UnderlyingType = underlyingType; public string OriginalNamespace = ""; } diff --git a/Assembly/TypeHelper.cs b/Assembly/TypeHelper.cs index b10ec94..fe75e25 100644 --- a/Assembly/TypeHelper.cs +++ b/Assembly/TypeHelper.cs @@ -138,8 +138,7 @@ public static void CollectNamespacesForSplitFile(TypeSig typeSig, HashSet namespaces, + private static void AddNamespaceForSplitFile(ITypeDefOrRef? typeRef, HashSet namespaces, string currentFileNamespace) { - if (typeDef == null) return; - var ns = typeDef.Namespace?.String; - if (string.IsNullOrEmpty(ns)) return; + if (typeRef == null) return; - if (ns == "System" || ns.StartsWith("System.") || ns == "UnityEngine") + var nsUtf8 = typeRef.Namespace; + if (UTF8String.IsNullOrEmpty(nsUtf8)) return; + + var ns = nsUtf8.ToString(); + if (ns == "System" || ns.StartsWith("System.")) + { + namespaces.Add(ns); + return; + } + + if (ns == "UnityEngine") { - AddNamespaceIfNeeded(typeDef, namespaces); + var name = typeRef.Name?.ToString(); + switch (name) + { + case "Vector2": + case "Vector3": + case "Vector4": + case "Quaternion": + case "Matrix4x4": + namespaces.Add("System.Numerics"); + break; + } return; } diff --git a/Services/CodeWriterService.cs b/Services/CodeWriterService.cs index 1d09fba..f1ee903 100644 --- a/Services/CodeWriterService.cs +++ b/Services/CodeWriterService.cs @@ -56,8 +56,7 @@ public static void WriteEnum(ref Utf8StringWriter { var actualIndent = context.actualIndent; - var enumTypeName = TypeStringConverter.SystemToStringType(context.@enum.Type); - writer.AppendFormat($"{actualIndent}public enum {context.@enum.EnumName} : {enumTypeName}\n"); + writer.AppendFormat($"{actualIndent}public enum {context.@enum.EnumName} : {context.@enum.UnderlyingType}\n"); writer.AppendFormat($"{actualIndent}{{\n"); for (var i = 0; i < context.@enum.Fields.Count; i++) From 5a2b8f390bb406c04128a181ad669b304d5c70e8 Mon Sep 17 00:00:00 2001 From: Deathemonic Date: Sat, 10 Jan 2026 20:40:32 +0800 Subject: [PATCH 5/9] fix: system types --- Assembly/TypeStringConverter.cs | 58 +++++++++------------------------ 1 file changed, 16 insertions(+), 42 deletions(-) diff --git a/Assembly/TypeStringConverter.cs b/Assembly/TypeStringConverter.cs index 283598a..c50d645 100644 --- a/Assembly/TypeStringConverter.cs +++ b/Assembly/TypeStringConverter.cs @@ -1,12 +1,12 @@ +using System.Collections.Frozen; using dnlib.DotNet; -using MemoryPackDumper.Helpers; using ZLinq; namespace MemoryPackDumper.Assembly; public static class TypeStringConverter { - private static readonly Dictionary TypeMap = new() + private static readonly FrozenDictionary TypeMap = new Dictionary { ["System.String"] = "string", ["System.Int16"] = "short", @@ -20,46 +20,30 @@ public static class TypeStringConverter ["System.Double"] = "double", ["System.SByte"] = "sbyte", ["System.Byte"] = "byte", - ["System.Decimal"] = "decimal" - }; + ["System.Decimal"] = "decimal", + ["System.Object"] = "object", + ["System.Void"] = "void", + ["System.Char"] = "char", + ["System.IntPtr"] = "nint", + ["System.UIntPtr"] = "nuint" + }.ToFrozenDictionary(); public static string TypeToString(TypeSig typeSig) { if (typeSig == null) return "void"; - if (typeSig is GenericInstSig genericInstance) return ConvertGenericType(genericInstance); - - if (typeSig is SZArraySig szArray) - { - return TypeToString(szArray.Next) + "[]"; - } - - if (typeSig is ArraySig array) + return typeSig switch { - return TypeToString(array.Next) + "[]"; - } - - var typeDef = typeSig.TryGetTypeDef(); - return typeDef != null ? SystemToStringType(typeDef) : CheckSystemType(typeSig); - } - - private static string CheckSystemType(TypeSig typeSig) - { - if (TypeMap.TryGetValue(typeSig.FullName, out var type)) - return type; - - var name = typeSig.TypeName; - var ns = typeSig.Namespace ?? ""; - if (ns.StartsWith("System")) - Log.Global.LogUnknownSystemType(name); - - return name; + GenericInstSig genericInstance => ConvertGenericType(genericInstance), + SZArraySig szArray => TypeToString(szArray.Next) + "[]", + ArraySig array => TypeToString(array.Next) + "[]", + _ => TypeMap.GetValueOrDefault(typeSig.FullName, typeSig.TypeName) + }; } private static string ConvertGenericType(GenericInstSig genericInstance) { var baseType = genericInstance.GenericType.TypeName; - if (baseType.Contains('`')) baseType = baseType[..baseType.IndexOf('`')]; var genericArgs = genericInstance.GenericArguments.AsValueEnumerable().Select(TypeToString).JoinToString(", "); @@ -68,16 +52,6 @@ private static string ConvertGenericType(GenericInstSig genericInstance) public static string SystemToStringType(TypeDef typeDef) { - var fullName = typeDef.FullName; - if (TypeMap.TryGetValue(fullName, out var type)) - return type; - - var name = typeDef.Name.String; - var ns = typeDef.Namespace?.String ?? ""; - - if (ns.StartsWith("System")) - Log.Global.LogUnknownSystemType(name); - - return name; + return TypeMap.GetValueOrDefault(typeDef.FullName, typeDef.Name.String); } } \ No newline at end of file From 6f3b881f6bc874b06186e88381b3ad6df7b7dd31 Mon Sep 17 00:00:00 2001 From: Deathemonic Date: Sat, 10 Jan 2026 21:05:19 +0800 Subject: [PATCH 6/9] feat: add --allow-hidden --- Assembly/MemberParser.cs | 2 ++ Assembly/TypeHelper.cs | 17 ++++++----- Assembly/TypeReferenceTracker.cs | 7 +++-- CLI/Arguments.cs | 4 ++- CLI/Parser.cs | 52 +++++++++++++------------------- Context/ParserOptionsContext.cs | 14 +++++++++ Helpers/Logger.cs | 8 ++--- Services/CodeWriterService.cs | 1 - 8 files changed, 57 insertions(+), 48 deletions(-) create mode 100644 Context/ParserOptionsContext.cs diff --git a/Assembly/MemberParser.cs b/Assembly/MemberParser.cs index 87c7d36..e5967a7 100644 --- a/Assembly/MemberParser.cs +++ b/Assembly/MemberParser.cs @@ -1,3 +1,4 @@ +using MemoryPackDumper.Context; using MemoryPackDumper.Helpers; using dnlib.DotNet; using ZLinq; @@ -81,6 +82,7 @@ private static void ProcessFields(TypeDef typeDef, MemoryPackClass memoryPackCla private static bool ShouldIncludeMember(MemoryPackMember member, bool isPublic) { + if (ParserOptionsContext.Current.AllowHidden) return !member.IsIgnored; return member.IsInclude || (!member.IsIgnored && isPublic); } diff --git a/Assembly/TypeHelper.cs b/Assembly/TypeHelper.cs index fe75e25..89ff7d2 100644 --- a/Assembly/TypeHelper.cs +++ b/Assembly/TypeHelper.cs @@ -1,4 +1,4 @@ -using MemoryPackDumper.CLI; +using MemoryPackDumper.Context; using dnlib.DotNet; using ZLinq; @@ -16,20 +16,21 @@ .. module.GetTypes().AsValueEnumerable().Where(t => ).ToArray() ]; - if (!string.IsNullOrEmpty(Parser.NameSpace2LookFor)) - ret = [.. ret.AsValueEnumerable().Where(t => t.Namespace == Parser.NameSpace2LookFor).ToArray()]; + var opts = ParserOptionsContext.Current; - if (!string.IsNullOrEmpty(Parser.Type2LookFor)) + if (!string.IsNullOrEmpty(opts.NamespaceToLookFor)) + ret = [.. ret.AsValueEnumerable().Where(t => t.Namespace == opts.NamespaceToLookFor).ToArray()]; + + if (!string.IsNullOrEmpty(opts.TypeToLookFor)) ret = [ .. ret.AsValueEnumerable().Where(t => - t.Name == Parser.Type2LookFor || - (t.BaseType != null && t.BaseType.Name == Parser.Type2LookFor) || - IsSubTypeOf(t, Parser.Type2LookFor) + t.Name == opts.TypeToLookFor || + (t.BaseType != null && t.BaseType.Name == opts.TypeToLookFor) || + IsSubTypeOf(t, opts.TypeToLookFor) ).ToArray() ]; - // Dedupe ret = [..ret.AsValueEnumerable().DistinctBy(t => t.FullName).ToArray()]; return ret; diff --git a/Assembly/TypeReferenceTracker.cs b/Assembly/TypeReferenceTracker.cs index 31546f2..fb30575 100644 --- a/Assembly/TypeReferenceTracker.cs +++ b/Assembly/TypeReferenceTracker.cs @@ -1,4 +1,4 @@ -using MemoryPackDumper.CLI; +using MemoryPackDumper.Context; using dnlib.DotNet; using ZLinq; @@ -34,9 +34,10 @@ private static void TrackTypeDefOrRef(ITypeDefOrRef? typeDefOrRef, HashSet e.FullName == typeDef.FullName)) + var enums = ParserOptionsContext.Current.DiscoveredEnums; + if (typeDef.IsEnum && !enums.AsValueEnumerable().Any(e => e.FullName == typeDef.FullName)) { - Parser.MemoryPackEnumsToAdd.Add(typeDef); + enums.Add(typeDef); return; } diff --git a/CLI/Arguments.cs b/CLI/Arguments.cs index e790b6c..01ae827 100644 --- a/CLI/Arguments.cs +++ b/CLI/Arguments.cs @@ -12,6 +12,7 @@ public static class Args /// -tl, Specifies the type to look for /// -t, Specifies a specific DLL to process (if not set, processes all DLLs) /// -sc, Split classes into individual files organized by namespace + /// -ah, Include private, protected, and internal members in output. /// -v, Enable verbose debug logging. /// -sw, Suppress warning messages. public static void Run( @@ -22,9 +23,10 @@ public static void Run( string? typeToLookFor = null, string? targetDll = null, bool splitClass = false, + bool allowHidden = false, bool verbose = false, bool suppressWarnings = false) { - Parser.Execute(dummyDll, outputFile, @namespace, namespaceToLookFor, typeToLookFor, targetDll, splitClass, verbose, suppressWarnings); + Parser.Execute(dummyDll, outputFile, @namespace, namespaceToLookFor, typeToLookFor, targetDll, splitClass, allowHidden, verbose, suppressWarnings); } } \ No newline at end of file diff --git a/CLI/Parser.cs b/CLI/Parser.cs index d7d4216..4864632 100644 --- a/CLI/Parser.cs +++ b/CLI/Parser.cs @@ -9,50 +9,40 @@ namespace MemoryPackDumper.CLI; public static class Parser { - private static string _dummyAssemblyDir = "DummyDll"; - private static string _outputFileName = "MemoryPack.cs"; - private static string? _customNameSpace = "MemoryPackData"; - private static bool _splitClass; - public static string? NameSpace2LookFor; - public static string? Type2LookFor; - public static readonly List MemoryPackEnumsToAdd = []; - public static bool SuppressWarnings; - public static void Execute(string dummyDll, string outputFile, string nameSpace, - string? namespaceToLookFor, string? type2LookFor, string? targetDll, bool splitClass, bool verbose, - bool suppressWarnings) + string? namespaceToLookFor, string? type2LookFor, string? targetDll, bool splitClass, bool allowHidden, + bool verbose, bool suppressWarnings) { - if (verbose) Log.EnableDebugLogging(); - - SuppressWarnings = suppressWarnings; + ParserOptionsContext.Current = new ParserOptionsContext + { + SuppressWarnings = suppressWarnings, + AllowHidden = allowHidden, + NamespaceToLookFor = namespaceToLookFor, + TypeToLookFor = type2LookFor + }; - _dummyAssemblyDir = dummyDll; - _outputFileName = outputFile; - _customNameSpace = nameSpace; - _splitClass = splitClass; - NameSpace2LookFor = namespaceToLookFor; - Type2LookFor = type2LookFor; + if (verbose) Log.EnableDebugLogging(); - if (!Directory.Exists(_dummyAssemblyDir)) + if (!Directory.Exists(dummyDll)) { - Log.Global.LogDummyDirNotFound(_dummyAssemblyDir); + Log.Global.LogDummyDirNotFound(dummyDll); Log.Error("Please provide a valid path using -dummydll or -d."); Log.Shutdown(); Environment.Exit(1); } var assemblyResolver = new AssemblyResolver(); - assemblyResolver.PreSearchPaths.Add(_dummyAssemblyDir); + assemblyResolver.PreSearchPaths.Add(dummyDll); var moduleContext = new ModuleContext(assemblyResolver); var readerParameters = new ModuleCreationOptions(moduleContext); Log.Info("Reading game assemblies..."); List dllPaths = !string.IsNullOrEmpty(targetDll) - ? [Path.Combine(_dummyAssemblyDir, targetDll)] + ? [Path.Combine(dummyDll, targetDll)] : [ - .. Directory.GetFiles(_dummyAssemblyDir, "*.dll") + .. Directory.GetFiles(dummyDll, "*.dll") .AsValueEnumerable() .Where(path => { @@ -67,7 +57,7 @@ .. Directory.GetFiles(_dummyAssemblyDir, "*.dll") { if (!File.Exists(dllPaths[0])) { - Log.Global.LogFileNotFound(targetDll, _dummyAssemblyDir); + Log.Global.LogFileNotFound(targetDll, dummyDll); Log.Shutdown(); Environment.Exit(1); } @@ -130,19 +120,19 @@ .. Directory.GetFiles(_dummyAssemblyDir, "*.dll") } Log.Info("Adding enums..."); - foreach (var fEnum in MemoryPackEnumsToAdd.AsValueEnumerable().Select(MemberParser.TypeToEnum)) + foreach (var fEnum in ParserOptionsContext.Current.DiscoveredEnums.AsValueEnumerable().Select(MemberParser.TypeToEnum)) schema.Enums.Add(fEnum); - var context = new CodeGenerationContext(_customNameSpace, _splitClass, _outputFileName); + var context = new CodeGenerationContext(nameSpace, splitClass, outputFile); - if (_splitClass) + if (splitClass) { - Log.Info($"Writing split C# files to {_outputFileName}/..."); + Log.Info($"Writing split C# files to {outputFile}/..."); FileGeneratorService.WriteSplitFiles(schema, context); } else { - Log.Info($"Writing C# code to {_outputFileName}..."); + Log.Info($"Writing C# code to {outputFile}..."); FileGeneratorService.WriteSingleFile(schema, context); } diff --git a/Context/ParserOptionsContext.cs b/Context/ParserOptionsContext.cs new file mode 100644 index 0000000..683fda4 --- /dev/null +++ b/Context/ParserOptionsContext.cs @@ -0,0 +1,14 @@ +using dnlib.DotNet; + +namespace MemoryPackDumper.Context; + +public sealed class ParserOptionsContext +{ + public static ParserOptionsContext Current { get; set; } = new(); + + public bool SuppressWarnings { get; init; } + public bool AllowHidden { get; init; } + public string? NamespaceToLookFor { get; init; } + public string? TypeToLookFor { get; init; } + public List DiscoveredEnums { get; } = []; +} diff --git a/Helpers/Logger.cs b/Helpers/Logger.cs index 149b6f6..a59657e 100644 --- a/Helpers/Logger.cs +++ b/Helpers/Logger.cs @@ -1,5 +1,5 @@ using Kokuban; -using MemoryPackDumper.CLI; +using MemoryPackDumper.Context; using Microsoft.Extensions.Logging; using ZLogger; @@ -87,7 +87,7 @@ public static void Error(string message, Exception exception) public static void Warning(string message) { - if (Parser.SuppressWarnings) return; + if (ParserOptionsContext.Current.SuppressWarnings) return; EnsureInitialized(); _logger!.ZLogWarning($"{message}"); @@ -134,7 +134,7 @@ public static partial class LogMessages public static void LogUnknownSystemType(this ILogger logger, string typeName) { - if (!Parser.SuppressWarnings) logger.LogUnknownSystemTypeInternal(typeName); + if (!ParserOptionsContext.Current.SuppressWarnings) logger.LogUnknownSystemTypeInternal(typeName); } [ZLoggerMessage(LogLevel.Debug, "\t0x{address:X}: {mnemonic} {operand}")] @@ -145,6 +145,6 @@ public static void LogUnknownSystemType(this ILogger logger, string typeName) public static void LogSkippingCall(this ILogger logger, ulong address, string reason) { - if (!Parser.SuppressWarnings) logger.LogSkippingCallInternal(address, reason); + if (!ParserOptionsContext.Current.SuppressWarnings) logger.LogSkippingCallInternal(address, reason); } } \ No newline at end of file diff --git a/Services/CodeWriterService.cs b/Services/CodeWriterService.cs index f1ee903..3e97070 100644 --- a/Services/CodeWriterService.cs +++ b/Services/CodeWriterService.cs @@ -40,7 +40,6 @@ public static void WriteClass(ref Utf8StringWriter new MethodWriteContext(method, actualIndent, context.@class.ClassName))) WriteMethod(ref writer, methodContext); - // Write nested classes foreach (var nestedClass in context.@class.NestedClasses) { writer.AppendLine(); From 8e9174b7e6328b72f925051f0fd3b4b74689b2e6 Mon Sep 17 00:00:00 2001 From: Deathemonic Date: Sat, 10 Jan 2026 21:18:17 +0800 Subject: [PATCH 7/9] fix: not reading from il namespaces --- Assembly/MemberParser.cs | 9 ++++++++- Assembly/TypeHelper.cs | 29 +++++++++++++---------------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/Assembly/MemberParser.cs b/Assembly/MemberParser.cs index e5967a7..1b8da8b 100644 --- a/Assembly/MemberParser.cs +++ b/Assembly/MemberParser.cs @@ -70,7 +70,8 @@ private static void ProcessProperties(TypeDef typeDef, MemoryPackClass memoryPac private static void ProcessFields(TypeDef typeDef, MemoryPackClass memoryPackClass, HashSet discoveredTypes) { - foreach (var field in typeDef.Fields.AsValueEnumerable().Where(f => !f.IsStatic && !f.IsLiteral)) + foreach (var field in typeDef.Fields.AsValueEnumerable() + .Where(f => !f.IsStatic && !f.IsLiteral && !IsCompilerGeneratedBackingField(f))) { var member = CreateMemberFromField(field); if (!ShouldIncludeMember(member, field.IsPublic)) continue; @@ -80,6 +81,12 @@ private static void ProcessFields(TypeDef typeDef, MemoryPackClass memoryPackCla } } + private static bool IsCompilerGeneratedBackingField(FieldDef field) + { + var name = field.Name.String; + return name.StartsWith("<") && name.EndsWith(">k__BackingField"); + } + private static bool ShouldIncludeMember(MemoryPackMember member, bool isPublic) { if (ParserOptionsContext.Current.AllowHidden) return !member.IsIgnored; diff --git a/Assembly/TypeHelper.cs b/Assembly/TypeHelper.cs index 89ff7d2..4a9a21a 100644 --- a/Assembly/TypeHelper.cs +++ b/Assembly/TypeHelper.cs @@ -70,8 +70,7 @@ public static void CollectNamespaces(TypeSig typeSig, HashSet namespaces { case GenericInstSig genericType: { - var elementType = genericType.GenericType.ToTypeDefOrRef().ResolveTypeDef(); - AddNamespaceIfNeeded(elementType, namespaces); + AddNamespaceIfNeeded(genericType.GenericType?.TypeDefOrRef, namespaces); foreach (var arg in genericType.GenericArguments) CollectNamespaces(arg, namespaces); @@ -84,11 +83,8 @@ public static void CollectNamespaces(TypeSig typeSig, HashSet namespaces CollectNamespaces(arrayType.Next, namespaces); break; default: - { - var resolved = typeSig.TryGetTypeDef(); - AddNamespaceIfNeeded(resolved, namespaces); + AddNamespaceIfNeeded(typeSig.ToTypeDefOrRef(), namespaces); break; - } } } @@ -102,24 +98,25 @@ public static void CollectNamespaces(ITypeDefOrRef? typeRef, HashSet nam return; } - var resolved = typeRef.ResolveTypeDef(); - AddNamespaceIfNeeded(resolved, namespaces); + AddNamespaceIfNeeded(typeRef, namespaces); } - private static void AddNamespaceIfNeeded(TypeDef? typeDef, HashSet namespaces) + private static void AddNamespaceIfNeeded(ITypeDefOrRef? typeRef, HashSet namespaces) { - if (typeDef == null) return; - var ns = typeDef.Namespace?.String; - if (string.IsNullOrEmpty(ns)) return; + if (typeRef == null) return; - if (ns.StartsWith("System.")) + var ns = typeRef.Namespace; + if (UTF8String.IsNullOrEmpty(ns)) return; + + var nsStr = ns.ToString(); + if (nsStr.StartsWith("System.")) { - namespaces.Add(ns); + namespaces.Add(nsStr); return; } - if (ns != "UnityEngine") return; - var name = typeDef.Name?.String; + if (nsStr != "UnityEngine") return; + var name = typeRef.Name?.String; switch (name) { case "Vector2": From 5a0b88b16560fdc898e89fa14d8729962e69afe4 Mon Sep 17 00:00:00 2001 From: Deathemonic Date: Sat, 10 Jan 2026 21:45:19 +0800 Subject: [PATCH 8/9] refactor: code cleanup --- Assembly/AttributeExtractor.cs | 2 +- Assembly/MemberParser.cs | 31 +++++++----------- Assembly/MemoryPackTypes.cs | 2 +- Assembly/TypeHelper.cs | 55 ++++++++++++++++---------------- Assembly/TypeReferenceTracker.cs | 8 ++--- Assembly/TypeStringConverter.cs | 7 +--- CLI/Parser.cs | 15 +++++---- Context/ParserOptionsContext.cs | 14 ++++---- Helpers/Logger.cs | 6 ++-- README.md | 1 + Services/FileGeneratorService.cs | 2 -- 11 files changed, 65 insertions(+), 78 deletions(-) diff --git a/Assembly/AttributeExtractor.cs b/Assembly/AttributeExtractor.cs index 087aafc..e8ab5e3 100644 --- a/Assembly/AttributeExtractor.cs +++ b/Assembly/AttributeExtractor.cs @@ -38,7 +38,7 @@ private static void ExtractMemoryPackableAttribute(CustomAttribute attr, MemoryP else { var layoutProp = attr.NamedArguments.FirstOrDefault(p => p.Name == "SerializeLayout"); - if (layoutProp != null && layoutProp.Argument.Value != null) + if (layoutProp is { Argument.Value: not null }) memoryPackClass.SerializeLayout = EnumMapper.MapSerializeLayout(layoutProp.Argument.Value.ToString()!); } } diff --git a/Assembly/MemberParser.cs b/Assembly/MemberParser.cs index 1b8da8b..7fef96a 100644 --- a/Assembly/MemberParser.cs +++ b/Assembly/MemberParser.cs @@ -1,6 +1,5 @@ -using MemoryPackDumper.Context; -using MemoryPackDumper.Helpers; using dnlib.DotNet; +using MemoryPackDumper.Context; using ZLinq; namespace MemoryPackDumper.Assembly; @@ -84,12 +83,12 @@ private static void ProcessFields(TypeDef typeDef, MemoryPackClass memoryPackCla private static bool IsCompilerGeneratedBackingField(FieldDef field) { var name = field.Name.String; - return name.StartsWith("<") && name.EndsWith(">k__BackingField"); + return name.StartsWith('<') && name.EndsWith(">k__BackingField"); } private static bool ShouldIncludeMember(MemoryPackMember member, bool isPublic) { - if (ParserOptionsContext.Current.AllowHidden) return !member.IsIgnored; + if (ParserOptionsContext.current.allowHidden) return !member.IsIgnored; return member.IsInclude || (!member.IsIgnored && isPublic); } @@ -132,10 +131,7 @@ private static bool IsOverrideMethod(MethodDef method) if (method is not { IsVirtual: true, IsNewSlot: false, IsGetter: false, IsSetter: false }) return false; - if (method.Name == "Serialize" || method.Name == "Deserialize") - return false; - - return true; + return method.Name != "Serialize" && method.Name != "Deserialize"; } private static bool IsMemoryPackConstructor(MethodDef method) @@ -177,7 +173,7 @@ private static MemoryPackMethod CreateMethodFromDefinition(MethodDef methodDef) foreach (var param in methodDef.Parameters) { - if (param.IsHiddenThisParameter) continue; + if (param.IsHiddenThisParameter) continue; var paramType = TypeStringConverter.TypeToString(param.Type); method.Parameters.Add((paramType, param.Name)); @@ -238,7 +234,6 @@ private static string GetEnumUnderlyingTypeName(TypeDef typeDef) { var valueField = typeDef.Fields.FirstOrDefault(f => f.Name == "value__"); if (valueField != null) - { return valueField.FieldType.FullName switch { "System.Byte" => "byte", @@ -251,7 +246,6 @@ private static string GetEnumUnderlyingTypeName(TypeDef typeDef) "System.UInt64" => "ulong", _ => "int" }; - } return "int"; } @@ -281,15 +275,14 @@ private static bool IsAutoGeneratedFormatter(TypeDef nestedType, string parentCl var baseTypeName = nestedType.BaseType.Name.String; if (!baseTypeName.StartsWith("MemoryPackFormatter")) return false; - if (nestedType.BaseType is TypeSpec typeSpec && typeSpec.TypeSig is GenericInstSig genericBase && genericBase.GenericArguments.Count > 0) - { - var formattedTypeName = genericBase.GenericArguments[0].TypeName; - var parentBaseName = parentClassName.Contains('<') - ? parentClassName[..parentClassName.IndexOf('<')] - : parentClassName; + if (nestedType.BaseType is not TypeSpec { TypeSig: GenericInstSig genericBase } || + genericBase.GenericArguments.Count <= 0) return false; + var formattedTypeName = genericBase.GenericArguments[0].TypeName; + var parentBaseName = parentClassName.Contains('<') + ? parentClassName[..parentClassName.IndexOf('<')] + : parentClassName; - if (formattedTypeName == parentBaseName) return true; - } + if (formattedTypeName == parentBaseName) return true; return false; } diff --git a/Assembly/MemoryPackTypes.cs b/Assembly/MemoryPackTypes.cs index 1c5b125..aa31bf6 100644 --- a/Assembly/MemoryPackTypes.cs +++ b/Assembly/MemoryPackTypes.cs @@ -20,7 +20,7 @@ public class MemoryPackClass(string className, string baseClassName, string type public ITypeDefOrRef? BaseTypeReference = null; public string? GenerateType = null; public bool IsRecord = false; - public List NestedClasses = []; + public readonly List NestedClasses = []; public string OriginalNamespace = ""; public string? SerializeLayout = null; } diff --git a/Assembly/TypeHelper.cs b/Assembly/TypeHelper.cs index 4a9a21a..6ceaf6b 100644 --- a/Assembly/TypeHelper.cs +++ b/Assembly/TypeHelper.cs @@ -1,5 +1,5 @@ -using MemoryPackDumper.Context; using dnlib.DotNet; +using MemoryPackDumper.Context; using ZLinq; namespace MemoryPackDumper.Assembly; @@ -16,18 +16,18 @@ .. module.GetTypes().AsValueEnumerable().Where(t => ).ToArray() ]; - var opts = ParserOptionsContext.Current; + var opts = ParserOptionsContext.current; - if (!string.IsNullOrEmpty(opts.NamespaceToLookFor)) - ret = [.. ret.AsValueEnumerable().Where(t => t.Namespace == opts.NamespaceToLookFor).ToArray()]; + if (!string.IsNullOrEmpty(opts.namespaceToLookFor)) + ret = [.. ret.AsValueEnumerable().Where(t => t.Namespace == opts.namespaceToLookFor).ToArray()]; - if (!string.IsNullOrEmpty(opts.TypeToLookFor)) + if (!string.IsNullOrEmpty(opts.typeToLookFor)) ret = [ .. ret.AsValueEnumerable().Where(t => - t.Name == opts.TypeToLookFor || - (t.BaseType != null && t.BaseType.Name == opts.TypeToLookFor) || - IsSubTypeOf(t, opts.TypeToLookFor) + t.Name == opts.typeToLookFor || + (t.BaseType != null && t.BaseType.Name == opts.typeToLookFor) || + IsSubTypeOf(t, opts.typeToLookFor) ).ToArray() ]; @@ -53,9 +53,9 @@ public static string GetBaseType(TypeDef typeDef) { if (typeDef.BaseType == null || typeDef.BaseType.FullName == "System.Object" || typeDef.BaseType.FullName == "System.ValueType" || typeDef.BaseType.FullName == "System.Enum") return ""; - - if (typeDef.BaseType is TypeSpec typeSpec && typeSpec.TypeSig is GenericInstSig genericSig) - return TypeStringConverter.TypeToString(genericSig); + + if (typeDef.BaseType is TypeSpec { TypeSig: GenericInstSig genericSig }) + return TypeStringConverter.TypeToString(genericSig); var baseName = typeDef.BaseType.Name.String; if (baseName.Contains('`')) @@ -90,15 +90,17 @@ public static void CollectNamespaces(TypeSig typeSig, HashSet namespaces public static void CollectNamespaces(ITypeDefOrRef? typeRef, HashSet namespaces) { - if (typeRef == null) return; - - if (typeRef is TypeSpec typeSpec) + switch (typeRef) { - CollectNamespaces(typeSpec.TypeSig, namespaces); - return; + case null: + return; + case TypeSpec typeSpec: + CollectNamespaces(typeSpec.TypeSig, namespaces); + return; + default: + AddNamespaceIfNeeded(typeRef, namespaces); + break; } - - AddNamespaceIfNeeded(typeRef, namespaces); } private static void AddNamespaceIfNeeded(ITypeDefOrRef? typeRef, HashSet namespaces) @@ -108,14 +110,13 @@ private static void AddNamespaceIfNeeded(ITypeDefOrRef? typeRef, HashSet var ns = typeRef.Namespace; if (UTF8String.IsNullOrEmpty(ns)) return; - var nsStr = ns.ToString(); - if (nsStr.StartsWith("System.")) + if (ns.StartsWith("System.")) { - namespaces.Add(nsStr); + namespaces.Add(ns); return; } - if (nsStr != "UnityEngine") return; + if (ns != "UnityEngine") return; var name = typeRef.Name?.String; switch (name) { @@ -176,14 +177,13 @@ private static void AddNamespaceForSplitFile(ITypeDefOrRef? typeRef, HashSet discover private static void TrackTypeDefOrRef(ITypeDefOrRef? typeDefOrRef, HashSet discoveredTypes) { - if (typeDefOrRef == null) return; - - var typeDef = typeDefOrRef.ResolveTypeDef(); + var typeDef = typeDefOrRef?.ResolveTypeDef(); if (typeDef == null) return; - var enums = ParserOptionsContext.Current.DiscoveredEnums; + var enums = ParserOptionsContext.current.discoveredEnums; if (typeDef.IsEnum && !enums.AsValueEnumerable().Any(e => e.FullName == typeDef.FullName)) { enums.Add(typeDef); diff --git a/Assembly/TypeStringConverter.cs b/Assembly/TypeStringConverter.cs index c50d645..b96d373 100644 --- a/Assembly/TypeStringConverter.cs +++ b/Assembly/TypeStringConverter.cs @@ -28,7 +28,7 @@ public static class TypeStringConverter ["System.UIntPtr"] = "nuint" }.ToFrozenDictionary(); - public static string TypeToString(TypeSig typeSig) + public static string TypeToString(TypeSig? typeSig) { if (typeSig == null) return "void"; @@ -49,9 +49,4 @@ private static string ConvertGenericType(GenericInstSig genericInstance) var genericArgs = genericInstance.GenericArguments.AsValueEnumerable().Select(TypeToString).JoinToString(", "); return $"{baseType}<{genericArgs}>"; } - - public static string SystemToStringType(TypeDef typeDef) - { - return TypeMap.GetValueOrDefault(typeDef.FullName, typeDef.Name.String); - } } \ No newline at end of file diff --git a/CLI/Parser.cs b/CLI/Parser.cs index 4864632..c2583b9 100644 --- a/CLI/Parser.cs +++ b/CLI/Parser.cs @@ -1,8 +1,8 @@ +using dnlib.DotNet; using MemoryPackDumper.Assembly; using MemoryPackDumper.Context; using MemoryPackDumper.Helpers; using MemoryPackDumper.Services; -using dnlib.DotNet; using ZLinq; namespace MemoryPackDumper.CLI; @@ -13,12 +13,12 @@ public static void Execute(string dummyDll, string outputFile, string nameSpace, string? namespaceToLookFor, string? type2LookFor, string? targetDll, bool splitClass, bool allowHidden, bool verbose, bool suppressWarnings) { - ParserOptionsContext.Current = new ParserOptionsContext + ParserOptionsContext.current = new ParserOptionsContext { - SuppressWarnings = suppressWarnings, - AllowHidden = allowHidden, - NamespaceToLookFor = namespaceToLookFor, - TypeToLookFor = type2LookFor + suppressWarnings = suppressWarnings, + allowHidden = allowHidden, + namespaceToLookFor = namespaceToLookFor, + typeToLookFor = type2LookFor }; if (verbose) Log.EnableDebugLogging(); @@ -120,7 +120,8 @@ .. Directory.GetFiles(dummyDll, "*.dll") } Log.Info("Adding enums..."); - foreach (var fEnum in ParserOptionsContext.Current.DiscoveredEnums.AsValueEnumerable().Select(MemberParser.TypeToEnum)) + foreach (var fEnum in ParserOptionsContext.current.discoveredEnums.AsValueEnumerable() + .Select(MemberParser.TypeToEnum)) schema.Enums.Add(fEnum); var context = new CodeGenerationContext(nameSpace, splitClass, outputFile); diff --git a/Context/ParserOptionsContext.cs b/Context/ParserOptionsContext.cs index 683fda4..2eb8902 100644 --- a/Context/ParserOptionsContext.cs +++ b/Context/ParserOptionsContext.cs @@ -4,11 +4,11 @@ namespace MemoryPackDumper.Context; public sealed class ParserOptionsContext { - public static ParserOptionsContext Current { get; set; } = new(); + public static ParserOptionsContext current { get; set; } = new(); - public bool SuppressWarnings { get; init; } - public bool AllowHidden { get; init; } - public string? NamespaceToLookFor { get; init; } - public string? TypeToLookFor { get; init; } - public List DiscoveredEnums { get; } = []; -} + public bool suppressWarnings { get; init; } + public bool allowHidden { get; init; } + public string? namespaceToLookFor { get; init; } + public string? typeToLookFor { get; init; } + public List discoveredEnums { get; } = []; +} \ No newline at end of file diff --git a/Helpers/Logger.cs b/Helpers/Logger.cs index a59657e..da588b5 100644 --- a/Helpers/Logger.cs +++ b/Helpers/Logger.cs @@ -87,7 +87,7 @@ public static void Error(string message, Exception exception) public static void Warning(string message) { - if (ParserOptionsContext.Current.SuppressWarnings) return; + if (ParserOptionsContext.current.suppressWarnings) return; EnsureInitialized(); _logger!.ZLogWarning($"{message}"); @@ -134,7 +134,7 @@ public static partial class LogMessages public static void LogUnknownSystemType(this ILogger logger, string typeName) { - if (!ParserOptionsContext.Current.SuppressWarnings) logger.LogUnknownSystemTypeInternal(typeName); + if (!ParserOptionsContext.current.suppressWarnings) logger.LogUnknownSystemTypeInternal(typeName); } [ZLoggerMessage(LogLevel.Debug, "\t0x{address:X}: {mnemonic} {operand}")] @@ -145,6 +145,6 @@ public static void LogUnknownSystemType(this ILogger logger, string typeName) public static void LogSkippingCall(this ILogger logger, ulong address, string reason) { - if (!ParserOptionsContext.Current.SuppressWarnings) logger.LogSkippingCallInternal(address, reason); + if (!ParserOptionsContext.current.suppressWarnings) logger.LogSkippingCallInternal(address, reason); } } \ No newline at end of file diff --git a/README.md b/README.md index f2cb16a..d6a081d 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ dotnet build - `-o, --output-file`: Specifies the output file or directory when using --split-class (Default: MemoryPack.cs) - `-n, --namespace`: Specifies the C# namespace for generated classes (Default: MemoryPackData) - `-sc, --split-class`: Split classes into individual files organized by namespace folders +- `-ah, --allow-hidden`: Include private, protected, and internal members in output - `-nl, --namespace-to-look-for`: Specifies the namespace to look for (filters types) - `-tl, --type-to-look-for`: Specifies the type to look for (filters types) - `-t, --target-dll`: Specifies a specific DLL to process diff --git a/Services/FileGeneratorService.cs b/Services/FileGeneratorService.cs index bff912d..d457467 100644 --- a/Services/FileGeneratorService.cs +++ b/Services/FileGeneratorService.cs @@ -27,9 +27,7 @@ public static void WriteSingleFile(MemoryPackSchema schema, CodeGenerationContex stringWriter.AppendLine(); if (!string.IsNullOrEmpty(context.customNamespace)) - { stringWriter.AppendFormat($"namespace {context.customNamespace};\n\n"); - } var indent = string.IsNullOrEmpty(context.customNamespace) ? "" : null; From 0a84a1f80c326efe6d779f51aef40d9fb9f77e8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=83=92=E3=83=A4=E3=82=B7=E3=83=B3=E3=82=B9?= Date: Sun, 11 Jan 2026 07:48:18 +0800 Subject: [PATCH 9/9] chore: cleanup --- MemoryPackDumper.csproj | 4 ---- 1 file changed, 4 deletions(-) diff --git a/MemoryPackDumper.csproj b/MemoryPackDumper.csproj index 05a8c84..31f5cad 100644 --- a/MemoryPackDumper.csproj +++ b/MemoryPackDumper.csproj @@ -26,8 +26,4 @@ - - - -