Decompiled source of SuperUltrawideSupport v1.1.2

SuperUltrawideSupport.dll

Decompiled 4 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("SuperUltrawideSupport")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Riintouge")]
[assembly: AssemblyProduct("SuperUltrawideSupport")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("8ca56582-078a-4428-b55f-0e59e84925ff")]
[assembly: AssemblyFileVersion("1.1.2.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.1.2.0")]
namespace SuperUltrawideSupport;

internal class OriginalRectTransform
{
	public readonly float minX;

	public readonly float minY;

	public readonly float maxX;

	public readonly float maxY;

	public readonly WeakReference<RectTransform> original;

	public OriginalRectTransform(RectTransform rectTransform)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		minX = rectTransform.anchorMin.x;
		minY = rectTransform.anchorMin.y;
		maxX = rectTransform.anchorMax.x;
		maxY = rectTransform.anchorMax.y;
		original = new WeakReference<RectTransform>(rectTransform);
	}
}
internal class AspectLerper
{
	private Dictionary<string, OriginalRectTransform> originals = new Dictionary<string, OriginalRectTransform>();

	private int targetWidth;

	private int targetHeight;

	private float xBufferNormalized;

	private float yBufferNormalized;

	private bool enabled = true;

	public AspectLerper(int currentWidth, int currentHeight, float targetAspectWidth, float targetAspectHeight)
	{
		Update(currentWidth, currentHeight, targetAspectWidth, targetAspectHeight);
	}

	public void Update(int currentWidth, int currentHeight, float targetAspectWidth, float targetAspectHeight)
	{
		lock (originals)
		{
			float num = Math.Min(currentHeight, (float)currentWidth / targetAspectWidth * targetAspectHeight);
			float num2 = num / targetAspectHeight * targetAspectWidth;
			targetHeight = (int)Math.Floor(num);
			targetWidth = (int)Math.Floor(num2);
			xBufferNormalized = (float)(currentWidth - targetWidth) / 2f / (float)currentWidth;
			yBufferNormalized = (float)(currentHeight - targetHeight) / 2f / (float)currentHeight;
			Update();
		}
	}

	public void Update()
	{
		lock (originals)
		{
			HashSet<string> hashSet = new HashSet<string>();
			foreach (KeyValuePair<string, OriginalRectTransform> original in originals)
			{
				if (original.Value.original.TryGetTarget(out var target))
				{
					LerpCore(target, original.Value);
				}
				else
				{
					hashSet.Add(original.Key);
				}
			}
			foreach (string item in hashSet)
			{
				originals.Remove(item);
			}
		}
	}

	public void Update(bool enable)
	{
		lock (originals)
		{
			if (enabled != enable)
			{
				enabled = enable;
				Update();
			}
		}
	}

	public void Register(RectTransform rectTransform)
	{
		lock (originals)
		{
			if (!((Object)(object)rectTransform == (Object)null))
			{
				if (originals.ContainsKey(((Object)rectTransform).name))
				{
					Unregister(((Object)rectTransform).name);
					originals.Remove(((Object)rectTransform).name);
				}
				originals.Add(((Object)rectTransform).name, new OriginalRectTransform(rectTransform));
			}
		}
	}

