0
0
mirror of https://github.com/sp-tarkov/assembly-tool.git synced 2025-02-13 07:30:43 -05:00

Merge pull request #16 from sp-tarkov/SmartMapper

Automatic mapping generation
This commit is contained in:
Cj 2025-01-02 01:30:46 -05:00 committed by GitHub
commit 533ab39f30
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 3365 additions and 3376 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,50 @@
using CliFx;
using CliFx.Attributes;
using CliFx.Infrastructure;
using ReCodeItLib.Models;
using ReCodeItLib.ReMapper;
using ReCodeItLib.Utils;
namespace ReCodeItCLI.Commands;
[Command("AutoMatch", Description = "This command will automatically try to generate a mapping object given old type and new type names.")]
public class AutoMatchCommand : ICommand
{
[CommandParameter(0, IsRequired = true, Description = "The absolute path to your assembly, folder must contain all references to be resolved.")]
public required string AssemblyPath { get; init; }
[CommandParameter(1, IsRequired = true, Description = "Path to your mapping file so it can be updated if a match is found")]
public string MappingsPath { get; init; }
[CommandParameter(2, IsRequired = true, Description = "Full old type name including namespace")]
public required string OldTypeName { get; init; }
[CommandParameter(3, IsRequired = true, Description = "The name you want the type to be renamed to")]
public required string NewTypeName { get; init; }
public ValueTask ExecuteAsync(IConsole console)
{
DataProvider.IsCli = true;
DataProvider.LoadAppSettings();
Logger.LogSync("Finding match...");
var remaps = new List<RemapModel>();
if (!string.IsNullOrEmpty(MappingsPath))
{
Logger.LogSync("Loaded mapping file", ConsoleColor.Green);
remaps.AddRange(DataProvider.LoadMappingFile(MappingsPath));
}
new AutoMatcher(remaps, MappingsPath)
.AutoMatch(AssemblyPath, OldTypeName, NewTypeName);
// Wait for log termination
Logger.Terminate();
while(Logger.IsRunning()) {}
return default;
}
}

View File

@ -6,6 +6,7 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -14,6 +14,17 @@ references needed to be resolved.
--- ---
- `automatch` - This command will Automatically try to generate a mapping object given old type and new type names.
- `AssemblyPath` - The absolute path to your assembly, folder must contain all references to be resolved.
- `MappingsPath` - Path to your mapping file so it can be updated if a match is found.
- `OldTypeName` - Full old type name including namespace.
- `NewTypeName` - The name you want the type to be renamed to.
- This command will prompt you to append your created mapping to the mapping file.
- It will then prompt you to run the remap process.
---
- `remap` - Generates a re-mapped dll provided a mapping file and dll. If the dll is obfuscated, it will automatically de-obfuscate. - `remap` - Generates a re-mapped dll provided a mapping file and dll. If the dll is obfuscated, it will automatically de-obfuscate.
- Param `MappingJsonPath` - The absolute path to the `mapping.json` file supports both `json` and `jsonc`. - Param `MappingJsonPath` - The absolute path to the `mapping.json` file supports both `json` and `jsonc`.
- Param `AssemblyPath` - The absolute path to the dll generated from the `deobfuscate` command. - Param `AssemblyPath` - The absolute path to the dll generated from the `deobfuscate` command.

View File

@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 17
VisualStudioVersion = 17.9.34728.123 VisualStudioVersion = 17.9.34728.123
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReCodeItGUI", "RecodeItGUI\ReCodeItGUI.csproj", "{7C4A62CE-8072-454F-9D95-6CB4D837F485}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReCodeItLib", "RecodeItLib\ReCodeItLib.csproj", "{FDA58DB6-E114-4FE0-AAF1-C3DEE44AEF99}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReCodeItLib", "RecodeItLib\ReCodeItLib.csproj", "{FDA58DB6-E114-4FE0-AAF1-C3DEE44AEF99}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReCodeItCLI", "ReCodeItCLI\ReCodeItCLI.csproj", "{E404EC0B-06D2-4964-8ABA-A634F259655C}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReCodeItCLI", "ReCodeItCLI\ReCodeItCLI.csproj", "{E404EC0B-06D2-4964-8ABA-A634F259655C}"
@ -25,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "de4dot.blocks", "de4dot\de4
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "de4dot-x64", "de4dot\de4dot-x64\de4dot-x64.csproj", "{3D0F9399-7814-4EB9-8436-D56BA87F874C}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "de4dot-x64", "de4dot\de4dot-x64\de4dot-x64.csproj", "{3D0F9399-7814-4EB9-8436-D56BA87F874C}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "de4dot", "de4dot", "{B12B2700-C6F1-48F8-82AD-8A8C9083D66F}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -39,26 +39,6 @@ Global
Release|x86 = Release|x86 Release|x86 = Release|x86
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7C4A62CE-8072-454F-9D95-6CB4D837F485}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7C4A62CE-8072-454F-9D95-6CB4D837F485}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7C4A62CE-8072-454F-9D95-6CB4D837F485}.Debug|ARM.ActiveCfg = Debug|Any CPU
{7C4A62CE-8072-454F-9D95-6CB4D837F485}.Debug|ARM.Build.0 = Debug|Any CPU
{7C4A62CE-8072-454F-9D95-6CB4D837F485}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{7C4A62CE-8072-454F-9D95-6CB4D837F485}.Debug|ARM64.Build.0 = Debug|Any CPU
{7C4A62CE-8072-454F-9D95-6CB4D837F485}.Debug|x64.ActiveCfg = Debug|Any CPU
{7C4A62CE-8072-454F-9D95-6CB4D837F485}.Debug|x64.Build.0 = Debug|Any CPU
{7C4A62CE-8072-454F-9D95-6CB4D837F485}.Debug|x86.ActiveCfg = Debug|Any CPU
{7C4A62CE-8072-454F-9D95-6CB4D837F485}.Debug|x86.Build.0 = Debug|Any CPU
{7C4A62CE-8072-454F-9D95-6CB4D837F485}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7C4A62CE-8072-454F-9D95-6CB4D837F485}.Release|Any CPU.Build.0 = Release|Any CPU
{7C4A62CE-8072-454F-9D95-6CB4D837F485}.Release|ARM.ActiveCfg = Release|Any CPU
{7C4A62CE-8072-454F-9D95-6CB4D837F485}.Release|ARM.Build.0 = Release|Any CPU
{7C4A62CE-8072-454F-9D95-6CB4D837F485}.Release|ARM64.ActiveCfg = Release|Any CPU
{7C4A62CE-8072-454F-9D95-6CB4D837F485}.Release|ARM64.Build.0 = Release|Any CPU
{7C4A62CE-8072-454F-9D95-6CB4D837F485}.Release|x64.ActiveCfg = Release|Any CPU
{7C4A62CE-8072-454F-9D95-6CB4D837F485}.Release|x64.Build.0 = Release|Any CPU
{7C4A62CE-8072-454F-9D95-6CB4D837F485}.Release|x86.ActiveCfg = Release|Any CPU
{7C4A62CE-8072-454F-9D95-6CB4D837F485}.Release|x86.Build.0 = Release|Any CPU
{FDA58DB6-E114-4FE0-AAF1-C3DEE44AEF99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FDA58DB6-E114-4FE0-AAF1-C3DEE44AEF99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FDA58DB6-E114-4FE0-AAF1-C3DEE44AEF99}.Debug|Any CPU.Build.0 = Debug|Any CPU {FDA58DB6-E114-4FE0-AAF1-C3DEE44AEF99}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FDA58DB6-E114-4FE0-AAF1-C3DEE44AEF99}.Debug|ARM.ActiveCfg = Debug|Any CPU {FDA58DB6-E114-4FE0-AAF1-C3DEE44AEF99}.Debug|ARM.ActiveCfg = Debug|Any CPU
@ -266,4 +246,13 @@ Global
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C2C7C51D-6773-404D-B51D-BC279AC9B923} SolutionGuid = {C2C7C51D-6773-404D-B51D-BC279AC9B923}
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{02FBA28C-E86C-49DC-8B44-A69CC542F693} = {B12B2700-C6F1-48F8-82AD-8A8C9083D66F}
{CF1A1A5E-292B-42DE-AAA0-6801AD1AD407} = {B12B2700-C6F1-48F8-82AD-8A8C9083D66F}
{3D0F9399-7814-4EB9-8436-D56BA87F874C} = {B12B2700-C6F1-48F8-82AD-8A8C9083D66F}
{8365D905-3BC4-42A0-B072-035598C6AF8C} = {B12B2700-C6F1-48F8-82AD-8A8C9083D66F}
{C3C1267E-CDB9-4C47-B7F1-C929A6F2F31C} = {B12B2700-C6F1-48F8-82AD-8A8C9083D66F}
{2BCD50E1-77D5-47E3-B317-04568BF051AB} = {B12B2700-C6F1-48F8-82AD-8A8C9083D66F}
{7C68B124-809B-4D4A-960B-467B2DAF2A0A} = {B12B2700-C6F1-48F8-82AD-8A8C9083D66F}
EndGlobalSection
EndGlobal EndGlobal

File diff suppressed because it is too large Load Diff

View File

