|
| 1 | +using HarmonyLib; |
| 2 | +using Il2CppInterop.Runtime; |
| 3 | +using Il2CppInterop.Runtime.Injection; |
| 4 | +using System; |
| 5 | +using System.Collections.Generic; |
| 6 | + |
| 7 | +namespace Tangerine.Game |
| 8 | +{ |
| 9 | + public static class TangerineCharacter |
| 10 | + { |
| 11 | + private static readonly Dictionary<int, Type> _characterDict = new(); |
| 12 | + |
| 13 | + internal static void InitializeHarmony(Harmony harmony) |
| 14 | + { |
| 15 | + harmony.PatchAll(typeof(TangerineCharacter)); |
| 16 | + } |
| 17 | + |
| 18 | + /// <summary> |
| 19 | + /// Adds a controller class by injecting it into the game's runtime |
| 20 | + /// </summary> |
| 21 | + /// <param name="characterId"><c>n_ID</c> of the character that will use this controller</param> |
| 22 | + /// <param name="controllerType"><see langword="typeof"/> the controller class</param> |
| 23 | + /// <param name="interfaces">Interfaces the class should implement (e.g. <see cref="ILogicUpdate"/>)</param> |
| 24 | + public static void AddController(int characterId, Type controllerType, Type[] interfaces) |
| 25 | + { |
| 26 | + // Throw an exception if a controller with the same ID is already registered |
| 27 | + _characterDict[characterId] = controllerType; |
| 28 | + |
| 29 | + if (!ClassInjector.IsTypeRegisteredInIl2Cpp(controllerType)) |
| 30 | + { |
| 31 | + Plugin.Log.LogWarning($"Registering character controller: {controllerType}"); |
| 32 | + |
| 33 | + var options = new RegisterTypeOptions() |
| 34 | + { |
| 35 | + Interfaces = new Il2CppInterfaceCollection(interfaces), |
| 36 | + }; |
| 37 | + |
| 38 | + ClassInjector.RegisterTypeInIl2Cpp(controllerType, options); |
| 39 | + } |
| 40 | + |
| 41 | + // Example of injecting an enum value. This is not needed as the game can cast the values itself |
| 42 | + // EnumInjector.InjectEnumValues<EControlCharacter>(new Dictionary<string, object>() { { "X_DMC", 139 } }); |
| 43 | + } |
| 44 | + |
| 45 | + [HarmonyPatch(typeof(CharacterControlFactory), nameof(CharacterControlFactory.GetCharacterControlType))] |
| 46 | + [HarmonyPrefix] |
| 47 | + private static bool CharacterControlTypePrefix(EControlCharacter character, int subID, ref Il2CppSystem.Type __result) |
| 48 | + { |
| 49 | + if (_characterDict.TryGetValue((int)character, out var type)) |
| 50 | + { |
| 51 | + __result = Il2CppType.From(type); |
| 52 | + Plugin.Log.LogWarning($"Loading character controller {__result}"); |
| 53 | + return false; |
| 54 | + } |
| 55 | + |
| 56 | + return true; |
| 57 | + } |
| 58 | + } |
| 59 | +} |
0 commit comments