using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using REPOUW.Utils; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("REPOUW")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("REPOUW")] [assembly: AssemblyTitle("REPOUW")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace REPOUW { internal static class UWConfig { public static ConfigEntry Enabled; public static ConfigEntry ToggleKey; public static ConfigEntry QualityScale; public static void Bind(ConfigFile cfg) { Enabled = cfg.Bind("General", "Enabled", true, "Resize REPO's internal render target to match your screen aspect, giving true ultrawide / non-16:9 rendering. REPO's own HUD anchors (dollar counter, compass, level intro overlay) are NOT re-laid-out — they sit at their 16:9 positions with empty space alongside."); ToggleKey = cfg.Bind("General", "ToggleKey", (KeyCode)283, "Key to toggle the override at runtime."); QualityScale = cfg.Bind("General", "QualityScale", 1f, "Render resolution as a fraction of native screen. 1.0 = native, 0.75 = 75% downsample, 0.5 = half. REPO's in-game Render Size dropdown maps Small→0.5, Medium→0.75, Large→this value, so set this to your preferred max-quality scale."); } } [BepInPlugin("com.wearebonkers.repouw", "REPO Ultrawide", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.wearebonkers.repouw"; public const string PluginName = "REPO Ultrawide"; public const string PluginVersion = "1.0.0"; private GameObject _host; internal static Plugin Instance { get; private set; } internal static ManualLogSource Logger { get; private set; } private void Awake() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown Instance = this; Logger = ((BaseUnityPlugin)this).Logger; UWConfig.Bind(((BaseUnityPlugin)this).Config); _host = new GameObject("REPOUW_Host"); ((Object)_host).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)_host); _host.AddComponent(); Logger.LogInfo((object)"REPO Ultrawide 1.0.0 loaded."); } } internal class UltrawidePatcher : MonoBehaviour { private struct ImageState { public RawImage img; public Vector2 anchorMin; public Vector2 anchorMax; public Vector2 offsetMin; public Vector2 offsetMax; public bool hadFitter; public bool fitterEnabled; public AspectRatioFitter fitter; } private bool _applied; private Component _rtmCached; private bool _haveSavedOriginals; private float _savedSmallW; private float _savedSmallH; private float _savedMediumW; private float _savedMediumH; private float _savedLargeW; private float _savedLargeH; private float _savedOriginalW; private float _savedOriginalH; private readonly List _savedImages = new List(); private int _lastScreenW; private int _lastScreenH; private void Update() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown(UWConfig.ToggleKey.Value)) { UWConfig.Enabled.Value = !UWConfig.Enabled.Value; Plugin.Logger.LogInfo((object)$"Ultrawide override: {UWConfig.Enabled.Value}"); } } private void LateUpdate() { bool value = UWConfig.Enabled.Value; Component val = ResolveRtm(); if ((Object)(object)val != (Object)(object)_rtmCached) { _rtmCached = val; _applied = false; _haveSavedOriginals = false; _savedImages.Clear(); } if ((Object)(object)val == (Object)null) { return; } if (value != _applied) { if (value) { Apply(val); } else { Revert(val); } _applied = value; _lastScreenW = Screen.width; _lastScreenH = Screen.height; } else if (_applied && (Screen.width != _lastScreenW || Screen.height != _lastScreenH)) { Apply(val); _lastScreenW = Screen.width; _lastScreenH = Screen.height; } } private static Component ResolveRtm() { Type type = Reflect.FindType("RenderTextureMain"); if (type == null) { return null; } object staticMember = Reflect.GetStaticMember(type, "instance"); return (Component)((staticMember is Component) ? staticMember : null); } private void Apply(Component rtm) { if (!_haveSavedOriginals) { SaveOriginals(rtm); } int num = Mathf.Max(1, Screen.width); int num2 = Mathf.Max(1, Screen.height); float num3 = Mathf.Clamp(UWConfig.QualityScale.Value, 0.25f, 2f); float num4 = (float)num * num3; float num5 = (float)num2 * num3; SetFloat(rtm, "textureWidthSmall", (float)num * 0.5f); SetFloat(rtm, "textureHeightSmall", (float)num2 * 0.5f); SetFloat(rtm, "textureWidthMedium", (float)num * 0.75f); SetFloat(rtm, "textureHeightMedium", (float)num2 * 0.75f); SetFloat(rtm, "textureWidthLarge", num4); SetFloat(rtm, "textureHeightLarge", num5); SetFloat(rtm, "textureWidthOriginal", num4); SetFloat(rtm, "textureHeightOriginal", num5); InvokeNoArgs(rtm, "ResetResolution"); FixDisplayImages(rtm); Plugin.Logger.LogInfo((object)$"Applied {num4:0}×{num5:0} (scale {num3:F2}), {_savedImages.Count} display rect(s) stretched."); } private void Revert(Component rtm) { //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) if (!_haveSavedOriginals) { return; } SetFloat(rtm, "textureWidthSmall", _savedSmallW); SetFloat(rtm, "textureHeightSmall", _savedSmallH); SetFloat(rtm, "textureWidthMedium", _savedMediumW); SetFloat(rtm, "textureHeightMedium", _savedMediumH); SetFloat(rtm, "textureWidthLarge", _savedLargeW); SetFloat(rtm, "textureHeightLarge", _savedLargeH); SetFloat(rtm, "textureWidthOriginal", _savedOriginalW); SetFloat(rtm, "textureHeightOriginal", _savedOriginalH); InvokeNoArgs(rtm, "ResetResolution"); for (int i = 0; i < _savedImages.Count; i++) { ImageState imageState = _savedImages[i]; if (!((Object)(object)imageState.img == (Object)null)) { RectTransform rectTransform = ((Graphic)imageState.img).rectTransform; rectTransform.anchorMin = imageState.anchorMin; rectTransform.anchorMax = imageState.anchorMax; rectTransform.offsetMin = imageState.offsetMin; rectTransform.offsetMax = imageState.offsetMax; if (imageState.hadFitter && (Object)(object)imageState.fitter != (Object)null) { ((Behaviour)imageState.fitter).enabled = imageState.fitterEnabled; } } } _savedImages.Clear(); Plugin.Logger.LogInfo((object)"Reverted to authored 16:9 sizes."); } private void SaveOriginals(Component rtm) { _savedSmallW = GetFloat(rtm, "textureWidthSmall"); _savedSmallH = GetFloat(rtm, "textureHeightSmall"); _savedMediumW = GetFloat(rtm, "textureWidthMedium"); _savedMediumH = GetFloat(rtm, "textureHeightMedium"); _savedLargeW = GetFloat(rtm, "textureWidthLarge"); _savedLargeH = GetFloat(rtm, "textureHeightLarge"); _savedOriginalW = GetFloat(rtm, "textureWidthOriginal"); _savedOriginalH = GetFloat(rtm, "textureHeightOriginal"); _haveSavedOriginals = true; } private void FixDisplayImages(Component rtm) { //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) object member = Reflect.GetMember(rtm, "renderTexture"); RenderTexture val = (RenderTexture)((member is RenderTexture) ? member : null); if ((Object)(object)val == (Object)null) { return; } RawImage[] array = Object.FindObjectsOfType(); foreach (RawImage val2 in array) { if ((Object)(object)val2 == (Object)null || (Object)(object)val2.texture != (Object)(object)val) { continue; } bool flag = false; for (int j = 0; j < _savedImages.Count; j++) { if ((Object)(object)_savedImages[j].img == (Object)(object)val2) { flag = true; break; } } if (!flag) { AspectRatioFitter component = ((Component)val2).GetComponent(); _savedImages.Add(new ImageState { img = val2, anchorMin = ((Graphic)val2).rectTransform.anchorMin, anchorMax = ((Graphic)val2).rectTransform.anchorMax, offsetMin = ((Graphic)val2).rectTransform.offsetMin, offsetMax = ((Graphic)val2).rectTransform.offsetMax, hadFitter = ((Object)(object)component != (Object)null), fitterEnabled = ((Object)(object)component != (Object)null && ((Behaviour)component).enabled), fitter = component }); } RectTransform rectTransform = ((Graphic)val2).rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.offsetMin = Vector2.zero; rectTransform.offsetMax = Vector2.zero; AspectRatioFitter component2 = ((Component)val2).GetComponent(); if ((Object)(object)component2 != (Object)null) { ((Behaviour)component2).enabled = false; } } } private static float GetFloat(Component c, string field) { object member = Reflect.GetMember(c, field); if (member is float) { return (float)member; } if (member is int num) { return num; } return 0f; } private static void SetFloat(Component c, string field, float value) { if ((Object)(object)c == (Object)null) { return; } Type type = ((object)c).GetType(); FieldInfo field2 = type.GetField(field, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field2 != null) { field2.SetValue(c, value); return; } PropertyInfo property = type.GetProperty(field, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.CanWrite) { property.SetValue(c, value, null); } } private static void InvokeNoArgs(Component c, string method) { if (!((Object)(object)c == (Object)null)) { ((object)c).GetType().GetMethod(method, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null)?.Invoke(c, null); } } } public static class PluginInfo { public const string PLUGIN_GUID = "REPOUW"; public const string PLUGIN_NAME = "REPOUW"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace REPOUW.Utils { internal static class Reflect { private static readonly Dictionary _typeCache = new Dictionary(); public static Type FindType(params string[] candidateNames) { foreach (string text in candidateNames) { if (_typeCache.TryGetValue(text, out var value)) { if (value != null) { return value; } continue; } Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int j = 0; j < assemblies.Length; j++) { type = assemblies[j].GetType(text, throwOnError: false); if (type != null) { break; } } _typeCache[text] = type; if (type != null) { return type; } } return null; } public static object GetMember(object instance, params string[] memberNames) { if (instance == null) { return null; } Type type = instance.GetType(); foreach (string name in memberNames) { FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field.GetValue(instance); } PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.CanRead) { try { return property.GetValue(instance, null); } catch { } } } return null; } public static object GetStaticMember(Type type, params string[] memberNames) { if (type == null) { return null; } foreach (string name in memberNames) { FieldInfo field = type.GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field.GetValue(null); } PropertyInfo property = type.GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.CanRead) { try { return property.GetValue(null, null); } catch { } } } return null; } } }