@ -1,999 +0,0 @@
using ReCodeItLib.Models;
using ReCodeItLib.ReMapper;
using ReCodeItLib.Utils;
using System.Diagnostics;
namespace ReCodeIt.GUI;
public partial class ReCodeItForm : Form
{
private static ReMapper Remapper { get; set; } = new();
private static Settings AppSettings => DataProvider.Settings;
private bool _isSearched = false;
public static Dictionary<TreeNode, RemapModel> RemapNodes = [];
private int _selectedRemapTreeIndex = 0;
private int _selectedCCRemapTreeIndex = 0;
private List<string> _cachedNewTypeNames = [];
public ReCodeItForm()
{
InitializeComponent();
SubscribeToEvents();
PopulateDomainUpDowns();
RefreshSettingsPage();
LoadMappingFile();
var remaps = DataProvider.Remaps;
ReloadRemapTreeView(remaps);
}
private void SubscribeToEvents()
{
RemapTreeView.NodeMouseDoubleClick += ManualEditSelectedRemap;
Remapper.OnComplete += ReloadTreeAfterMapping;
#region MANUAL_REMAPPER
NewTypeName.GotFocus += (sender, e) =>
{
_cachedNewTypeNames.Add(NewTypeName.Text);
};
IncludeMethodTextBox.KeyDown += (sender, e) =>
{
if (e.KeyCode == Keys.Enter)
{
MethodIncludeAddButton_Click(sender, e);
}
};
ExcludeMethodTextBox.KeyDown += (sender, e) =>
{
if (e.KeyCode == Keys.Enter)
{
MethodExcludeAddButton_Click(sender, e);
}
};
FieldsIncludeTextInput.KeyDown += (sender, e) =>
{
if (e.KeyCode == Keys.Enter)
{
FIeldIncludeAddButton_Click(sender, e);
}
};
FieldsExcludeTextInput.KeyDown += (sender, e) =>
{
if (e.KeyCode == Keys.Enter)
{
FieldExcludeAddButton_Click(sender, e);
}
};
PropertiesIncludeTextField.KeyDown += (sender, e) =>
{
if (e.KeyCode == Keys.Enter)
{
PropertiesIncludeAddButton_Click(sender, e);
}
};
PropertiesExcludeTextField.KeyDown += (sender, e) =>
{
if (e.KeyCode == Keys.Enter)
{
PropertiesExcludeAddButton_Click(sender, e);
}
};
NestedTypesIncludeTextField.KeyDown += (sender, e) =>
{
if (e.KeyCode == Keys.Enter)
{
NestedTypesAddButton_Click(sender, e);
}
};
NestedTypesExcludeTextField.KeyDown += (sender, e) =>
{
if (e.KeyCode == Keys.Enter)
{
NestedTypesExlcudeAddButton_Click(sender, e);
}
};
EventsIncludeTextField.KeyDown += (sender, e) =>
{
if (e.KeyCode == Keys.Enter)
{
EventsAddButton_Click(sender, e);
}
};
EventsExcludeTextField.KeyDown += (sender, e) =>
{
if (e.KeyCode == Keys.Enter)
{
EventsExcludeAddButton_Click(sender, e);
}
};
#endregion MANUAL_REMAPPER
}
#region MANUAL_REMAPPER
private void LoadMappingFile()
{
DataProvider.Remaps = DataProvider.LoadMappingFile(AppSettings.Remapper.MappingPath);
LoadedMappingFilePath.Text = AppSettings.Remapper.MappingPath;
}
#region BUTTONS
#region MAIN_BUTTONS
private void SearchTreeView(object sender, EventArgs e)
{
if (RemapTreeView.Nodes.Count == 0) { return; }
if (RMSearchBox.Text == string.Empty) { return; }
bool projectMode = AppSettings.Remapper.UseProjectMappings;
var remaps = DataProvider.Remaps;
var matches = remaps
.Where(x => x.NewTypeName == RMSearchBox.Text
|| x.NewTypeName.StartsWith(RMSearchBox.Text));
if (!matches.Any()) { return; }
RemapTreeView.Nodes.Clear();
foreach (var match in matches)
{
RemapTreeView.Nodes.Add(GUIHelpers.GenerateTreeNode(match, this));
}
_isSearched = true;
}
private void ResetSearchButton_Click(object sender, EventArgs e)
{
bool projectMode = AppSettings.Remapper.UseProjectMappings;
var remaps = DataProvider.Remaps;
RemapTreeView.Nodes.Clear();
ReloadRemapTreeView(remaps);
RMSearchBox.Clear();
_isSearched = false;
}
private RemapModel? CreateRemapFromGUI()
{
if (NewTypeName.Text == string.Empty)
{
MessageBox.Show("Please enter a new type name", "Invalid data");
return null;
}
var newRemap = new RemapModel
{
Succeeded = false,
NoMatchReasons = [],
NewTypeName = NewTypeName.Text,
OriginalTypeName = OriginalTypeName.Text == string.Empty ? null : OriginalTypeName.Text,
UseForceRename = RemapperUseForceRename.Checked,
SearchParams = new SearchParams
{
GenericParams =
{
IsPublic = bool.Parse(IsPublicComboBox.GetSelectedItem<string>().AsSpan()),
IsAbstract = IsAbstractComboBox.SelectedItem as string != "Disabled"
? bool.Parse(IsAbstractComboBox.GetSelectedItem<string>().AsSpan())
: null,
IsSealed = IsSealedComboBox.SelectedItem as string != "Disabled"
? bool.Parse(IsSealedComboBox.GetSelectedItem<string>().AsSpan())
: null,
IsInterface = IsInterfaceComboBox.SelectedItem as string != "Disabled"
? bool.Parse(IsInterfaceComboBox.GetSelectedItem<string>().AsSpan())
: null,
IsStruct = IsStructComboBox.SelectedItem as string != "Disabled"
? bool.Parse(IsStructComboBox.GetSelectedItem<string>().AsSpan())
: null,
IsEnum = IsEnumComboBox.SelectedItem as string != "Disabled"
? bool.Parse(IsEnumComboBox.GetSelectedItem<string>().AsSpan())
: null,
HasAttribute = HasAttributeComboBox.SelectedItem as string != "Disabled"
? bool.Parse(HasAttributeComboBox.GetSelectedItem<string>().AsSpan())
: null,
HasGenericParameters = HasGenericParamsComboBox.SelectedItem as string != "Disabled"
? bool.Parse(HasGenericParamsComboBox.GetSelectedItem<string>().AsSpan())
: null,
IsNested = IsNestedUpDown.GetEnabled(),
IsDerived = IsDerivedUpDown.GetEnabled(),
NTParentName = NestedTypeParentName.Text == string.Empty
? null
: NestedTypeParentName.Text,
MatchBaseClass = BaseClassIncludeTextFIeld.Text == string.Empty
? null
: BaseClassIncludeTextFIeld.Text,
IgnoreBaseClass = BaseClassExcludeTextField.Text == string.Empty
? null
: BaseClassExcludeTextField.Text,
},
Methods =
{
ConstructorParameterCount = (int)ConstructorCountEnabled.GetCount(ConstuctorCountUpDown),
MethodCount = (int)MethodCountEnabled.GetCount(MethodCountUpDown),
IncludeMethods = GUIHelpers.GetAllEntriesFromListBox(MethodIncludeBox),
ExcludeMethods = GUIHelpers.GetAllEntriesFromListBox(MethodExcludeBox),
},
Fields =
{
FieldCount = (int)FieldCountEnabled.GetCount(FieldCountUpDown),
IncludeFields = GUIHelpers.GetAllEntriesFromListBox(FieldIncludeBox),
ExcludeFields = GUIHelpers.GetAllEntriesFromListBox(FieldExcludeBox),
},
Properties =
{
PropertyCount = (int)PropertyCountEnabled.GetCount(PropertyCountUpDown),
IncludeProperties = GUIHelpers.GetAllEntriesFromListBox(PropertiesIncludeBox),
ExcludeProperties = GUIHelpers.GetAllEntriesFromListBox(PropertiesExcludeBox),
},
NestedTypes =
{
NestedTypeCount = (int)NestedTypeCountEnabled.GetCount(NestedTypeCountUpDown),
IncludeNestedTypes = GUIHelpers.GetAllEntriesFromListBox(NestedTypesIncludeBox),
ExcludeNestedTypes = GUIHelpers.GetAllEntriesFromListBox(NestedTypesExcludeBox),
},
Events =
{
IncludeEvents = GUIHelpers.GetAllEntriesFromListBox(EventsIncludeBox),
ExcludeEvents = GUIHelpers.GetAllEntriesFromListBox(EventsExcludeBox)
}
}
};
return newRemap;
}
/// <summary>
/// Construct a new remap when the button is pressed
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void AddRemapButton_Click(object sender, EventArgs e)
{
ResetSearchButton_Click(this, e);
var newRemap = CreateRemapFromGUI();
if (newRemap is null) return;
bool projectMode = AppSettings.Remapper.UseProjectMappings;
Logger.Log(projectMode);
var remaps = DataProvider.Remaps;
var existingRemap = remaps
.FirstOrDefault(remap => remap.NewTypeName == newRemap.NewTypeName);
if (existingRemap == null)
{
existingRemap = remaps
.FirstOrDefault(remap => _cachedNewTypeNames.Contains(remap.NewTypeName));
}
// Handle overwriting an existing remap
if (existingRemap != null)
{
var index = remaps.IndexOf(existingRemap);
remaps.Remove(existingRemap);
RemapTreeView.Nodes.RemoveAt(index);
remaps.Insert(index, newRemap);
RemapTreeView.Nodes.Insert(index, GUIHelpers.GenerateTreeNode(newRemap, this));
DataProvider.SaveMapping();
ReloadRemapTreeView(remaps);
ResetAllRemapFields();
return;
}
DataProvider.Remaps.Add(newRemap);
DataProvider.SaveMapping();
var node = GUIHelpers.GenerateTreeNode(newRemap, this);
node.Clone();
//RemapTreeView.Nodes.Remove(node);
RemapTreeView.Nodes.Add(node);
_cachedNewTypeNames.Clear();
ReloadRemapTreeView(remaps);
ResetAllRemapFields();
}
private void RemoveRemapButton_Click(object sender, EventArgs e)
{
foreach (var node in RemapNodes.ToArray())
{
if (node.Key == RemapTreeView.SelectedNode)
{
bool projectMode = AppSettings.Remapper.UseProjectMappings;
var remaps = DataProvider.Remaps;
remaps.Remove(node.Value);
RemapNodes.Remove(node.Key);
RemapTreeView.Nodes.Remove(node.Key);
}
}
ResetAllRemapFields();
DataProvider.SaveMapping();
}
private void RunRemapButton_Click(object sender, EventArgs e)
{
if (ReMapper.IsRunning) { return; }
if (string.IsNullOrEmpty(AppSettings.Remapper.AssemblyPath))
{
MessageBox.Show("Please select an assembly path", "Assembly not loaded");
return;
}
Remapper.InitializeRemap(
DataProvider.LoadMappingFile(AppSettings.Remapper.MappingPath),
AppSettings.Remapper.AssemblyPath,
AppSettings.Remapper.OutputPath);
ReloadRemapTreeView(DataProvider.Remaps);
}
private void ValidateRemapButton_Click(object sender, EventArgs e)
{
List<RemapModel> validation = [];
var remapToValidate = CreateRemapFromGUI();
if (remapToValidate is null) return;
validation.Add(remapToValidate);
Remapper.InitializeRemap(
validation,
AppSettings.Remapper.AssemblyPath,
AppSettings.Remapper.OutputPath,
validate: true);
}
/// <summary>
/// Only used by the manual remap process, not apart of the cross compiler process
/// </summary>
private void ReloadTreeAfterMapping()
{
ReloadRemapTreeView(DataProvider.Remaps);
}
private void SaveMappingFileButton_Click(object sender, EventArgs e)
{
DataProvider.SaveMapping();
}
private void LoadMappingFileButton_Click(object sender, EventArgs e)
{
var result = GUIHelpers.OpenFileDialog("Select a mapping file",
"JSON Files (*.json)|*.json|JSONC Files (*.jsonc)|*.jsonc|All Files (*.*)|*.*");
if (result == string.Empty) { return; }
DataProvider.Remaps = DataProvider.LoadMappingFile(result);
AppSettings.Remapper.MappingPath = result;
AppSettings.Remapper.UseProjectMappings = false;
LoadedMappingFilePath.Text = result;
RemapTreeView.Nodes.Clear();
foreach (var remap in DataProvider.Remaps)
{
RemapTreeView.Nodes.Add(GUIHelpers.GenerateTreeNode(remap, this));
}
}
private void PickAssemblyPathButton_Click_1(object sender, EventArgs e)
{
var result = GUIHelpers.OpenFileDialog("Select a DLL file",
"DLL Files (*.dll)|*.dll|All Files (*.*)|*.*");
if (result != string.Empty)
{
AppSettings.Remapper.AssemblyPath = result;
TargetAssemblyPath.Text = result;
}
}
private void OutputDirectoryButton_Click_1(object sender, EventArgs e)
{
var result = GUIHelpers.OpenFolderDialog("Select an output directory");
if (result != string.Empty)
{
AppSettings.Remapper.OutputPath = result;
RemapperOutputDirectoryPath.Text = result;
}
}
#endregion MAIN_BUTTONS
#region LISTBOX_BUTTONS
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);
IncludeMethodTextBox.Clear();
}
}
private void MethodIncludeRemoveButton_Click(object sender, EventArgs e)
{
if (MethodIncludeBox.SelectedItem != null)
{
MethodIncludeBox.Items.Remove(MethodIncludeBox.SelectedItem);
}
}
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);
ExcludeMethodTextBox.Clear();
}
}
private void MethodExcludeRemoveButton_Click(object sender, EventArgs e)
{
if (MethodExcludeBox.SelectedItem != null)
{
MethodExcludeBox.Items.Remove(MethodExcludeBox.SelectedItem);
}
}
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);
FieldsIncludeTextInput.Clear();
}
}
private void FieldIncludeRemoveButton_Click(object sender, EventArgs e)
{
if (FieldIncludeBox.SelectedItem != null)
{
FieldIncludeBox.Items.Remove(FieldIncludeBox.SelectedItem);
}
}
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);
FieldsExcludeTextInput.Clear();
}
}
private void FieldExcludeRemoveButton_Click(object sender, EventArgs e)
{
if (FieldExcludeBox.SelectedItem != null)
{
FieldExcludeBox.Items.Remove(FieldExcludeBox.SelectedItem);
}
}
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);
PropertiesIncludeTextField.Clear();
}
}
private void PropertiesIncludeRemoveButton_Click(object sender, EventArgs e)
{
if (PropertiesIncludeBox.SelectedItem != null)
{
PropertiesIncludeBox.Items.Remove(PropertiesIncludeBox.SelectedItem);
}
}
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);
PropertiesExcludeTextField.Clear();
}
}
private void PropertiesExcludeRemoveButton_Click(object sender, EventArgs e)
{
if (PropertiesExcludeBox.SelectedItem != null)
{
PropertiesExcludeBox.Items.Remove(PropertiesExcludeBox.SelectedItem);
}
}
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);
NestedTypesIncludeTextField.Clear();
}
}
private void NestedTypesRemoveButton_Click(object sender, EventArgs e)
{
if (NestedTypesIncludeBox.SelectedItem != null)
{
NestedTypesIncludeBox.Items.Remove(NestedTypesIncludeBox.SelectedItem);
}
}
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);
NestedTypesExcludeTextField.Clear();
}
}
private void NestedTypesExcludeRemoveButton_Click(object sender, EventArgs e)
{
if (NestedTypesExcludeBox.SelectedItem != null)
{
NestedTypesExcludeBox.Items.Remove(NestedTypesExcludeBox.SelectedItem);
}
}
private void EventsAddButton_Click(object sender, EventArgs e)
{
if (EventsIncludeTextField.Text == string.Empty) return;
if (!EventsIncludeBox.Items.Contains(EventsIncludeTextField.Text))
{
EventsIncludeBox.Items.Add(EventsIncludeTextField.Text);
EventsIncludeTextField.Clear();
}
}
private void EventsRemoveButton_Click(object sender, EventArgs e)
{
if (EventsIncludeBox.SelectedItem != null)
{
EventsIncludeBox.Items.Remove(EventsIncludeBox.SelectedItem);
}
}
private void EventsExcludeAddButton_Click(object sender, EventArgs e)
{
if (EventsExcludeTextField.Text == string.Empty) return;
if (!EventsExcludeBox.Items.Contains(EventsExcludeTextField.Text))
{
EventsExcludeBox.Items.Add(EventsExcludeTextField.Text);
EventsExcludeTextField.Clear();
}
}
private void EventsExcludeRemoveButton_Click(object sender, EventArgs e)
{
if (EventsExcludeBox.SelectedItem != null)
{
EventsExcludeBox.Items.Remove(EventsExcludeBox.SelectedItem);
}
}
private void AutoMapperExcludeAddButton_Click(object sender, EventArgs e)
{
MessageBox.Show("Feature has been removed from this build.", "Feature Removed");
}
private void AutoMapperExcludeRemoveButton_Click(object sender, EventArgs e)
{
MessageBox.Show("Feature has been removed from this build.", "Feature Removed");
}
private void RunAutoRemapButton_Click(object sender, EventArgs e)
{
MessageBox.Show("Feature has been removed from this build.", "Feature Removed");
}
#endregion LISTBOX_BUTTONS
#region CHECKBOX
private void RemapperUnseal_CheckedChanged(object sender, EventArgs e)
{
AppSettings.Remapper.MappingSettings.Unseal = RemapperUnseal.Checked;
}
private void RemapperPublicicize_CheckedChanged(object sender, EventArgs e)
{
AppSettings.Remapper.MappingSettings.Publicize = RemapperPublicicize.Checked;
}
private void RenameFieldsCheckbox_CheckedChanged(object sender, EventArgs e)
{
AppSettings.Remapper.MappingSettings.RenameFields = RenameFieldsCheckbox.Checked;
}
private void RenamePropertiesCheckbox_CheckedChanged(object sender, EventArgs e)
{
AppSettings.Remapper.MappingSettings.RenameProperties = RenamePropertiesCheckbox.Checked;
}
#endregion CHECKBOX
#endregion BUTTONS
#endregion MANUAL_REMAPPER
#region SETTINGS_TAB
public void RefreshSettingsPage()
{
// Settings page
DebugLoggingCheckbox.Checked = AppSettings.AppSettings.Debug;
SilentModeCheckbox.Checked = AppSettings.AppSettings.SilentMode;
// Remapper page
TargetAssemblyPath.Text = AppSettings.Remapper.AssemblyPath;
RemapperOutputDirectoryPath.Text = AppSettings.Remapper.OutputPath;
RenameFieldsCheckbox.Checked = AppSettings.Remapper.MappingSettings.RenameFields;
RenamePropertiesCheckbox.Checked = AppSettings.Remapper.MappingSettings.RenameProperties;
RemapperPublicicize.Checked = AppSettings.Remapper.MappingSettings.Publicize;
RemapperUnseal.Checked = AppSettings.Remapper.MappingSettings.Unseal;
}
#region CHECKBOXES
private void DebugLoggingCheckbox_CheckedChanged(object sender, EventArgs e)
{
DataProvider.Settings.AppSettings.Debug = DebugLoggingCheckbox.Checked;
}
private void SilentModeCheckbox_CheckedChanged(object sender, EventArgs e)
{
DataProvider.Settings.AppSettings.SilentMode = SilentModeCheckbox.Checked;
}
#endregion CHECKBOXES
#endregion SETTINGS_TAB
// Reset All UI elements to default
private void ResetAllRemapFields()
{
PopulateDomainUpDowns();
// Text fields
NewTypeName.Clear();
OriginalTypeName.Clear();
BaseClassIncludeTextFIeld.Clear();
BaseClassExcludeTextField.Clear();
NestedTypeParentName.Clear();
BaseClassExcludeTextField.Clear();
IncludeMethodTextBox.Clear();
ExcludeMethodTextBox.Clear();
FieldsIncludeTextInput.Clear();
FieldsExcludeTextInput.Clear();
PropertiesIncludeTextField.Clear();
PropertiesExcludeTextField.Clear();
NestedTypesIncludeTextField.Clear();
NestedTypesExcludeTextField.Clear();
EventsIncludeTextField.Clear();
EventsExcludeTextField.Clear();
// Numeric UpDowns
ConstuctorCountUpDown.Value = 0;
MethodCountUpDown.Value = 0;
FieldCountUpDown.Value = 0;
PropertyCountUpDown.Value = 0;
NestedTypeCountUpDown.Value = 0;
// Check boxes
RemapperUseForceRename.Checked = false;
ConstructorCountEnabled.Checked = false;
MethodCountEnabled.Checked = false;
FieldCountEnabled.Checked = false;
PropertyCountEnabled.Checked = false;
NestedTypeCountEnabled.Checked = false;
// List boxes
MethodIncludeBox.Items.Clear();
MethodExcludeBox.Items.Clear();
FieldIncludeBox.Items.Clear();
FieldExcludeBox.Items.Clear();
PropertiesIncludeBox.Items.Clear();
PropertiesExcludeBox.Items.Clear();
NestedTypesIncludeBox.Items.Clear();
NestedTypesExcludeBox.Items.Clear();
EventsIncludeBox.Items.Clear();
EventsExcludeBox.Items.Clear();
}
private void ManualEditSelectedRemap(object? sender, TreeNodeMouseClickEventArgs e)
{
EditSelectedRemap(this, e);
}
private void EditSelectedRemap(
object? sender,
TreeNodeMouseClickEventArgs e,
bool isComingFromOtherTab = false)
{
if (e?.Node.Level != 0 || RemapTreeView?.SelectedNode?.Index < 0 || RemapTreeView?.SelectedNode?.Index == null)
{
return;
}
RemapModel remap = null;
foreach (var node in RemapNodes.ToArray())
{
if (node.Key == RemapTreeView.SelectedNode)
{
bool projectMode = AppSettings.Remapper.UseProjectMappings;
var remaps = DataProvider.Remaps;
remap = remaps.FirstOrDefault(x => x.NewTypeName == node.Value.NewTypeName);
break;
}
}
if (remap == null)
{
return;
}
_selectedRemapTreeIndex = RemapTreeView.SelectedNode.Index;
ResetAllRemapFields();
NewTypeName.Text = remap.NewTypeName;
OriginalTypeName.Text = remap.OriginalTypeName;
RemapperUseForceRename.Checked = remap.UseForceRename;
BaseClassIncludeTextFIeld.Text = remap.SearchParams.GenericParams.MatchBaseClass;
BaseClassExcludeTextField.Text = remap.SearchParams.GenericParams.IgnoreBaseClass;
NestedTypeParentName.Text = remap.SearchParams.GenericParams.NTParentName;
ConstructorCountEnabled.Checked = remap.SearchParams.Methods.ConstructorParameterCount >= 0;
MethodCountEnabled.Checked = remap.SearchParams.Methods.MethodCount >= 0;
FieldCountEnabled.Checked = remap.SearchParams.Fields.FieldCount >= 0;
PropertyCountEnabled.Checked = remap.SearchParams.Properties.PropertyCount >= 0;
NestedTypeCountEnabled.Checked = remap.SearchParams.NestedTypes.NestedTypeCount >= 0;
ConstuctorCountUpDown.Value = remap.SearchParams.Methods.ConstructorParameterCount;
MethodCountUpDown.Value = remap.SearchParams.Methods.MethodCount;
FieldCountUpDown.Value = remap.SearchParams.Fields.FieldCount;
PropertyCountUpDown.Value = remap.SearchParams.Properties.PropertyCount;
NestedTypeCountUpDown.Value = remap.SearchParams.NestedTypes.NestedTypeCount;
IsPublicComboBox.SelectedItem = remap.SearchParams.GenericParams.IsPublic.ToString();
IsAbstractComboBox.SelectedItem = remap.SearchParams.GenericParams.IsAbstract is not null
? remap.SearchParams.GenericParams.IsAbstract.ToString()
: "Disabled";
IsSealedComboBox.SelectedItem = remap.SearchParams.GenericParams.IsSealed is not null
? remap.SearchParams.GenericParams.IsSealed.ToString()
: "Disabled";
IsInterfaceComboBox.SelectedItem = remap.SearchParams.GenericParams.IsInterface is not null
? remap.SearchParams.GenericParams.IsInterface.ToString()
: "Disabled";
IsStructComboBox.SelectedItem = remap.SearchParams.GenericParams.IsStruct is not null
? remap.SearchParams.GenericParams.IsStruct.ToString()
: "Disabled";
IsEnumComboBox.SelectedItem = remap.SearchParams.GenericParams.IsEnum is not null
? remap.SearchParams.GenericParams.IsEnum.ToString()
: "Disabled";
HasAttributeComboBox.SelectedItem = remap.SearchParams.GenericParams.HasAttribute is not null
? remap.SearchParams.GenericParams.HasAttribute.ToString()
: "Disabled";
HasGenericParamsComboBox.SelectedItem = remap.SearchParams.GenericParams.HasGenericParameters is not null
? remap.SearchParams.GenericParams.HasGenericParameters.ToString()
: "Disabled";
IsNestedUpDown.BuildStringList("IsNested", false, remap.SearchParams.GenericParams.IsNested);
IsDerivedUpDown.BuildStringList("IsDerived", false, remap.SearchParams.GenericParams.IsDerived);
foreach (var method in remap.SearchParams.Methods.IncludeMethods)
{
MethodIncludeBox.Items.Add(method);
}
foreach (var method in remap.SearchParams.Methods.ExcludeMethods)
{
MethodExcludeBox.Items.Add(method);
}
foreach (var method in remap.SearchParams.Fields.IncludeFields)
{
FieldIncludeBox.Items.Add(method);
}
foreach (var method in remap.SearchParams.Fields.ExcludeFields)
{
FieldExcludeBox.Items.Add(method);
}
foreach (var method in remap.SearchParams.Properties.IncludeProperties)
{
PropertiesIncludeBox.Items.Add(method);
}
foreach (var method in remap.SearchParams.Properties.ExcludeProperties)
{
PropertiesExcludeBox.Items.Add(method);
}
foreach (var method in remap.SearchParams.NestedTypes.IncludeNestedTypes)
{
NestedTypesIncludeBox.Items.Add(method);
}
foreach (var method in remap.SearchParams.NestedTypes.ExcludeNestedTypes)
{
NestedTypesExcludeBox.Items.Add(method);
}
foreach (var method in remap.SearchParams.Events.IncludeEvents)
{
EventsIncludeBox.Items.Add(method);
}
foreach (var method in remap.SearchParams.Events.ExcludeEvents)
{
EventsExcludeBox.Items.Add(method);
}
}
private void PopulateDomainUpDowns()
{
// Clear them all first just incase
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);
}
/// <summary>
/// Subscribes the the remappers OnComplete event
/// </summary>
/// <param name="remaps"></param>
private void ReloadRemapTreeView(List<RemapModel>? remaps)
{
RemapTreeView.Nodes.Clear();
RemapNodes.Clear();
if (remaps is null)
{
return;
}
foreach (var remap in remaps)
{
RemapTreeView.Nodes.Add(GUIHelpers.GenerateTreeNode(remap, this));
}
}
private void GithubLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
Process.Start(new ProcessStartInfo
{
FileName = GithubLinkLabel.Text,
UseShellExecute = true
});
}
}

