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;
}
}