0
0
mirror of https://github.com/sp-tarkov/assembly-tool.git synced 2025-02-13 03:10:45 -05:00

Merge pull request 'Feature: Auto map types based on items.json and BSG's TypeTable' (#15) from Feat-Auto-map-items into master

Reviewed-on: SPT/AssemblyTool#15
This commit is contained in:
Cj 2024-11-06 19:18:28 +00:00
commit 06ada00039
5 changed files with 524658 additions and 535 deletions

524563
Assets/Templates/items.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -184,25 +184,6 @@
"ExcludeNestedTypes": [] "ExcludeNestedTypes": []
} }
}, },
{
"NewTypeName": "RecodableItemClass",
"OriginalTypeName": "GClass2981",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IsInterface": false,
"IncludeMethods": [
"OnAddRecodableItem"
],
"ExcludeMethods": [],
"IncludeFields": [],
"ExcludeFields": [],
"IncludeProperties": [],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{ {
"NewTypeName": "RadioTransmitterHandlerClass", "NewTypeName": "RadioTransmitterHandlerClass",
"OriginalTypeName": "GClass1592", "OriginalTypeName": "GClass1592",
@ -1208,153 +1189,6 @@
"ExcludeNestedTypes": [] "ExcludeNestedTypes": []
} }
}, },
{
"NewTypeName": "SecureContainerTemplateClass",
"OriginalTypeName": "GClass2827",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IncludeMethods": [],
"ExcludeMethods": [],
"IncludeFields": [
"containType"
],
"ExcludeFields": [],
"IncludeProperties": [],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{
"NewTypeName": "Meds2Class",
"OriginalTypeName": "GClass2855",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IncludeMethods": [],
"ExcludeMethods": [],
"IncludeFields": [
"BodyPartTimeMults"
],
"ExcludeFields": [],
"IncludeProperties": [],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{
"NewTypeName": "RepairKitClass",
"OriginalTypeName": "GClass2860",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IncludeMethods": [],
"ExcludeMethods": [],
"IncludeFields": [
"TargetItemFilter"
],
"ExcludeFields": [],
"IncludeProperties": [],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{
"NewTypeName": "MoneyClass",
"OriginalTypeName": "GClass2870",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IncludeMethods": [],
"ExcludeMethods": [],
"IncludeFields": [
"eqMax"
],
"ExcludeFields": [],
"IncludeProperties": [],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{
"NewTypeName": "ThrowableWeaponClass",
"OriginalTypeName": "GClass2872",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IncludeMethods": [],
"ExcludeMethods": [],
"IncludeFields": [
"MinFragmentDamage"
],
"ExcludeFields": [],
"IncludeProperties": [],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{
"NewTypeName": "ArmorClass",
"OriginalTypeName": "GClass2877",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"ConstructorParameterCount": 2,
"MethodCount": 1,
"IncludeMethods": [],
"ExcludeMethods": [],
"IncludeFields": [
"FaceShield"
],
"ExcludeFields": [],
"IncludeProperties": [],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{
"NewTypeName": "GogglesClass",
"OriginalTypeName": "GClass2883",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IsInterface": false,
"IncludeMethods": [],
"ExcludeMethods": [],
"IncludeFields": [],
"ExcludeFields": [],
"IncludeProperties": [
"BlindnessProtection"
],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{
"NewTypeName": "SightModClass",
"OriginalTypeName": "GClass2902",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IncludeMethods": [],
"ExcludeMethods": [],
"IncludeFields": [
"Sight"
],
"ExcludeFields": [],
"IncludeProperties": [],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{ {
"NewTypeName": "BossKnightBrainClass", "NewTypeName": "BossKnightBrainClass",
"OriginalTypeName": "GClass292", "OriginalTypeName": "GClass292",
@ -1399,301 +1233,6 @@
"ExcludeNestedTypes": [] "ExcludeNestedTypes": []
} }
}, },
{
"NewTypeName": "MagazineClass",
"OriginalTypeName": "GClass2914",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IncludeMethods": [],
"ExcludeMethods": [],
"IncludeFields": [],
"ExcludeFields": [],
"IncludeProperties": [
"LoadUnloadModifier"
],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{
"NewTypeName": "CylinderMagazineClass",
"OriginalTypeName": "GClass2915",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IncludeMethods": [],
"ExcludeMethods": [],
"IncludeFields": [],
"ExcludeFields": [],
"IncludeProperties": [
"Camoras"
],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{
"NewTypeName": "SpringDrivenCylinderMagazineClass",
"OriginalTypeName": "GClass2916",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"FieldCount": 0,
"IncludeMethods": [
"CamoraIndexForDoubleActionFire"
],
"ExcludeMethods": [],
"IncludeFields": [],
"ExcludeFields": [],
"IncludeProperties": [],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{
"NewTypeName": "MountModClass",
"OriginalTypeName": "GClass2922",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IsDerived": true,
"ConstructorParameterCount": 2,
"FieldCount": 0,
"PropertyCount": 2,
"IncludeMethods": [],
"ExcludeMethods": [],
"IncludeFields": [],
"ExcludeFields": [],
"IncludeProperties": [
"HeatFactor",
"CoolFactor"
],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{
"NewTypeName": "StockItemClass",
"OriginalTypeName": "GClass2919",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IncludeMethods": [],
"ExcludeMethods": [],
"IncludeFields": [
"Foldable"
],
"ExcludeFields": [],
"IncludeProperties": [
"HeatFactor",
"CoolFactor",
"DurabilityBurnModificator"
],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{
"NewTypeName": "BarrelModClass",
"OriginalTypeName": "GClass2921",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IncludeMethods": [],
"ExcludeMethods": [],
"IncludeFields": [],
"ExcludeFields": [],
"IncludeProperties": [
"DurabilityBurnModificator",
"HeatFactor",
"CoolFactor",
"CenterOfImpactMOA"
],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{
"NewTypeName": "SearchableItemClass",
"OriginalTypeName": "GClass2925",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IncludeMethods": [],
"ExcludeMethods": [],
"IncludeFields": [],
"ExcludeFields": [],
"IncludeProperties": [
"SearchSound"
],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{
"NewTypeName": "ItemContainerClass",
"OriginalTypeName": "GClass2927",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IsInterface": false,
"IncludeMethods": [],
"ExcludeMethods": [],
"IncludeFields": [],
"ExcludeFields": [],
"IncludeProperties": [
"isSecured"
],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{
"NewTypeName": "SortingTableClass",
"OriginalTypeName": "GClass2947",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IncludeMethods": [
"ClampSize"
],
"ExcludeMethods": [],
"IncludeFields": [],
"ExcludeFields": [],
"IncludeProperties": [],
"ExcludeProperties": [
"CanStretchHorizontally"
],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{
"NewTypeName": "StashClass",
"OriginalTypeName": "GClass2946",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IncludeMethods": [
"UpdateBonuses"
],
"ExcludeMethods": [],
"IncludeFields": [],
"ExcludeFields": [],
"IncludeProperties": [],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{
"NewTypeName": "FoodClass",
"OriginalTypeName": "GClass2961",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IncludeMethods": [],
"ExcludeMethods": [],
"IncludeFields": [
"FoodDrinkComponent"
],
"ExcludeFields": [],
"IncludeProperties": [],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{
"NewTypeName": "KnifeClass",
"OriginalTypeName": "GClass2967",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IncludeMethods": [],
"ExcludeMethods": [],
"IncludeFields": [
"KnifeComponent"
],
"ExcludeFields": [],
"IncludeProperties": [],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{
"NewTypeName": "MedsClass",
"OriginalTypeName": "GClass2969",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"ConstructorParameterCount": 2,
"MethodCount": 1,
"FieldCount": 2,
"PropertyCount": 1,
"NestedTypeCount": 0,
"IncludeMethods": [],
"ExcludeMethods": [
"ToString"
],
"IncludeFields": [
"HealthEffectsComponent",
"MedKitComponent",
""
],
"ExcludeFields": [],
"IncludeProperties": [],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{
"NewTypeName": "BulletClass",
"OriginalTypeName": "GClass2983",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IncludeMethods": [],
"ExcludeMethods": [],
"IncludeFields": [],
"ExcludeFields": [],
"IncludeProperties": [
"GetBulletSpeed"
],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{
"NewTypeName": "GrenadeClass",
"OriginalTypeName": "GClass2986",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IncludeMethods": [],
"ExcludeMethods": [],
"IncludeFields": [],
"ExcludeFields": [],
"IncludeProperties": [
"MinTimeToContactExplode"
],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{ {
"NewTypeName": "TemplateIdToObjectMappingsClass", "NewTypeName": "TemplateIdToObjectMappingsClass",
"OriginalTypeName": "GClass2989", "OriginalTypeName": "GClass2989",
@ -2693,16 +2232,10 @@
"ExcludeMethods": [], "ExcludeMethods": [],
"IncludeFields": [ "IncludeFields": [
"OverDamageFrom", "OverDamageFrom",
"Player", "Player"
"BodyPartColliderType",
"HittedBallisticColliders"
], ],
"ExcludeFields": [], "ExcludeFields": [],
"IncludeProperties": [ "IncludeProperties": [],
"Penetrated",
"HaveOwner",
"Blunt"
],
"ExcludeProperties": [], "ExcludeProperties": [],
"IncludeNestedTypes": [], "IncludeNestedTypes": [],
"ExcludeNestedTypes": [] "ExcludeNestedTypes": []
@ -4797,25 +4330,6 @@
"ExcludeNestedTypes": [] "ExcludeNestedTypes": []
} }
}, },
{
"NewTypeName": "RepairKitItemClass",
"OriginalTypeName": "GClass2974",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IncludeMethods": [],
"ExcludeMethods": [],
"IncludeFields": [],
"ExcludeFields": [],
"IncludeProperties": [
"TargetItemFilter",
"RepairQuality"
],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{ {
"NewTypeName": "TimeRangeInfoStruct", "NewTypeName": "TimeRangeInfoStruct",
"OriginalTypeName": "GStruct98", "OriginalTypeName": "GStruct98",
@ -5016,25 +4530,6 @@
"ExcludeNestedTypes": [] "ExcludeNestedTypes": []
} }
}, },
{
"NewTypeName": "MarkOfUnknownItemClass",
"OriginalTypeName": "GClass2977",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IncludeMethods": [],
"ExcludeMethods": [],
"IncludeFields": [],
"ExcludeFields": [],
"IncludeProperties": [
"ScavKillExpPenalty",
"ScavKillStandingPenalty"
],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{ {
"NewTypeName": "IOnItemAdded", "NewTypeName": "IOnItemAdded",
"OriginalTypeName": "GInterface131", "OriginalTypeName": "GInterface131",
@ -6735,28 +6230,6 @@
"ExcludeNestedTypes": [] "ExcludeNestedTypes": []
} }
}, },
{
"NewTypeName": "CultistAmuletClass",
"OriginalTypeName": "GClass2960",
"UseForceRename": false,
"SearchParams": {
"IsPublic": true,
"IsInterface": false,
"IsNested": false,
"IncludeMethods": [
"TryExpendCharge"
],
"ExcludeMethods": [],
"IncludeFields": [
"CultistAmuletComponent"
],
"ExcludeFields": [],
"IncludeProperties": [],
"ExcludeProperties": [],
"IncludeNestedTypes": [],
"ExcludeNestedTypes": []
}
},
{ {
"NewTypeName": "BotAimingClass", "NewTypeName": "BotAimingClass",
"OriginalTypeName": "GClass551", "OriginalTypeName": "GClass551",
@ -7659,8 +7132,7 @@
"FieldCount": 1, "FieldCount": 1,
"IncludeMethods": [ "IncludeMethods": [
"Enter", "Enter",
"Exit", "Exit"
"ManualAnimatorMoveUpdate"
], ],
"ExcludeMethods": [ "ExcludeMethods": [
"ProcessAnimatorMovement", "ProcessAnimatorMovement",

View File

@ -0,0 +1,9 @@
namespace ReCodeIt.Models;
public class ItemTemplateModel
{
public string _id;
public string _name;
public string _parent;
public string _type;
}

View File

@ -6,6 +6,7 @@ using ReCodeIt.ReMapper.Search;
using ReCodeIt.Utils; using ReCodeIt.Utils;
using ReCodeItLib.Remapper.Search; using ReCodeItLib.Remapper.Search;
using System.Diagnostics; using System.Diagnostics;
using System.Reflection;
namespace ReCodeIt.ReMapper; namespace ReCodeIt.ReMapper;
@ -62,6 +63,8 @@ public class ReCodeItRemapper
return; return;
} }
GenerateDynamicRemaps(assemblyPath, types);
var tasks = new List<Task>(remapModels.Count); var tasks = new List<Task>(remapModels.Count);
foreach (var remap in remapModels) foreach (var remap in remapModels)
{ {
@ -95,7 +98,7 @@ public class ReCodeItRemapper
); );
} }
Task.WaitAll(renameTasks.ToArray()); Task.WaitAll(renameTasks.ToArray());
// Don't publicize and unseal until after the remapping, so we can use those as search parameters // Don't publicize and unseal until after the remapping, so we can use those as search parameters
if (Settings.MappingSettings.Publicize) if (Settings.MappingSettings.Publicize)
{ {
@ -103,7 +106,7 @@ public class ReCodeItRemapper
SPTPublicizer.PublicizeClasses(Module); SPTPublicizer.PublicizeClasses(Module);
} }
// We are done, write the assembly // We are done, write the assembly
WriteAssembly(); WriteAssembly();
} }
@ -427,6 +430,68 @@ public class ReCodeItRemapper
} }
} }
private void GenerateDynamicRemaps(string path, IEnumerable<TypeDef> types)
{
// HACK: Because this is written in net8 and the assembly is net472 we must resolve the type this way instead of
// filtering types directly using GetTypes() Otherwise, it causes serialization issues.
// This is also necessary because we can't access non-compile time constants with dnlib.
var templateMappingTypeDef = types.SingleOrDefault(t => t.FindField("TypeTable") != null);
if (templateMappingTypeDef is null)
{
Logger.Log("Could not find type for field TypeTable", ConsoleColor.Red);
return;
}
var assembly = Assembly.LoadFrom(path);
var templateMappingClass = assembly.Modules
.First()
.GetType(templateMappingTypeDef.Name);
if (templateMappingClass is null)
{
Logger.Log($"Could not resolve type for {templateMappingTypeDef.Name}", ConsoleColor.Red);
return;
}
var typeTable = (Dictionary<string, Type>)templateMappingClass
.GetField("TypeTable")
.GetValue(templateMappingClass);
BuildAssociationFromTable(typeTable, "ItemClass");
var templateTypeTable = (Dictionary<string, Type>)templateMappingClass
.GetField("TemplateTypeTable")
.GetValue(templateMappingClass);
BuildAssociationFromTable(templateTypeTable, "TemplateClass");
}
private void BuildAssociationFromTable(Dictionary<string, Type> table, string extName)
{
foreach (var type in table)
{
if (DataProvider.ItemTemplates!.TryGetValue(type.Key, out var template))
{
if (!type.Value.Name.StartsWith("GClass")) continue;
Logger.Log($"Key: {type.Key} Type: {type.Value.Name} Associated to {template._name}", ConsoleColor.Green);
var remap = new RemapModel
{
OriginalTypeName = type.Value.Name,
NewTypeName = $"{template._name}{extName}",
UseForceRename = true
};
_remaps.Add(remap);
continue;
}
Logger.Log($"Found no association for key: {type.Key} Type: {type.Value}", ConsoleColor.Yellow);
}
}
/// <summary> /// <summary>
/// Choose the best possible match from all remaps /// Choose the best possible match from all remaps
/// </summary> /// </summary>

View File

@ -7,6 +7,11 @@ namespace ReCodeIt.Utils;
public static class DataProvider public static class DataProvider
{ {
static DataProvider()
{
LoadItems();
}
/// <summary> /// <summary>
/// Is this running in the CLI? /// Is this running in the CLI?
/// </summary> /// </summary>
@ -15,7 +20,8 @@ public static class DataProvider
public static string DataPath => Path.Combine(AppContext.BaseDirectory, "Data"); public static string DataPath => Path.Combine(AppContext.BaseDirectory, "Data");
public static List<RemapModel> Remaps { get; set; } = []; public static List<RemapModel> Remaps { get; set; } = [];
public static Dictionary<string, ItemTemplateModel>? ItemTemplates { get; private set; }
public static Settings Settings { get; private set; } public static Settings Settings { get; private set; }
public static void LoadAppSettings() public static void LoadAppSettings()
@ -116,7 +122,7 @@ public static class DataProvider
public static ModuleDefMD LoadModule(string path) public static ModuleDefMD LoadModule(string path)
{ {
var mcOptions = new ModuleCreationOptions(ModuleDef.CreateModuleContext()); var mcOptions = new ModuleCreationOptions(ModuleDef.CreateModuleContext());
ModuleDefMD module = ModuleDefMD.Load(path, mcOptions); var module = ModuleDefMD.Load(path, mcOptions);
module.Context = mcOptions.Context; module.Context = mcOptions.Context;
@ -127,4 +133,12 @@ public static class DataProvider
return module; return module;
} }
private static void LoadItems()
{
var itemsPath = Path.Combine(DataPath, "items.json");
var jsonText = File.ReadAllText(itemsPath);
ItemTemplates = JsonConvert.DeserializeObject<Dictionary<string, ItemTemplateModel>>(jsonText);
}
} }