	protected void Unregister(string name, RectTransform rectTransform, OriginalRectTransform original)
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		lock (originals)
		{
			if ((Object)(object)rectTransform != (Object)null && original != null)
			{
				rectTransform.anchorMin = new Vector2(original.minX, original.minY);
				rectTransform.anchorMax = new Vector2(original.maxX, original.maxY);
			}
			originals.Remove(name);
		}
	}

	public void Unregister(RectTransform rectTransform)
	{
		lock (originals)
		{
			if ((Object)(object)rectTransform != (Object)null && originals.TryGetValue(((Object)rectTransform).name, out var value))
			{
				Unregister(((Object)rectTransform).name, rectTransform, value);
			}
		}
	}

	public void Unregister(string name)
	{
		lock (originals)
		{
			if (name != null && originals.TryGetValue(name, out var value))
			{
				value.original.TryGetTarget(out var target);
				Unregister(name, target, value);
			}
		}
	}

	public void Lerp(RectTransform rectTransform)
	{
		lock (originals)
		{
			if ((Object)(object)rectTransform != (Object)null && originals.TryGetValue(((Object)rectTransform).name, out var value))
			{
				LerpCore(rectTransform, value);
			}
		}
	}

	protected void LerpCore(RectTransform rectTransform, OriginalRectTransform original)
	{
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		lock (originals)
		{
			try
			{
				if (enabled)
				{
					rectTransform.anchorMin = new Vector2(Mathf.Lerp(xBufferNormalized, 1f - xBufferNormalized, original.minX), Mathf.Lerp(yBufferNormalized, 1f - yBufferNormalized, original.minY));
					rectTransform.anchorMax = new Vector2(Mathf.Lerp(xBufferNormalized, 1f - xBufferNormalized, original.maxX), Mathf.Lerp(yBufferNormalized, 1f - yBufferNormalized, original.maxY));
				}
				else
				{
					rectTransform.anchorMin = new Vector2(original.minX, original.minY);
					rectTransform.anchorMax = new Vector2(original.maxX, original.maxY);
				}
			}
			catch (NullReferenceException)
			{
			}
		}
	}

	public void InverseLerp(RectTransform rectTransform)
	{
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		lock (originals)
		{
			if (enabled)
			{
				float num = xBufferNormalized / (1f - xBufferNormalized * 2f);
				float num2 = yBufferNormalized / (1f - yBufferNormalized * 2f);
				rectTransform.anchorMin = new Vector2(rectTransform.anchorMin.x - num, rectTransform.anchorMin.y - num2);
				rectTransform.anchorMax = new Vector2(rectTransform.anchorMax.x + num, rectTransform.anchorMax.y + num2);
			}
		}
	}
}
[BepInPlugin("com.riintouge.superultrawidesupport", "Super Ultrawide Support", "1.1.2")]
[BepInProcess("valheim.exe")]
public class SuperUltrawideSupport : BaseUnityPlugin
{
	[HarmonyPatch(typeof(Barber))]
	private class BarberPatch
	{
		[HarmonyPatch("Interact")]
		[HarmonyPostfix]
		private static void InteractPostfix(ref Barber __instance)
		{
			GameObject gameObject = PlayerCustomizaton.m_barberInstance.m_rootPanel.gameObject;
			if (gameObject.activeInHierarchy)
			{
				Transform obj = Common.FindParentOrSelf(gameObject.transform, "BarberGui");
				RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
				if ((Object)(object)val != (Object)null)
				{
					Lerper.Register(val);
					Lerper.Lerp(val);
				}
			}
		}
	}

	[HarmonyPatch(typeof(FejdStartup))]
	private class FejdStartupPatch
	{
		private static HashSet<string> TransformNames = new HashSet<string>();

		private static void Reset()
		{
			foreach (string transformName in TransformNames)
			{
				Lerper.Unregister(transformName);
			}
			TransformNames.Clear();
		}

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AwakePostfix(ref FejdStartup __instance)
		{
			Reset();
			Transform val = Common.FindParentOrSelf((Transform)(object)__instance.m_creditsList, "StartGui");
			if (!((Object)(object)val != (Object)null))
			{
				return;
			}
			for (int i = 0; i < val.childCount; i++)
			{
				Transform child = val.GetChild(i);
				RectTransform val2 = (RectTransform)(object)((child is RectTransform) ? child : null);
				if ((Object)(object)val2 != (Object)null && ((Object)val2).name != "BLACK" && ((Object)val2).name != "Loading" && ((Object)val2).name != "PleaseWait" && ((Object)val2).name != "Scaled 3D Viewport")
				{
					TransformNames.Add(((Object)val2).name);
					Lerper.Register(val2);
					Lerper.Lerp(val2);
				}
			}
		}

		[HarmonyPatch("OnDestroy")]
		[HarmonyPrefix]
		private static void OnDestroyPrefix()
		{
			Reset();
		}
	}

	[HarmonyPatch(typeof(Hud))]
	private class HudPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AwakePostfix(ref Hud __instance)
		{
			Transform obj = ((Component)__instance).transform.Find("hudroot");
			RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
			if ((Object)(object)val != (Object)null)
			{
				Lerper.Register(val);
				Lerper.Lerp(val);
			}
		}