View File

@ -1,132 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="groupBox6.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="groupBox7.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>47</value>
</metadata>
</root>

View File

@ -1,20 +0,0 @@
using ReCodeIt.GUI;
using ReCodeItLib.Utils;
namespace ReCodeIt;
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
private static void Main()
{
DataProvider.LoadAppSettings();
// To customize application configuration such as set high DPI settings or default font, see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
Application.Run(new ReCodeItForm());
}
}

View File

@ -1,22 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Version>0.1.0</Version>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0-windows10.0.26100.0</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="xcopy &quot;$(SolutionDir)\Assets\Templates&quot; &quot;$(TargetDir)Data&quot; /E /I /Y" />
</Target>
<ItemGroup>
<ProjectReference Include="..\RecodeItLib\ReCodeItLib.csproj" />
</ItemGroup>
</Project>

View File

@ -1,360 +0,0 @@
using ReCodeItLib.Models;
using ReCodeItLib.Utils;
namespace ReCodeIt.GUI;
internal static class GUIHelpers
{
/// <summary>
/// Returns the value of the count or null if disabled
/// </summary>
/// <param name="box"></param>
/// <returns></returns>
public static int? GetCount(this CheckBox box, NumericUpDown upDown)
{
if (box.Checked)
{
return (int?)upDown.Value;
}
return null;
}
public static bool? GetEnabled(this DomainUpDown domainUpDown)
{
if (domainUpDown.Text == "True")
{
return true;
}
else if (domainUpDown.Text == "False")
{
return false;
}
return null;
}
/// <summary>
/// Builds the name list for the this updown
/// </summary>
/// <param name="domainUpDown"></param>
/// <param name="name"></param>
public static void BuildStringList(this DomainUpDown domainUpDown, string name, bool required, bool? update = null)
{
domainUpDown.Items.Clear();
domainUpDown.Text = required
? name + @" (Required)"
: name + @" (Disabled)";
domainUpDown.ReadOnly = true;
var list = new List<string>
{
name + " (Disabled)",
"True",
"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<string> items)
{
cb.Items.Clear();
foreach (var item in items)
{
cb.Items.Add(item);
}
}
public static T? GetSelectedItem<T>(this ComboBox cb)
{
return (T)cb.SelectedItem;
}
/// <summary>
/// Generates a tree node to display on the GUI
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public static TreeNode GenerateTreeNode(RemapModel model, ReCodeItForm gui)
{
var isPublic = model.SearchParams.GenericParams.IsPublic;
var isAbstract = model.SearchParams.GenericParams.IsAbstract == null ? null : model.SearchParams.GenericParams.IsAbstract;
var isInterface = model.SearchParams.GenericParams.IsInterface == null ? null : model.SearchParams.GenericParams.IsInterface;
var isStruct = model.SearchParams.GenericParams.IsStruct == null ? null : model.SearchParams.GenericParams.IsStruct;
var isEnum = model.SearchParams.GenericParams.IsEnum == null ? null : model.SearchParams.GenericParams.IsEnum;
var isNested = model.SearchParams.GenericParams.IsNested == null ? null : model.SearchParams.GenericParams.IsNested;
var isSealed = model.SearchParams.GenericParams.IsSealed == null ? null : model.SearchParams.GenericParams.IsSealed;
var HasAttribute = model.SearchParams.GenericParams.HasAttribute == null ? null : model.SearchParams.GenericParams.HasAttribute;
var IsDerived = model.SearchParams.GenericParams.IsDerived == null ? null : model.SearchParams.GenericParams.IsDerived;
var HasGenericParameters = model.SearchParams.GenericParams.HasGenericParameters == null ? null : model.SearchParams.GenericParams.HasGenericParameters;
var remapTreeItem = new TreeNode($"{model.NewTypeName}");
var originalTypeName = new TreeNode($"Original Name: {model.OriginalTypeName}");
remapTreeItem.Nodes.Add(originalTypeName);
if (model.UseForceRename)
{
remapTreeItem.Nodes.Add(new TreeNode($"Force Rename: {model.UseForceRename}"));
}
remapTreeItem.Nodes.Add(new TreeNode($"IsPublic: {isPublic}"));
if (isAbstract is not null)
{
remapTreeItem.Nodes.Add(new TreeNode($"IsAbstract: {isAbstract}"));
}
if (isInterface is not null)
{
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}"));
}
if (isNested is not null)
{
remapTreeItem.Nodes.Add(new TreeNode($"IsNested: {isNested}"));
}
if (isSealed is not null)
{
remapTreeItem.Nodes.Add(new TreeNode($"IsSealed: {isSealed}"));
}
if (HasAttribute is not null)
{
remapTreeItem.Nodes.Add(new TreeNode($"HasAttribute: {HasAttribute}"));
}
if (IsDerived is not null)
{
remapTreeItem.Nodes.Add(new TreeNode($"IsDerived: {IsDerived}"));
}
if (HasGenericParameters is not null)
{
remapTreeItem.Nodes.Add(new TreeNode($"HasGenericParameters: {HasGenericParameters}"));
}
if (model.SearchParams.Methods.ConstructorParameterCount > 0)
{
remapTreeItem.Nodes.Add(new TreeNode($"Constructor Parameter Count: {model.SearchParams.Methods.ConstructorParameterCount}"));
}
if (model.SearchParams.Methods.MethodCount >= 0)
{
remapTreeItem.Nodes.Add(new TreeNode($"Method Count: {model.SearchParams.Methods.MethodCount}"));
}
if (model.SearchParams.Fields.FieldCount >= 0)
{
remapTreeItem.Nodes.Add(new TreeNode($"Field Count: {model.SearchParams.Fields.FieldCount}"));
}
if (model.SearchParams.Properties.PropertyCount >= 0)
{
remapTreeItem.Nodes.Add(new TreeNode($"Property Count: {model.SearchParams.Properties.PropertyCount}"));
}
if (model.SearchParams.NestedTypes.NestedTypeCount >= 0)
{
remapTreeItem.Nodes.Add(new TreeNode($"Nested OriginalTypeRef Count: {model.SearchParams.NestedTypes.NestedTypeCount}"));
}
if (model.SearchParams.Methods.IncludeMethods.Count > 0)
{
var includeMethodsNode =
GenerateNodeFromList(model.SearchParams.Methods.IncludeMethods, "Include Methods");
remapTreeItem.Nodes.Add(includeMethodsNode);
}
if (model.SearchParams.Methods.ExcludeMethods?.Count > 0)
{
var excludeMethodsNode =
GenerateNodeFromList(model.SearchParams.Methods.ExcludeMethods, "Exclude Methods");
remapTreeItem.Nodes.Add(excludeMethodsNode);
}
if (model.SearchParams.Fields.IncludeFields?.Count > 0)
{
var includeFieldsNode =
GenerateNodeFromList(model.SearchParams.Fields.IncludeFields, "Include Fields");
remapTreeItem.Nodes.Add(includeFieldsNode);
}
if (model.SearchParams.Fields.ExcludeFields?.Count > 0)
{
var excludeFieldsNode =
GenerateNodeFromList(model.SearchParams.Fields.ExcludeFields, "Exclude Fields");
remapTreeItem.Nodes.Add(excludeFieldsNode);
}
if (model.SearchParams.Properties.IncludeProperties?.Count > 0)
{
var includeProperties =
GenerateNodeFromList(model.SearchParams.Properties.IncludeProperties, "Include Properties");
remapTreeItem.Nodes.Add(includeProperties);
}
if (model.SearchParams.Properties.ExcludeProperties?.Count > 0)
{
var excludeProperties =
GenerateNodeFromList(model.SearchParams.Properties.ExcludeProperties, "Exclude Properties");
remapTreeItem.Nodes.Add(excludeProperties);
}
if (model.SearchParams.NestedTypes.IncludeNestedTypes?.Count > 0)
{
var includeNestedTypes =
GenerateNodeFromList(model.SearchParams.NestedTypes.IncludeNestedTypes, "Include Nested Types");
remapTreeItem.Nodes.Add(includeNestedTypes);
}
if (model.SearchParams.NestedTypes.ExcludeNestedTypes?.Count > 0)
{
var excludeNestedTypes =
GenerateNodeFromList(model.SearchParams.NestedTypes.ExcludeNestedTypes, "Exclude Nested Types");
remapTreeItem.Nodes.Add(excludeNestedTypes);
}
if (model.SearchParams.Events.IncludeEvents?.Count > 0)
{
var includeEvents =
GenerateNodeFromList(model.SearchParams.Events.IncludeEvents, "Include Events");
remapTreeItem.Nodes.Add(includeEvents);
}
if (model.SearchParams.Events.ExcludeEvents?.Count > 0)
{
var excludeEvents =
GenerateNodeFromList(model.SearchParams.Events.ExcludeEvents, "Exclude Events");
remapTreeItem.Nodes.Add(excludeEvents);
}
ReCodeItForm.RemapNodes.Add(remapTreeItem, model);
return remapTreeItem;
}
/// <summary>
/// Generates a new node from a list of strings
/// </summary>
/// <param name="items"></param>
/// <param name="name"></param>
/// <returns>A new tree node, or null if the provided list is empty</returns>
private static TreeNode GenerateNodeFromList(List<string> items, string name)
{
var node = new TreeNode(name);
foreach (var item in items)
{
node.Nodes.Add(item);
}
return node;
}
/// <summary>
/// Buils a list of strings from list box entries
/// </summary>
/// <param name="lb"></param>
/// <returns></returns>
public static List<string> GetAllEntriesFromListBox(ListBox lb)
{
var tmp = new List<string>();
foreach (var entry in lb.Items)
{
tmp.Add((string)entry);
}
return tmp;
}
/// <summary>
/// Opens and returns a path from a file dialogue
/// </summary>
/// <param name="title"></param>
/// <param name="filter"></param>
/// <returns>Path if selected, or empty string</returns>
public static string OpenFileDialog(string title, string filter)
{
OpenFileDialog fDialog = new()
{
Title = title,
Filter = filter,
Multiselect = false
};
if (fDialog.ShowDialog() == DialogResult.OK)
{
return fDialog.FileName;
}
return string.Empty;
}
/// <summary>
/// Opens and returns a path from a folder dialogue
/// </summary>
/// <param name="description"></param>
/// <returns>Path if selected, or empty string</returns>
public static string OpenFolderDialog(string description)
{
using FolderBrowserDialog fDialog = new();
fDialog.Description = description;
fDialog.ShowNewFolderButton = true;
if (fDialog.ShowDialog() == DialogResult.OK)
{
return fDialog.SelectedPath;
}
return string.Empty;
}
}

View File

@ -35,6 +35,8 @@ public class RemapModel
public bool UseForceRename { get; set; } public bool UseForceRename { get; set; }
public bool? AutoGenerated { get; set; } = null;
public SearchParams SearchParams { get; set; } = new(); public SearchParams SearchParams { get; set; } = new();
} }
@ -59,59 +61,55 @@ public class GenericParams
public bool? IsInterface { get; set; } = null; public bool? IsInterface { get; set; } = null;
public bool? IsStruct { get; set; } = null; public bool? IsStruct { get; set; } = null;
public bool? IsEnum { get; set; } = null; public bool? IsEnum { get; set; } = null;
public bool? IsNested { get; set; } = null;
/// <summary>
/// Name of the nested types parent
/// </summary>
public string? NTParentName { get; set; } = null;
public bool? IsSealed { get; set; } = null; public bool? IsSealed { get; set; } = null;
public bool? HasAttribute { get; set; } = null; public bool? HasAttribute { get; set; } = null;
public bool? HasGenericParameters { get; set; } = null;
public bool? IsDerived { get; set; } = null; public bool? IsDerived { get; set; } = null;
/// <summary> /// <summary>
/// Name of the derived classes declaring type /// Name of the derived classes declaring type
/// </summary> /// </summary>
public string? MatchBaseClass { get; set; } = null; public string? MatchBaseClass { get; set; } = null;
/// <summary>
/// Name of the derived classes declaring type we want to ignore
/// </summary>
public string? IgnoreBaseClass { get; set; } = null;
public bool? HasGenericParameters { get; set; } = null;
} }
public class MethodParams public class MethodParams
{ {
public int ConstructorParameterCount { get; set; } = -1; public int ConstructorParameterCount { get; set; } = -1;
public int MethodCount { get; set; } = -1; public int MethodCount { get; set; } = -1;
public List<string> IncludeMethods { get; set; } = []; public HashSet<string> IncludeMethods { get; set; } = [];
public List<string> ExcludeMethods { get; set; } = []; public HashSet<string> ExcludeMethods { get; set; } = [];
} }
public class FieldParams public class FieldParams
{ {
public int FieldCount { get; set; } = -1; public int FieldCount { get; set; } = -1;
public List<string> IncludeFields { get; set; } = []; public HashSet<string> IncludeFields { get; set; } = [];
public List<string> ExcludeFields { get; set; } = []; public HashSet<string> ExcludeFields { get; set; } = [];
} }
public class PropertyParams public class PropertyParams
{ {
public int PropertyCount { get; set; } = -1; public int PropertyCount { get; set; } = -1;
public List<string> IncludeProperties { get; set; } = []; public HashSet<string> IncludeProperties { get; set; } = [];
public List<string> ExcludeProperties { get; set; } = []; public HashSet<string> ExcludeProperties { get; set; } = [];
} }
public class NestedTypeParams public class NestedTypeParams
{ {
public bool IsNested { get; set; }
/// <summary>
/// Name of the nested types parent
/// </summary>
public string NestedTypeParentName { get; set; } = string.Empty;
public int NestedTypeCount { get; set; } = -1; public int NestedTypeCount { get; set; } = -1;
public List<string> IncludeNestedTypes { get; set; } = []; public HashSet<string> IncludeNestedTypes { get; set; } = [];
public List<string> ExcludeNestedTypes { get; set; } = []; public HashSet<string> ExcludeNestedTypes { get; set; } = [];
} }
public class EventParams public class EventParams
{ {
public List<string> IncludeEvents { get; set; } = []; public int EventCount { get; set; } = -1;
public List<string> ExcludeEvents { get; set; } = []; public HashSet<string> IncludeEvents { get; set; } = [];
public HashSet<string> ExcludeEvents { get; set; } = [];
} }

