Decompiled source of MoreUpgrades Fix v1.0.1

MoreUpgradesFix.dll

Decompiled a day ago
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<bool> DebugLogging;

	internal static ConfigEntry<bool> 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<bool>("General", "DebugLogging", false, "Enable extra logs for MoreUpgrades Fix.");
		RebuildTrackerSafely = ((BaseUnityPlugin)this).Config.Bind<bool>("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<Type, FieldInfo> SpriteRendererFields = new Dictionary<Type, FieldInfo>();

	private static readonly Dictionary<Type, FieldInfo> ParentFields = new Dictionary<Type, FieldInfo>();

	public static void Apply(Harmony harmony)
	{
		PatchGeneratedMethod(harmony, "<Awake>g__UpdateTracker|1", "TrackerPrefix");
		PatchGeneratedMethod(harmony, "<Awake>g__UpdateMapZoom|2", "MapZoomPrefix");
		PatchGeneratedMethod(harmony, "<Awake>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<float>(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<T>(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<Type, FieldInfo> 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<bool>(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<Color>(upgradeItem, "Color");
		if (GetUpgradeName(upgradeItem) == "Map Player Tracker" && GetConfig<bool>(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);
			}
		}
	}
}