2024-06-12 00:07:44 -04:00
|
|
|
|
using AssemblyRemapper.Enums;
|
|
|
|
|
using AssemblyRemapper.Models;
|
2024-06-11 19:18:48 -04:00
|
|
|
|
using AssemblyRemapper.Utils;
|
|
|
|
|
using Mono.Cecil;
|
|
|
|
|
|
|
|
|
|
namespace AssemblyRemapper.Reflection;
|
|
|
|
|
|
|
|
|
|
internal class Remapper
|
|
|
|
|
{
|
|
|
|
|
public void InitializeRemap()
|
|
|
|
|
{
|
|
|
|
|
DisplayBasicModuleInformation();
|
|
|
|
|
|
2024-06-12 00:05:59 -04:00
|
|
|
|
foreach (var remap in DataProvider.Remaps)
|
2024-06-11 19:18:48 -04:00
|
|
|
|
{
|
2024-06-11 23:07:59 -04:00
|
|
|
|
Logger.Log($"Trying to remap {remap.NewTypeName}...", ConsoleColor.Gray);
|
2024-06-11 19:18:48 -04:00
|
|
|
|
|
|
|
|
|
HandleMapping(remap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ChooseBestMatches();
|
|
|
|
|
|
|
|
|
|
if (DataProvider.AppSettings.ScoringMode) { return; }
|
|
|
|
|
|
|
|
|
|
// Dont publicize and unseal until after the remapping so we can use those as search parameters
|
|
|
|
|
HandlePublicize();
|
|
|
|
|
HandleUnseal();
|
|
|
|
|
|
|
|
|
|
// We are done, write the assembly
|
|
|
|
|
WriteAssembly();
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-12 14:38:43 -04:00
|
|
|
|
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: {DataProvider.AppSettings.Publicize}", ConsoleColor.Yellow);
|
|
|
|
|
Logger.Log($"Unseal: {DataProvider.AppSettings.Unseal}", ConsoleColor.Yellow);
|
|
|
|
|
Logger.Log("-----------------------------------------------", ConsoleColor.Yellow);
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-12 00:05:59 -04:00
|
|
|
|
private void HandleMapping(RemapModel mapping)
|
2024-06-11 19:18:48 -04:00
|
|
|
|
{
|
|
|
|
|
foreach (var type in DataProvider.ModuleDefinition.Types)
|
|
|
|
|
{
|
|
|
|
|
ScoreType(type, mapping);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void HandlePublicize()
|
|
|
|
|
{
|
|
|
|
|
if (!DataProvider.AppSettings.Publicize) { return; }
|
|
|
|
|
|
2024-06-11 23:07:59 -04:00
|
|
|
|
Logger.Log("Starting publicization...", ConsoleColor.Green);
|
2024-06-11 19:18:48 -04:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void HandleUnseal()
|
|
|
|
|
{
|
|
|
|
|
if (!DataProvider.AppSettings.Unseal) { return; }
|
|
|
|
|
|
2024-06-11 23:07:59 -04:00
|
|
|
|
Logger.Log("Starting unseal...", ConsoleColor.Green);
|
2024-06-11 19:18:48 -04:00
|
|
|
|
|
|
|
|
|
foreach (var type in DataProvider.ModuleDefinition.Types)
|
|
|
|
|
{
|
|
|
|
|
if (type.IsSealed) { type.IsSealed = false; }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-12 00:05:59 -04:00
|
|
|
|
private void ScoreType(TypeDefinition type, RemapModel remap, string parentTypeName = "")
|
2024-06-11 19:18:48 -04:00
|
|
|
|
{
|
2024-06-11 23:07:59 -04:00
|
|
|
|
// Handle Direct Remaps by strict naming first bypasses everything else
|
|
|
|
|
if (remap.UseForceRename)
|
|
|
|
|
{
|
|
|
|
|
HandleByDirectName(type, remap);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-11 19:18:48 -04:00
|
|
|
|
foreach (var nestedType in type.NestedTypes)
|
|
|
|
|
{
|
|
|
|
|
ScoreType(nestedType, remap, type.Name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var score = new ScoringModel
|
|
|
|
|
{
|
|
|
|
|
ProposedNewName = remap.NewTypeName,
|
2024-06-12 00:05:59 -04:00
|
|
|
|
RemapModel = remap,
|
|
|
|
|
Definition = type,
|
2024-06-11 19:18:48 -04:00
|
|
|
|
};
|
|
|
|
|
|
2024-06-12 14:38:43 -04:00
|
|
|
|
// Set the original type name to be used later
|
|
|
|
|
score.RemapModel.OriginalTypeName = type.Name;
|
|
|
|
|
|
2024-06-11 19:18:48 -04:00
|
|
|
|
if (type.MatchIsAbstract(remap.SearchParams, score) == EMatchResult.NoMatch)
|
|
|
|
|
{
|
2024-06-11 23:07:59 -04:00
|
|
|
|
LogDiscard("IsAbstract", type.Name, score.ProposedNewName);
|
2024-06-11 19:18:48 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
2024-06-12 00:05:59 -04:00
|
|
|
|
|
2024-06-11 19:18:48 -04:00
|
|
|
|
if (type.MatchIsEnum(remap.SearchParams, score) == EMatchResult.NoMatch)
|
|
|
|
|
{
|
2024-06-11 23:07:59 -04:00
|
|
|
|
LogDiscard("IsEnum", type.Name, score.ProposedNewName);
|
2024-06-11 19:18:48 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type.MatchIsNested(remap.SearchParams, score) == EMatchResult.NoMatch)
|
|
|
|
|
{
|
2024-06-11 23:07:59 -04:00
|
|
|
|
LogDiscard("IsNested", type.Name, score.ProposedNewName);
|
2024-06-11 19:18:48 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type.MatchIsSealed(remap.SearchParams, score) == EMatchResult.NoMatch)
|
|
|
|
|
{
|
2024-06-11 23:07:59 -04:00
|
|
|
|
LogDiscard("IsSealed", type.Name, score.ProposedNewName);
|
2024-06-11 19:18:48 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type.MatchIsDerived(remap.SearchParams, score) == EMatchResult.NoMatch)
|
|
|
|
|
{
|
2024-06-11 23:07:59 -04:00
|
|
|
|
LogDiscard("IsDerived", type.Name, score.ProposedNewName);
|
2024-06-11 19:18:48 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type.MatchIsInterface(remap.SearchParams, score) == EMatchResult.NoMatch)
|
|
|
|
|
{
|
2024-06-11 23:07:59 -04:00
|
|
|
|
LogDiscard("IsInterface", type.Name, score.ProposedNewName);
|
2024-06-11 19:18:48 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type.MatchIsGeneric(remap.SearchParams, score) == EMatchResult.NoMatch)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type.MatchIsPublic(remap.SearchParams, score) == EMatchResult.NoMatch)
|
|
|
|
|
{
|
2024-06-11 23:07:59 -04:00
|
|
|
|
LogDiscard("IsPublic", type.Name, score.ProposedNewName);
|
2024-06-11 19:18:48 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type.MatchHasAttribute(remap.SearchParams, score) == EMatchResult.NoMatch)
|
|
|
|
|
{
|
2024-06-11 23:07:59 -04:00
|
|
|
|
LogDiscard("HasAttribute", type.Name, score.ProposedNewName);
|
2024-06-11 19:18:48 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type.MatchMethods(remap.SearchParams, score) == EMatchResult.NoMatch)
|
|
|
|
|
{
|
2024-06-11 23:07:59 -04:00
|
|
|
|
LogDiscard("Methods", type.Name, score.ProposedNewName);
|
2024-06-11 19:18:48 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type.MatchFields(remap.SearchParams, score) == EMatchResult.NoMatch)
|
|
|
|
|
{
|
2024-06-11 23:07:59 -04:00
|
|
|
|
LogDiscard("Fields", type.Name, score.ProposedNewName);
|
2024-06-11 19:18:48 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type.MatchProperties(remap.SearchParams, score) == EMatchResult.NoMatch)
|
|
|
|
|
{
|
2024-06-11 23:07:59 -04:00
|
|
|
|
LogDiscard("Properties", type.Name, score.ProposedNewName);
|
2024-06-11 19:18:48 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type.MatchNestedTypes(remap.SearchParams, score) == EMatchResult.NoMatch)
|
|
|
|
|
{
|
2024-06-11 23:07:59 -04:00
|
|
|
|
LogDiscard("NestedTypes", type.Name, score.ProposedNewName);
|
2024-06-11 19:18:48 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
2024-06-11 23:07:59 -04:00
|
|
|
|
|
2024-06-11 19:18:48 -04:00
|
|
|
|
ScoringModelExtensions.AddModelToResult(score);
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-12 00:05:59 -04:00
|
|
|
|
private void HandleByDirectName(TypeDefinition type, RemapModel remap)
|
2024-06-11 23:07:59 -04:00
|
|
|
|
{
|
2024-06-12 00:05:59 -04:00
|
|
|
|
if (type.Name != remap.OriginalTypeName) { return; }
|
2024-06-11 23:07:59 -04:00
|
|
|
|
|
|
|
|
|
var oldName = type.Name;
|
|
|
|
|
type.Name = remap.NewTypeName;
|
|
|
|
|
|
2024-06-12 14:38:43 -04:00
|
|
|
|
Logger.Log("-----------------------------------------------", ConsoleColor.Green);
|
2024-06-11 23:07:59 -04:00
|
|
|
|
Logger.Log($"Renamed {oldName} to {type.Name} directly", ConsoleColor.Green);
|
2024-06-12 14:38:43 -04:00
|
|
|
|
|
|
|
|
|
RenameService.RenameAllDirect(remap, type);
|
|
|
|
|
|
|
|
|
|
Logger.Log("-----------------------------------------------", ConsoleColor.Green);
|
2024-06-11 23:07:59 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void LogDiscard(string action, string type, string search)
|
|
|
|
|
{
|
|
|
|
|
if (DataProvider.AppSettings.Debug)
|
|
|
|
|
{
|
|
|
|
|
Logger.Log($"[{action}] Discarding type [{type}] for search [{search}]", ConsoleColor.Red);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-11 19:18:48 -04:00
|
|
|
|
private void ChooseBestMatches()
|
|
|
|
|
{
|
2024-06-11 23:07:59 -04:00
|
|
|
|
foreach (var score in DataProvider.ScoringModels)
|
2024-06-11 19:18:48 -04:00
|
|
|
|
{
|
2024-06-11 23:07:59 -04:00
|
|
|
|
ChooseBestMatch(score.Value, true);
|
2024-06-11 19:18:48 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ChooseBestMatch(HashSet<ScoringModel> scores, bool isBest = false)
|
|
|
|
|
{
|
2024-06-11 23:07:59 -04:00
|
|
|
|
if (DataProvider.ScoringModels.Count == 0)
|
2024-06-11 19:18:48 -04:00
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var highestScore = scores.OrderByDescending(model => model.Score).FirstOrDefault();
|
2024-06-11 23:07:59 -04:00
|
|
|
|
var nextHighestScores = scores.OrderByDescending(model => model.Score).Skip(1);
|
2024-06-11 19:18:48 -04:00
|
|
|
|
|
2024-06-11 23:07:59 -04:00
|
|
|
|
if (highestScore is null) { return; }
|
2024-06-11 19:18:48 -04:00
|
|
|
|
|
|
|
|
|
var potentialText = isBest
|
|
|
|
|
? "Best potential"
|
|
|
|
|
: "Next potential";
|
|
|
|
|
|
2024-06-11 23:07:59 -04:00
|
|
|
|
Logger.Log("-----------------------------------------------", ConsoleColor.Green);
|
2024-06-12 00:05:59 -04:00
|
|
|
|
Logger.Log($"Renaming {highestScore.Definition.Name} to {highestScore.ProposedNewName}", ConsoleColor.Green);
|
|
|
|
|
|
2024-06-12 14:38:43 -04:00
|
|
|
|
// Rename type and all associated type members
|
|
|
|
|
RenameService.RenameAll(highestScore);
|
2024-06-11 19:18:48 -04:00
|
|
|
|
|
2024-06-11 23:07:59 -04:00
|
|
|
|
if (DataProvider.AppSettings.ScoringMode)
|
2024-06-11 19:18:48 -04:00
|
|
|
|
{
|
2024-06-11 23:07:59 -04:00
|
|
|
|
scores.Remove(highestScore);
|
|
|
|
|
ChooseBestMatch(scores);
|
2024-06-11 19:18:48 -04:00
|
|
|
|
|
2024-06-11 23:07:59 -04:00
|
|
|
|
Logger.Log("-----------------------------------------------", ConsoleColor.Green);
|
2024-06-11 19:18:48 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-11 23:07:59 -04:00
|
|
|
|
Logger.Log("-----------------------------------------------", ConsoleColor.Green);
|
|
|
|
|
|
2024-06-11 19:18:48 -04:00
|
|
|
|
scores.Remove(highestScore);
|
|
|
|
|
ChooseBestMatch(scores);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void WriteAssembly()
|
|
|
|
|
{
|
|
|
|
|
var filename = Path.GetFileNameWithoutExtension(DataProvider.AppSettings.AssemblyPath);
|
|
|
|
|
var strippedPath = Path.GetDirectoryName(filename);
|
|
|
|
|
|
|
|
|
|
filename = $"{filename}-Remapped.dll";
|
|
|
|
|
|
|
|
|
|
var remappedPath = Path.Combine(strippedPath, filename);
|
|
|
|
|
|
|
|
|
|
DataProvider.AssemblyDefinition.Write(remappedPath);
|
|
|
|
|
|
2024-06-11 23:07:59 -04:00
|
|
|
|
Logger.Log("-----------------------------------------------", ConsoleColor.Green);
|
|
|
|
|
Logger.Log($"Complete: Assembly written to `{remappedPath}`", ConsoleColor.Green);
|
|
|
|
|
Logger.Log("-----------------------------------------------", ConsoleColor.Green);
|
2024-06-11 19:18:48 -04:00
|
|
|
|
}
|
|
|
|
|
}
|