using System; using System.Collections; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using REPOLib.Modules; using UnityEngine; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyVersion("0.0.0.0")] namespace MoreUpgradesFix; [BepInPlugin("moreupgrades.fix.runtime", "MoreUpgrades Fix", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { internal static ManualLogSource Log; internal static ConfigEntry DebugLogging; internal static ConfigEntry RebuildTrackerSafely; private void Awake() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; DebugLogging = ((BaseUnityPlugin)this).Config.Bind("General", "DebugLogging", false, "Enable extra logs for MoreUpgrades Fix."); RebuildTrackerSafely = ((BaseUnityPlugin)this).Config.Bind("General", "RebuildTrackerSafely", true, "Use the heavier fallback tracker rebuild instead of the low-overhead guarded original tracker logic."); MoreUpgradesTrackerPatch.Apply(new Harmony("moreupgrades.fix.runtime")); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Patched MoreUpgrades tracker guards."); } } internal static class ModLog { private static bool loggedMissingTarget; public static void Debug(string message) { if (Plugin.DebugLogging != null && Plugin.DebugLogging.Value && Plugin.Log != null) { Plugin.Log.LogInfo((object)("[Debug] " + message)); } } public static void Warning(string message) { if (Plugin.Log != null) { Plugin.Log.LogWarning((object)message); } } public static void MissingTarget(string name) { if (!loggedMissingTarget) { Warning("MoreUpgrades patch target was not found: " + name); loggedMissingTarget = true; } } public static void SuppressedTracker(Exception ex) { Debug("Suppressed a MoreUpgrades tracker exception: " + ex.GetType().Name + ": " + ex.Message); } } internal static class MoreUpgradesTrackerPatch { private static readonly Type ClosureType = AccessTools.TypeByName("MoreUpgrades.Plugin+<>c__DisplayClass17_0"); private static readonly Type UpgradeItemType = AccessTools.TypeByName("MoreUpgrades.Classes.UpgradeItem"); private static readonly Type UpgradeBaseType = AccessTools.TypeByName("MoreUpgrades.Classes.UpgradeItem+Base"); private static readonly Type MapInfoType = AccessTools.TypeByName("MoreUpgrades.Classes.MapInfo"); private static readonly Type MapPatchType = AccessTools.TypeByName("MoreUpgrades.Patches.MapPatch"); private static readonly FieldInfo ClosurePluginField = AccessTools.Field(ClosureType, "<>4__this"); private static readonly FieldInfo ClosureMapTrackerField = AccessTools.Field(ClosureType, "mapTracker"); private static readonly FieldInfo ClosureMapZoomField = AccessTools.Field(ClosureType, "mapZoom"); private static readonly FieldInfo ClosureMapCosmeticsTrackerField = AccessTools.Field(ClosureType, "mapCosmeticsTracker"); private static readonly FieldInfo PluginUpdateTrackerField = AccessTools.Field(AccessTools.TypeByName("MoreUpgrades.Plugin"), "updateTracker"); private static readonly FieldInfo UpgradePlayerUpgradeField = AccessTools.Field(UpgradeItemType, "playerUpgrade"); private static readonly FieldInfo UpgradeBaseField = AccessTools.Field(UpgradeItemType, "upgradeBase"); private static readonly FieldInfo UpgradeBaseNameField = AccessTools.Field(UpgradeBaseType, "name"); private static readonly FieldInfo MapInfoEntityField = AccessTools.Field(MapInfoType, "mapCustomEntity"); private static readonly FieldInfo MapInfoVisibleField = AccessTools.Field(MapInfoType, "visible"); private static readonly FieldInfo AvatarDeathHeadField = AccessTools.Field(typeof(PlayerAvatar), "playerDeathHead"); private static readonly FieldInfo AvatarVisualColorField = FindInstanceField(typeof(PlayerAvatarVisuals), "color"); private static readonly FieldInfo MapPatchCameraField = AccessTools.Field(MapPatchType, "mapCamera"); private static readonly FieldInfo MapPatchDefaultZoomField = AccessTools.Field(MapPatchType, "defaultMapZoom"); private static readonly MethodInfo PlayerUpgradeGetLevelMethod = AccessTools.Method(typeof(PlayerUpgrade), "GetLevel", new Type[1] { typeof(PlayerAvatar) }, (Type[])null); private static readonly MethodInfo UpgradeGetVariableMethod = AccessTools.Method(UpgradeItemType, "GetVariable", (Type[])null, (Type[])null); private static readonly MethodInfo UpgradeGetConfigMethod = AccessTools.Method(UpgradeItemType, "GetConfig", (Type[])null, (Type[])null); private static readonly MethodInfo UpgradeGetMapInfosMethod = MakeGenericMethod(UpgradeGetVariableMethod, (MapInfoType == null) ? null : typeof(List<>).MakeGenericType(MapInfoType)); private static readonly Dictionary SpriteRendererFields = new Dictionary(); private static readonly Dictionary ParentFields = new Dictionary(); public static void Apply(Harmony harmony) { PatchGeneratedMethod(harmony, "g__UpdateTracker|1", "TrackerPrefix"); PatchGeneratedMethod(harmony, "g__UpdateMapZoom|2", "MapZoomPrefix"); PatchGeneratedMethod(harmony, "b__14", "CosmeticTrackerPrefix"); } private static FieldInfo FindInstanceField(Type type, string fieldName) { return (type == null) ? null : type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } private static MethodInfo MakeGenericMethod(MethodInfo method, Type type) { return (method == null || type == null) ? null : method.MakeGenericMethod(type); } private static void PatchGeneratedMethod(Harmony harmony, string targetName, string prefixName) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_0074: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(ClosureType, targetName, (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(MoreUpgradesTrackerPatch), prefixName, (Type[])null, (Type[])null); MethodInfo methodInfo3 = AccessTools.Method(typeof(MoreUpgradesTrackerPatch), "Finalizer", (Type[])null, (Type[])null); if (methodInfo == null || methodInfo2 == null) { ModLog.MissingTarget(targetName); } else { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo3), (HarmonyMethod)null); } } private static bool TrackerPrefix(object __instance, object upgradeItem) { if (Plugin.RebuildTrackerSafely != null && Plugin.RebuildTrackerSafely.Value) { try { UpdateTrackerSafely(__instance, upgradeItem); } catch (Exception ex) { SetUpdateTracker(__instance, value: false); ModLog.SuppressedTracker(ex); } return false; } try { if (!CanOriginalTrackerRun(__instance, upgradeItem)) { SetUpdateTracker(__instance, value: false); return false; } } catch (Exception ex) { SetUpdateTracker(__instance, value: false); ModLog.SuppressedTracker(ex); return false; } return true; } private static bool MapZoomPrefix(object __instance, PlayerAvatar playerAvatar, int level) { try { if ((Object)(object)PlayerController.instance == (Object)null || (Object)(object)PlayerController.instance.playerAvatarScript == (Object)null) { return false; } if ((Object)(object)PlayerController.instance.playerAvatarScript != (Object)(object)playerAvatar) { return false; } Camera val = (Camera)((MapPatchCameraField == null) ? null : /*isinst with value type is only supported in some contexts*/); if ((Object)(object)val == (Object)null) { return false; } object obj = ((ClosureMapZoomField == null) ? null : ClosureMapZoomField.GetValue(__instance)); if (obj == null) { return false; } float config = GetConfig(obj, "Scaling Factor"); float num = 0f; if (MapPatchDefaultZoomField != null) { object value = MapPatchDefaultZoomField.GetValue(null); if (value is float) { num = (float)value; } } val.orthographicSize = num + (float)level * config; } catch (Exception ex) { ModLog.SuppressedTracker(ex); } return false; } private static bool CosmeticTrackerPrefix(object __instance) { try { PlayerController instance = PlayerController.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.playerAvatarScript == (Object)null) { SetUpdateTracker(__instance, value: false); return false; } if ((Object)(object)MapToolController.instance == (Object)null) { SetUpdateTracker(__instance, value: false); return false; } object obj = ((ClosureMapCosmeticsTrackerField == null) ? null : ClosureMapCosmeticsTrackerField.GetValue(__instance)); if (obj == null) { SetUpdateTracker(__instance, value: false); return false; } } catch (Exception ex) { SetUpdateTracker(__instance, value: false); ModLog.SuppressedTracker(ex); return false; } return true; } private static Exception Finalizer(object __instance, Exception __exception) { if (__exception == null) { return null; } if (__exception is NullReferenceException) { SetUpdateTracker(__instance, value: false); ModLog.SuppressedTracker(__exception); return null; } return __exception; } private static void UpdateTrackerSafely(object closure, object upgradeItem) { if (upgradeItem == null) { SetUpdateTracker(closure, value: false); return; } object obj = ((UpgradePlayerUpgradeField == null) ? null : UpgradePlayerUpgradeField.GetValue(upgradeItem)); if (obj == null) { SetUpdateTracker(closure, value: false); return; } PlayerController instance = PlayerController.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.playerAvatarScript == (Object)null) { SetUpdateTracker(closure, value: false); return; } PlayerAvatar playerAvatarScript = instance.playerAvatarScript; int playerUpgradeLevel = GetPlayerUpgradeLevel(obj, playerAvatarScript); bool flag = playerUpgradeLevel > 0; IEnumerable mapInfos = GetMapInfos(upgradeItem); if (mapInfos == null) { SetUpdateTracker(closure, value: false); return; } PlayerDeathHead deathHead = (PlayerDeathHead)((AvatarDeathHeadField == null) ? null : /*isinst with value type is only supported in some contexts*/); foreach (object item in mapInfos) { if (item == null) { continue; } object obj2 = ((MapInfoEntityField == null) ? null : MapInfoEntityField.GetValue(item)); SpriteRenderer entitySpriteRenderer = GetEntitySpriteRenderer(obj2); if (obj2 != null && !((Object)(object)entitySpriteRenderer == (Object)null)) { if (flag) { UpdateEntityPosition(obj2); UpdateEntitySprite(closure, upgradeItem, entitySpriteRenderer, deathHead); UpdateEntityColor(upgradeItem, entitySpriteRenderer, GetEntityParent(obj2), playerAvatarScript); } ((Renderer)entitySpriteRenderer).enabled = flag && GetMapInfoVisible(item); } } SetUpdateTracker(closure, value: false); } private static bool CanOriginalTrackerRun(object closure, object upgradeItem) { if (upgradeItem == null || UpgradePlayerUpgradeField == null) { return false; } if (UpgradePlayerUpgradeField.GetValue(upgradeItem) == null) { return false; } PlayerController instance = PlayerController.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.playerAvatarScript == (Object)null) { return false; } return GetMapInfos(upgradeItem) != null; } private static int GetPlayerUpgradeLevel(object playerUpgrade, PlayerAvatar avatar) { if (playerUpgrade == null || (Object)(object)avatar == (Object)null || PlayerUpgradeGetLevelMethod == null) { return 0; } object obj = PlayerUpgradeGetLevelMethod.Invoke(playerUpgrade, new object[1] { avatar }); return (obj is int) ? ((int)obj) : 0; } private static IEnumerable GetMapInfos(object upgradeItem) { if (upgradeItem == null || UpgradeItemType == null || MapInfoType == null) { return null; } if (UpgradeGetMapInfosMethod == null) { return null; } return UpgradeGetMapInfosMethod.Invoke(upgradeItem, new object[1] { "Map Infos" }) as IEnumerable; } private static T GetConfig(object upgradeItem, string key) { if (upgradeItem == null || UpgradeItemType == null) { return default(T); } if (UpgradeGetConfigMethod == null) { return default(T); } MethodInfo methodInfo = UpgradeGetConfigMethod.MakeGenericMethod(typeof(T)); object obj = methodInfo.Invoke(upgradeItem, new object[1] { key }); return (obj is T) ? ((T)obj) : default(T); } private static bool GetMapInfoVisible(object mapInfo) { if (mapInfo == null || MapInfoVisibleField == null) { return false; } object value = MapInfoVisibleField.GetValue(mapInfo); return value is bool && (bool)value; } private static SpriteRenderer GetEntitySpriteRenderer(object entity) { if (entity == null) { return null; } FieldInfo cachedField = GetCachedField(SpriteRendererFields, entity.GetType(), "spriteRenderer"); return (SpriteRenderer)((cachedField == null) ? null : /*isinst with value type is only supported in some contexts*/); } private static Transform GetEntityParent(object entity) { if (entity == null) { return null; } FieldInfo cachedField = GetCachedField(ParentFields, entity.GetType(), "Parent"); return (Transform)((cachedField == null) ? null : /*isinst with value type is only supported in some contexts*/); } private static FieldInfo GetCachedField(Dictionary cache, Type type, string fieldName) { if (type == null) { return null; } if (!cache.TryGetValue(type, out var value)) { value = (cache[type] = FindInstanceField(type, fieldName)); } return value; } private static Transform GetEntityTransform(object entity) { Component val = (Component)((entity is Component) ? entity : null); return ((Object)(object)val == (Object)null) ? null : val.transform; } private static void UpdateEntityPosition(object entity) { Transform entityTransform = GetEntityTransform(entity); Transform entityParent = GetEntityParent(entity); if (!((Object)(object)entityTransform == (Object)null) && !((Object)(object)entityParent == (Object)null) && !((Object)(object)Map.Instance == (Object)null) && Map.Instance.Active) { Map.Instance.CustomPositionSet(entityTransform, entityParent); } } private static void UpdateEntitySprite(object closure, object upgradeItem, SpriteRenderer renderer, PlayerDeathHead deathHead) { if ((Object)(object)renderer == (Object)null || upgradeItem == null) { return; } if (GetConfig(upgradeItem, "Arrow Icon")) { Sprite val = (Sprite)((ClosureMapTrackerField == null) ? null : /*isinst with value type is only supported in some contexts*/); if ((Object)(object)val != (Object)null) { renderer.sprite = val; } } else if ((Object)(object)deathHead != (Object)null && (Object)(object)deathHead.mapCustom != (Object)null && (Object)(object)deathHead.mapCustom.sprite != (Object)null) { renderer.sprite = deathHead.mapCustom.sprite; } } private static void UpdateEntityColor(object upgradeItem, SpriteRenderer renderer, Transform parent, PlayerAvatar avatar) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) if (upgradeItem == null || (Object)(object)renderer == (Object)null) { return; } Color color = GetConfig(upgradeItem, "Color"); if (GetUpgradeName(upgradeItem) == "Map Player Tracker" && GetConfig(upgradeItem, "Player Color") && (Object)(object)avatar != (Object)null && (Object)(object)avatar.playerAvatarVisuals != (Object)null && AvatarVisualColorField != null) { object value = AvatarVisualColorField.GetValue(avatar.playerAvatarVisuals); if (value is Color) { color = (Color)value; } } if ((Object)(object)Map.Instance != (Object)null && (Object)(object)parent != (Object)null) { MapLayer layerParent = Map.Instance.GetLayerParent(parent.position.y + 1f); color.a = (((Object)(object)layerParent != (Object)null && layerParent.layer == Map.Instance.PlayerLayer) ? 1f : 0.3f); } renderer.color = color; } private static string GetUpgradeName(object upgradeItem) { if (upgradeItem == null || UpgradeBaseField == null || UpgradeBaseNameField == null) { return string.Empty; } object value = UpgradeBaseField.GetValue(upgradeItem); object obj = ((value == null) ? null : UpgradeBaseNameField.GetValue(value)); return (obj as string) ?? string.Empty; } private static void SetUpdateTracker(object closure, bool value) { if (closure != null && !(ClosurePluginField == null) && !(PluginUpdateTrackerField == null)) { object value2 = ClosurePluginField.GetValue(closure); if (value2 != null) { PluginUpdateTrackerField.SetValue(value2, value); } } } }