		[HarmonyPatch("OnDestroy")]
		[HarmonyPrefix]
		private static void OnDestroyPrefix()
		{
			Lerper.Unregister("hudroot");
		}
	}

	[HarmonyPatch(typeof(InventoryGui))]
	private class InventoryGuiPatch
	{
		private static HashSet<string> TransformNames = new HashSet<string>();

		private static void Reset()
		{
			foreach (string transformName in TransformNames)
			{
				Lerper.Unregister(transformName);
			}
			TransformNames.Clear();
		}

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AwakePostfix(ref InventoryGui __instance)
		{
			Reset();
			for (int i = 0; i < __instance.m_inventoryRoot.childCount; i++)
			{
				Transform child = __instance.m_inventoryRoot.GetChild(i);
				RectTransform val = (RectTransform)(object)((child is RectTransform) ? child : null);
				if ((Object)(object)val != (Object)null && ((Object)val).name != "dropButton")
				{
					TransformNames.Add(((Object)val).name);
					Lerper.Register(val);
					Lerper.Lerp(val);
				}
			}
		}

		[HarmonyPatch("OnDestroy")]
		[HarmonyPrefix]
		private static void OnDestroyPrefix(ref InventoryGui __instance)
		{
			Reset();
		}
	}

	[HarmonyPatch(typeof(MessageHud))]
	private class MessageHudPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AwakePostfix(ref MessageHud __instance)
		{
			Transform obj = Common.FindParentOrSelf(((Component)__instance).transform, "HudMessage");
			RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
			if ((Object)(object)val != (Object)null)
			{
				Lerper.Register(val);
				Lerper.Lerp(val);
			}
			Transform obj2 = Common.FindParentOrSelf(((Component)__instance.m_messageText).gameObject.transform, "TopLeftMessage");
			RectTransform val2 = (RectTransform)(object)((obj2 is RectTransform) ? obj2 : null);
			if ((Object)(object)val2 != (Object)null)
			{
				Lerper.Register(val2);
				Lerper.Lerp(val2);
			}
		}

		[HarmonyPatch("OnDestroy")]
		[HarmonyPrefix]
		private static void OnDestroyPrefix()
		{
			Lerper.Unregister("HudMessage");
			Lerper.Unregister("TopLeftMessage");
		}
	}

	[HarmonyPatch(typeof(Minimap))]
	private class MinimapPatch
	{
		private static RectTransform largeTransform;

		private static float minX;

		private static float minY;

		private static float maxX;

		private static float maxY;

		private static bool AppliedInverseLerp;

		public static void Update(bool userUpdate)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)largeTransform == (Object)null) && (int)Minimap.instance.m_mode == 2)
			{
				if (userUpdate)
				{
					Minimap.instance.SetMapMode((MapMode)1);
					Minimap.instance.SetMapMode((MapMode)2);
				}
				largeTransform.anchorMin = new Vector2(minX, minY);
				largeTransform.anchorMax = new Vector2(maxX, maxY);
				AppliedInverseLerp = false;
				if (IsEnabled.Value && FullSizeMap.Value && !AppliedInverseLerp)
				{
					Lerper.InverseLerp(largeTransform);
					AppliedInverseLerp = true;
				}
			}
		}

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AwakePostfix(ref Minimap __instance)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = __instance.m_largeRoot.transform;
			largeTransform = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			minX = largeTransform.anchorMin.x;
			minY = largeTransform.anchorMin.y;
			maxX = largeTransform.anchorMax.x;
			maxY = largeTransform.anchorMax.y;
			AppliedInverseLerp = false;
		}

		[HarmonyPatch("OnDestroy")]
		[HarmonyPrefix]
		private static void OnDestroyPrefix()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)largeTransform != (Object)null)
			{
				largeTransform.anchorMin = new Vector2(minX, minY);
				largeTransform.anchorMax = new Vector2(maxX, maxY);
			}
			largeTransform = null;
			minX = 0f;
			minY = 0f;
			maxX = 0f;
			maxY = 0f;
			AppliedInverseLerp = false;
		}

		[HarmonyPatch("SetMapMode")]
		[HarmonyPrefix]
		private static void SetMapModePrefix(ref Minimap __instance, ref MapMode mode, out MapMode __state)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Expected I4, but got Unknown
			__state = (MapMode)(int)__instance.m_mode;
		}

		[HarmonyPatch("SetMapMode")]
		[HarmonyPostfix]
		private static void SetMapModePostfix(ref Minimap __instance, ref MapMode mode, ref MapMode __state)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			if ((int)__instance.m_mode != (int)__state)
			{
				Update(userUpdate: false);
			}
		}
	}

	[HarmonyPatch(typeof(StoreGui))]
	private class StoreGuiPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AwakePostfix(ref StoreGui __instance)
		{
			Transform obj = Common.FindParentOrSelf(((Component)__instance).transform, "Store_Screen");
			RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
			if ((Object)(object)val != (Object)null)
			{
				Lerper.Register(val);
				Lerper.Lerp(val);
			}
		}

		[HarmonyPatch("OnDestroy")]
		[HarmonyPrefix]
		private static void OnDestroyPrefix()
		{
			Lerper.Unregister("Store_Screen");
		}
	}

	[HarmonyPatch(typeof(Terminal))]
	private class TerminalPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AwakePostfix(ref Terminal __instance)
		{
			RectTransform chatWindow = __instance.m_chatWindow;
			if ((Object)(object)chatWindow != (Object)null)
			{
				Lerper.Register(chatWindow);
				Lerper.Lerp(chatWindow);
			}
		}
	}

	public static SuperUltrawideSupport Instance = null;

	public static ConfigEntry<bool> IsEnabled;

	public static ConfigEntry<bool> LoadOnStart;

	public static ConfigEntry<string> AspectRatio;

	internal static AspectLerper Lerper = null;

	private string LastAspectRatio = "16:9";

	private static int LastAspectWidth = 16;

	private static int LastAspectHeight = 9;

	private static Coroutine ScreenSizeDetectorCoroutine = null;

	private static int LastScreenWidth = -1;

	private static int LastScreenHeight = -1;

	public static ConfigEntry<bool> FullSizeMap;

	private readonly Harmony Harmony = new Harmony("com.riintouge.superultrawidesupport");

	private void Awake()
	{
		IsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Core", "Enable", true, "Whether this plugin has any effect when loaded.");
		LoadOnStart = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Core", "LoadOnStart", true, "Whether this plugin loads on game start.");
		AspectRatio = ((BaseUnityPlugin)this).Config.Bind<string>("1 - General", "AspectRatio", LastAspectRatio, "The desired aspect ratio in whole numbers, like \"" + LastAspectRatio + "\".");
		FullSizeMap = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "FullSizeMap", true, "Whether the map appears at full size regardless of the specified aspect ratio.");
		if (LoadOnStart.Value)
		{
			Instance = this;
			Harmony.PatchAll();
			UpdateAspectRatio(AspectRatio.Value);
			((BaseUnityPlugin)this).Config.SettingChanged += Config_SettingChanged;
			ScreenSizeDetectorCoroutine = ((MonoBehaviour)Instance).StartCoroutine(CoCheckForScreenResize());
		}
	}

	private void OnDestroy()
	{
		if (ScreenSizeDetectorCoroutine != null)
		{
			((MonoBehaviour)Instance).StopCoroutine(ScreenSizeDetectorCoroutine);
		}
		Harmony.UnpatchSelf();
	}

	private IEnumerator CoCheckForScreenResize()
	{
		while (true)
		{
			yield return (object)new WaitForSecondsRealtime(3f);
			if (LastScreenWidth == -1 || LastScreenHeight == -1)
			{
				LastScreenWidth = Screen.width;
				LastScreenHeight = Screen.height;
			}
			else if (LastScreenWidth != Screen.width || LastScreenHeight != Screen.height)
			{
				LastScreenWidth = Screen.width;
				LastScreenHeight = Screen.height;
				Lerper.Update(LastScreenWidth, LastScreenHeight, LastAspectWidth, LastAspectHeight);
				MinimapPatch.Update(userUpdate: true);
			}
		}
	}

	private void Config_SettingChanged(object sender, SettingChangedEventArgs e)
	{
		if (e.ChangedSetting == IsEnabled)
		{
			Lerper.Update(IsEnabled.Value);
			MinimapPatch.Update(userUpdate: true);
		}
		else if (e.ChangedSetting == AspectRatio)
		{
			UpdateAspectRatio(AspectRatio.Value);
		}
		else if (e.ChangedSetting == FullSizeMap)
		{
			MinimapPatch.Update(userUpdate: true);
		}
	}

	private void UpdateAspectRatio(string value)
	{
		try
		{
			int num = 0;
			int num2 = 0;
			if (value == string.Empty)
			{
				num = Screen.width;
				num2 = Screen.height;
			}
			else
			{
				string[] array = value.Split(new char[1] { ':' });
				num = int.Parse(array[0]);
				num2 = int.Parse(array[1]);
			}
			if (num > 0 && num2 > 0)
			{
				LastAspectRatio = $"{num}:{num2}";
				LastAspectWidth = num;
				LastAspectHeight = num2;
				if (Lerper == null)
				{
					Lerper = new AspectLerper(Screen.width, Screen.height, LastAspectWidth, LastAspectHeight);
					Lerper.Update(IsEnabled.Value);
				}
				else
				{
					Lerper.Update(Screen.width, Screen.height, LastAspectWidth, LastAspectHeight);
				}
				MinimapPatch.Update(userUpdate: true);
			}
		}
		catch (Exception)
		{
			AspectRatio.Value = ((AspectRatio.Value != LastAspectRatio) ? LastAspectRatio : string.Empty);
		}
	}
}
public static class Common
{
	public static Transform FindParentOrSelf(Transform transform, string name)
	{
		while ((Object)(object)transform != (Object)null)
		{
			if (((Object)transform).name == name)
			{
				return transform;
			}
			Transform parent = transform.parent;
			object obj;
			if (parent == null)
			{
				obj = null;
			}
			else
			{
				GameObject gameObject = ((Component)parent).gameObject;
				obj = ((gameObject != null) ? gameObject.transform : null);
			}
			transform = (Transform)obj;
		}
		return null;
	}
}