View File

@ -0,0 +1,34 @@
using dnlib.DotNet;
using ReCodeItLib.Utils;
namespace ReCodeItLib.ReMapper;
internal static class AssemblyUtils
{
public static string TryDeObfuscate(ModuleDefMD module, string assemblyPath, out ModuleDefMD cleanedModule)
{
if (!module!.GetTypes().Any(t => t.Name.Contains("GClass")))
{
Logger.LogSync("Assembly is obfuscated, running de-obfuscation...\n", ConsoleColor.Yellow);
module.Dispose();
module = null;
Deobfuscator.Deobfuscate(assemblyPath);
var cleanedName = Path.GetFileNameWithoutExtension(assemblyPath);
cleanedName = $"{cleanedName}-cleaned.dll";
var newPath = Path.GetDirectoryName(assemblyPath);
newPath = Path.Combine(newPath!, cleanedName);
Logger.LogSync($"Cleaning assembly: {newPath}", ConsoleColor.Green);
cleanedModule = DataProvider.LoadModule(newPath);
return newPath;
}
cleanedModule = module;
return assemblyPath;
}
}

View File

@ -0,0 +1,416 @@
using dnlib.DotNet;
using ReCodeItLib.Models;
using ReCodeItLib.Utils;
namespace ReCodeItLib.ReMapper;
public class AutoMatcher(List<RemapModel> mappings, string mappingPath)
{
private ModuleDefMD? Module { get; set; }
private List<TypeDef>? CandidateTypes { get; set; }
private static List<string> _tokens = DataProvider.Settings!.Remapper!.TokensToMatch;
public void AutoMatch(string assemblyPath, string oldTypeName, string newTypeName)
{
assemblyPath = AssemblyUtils.TryDeObfuscate(
DataProvider.LoadModule(assemblyPath),
assemblyPath,
out var module);
Module = module;
CandidateTypes = Module.GetTypes()
.Where(t => _tokens.Any(token => t.Name.StartsWith(token)))
// .Where(t => t.Name != oldTypeName)
.ToList();
var targetTypeDef = FindTargetType(oldTypeName);
if (targetTypeDef is null)
{
Logger.LogSync($"Could not target type: {oldTypeName}", ConsoleColor.Red);
return;
}
Logger.LogSync($"Found target type: {targetTypeDef!.FullName}", ConsoleColor.Green);
var remapModel = new RemapModel();
remapModel.NewTypeName = newTypeName;
StartFilter(targetTypeDef, remapModel, assemblyPath);
}
private TypeDef? FindTargetType(string oldTypeName)
{
return Module!.GetTypes().FirstOrDefault(t => t.FullName == oldTypeName);
}
private void StartFilter(TypeDef target, RemapModel remapModel, string assemblyPath)
{
Logger.LogSync($"Starting Candidates: {CandidateTypes!.Count}", ConsoleColor.Yellow);
// Purpose of this pass is to eliminate any types that have no matching parameters
foreach (var candidate in CandidateTypes!.ToList())
{
if (!PassesGeneralChecks(target, candidate, remapModel.SearchParams.GenericParams))
{
CandidateTypes!.Remove(candidate);
continue;
}
if (!ContainsTargetMethods(target, candidate, remapModel.SearchParams.Methods))
{
CandidateTypes!.Remove(candidate);
continue;
}
if (!ContainsTargetFields(target, candidate, remapModel.SearchParams.Fields))
{
CandidateTypes!.Remove(candidate);
continue;
}
if (!ContainsTargetProperties(target, candidate, remapModel.SearchParams.Properties))
{
CandidateTypes!.Remove(candidate);
continue;
}
if (!ContainsTargetNestedTypes(target, candidate, remapModel.SearchParams.NestedTypes))
{
CandidateTypes!.Remove(candidate);
continue;
}
if (!ContainsTargetEvents(target, candidate, remapModel.SearchParams.Events))
{
CandidateTypes!.Remove(candidate);
}
}
if (CandidateTypes!.Count == 1)
{
Logger.LogSync("Narrowed candidates down to one. Testing generated model...", ConsoleColor.Green);
var tmpList = new List<RemapModel>()
{
remapModel
};
new ReMapper().InitializeRemap(tmpList, assemblyPath, validate: true);
ProcessEndQuestions(remapModel, assemblyPath);
return;
}
Logger.LogSync("Could not find a match... :(", ConsoleColor.Red);
}
private bool PassesGeneralChecks(TypeDef target, TypeDef candidate, GenericParams parms)
{
if (target.IsPublic != candidate.IsPublic) return false;
if (target.IsAbstract != candidate.IsAbstract) return false;
if (target.IsInterface != candidate.IsInterface) return false;
if (target.IsEnum != candidate.IsEnum) return false;
if (target.IsValueType != candidate.IsValueType) return false;
if (target.HasGenericParameters != candidate.HasGenericParameters) return false;
if (target.IsNested != candidate.IsNested) return false;
if (target.IsSealed != candidate.IsSealed) return false;
if (target.HasCustomAttributes != candidate.HasCustomAttributes) return false;
parms.IsPublic = target.IsPublic;
parms.IsAbstract = target.IsAbstract;
parms.IsInterface = target.IsInterface;
parms.IsEnum = target.IsEnum;
parms.IsStruct = target.IsValueType && !target.IsEnum;
parms.HasGenericParameters = target.HasGenericParameters;
parms.IsSealed = target.IsSealed;
parms.HasAttribute = target.HasCustomAttributes;
parms.IsDerived = target.BaseType != null && target.BaseType.Name != "Object";
if ((bool)parms.IsDerived)
{
parms.MatchBaseClass = target.BaseType?.Name.String;
}
return true;
}
private bool ContainsTargetMethods(TypeDef target, TypeDef candidate, MethodParams methods)
{
// Target has no methods and type has no methods
if (!target.Methods.Any() && !candidate.Methods.Any())
{
methods.MethodCount = 0;
return true;
}
// Target has no methods but type has methods
if (!target.Methods.Any() && candidate.Methods.Any()) return false;
// Target has methods but type has no methods
if (target.Methods.Any() && !candidate.Methods.Any()) return false;
// Target has a different number of methods
if (target.Methods.Count != candidate.Methods.Count) return false;
var commonMethods = target.Methods
.Where(m => !m.IsConstructor && !m.IsGetter && !m.IsSetter)
.Select(s => s.Name)
.Intersect(candidate.Methods
.Where(m => !m.IsConstructor && !m.IsGetter && !m.IsSetter)
.Select(s => s.Name));
// Methods in target that are not in candidate
var includeMethods = target.Methods
.Where(m => !m.IsConstructor && !m.IsGetter && !m.IsSetter)
.Select(s => s.Name.ToString())
.Except(candidate.Methods
.Where(m => !m.IsConstructor && !m.IsGetter && !m.IsSetter)
.Select(s => s.Name.ToString()));
// Methods in candidate that are not in target
var excludeMethods = candidate.Methods
.Where(m => !m.IsConstructor && !m.IsGetter && !m.IsSetter)
.Select(s => s.Name.ToString())
.Except(target.Methods
.Where(m => !m.IsConstructor && !m.IsGetter && !m.IsSetter)
.Select(s => s.Name.ToString()));
foreach (var include in includeMethods)
{
methods.IncludeMethods.Add(include);
}
foreach (var exclude in excludeMethods)
{
methods.ExcludeMethods.Add(exclude);
}
methods.MethodCount = target.Methods
.Count(m => !m.IsConstructor && !m.IsGetter && !m.IsSetter && !m.IsSpecialName);
if (target.Methods.Any(m => m.IsConstructor && m.Parameters.Count > 0))
{
methods.ConstructorParameterCount = target.Methods.First(m => m.IsConstructor && m.Parameters.Count > 0).Parameters.Count - 1;
}
return commonMethods.Any();
}
private bool ContainsTargetFields(TypeDef target, TypeDef candidate, FieldParams fields)
{
// Target has no fields and type has no fields
if (!target.Fields.Any() && !candidate.Fields.Any())
{
fields.FieldCount = 0;
return true;
}
// Target has fields but type has no fields
if (target.Fields.Any() && !candidate.Fields.Any()) return false;
// Target has a different number of fields
if (target.Fields.Count != candidate.Fields.Count) return false;
var commonFields = target.Fields
.Select(s => s.Name)
.Intersect(candidate.Fields.Select(s => s.Name));
// Methods in target that are not in candidate
var includeFields = target.Fields
.Select(s => s.Name.ToString())
.Except(candidate.Fields.Select(s => s.Name.ToString()));
// Methods in candidate that are not in target
var excludeFields = candidate.Fields
.Select(s => s.Name.ToString())
.Except(target.Fields.Select(s => s.Name.ToString()));
foreach (var include in includeFields)
{
fields.IncludeFields.Add(include);
}
foreach (var exclude in excludeFields)
{
fields.ExcludeFields.Add(exclude);
}
fields.FieldCount = target.Fields.Count;
return commonFields.Any();
}
private bool ContainsTargetProperties(TypeDef target, TypeDef candidate, PropertyParams props)
{
// Both target and candidate don't have properties
if (!target.Properties.Any() && !candidate.Properties.Any())
{
props.PropertyCount = 0;
return true;
}
// Target has props but type has no props
if (target.Properties.Any() && !candidate.Properties.Any()) return false;
// Target has a different number of props
if (target.Properties.Count != candidate.Properties.Count) return false;
var commonProps = target.Properties
.Select(s => s.Name)
.Intersect(candidate.Properties.Select(s => s.Name));
// Props in target that are not in candidate
var includeProps = target.Properties
.Select(s => s.Name.ToString())
.Except(candidate.Properties.Select(s => s.Name.ToString()));
// Props in candidate that are not in target
var excludeProps = candidate.Properties
.Select(s => s.Name.ToString())
.Except(target.Properties.Select(s => s.Name.ToString()));
foreach (var include in includeProps)
{
props.IncludeProperties.Add(include);
}
foreach (var exclude in excludeProps)
{
props.ExcludeProperties.Add(exclude);
}
props.PropertyCount = target.Properties.Count;
return commonProps.Any();
}
private bool ContainsTargetNestedTypes(TypeDef target, TypeDef candidate, NestedTypeParams nt)
{
// Target has no nt's but type has nt's
if (!target.NestedTypes.Any() && candidate.NestedTypes.Any())
{
nt.NestedTypeCount = 0;
return false;
}
// Target has nt's but type has no nt's
if (target.NestedTypes.Any() && !candidate.NestedTypes.Any()) return false;
// Target has a different number of nt's
if (target.NestedTypes.Count != candidate.NestedTypes.Count) return false;
var commonNts = target.NestedTypes
.Select(s => s.Name)
.Intersect(candidate.NestedTypes.Select(s => s.Name));
var includeNts = target.NestedTypes
.Select(s => s.Name.ToString())
.Except(candidate.NestedTypes.Select(s => s.Name.ToString()));
var excludeNts = candidate.NestedTypes
.Select(s => s.Name.ToString())
.Except(target.NestedTypes.Select(s => s.Name.ToString()));
foreach (var include in includeNts)
{
nt.IncludeNestedTypes.Add(include);
}
foreach (var exclude in excludeNts)
{
nt.ExcludeNestedTypes.Add(exclude);
}
nt.NestedTypeCount = target.NestedTypes.Count;
nt.IsNested = target.IsNested;
if (target.DeclaringType is not null)
{
nt.NestedTypeParentName = target.DeclaringType.Name.String;
}
return commonNts.Any() || !target.IsNested;
}
private bool ContainsTargetEvents(TypeDef target, TypeDef candidate, EventParams events)
{
// Target has no events but type has events
if (!target.Events.Any() && candidate.Events.Any())
{
events.EventCount = 0;
return false;
}
// Target has events but type has no events
if (target.Events.Any() && !candidate.Events.Any()) return false;
// Target has a different number of events
if (target.Events.Count != candidate.Events.Count) return false;
var commonEvents = target.Events
.Select(s => s.Name)
.Intersect(candidate.Events.Select(s => s.Name));
var includeEvents = target.Events
.Select(s => s.Name.ToString())
.Except(candidate.Events.Select(s => s.Name.ToString()));
var excludeEvents = candidate.Events
.Select(s => s.Name.ToString())
.Except(target.Events.Select(s => s.Name.ToString()));
foreach (var include in includeEvents)
{
events.IncludeEvents.Add(include);
}
foreach (var exclude in excludeEvents)
{
events.ExcludeEvents.Add(exclude);
}
events.EventCount = target.NestedTypes.Count;
return commonEvents.Any() || target.Events.Count == 0;
}
private void ProcessEndQuestions(RemapModel remapModel, string assemblyPath)
{
Thread.Sleep(1000);
Logger.LogSync("Add remap to existing list?.. (y/n)", ConsoleColor.Yellow);
var resp = Console.ReadLine();
if (resp == "y" || resp == "yes" || resp == "Y")
{
if (mappings.Count == 0)
{
Logger.LogSync("No remaps loaded. Please restart with a provided mapping path.", ConsoleColor.Red);
return;
}
if (mappings.Any(m => m.NewTypeName == remapModel.NewTypeName))
{
Logger.LogSync($"Ambiguous new type names found for {remapModel.NewTypeName}. Please pick a different name.", ConsoleColor.Red);
return;
}
remapModel.AutoGenerated = true;
mappings.Add(remapModel);
DataProvider.UpdateMapping(mappingPath, mappings);
}
Logger.LogSync("Would you like to run the remap process?... (y/n)", ConsoleColor.Yellow);
var resp2 = Console.ReadLine();
if (resp2 == "y" || resp2 == "yes" || resp2 == "Y")
{
var outPath = Path.GetDirectoryName(assemblyPath);
new ReMapper().InitializeRemap(mappings, assemblyPath, outPath);
}
}
}

