diff --git a/Obsidian Notes/ReCodeIt/.obsidian/workspace.json b/Obsidian Notes/ReCodeIt/.obsidian/workspace.json index 1ac8b31..3fd305c 100644 --- a/Obsidian Notes/ReCodeIt/.obsidian/workspace.json +++ b/Obsidian Notes/ReCodeIt/.obsidian/workspace.json @@ -17,7 +17,7 @@ "viewState": { "x": -1324.3333740234375, "y": -365.66656494140625, - "zoom": 0 + "zoom": -0.6666666666666666 } } } diff --git a/Obsidian Notes/ReCodeIt/Untitled.canvas b/Obsidian Notes/ReCodeIt/Untitled.canvas index 118d7df..b3929ea 100644 --- a/Obsidian Notes/ReCodeIt/Untitled.canvas +++ b/Obsidian Notes/ReCodeIt/Untitled.canvas @@ -1,7 +1,12 @@ { "nodes":[ - {"id":"ffede66903965668","x":-1260,"y":-740,"width":660,"height":300,"color":"4","type":"text","text":"ReCodeIt Cross Compiler\n\n- "}, - {"id":"4116b6bff3d9eb35","x":-2020,"y":-740,"width":250,"height":460,"type":"text","text":"ReCodeItCrossCompiler\n\n"} + {"id":"02cecbc06ca4e27e","x":-2460,"y":-840,"width":680,"height":440,"type":"text","text":"Re-Mapper overhaul\n\n- More required parameters for better searches\n - Is Asbstract\n - Is Interface\n - Is Public"}, + {"id":"ef843881ce9f25ca","x":-1410,"y":-680,"width":170,"height":60,"type":"text","text":"Is Abstract"}, + {"id":"d0995cf4fa4e7306","x":-1194,"y":-840,"width":120,"height":60,"type":"text","text":"IsPublic"}, + {"id":"ef16782e8346c662","type":"text","text":"Is Interface","x":-1208,"y":-676,"width":149,"height":56} ], - "edges":[] + "edges":[ + {"id":"3e2076115efebf6f","fromNode":"d0995cf4fa4e7306","fromSide":"bottom","toNode":"ef843881ce9f25ca","toSide":"top"}, + {"id":"a7c1e1576f14002e","fromNode":"d0995cf4fa4e7306","fromSide":"bottom","toNode":"ef16782e8346c662","toSide":"top"} + ] } \ No newline at end of file diff --git a/ReCodeItCLI/Commands/Build.cs b/ReCodeItCLI/Commands/Build.cs index 1233834..0cd9def 100644 --- a/ReCodeItCLI/Commands/Build.cs +++ b/ReCodeItCLI/Commands/Build.cs @@ -26,6 +26,10 @@ public class Build : ICommand if (isRemote) { return; } await UseLastLoadedProject(console); + + // Wait for log termination + Logger.Terminate(); + while(Logger.IsRunning()) {} } private async Task UseLocalProject(IConsole console) diff --git a/ReCodeItCLI/Commands/BuildRef.cs b/ReCodeItCLI/Commands/BuildRef.cs index 5ebaf7d..063b3e5 100644 --- a/ReCodeItCLI/Commands/BuildRef.cs +++ b/ReCodeItCLI/Commands/BuildRef.cs @@ -30,9 +30,12 @@ public class BuildRef : ICommand CrossCompiler.StartRemap(); DataProvider.SaveAppSettings(); - return default; } + // Wait for log termination + Logger.Terminate(); + while(Logger.IsRunning()) {} + return default; } diff --git a/ReCodeItCLI/Commands/DeObfuscate.cs b/ReCodeItCLI/Commands/DeObfuscate.cs index ff5cd74..3b22553 100644 --- a/ReCodeItCLI/Commands/DeObfuscate.cs +++ b/ReCodeItCLI/Commands/DeObfuscate.cs @@ -23,6 +23,10 @@ public class DeObfuscate : ICommand Logger.Log("Complete", ConsoleColor.Green); + // Wait for log termination + Logger.Terminate(); + while(Logger.IsRunning()) {} + return default; } } \ No newline at end of file diff --git a/ReCodeItCLI/Commands/GenRefList.cs b/ReCodeItCLI/Commands/GenRefList.cs new file mode 100644 index 0000000..e4b3be1 --- /dev/null +++ b/ReCodeItCLI/Commands/GenRefList.cs @@ -0,0 +1,108 @@ +using CliFx; +using CliFx.Attributes; +using CliFx.Infrastructure; +using dnlib.DotNet; + +namespace ReCodeIt.Commands; + +[Command("GenRefCountList", Description = "Generates a print out of the most used classes. Useful to prioritize remap targets")] +public class GenRefList : ICommand +{ + [CommandParameter(0, IsRequired = true, Description = "The absolute path to your de-obfuscated dll, remapped dll.")] + public string AssemblyPath { get; init; } + + private static readonly List Match = new() + { + "Class", + "GClass", + "GInterface", + "Interface", + "GStruct" + }; + + public ValueTask ExecuteAsync(IConsole console) + { + var references = CountTypeReferences(AssemblyPath); + + // Sort and display the top 10 most referenced types + foreach (var pair in references.OrderByDescending(p => p.Value).Take(100)) + { + Console.WriteLine($"{pair.Key}: {pair.Value}"); + } + + return default; + } + + public static Dictionary CountTypeReferences(string assemblyPath) + { + var typeReferenceCounts = new Dictionary(); + + using (var module = ModuleDefMD.Load(assemblyPath)) + { + foreach (var type in module.GetTypes()) + { + CountReferencesInType(type, typeReferenceCounts); + } + } + + return typeReferenceCounts; + } + + private static void CountReferencesInType(TypeDef type, Dictionary counts) + { + foreach (var method in type.Methods) + { + if (Match.Any(item => method.ReturnType.TypeName.StartsWith(item))) IncrementCount(method.ReturnType.TypeName, counts); + + CountReferencesInMethod(method, counts); + } + + foreach (var field in type.Fields) + { + if (field.FieldType.IsValueType || field.FieldType.IsPrimitive) continue; + + if (!Match.Any(item => field.FieldType.TypeName.StartsWith(item))) continue; + + IncrementCount(field.FieldType.FullName, counts); + } + + foreach (var property in type.Properties) + { + if (property.PropertySig.RetType.IsValueType || property.PropertySig.RetType.IsPrimitive) continue; + + if (!Match.Any(item => property.PropertySig.RetType.TypeName.StartsWith(item))) continue; + + IncrementCount(property.PropertySig.RetType.FullName, counts); + } + } + + private static void CountReferencesInMethod(MethodDef method, Dictionary counts) + { + if (!method.HasBody) return; + + foreach (var instr in method.Body.Instructions) + { + if (instr.Operand is FieldDef fieldDef && Match.Any(item => fieldDef.FieldType.TypeName.StartsWith(item))) + { + IncrementCount(fieldDef.FieldType.FullName, counts); + } + + if (instr.Operand is PropertyDef propDef && Match.Any(item => propDef.PropertySig.RetType.FullName.StartsWith(item))) + { + IncrementCount(propDef.PropertySig.RetType.FullName, counts); + } + + if (instr.Operand is MethodDef methodDef && Match.Any(item => methodDef.DeclaringType.FullName.StartsWith(item))) + { + if (methodDef.ReturnType.IsValueType || methodDef.ReturnType.IsPrimitive || methodDef.ReturnType.IsCorLibType) continue; + + IncrementCount(methodDef.ReturnType.FullName, counts); + } + } + } + + private static void IncrementCount(string typeName, Dictionary counts) + { + counts[typeName] = counts.GetValueOrDefault(typeName, 0) + 1; + } +} \ No newline at end of file diff --git a/ReCodeItCLI/Commands/ReMap.cs b/ReCodeItCLI/Commands/ReMap.cs index 38ea678..24252ea 100644 --- a/ReCodeItCLI/Commands/ReMap.cs +++ b/ReCodeItCLI/Commands/ReMap.cs @@ -38,6 +38,10 @@ public class ReMap : ICommand _remapper.InitializeRemap(remaps, AssemblyPath, Path.GetDirectoryName(AssemblyPath)); + // Wait for log termination + Logger.Terminate(); + while(Logger.IsRunning()) {} + return default; } } \ No newline at end of file diff --git a/RecodeItGUI/GUI/Main.Designer.cs b/RecodeItGUI/GUI/Main.Designer.cs index f4d2178..c2a0a0f 100644 --- a/RecodeItGUI/GUI/Main.Designer.cs +++ b/RecodeItGUI/GUI/Main.Designer.cs @@ -30,12 +30,29 @@ partial class ReCodeItForm { components = new System.ComponentModel.Container(); RemapperTabPage = new TabPage(); + label1 = new Label(); ResetSearchButton = new Button(); ActiveProjectMappingsCheckbox = new CheckBox(); LoadedMappingFilePath = new TextBox(); RMSearchBox = new TextBox(); RemapTreeView = new TreeView(); groupBox1 = new GroupBox(); + label11 = new Label(); + IsStructComboBox = new ComboBox(); + label10 = new Label(); + HasGenericParamsComboBox = new ComboBox(); + label8 = new Label(); + HasAttributeComboBox = new ComboBox(); + label9 = new Label(); + IsEnumComboBox = new ComboBox(); + label2322 = new Label(); + IsInterfaceComboBox = new ComboBox(); + label7 = new Label(); + IsSealedComboBox = new ComboBox(); + label6 = new Label(); + IsAbstractComboBox = new ComboBox(); + label5 = new Label(); + IsPublicComboBox = new ComboBox(); ConstuctorCountUpDown = new NumericUpDown(); ConstructorCountEnabled = new CheckBox(); Inclusions = new TabControl(); @@ -77,27 +94,20 @@ partial class ReCodeItForm NestedTypesIncludeBox = new ListBox(); NewTypeName = new TextBox(); PropertyCountEnabled = new CheckBox(); - IsInterfaceUpDown = new DomainUpDown(); RemapperUseForceRename = new CheckBox(); NestedTypeCountEnabled = new CheckBox(); PropertyCountUpDown = new NumericUpDown(); FieldCountUpDown = new NumericUpDown(); - IsPublicUpDown = new DomainUpDown(); FieldCountEnabled = new CheckBox(); NestedTypeParentName = new TextBox(); MethodCountUpDown = new NumericUpDown(); - IsAbstractUpDown = new DomainUpDown(); BaseClassIncludeTextFIeld = new TextBox(); OriginalTypeName = new TextBox(); - HasGenericParametersUpDown = new DomainUpDown(); - IsEnumUpDown = new DomainUpDown(); NestedTypeCountUpDown = new NumericUpDown(); IsDerivedUpDown = new DomainUpDown(); IsNestedUpDown = new DomainUpDown(); - HasAttributeUpDown = new DomainUpDown(); BaseClassExcludeTextField = new TextBox(); MethodCountEnabled = new CheckBox(); - IsSealedUpDown = new DomainUpDown(); RemapperOutputDirectoryPath = new TextBox(); TargetAssemblyPath = new TextBox(); OutputDirectoryButton = new Button(); @@ -168,7 +178,6 @@ partial class ReCodeItForm SilentModeCheckbox = new CheckBox(); DebugLoggingCheckbox = new CheckBox(); toolTip1 = new ToolTip(components); - label1 = new Label(); RemapperTabPage.SuspendLayout(); groupBox1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)ConstuctorCountUpDown).BeginInit(); @@ -222,6 +231,15 @@ partial class ReCodeItForm RemapperTabPage.TabIndex = 1; RemapperTabPage.Text = "Remapper"; // + // label1 + // + label1.AutoSize = true; + label1.Location = new Point(777, 47); + label1.Name = "label1"; + label1.Size = new Size(235, 25); + label1.TabIndex = 41; + label1.Text = "Double click to edit a remap"; + // // ResetSearchButton // ResetSearchButton.Location = new Point(1155, 14); @@ -276,32 +294,41 @@ partial class ReCodeItForm // // groupBox1 // + groupBox1.Controls.Add(label11); + groupBox1.Controls.Add(IsStructComboBox); + groupBox1.Controls.Add(label10); + groupBox1.Controls.Add(HasGenericParamsComboBox); + groupBox1.Controls.Add(label8); + groupBox1.Controls.Add(HasAttributeComboBox); + groupBox1.Controls.Add(label9); + groupBox1.Controls.Add(IsEnumComboBox); + groupBox1.Controls.Add(label2322); + groupBox1.Controls.Add(IsInterfaceComboBox); + groupBox1.Controls.Add(label7); + groupBox1.Controls.Add(IsSealedComboBox); + groupBox1.Controls.Add(label6); + groupBox1.Controls.Add(IsAbstractComboBox); + groupBox1.Controls.Add(label5); + groupBox1.Controls.Add(IsPublicComboBox); groupBox1.Controls.Add(ConstuctorCountUpDown); groupBox1.Controls.Add(ConstructorCountEnabled); groupBox1.Controls.Add(Inclusions); groupBox1.Controls.Add(NewTypeName); groupBox1.Controls.Add(PropertyCountEnabled); - groupBox1.Controls.Add(IsInterfaceUpDown); groupBox1.Controls.Add(RemapperUseForceRename); groupBox1.Controls.Add(NestedTypeCountEnabled); groupBox1.Controls.Add(PropertyCountUpDown); groupBox1.Controls.Add(FieldCountUpDown); - groupBox1.Controls.Add(IsPublicUpDown); groupBox1.Controls.Add(FieldCountEnabled); groupBox1.Controls.Add(NestedTypeParentName); groupBox1.Controls.Add(MethodCountUpDown); - groupBox1.Controls.Add(IsAbstractUpDown); groupBox1.Controls.Add(BaseClassIncludeTextFIeld); groupBox1.Controls.Add(OriginalTypeName); - groupBox1.Controls.Add(HasGenericParametersUpDown); - groupBox1.Controls.Add(IsEnumUpDown); groupBox1.Controls.Add(NestedTypeCountUpDown); groupBox1.Controls.Add(IsDerivedUpDown); groupBox1.Controls.Add(IsNestedUpDown); - groupBox1.Controls.Add(HasAttributeUpDown); groupBox1.Controls.Add(BaseClassExcludeTextField); groupBox1.Controls.Add(MethodCountEnabled); - groupBox1.Controls.Add(IsSealedUpDown); groupBox1.Location = new Point(6, 6); groupBox1.Name = "groupBox1"; groupBox1.Size = new Size(769, 904); @@ -309,6 +336,158 @@ partial class ReCodeItForm groupBox1.TabStop = false; groupBox1.Text = "Remap Editor"; // + // label11 + // + label11.AutoSize = true; + label11.Location = new Point(224, 264); + label11.Name = "label11"; + label11.Size = new Size(75, 25); + label11.TabIndex = 53; + label11.Text = "Is Struct"; + // + // IsStructComboBox + // + IsStructComboBox.BackColor = SystemColors.ScrollBar; + IsStructComboBox.FormattingEnabled = true; + IsStructComboBox.Location = new Point(10, 258); + IsStructComboBox.Name = "IsStructComboBox"; + IsStructComboBox.Size = new Size(208, 33); + IsStructComboBox.TabIndex = 52; + toolTip1.SetToolTip(IsStructComboBox, "Is the type an enum?"); + // + // label10 + // + label10.AutoSize = true; + label10.Location = new Point(224, 380); + label10.Name = "label10"; + label10.Size = new Size(197, 25); + label10.TabIndex = 51; + label10.Text = "Has Generic Parameters"; + // + // HasGenericParamsComboBox + // + HasGenericParamsComboBox.BackColor = SystemColors.ScrollBar; + HasGenericParamsComboBox.FormattingEnabled = true; + HasGenericParamsComboBox.Location = new Point(10, 374); + HasGenericParamsComboBox.Name = "HasGenericParamsComboBox"; + HasGenericParamsComboBox.Size = new Size(208, 33); + HasGenericParamsComboBox.TabIndex = 50; + toolTip1.SetToolTip(HasGenericParamsComboBox, "Does the type have generic parameters?"); + // + // label8 + // + label8.AutoSize = true; + label8.Location = new Point(224, 343); + label8.Name = "label8"; + label8.Size = new Size(117, 25); + label8.TabIndex = 49; + label8.Text = "Has Attribute"; + // + // HasAttributeComboBox + // + HasAttributeComboBox.BackColor = SystemColors.ScrollBar; + HasAttributeComboBox.FormattingEnabled = true; + HasAttributeComboBox.Location = new Point(10, 335); + HasAttributeComboBox.Name = "HasAttributeComboBox"; + HasAttributeComboBox.Size = new Size(208, 33); + HasAttributeComboBox.TabIndex = 48; + toolTip1.SetToolTip(HasAttributeComboBox, "does the type have an attribute?"); + // + // label9 + // + label9.AutoSize = true; + label9.Location = new Point(224, 303); + label9.Name = "label9"; + label9.Size = new Size(75, 25); + label9.TabIndex = 47; + label9.Text = "Is Enum"; + // + // IsEnumComboBox + // + IsEnumComboBox.BackColor = SystemColors.ScrollBar; + IsEnumComboBox.FormattingEnabled = true; + IsEnumComboBox.Location = new Point(10, 297); + IsEnumComboBox.Name = "IsEnumComboBox"; + IsEnumComboBox.Size = new Size(208, 33); + IsEnumComboBox.TabIndex = 46; + toolTip1.SetToolTip(IsEnumComboBox, "Is the type an enum?"); + // + // label2322 + // + label2322.AutoSize = true; + label2322.Location = new Point(224, 225); + label2322.Name = "label2322"; + label2322.Size = new Size(98, 25); + label2322.TabIndex = 45; + label2322.Text = "Is Interface"; + // + // IsInterfaceComboBox + // + IsInterfaceComboBox.BackColor = SystemColors.ScrollBar; + IsInterfaceComboBox.FormattingEnabled = true; + IsInterfaceComboBox.Location = new Point(10, 219); + IsInterfaceComboBox.Name = "IsInterfaceComboBox"; + IsInterfaceComboBox.Size = new Size(208, 33); + IsInterfaceComboBox.TabIndex = 44; + toolTip1.SetToolTip(IsInterfaceComboBox, "Is the type an interface?"); + // + // label7 + // + label7.AutoSize = true; + label7.Location = new Point(224, 186); + label7.Name = "label7"; + label7.Size = new Size(82, 25); + label7.TabIndex = 43; + label7.Text = "Is Sealed"; + // + // IsSealedComboBox + // + IsSealedComboBox.BackColor = SystemColors.ScrollBar; + IsSealedComboBox.FormattingEnabled = true; + IsSealedComboBox.Location = new Point(10, 180); + IsSealedComboBox.Name = "IsSealedComboBox"; + IsSealedComboBox.Size = new Size(208, 33); + IsSealedComboBox.TabIndex = 42; + toolTip1.SetToolTip(IsSealedComboBox, "Is the type sealed?"); + // + // label6 + // + label6.AutoSize = true; + label6.Location = new Point(224, 148); + label6.Name = "label6"; + label6.Size = new Size(96, 25); + label6.TabIndex = 41; + label6.Text = "Is Abstract"; + // + // IsAbstractComboBox + // + IsAbstractComboBox.BackColor = SystemColors.ScrollBar; + IsAbstractComboBox.FormattingEnabled = true; + IsAbstractComboBox.Location = new Point(10, 142); + IsAbstractComboBox.Name = "IsAbstractComboBox"; + IsAbstractComboBox.Size = new Size(208, 33); + IsAbstractComboBox.TabIndex = 40; + toolTip1.SetToolTip(IsAbstractComboBox, "Is the type abstract? "); + // + // label5 + // + label5.AutoSize = true; + label5.Location = new Point(224, 110); + label5.Name = "label5"; + label5.Size = new Size(77, 25); + label5.TabIndex = 39; + label5.Text = "Is Public"; + // + // IsPublicComboBox + // + IsPublicComboBox.BackColor = SystemColors.ScrollBar; + IsPublicComboBox.FormattingEnabled = true; + IsPublicComboBox.Location = new Point(10, 104); + IsPublicComboBox.Name = "IsPublicComboBox"; + IsPublicComboBox.Size = new Size(208, 33); + IsPublicComboBox.TabIndex = 38; + toolTip1.SetToolTip(IsPublicComboBox, "Is the type public? This is required."); + // // ConstuctorCountUpDown // ConstuctorCountUpDown.BackColor = SystemColors.ScrollBar; @@ -757,17 +936,6 @@ partial class ReCodeItForm PropertyCountEnabled.Text = "Property Count"; PropertyCountEnabled.UseVisualStyleBackColor = true; // - // IsInterfaceUpDown - // - IsInterfaceUpDown.BackColor = SystemColors.ScrollBar; - IsInterfaceUpDown.Location = new Point(10, 215); - IsInterfaceUpDown.Name = "IsInterfaceUpDown"; - IsInterfaceUpDown.Size = new Size(208, 31); - IsInterfaceUpDown.Sorted = true; - IsInterfaceUpDown.TabIndex = 15; - IsInterfaceUpDown.Text = "IsInterface"; - toolTip1.SetToolTip(IsInterfaceUpDown, "Is the type an interface?"); - // // RemapperUseForceRename // RemapperUseForceRename.AutoSize = true; @@ -807,17 +975,6 @@ partial class ReCodeItForm FieldCountUpDown.TabIndex = 3; toolTip1.SetToolTip(FieldCountUpDown, "How many fields are there?"); // - // IsPublicUpDown - // - IsPublicUpDown.BackColor = SystemColors.ScrollBar; - IsPublicUpDown.Location = new Point(10, 104); - IsPublicUpDown.Name = "IsPublicUpDown"; - IsPublicUpDown.Size = new Size(208, 31); - IsPublicUpDown.Sorted = true; - IsPublicUpDown.TabIndex = 0; - IsPublicUpDown.Text = "IsPublic"; - toolTip1.SetToolTip(IsPublicUpDown, "Is the type public? Note: Only public counts as public all other access modifiers fall under false."); - // // FieldCountEnabled // FieldCountEnabled.AutoSize = true; @@ -831,7 +988,7 @@ partial class ReCodeItForm // NestedTypeParentName // NestedTypeParentName.BackColor = SystemColors.ScrollBar; - NestedTypeParentName.Location = new Point(224, 363); + NestedTypeParentName.Location = new Point(221, 421); NestedTypeParentName.Name = "NestedTypeParentName"; NestedTypeParentName.PlaceholderText = "Nested Type Parent Name"; NestedTypeParentName.Size = new Size(208, 31); @@ -847,21 +1004,10 @@ partial class ReCodeItForm MethodCountUpDown.TabIndex = 6; toolTip1.SetToolTip(MethodCountUpDown, "How many methods are there?"); // - // IsAbstractUpDown - // - IsAbstractUpDown.BackColor = SystemColors.ScrollBar; - IsAbstractUpDown.Location = new Point(10, 141); - IsAbstractUpDown.Name = "IsAbstractUpDown"; - IsAbstractUpDown.Size = new Size(208, 31); - IsAbstractUpDown.Sorted = true; - IsAbstractUpDown.TabIndex = 1; - IsAbstractUpDown.Text = "IsAbstract"; - toolTip1.SetToolTip(IsAbstractUpDown, "Is the class an abstract class?"); - // // BaseClassIncludeTextFIeld // BaseClassIncludeTextFIeld.BackColor = SystemColors.ScrollBar; - BaseClassIncludeTextFIeld.Location = new Point(224, 399); + BaseClassIncludeTextFIeld.Location = new Point(221, 457); BaseClassIncludeTextFIeld.Name = "BaseClassIncludeTextFIeld"; BaseClassIncludeTextFIeld.PlaceholderText = "Include Base Class"; BaseClassIncludeTextFIeld.Size = new Size(208, 31); @@ -878,28 +1024,6 @@ partial class ReCodeItForm OriginalTypeName.TabIndex = 1; toolTip1.SetToolTip(OriginalTypeName, "The original name of the type, you can leave this blank if not using force rename."); // - // HasGenericParametersUpDown - // - HasGenericParametersUpDown.BackColor = SystemColors.ScrollBar; - HasGenericParametersUpDown.Location = new Point(10, 326); - HasGenericParametersUpDown.Name = "HasGenericParametersUpDown"; - HasGenericParametersUpDown.Size = new Size(208, 31); - HasGenericParametersUpDown.Sorted = true; - HasGenericParametersUpDown.TabIndex = 7; - HasGenericParametersUpDown.Text = "HasGenericParameters"; - toolTip1.SetToolTip(HasGenericParametersUpDown, "Does the type have generic parameters? class Foo"); - // - // IsEnumUpDown - // - IsEnumUpDown.BackColor = SystemColors.ScrollBar; - IsEnumUpDown.Location = new Point(10, 252); - IsEnumUpDown.Name = "IsEnumUpDown"; - IsEnumUpDown.Size = new Size(208, 31); - IsEnumUpDown.Sorted = true; - IsEnumUpDown.TabIndex = 2; - IsEnumUpDown.Text = "IsEnum"; - toolTip1.SetToolTip(IsEnumUpDown, "Is the type an enum?"); - // // NestedTypeCountUpDown // NestedTypeCountUpDown.BackColor = SystemColors.ScrollBar; @@ -912,7 +1036,7 @@ partial class ReCodeItForm // IsDerivedUpDown // IsDerivedUpDown.BackColor = SystemColors.ScrollBar; - IsDerivedUpDown.Location = new Point(10, 400); + IsDerivedUpDown.Location = new Point(7, 458); IsDerivedUpDown.Name = "IsDerivedUpDown"; IsDerivedUpDown.Size = new Size(208, 31); IsDerivedUpDown.Sorted = true; @@ -923,7 +1047,7 @@ partial class ReCodeItForm // IsNestedUpDown // IsNestedUpDown.BackColor = SystemColors.ScrollBar; - IsNestedUpDown.Location = new Point(10, 363); + IsNestedUpDown.Location = new Point(7, 421); IsNestedUpDown.Name = "IsNestedUpDown"; IsNestedUpDown.Size = new Size(208, 31); IsNestedUpDown.Sorted = true; @@ -931,21 +1055,10 @@ partial class ReCodeItForm IsNestedUpDown.Text = "IsNested"; toolTip1.SetToolTip(IsNestedUpDown, "Is the type nested within another type?"); // - // HasAttributeUpDown - // - HasAttributeUpDown.BackColor = SystemColors.ScrollBar; - HasAttributeUpDown.Location = new Point(10, 289); - HasAttributeUpDown.Name = "HasAttributeUpDown"; - HasAttributeUpDown.Size = new Size(208, 31); - HasAttributeUpDown.Sorted = true; - HasAttributeUpDown.TabIndex = 5; - HasAttributeUpDown.Text = "HasAttribute"; - toolTip1.SetToolTip(HasAttributeUpDown, "Does the type have an attribute?"); - // // BaseClassExcludeTextField // BaseClassExcludeTextField.BackColor = SystemColors.ScrollBar; - BaseClassExcludeTextField.Location = new Point(438, 400); + BaseClassExcludeTextField.Location = new Point(435, 458); BaseClassExcludeTextField.Name = "BaseClassExcludeTextField"; BaseClassExcludeTextField.PlaceholderText = "Exclude Base Class"; BaseClassExcludeTextField.Size = new Size(208, 31); @@ -962,17 +1075,6 @@ partial class ReCodeItForm MethodCountEnabled.Text = "Method Count"; MethodCountEnabled.UseVisualStyleBackColor = true; // - // IsSealedUpDown - // - IsSealedUpDown.BackColor = SystemColors.ScrollBar; - IsSealedUpDown.Location = new Point(10, 179); - IsSealedUpDown.Name = "IsSealedUpDown"; - IsSealedUpDown.Size = new Size(208, 31); - IsSealedUpDown.Sorted = true; - IsSealedUpDown.TabIndex = 4; - IsSealedUpDown.Text = "IsSealed"; - toolTip1.SetToolTip(IsSealedUpDown, "Is the type sealed? Note that unsealing and publicization does not happen until after the remap so they can be used as parameters"); - // // RemapperOutputDirectoryPath // RemapperOutputDirectoryPath.BackColor = SystemColors.ScrollBar; @@ -1760,15 +1862,6 @@ partial class ReCodeItForm DebugLoggingCheckbox.UseVisualStyleBackColor = true; DebugLoggingCheckbox.CheckedChanged += DebugLoggingCheckbox_CheckedChanged; // - // label1 - // - label1.AutoSize = true; - label1.Location = new Point(777, 47); - label1.Name = "label1"; - label1.Size = new Size(235, 25); - label1.TabIndex = 41; - label1.Text = "Double click to edit a remap"; - // // ReCodeItForm // AutoScaleDimensions = new SizeF(10F, 25F); @@ -1778,7 +1871,7 @@ partial class ReCodeItForm Controls.Add(TabControlMain); FormBorderStyle = FormBorderStyle.FixedSingle; Name = "ReCodeItForm"; - Text = "ReCodeIt V0.1.0"; + Text = "ReCodeIt V0.2.0"; RemapperTabPage.ResumeLayout(false); RemapperTabPage.PerformLayout(); groupBox1.ResumeLayout(false); @@ -1867,18 +1960,11 @@ partial class ReCodeItForm private Button SaveRemapButton; private ListView RemapListView; private TabControl TabControlMain; - private DomainUpDown IsPublicUpDown; - private DomainUpDown HasGenericParametersUpDown; private DomainUpDown IsDerivedUpDown; - private DomainUpDown HasAttributeUpDown; - private DomainUpDown IsSealedUpDown; private DomainUpDown IsNestedUpDown; - private DomainUpDown IsEnumUpDown; - private DomainUpDown IsAbstractUpDown; private CheckBox FieldCountEnabled; private CheckBox PropertyCountEnabled; private CheckBox NestedTypeCountEnabled; - private DomainUpDown IsInterfaceUpDown; private TreeView RemapTreeView; private Button RunRemapButton; private Button LoadMappingFileButton; @@ -1964,4 +2050,20 @@ partial class ReCodeItForm private TextBox RMSearchBox; private Button ResetSearchButton; private Label label1; + private ComboBox IsPublicComboBox; + private Label label7; + private ComboBox IsSealedComboBox; + private Label label6; + private ComboBox IsAbstractComboBox; + private Label label5; + private Label label8; + private ComboBox HasAttributeComboBox; + private Label label9; + private ComboBox IsEnumComboBox; + private Label label2322; + private ComboBox IsInterfaceComboBox; + private Label label10; + private ComboBox HasGenericParamsComboBox; + private Label label11; + private ComboBox IsStructComboBox; } diff --git a/RecodeItGUI/GUI/Main.cs b/RecodeItGUI/GUI/Main.cs index 01be27c..9157ac0 100644 --- a/RecodeItGUI/GUI/Main.cs +++ b/RecodeItGUI/GUI/Main.cs @@ -2,7 +2,6 @@ using ReCodeIt.AutoMapper; using ReCodeIt.CrossCompiler; -using ReCodeIt.Enums; using ReCodeIt.Models; using ReCodeIt.ReMapper; using ReCodeIt.Utils; @@ -269,26 +268,51 @@ public partial class ReCodeItForm : Form return; } + ResetSearchButton_Click(this, e); + var newRemap = new RemapModel { Succeeded = false, - FailureReason = EFailureReason.None, + NoMatchReasons = [], NewTypeName = NewTypeName.Text, OriginalTypeName = OriginalTypeName.Text == string.Empty ? null : OriginalTypeName.Text, UseForceRename = RemapperUseForceRename.Checked, SearchParams = new SearchParams { - IsPublic = IsPublicUpDown.GetEnabled(), - IsAbstract = IsAbstractUpDown.GetEnabled(), - IsInterface = IsInterfaceUpDown.GetEnabled(), - IsEnum = IsEnumUpDown.GetEnabled(), - IsNested = IsNestedUpDown.GetEnabled(), - IsSealed = IsSealedUpDown.GetEnabled(), - HasAttribute = HasAttributeUpDown.GetEnabled(), - IsDerived = IsDerivedUpDown.GetEnabled(), - HasGenericParameters = HasGenericParametersUpDown.GetEnabled(), + IsPublic = bool.Parse(IsPublicComboBox.GetSelectedItem().AsSpan()), - ParentName = NestedTypeParentName.Text == string.Empty + IsAbstract = IsAbstractComboBox.SelectedItem as string != "Disabled" + ? bool.Parse(IsAbstractComboBox.GetSelectedItem().AsSpan()) + : null, + + IsSealed = IsSealedComboBox.SelectedItem as string != "Disabled" + ? bool.Parse(IsSealedComboBox.GetSelectedItem().AsSpan()) + : null, + + IsInterface = IsInterfaceComboBox.SelectedItem as string != "Disabled" + ? bool.Parse(IsInterfaceComboBox.GetSelectedItem().AsSpan()) + : null, + + IsStruct = IsStructComboBox.SelectedItem as string != "Disabled" + ? bool.Parse(IsStructComboBox.GetSelectedItem().AsSpan()) + : null, + + IsEnum = IsEnumComboBox.SelectedItem as string != "Disabled" + ? bool.Parse(IsEnumComboBox.GetSelectedItem().AsSpan()) + : null, + + HasAttribute = HasAttributeComboBox.SelectedItem as string != "Disabled" + ? bool.Parse(HasAttributeComboBox.GetSelectedItem().AsSpan()) + : null, + + HasGenericParameters = HasGenericParamsComboBox.SelectedItem as string != "Disabled" + ? bool.Parse(HasGenericParamsComboBox.GetSelectedItem().AsSpan()) + : null, + + IsNested = IsNestedUpDown.GetEnabled(), + IsDerived = IsDerivedUpDown.GetEnabled(), + + NTParentName = NestedTypeParentName.Text == string.Empty ? null : NestedTypeParentName.Text, @@ -436,9 +460,9 @@ public partial class ReCodeItForm : Form } Remapper.InitializeRemap( - DataProvider.Remaps, + DataProvider.LoadMappingFile(AppSettings.Remapper.MappingPath), AppSettings.Remapper.AssemblyPath, - Path.GetDirectoryName(AppSettings.Remapper.OutputPath)); + AppSettings.Remapper.OutputPath); ReloadRemapTreeView(DataProvider.Remaps); } @@ -512,6 +536,8 @@ public partial class ReCodeItForm : Form private void MethodIncludeAddButton_Click(object sender, EventArgs e) { + if (IncludeMethodTextBox.Text == string.Empty) return; + if (!MethodIncludeBox.Items.Contains(IncludeMethodTextBox.Text)) { MethodIncludeBox.Items.Add(IncludeMethodTextBox.Text); @@ -529,6 +555,8 @@ public partial class ReCodeItForm : Form private void MethodExcludeAddButton_Click(object sender, EventArgs e) { + if (ExcludeMethodTextBox.Text == string.Empty) return; + if (!MethodExcludeBox.Items.Contains(ExcludeMethodTextBox.Text)) { MethodExcludeBox.Items.Add(ExcludeMethodTextBox.Text); @@ -546,6 +574,8 @@ public partial class ReCodeItForm : Form private void FIeldIncludeAddButton_Click(object sender, EventArgs e) { + if (FieldsIncludeTextInput.Text == string.Empty) return; + if (!FieldIncludeBox.Items.Contains(FieldsIncludeTextInput.Text)) { FieldIncludeBox.Items.Add(FieldsIncludeTextInput.Text); @@ -563,6 +593,8 @@ public partial class ReCodeItForm : Form private void FieldExcludeAddButton_Click(object sender, EventArgs e) { + if (FieldsExcludeTextInput.Text == string.Empty) return; + if (!FieldExcludeBox.Items.Contains(FieldsExcludeTextInput.Text)) { FieldExcludeBox.Items.Add(FieldsExcludeTextInput.Text); @@ -580,6 +612,8 @@ public partial class ReCodeItForm : Form private void PropertiesIncludeAddButton_Click(object sender, EventArgs e) { + if (PropertiesIncludeTextField.Text == string.Empty) return; + if (!PropertiesIncludeBox.Items.Contains(PropertiesIncludeTextField.Text)) { PropertiesIncludeBox.Items.Add(PropertiesIncludeTextField.Text); @@ -597,6 +631,8 @@ public partial class ReCodeItForm : Form private void PropertiesExcludeAddButton_Click(object sender, EventArgs e) { + if (PropertiesExcludeTextField.Text == string.Empty) return; + if (!PropertiesExcludeBox.Items.Contains(PropertiesExcludeTextField.Text)) { PropertiesExcludeBox.Items.Add(PropertiesExcludeTextField.Text); @@ -614,6 +650,8 @@ public partial class ReCodeItForm : Form private void NestedTypesAddButton_Click(object sender, EventArgs e) { + if (NestedTypesIncludeTextField.Text == string.Empty) return; + if (!NestedTypesIncludeBox.Items.Contains(NestedTypesIncludeTextField.Text)) { NestedTypesIncludeBox.Items.Add(NestedTypesIncludeTextField.Text); @@ -631,6 +669,8 @@ public partial class ReCodeItForm : Form private void NestedTypesExlcudeAddButton_Click(object sender, EventArgs e) { + if (NestedTypesExcludeTextField.Text == string.Empty) return; + if (!NestedTypesExcludeBox.Items.Contains(NestedTypesExcludeTextField.Text)) { NestedTypesExcludeBox.Items.Add(NestedTypesExcludeTextField.Text); @@ -648,6 +688,8 @@ public partial class ReCodeItForm : Form private void AutoMapperExcludeAddButton_Click(object sender, EventArgs e) { + if (AutoMapperTypesToIgnoreTextField.Text == string.Empty) return; + if (!AutoMapperTypesExcludeBox.Items.Contains(AutoMapperTypesToIgnoreTextField.Text)) { DataProvider.Settings.AutoMapper.TypesToIgnore.Add(AutoMapperTypesToIgnoreTextField.Text); @@ -1070,12 +1112,6 @@ public partial class ReCodeItForm : Form AppSettings.CrossCompiler.AutoLoadLastActiveProject = CCAutoLoadLastProj.Checked; } - // Use the projects remap list on the remap tab - private void ActiveProjectMappingsCheckbox_CheckedChanged(object sender, EventArgs e) - { - // TODO - } - private void CCImportMappings_Click(object sender, EventArgs e) { if (CrossCompiler.ActiveProject == null) @@ -1236,29 +1272,80 @@ public partial class ReCodeItForm : Form BaseClassIncludeTextFIeld.Text = remap.SearchParams.MatchBaseClass; BaseClassExcludeTextField.Text = remap.SearchParams.IgnoreBaseClass; - NestedTypeParentName.Text = remap.SearchParams.ParentName; + NestedTypeParentName.Text = remap.SearchParams.NTParentName; - ConstructorCountEnabled.Checked = remap.SearchParams.ConstructorParameterCount != null ? remap.SearchParams.ConstructorParameterCount > 0 : false; - MethodCountEnabled.Checked = remap.SearchParams.MethodCount != null ? remap.SearchParams.MethodCount >= 0 : false; - FieldCountEnabled.Checked = remap.SearchParams.FieldCount != null ? remap.SearchParams.FieldCount >= 0 : false; - PropertyCountEnabled.Checked = remap.SearchParams.PropertyCount != null ? remap.SearchParams.PropertyCount >= 0 : false; - NestedTypeCountEnabled.Checked = remap.SearchParams.NestedTypeCount != null ? remap.SearchParams.NestedTypeCount >= 0 : false; + ConstructorCountEnabled.Checked = remap.SearchParams.ConstructorParameterCount is not null + ? remap.SearchParams.ConstructorParameterCount > 0 + : false; - ConstuctorCountUpDown.Value = (decimal)((remap.SearchParams.ConstructorParameterCount != null ? remap.SearchParams.ConstructorParameterCount : 0)); - MethodCountUpDown.Value = (decimal)(remap.SearchParams.MethodCount != null ? remap.SearchParams.MethodCount : 0); - FieldCountUpDown.Value = (decimal)(remap.SearchParams.FieldCount != null ? remap.SearchParams.FieldCount : 0); - PropertyCountUpDown.Value = (decimal)(remap.SearchParams.PropertyCount != null ? remap.SearchParams.PropertyCount : 0); - NestedTypeCountUpDown.Value = (decimal)(remap.SearchParams.NestedTypeCount != null ? remap.SearchParams.NestedTypeCount : 0); + MethodCountEnabled.Checked = remap.SearchParams.MethodCount is not null + ? remap.SearchParams.MethodCount >= 0 + : false; - IsPublicUpDown.BuildStringList("IsPublic", remap.SearchParams.IsPublic); - IsAbstractUpDown.BuildStringList("IsAbstract", remap.SearchParams.IsAbstract); - IsInterfaceUpDown.BuildStringList("IsInterface", remap.SearchParams.IsInterface); - IsEnumUpDown.BuildStringList("IsEnum", remap.SearchParams.IsEnum); - IsNestedUpDown.BuildStringList("IsNested", remap.SearchParams.IsNested); - IsSealedUpDown.BuildStringList("IsSealed", remap.SearchParams.IsSealed); - HasAttributeUpDown.BuildStringList("HasAttribute", remap.SearchParams.HasAttribute); - IsDerivedUpDown.BuildStringList("IsDerived", remap.SearchParams.IsDerived); - HasGenericParametersUpDown.BuildStringList("HasGenericParams", remap.SearchParams.HasGenericParameters); + FieldCountEnabled.Checked = remap.SearchParams.FieldCount is not null + ? remap.SearchParams.FieldCount >= 0 + : false; + + PropertyCountEnabled.Checked = remap.SearchParams.PropertyCount is not null + ? remap.SearchParams.PropertyCount >= 0 + : false; + + NestedTypeCountEnabled.Checked = remap.SearchParams.NestedTypeCount is not null + ? remap.SearchParams.NestedTypeCount >= 0 + : false; + + ConstuctorCountUpDown.Value = (decimal)((remap.SearchParams.ConstructorParameterCount != null + ? remap.SearchParams.ConstructorParameterCount + : 0)); + + MethodCountUpDown.Value = (decimal)(remap.SearchParams.MethodCount != null + ? remap.SearchParams.MethodCount + : 0); + + FieldCountUpDown.Value = (decimal)(remap.SearchParams.FieldCount != null + ? remap.SearchParams.FieldCount + : 0); + + PropertyCountUpDown.Value = (decimal)(remap.SearchParams.PropertyCount != null + ? remap.SearchParams.PropertyCount + : 0); + + NestedTypeCountUpDown.Value = (decimal)(remap.SearchParams.NestedTypeCount != null + ? remap.SearchParams.NestedTypeCount + : 0); + + IsPublicComboBox.SelectedItem = remap.SearchParams.IsPublic.ToString(); + + IsAbstractComboBox.SelectedItem = remap.SearchParams.IsAbstract is not null + ? remap.SearchParams.IsAbstract.ToString() + : "Disabled"; + + IsSealedComboBox.SelectedItem = remap.SearchParams.IsSealed is not null + ? remap.SearchParams.IsSealed.ToString() + : "Disabled"; + + IsInterfaceComboBox.SelectedItem = remap.SearchParams.IsInterface is not null + ? remap.SearchParams.IsInterface.ToString() + : "Disabled"; + + IsStructComboBox.SelectedItem = remap.SearchParams.IsStruct is not null + ? remap.SearchParams.IsStruct.ToString() + : "Disabled"; + + IsEnumComboBox.SelectedItem = remap.SearchParams.IsEnum is not null + ? remap.SearchParams.IsEnum.ToString() + : "Disabled"; + + HasAttributeComboBox.SelectedItem = remap.SearchParams.HasAttribute is not null + ? remap.SearchParams.HasAttribute.ToString() + : "Disabled"; + + HasGenericParamsComboBox.SelectedItem = remap.SearchParams.HasGenericParameters is not null + ? remap.SearchParams.HasGenericParameters.ToString() + : "Disabled"; + + IsNestedUpDown.BuildStringList("IsNested", false, remap.SearchParams.IsNested); + IsDerivedUpDown.BuildStringList("IsDerived", false, remap.SearchParams.IsDerived); foreach (var method in remap.SearchParams.IncludeMethods) { @@ -1304,15 +1391,32 @@ public partial class ReCodeItForm : Form private void PopulateDomainUpDowns() { // Clear them all first just incase - IsPublicUpDown.BuildStringList("IsPublic"); - IsAbstractUpDown.BuildStringList("IsAbstract"); - IsInterfaceUpDown.BuildStringList("IsInterface"); - IsEnumUpDown.BuildStringList("IsEnum"); - IsNestedUpDown.BuildStringList("IsNested"); - IsSealedUpDown.BuildStringList("IsSealed"); - HasAttributeUpDown.BuildStringList("HasAttribute"); - IsDerivedUpDown.BuildStringList("IsDerived"); - HasGenericParametersUpDown.BuildStringList("HasGenericParams"); + IsPublicComboBox.AddItemsToComboBox(["True", "False"]); + IsPublicComboBox.SelectedItem = "True"; + + IsAbstractComboBox.AddItemsToComboBox(["Disabled", "True", "False"]); + IsAbstractComboBox.SelectedItem = "Disabled"; + + IsSealedComboBox.AddItemsToComboBox(["Disabled", "True", "False"]); + IsSealedComboBox.SelectedItem = "Disabled"; + + IsInterfaceComboBox.AddItemsToComboBox(["Disabled", "True", "False"]); + IsInterfaceComboBox.SelectedItem = "Disabled"; + + IsStructComboBox.AddItemsToComboBox(["Disabled", "True", "False"]); + IsStructComboBox.SelectedItem = "Disabled"; + + IsEnumComboBox.AddItemsToComboBox(["Disabled", "True", "False"]); + IsEnumComboBox.SelectedItem = "Disabled"; + + HasAttributeComboBox.AddItemsToComboBox(["Disabled", "True", "False"]); + HasAttributeComboBox.SelectedItem = "Disabled"; + + HasGenericParamsComboBox.AddItemsToComboBox(["Disabled", "True", "False"]); + HasGenericParamsComboBox.SelectedItem = "Disabled"; + + IsNestedUpDown.BuildStringList("IsNested", false); + IsDerivedUpDown.BuildStringList("IsDerived", false); } /// diff --git a/RecodeItGUI/GUI/Main.resx b/RecodeItGUI/GUI/Main.resx index 2704a16..caefb92 100644 --- a/RecodeItGUI/GUI/Main.resx +++ b/RecodeItGUI/GUI/Main.resx @@ -120,4 +120,7 @@ 17, 17 + + 17, 17 + \ No newline at end of file diff --git a/RecodeItGUI/Utils/GUIHelpers.cs b/RecodeItGUI/Utils/GUIHelpers.cs index b0dcb7f..95f8c50 100644 --- a/RecodeItGUI/Utils/GUIHelpers.cs +++ b/RecodeItGUI/Utils/GUIHelpers.cs @@ -1,4 +1,5 @@ using ReCodeIt.Models; +using ReCodeIt.Utils; namespace ReCodeIt.GUI; @@ -38,10 +39,14 @@ internal static class GUIHelpers /// /// /// - public static void BuildStringList(this DomainUpDown domainUpDown, string name, bool? update = null) + public static void BuildStringList(this DomainUpDown domainUpDown, string name, bool required, bool? update = null) { domainUpDown.Items.Clear(); - domainUpDown.Text = name + " (Disabled)"; + + domainUpDown.Text = required + ? name + @" (Required)" + : name + @" (Disabled)"; + domainUpDown.ReadOnly = true; var list = new List @@ -51,14 +56,44 @@ internal static class GUIHelpers "False", }; + if (required) + { + list.RemoveAt(0); + } + if (update != null) { domainUpDown.Text = update.ToString(); + + if (update.ToString() == "True") + { + Logger.Log("Updating!"); + domainUpDown.SelectedItem = "True"; + } + else + { + domainUpDown.SelectedItem = "False"; + } } domainUpDown.Items.AddRange(list); } + public static void AddItemsToComboBox(this ComboBox cb, List items) + { + cb.Items.Clear(); + + foreach (var item in items) + { + cb.Items.Add(item); + } + } + + public static T? GetSelectedItem(this ComboBox cb) + { + return (T)cb.SelectedItem; + } + /// /// Generates a tree node to display on the GUI /// @@ -66,9 +101,10 @@ internal static class GUIHelpers /// public static TreeNode GenerateTreeNode(RemapModel model, ReCodeItForm gui) { - var isPublic = model.SearchParams.IsPublic == null ? null : model.SearchParams.IsPublic; + var isPublic = model.SearchParams.IsPublic; var isAbstract = model.SearchParams.IsAbstract == null ? null : model.SearchParams.IsAbstract; var isInterface = model.SearchParams.IsInterface == null ? null : model.SearchParams.IsInterface; + var isStruct = model.SearchParams.IsStruct == null ? null : model.SearchParams.IsStruct; var isEnum = model.SearchParams.IsEnum == null ? null : model.SearchParams.IsEnum; var isNested = model.SearchParams.IsNested == null ? null : model.SearchParams.IsNested; var isSealed = model.SearchParams.IsSealed == null ? null : model.SearchParams.IsSealed; @@ -87,10 +123,7 @@ internal static class GUIHelpers remapTreeItem.Nodes.Add(new TreeNode($"Force Rename: {model.UseForceRename}")); } - if (isPublic is not null) - { - remapTreeItem.Nodes.Add(new TreeNode($"IsPublic: {isPublic}")); - } + remapTreeItem.Nodes.Add(new TreeNode($"IsPublic: {isPublic}")); if (isAbstract is not null) { @@ -102,14 +135,19 @@ internal static class GUIHelpers remapTreeItem.Nodes.Add(new TreeNode($"IsInterface: {isInterface}")); } + if (isStruct is not null) + { + remapTreeItem.Nodes.Add(new TreeNode($"IsStruct: {isStruct}")); + } + if (isEnum is not null) { - remapTreeItem.Nodes.Add(new TreeNode($"isEnum: {isEnum}")); + remapTreeItem.Nodes.Add(new TreeNode($"IsEnum: {isEnum}")); } if (isNested is not null) { - remapTreeItem.Nodes.Add(new TreeNode($"IsNested: {isEnum}")); + remapTreeItem.Nodes.Add(new TreeNode($"IsNested: {isNested}")); } if (isSealed is not null) diff --git a/RecodeItLib/AutoMapper/MappingPair.cs b/RecodeItLib/AutoMapper/MappingPair.cs index e05a1c0..3c3038d 100644 --- a/RecodeItLib/AutoMapper/MappingPair.cs +++ b/RecodeItLib/AutoMapper/MappingPair.cs @@ -1,4 +1,4 @@ -using Mono.Cecil; +using dnlib.DotNet; namespace ReCodeIt.AutoMapper; @@ -10,18 +10,18 @@ namespace ReCodeIt.AutoMapper; /// /// public sealed class MappingPair( - TypeDefinition type, + TypeDef type, string name, bool isInterface, bool isStruct, bool isPublic) { - public TypeDefinition OriginalTypeDefinition { get; private set; } = type; + public TypeDef OriginalTypeDefinition { get; private set; } = type; /// /// The type reference we want to change /// - public TypeDefinition NewTypeRef { get; set; } + public TypeDef NewTypeRef { get; set; } /// /// Is this field an interface? diff --git a/RecodeItLib/AutoMapper/ReCodeItAutoMapper.cs b/RecodeItLib/AutoMapper/ReCodeItAutoMapper.cs index 10bb7a5..65fa2a0 100644 --- a/RecodeItLib/AutoMapper/ReCodeItAutoMapper.cs +++ b/RecodeItLib/AutoMapper/ReCodeItAutoMapper.cs @@ -1,19 +1,18 @@ -using Mono.Cecil; -using Mono.Collections.Generic; +using dnlib.DotNet; using ReCodeIt.Models; using ReCodeIt.ReMapper; using ReCodeIt.Utils; -using ReCodeIt.Utils; namespace ReCodeIt.AutoMapper; public class ReCodeItAutoMapper { + private ModuleDefMD Module { get; set; } private List MappingPairs { get; set; } = []; private List CompilerGeneratedClasses = []; - private List AllTypes { get; set; } = []; + private List AllTypes { get; set; } = []; private List AlreadyChangedNames { get; set; } = []; @@ -39,16 +38,16 @@ public class ReCodeItAutoMapper AllTypes = []; AlreadyChangedNames = []; - DataProvider.LoadAssemblyDefinition(Settings.AssemblyPath); + Module = DataProvider.LoadModule(Settings.AssemblyPath); Error = false; FailureCount = 0; TotalFieldRenameCount = 0; TotalPropertyRenameCount = 0; - FindCompilerGeneratedObjects(DataProvider.ModuleDefinition.Types); + var types = Module.GetTypes(); - var types = DataProvider.ModuleDefinition.Types; + FindCompilerGeneratedObjects(types); GetAllTypes(types); @@ -79,7 +78,7 @@ public class ReCodeItAutoMapper WriteChanges(); } - private void GetAllTypes(Collection types) + private void GetAllTypes(IEnumerable types) { AllTypes.AddRange(types); @@ -96,7 +95,7 @@ public class ReCodeItAutoMapper /// Finds any compiler generated code so we can ignore it, its mostly LINQ garbage /// /// - private void FindCompilerGeneratedObjects(Collection types) + private void FindCompilerGeneratedObjects(IEnumerable types) { foreach (var typeDefinition in types) { @@ -120,7 +119,7 @@ public class ReCodeItAutoMapper #region METHODS - private List GatherFromMethods(TypeDefinition type) + private List GatherFromMethods(TypeDef type) { var methodsWithTypes = new List(); @@ -132,7 +131,7 @@ public class ReCodeItAutoMapper var methods = type.Methods // We only want methods with parameters - .Where(m => m.HasParameters) + .Where(m => m.HasParams()) // Only want parameter names of a certain length .Where(m => m.Parameters.Any(p => p.Name.Length > Settings.MinLengthToMatch)); @@ -140,31 +139,26 @@ public class ReCodeItAutoMapper // Now go over over all filterd methods manually, because fuck this with linq foreach (var method in methods) { - var parmNames = method.Parameters.Select(p => p.Name); - var parmTypes = method.Parameters.Select(p => p.ParameterType.Name); - // Now over all parameters in the method foreach (var parm in method.Parameters) { // We dont want blacklisted items - if (Settings.MethodParamaterBlackList.Contains(parm.ParameterType.Name.TrimAfterSpecialChar()) - || Settings.TypesToIgnore.Contains(parm.ParameterType.Name.TrimAfterSpecialChar())) + if (Settings.MethodParamaterBlackList.Contains(parm.Name) + || Settings.TypesToIgnore.Contains(parm.Name)) { continue; } - if (parm.ParameterType.Resolve() == null) { continue; } - //Logger.Log($"Method Data Found"); //Logger.Log($"Parameter count: {method.Parameters.Count}"); //Logger.Log($"Paremeter Names: {string.Join(", ", parmNames)}"); //Logger.Log($"Paremeter Types: {string.Join(", ", parmTypes)}\n"); var mapPair = new MappingPair( - parm.ParameterType.Resolve(), + parm.Type.TryGetTypeDef(), parm.Name, - parm.ParameterType.Resolve().IsInterface, - parm.ParameterType.Name.Contains("Struct"), + parm.Type.TryGetTypeDef().IsInterface, + parm.Type.TryGetTypeDef().Name.Contains("Struct"), true); mapPair.AutoMappingResult = AutoMappingResult.Match_From_Method; @@ -185,7 +179,7 @@ public class ReCodeItAutoMapper /// /// /// - private List FilterFieldNames(TypeDefinition type) + private List FilterFieldNames(TypeDef type) { var fieldsWithTypes = new List(); @@ -197,7 +191,7 @@ public class ReCodeItAutoMapper var fields = type.Fields // we dont want names shorter than 4 - .Where(f => f.FieldType.Name.Length > 3) + .Where(f => f.Name.Length > 3) // Skip value types .Where(f => !f.FieldType.IsValueType) @@ -206,14 +200,14 @@ public class ReCodeItAutoMapper .Where(p => !p.FieldType.IsArray) // We dont want fields in the system type ignore list - .Where(f => !Settings.TypesToIgnore.Contains(f.FieldType.Name.TrimAfterSpecialChar())); + .Where(f => !Settings.TypesToIgnore.Contains(f.Name.TrimAfterSpecialChar())); // Include fields from the current type foreach (var field in fields) { //Logger.Log($"Collecting Field: OriginalTypeRef: {field.FieldType.Name.TrimAfterSpecialChar()} Field Name: {field.Name}"); - var typeDef = field.FieldType.Resolve(); + var typeDef = field.FieldType.TryGetTypeDef(); // Dont rename things we cant resolve if (typeDef is null) { continue; } @@ -221,8 +215,8 @@ public class ReCodeItAutoMapper var pair = new MappingPair( typeDef, field.Name, - field.FieldType.Name.Contains("Interface"), - field.FieldType.Name.Contains("Struct"), + typeDef.Name.Contains("Interface"), + typeDef.Name.Contains("Struct"), field.IsPublic); pair.AutoMappingResult = AutoMappingResult.Match_From_Field; @@ -238,7 +232,7 @@ public class ReCodeItAutoMapper /// /// /// - private IEnumerable FilterPropertyNames(TypeDefinition type) + private IEnumerable FilterPropertyNames(TypeDef type) { var propertiesWithTypes = new List(); @@ -250,23 +244,23 @@ public class ReCodeItAutoMapper var properties = type.Properties // we dont want names shorter than 4 - .Where(p => p.PropertyType.Name.Length > 3) + .Where(p => p.Name.Length > 3) // Skip value types - .Where(p => !p.PropertyType.IsValueType) + .Where(p => !p.PropertySig.RetType.GetIsValueType()) // TODO: Renaming arrays is strange, come back to this later - .Where(p => !p.PropertyType.IsArray) + .Where(p => !p.PropertySig.RetType.IsArray) // We dont want fields in the global ignore list - .Where(p => !Settings.TypesToIgnore.Contains(p.PropertyType.Name.TrimAfterSpecialChar())); + .Where(p => !Settings.TypesToIgnore.Contains(p.Name.TrimAfterSpecialChar())); // Include fields from the current type foreach (var property in properties) { //Logger.Log($"Collecting Property: OriginalTypeRef: {property.PropertyType.Name.TrimAfterSpecialChar()} Field Name: {property.Name}"); - var typeDef = property.PropertyType.Resolve(); + var typeDef = property.PropertySig.RetType.TryGetTypeDef(); // Dont rename things we cant resolve if (typeDef is null) { continue; } @@ -274,8 +268,8 @@ public class ReCodeItAutoMapper var mapPair = new MappingPair( typeDef, property.Name, - property.PropertyType.Name.Contains("Interface"), - property.PropertyType.Name.Contains("Struct"), + typeDef.Name.Contains("Interface"), + typeDef.Name.Contains("Struct"), true); mapPair.AutoMappingResult = AutoMappingResult.Match_From_Property; @@ -430,7 +424,7 @@ public class ReCodeItAutoMapper private void StartRenameProcess() { // Gather up any matches we have - foreach (var type in DataProvider.ModuleDefinition.Types.ToArray()) + foreach (var type in Module.GetTypes().ToArray()) { foreach (var pair in MappingPairs.ToArray()) { @@ -450,15 +444,12 @@ public class ReCodeItAutoMapper var fieldCount = RenameHelper.RenameAllFields( pair.OriginalTypeDefinition.Name, pair.Name, - DataProvider.ModuleDefinition.Types); + Module.GetTypes()); var propCount = RenameHelper.RenameAllProperties( pair.OriginalTypeDefinition.Name, pair.Name, - DataProvider.ModuleDefinition.Types); - - TotalFieldRenameCount += fieldCount; - TotalPropertyRenameCount += propCount; + Module.GetTypes()); Logger.Log($"Renamed: {fieldCount} fields", ConsoleColor.Green); Logger.Log($"Renamed: {propCount} properties", ConsoleColor.Green); @@ -508,7 +499,7 @@ public class ReCodeItAutoMapper /// /// /// - private void GatherMatchedTypeRefs(MappingPair pair, TypeDefinition type) + private void GatherMatchedTypeRefs(MappingPair pair, TypeDef type) { // Handle nested types recursively foreach (var nestedType in type.NestedTypes.ToArray()) @@ -524,14 +515,14 @@ public class ReCodeItAutoMapper private void WriteChanges() { - var path = DataProvider.WriteAssemblyDefinition(Settings.OutputPath); + Module.Write(Settings.OutputPath); var fieldCountMatchResult = MappingPairs.Where(x => x.AutoMappingResult == AutoMappingResult.Match_From_Property).Count(); var propertyCountMatchResult = MappingPairs.Where(x => x.AutoMappingResult == AutoMappingResult.Match_From_Property).Count(); var methodCountMatchResult = MappingPairs.Where(x => x.AutoMappingResult == AutoMappingResult.Match_From_Method).Count(); Logger.Log($"-------------------------------RESULT-----------------------------------", ConsoleColor.Green); - Logger.Log($"Complete: Assembly written to `{path}`", ConsoleColor.Green); + Logger.Log($"Complete: Assembly written to `{Settings.OutputPath}`", ConsoleColor.Green); Logger.Log($"Found {MappingPairs.Count()} automatic remaps", ConsoleColor.Green); Logger.Log($"Found {fieldCountMatchResult} automatic remaps from fields", ConsoleColor.Green); Logger.Log($"Found {propertyCountMatchResult} automatic remaps from properties", ConsoleColor.Green); diff --git a/RecodeItLib/Enums/EFailureReason.cs b/RecodeItLib/Enums/ENoMatchReason.cs similarity index 76% rename from RecodeItLib/Enums/EFailureReason.cs rename to RecodeItLib/Enums/ENoMatchReason.cs index de0082f..7cf7e84 100644 --- a/RecodeItLib/Enums/EFailureReason.cs +++ b/RecodeItLib/Enums/ENoMatchReason.cs @@ -1,19 +1,14 @@ namespace ReCodeIt.Enums; -public enum EFailureReason +public enum ENoMatchReason { - None, - IsAbstract, IsEnum, IsNested, IsSealed, IsDerived, - IsInterface, - IsPublic, HasGenericParameters, HasAttribute, - IsAttribute, - Constructor, + ConstructorParameterCount, MethodsInclude, MethodsExclude, MethodsCount, diff --git a/RecodeItLib/Models/RemapModel.cs b/RecodeItLib/Models/RemapModel.cs index 1669dc8..72ae48a 100644 --- a/RecodeItLib/Models/RemapModel.cs +++ b/RecodeItLib/Models/RemapModel.cs @@ -1,5 +1,6 @@ -using ReCodeIt.Enums; +using dnlib.DotNet; using Newtonsoft.Json; +using ReCodeIt.Enums; namespace ReCodeIt.Models; @@ -12,7 +13,19 @@ public class RemapModel public bool Succeeded { get; set; } = false; [JsonIgnore] - public EFailureReason FailureReason { get; set; } + public List NoMatchReasons { get; set; } = []; + + /// + /// This is a list of type candidates that made it through the filter + /// + [JsonIgnore] + public HashSet TypeCandidates { get; set; } = []; + + /// + /// This is the final chosen type we will use to remap + /// + [JsonIgnore] + public TypeDef TypePrimeCandidate { get; set; } public string NewTypeName { get; set; } = string.Empty; @@ -30,9 +43,14 @@ public class SearchParams { #region BOOL_PARAMS - public bool? IsPublic { get; set; } = null; + /// + /// Default to true, most types are public + /// + public bool IsPublic { get; set; } = true; + public bool? IsAbstract { get; set; } = null; public bool? IsInterface { get; set; } = null; + public bool? IsStruct { get; set; } = null; public bool? IsEnum { get; set; } = null; public bool? IsNested { get; set; } = null; public bool? IsSealed { get; set; } = null; @@ -44,8 +62,19 @@ public class SearchParams #region STR_PARAMS - public string? ParentName { get; set; } = null; + /// + /// Name of the nested types parent + /// + public string? NTParentName { get; set; } = null; + + /// + /// Name of the derived classes declaring type + /// public string? MatchBaseClass { get; set; } = null; + + /// + /// Name of the derived classes declaring type we want to ignore + /// public string? IgnoreBaseClass { get; set; } = null; #endregion STR_PARAMS diff --git a/RecodeItLib/Models/ScoringModel.cs b/RecodeItLib/Models/ScoringModel.cs deleted file mode 100644 index a3dc0a6..0000000 --- a/RecodeItLib/Models/ScoringModel.cs +++ /dev/null @@ -1,18 +0,0 @@ -using ReCodeIt.Enums; -using Mono.Cecil; - -namespace ReCodeIt.Models; - -public class ScoringModel -{ - public string ProposedNewName { get; set; } - public int Score { get; set; } = 0; - public TypeDefinition Definition { get; set; } - public RemapModel ReMap { get; internal set; } - - public EFailureReason FailureReason { get; set; } = EFailureReason.None; - - public ScoringModel() - { - } -} \ No newline at end of file diff --git a/RecodeItLib/ReCodeItLib.csproj b/RecodeItLib/ReCodeItLib.csproj index 6fef663..08d0973 100644 --- a/RecodeItLib/ReCodeItLib.csproj +++ b/RecodeItLib/ReCodeItLib.csproj @@ -9,14 +9,13 @@ + - - diff --git a/RecodeItLib/Remapper/DeObfuscator.cs b/RecodeItLib/Remapper/DeObfuscator.cs index a2c6bec..e46c9cf 100644 --- a/RecodeItLib/Remapper/DeObfuscator.cs +++ b/RecodeItLib/Remapper/DeObfuscator.cs @@ -1,5 +1,5 @@ -using Mono.Cecil; -using Mono.Cecil.Cil; +using dnlib.DotNet; +using dnlib.DotNet.Emit; using ReCodeIt.Utils; using System.Diagnostics; @@ -13,46 +13,47 @@ public static class Deobfuscator string token; - using (var assemblyDefinition = AssemblyDefinition.ReadAssembly(assemblyPath)) + ModuleContext modCtx = ModuleDef.CreateModuleContext(); + ModuleDefMD module = ModuleDefMD.Load(assemblyPath, modCtx); + + var potentialStringDelegates = new List(); + + foreach (var type in module.GetTypes()) { - var potentialStringDelegates = new List(); - - foreach (var type in assemblyDefinition.MainModule.Types) + foreach (var method in type.Methods) { - foreach (var method in type.Methods) + if (method.ReturnType.FullName != "System.String" + || method.Parameters.Count != 1 + || method.Parameters[0].Type.FullName != "System.Int32" + || method.Body == null + || !method.IsStatic) { - if (method.ReturnType.FullName != "System.String" - || method.Parameters.Count != 1 - || method.Parameters[0].ParameterType.FullName != "System.Int32" - || method.Body == null - || !method.IsStatic) - { - continue; - } - - if (!method.Body.Instructions.Any(x => - x.OpCode.Code == Code.Callvirt && - ((MethodReference)x.Operand).FullName == "System.Object System.AppDomain::GetData(System.String)")) - { - continue; - } - - potentialStringDelegates.Add(method); + continue; } + + if (!method.Body.Instructions.Any(x => + x.OpCode.Code == Code.Callvirt && + ((MethodDef)x.Operand).FullName == "System.Object System.AppDomain::GetData(System.String)")) + { + continue; + } + + potentialStringDelegates.Add(method); } - - if (potentialStringDelegates.Count != 1) - { - Logger.Log($"Expected to find 1 potential string delegate method; found {potentialStringDelegates.Count}. Candidates: {string.Join("\r\n", potentialStringDelegates.Select(x => x.FullName))}"); - } - - var deobfRid = potentialStringDelegates[0].MetadataToken; - - token = $"0x{((uint)deobfRid.TokenType | deobfRid.RID):x4}"; - - Console.WriteLine($"Deobfuscation token: {token}"); } + if (potentialStringDelegates.Count != 1) + { + Logger.Log($"Expected to find 1 potential string delegate method; found {potentialStringDelegates.Count}. Candidates: {string.Join("\r\n", potentialStringDelegates.Select(x => x.FullName))}"); + } + + var methodDef = potentialStringDelegates[0]; + MDToken deobfRid = methodDef.MDToken; + + // Construct the token string (similar to Mono.Cecil's format) + token = $"0x{(deobfRid.Raw | deobfRid.Rid):x4}"; + Console.WriteLine($"Deobfuscation token: {token}"); + var process = Process.Start(executablePath, $"--un-name \"!^<>[a-z0-9]$&!^<>[a-z0-9]__.*$&![A-Z][A-Z]\\$<>.*$&^[a-zA-Z_<{{$][a-zA-Z_0-9<>{{}}$.`-]*$\" \"{assemblyPath}\" --strtyp delegate --strtok \"{token}\""); @@ -61,16 +62,13 @@ public static class Deobfuscator // Fixes "ResolutionScope is null" by rewriting the assembly var cleanedDllPath = Path.Combine(Path.GetDirectoryName(assemblyPath), Path.GetFileNameWithoutExtension(assemblyPath) + "-cleaned.dll"); - var resolver = new DefaultAssemblyResolver(); - resolver.AddSearchDirectory(Path.GetDirectoryName(assemblyPath)); + ModuleDefMD assemblyRewrite = null; using (var memoryStream = new MemoryStream(File.ReadAllBytes(cleanedDllPath))) - using (var assemblyDefinition = AssemblyDefinition.ReadAssembly(memoryStream, new ReaderParameters() { - AssemblyResolver = resolver - })) - { - assemblyDefinition.Write(cleanedDllPath); + assemblyRewrite = ModuleDefMD.Load(memoryStream, modCtx); } + + assemblyRewrite.Write(cleanedDllPath); } } \ No newline at end of file diff --git a/RecodeItLib/Remapper/Publicizer.cs b/RecodeItLib/Remapper/Publicizer.cs index 22f2fec..bcf43c3 100644 --- a/RecodeItLib/Remapper/Publicizer.cs +++ b/RecodeItLib/Remapper/Publicizer.cs @@ -1,66 +1,15 @@ -using Mono.Cecil; -using Mono.Cecil.Rocks; -using ReCodeIt.Utils; +using dnlib.DotNet; using System.Runtime.CompilerServices; namespace ReCodeIt.ReMapper; -public static class Publicizer -{ - public static void Publicize() - { - Logger.Log("Starting publicization...", ConsoleColor.Green); - - foreach (var type in DataProvider.ModuleDefinition.Types) - { - if (type.IsNotPublic) { type.IsPublic = true; } - - // We only want to do methods and properties - - if (type.HasMethods) - { - foreach (var method in type.Methods) - { - method.IsPublic = true; - } - } - - if (type.HasProperties) - { - foreach (var property in type.Properties) - { - if (property.SetMethod != null) - { - property.SetMethod.IsPublic = true; - } - - if (property.GetMethod != null) - { - property.GetMethod.IsPublic = true; - } - } - } - } - } - - public static void Unseal() - { - Logger.Log("Starting unseal...", ConsoleColor.Green); - - foreach (var type in DataProvider.ModuleDefinition.Types) - { - if (type.IsSealed) { type.IsSealed = false; } - } - } -} - internal static class SPTPublicizer { - private static ModuleDefinition MainModule; + private static ModuleDefMD MainModule; - public static void PublicizeClasses(ModuleDefinition definition) + public static void PublicizeClasses(ModuleDefMD definition) { - var types = definition.GetAllTypes(); + var types = definition.GetTypes(); foreach (var type in types) { @@ -70,7 +19,7 @@ internal static class SPTPublicizer } } - private static void PublicizeType(TypeDefinition type) + private static void PublicizeType(TypeDef type) { // if (type.CustomAttributes.Any(a => a.AttributeType.Name == // nameof(CompilerGeneratedAttribute))) { return; } @@ -109,11 +58,11 @@ internal static class SPTPublicizer // Workaround to not publicize some nested types that cannot be patched easily and cause // issues Specifically, we want to find any type that implements the "IHealthController" // interface and make sure none of it's nested types that implement "IEffect" are changed - if (GetFlattenedInterfacesRecursive(type).Any(i => i.InterfaceType.Name == "IHealthController")) + if (GetFlattenedInterfacesRecursive(type).Any(i => i.Interface.Name == "IHealthController")) { // Specifically, any type that implements the IHealthController interface needs to not // publicize any nested types that implement the IEffect interface - nestedTypesToPublicize = type.NestedTypes.Where(t => t.IsAbstract || t.Interfaces.All(i => i.InterfaceType.Name != "IEffect")).ToArray(); + nestedTypesToPublicize = type.NestedTypes.Where(t => t.IsAbstract || t.Interfaces.All(i => i.Interface.Name != "IEffect")).ToArray(); } foreach (var nestedType in nestedTypesToPublicize) @@ -122,15 +71,7 @@ internal static class SPTPublicizer } } - // Don't publicize methods that implement interfaces not belonging to the current assembly - // Unused - sometimes some ambiguous reference errors appear due to this, but the pros outweigh - // the cons at the moment - private static bool CanPublicizeMethod(MethodDefinition method) - { - return !method.HasOverrides && method.GetBaseMethod().Equals(method) && !method.IsVirtual; - } - - private static void PublicizeMethod(MethodDefinition method) + private static void PublicizeMethod(MethodDef method) { if (method.IsCompilerControlled /*|| method.CustomAttributes.Any(a => a.AttributeType.Name == nameof(CompilerGeneratedAttribute))*/) { @@ -151,7 +92,7 @@ internal static class SPTPublicizer // Unused for now - publicizing fields is tricky, as it often creates MonoBehaviour loading // errors and prevents scenes from loading, most notably breaking the initial game loader scene // and causing the game to CTD right after starting - private static void PublicizeField(FieldDefinition field) + private static void PublicizeField(FieldDef field) { if (field.CustomAttributes.Any(a => a.AttributeType.Name == nameof(CompilerGeneratedAttribute)) // || field.HasCustomAttributes @@ -167,9 +108,9 @@ internal static class SPTPublicizer field.Attributes |= FieldAttributes.Public; } - private static List GetFlattenedInterfacesRecursive(TypeDefinition type) + private static List GetFlattenedInterfacesRecursive(TypeDef type) { - var interfaces = new List(); + var interfaces = new List(); if (type is null) return interfaces; @@ -180,7 +121,7 @@ internal static class SPTPublicizer if (type.BaseType != null && !type.BaseType.Name.Contains("Object")) { - var baseTypeDefinition = MainModule?.ImportReference(type.BaseType)?.Resolve(); + var baseTypeDefinition = MainModule?.Find(type.BaseType); var baseTypeInterfaces = GetFlattenedInterfacesRecursive(baseTypeDefinition); if (baseTypeInterfaces.Any()) diff --git a/RecodeItLib/Remapper/ReCodeItRemapper.cs b/RecodeItLib/Remapper/ReCodeItRemapper.cs index 4bed948..e9a5fba 100644 --- a/RecodeItLib/Remapper/ReCodeItRemapper.cs +++ b/RecodeItLib/Remapper/ReCodeItRemapper.cs @@ -1,10 +1,10 @@ -using Mono.Cecil; -using Mono.Cecil.Rocks; +using dnlib.DotNet; +using dnlib.DotNet.Emit; using ReCodeIt.CrossCompiler; -using ReCodeIt.Enums; using ReCodeIt.Models; using ReCodeIt.ReMapper.Search; using ReCodeIt.Utils; +using ReCodeItLib.Remapper.Search; using System.Diagnostics; namespace ReCodeIt.ReMapper; @@ -19,6 +19,8 @@ public class ReCodeItRemapper public ReCodeItRemapper() { } + private ModuleDefMD Module { get; set; } + private readonly ReCodeItCrossCompiler _compiler; public static bool IsRunning { get; private set; } = false; @@ -37,6 +39,8 @@ public class ReCodeItRemapper private string AssemblyPath { get; set; } + private List _remaps = []; + /// /// Start the remapping process /// @@ -46,7 +50,9 @@ public class ReCodeItRemapper string outPath, bool crossMapMode = false) { - DataProvider.LoadAssemblyDefinition(assemblyPath); + _remaps = []; + _remaps = remapModels; + Module = DataProvider.LoadModule(assemblyPath); AssemblyPath = assemblyPath; CrossMapMode = crossMapMode; @@ -54,32 +60,43 @@ public class ReCodeItRemapper OutPath = outPath; IsRunning = true; - DisplayBasicModuleInformation(); - Stopwatch.Start(); + var types = Module.GetTypes(); + + var tasks = new List(remapModels.Count); foreach (var remap in remapModels) { - Logger.Log($"Finding best match for {remap.NewTypeName}...", ConsoleColor.Gray); - - ScoreMapping(remap); + tasks.Add( + Task.Factory.StartNew(() => + { + Logger.Log($"\nFinding best match for {remap.NewTypeName}...", ConsoleColor.Gray); + ScoreMapping(remap, types); + }) + ); } + Task.WaitAll(tasks.ToArray()); ChooseBestMatches(); + var renameTasks = new List(remapModels.Count); + foreach (var remap in remapModels) + { + renameTasks.Add( + Task.Factory.StartNew(() => + { + RenameHelper.RenameAll(types, remap); + }) + ); + } + Task.WaitAll(renameTasks.ToArray()); + // Don't publicize and unseal until after the remapping, so we can use those as search parameters if (Settings.MappingSettings.Publicize) { - //Publicizer.Publicize(); + Logger.Log("Publicizing classes...", ConsoleColor.Yellow); - Logger.Log("Publicizing classes...", ConsoleColor.Green); - - SPTPublicizer.PublicizeClasses(DataProvider.ModuleDefinition); - } - - if (Settings.MappingSettings.Unseal) - { - //Publicizer.Unseal(); + SPTPublicizer.PublicizeClasses(Module); } // We are done, write the assembly @@ -92,134 +109,54 @@ public class ReCodeItRemapper } /// - /// Display information about the module we are remapping - /// - private void DisplayBasicModuleInformation() - { - Logger.Log("-----------------------------------------------", ConsoleColor.Yellow); - Logger.Log($"Starting remap...", ConsoleColor.Yellow); - Logger.Log($"Module contains {DataProvider.ModuleDefinition.Types.Count} Types", ConsoleColor.Yellow); - Logger.Log($"Publicize: {Settings.MappingSettings.Publicize}", ConsoleColor.Yellow); - Logger.Log($"Unseal: {Settings.MappingSettings.Unseal}", ConsoleColor.Yellow); - Logger.Log("-----------------------------------------------", ConsoleColor.Yellow); - } - - /// - /// Loop over all types in the assembly and score them + /// First we filter our type collection based on simple search parameters (true/false/null) + /// where null is a third disabled state. Then we score the types based on the search parameters /// /// Mapping to score - private void ScoreMapping(RemapModel mapping) + private void ScoreMapping(RemapModel mapping, IEnumerable types) { - foreach (var type in DataProvider.ModuleDefinition.Types) - { - FindMatch(type, mapping); - } - } - - /// - /// Find a match result - /// - /// OriginalTypeRef to score - /// Remap to check against - /// - /// EMatchResult - private void FindMatch(TypeDefinition type, RemapModel remap) - { - // Handle Direct Remaps by strict naming first bypasses everything else - if (remap.UseForceRename) - { - HandleByDirectName(type, remap); - return; - } - var tokens = DataProvider.Settings.AutoMapper.TokensToMatch; - bool ignore = tokens - .Where(token => !tokens - .Any(token => type.Name.StartsWith(token))).Any(); - - if (ignore && remap.SearchParams.IsNested is null) + if (mapping.SearchParams.IsNested is false or null) { - return; + types = types.Where(type => tokens.Any(token => type.Name.StartsWith(token))); } - foreach (var nestedType in type.NestedTypes) + types = GenericTypeFilters.FilterPublic(types, mapping.SearchParams); + + if (!types.Any()) { - FindMatch(nestedType, remap); + Logger.Log($"All types filtered out after public filter for: {mapping.NewTypeName}", ConsoleColor.Red); } - var score = new ScoringModel - { - ProposedNewName = remap.NewTypeName, - ReMap = remap, - Definition = type, - }; + types = GenericTypeFilters.FilterAbstract(types, mapping.SearchParams); + types = GenericTypeFilters.FilterSealed(types, mapping.SearchParams); + types = GenericTypeFilters.FilterInterface(types, mapping.SearchParams); + types = GenericTypeFilters.FilterStruct(types, mapping.SearchParams); + types = GenericTypeFilters.FilterEnum(types, mapping.SearchParams); + types = GenericTypeFilters.FilterAttributes(types, mapping.SearchParams); + types = GenericTypeFilters.FilterDerived(types, mapping.SearchParams); + types = GenericTypeFilters.FilterByGenericParameters(types, mapping.SearchParams); - var matches = new List - { - type.MatchConstructors(remap.SearchParams, score), - type.MatchMethods(remap.SearchParams, score), - type.MatchFields(remap.SearchParams, score), - type.MatchProperties(remap.SearchParams, score), - type.MatchNestedTypes(remap.SearchParams, score), - type.MatchIsPublic(remap.SearchParams, score) , - type.MatchIsInterface(remap.SearchParams, score), - type.MatchIsAbstract(remap.SearchParams, score), - type.MatchIsSealed(remap.SearchParams, score) , - type.MatchIsEnum(remap.SearchParams, score) , - type.MatchIsNested(remap.SearchParams, score), - type.MatchIsDerived(remap.SearchParams, score) , - type.MatchHasGenericParameters(remap.SearchParams, score), - type.MatchHasAttribute(remap.SearchParams, score), - }; + types = MethodTypeFilters.FilterByInclude(types, mapping.SearchParams); + types = MethodTypeFilters.FilterByExclude(types, mapping.SearchParams); + types = MethodTypeFilters.FilterByCount(types, mapping.SearchParams); - var NoMatch = matches.Where(x => x.Equals(EMatchResult.NoMatch)).FirstOrDefault(); + types = FieldTypeFilters.FilterByInclude(types, mapping.SearchParams); + types = FieldTypeFilters.FilterByExclude(types, mapping.SearchParams); + types = FieldTypeFilters.FilterByCount(types, mapping.SearchParams); - if (NoMatch == EMatchResult.NoMatch) - { - remap.FailureReason = score.FailureReason; - return; - } + types = PropertyTypeFilters.FilterByInclude(types, mapping.SearchParams); + types = PropertyTypeFilters.FilterByExclude(types, mapping.SearchParams); + types = PropertyTypeFilters.FilterByCount(types, mapping.SearchParams); - var match = matches - .Where(x => x.Equals(EMatchResult.Match)) - .Where(x => !x.Equals(EMatchResult.Disabled)) - .Any(); + types = CtorTypeFilters.FilterByParameterCount(types, mapping.SearchParams); - if (match) - { - // Set the original type name to be used later - score.ReMap.OriginalTypeName = type.FullName; - remap.OriginalTypeName = type.FullName; - remap.Succeeded = true; - remap.FailureReason = EFailureReason.None; - score.AddScoreToResult(); - } - } + types = NestedTypeFilters.FilterByInclude(types, mapping.SearchParams); + types = NestedTypeFilters.FilterByExclude(types, mapping.SearchParams); + types = NestedTypeFilters.FilterByCount(types, mapping.SearchParams); - private void HandleByDirectName(TypeDefinition type, RemapModel remap) - { - if (type.Name != remap.OriginalTypeName) { return; } - - var oldName = type.Name; - remap.OriginalTypeName = type.Name; - remap.FailureReason = EFailureReason.None; - remap.Succeeded = true; - - if (CrossMapMode) - { - // Store the original types for caching - _compiler.ActiveProject.ChangedTypes.Add(remap.NewTypeName, type.Name); - } - - type.Name = remap.NewTypeName; - - Logger.Log("-----------------------------------------------", ConsoleColor.Green); - Logger.Log($"Renamed {oldName} to {type.Name} directly", ConsoleColor.Green); - - RenameHelper.RenameAllDirect(remap, type); - - Logger.Log("-----------------------------------------------", ConsoleColor.Green); + mapping.TypeCandidates.UnionWith(types); } /// @@ -227,76 +164,34 @@ public class ReCodeItRemapper /// private void ChooseBestMatches() { - foreach (var score in DataProvider.ScoringModels) + foreach (var remap in _remaps) { - ChooseBestMatch(score.Value); + ChooseBestMatch(remap); } - - var failures = 0; - var changes = 0; - - foreach (var remap in DataProvider.Remaps) - { - if (remap.Succeeded is false) - { - Logger.Log("-----------------------------------------------", ConsoleColor.Red); - Logger.Log($"Renaming {remap.NewTypeName} failed with reason {remap.FailureReason}", ConsoleColor.Red); - Logger.Log("-----------------------------------------------", ConsoleColor.Red); - failures++; - continue; - } - - changes++; - } - - Logger.Log("-----------------------------------------------", ConsoleColor.Yellow); - Logger.Log($"Result: Remapped {changes} Types. Failed to remap {failures} Types", ConsoleColor.Yellow); - Logger.Log("-----------------------------------------------", ConsoleColor.Yellow); } /// /// Choose best match from a collection of scores, then start the renaming process /// /// Scores to rate - private void ChooseBestMatch(HashSet scores) + private void ChooseBestMatch(RemapModel remap) { - if (scores.Count == 0) { return; } + if (remap.TypeCandidates.Count == 0) { return; } - var filteredScores = scores - .Where(score => score.Score > 0) - .OrderByDescending(score => score.Score) - .Take(5); + var winner = remap.TypeCandidates.FirstOrDefault(); + remap.TypePrimeCandidate = winner; + remap.OriginalTypeName = winner.Name.String; - var highestScore = filteredScores.FirstOrDefault(); + if (winner is null) { return; } - if (highestScore is null) { return; } + remap.Succeeded = true; - Logger.Log("-----------------------------------------------", ConsoleColor.Green); - Logger.Log($"Renaming {highestScore.Definition.FullName} to {highestScore.ProposedNewName}", ConsoleColor.Green); - Logger.Log($"Scored: {highestScore.Score} points", ConsoleColor.Green); - - if (filteredScores.Count() > 1 && filteredScores.Skip(1).Any(score => score.Score == highestScore.Score)) - { - Logger.Log($"Warning! There were {filteredScores.Count()} possible matches. Considering adding more search parameters, Only showing first 5.", ConsoleColor.Yellow); - - foreach (var score in filteredScores.Skip(1).Take(5)) - { - Logger.Log($"{score.Definition.Name} - Score [{score.Score}]", ConsoleColor.Yellow); - } - } - - highestScore.ReMap.OriginalTypeName = highestScore.Definition.Name; + remap.OriginalTypeName = winner.Name.String; if (CrossMapMode) {// Store the original types for caching - _compiler.ActiveProject.ChangedTypes.Add(highestScore.ProposedNewName, highestScore.Definition.Name); + //_compiler.ActiveProject.ChangedTypes.Add(highestScore.ProposedNewName, highestScore.Definition.Name); } - - // Rename type and all associated type members - - RenameHelper.RenameAll(highestScore); - - Logger.Log("-----------------------------------------------", ConsoleColor.Green); } /// @@ -304,28 +199,35 @@ public class ReCodeItRemapper /// private void WriteAssembly() { - var moduleName = DataProvider.AssemblyDefinition.MainModule.Name; + var moduleName = Module.Name; moduleName = moduleName.Replace(".dll", "-Remapped.dll"); OutPath = Path.Combine(OutPath, moduleName); - var path = DataProvider.WriteAssemblyDefinition(OutPath); + try + { + Module.Write(OutPath); + } + catch (Exception e) + { + Logger.Log(e); + throw; + } Logger.Log("Creating Hollow...", ConsoleColor.Yellow); Hollow(); var hollowedDir = Path.GetDirectoryName(OutPath); var hollowedPath = Path.Combine(hollowedDir, "Hollowed.dll"); - DataProvider.WriteAssemblyDefinition(hollowedPath); + Module.Write(hollowedPath); - Logger.Log("-----------------------------------------------", ConsoleColor.Green); - Logger.Log($"Complete: Assembly written to `{path}`", ConsoleColor.Green); - Logger.Log($"Complete: Hollowed written to `{hollowedPath}`", ConsoleColor.Green); - Logger.Log("Original type names updated on mapping file.", ConsoleColor.Green); - Logger.Log($"Remap took {Stopwatch.Elapsed.TotalSeconds:F1} seconds", ConsoleColor.Green); - Logger.Log("-----------------------------------------------", ConsoleColor.Green); + DisplayEndBanner(hollowedPath); + + if (DataProvider.Settings.Remapper.MappingPath != string.Empty) + { + DataProvider.UpdateMapping(DataProvider.Settings.Remapper.MappingPath, _remaps); + } - DataProvider.ScoringModels = []; Stopwatch.Reset(); IsRunning = false; @@ -337,14 +239,75 @@ public class ReCodeItRemapper /// private void Hollow() { - foreach (var type in DataProvider.ModuleDefinition.GetAllTypes()) + foreach (var type in Module.GetTypes()) { foreach (var method in type.Methods.Where(m => m.HasBody)) { - var ilProcessor = method.Body.GetILProcessor(); + if (!method.HasBody) continue; - // Remove existing instructions - ilProcessor.Clear(); + method.Body = new CilBody(); + method.Body.Instructions.Add(OpCodes.Ret.ToInstruction()); + } + } + } + + private void DisplayEndBanner(string hollowedPath) + { + var failures = 0; + var changes = 0; + + foreach (var remap in _remaps) + { + if (remap.Succeeded is false) + { + Logger.Log("-----------------------------------------------", ConsoleColor.Red); + Logger.Log($"Renaming {remap.NewTypeName} failed with reason(s)", ConsoleColor.Red); + + foreach (var reason in remap.NoMatchReasons) + { + Logger.Log($"Reason: {reason}", ConsoleColor.Red); + } + + Logger.Log("-----------------------------------------------", ConsoleColor.Red); + failures++; + continue; + } + + changes++; + } + + Logger.Log("-----------------------------------------------", ConsoleColor.Green); + Logger.Log("-----------------------------------------------", ConsoleColor.Green); + + foreach (var remap in _remaps) + { + if (remap.Succeeded is false) { continue; } + + var original = remap.OriginalTypeName; + var proposed = remap.NewTypeName; + + Logger.Log($"Renamed {original} to {proposed}", ConsoleColor.Green); + + DisplayAlternativeMatches(remap); + } + + Logger.Log("-----------------------------------------------", ConsoleColor.Green); + Logger.Log("-----------------------------------------------", ConsoleColor.Green); + Logger.Log($"Result renamed {changes} Types. Failed to rename {failures} Types", ConsoleColor.Green); + Logger.Log($"Assembly written to `{OutPath}`", ConsoleColor.Green); + Logger.Log($"Hollowed written to `{hollowedPath}`", ConsoleColor.Green); + Logger.Log($"Remap took {Stopwatch.Elapsed.TotalSeconds:F1} seconds", ConsoleColor.Green); + } + + private void DisplayAlternativeMatches(RemapModel remap) + { + if (remap.TypeCandidates.Count() > 1) + { + Logger.Log($"Warning! There were {remap.TypeCandidates.Count()} possible matches for {remap.NewTypeName}. Consider adding more search parameters, Only showing the first 5.", ConsoleColor.Yellow); + + foreach (var type in remap.TypeCandidates.Skip(1).Take(5)) + { + Logger.Log($"{type.Name}", ConsoleColor.Yellow); } } } diff --git a/RecodeItLib/Remapper/RenameHelper.cs b/RecodeItLib/Remapper/RenameHelper.cs index cdbd833..4d90e40 100644 --- a/RecodeItLib/Remapper/RenameHelper.cs +++ b/RecodeItLib/Remapper/RenameHelper.cs @@ -1,5 +1,4 @@ -using Mono.Cecil; -using Mono.Cecil.Rocks; +using dnlib.DotNet; using ReCodeIt.Models; using ReCodeIt.Utils; @@ -12,42 +11,45 @@ internal static class RenameHelper /// /// Only used by the manual remapper, should probably be removed /// - /// - public static void RenameAll(ScoringModel score, bool direct = false) + /// + /// + /// + public static void RenameAll(IEnumerable types, RemapModel remap, bool direct = false) { - var types = DataProvider.ModuleDefinition.GetAllTypes(); - // Rename all fields and properties first if (DataProvider.Settings.Remapper.MappingSettings.RenameFields) { - RenameAllFields(score.Definition.Name, score.ReMap.NewTypeName, types); + RenameAllFields( + remap.TypePrimeCandidate.Name.String, + remap.NewTypeName, + types); } if (DataProvider.Settings.Remapper.MappingSettings.RenameProperties) { - RenameAllProperties(score.Definition.Name, score.ReMap.NewTypeName, types); + RenameAllProperties( + remap.TypePrimeCandidate.Name.String, + remap.NewTypeName, + types); } if (!direct) { - RenameType(types, score); + RenameType(types, remap); } - Logger.Log($"{score.Definition.Name} Renamed.", ConsoleColor.Green); + Logger.Log($"{remap.TypePrimeCandidate.Name.String} Renamed.", ConsoleColor.Green); } /// /// Only used by the manual remapper, should probably be removed /// - /// - public static void RenameAllDirect(RemapModel remap, TypeDefinition type) + /// + /// + /// + public static void RenameAllDirect(IEnumerable types, RemapModel remap, TypeDef type) { - var directRename = new ScoringModel - { - Definition = type, - ReMap = remap - }; - RenameAll(directRename, true); + RenameAll(types, remap, true); } /// @@ -57,10 +59,11 @@ internal static class RenameHelper /// /// /// - public static int RenameAllFields( + public static IEnumerable RenameAllFields( + string oldTypeName, string newTypeName, - IEnumerable typesToCheck, + IEnumerable typesToCheck, int overAllCount = 0) { foreach (var type in typesToCheck) @@ -73,29 +76,89 @@ internal static class RenameHelper int fieldCount = 0; foreach (var field in fields) { - if (field.FieldType.Name == oldTypeName) + if (field.FieldType.TypeName == oldTypeName) { - var newFieldName = GetNewFieldName(newTypeName, field.IsPrivate, fieldCount); + var newFieldName = GetNewFieldName(newTypeName, fieldCount); // Dont need to do extra work if (field.Name == newFieldName) { continue; } - Logger.Log($"Renaming original field type name: `{field.FieldType.Name}` with name `{field.Name}` to `{newFieldName}`", ConsoleColor.Green); + Logger.Log($"Renaming field on type {type.Name} named `{field.Name}` with type `{field.FieldType.TypeName}` to `{newFieldName}`", ConsoleColor.Green); + + var oldName = field.Name.ToString(); field.Name = newFieldName; + UpdateTypeFieldMemberRefs(type, field, oldName); + UpdateAllTypeFieldMemberRefs(typesToCheck, field, oldName); + fieldCount++; overAllCount++; } } - - if (type.HasNestedTypes) - { - RenameAllFields(oldTypeName, newTypeName, type.NestedTypes, overAllCount); - } } - return overAllCount; + return typesToCheck; + } + + private static void UpdateAllTypeFieldMemberRefs(IEnumerable typesToCheck, FieldDef newDef, string oldName) + { + foreach (var type in typesToCheck) + { + UpdateTypeFieldMemberRefs(type, newDef, oldName); + } + } + + private static void UpdateTypeFieldMemberRefs(TypeDef type, FieldDef newDef, string oldName) + { + foreach (var method in type.Methods) + { + if (!method.HasBody) continue; + + foreach (var instr in method.Body.Instructions) + { + if (instr.Operand is MemberRef memRef && memRef.Name == oldName) + { + //if (!memRef.Name.IsFieldOrPropNameInList(TokensToMatch)) continue; + + Logger.Log($"Renaming MemRef in method {method.DeclaringType.Name}::{method.Name} from `{memRef.Name}` to `{newDef.Name}`", ConsoleColor.Yellow); + memRef.Name = newDef.Name; + } + } + } + } + + private static void RenameAllFieldRefsInMethods(IEnumerable typesToCheck, FieldDef newDef, string oldName) + { + foreach (var type in typesToCheck) + { + foreach (var method in type.Methods) + { + if (!method.HasBody) continue; + + ChangeFieldNamesInMethods(method, newDef, oldName); + } + } + } + + /// + /// Rename all field and member refs in a method + /// + /// + /// + /// + private static void ChangeFieldNamesInMethods(MethodDef method, FieldDef newDef, string oldName) + { + foreach (var instr in method.Body.Instructions) + { + if (instr.Operand is FieldDef fieldDef && fieldDef.Name == oldName) + { + if (!fieldDef.Name.IsFieldOrPropNameInList(TokensToMatch)) continue; + + Logger.Log($"Renaming fieldDef in method {method.Name} from `{fieldDef.Name}` to `{newDef.Name}`", ConsoleColor.Yellow); + fieldDef.Name = newDef.Name; + } + } } /// @@ -108,7 +171,7 @@ internal static class RenameHelper public static int RenameAllProperties( string oldTypeName, string newTypeName, - IEnumerable typesToCheck, + IEnumerable typesToCheck, int overAllCount = 0) { foreach (var type in typesToCheck) @@ -121,35 +184,30 @@ internal static class RenameHelper int propertyCount = 0; foreach (var property in properties) { - if (property.PropertyType.Name == oldTypeName) + if (property.PropertySig.RetType.TypeName == oldTypeName) { var newPropertyName = GetNewPropertyName(newTypeName, propertyCount); // Dont need to do extra work if (property.Name == newPropertyName) { continue; } - Logger.Log($"Renaming original property type name: `{property.PropertyType.Name}` with name `{property.Name}` to `{newPropertyName}`", ConsoleColor.Green); - property.Name = newPropertyName; + Logger.Log($"Renaming property on type {type.Name} named `{property.Name}` with type `{property.PropertySig.RetType.TypeName}` to `{newPropertyName}`", ConsoleColor.Green); + property.Name = new UTF8String(newPropertyName); + propertyCount++; overAllCount++; } } - - if (type.HasNestedTypes) - { - RenameAllProperties(oldTypeName, newTypeName, type.NestedTypes, overAllCount); - } } return overAllCount; } - public static string GetNewFieldName(string NewName, bool isPrivate, int fieldCount = 0) + public static string GetNewFieldName(string NewName, int fieldCount = 0) { - var discard = isPrivate ? "_" : ""; string newFieldCount = fieldCount > 0 ? $"_{fieldCount}" : string.Empty; - return $"{discard}{char.ToLower(NewName[0])}{NewName[1..]}{newFieldCount}"; + return $"{char.ToLower(NewName[0])}{NewName[1..]}{newFieldCount}"; } public static string GetNewPropertyName(string newName, int propertyCount = 0) @@ -157,26 +215,26 @@ internal static class RenameHelper return propertyCount > 0 ? $"{newName}_{propertyCount}" : newName; } - private static void RenameType(IEnumerable typesToCheck, ScoringModel score) + private static void RenameType(IEnumerable typesToCheck, RemapModel remap) { foreach (var type in typesToCheck) { if (type.HasNestedTypes) { - RenameType(type.NestedTypes, score); + RenameType(type.NestedTypes, remap); } - if (score.Definition.Name is null) { continue; } + if (remap.TypePrimeCandidate.Name is null) { continue; } - if (score.ReMap.SearchParams.IsNested is true && - type.IsNested && type.Name == score.Definition.Name) + if (remap.SearchParams.IsNested is true && + type.IsNested && type.Name == remap.TypePrimeCandidate.Name) { - type.Name = score.ProposedNewName; + type.Name = remap.NewTypeName; } - if (type.FullName == score.Definition.Name) + if (type.FullName == remap.TypePrimeCandidate.Name) { - type.Name = score.ProposedNewName; + type.Name = remap.NewTypeName; } } } diff --git a/RecodeItLib/Remapper/Search/Constructors.cs b/RecodeItLib/Remapper/Search/Constructors.cs deleted file mode 100644 index a19bf3a..0000000 --- a/RecodeItLib/Remapper/Search/Constructors.cs +++ /dev/null @@ -1,28 +0,0 @@ -using ReCodeIt.Enums; -using ReCodeIt.Models; -using Mono.Cecil; -using Mono.Cecil.Rocks; - -namespace ReCodeIt.ReMapper.Search; - -internal static class Constructors -{ - /// - /// Search for types with a constructor of a given length - /// - /// - /// - /// Match if constructor parameters matches - public static EMatchResult GetTypeByParameterCount(TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.ConstructorParameterCount is null) return EMatchResult.Disabled; - - var match = type.GetConstructors() - .Where(c => c.Parameters.Count == parms.ConstructorParameterCount) - .Any(); - - return match - ? EMatchResult.Match - : EMatchResult.NoMatch; - } -} \ No newline at end of file diff --git a/RecodeItLib/Remapper/Search/CtorTypeFilters.cs b/RecodeItLib/Remapper/Search/CtorTypeFilters.cs new file mode 100644 index 0000000..c527d21 --- /dev/null +++ b/RecodeItLib/Remapper/Search/CtorTypeFilters.cs @@ -0,0 +1,30 @@ +using dnlib.DotNet; +using ReCodeIt.Models; + +namespace ReCodeIt.ReMapper.Search; + +internal static class CtorTypeFilters +{ + /// + /// Search for types with a constructor of a given length + /// + /// + /// + /// Filtered list + public static IEnumerable FilterByParameterCount(IEnumerable types, SearchParams parms) + { + if (parms.ConstructorParameterCount is null) return types; + + return types.Where(type => + { + var constructors = type.FindConstructors(); + return constructors != null && constructors.Any(ctor => + { + // Ensure Parameters isn't null before checking Count + var parameters = ctor.Parameters; + // This +1 offset is needed for some reason, needs investigation + return parameters != null && parameters.Count == parms.ConstructorParameterCount + 1; + }); + }); + } +} \ No newline at end of file diff --git a/RecodeItLib/Remapper/Search/FieldTypeFilters.cs b/RecodeItLib/Remapper/Search/FieldTypeFilters.cs new file mode 100644 index 0000000..cf25166 --- /dev/null +++ b/RecodeItLib/Remapper/Search/FieldTypeFilters.cs @@ -0,0 +1,78 @@ +using dnlib.DotNet; +using ReCodeIt.Models; +using ReCodeIt.Utils; + +namespace ReCodeItLib.Remapper.Search; + +internal static class FieldTypeFilters +{ + /// + /// Filters based on field name + /// + /// + /// + /// Filtered list + public static IEnumerable FilterByInclude(IEnumerable types, SearchParams parms) + { + if (parms.IncludeFields.Count == 0) return types; + + List filteredTypes = []; + + foreach (var type in types) + { + if (parms.IncludeFields + .All(includeName => type.Fields + .Any(field => field.Name.String == includeName))) + { + filteredTypes.Add(type); + } + } + + return filteredTypes.Any() ? filteredTypes : types; + } + + /// + /// Filters based on field name + /// + /// + /// + /// Filtered list + public static IEnumerable FilterByExclude(IEnumerable types, SearchParams parms) + { + if (parms.ExcludeFields.Count == 0) return types; + + List filteredTypes = []; + + foreach (var type in types) + { + var match = type.Fields + .Where(field => parms.ExcludeFields.Contains(field.Name.String)); + + if (!match.Any()) + { + filteredTypes.Add(type); + } + } + + return filteredTypes.Any() ? filteredTypes : types; + } + + /// + /// Filters based on method count + /// + /// + /// + /// Filtered list + public static IEnumerable FilterByCount(IEnumerable types, SearchParams parms) + { + if (parms.FieldCount is null) return types; + + if (parms.FieldCount >= 0) + { + Logger.Log("Matching field count", ConsoleColor.Yellow); + types = types.Where(t => t.Fields.Count == parms.FieldCount); + } + + return types; + } +} \ No newline at end of file diff --git a/RecodeItLib/Remapper/Search/Fields.cs b/RecodeItLib/Remapper/Search/Fields.cs deleted file mode 100644 index a4122a2..0000000 --- a/RecodeItLib/Remapper/Search/Fields.cs +++ /dev/null @@ -1,79 +0,0 @@ -using Mono.Cecil; -using MoreLinq; -using ReCodeIt.Enums; -using ReCodeIt.Models; - -namespace ReCodeIt.ReMapper.Search; - -internal static class Fields -{ - /// - /// Returns a match on any type with the provided fields - /// - /// - /// - /// - /// - public static EMatchResult Include(TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.IncludeFields is null || parms.IncludeFields.Count == 0) return EMatchResult.Disabled; - - var matches = type.Fields - .Where(field => parms.IncludeFields.Contains(field.Name)) - .Count(); - - score.Score += matches > 0 ? matches : -matches; - - score.FailureReason = matches > 0 ? EFailureReason.None : EFailureReason.FieldsInclude; - - return matches > 0 - ? EMatchResult.Match - : EMatchResult.NoMatch; - } - - /// - /// Returns a match on any type without the provided fields - /// - /// - /// - /// - /// - public static EMatchResult Exclude(TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.ExcludeFields is null || parms.ExcludeFields.Count == 0) return EMatchResult.Disabled; - - var matches = type.Fields - .Where(field => parms.ExcludeFields.Contains(field.Name)) - .Count(); - - score.Score += matches > 0 ? -matches : 1; - - score.FailureReason = matches > 0 ? EFailureReason.FieldsExclude : EFailureReason.None; - - return matches > 0 - ? EMatchResult.NoMatch - : EMatchResult.Match; - } - - /// - /// Returns a match on any type with a matching number of fields - /// - /// - /// - /// - /// - public static EMatchResult Count(TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.FieldCount is null) return EMatchResult.Disabled; - - var match = type.Fields.Exactly((int)parms.FieldCount); - - score.Score += match ? (int)parms.FieldCount : -(int)parms.FieldCount; - - score.FailureReason = match ? EFailureReason.None : EFailureReason.FieldsCount; - - return match - ? EMatchResult.Match - : EMatchResult.NoMatch; - } -} \ No newline at end of file diff --git a/RecodeItLib/Remapper/Search/GenericTypeFilters.cs b/RecodeItLib/Remapper/Search/GenericTypeFilters.cs new file mode 100644 index 0000000..34a996f --- /dev/null +++ b/RecodeItLib/Remapper/Search/GenericTypeFilters.cs @@ -0,0 +1,256 @@ +using dnlib.DotNet; +using ReCodeIt.Models; +using ReCodeIt.Utils; + +namespace ReCodeItLib.Remapper.Search; + +internal static class GenericTypeFilters +{ + /// + /// Filters based on public, or nested public or private if the nested flag is set. This is a + /// required property + /// + /// + /// + /// Filtered list + public static IEnumerable FilterPublic(IEnumerable types, SearchParams parms) + { + // REQUIRED PROPERTY + if (parms.IsPublic) + { + if (parms.IsNested is true) + { + Logger.Log("IsNested Public", ConsoleColor.Yellow); + + types = types.Where(t => t.IsNestedPublic); + + types = FilterNestedByName(types, parms); + } + else + { + Logger.Log("IsPublic is true", ConsoleColor.Yellow); + types = types.Where(t => t.IsPublic); + } + } + else + { + if (parms.IsNested is true) + { + Logger.Log("IsNested Private or family", ConsoleColor.Yellow); + + types = types.Where(t => t.IsNestedPrivate + || t.IsNestedFamily + || t.IsNestedFamilyAndAssembly + || t.IsNestedAssembly); + + types = FilterNestedByName(types, parms); + } + else + { + Logger.Log("IsPublic is false", ConsoleColor.Yellow); + types = types.Where(t => t.IsNotPublic); + } + } + + return types; + } + + private static IEnumerable FilterNestedByName(IEnumerable types, SearchParams parms) + { + if (parms.NTParentName is not null) + { + Logger.Log($"NT Parent: {parms.NTParentName}", ConsoleColor.Yellow); + types = types.Where(t => t.DeclaringType.Name.String == parms.NTParentName); + } + + return types; + } + + /// + /// Filters based on IsAbstract + /// + /// + /// + /// Filtered list + public static IEnumerable FilterAbstract(IEnumerable types, SearchParams parms) + { + // Filter based on abstract or not + if (parms.IsAbstract is true) + { + Logger.Log("IsAbstract is true", ConsoleColor.Yellow); + types = types.Where(t => t.IsAbstract && !t.IsInterface); + } + else if (parms.IsAbstract is false) + { + Logger.Log("IsAbstract is false", ConsoleColor.Yellow); + types = types.Where(t => !t.IsAbstract); + } + + return types; + } + + /// + /// Filters based on IsAbstract + /// + /// + /// + /// Filtered list + public static IEnumerable FilterSealed(IEnumerable types, SearchParams parms) + { + // Filter based on abstract or not + if (parms.IsSealed is true) + { + Logger.Log("IsSealed is true", ConsoleColor.Yellow); + types = types.Where(t => t.IsSealed); + } + else if (parms.IsSealed is false) + { + Logger.Log("IsSealed is false", ConsoleColor.Yellow); + types = types.Where(t => !t.IsSealed); + } + + return types; + } + + /// + /// Filters based on IsInterface + /// + /// + /// + /// Filtered list + public static IEnumerable FilterInterface(IEnumerable types, SearchParams parms) + { + // Filter based on interface or not + if (parms.IsInterface is true) + { + Logger.Log("IsInterface is true", ConsoleColor.Yellow); + types = types.Where(t => t.IsInterface); + } + else if (parms.IsInterface is false) + { + Logger.Log("IsInterface is false", ConsoleColor.Yellow); + types = types.Where(t => !t.IsInterface); + } + + return types; + } + + /// + /// Filters based on IsStruct + /// + /// + /// + /// Filtered list + public static IEnumerable FilterStruct(IEnumerable types, SearchParams parms) + { + if (parms.IsStruct is true) + { + Logger.Log("IsStruct is true", ConsoleColor.Yellow); + types = types.Where(t => t.IsValueType && !t.IsEnum); + } + else if (parms.IsStruct is false) + { + Logger.Log("IsStruct is false", ConsoleColor.Yellow); + types = types.Where(t => !t.IsValueType); + } + + return types; + } + + /// + /// Filters based on IsEnum + /// + /// + /// + /// Filtered list + public static IEnumerable FilterEnum(IEnumerable types, SearchParams parms) + { + // Filter based on enum or not + if (parms.IsEnum is true) + { + Logger.Log("IsEnum is true", ConsoleColor.Yellow); + types = types.Where(t => t.IsEnum); + } + else if (parms.IsEnum is false) + { + Logger.Log("IsEnum is false", ConsoleColor.Yellow); + types = types.Where(t => !t.IsEnum); + } + + return types; + } + + /// + /// Filters based on HasAttribute + /// + /// + /// + /// Filtered list + public static IEnumerable FilterAttributes(IEnumerable types, SearchParams parms) + { + // Filter based on HasAttribute or not + if (parms.HasAttribute is true) + { + Logger.Log("HasAttribute is true", ConsoleColor.Yellow); + types = types.Where(t => t.HasCustomAttributes); + } + else if (parms.HasAttribute is false) + { + Logger.Log("HasAttribute is false", ConsoleColor.Yellow); + types = types.Where(t => !t.HasCustomAttributes); + } + + return types; + } + + /// + /// Filters based on HasAttribute + /// + /// + /// + /// Filtered list + public static IEnumerable FilterDerived(IEnumerable types, SearchParams parms) + { + // Filter based on IsDerived or not + if (parms.IsDerived is true) + { + Logger.Log("IsDerived is true", ConsoleColor.Yellow); + types = types.Where(t => t.GetBaseType()?.Name?.String != "Object"); + + if (parms.MatchBaseClass is not null and not "") + { + Logger.Log($"Matching base class: {parms.MatchBaseClass}", ConsoleColor.Yellow); + types = types.Where(t => t.GetBaseType()?.Name?.String == parms.MatchBaseClass); + } + + if (parms.IgnoreBaseClass is not null and not "") + { + Logger.Log($"Ignoring base class: {parms.MatchBaseClass}", ConsoleColor.Yellow); + types = types.Where(t => t.GetBaseType()?.Name?.String != parms.IgnoreBaseClass); + } + } + else if (parms.IsDerived is false) + { + Logger.Log("IsDerived is false", ConsoleColor.Yellow); + types = types.Where(t => t.GetBaseType()?.Name?.String is "Object"); + } + + return types; + } + + /// + /// Filters based on method count + /// + /// + /// + /// Filtered list + public static IEnumerable FilterByGenericParameters(IEnumerable types, SearchParams parms) + { + if (parms.HasGenericParameters is null) return types; + + Logger.Log("Matching generic parameters", ConsoleColor.Yellow); + types = types.Where(t => t.HasGenericParameters == parms.HasGenericParameters); + + return types; + } +} \ No newline at end of file diff --git a/RecodeItLib/Remapper/Search/MethodTypeFilters.cs b/RecodeItLib/Remapper/Search/MethodTypeFilters.cs new file mode 100644 index 0000000..c570085 --- /dev/null +++ b/RecodeItLib/Remapper/Search/MethodTypeFilters.cs @@ -0,0 +1,96 @@ +using dnlib.DotNet; +using ReCodeIt.Models; +using ReCodeIt.Utils; + +namespace ReCodeItLib.Remapper.Search; + +internal static class MethodTypeFilters +{ + /// + /// Filters based on method includes + /// + /// + /// + /// Filtered list + public static IEnumerable FilterByInclude(IEnumerable types, SearchParams parms) + { + if (parms.IncludeMethods.Count == 0) return types; + + List filteredTypes = []; + + foreach (var type in types) + { + if (parms.IncludeMethods + .All(includeName => type.Methods + .Any(method => method.Name.String == includeName))) + { + filteredTypes.Add(type); + } + } + + return filteredTypes.Any() ? filteredTypes : types; + } + + /// + /// Filters based on method excludes + /// + /// + /// + /// Filtered list + public static IEnumerable FilterByExclude(IEnumerable types, SearchParams parms) + { + if (parms.ExcludeMethods.Count == 0) return types; + + List filteredTypes = []; + + foreach (var type in types) + { + var match = type.Methods + .Where(method => parms.ExcludeMethods.Contains(method.Name.String)); + + if (!match.Any()) + { + filteredTypes.Add(type); + } + } + + return filteredTypes.Any() ? filteredTypes : types; + } + + /// + /// Filters based on method count + /// + /// + /// + /// Filtered list + public static IEnumerable FilterByCount(IEnumerable types, SearchParams parms) + { + if (parms.MethodCount is null) return types; + + if (parms.MethodCount >= 0) + { + Logger.Log("Matching method count", ConsoleColor.Yellow); + types = types.Where(t => GetMethodCountExcludingConstructors(t) == parms.MethodCount); + } + + return types; + } + + /// + /// We don't want the constructors included in the count + /// + /// + /// + private static int GetMethodCountExcludingConstructors(TypeDef type) + { + int count = 0; + foreach (var method in type.Methods) + { + if (!method.IsConstructor && !method.IsSpecialName) + { + count++; + } + } + return count; + } +} \ No newline at end of file diff --git a/RecodeItLib/Remapper/Search/Methods.cs b/RecodeItLib/Remapper/Search/Methods.cs deleted file mode 100644 index a49d483..0000000 --- a/RecodeItLib/Remapper/Search/Methods.cs +++ /dev/null @@ -1,80 +0,0 @@ -using Mono.Cecil; -using Mono.Cecil.Rocks; -using ReCodeIt.Enums; -using ReCodeIt.Models; - -namespace ReCodeIt.ReMapper.Search; - -internal static class Methods -{ - /// - /// returns a match on all types with the specified methods - /// - /// - /// - /// - /// Match if type contains any supplied methods - public static EMatchResult Include(TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.IncludeMethods is null || parms.IncludeMethods.Count == 0) return EMatchResult.Disabled; - - var matches = type.Methods - .Where(method => parms.IncludeMethods.Any(include => method.Name.Contains(include))) - .Count(); - - score.Score += matches > 0 ? matches : -matches; - - score.FailureReason = matches > 0 ? EFailureReason.None : EFailureReason.MethodsInclude; - - return matches > 0 - ? EMatchResult.Match - : EMatchResult.NoMatch; - } - - /// - /// Returns a match on all types without methods - /// - /// - /// - /// - /// Match if type has no methods - public static EMatchResult Exclude(TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.ExcludeMethods is null || parms.ExcludeMethods.Count == 0) return EMatchResult.Disabled; - - var matches = type.Methods - .Where(method => parms.ExcludeMethods.Contains(method.Name)) - .Count(); - - score.Score += matches > 0 ? -matches : 1; - - score.FailureReason = matches > 0 ? EFailureReason.MethodsExclude : EFailureReason.None; - - return matches > 0 - ? EMatchResult.NoMatch - : EMatchResult.Match; - } - - /// - /// Returns a match if the type has the provided number of methods - /// - /// - /// - /// - /// - public static EMatchResult Count(TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.MethodCount is null) return EMatchResult.Disabled; - - var numMethods = type.Methods.Count - type.GetConstructors().Count(); - bool match = numMethods == parms.MethodCount; - - score.Score += match ? (int)parms.MethodCount : -(int)parms.MethodCount; - - score.FailureReason = match ? EFailureReason.None : EFailureReason.MethodsCount; - - return match - ? EMatchResult.Match - : EMatchResult.NoMatch; - } -} \ No newline at end of file diff --git a/RecodeItLib/Remapper/Search/NestedTypeFilters.cs b/RecodeItLib/Remapper/Search/NestedTypeFilters.cs new file mode 100644 index 0000000..18c14d8 --- /dev/null +++ b/RecodeItLib/Remapper/Search/NestedTypeFilters.cs @@ -0,0 +1,76 @@ +using dnlib.DotNet; +using ReCodeIt.Models; + +namespace ReCodeIt.ReMapper.Search; + +internal static class NestedTypeFilters +{ + /// + /// Filters based on nested type includes + /// + /// + /// + /// Filtered list + public static IEnumerable FilterByInclude(IEnumerable types, SearchParams parms) + { + if (parms.IncludeNestedTypes.Count == 0) return types; + + List filteredTypes = []; + + foreach (var type in types) + { + if (parms.IncludeNestedTypes + .All(includeName => type.NestedTypes + .Any(nestedType => nestedType.Name.String == includeName))) + { + filteredTypes.Add(type); + } + } + + return filteredTypes.Any() ? filteredTypes : types; + } + + /// + /// Filters based on nested type excludes + /// + /// + /// + /// Filtered list + public static IEnumerable FilterByExclude(IEnumerable types, SearchParams parms) + { + if (parms.ExcludeNestedTypes.Count == 0) return types; + + List filteredTypes = []; + + foreach (var type in types) + { + var match = type.Fields + .Where(field => parms.ExcludeNestedTypes.Contains(field.Name.String)); + + if (!match.Any()) + { + filteredTypes.Add(type); + } + } + + return filteredTypes.Any() ? filteredTypes : types; + } + + /// + /// Filters based on nested type count + /// + /// + /// + /// Filtered list + public static IEnumerable FilterByCount(IEnumerable types, SearchParams parms) + { + if (parms.NestedTypeCount is null) return types; + + if (parms.NestedTypeCount >= 0) + { + types = types.Where(t => t.NestedTypes.Count == parms.NestedTypeCount); + } + + return types; + } +} \ No newline at end of file diff --git a/RecodeItLib/Remapper/Search/NestedTypes.cs b/RecodeItLib/Remapper/Search/NestedTypes.cs deleted file mode 100644 index 3d19ea8..0000000 --- a/RecodeItLib/Remapper/Search/NestedTypes.cs +++ /dev/null @@ -1,58 +0,0 @@ -using Mono.Cecil; -using MoreLinq; -using ReCodeIt.Enums; -using ReCodeIt.Models; - -namespace ReCodeIt.ReMapper.Search; - -internal class NestedTypes -{ - public static EMatchResult Include(TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.IncludeNestedTypes is null || parms.IncludeNestedTypes.Count == 0) return EMatchResult.Disabled; - - var matches = type.NestedTypes - .Where(nt => parms.IncludeNestedTypes.Contains(nt.Name)) - .Count(); - - score.Score += matches > 0 ? matches : -matches; - - score.FailureReason = matches > 0 ? EFailureReason.None : EFailureReason.NestedTypeInclude; - - return matches > 0 - ? EMatchResult.Match - : EMatchResult.NoMatch; - } - - public static EMatchResult Exclude(TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.ExcludeNestedTypes is null || parms.ExcludeNestedTypes.Count == 0) return EMatchResult.Disabled; - - var matches = type.NestedTypes - .Where(nt => parms.ExcludeNestedTypes.Contains(nt.Name)) - .Count(); - - score.Score += matches > 0 ? -matches : 1; - - score.FailureReason = matches > 0 ? EFailureReason.NestedTypeExclude : EFailureReason.None; - - return matches > 0 - ? EMatchResult.NoMatch - : EMatchResult.Match; - } - - public static EMatchResult Count(TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.NestedTypeCount is null) return EMatchResult.Disabled; - - var match = type.NestedTypes.Exactly((int)parms.NestedTypeCount); - - score.Score += match ? type.NestedTypes.Count : -type.NestedTypes.Count - 1; - - score.FailureReason = match ? EFailureReason.None : EFailureReason.NestedTypeCount; - - return match - ? EMatchResult.Match - : EMatchResult.NoMatch; - } -} \ No newline at end of file diff --git a/RecodeItLib/Remapper/Search/Properties.cs b/RecodeItLib/Remapper/Search/Properties.cs deleted file mode 100644 index 3b2e266..0000000 --- a/RecodeItLib/Remapper/Search/Properties.cs +++ /dev/null @@ -1,57 +0,0 @@ -using Mono.Cecil; -using MoreLinq; -using ReCodeIt.Enums; -using ReCodeIt.Models; - -namespace ReCodeIt.ReMapper.Search -{ - internal class Properties - { - public static EMatchResult Include(TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.IncludeProperties is null || parms.IncludeProperties.Count == 0) return EMatchResult.Disabled; - - var matches = type.Properties - .Where(property => parms.IncludeProperties.Contains(property.Name)) - .Count(); - - score.Score += matches > 0 ? matches : -matches; - - score.FailureReason = matches > 0 ? EFailureReason.None : EFailureReason.PropertiesInclude; - - return matches > 0 - ? EMatchResult.Match - : EMatchResult.NoMatch; - } - - public static EMatchResult Exclude(TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.ExcludeProperties is null || parms.ExcludeProperties.Count == 0) return EMatchResult.Disabled; - - var matches = type.Properties - .Where(property => parms.ExcludeProperties.Contains(property.Name)) - .Count(); - - score.Score += matches > 0 ? -matches : 1; - - score.FailureReason = matches > 0 ? EFailureReason.PropertiesExclude : EFailureReason.None; - - return matches > 0 - ? EMatchResult.NoMatch - : EMatchResult.Match; - } - - public static EMatchResult Count(TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.PropertyCount is null) return EMatchResult.Disabled; - - var match = type.Properties.Exactly((int)parms.PropertyCount); - - score.Score += match ? (int)parms.PropertyCount : -(int)parms.PropertyCount; - - return match - ? EMatchResult.Match - : EMatchResult.NoMatch; - } - } -} \ No newline at end of file diff --git a/RecodeItLib/Remapper/Search/PropertyTypeFilters.cs b/RecodeItLib/Remapper/Search/PropertyTypeFilters.cs new file mode 100644 index 0000000..3e0ec81 --- /dev/null +++ b/RecodeItLib/Remapper/Search/PropertyTypeFilters.cs @@ -0,0 +1,78 @@ +using dnlib.DotNet; +using ReCodeIt.Models; +using ReCodeIt.Utils; + +namespace ReCodeItLib.Remapper.Search; + +internal static class PropertyTypeFilters +{ + /// + /// Filters based on property includes + /// + /// + /// + /// Filtered list + public static IEnumerable FilterByInclude(IEnumerable types, SearchParams parms) + { + if (parms.IncludeProperties.Count == 0) return types; + + List filteredTypes = []; + + foreach (var type in types) + { + if (parms.IncludeProperties + .All(includeName => type.Properties + .Any(prop => prop.Name.String == includeName))) + { + filteredTypes.Add(type); + } + } + + return filteredTypes.Any() ? filteredTypes : types; + } + + /// + /// Filters based on property excludes + /// + /// + /// + /// Filtered list + public static IEnumerable FilterByExclude(IEnumerable types, SearchParams parms) + { + if (parms.ExcludeProperties.Count == 0) return types; + + List filteredTypes = []; + + foreach (var type in types) + { + var match = type.Properties + .Where(prop => parms.ExcludeProperties.Contains(prop.Name.String)); + + if (!match.Any()) + { + filteredTypes.Add(type); + } + } + + return filteredTypes.Any() ? filteredTypes : types; + } + + /// + /// Filters based on property count + /// + /// + /// + /// Filtered list + public static IEnumerable FilterByCount(IEnumerable types, SearchParams parms) + { + if (parms.PropertyCount is null) return types; + + if (parms.PropertyCount >= 0) + { + Logger.Log("Matching property count", ConsoleColor.Yellow); + types = types.Where(t => t.Properties.Count == parms.PropertyCount); + } + + return types; + } +} \ No newline at end of file diff --git a/RecodeItLib/Remapper/Search/TypeDefExtensions.cs b/RecodeItLib/Remapper/Search/TypeDefExtensions.cs deleted file mode 100644 index 49ec28e..0000000 --- a/RecodeItLib/Remapper/Search/TypeDefExtensions.cs +++ /dev/null @@ -1,266 +0,0 @@ -using Mono.Cecil; -using ReCodeIt.Enums; -using ReCodeIt.Models; -using ReCodeIt.Utils; - -namespace ReCodeIt.ReMapper.Search; - -internal static class TypeDefExtensions -{ - public static EMatchResult MatchIsAbstract(this TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.IsAbstract is null) - { - return EMatchResult.Disabled; - } - - // Interfaces cannot be abstract - if (type.IsInterface) - { - score.FailureReason = EFailureReason.IsAbstract; - return EMatchResult.NoMatch; - } - - if (type.IsAbstract == parms.IsAbstract) - { - score.Score++; - return EMatchResult.Match; - } - - score.FailureReason = EFailureReason.IsAbstract; - return EMatchResult.NoMatch; - } - - public static EMatchResult MatchIsEnum(this TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.IsEnum is null) - { - return EMatchResult.Disabled; - } - - if (type.IsEnum == parms.IsEnum) - { - score.Score++; - return EMatchResult.Match; - } - - score.FailureReason = EFailureReason.IsEnum; - return EMatchResult.NoMatch; - } - - public static EMatchResult MatchIsNested(this TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.IsNested is null) - { - return EMatchResult.Disabled; - } - - if (parms.ParentName is not null) - { - if (type.Name == parms.ParentName) - { - score.Score++; - return EMatchResult.Match; - } - } - - if (type.IsNested == parms.IsNested) - { - score.Score++; - return EMatchResult.Match; - } - - score.FailureReason = EFailureReason.IsNested; - return EMatchResult.NoMatch; - } - - public static EMatchResult MatchIsSealed(this TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.IsSealed is null) - { - return EMatchResult.Disabled; - } - - if (type.IsSealed == parms.IsSealed) - { - score.Score++; - return EMatchResult.Match; - } - - score.FailureReason = EFailureReason.IsSealed; - return EMatchResult.NoMatch; - } - - public static EMatchResult MatchIsDerived(this TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.IsDerived is null) - { - return EMatchResult.Disabled; - } - - if (type.BaseType is not null && (bool)parms.IsDerived is true) - { - if (type.BaseType.Name.Contains("Object")) { return EMatchResult.NoMatch; } - - score.Score++; - return EMatchResult.Match; - } - - if (type.BaseType?.Name == parms.MatchBaseClass) - { - return EMatchResult.Match; - } - - if (type.BaseType?.Name == parms.IgnoreBaseClass) - { - score.FailureReason = EFailureReason.IsDerived; - return EMatchResult.NoMatch; - } - - score.FailureReason = EFailureReason.IsDerived; - return EMatchResult.NoMatch; - } - - public static EMatchResult MatchIsInterface(this TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.IsInterface is null) - { - return EMatchResult.Disabled; - } - - if (type.IsInterface == parms.IsInterface) - { - score.Score++; - return EMatchResult.Match; - } - - score.FailureReason = EFailureReason.IsInterface; - return EMatchResult.NoMatch; - } - - public static EMatchResult MatchHasGenericParameters(this TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.HasGenericParameters is null) - { - return EMatchResult.Disabled; - } - - if (type.HasGenericParameters == parms.HasGenericParameters) - { - score.Score++; - return EMatchResult.Match; - } - - score.FailureReason = EFailureReason.HasGenericParameters; - return EMatchResult.NoMatch; - } - - public static EMatchResult MatchIsPublic(this TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.IsPublic == null) - { - return EMatchResult.Disabled; - } - - if ((bool)!parms.IsPublic && type.IsNotPublic) - { - score.Score++; - - return EMatchResult.Match; - } - - if ((bool)parms.IsPublic && type.IsPublic) - { - score.Score++; - return EMatchResult.Match; - } - - score.FailureReason = EFailureReason.IsPublic; - return EMatchResult.NoMatch; - } - - public static EMatchResult MatchHasAttribute(this TypeDefinition type, SearchParams parms, ScoringModel score) - { - if (parms.HasAttribute is null) - { - return EMatchResult.Disabled; - } - - if (type.HasCustomAttributes == parms.HasAttribute) - { - score.Score++; - return EMatchResult.Match; - } - - score.FailureReason = EFailureReason.HasAttribute; - return EMatchResult.NoMatch; - } - - public static EMatchResult MatchConstructors(this TypeDefinition type, SearchParams parms, ScoringModel score) - { - var matches = new List { }; - - if (parms.ConstructorParameterCount is not null) - { - matches.Add(Constructors.GetTypeByParameterCount(type, parms, score)); - } - - return matches.GetMatch(); - } - - /// - /// Handle running all method matching routines - /// - /// Match if any search criteria met - public static EMatchResult MatchMethods(this TypeDefinition type, SearchParams parms, ScoringModel score) - { - var matches = new List - { - Methods.Include(type, parms, score), - Methods.Exclude(type, parms, score), - Methods.Count(type, parms, score) - }; - - // return match if any condition matched - return matches.GetMatch(); - } - - public static EMatchResult MatchFields(this TypeDefinition type, SearchParams parms, ScoringModel score) - { - var matches = new List - { - Fields.Include(type, parms, score), - Fields.Exclude(type, parms, score), - Fields.Count(type, parms, score) - }; - - // return match if any condition matched - return matches.GetMatch(); - } - - public static EMatchResult MatchProperties(this TypeDefinition type, SearchParams parms, ScoringModel score) - { - var matches = new List - { - Properties.Include(type, parms, score), - Properties.Exclude(type, parms, score), - Properties.Count(type, parms, score) - }; - - // return match if any condition matched - return matches.GetMatch(); - } - - public static EMatchResult MatchNestedTypes(this TypeDefinition type, SearchParams parms, ScoringModel score) - { - var matches = new List - { - NestedTypes.Include(type, parms, score), - NestedTypes.Exclude(type, parms, score), - NestedTypes.Count(type, parms, score) - }; - - // return match if any condition matched - return matches.GetMatch(); - } -} \ No newline at end of file diff --git a/RecodeItLib/Utils/DataProvider.cs b/RecodeItLib/Utils/DataProvider.cs index 3b0ce1d..a85dd72 100644 --- a/RecodeItLib/Utils/DataProvider.cs +++ b/RecodeItLib/Utils/DataProvider.cs @@ -1,4 +1,4 @@ -using Mono.Cecil; +using dnlib.DotNet; using Newtonsoft.Json; using ReCodeIt.Models; using ReCodeItLib.Utils; @@ -26,14 +26,8 @@ public static class DataProvider public static List Remaps { get; set; } = []; - public static Dictionary> ScoringModels { get; set; } = []; - public static Settings Settings { get; private set; } - public static AssemblyDefinition AssemblyDefinition { get; private set; } - - public static ModuleDefinition ModuleDefinition { get; private set; } - public static void LoadAppSettings() { if (IsCli) @@ -97,26 +91,11 @@ public static class DataProvider var jsonText = File.ReadAllText(path); - ScoringModels = []; - var remaps = JsonConvert.DeserializeObject>(jsonText); if (remaps == null) { return []; } - var properties = typeof(SearchParams).GetProperties(); - - foreach (var remap in Remaps) - { - foreach (var property in properties) - { - if (property.PropertyType == typeof(List) && property.GetValue(remap.SearchParams) is null) - { - property.SetValue(remap.SearchParams, new List()); - } - } - } - - Logger.Log($"Mapping file loaded from '{path}' containing {Remaps.Count} remaps"); + Logger.Log($"Mapping file loaded from '{path}' containing {remaps.Count} remaps"); return remaps; } @@ -137,7 +116,7 @@ public static class DataProvider Logger.Log($"Mapping File Saved To {path}"); } - public static void UpdateMapping(string path) + public static void UpdateMapping(string path, List remaps) { if (!File.Exists(path)) { @@ -150,62 +129,26 @@ public static class DataProvider Formatting = Formatting.Indented }; - var properties = typeof(SearchParams).GetProperties(); - - foreach (var remap in Remaps) - { - foreach (var property in properties) - { - if (property.PropertyType == typeof(List)) - { - var val = property.GetValue(remap.SearchParams); - - if (val is List list && list.Count > 0) { continue; } - - property.SetValue(remap.SearchParams, null); - } - } - } - var jsonText = JsonConvert.SerializeObject(Remaps, settings); File.WriteAllText(path, jsonText); - Logger.Log($"Mapping file saved to {path}"); + Logger.Log($"Mapping file updated with new type names and saved to {path}", ConsoleColor.Yellow); } - public static void LoadAssemblyDefinition(string path) + public static ModuleDefMD LoadModule(string path) { - AssemblyDefinition = null; - ModuleDefinition = null; + var mcOptions = new ModuleCreationOptions(ModuleDef.CreateModuleContext()); + ModuleDefMD module = ModuleDefMD.Load(path, mcOptions); - DefaultAssemblyResolver resolver = new(); + module.Context = mcOptions.Context; - Console.WriteLine(path); - - resolver.AddSearchDirectory(Path.GetDirectoryName(path)); // Replace with the correct path : (6/14) I have no idea what I met by that - ReaderParameters parameters = new() { AssemblyResolver = resolver }; - - var assemblyDefinition = AssemblyDefinition.ReadAssembly( - path, - parameters); - - if (assemblyDefinition is null) + if (module is null) { - throw new NullReferenceException("AssemblyDefinition was null..."); + throw new NullReferenceException("Module is null..."); } - var fileName = Path.GetFileName(path); - - AssemblyDefinition = assemblyDefinition; - ModuleDefinition = assemblyDefinition.MainModule; - } - - public static string WriteAssemblyDefinition(string path) - { - AssemblyDefinition.Write(path); - - return path; + return module; } private static Settings CreateFakeSettings() diff --git a/RecodeItLib/Utils/EnumHelpers.cs b/RecodeItLib/Utils/EnumHelpers.cs index c9297f0..ce1253d 100644 --- a/RecodeItLib/Utils/EnumHelpers.cs +++ b/RecodeItLib/Utils/EnumHelpers.cs @@ -1,5 +1,4 @@ using ReCodeIt.Enums; -using MoreLinq.Extensions; namespace ReCodeIt.Utils; diff --git a/RecodeItLib/Utils/ExtentionMethods.cs b/RecodeItLib/Utils/ExtentionMethods.cs deleted file mode 100644 index 97e565d..0000000 --- a/RecodeItLib/Utils/ExtentionMethods.cs +++ /dev/null @@ -1,62 +0,0 @@ -using ReCodeIt.Models; - -namespace ReCodeIt.Utils; - -internal static class ExtentionMethods -{ - public static void AddScoreToResult(this ScoringModel model) - { - try - { - if (DataProvider.ScoringModels.TryGetValue(model.ProposedNewName, out HashSet modelHashset)) - { - foreach (var outVal in modelHashset) - { - if (outVal.Definition.Name == model.Definition.Name) - { - return; - } - } - - modelHashset.Add(model); - return; - } - - var newHash = new HashSet - { - model - }; - - DataProvider.ScoringModels.Add(model.ProposedNewName, newHash); - } - catch (Exception e) - { - Console.WriteLine(e.ToString()); - } - } - - public static int CalculateMaxScore(this SearchParams parms) - { - var propInfos = typeof(SearchParams).GetProperties(); - - int maxScore = 0; - - foreach (var propInfo in propInfos) - { - object value = propInfo.GetValue(parms); - - if (value == null) continue; - - if (value is List list) - { - maxScore += list.Count; - } - else - { - maxScore++; - } - } - - return maxScore; - } -} \ No newline at end of file diff --git a/RecodeItLib/Utils/Logger.cs b/RecodeItLib/Utils/Logger.cs index 58b64b8..aec4c04 100644 --- a/RecodeItLib/Utils/Logger.cs +++ b/RecodeItLib/Utils/Logger.cs @@ -1,9 +1,20 @@ -using ReCodeItLib.Utils; +using System.Collections.Concurrent; +using ReCodeItLib.Utils; namespace ReCodeIt.Utils; public static class Logger { + // This queue will hold the messages to then place them on the wait list + private static readonly ConcurrentQueue _messages = new(); + private static bool Running = true; + private static bool IsTerminated; + // This dictionary acts as a waitlist, we are going to wait _defaultWaitTimeMs before logging all the messages + // coming from certain thread into the console, this way we can make sure they are grouped in relevance + private static readonly Dictionary _heldMessages = new(); + // This is the timeout we will wait before logging a whole group of messages coming from a single thread + private static readonly TimeSpan _defaultWaitTimeMs = TimeSpan.FromMilliseconds(500); + static Logger() { if (File.Exists(_logPath)) @@ -11,9 +22,70 @@ public static class Logger File.Delete(_logPath); File.Create(_logPath).Close(); } + + Task.Factory.StartNew(LogThread, TaskCreationOptions.LongRunning); } - private static string _logPath => RegistryHelper.GetRegistryValue("LogPath"); + private static void LogThread() + { + while (Running || _heldMessages.Count > 0) + { + Thread.Sleep(TimeSpan.FromMilliseconds(100)); + // Check the message queue and add them to the waitlist + CheckAndHoldMessages(); + // Check the waitlist messages and see if any are ready to be logged + LogHeldMessages(); + } + + IsTerminated = true; + } + + private static void LogHeldMessages() + { + var currentLogExecution = DateTime.Now; + foreach (var heldMessagesKP in _heldMessages) + { + var heldMessages = heldMessagesKP.Value; + if (currentLogExecution - heldMessages.FirstInsertion > _defaultWaitTimeMs) + { + while (heldMessages.Messages.TryDequeue(out var messageToLog)) + LogInternal(messageToLog); + _heldMessages.Remove(heldMessagesKP.Key); + } + + } + } + + private static void CheckAndHoldMessages() + { + var currentLogExecution = DateTime.Now; + while (_messages.TryDequeue(out var messageToHold)) + { + if (!_heldMessages.TryGetValue(messageToHold.ThreadId, out var heldMessages)) + { + heldMessages = new HeldMessages + { + FirstInsertion = currentLogExecution, + ThreadID = messageToHold.ThreadId + }; + _heldMessages.Add(heldMessages.ThreadID, heldMessages); + } + heldMessages.Messages.Enqueue(messageToHold); + } + } + + public static void Terminate() + { + Running = false; + } + + public static bool IsRunning() + { + return !IsTerminated; + } + + private const string _defaultFileName = "ReCodeIt.log"; + private static string _logPath => RegistryHelper.GetRegistryValue("LogPath") ?? $"{AppDomain.CurrentDomain.BaseDirectory}{_defaultFileName}"; public static void ClearLog() { @@ -26,32 +98,23 @@ public static class Logger public static void Log(object message, ConsoleColor color = ConsoleColor.Gray, bool silent = false) { - if (!silent) - { - Console.ForegroundColor = color; - Console.WriteLine(message); - } - - WriteToDisk(message); + _messages.Enqueue(new LogMessage {Message = message, Color = color, Silent = silent, ThreadId = Thread.CurrentThread.ManagedThreadId}); } - - public static void LogDebug(object message, ConsoleColor color = ConsoleColor.Gray, bool silent = false) + + private static void LogInternal(LogMessage message) { - if (DataProvider.Settings.AppSettings.Debug) + if (!message.Silent) { - Console.ForegroundColor = color; - Console.WriteLine(message); + Console.ForegroundColor = message.Color; + Console.WriteLine(message.Message); Console.ResetColor(); - WriteToDisk(message); } - WriteToDisk(message); + WriteToDisk(message.Message); } private static void WriteToDisk(object message) { - if (DataProvider.IsCli) { return; } - try { using (StreamWriter sw = File.AppendText(_logPath)) @@ -66,4 +129,18 @@ public static class Logger Console.WriteLine($"Error logging: {ex.Message}"); } } + private class LogMessage + { + public object Message { get; init; } + public ConsoleColor Color { get; init; } + public bool Silent { get; init; } + public int ThreadId { get; init; } + } + + private class HeldMessages + { + public int ThreadID { get; init; } + public DateTime FirstInsertion { get; init; } + public Queue Messages { get; } = new(10); + } } \ No newline at end of file diff --git a/RecodeItLib/Utils/RegistryHelper.cs b/RecodeItLib/Utils/RegistryHelper.cs index 294a307..112aefb 100644 --- a/RecodeItLib/Utils/RegistryHelper.cs +++ b/RecodeItLib/Utils/RegistryHelper.cs @@ -26,7 +26,6 @@ public static class RegistryHelper public static T? GetRegistryValue(string key) { var regKey = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\ReCodeIt"); - - return (T)regKey.GetValue(key); + return (T)regKey?.GetValue(key); } } \ No newline at end of file diff --git a/RecodeItLib/Utils/SysTypeExtentions.cs b/RecodeItLib/Utils/SysTypeExtentions.cs index 4972774..9557e61 100644 --- a/RecodeItLib/Utils/SysTypeExtentions.cs +++ b/RecodeItLib/Utils/SysTypeExtentions.cs @@ -1,9 +1,45 @@ -using System.Text; +using dnlib.DotNet; +using System.Text; namespace ReCodeIt.Utils; public static class SysTypeExtentions { + /// + /// Returns a string trimmed after any non letter character + /// + /// + /// Trimmed string if special character found, or the original string + public static string TrimAfterSpecialChar(this UTF8String str) + { + var sb = new StringBuilder(); + + var trimChars = new char[] { '`', '[', ']' }; + + foreach (char c in str.ToString()) + { + if (trimChars.Contains(c)) + { + } + + if (char.IsLetter(c) || char.IsDigit(c)) + { + sb.Append(c); + } + else + { + return sb.ToString(); + } + } + + if (sb.Length > 0) + { + return sb.ToString(); + } + + return str; + } + /// /// Returns a string trimmed after any non letter character /// @@ -39,6 +75,24 @@ public static class SysTypeExtentions return str; } + /// + /// Does the property or field name exist in a given list, this applies prefixes and handles capitalization. + /// + /// + /// + /// True if it in the list + public static bool IsFieldOrPropNameInList(this UTF8String str, List list) + { + if (str.Trim().StartsWith("_")) + { + str = str.Replace("_", ""); + } + + var result = list.Any(item => str.StartsWith(item, StringComparison.CurrentCultureIgnoreCase)); + + return result; + } + /// /// Does the property or field name exist in a given list, this applies prefixes and handles capitalization. /// @@ -47,7 +101,7 @@ public static class SysTypeExtentions /// True if it in the list public static bool IsFieldOrPropNameInList(this string str, List list) { - if (str.Trim().ElementAt(0) == '_') + if (str.Trim().StartsWith("_")) { str = str.Replace("_", ""); } diff --git a/Templates/Settings.jsonc b/Templates/Settings.jsonc index 82c112a..0926fd1 100644 --- a/Templates/Settings.jsonc +++ b/Templates/Settings.jsonc @@ -1,74 +1,73 @@ { - "AppSettings": { - "Debug": false, // Enables extra debug logging, slows down the program by alot - "SilentMode": true // The tool will stop and prompt you to continue on every remapping if disable - }, - "Remapper": { - "AssemblyPath": "", // Path to the assembly we want to remap - "OutputPath": "", // Path including the filename and extension we want to write the changes to - "MappingPath": "", // Path to the mapping file - "UseProjectMappings": true, // Use the active cross compiler projects mappings - "MappingSettings": { - "RenameFields": true, // Names of fields of the matched type will be renamed to the type name with approproiate convention - "RenameProperties": true, // Names of properties of the matched type will be renamed to the type name with approproiate convention - "Publicize": true, // Publicize all types, methods, and properties : NOTE: Not run until after the remap has completed - "Unseal": true // Unseal all types : NOTE: Not run until after the remap has completed - } - }, - "AutoMapper": { - "AssemblyPath": "", // Path to the assembly we want to remap - "OutputPath": "", // Path including the filename and extension we want to write the changes to - "RequiredMatches": 5, // Minimum number of times a member must have this name in the assembly before considering it for remapping - "MinLengthToMatch": 7, // Minimum length of the field/property name in code before it will be considered for a rename - "SearchMethods": true, // Will attempt to map types from method meta data and parameters - "MappingSettings": { - "RenameFields": true, // Names of fields of the matched type will be renamed to the type name with approproiate convention - "RenameProperties": true, // Names of properties of the matched type will be renamed to the type name with approproiate convention - "Publicize": true, // Publicize all types, methods, and properties : NOTE: Not run until after the remap has completed - "Unseal": true // Unseal all types : NOTE: Not run until after the remap has completed - }, - "TypesToIgnore": [ // Any member name you want to ignore while iterating through the assembly - "Boolean", - "List", - "Dictionary", - "Byte", - "Int16", - "Int32", - "Func", - "Action", - "Object", - "String", - "Vector2", - "Vector3", - "Vector4", - "Stream", - "HashSet", - "Double", - "IEnumerator" - ], - "TokensToMatch": [ // The auto mapper will look for these tokens in class names and prioritize those - "Class", - "GClass", - "GStruct", - "Interface", - "GInterface" - ], - "PropertyFieldBlackList": [ // Property or fields names to ignore in the automap, these are case sanitized so case does not matter - "Columns", - "mColumns", - "Template", - "Condition", - "Conditions", - "Counter", - "Instance", - "Command", - "_template" - ], - "MethodParamaterBlackList": [ // method parameter names to ignore in the automap, these are case sanitized so case does not matter - ] - }, - "CrossCompiler": { - "AutoLoadLastActiveProject": true, // Autoload last active project - "LastLoadedProject": "" // Last loaded project path + "AppSettings": { + "Debug": false, + "SilentMode": true + }, + "Remapper": { + "AssemblyPath": "G:\\development\\ReCodeIt\\RecodeItGUI\\bin\\Debug\\net8.0-windows\\Data\\Managed\\Assembly-CSharp-cleaned.dll", + "OutputPath": "G:\\development\\ReCodeIt\\RecodeItGUI\\bin\\Debug\\net8.0-windows\\Data", + "MappingPath": "G:\\development\\ReCodeIt\\RecodeItGUI\\bin\\Debug\\net8.0-windows\\Data\\Mappings.jsonc", + "UseProjectMappings": false, + "MappingSettings": { + "RenameFields": true, + "RenameProperties": true, + "Publicize": true, + "Unseal": true } -} + }, + "AutoMapper": { + "AssemblyPath": "", + "OutputPath": "", + "RequiredMatches": 5, + "MinLengthToMatch": 7, + "SearchMethods": true, + "MappingSettings": { + "RenameFields": true, + "RenameProperties": true, + "Publicize": true, + "Unseal": true + }, + "TypesToIgnore": [ + "Boolean", + "List", + "Dictionary", + "Byte", + "Int16", + "Int32", + "Func", + "Action", + "Object", + "String", + "Vector2", + "Vector3", + "Vector4", + "Stream", + "HashSet", + "Double", + "IEnumerator" + ], + "TokensToMatch": [ + "Class", + "GClass", + "GStruct", + "Interface", + "GInterface" + ], + "PropertyFieldBlackList": [ + "Columns", + "mColumns", + "Template", + "Condition", + "Conditions", + "Counter", + "Instance", + "Command", + "_template" + ], + "MethodParamaterBlackList": [] + }, + "CrossCompiler": { + "LastLoadedProject": "", + "AutoLoadLastActiveProject": true + } +} \ No newline at end of file