View File

@ -17,7 +17,7 @@ internal static class GenericTypeFilters
// REQUIRED PROPERTY // REQUIRED PROPERTY
if (parms.GenericParams.IsPublic) if (parms.GenericParams.IsPublic)
{ {
if (parms.GenericParams.IsNested is true) if (parms.NestedTypes.IsNested is true)
{ {
types = types.Where(t => t.IsNestedPublic); types = types.Where(t => t.IsNestedPublic);
@ -30,7 +30,7 @@ internal static class GenericTypeFilters
} }
else else
{ {
if (parms.GenericParams.IsNested is true) if (parms.NestedTypes.IsNested is true)
{ {
types = types.Where(t => t.IsNestedPrivate types = types.Where(t => t.IsNestedPrivate
|| t.IsNestedFamily || t.IsNestedFamily
@ -50,9 +50,9 @@ internal static class GenericTypeFilters
private static IEnumerable<TypeDef> FilterNestedByName(IEnumerable<TypeDef> types, SearchParams parms) private static IEnumerable<TypeDef> FilterNestedByName(IEnumerable<TypeDef> types, SearchParams parms)
{ {
if (parms.GenericParams.NTParentName is not null) if (parms.NestedTypes.NestedTypeParentName is not "")
{ {
types = types.Where(t => t.DeclaringType.Name.String == parms.GenericParams.NTParentName); types = types.Where(t => t.DeclaringType.Name.String == parms.NestedTypes.NestedTypeParentName);
} }
return types; return types;
@ -200,11 +200,6 @@ internal static class GenericTypeFilters
{ {
types = types.Where(t => t.GetBaseType()?.Name?.String == parms.GenericParams.MatchBaseClass); types = types.Where(t => t.GetBaseType()?.Name?.String == parms.GenericParams.MatchBaseClass);
} }
if (parms.GenericParams.IgnoreBaseClass is not null and not "")
{
types = types.Where(t => t.GetBaseType()?.Name?.String != parms.GenericParams.IgnoreBaseClass);
}
} }
else if (parms.GenericParams.IsDerived is false) else if (parms.GenericParams.IsDerived is false)
{ {

View File

@ -34,14 +34,19 @@ public class ReMapper
public void InitializeRemap( public void InitializeRemap(
List<RemapModel> remapModels, List<RemapModel> remapModels,
string assemblyPath, string assemblyPath,
string outPath, string outPath = "",
bool validate = false) bool validate = false)
{ {
_remaps = []; _remaps = [];
_remaps = remapModels; _remaps = remapModels;
_alreadyGivenNames = []; _alreadyGivenNames = [];
Module = DataProvider.LoadModule(assemblyPath); assemblyPath = AssemblyUtils.TryDeObfuscate(
DataProvider.LoadModule(assemblyPath),
assemblyPath,
out var module);
Module = module;
OutPath = outPath; OutPath = outPath;
@ -52,8 +57,12 @@ public class ReMapper
var types = Module.GetTypes(); var types = Module.GetTypes();
TryDeObfuscate(types, assemblyPath); if (!validate)
FindBestMatches(types); {
GenerateDynamicRemaps(assemblyPath, types);
}
FindBestMatches(types, validate);
ChooseBestMatches(); ChooseBestMatches();
// Don't go any further during a validation // Don't go any further during a validation
@ -72,36 +81,7 @@ public class ReMapper
WriteAssembly(); WriteAssembly();
} }
private void TryDeObfuscate(IEnumerable<TypeDef> types, string assemblyPath) private void FindBestMatches(IEnumerable<TypeDef> types, bool validate)
{
if (!Module!.GetTypes().Any(t => t.Name.Contains("GClass")))
{
Logger.LogSync("Assembly is obfuscated, running de-obfuscation...\n", ConsoleColor.Yellow);
Module.Dispose();
Module = null;
Deobfuscator.Deobfuscate(assemblyPath);
var cleanedName = Path.GetFileNameWithoutExtension(assemblyPath);
cleanedName = $"{cleanedName}-cleaned.dll";
var newPath = Path.GetDirectoryName(assemblyPath);
newPath = Path.Combine(newPath!, cleanedName);
Console.WriteLine($"Cleaning assembly: {newPath}");
Module = DataProvider.LoadModule(newPath);
types = Module.GetTypes();
GenerateDynamicRemaps(newPath, types);
return;
}
GenerateDynamicRemaps(assemblyPath, types);
}
private void FindBestMatches(IEnumerable<TypeDef> types)
{ {
Logger.LogSync("Finding Best Matches...", ConsoleColor.Green); Logger.LogSync("Finding Best Matches...", ConsoleColor.Green);
@ -116,10 +96,13 @@ public class ReMapper
); );
} }
if (!validate)
{
while (!tasks.TrueForAll(t => t.Status == TaskStatus.RanToCompletion)) while (!tasks.TrueForAll(t => t.Status == TaskStatus.RanToCompletion))
{ {
Logger.DrawProgressBar(tasks.Where(t => t.IsCompleted)!.Count(), tasks.Count, 50); Logger.DrawProgressBar(tasks.Where(t => t.IsCompleted)!.Count(), tasks.Count, 50);
} }
}
Task.WaitAll(tasks.ToArray()); Task.WaitAll(tasks.ToArray());
} }
@ -197,11 +180,16 @@ public class ReMapper
} }
// Filter down nested objects // Filter down nested objects
if (mapping.SearchParams.GenericParams.IsNested is false or null) if (mapping.SearchParams.NestedTypes.IsNested is false)
{ {
types = types.Where(type => tokens!.Any(token => type.Name.StartsWith(token))); types = types.Where(type => tokens!.Any(token => type.Name.StartsWith(token)));
} }
if (mapping.SearchParams.NestedTypes.NestedTypeParentName != string.Empty)
{
types = types.Where(t => t.DeclaringType != null && t.DeclaringType.Name == mapping.SearchParams.NestedTypes.NestedTypeParentName);
}
// Run through a series of filters and report an error if all types are filtered out. // Run through a series of filters and report an error if all types are filtered out.
var filters = new TypeFilters(); var filters = new TypeFilters();

View File

@ -187,7 +187,7 @@ internal static class RenameHelper
if (remap?.TypePrimeCandidate?.Name is null) { continue; } if (remap?.TypePrimeCandidate?.Name is null) { continue; }
if (remap.SearchParams.GenericParams.IsNested is true && if (remap.SearchParams.NestedTypes.IsNested is true &&
type.IsNested && type.Name == remap.TypePrimeCandidate.Name) type.IsNested && type.Name == remap.TypePrimeCandidate.Name)
{ {
type.Name = remap.NewTypeName; type.Name = remap.NewTypeName;

View File

@ -1,4 +1,5 @@
using System.Diagnostics; using System.Diagnostics;
using Newtonsoft.Json;
using ReCodeItLib.Enums; using ReCodeItLib.Enums;
using ReCodeItLib.Models; using ReCodeItLib.Models;
using ReCodeItLib.Utils; using ReCodeItLib.Utils;
@ -14,7 +15,7 @@ public class Statistics(
public void DisplayStatistics(bool validate = false) public void DisplayStatistics(bool validate = false)
{ {
DisplayAlternativeMatches(); DisplayAlternativeMatches();
DisplayFailuresAndChanges(); DisplayFailuresAndChanges(validate);
if (!validate) if (!validate)
{ {
@ -45,7 +46,7 @@ public class Statistics(
} }
} }
private void DisplayFailuresAndChanges() private void DisplayFailuresAndChanges(bool validate)
{ {
var failures = 0; var failures = 0;
var changes = 0; var changes = 0;
@ -75,6 +76,15 @@ public class Statistics(
continue; continue;
} }
if (validate && remap.Succeeded)
{
Logger.Log("Generated Model: ", ConsoleColor.Blue);
Logger.LogRemapModel(remap);
Logger.Log("Passed validation", ConsoleColor.Green);
return;
}
changes++; changes++;
} }

View File

@ -1,4 +1,6 @@
using System.Collections.Concurrent; using System.Collections.Concurrent;
using Newtonsoft.Json;
using ReCodeItLib.Models;
namespace ReCodeItLib.Utils; namespace ReCodeItLib.Utils;
@ -119,6 +121,12 @@ public static class Logger
Console.ResetColor(); Console.ResetColor();
} }
public static void LogRemapModel(RemapModel remapModel)
{
var str = JsonConvert.SerializeObject(remapModel, Formatting.Indented);
LogSync(str, ConsoleColor.Blue);
}
private static void LogInternal(LogMessage message) private static void LogInternal(LogMessage message)
{ {
if (!message.Silent) if (!message.Silent)