Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Enigmas Snug Fit v0.1.18
EnigmasSnugFit.dll
Decompiled 14 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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 EnigmasSnugFit { [BepInPlugin("EnigmaPrime.EnigmasSnugFit", "Enigma's Snug Fit", "0.1.18")] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "EnigmaPrime.EnigmasSnugFit"; public const string PluginName = "Enigma's Snug Fit"; public const string PluginVersion = "0.1.18"; internal static ManualLogSource Log; internal static Plugin Instance; internal static ConfigEntry<float> YStepDegrees; internal static ConfigEntry<float> TiltStepDegrees; internal static ConfigEntry<bool> EnableTilt; internal static ConfigEntry<KeyCode> TiltModifierKey; internal static ConfigEntry<bool> ResetTiltOnPieceChange; internal static ConfigEntry<string> TiltCategories; internal static ConfigEntry<string> TiltExtraPieces; internal static ConfigEntry<bool> CopyTilt; internal static ConfigEntry<bool> EnableNudge; internal static ConfigEntry<float> NudgeStepMeters; internal static ConfigEntry<KeyCode> NudgeUpDownKey; internal static ConfigEntry<KeyCode> NudgeLeftRightKey; internal static ConfigEntry<KeyCode> NudgeForwardBackKey; internal static ConfigEntry<float> ForwardBackLimitMeters; internal static ConfigEntry<bool> ResetNudgeAfterPlacing; internal static ConfigEntry<float> UpDownLimitMeters; internal static ConfigEntry<float> LeftRightLimitMeters; internal static ConfigEntry<bool> EnableSnapCenter; internal static ConfigEntry<string> SnapCenterCategories; internal static ConfigEntry<string> SnapCenterExtraPieces; internal static ConfigEntry<KeyCode> ResetKey; internal static ConfigEntry<bool> ShowKeyHints; internal static ConfigEntry<bool> ReserveStrip; internal static ConfigEntry<float> StripHeight; internal static ConfigEntry<string> StripSkip; internal static ConfigEntry<bool> StripLog; internal static ConfigEntry<float> HintScale; internal static ConfigEntry<bool> CenterHints; internal static ConfigEntry<float> HintOffset; internal static ConfigEntry<bool> MoveBuildPanel; internal static ConfigEntry<float> BuildPanelGap; internal static ConfigEntry<bool> HidePieceHealth; internal static ConfigEntry<bool> EnableShowColors; internal static ConfigEntry<KeyCode> ShowColorsKey; internal static ConfigEntry<float> ShowColorsRadius; internal static ConfigEntry<bool> ConflictCheckEnabled; internal static readonly bool ColorViewParked = true; private Harmony _harmony; private void Awake() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Instance = this; BindConfig(); _harmony = new Harmony("EnigmaPrime.EnigmasSnugFit"); _harmony.PatchAll(); Log.LogInfo((object)"Enigma's Snug Fit 0.1.18 loaded."); } private void BindConfig() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Expected O, but got Unknown //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Expected O, but got Unknown //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Expected O, but got Unknown //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Expected O, but got Unknown //IL_0461: Unknown result type (might be due to invalid IL or missing references) //IL_046b: Expected O, but got Unknown //IL_04e2: Unknown result type (might be due to invalid IL or missing references) //IL_04ec: Expected O, but got Unknown //IL_053f: Unknown result type (might be due to invalid IL or missing references) //IL_0549: Expected O, but got Unknown //IL_059c: Unknown result type (might be due to invalid IL or missing references) //IL_05a6: Expected O, but got Unknown //IL_035c: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Expected O, but got Unknown YStepDegrees = ((BaseUnityPlugin)this).Config.Bind<float>("1 - Rotation", "Spin step (degrees)", 22.5f, new ConfigDescription("Degrees per scroll click when spinning a piece around the vertical axis. Vanilla is 22.5.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 90f), Array.Empty<object>())); EnableTilt = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Rotation", "Enable tilt", true, "Hold the tilt key while scrolling to tilt the piece around its own X axis (controller: hold the alt-keys button while rotating)."); TiltStepDegrees = ((BaseUnityPlugin)this).Config.Bind<float>("1 - Rotation", "Tilt step (degrees)", 22.5f, new ConfigDescription("Degrees per scroll click while tilting.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 90f), Array.Empty<object>())); TiltModifierKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("1 - Rotation", "Tilt key", (KeyCode)304, "Hold this while scrolling to tilt instead of spin."); ResetTiltOnPieceChange = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Rotation", "Reset tilt when the piece changes", true, "Clears the tilt when you pick a different piece (the spin angle is kept, like vanilla)."); TiltCategories = ((BaseUnityPlugin)this).Config.Bind<string>("1 - Rotation", "Tilt piece categories", "BuildingWorkbench,BuildingStonecutter", "Which hammer categories can tilt, comma separated (Misc, Crafting, BuildingWorkbench, BuildingStonecutter, Furniture, DeepNorth, Feasts, Food, Meads, or a number for modded categories). Item stands can always tilt. Other pieces only spin, like vanilla."); TiltExtraPieces = ((BaseUnityPlugin)this).Config.Bind<string>("1 - Rotation", "Tilt extra pieces", "", "Extra piece names that can tilt even if their category is not listed, comma separated (prefab names, for example piece_chest_wood). Leave empty for none."); CopyTilt = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Rotation", "Copy tilt with copy-rotation", true, "When you copy a placed piece the vanilla way (middle mouse by default), also copy its tilt."); EnableNudge = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Nudge", "Enable nudge", true, "Hold a nudge key and scroll the mouse wheel to move the piece after snapping (see the three nudge key settings). Left and right follow the piece, up and down are world up and down, forward and back follow the piece's front. Controller: hold the alt-keys button and push the right stick (up, down, left, right only)."); NudgeStepMeters = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Nudge", "Nudge step (meters)", 0.02f, new ConfigDescription("Distance per scroll click. 0.02 is 2 cm.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.005f, 1f), Array.Empty<object>())); NudgeUpDownKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("2 - Nudge", "Nudge up and down key", (KeyCode)306, "Hold this and scroll the wheel: up (scroll up) or down (scroll down), in world up and down."); NudgeLeftRightKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("2 - Nudge", "Nudge left and right key", (KeyCode)122, "Hold this and scroll the wheel: right (scroll up) or left (scroll down), following the piece's own sides."); NudgeForwardBackKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("2 - Nudge", "Nudge forward and back key", (KeyCode)120, "Hold this and scroll the wheel: forward (scroll up) or back (scroll down), along the piece's own front, kept level."); ForwardBackLimitMeters = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Nudge", "Forward and back limit (meters)", 0.14f, new ConfigDescription("How far forward or back a piece can be nudged, in meters. 0.14 is 14 cm. 0 means no limit.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>())); ResetNudgeAfterPlacing = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Nudge", "Reset nudge after placing", true, "Clears the nudge after each placed piece so the next one does not start sunken or shifted."); UpDownLimitMeters = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Nudge", "Up and down limit (meters)", 0.14f, new ConfigDescription("How far up or down a piece can be nudged, in meters. 0.14 is 14 cm. 0 means no limit.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>())); LeftRightLimitMeters = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Nudge", "Left and right limit (meters)", 0.14f, new ConfigDescription("How far left or right a piece can be nudged, in meters. 0.14 is 14 cm. 0 means no limit.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>())); if (!ColorViewParked) { EnableShowColors = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Structure colors", "Enable structure color view", true, "Press the key while the hammer is out to show the stability color (blue, green, yellow, red) on every piece around you, using the game's own highlight. Press again to turn it off. It also turns off when you put the hammer away. Controller: hold the alt-keys button and press Y."); ShowColorsKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("4 - Structure colors", "Structure color key", (KeyCode)277, "Turns the structure color view on and off."); ShowColorsRadius = ((BaseUnityPlugin)this).Config.Bind<float>("4 - Structure colors", "Structure color radius (meters)", 20f, new ConfigDescription("How far around you pieces are colored. Bigger values cost more on large bases.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 60f), Array.Empty<object>())); } EnableSnapCenter = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Snap center", "Enable snap center", true, "Adds a Center point to the snap cycle (Tab, or the controller's snap buttons) for building pieces. While Center is picked, the middle of the piece you hold snaps onto the snap points and the middle of nearby building pieces. Normal snapping is not changed."); SnapCenterCategories = ((BaseUnityPlugin)this).Config.Bind<string>("5 - Snap center", "Snap center piece categories", "BuildingWorkbench,BuildingStonecutter", "Which hammer categories get the Center point, comma separated (Misc, Crafting, BuildingWorkbench, BuildingStonecutter, Furniture, DeepNorth, Feasts, Food, Meads, or a number for modded categories). The held piece and the pieces it snaps to both have to be in this list."); SnapCenterExtraPieces = ((BaseUnityPlugin)this).Config.Bind<string>("5 - Snap center", "Snap center extra pieces", "", "Extra piece names that get the Center point even if their category is not listed, comma separated (prefab names). Leave empty for none."); ResetKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("3 - Other", "Reset key", (KeyCode)8, "Clears the tilt and the nudge on the current piece."); ShowKeyHints = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Other", "Show key hints", true, "Adds Tilt and Nudge lines to the build key hints on screen (follows the game's own key hints setting)."); ReserveStrip = ((BaseUnityPlugin)this).Config.Bind<bool>("6 - Reserved strip", "Reserve bottom strip", true, "Keeps an empty strip along the bottom of the screen for the key hints, whether the hammer is out or not. Other on-screen elements that reach into the strip are moved up out of it."); StripHeight = ((BaseUnityPlugin)this).Config.Bind<float>("6 - Reserved strip", "Strip height", 85f, new ConfigDescription("Height of the reserved strip in screen units (the game's HUD is about 1080 units tall). Raise it if something still overlaps the hints.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f), Array.Empty<object>())); StripSkip = ((BaseUnityPlugin)this).Config.Bind<string>("6 - Reserved strip", "Never move these", "", "Names of on-screen elements to leave where they are, comma separated. The log lists every element that was moved (see Log moved elements)."); StripLog = ((BaseUnityPlugin)this).Config.Bind<bool>("6 - Reserved strip", "Log moved elements", false, "Writes the name and path of every element moved out of the strip to the BepInEx log, once each. Useful for filling the list above."); HintScale = ((BaseUnityPlugin)this).Config.Bind<float>("7 - Hint bar", "Hint bar scale", 0.95f, new ConfigDescription("Size of the build key hint bar (1 = the game's size). Slightly smaller gives the long hint line more room.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 1.2f), Array.Empty<object>())); CenterHints = ((BaseUnityPlugin)this).Config.Bind<bool>("7 - Hint bar", "Center hint bar", true, "Centers the build key hints on the screen (the game's bar leaves a gap on the left and runs to the right edge)."); HintOffset = ((BaseUnityPlugin)this).Config.Bind<float>("7 - Hint bar", "Hint bar offset", 0f, new ConfigDescription("Extra sideways shift of the hint bar in screen units after centering (negative = left).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-200f, 200f), Array.Empty<object>())); MoveBuildPanel = ((BaseUnityPlugin)this).Config.Bind<bool>("8 - Build panel", "Move build panel above the strip", true, "Moves the box that shows the selected piece (name, description, costs, or Repair) down so it sits just above the reserved strip."); BuildPanelGap = ((BaseUnityPlugin)this).Config.Bind<float>("8 - Build panel", "Gap above the strip", 6f, new ConfigDescription("Space between the build panel and the strip, in screen units.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-50f, 200f), Array.Empty<object>())); HidePieceHealth = ((BaseUnityPlugin)this).Config.Bind<bool>("8 - Build panel", "Hide piece health while placing", true, "Hides the health bar of the piece under the crosshair while a piece is selected for placing. It still shows with the hammer's Repair."); ConflictCheckEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Other", "Turn off rotation features if another mod changes rotation", true, "Snug Fit looks for other mods that rewrite the game's placement rotation code (Gizmo and similar). If it finds one, spin step and tilt switch themselves off so the two do not fight. Nudge keeps working. Set to false to force Snug Fit on anyway."); ((BaseUnityPlugin)this).Config.SettingChanged += delegate { PlacementState.ConfigChanged(); }; } private void Start() { ConflictCheck.Run(); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } internal static class PlacementState { internal static int TiltSteps; internal static float NudgeRight; internal static float NudgeUp; internal static float NudgeForward; internal static bool TiltAllowed = true; internal static int? PendingTilt; internal static bool TiltHookWorks; internal static bool RotationConflict; internal static bool RotationActive => !RotationConflict; internal static void Reset() { TiltSteps = 0; ResetNudge(); } internal static void ResetNudge() { NudgeRight = 0f; NudgeUp = 0f; NudgeForward = 0f; } internal static bool CanTilt(GameObject ghost) { if ((Object)(object)ghost == (Object)null) { return true; } if ((Object)(object)ghost.GetComponent<ItemStand>() != (Object)null) { return true; } return MatchesPieceList(ghost, Plugin.TiltCategories.Value, Plugin.TiltExtraPieces.Value); } internal static bool MatchesPieceList(GameObject go, string categories, string extraPieces) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)go == (Object)null) { return false; } string b = StripClone(((Object)go).name); string[] array = extraPieces.Split(new char[1] { ',' }); foreach (string text in array) { if (text.Trim().Length > 0 && string.Equals(text.Trim(), b, StringComparison.OrdinalIgnoreCase)) { return true; } } Piece component = go.GetComponent<Piece>(); if ((Object)(object)component == (Object)null) { return false; } array = categories.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.Length != 0 && Enum.TryParse<PieceCategory>(text2, ignoreCase: true, out PieceCategory result) && result == component.m_category) { return true; } } return false; } internal static string StripClone(string name) { if (name == null) { return null; } int num = name.IndexOf("(Clone)", StringComparison.Ordinal); return ((num >= 0) ? name.Substring(0, num) : name).Trim(); } internal static void ClampNudge() { float value = Plugin.UpDownLimitMeters.Value; if (value > 0f) { NudgeUp = Mathf.Clamp(NudgeUp, 0f - value, value); } float value2 = Plugin.LeftRightLimitMeters.Value; if (value2 > 0f) { NudgeRight = Mathf.Clamp(NudgeRight, 0f - value2, value2); } float value3 = Plugin.ForwardBackLimitMeters.Value; if (value3 > 0f) { NudgeForward = Mathf.Clamp(NudgeForward, 0f - value3, value3); } } internal static void ConfigChanged() { SnugKeyHints.Refresh(); } public static Quaternion ApplyTilt(Quaternion yaw) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) if (RotationConflict || !TiltAllowed || !Plugin.EnableTilt.Value || TiltSteps == 0) { return yaw; } return yaw * Quaternion.Euler((float)TiltSteps * Plugin.TiltStepDegrees.Value, 0f, 0f); } } [HarmonyPatch(typeof(Player), "UpdatePlacement")] internal static class UpdatePlacementPatch { private static readonly FieldInfo DegreesField = AccessTools.Field(typeof(Player), "m_placeRotationDegrees"); private static readonly FieldInfo RotationField = AccessTools.Field(typeof(Player), "m_placeRotation"); private static readonly FieldInfo GhostField = AccessTools.Field(typeof(Player), "m_placementGhost"); private static float _nextRepeat; private static int _heldDir; private static float _nudgeScroll; private static void Prefix(Player __instance, out int __state) { if (PlacementState.RotationActive) { DegreesField.SetValue(__instance, Plugin.YStepDegrees.Value); } __state = (int)RotationField.GetValue(__instance); } private static void Postfix(Player __instance, bool takeInput, int __state) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_016b: Unknown result type (might be due to invalid IL or missing references) GameObject val = (GameObject)GhostField.GetValue(__instance); if (!takeInput || (Object)(object)val == (Object)null || !val.activeInHierarchy) { _heldDir = 0; _nudgeScroll = 0f; return; } int num = (int)RotationField.GetValue(__instance) - __state; int num2 = (Plugin.EnableNudge.Value ? NudgeAxisHeld() : 0); if (num2 != 0) { if (num != 0) { RotationField.SetValue(__instance, __state); } _nudgeScroll += ZInput.GetMouseScrollWheel(); int num3 = 0; if (_nudgeScroll > 0.1f) { num3 = 1; _nudgeScroll = 0f; } else if (_nudgeScroll < -0.1f) { num3 = -1; _nudgeScroll = 0f; } if (num3 != 0) { float num4 = (float)num3 * Plugin.NudgeStepMeters.Value; switch (num2) { case 1: PlacementState.NudgeUp += num4; break; case 2: PlacementState.NudgeRight += num4; break; default: PlacementState.NudgeForward += num4; break; } PlacementState.ClampNudge(); } } else { _nudgeScroll = 0f; if (num != 0 && Math.Abs(num) <= 2 && PlacementState.RotationActive && PlacementState.TiltAllowed && Plugin.EnableTilt.Value && TiltModifierHeld()) { RotationField.SetValue(__instance, __state); if (PlacementState.TiltHookWorks) { PlacementState.TiltSteps += num; } } } if (ZInput.GetKeyDown(Plugin.ResetKey.Value, false)) { PlacementState.Reset(); } if (Plugin.EnableNudge.Value) { HandlePadNudge(); } } private static int NudgeAxisHeld() { //IL_0005: 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_002d: Unknown result type (might be due to invalid IL or missing references) if (ZInput.GetKey(Plugin.NudgeUpDownKey.Value, false)) { return 1; } if (ZInput.GetKey(Plugin.NudgeLeftRightKey.Value, false)) { return 2; } if (ZInput.GetKey(Plugin.NudgeForwardBackKey.Value, false)) { return 3; } return 0; } private static bool TiltModifierHeld() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (ZInput.GetKey(Plugin.TiltModifierKey.Value, false)) { return true; } if (ZInput.IsGamepadActive()) { return ZInput.GetButton("JoyAltKeys"); } return false; } private static void HandlePadNudge() { if (!ZInput.IsGamepadActive() || !ZInput.GetButton("JoyAltKeys")) { _heldDir = 0; return; } float joyRightStickX = ZInput.GetJoyRightStickX(); float num = 0f - ZInput.GetJoyRightStickY(); int num2 = 0; if (joyRightStickX < -0.5f) { num2 = 1; } else if (joyRightStickX > 0.5f) { num2 = 2; } else if (num > 0.5f) { num2 = 3; } else if (num < -0.5f) { num2 = 4; } if (num2 == 0) { _heldDir = 0; return; } float unscaledTime = Time.unscaledTime; if (num2 != _heldDir) { _heldDir = num2; _nextRepeat = unscaledTime + 0.35f; } else { if (unscaledTime < _nextRepeat) { return; } _nextRepeat = unscaledTime + 0.08f; } float value = Plugin.NudgeStepMeters.Value; switch (num2) { case 1: PlacementState.NudgeRight -= value; break; case 2: PlacementState.NudgeRight += value; break; case 3: PlacementState.NudgeUp += value; break; default: PlacementState.NudgeUp -= value; break; } PlacementState.ClampNudge(); } } [HarmonyPatch(typeof(Player), "Update")] internal static class ShowColorsPatch { internal static bool Active; private static bool _logNextRound; private static bool _wasDown; private static bool _padWasDown; private static readonly KeyCode[] ProbeKeys; private static readonly bool[] _probeDown; private static bool _loggedReady; private static float _next; private static readonly List<Piece> Pieces; private static readonly MethodInfo TakeInputMethod; private static bool Prepare() { return !Plugin.ColorViewParked; } private static void Postfix(Player __instance) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } bool flag = true; if (TakeInputMethod != null) { try { flag = (bool)TakeInputMethod.Invoke(__instance, null); } catch { flag = true; } } if (!Plugin.EnableShowColors.Value) { if (Active) { Active = false; SnugKeyHints.Refresh(); } return; } bool num = flag && ZInput.GetKey(Plugin.ShowColorsKey.Value, false); bool flag2 = flag && ZInput.IsGamepadActive() && ZInput.GetButton("JoyAltKeys") && ZInput.GetButton("JoyButtonY"); bool flag3 = (num && !_wasDown) || (flag2 && !_padWasDown); _wasDown = num; _padWasDown = flag2; if (flag) { for (int i = 0; i < ProbeKeys.Length; i++) { bool key = ZInput.GetKey(ProbeKeys[i], false); if (key && !_probeDown[i]) { Plugin.Log.LogInfo((object)("Key seen: " + ((object)Unsafe.As<KeyCode, KeyCode>(ref ProbeKeys[i])/*cast due to .constrained prefix*/).ToString())); } _probeDown[i] = key; } } if (!_loggedReady) { _loggedReady = true; Plugin.Log.LogInfo((object)("Structure colors ready: key " + ((object)Plugin.ShowColorsKey.Value/*cast due to .constrained prefix*/).ToString() + ", radius " + Plugin.ShowColorsRadius.Value + " m, takeInput " + flag + ".")); } if (flag3) { Active = !Active; _next = 0f; _logNextRound = Active; Plugin.Log.LogInfo((object)("Structure colors " + (Active ? "on" : "off") + " (key " + ((object)Plugin.ShowColorsKey.Value/*cast due to .constrained prefix*/).ToString() + ").")); SnugKeyHints.Refresh(); } if (!Active) { return; } float unscaledTime = Time.unscaledTime; if (unscaledTime < _next) { return; } _next = unscaledTime + 0.15f; Pieces.Clear(); Piece.GetAllPiecesInRadius(((Component)__instance).transform.position, Plugin.ShowColorsRadius.Value, Pieces); int num2 = 0; foreach (Piece piece in Pieces) { if ((Object)(object)piece == (Object)null) { continue; } WearNTear component = ((Component)piece).GetComponent<WearNTear>(); if ((Object)(object)component == (Object)null) { continue; } try { component.Highlight(); num2++; } catch (Exception ex) { if (_logNextRound) { Plugin.Log.LogWarning((object)("Structure colors: Highlight failed on " + ((Object)piece).name + ": " + ex.Message)); _logNextRound = false; } } } if (_logNextRound) { _logNextRound = false; Plugin.Log.LogInfo((object)("Structure colors: " + Pieces.Count + " pieces within " + Plugin.ShowColorsRadius.Value + " m, " + num2 + " highlighted.")); } } static ShowColorsPatch() { KeyCode[] array = new KeyCode[7]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); ProbeKeys = (KeyCode[])(object)array; _probeDown = new bool[7]; Pieces = new List<Piece>(); TakeInputMethod = AccessTools.Method(typeof(Player), "TakeInput", (Type[])null, (Type[])null); } } [HarmonyPatch(typeof(Player), "UpdatePlacementGhost")] internal static class UpdatePlacementGhostPatch { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(instructions); FieldInfo fieldInfo = AccessTools.Field(typeof(Player), "m_placeRotationDegrees"); MethodInfo methodInfo = AccessTools.Method(typeof(Quaternion), "Euler", new Type[3] { typeof(float), typeof(float), typeof(float) }, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(PlacementState), "ApplyTilt", (Type[])null, (Type[])null); int num = 0; for (int i = 0; i < list.Count; i++) { if (!CodeInstructionExtensions.Calls(list[i], methodInfo)) { continue; } bool flag = false; for (int j = Math.Max(0, i - 10); j < i; j++) { if (CodeInstructionExtensions.LoadsField(list[j], fieldInfo, false)) { flag = true; break; } } if (flag) { list.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)methodInfo2)); num++; i++; } } PlacementState.TiltHookWorks = num == 1; if (num != 1) { Plugin.Log.LogWarning((object)$"Tilt hook: expected 1 place in Player.UpdatePlacementGhost, found {num}. Tilt is switched off (spin step and nudge still work). The game or another mod may have changed that method."); return instructions; } return list; } [HarmonyPriority(200)] private static void Postfix(Player __instance) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: 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_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.EnableNudge.Value || (PlacementState.NudgeRight == 0f && PlacementState.NudgeUp == 0f && PlacementState.NudgeForward == 0f)) { return; } GameObject val = (GameObject)AccessTools.Field(typeof(Player), "m_placementGhost").GetValue(__instance); if (!((Object)(object)val == (Object)null) && val.activeInHierarchy) { Transform transform = val.transform; Vector3 val2 = Vector3.ProjectOnPlane(transform.forward, Vector3.up); if (((Vector3)(ref val2)).sqrMagnitude < 0.01f) { val2 = Vector3.ProjectOnPlane(transform.up, Vector3.up); } val2 = ((Vector3)(ref val2)).normalized; transform.position += transform.right * PlacementState.NudgeRight + Vector3.up * PlacementState.NudgeUp + val2 * PlacementState.NudgeForward; } } } [HarmonyPatch(typeof(Player), "PlacePiece")] internal static class PlacePiecePatch { private static void Postfix() { if (Plugin.ResetNudgeAfterPlacing.Value) { PlacementState.ResetNudge(); } } } [HarmonyPatch(typeof(Player), "SetupPlacementGhost")] internal static class SetupPlacementGhostPatch { private static string _lastName; internal static string LastGhostName => PlacementState.StripClone(_lastName); private static void Postfix(Player __instance) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown GameObject val = (GameObject)AccessTools.Field(typeof(Player), "m_placementGhost").GetValue(__instance); string text = (((Object)(object)val != (Object)null) ? ((Object)val).name : null); if (text != _lastName) { _lastName = text; PlacementState.ResetNudge(); if (Plugin.ResetTiltOnPieceChange.Value) { PlacementState.TiltSteps = 0; } } PlacementState.TiltAllowed = PlacementState.CanTilt(val); if (PlacementState.PendingTilt.HasValue) { PlacementState.TiltSteps = (PlacementState.TiltAllowed ? PlacementState.PendingTilt.Value : 0); PlacementState.PendingTilt = null; } else if (!PlacementState.TiltAllowed) { PlacementState.TiltSteps = 0; } SnugKeyHints.Refresh(); } } [HarmonyPatch(typeof(Player), "CopyPiece")] internal static class CopyPiecePatch { private static readonly FieldInfo RemoveMask = AccessTools.Field(typeof(Player), "m_removeRayMask"); private static readonly FieldInfo EyeField = AccessTools.Field(typeof(Player), "m_eye"); private static readonly FieldInfo MaxDistField = AccessTools.Field(typeof(Player), "m_maxPlaceDistance"); private static readonly FieldInfo RotationField = AccessTools.Field(typeof(Player), "m_placeRotation"); private static void Postfix(Player __instance, bool __result) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: 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_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) if (!__result || !PlacementState.RotationActive || !Plugin.EnableTilt.Value || !Plugin.CopyTilt.Value) { return; } try { RaycastHit val = default(RaycastHit); if ((Object)(object)GameCamera.instance == (Object)null || !Physics.Raycast(((Component)GameCamera.instance).transform.position, ((Component)GameCamera.instance).transform.forward, ref val, 50f, (int)RemoveMask.GetValue(__instance))) { return; } Piece componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Piece>(); if (!((Object)(object)componentInParent == (Object)null)) { Quaternion rotation = ((Component)componentInParent).transform.rotation; Vector3 val2 = rotation * Vector3.right; float num = Mathf.Atan2(0f - val2.z, val2.x) * 57.29578f; Vector3 val3 = Quaternion.Euler(0f, 0f - num, 0f) * (rotation * Vector3.up); float num2 = Mathf.Atan2(val3.z, val3.y) * 57.29578f; float value = Plugin.YStepDegrees.Value; int num3 = (int)Math.Round(num / value); RotationField.SetValue(__instance, num3); int num4 = (int)Math.Round(num2 / Plugin.TiltStepDegrees.Value); if (PlacementState.StripClone(((Object)((Component)componentInParent).gameObject).name) == SetupPlacementGhostPatch.LastGhostName) { PlacementState.TiltSteps = (PlacementState.TiltAllowed ? num4 : 0); } else { PlacementState.PendingTilt = num4; } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Copy tilt failed: " + ex.Message)); } } } internal static class ConflictCheck { private static readonly string[] Methods = new string[2] { "UpdatePlacementGhost", "UpdatePlacement" }; private static string _lastReport = ""; internal static void Run() { try { List<string> list = new List<string>(); List<string> list2 = new List<string>(); string[] methods = Methods; foreach (string text in methods) { MethodBase methodBase = AccessTools.Method(typeof(Player), text, (Type[])null, (Type[])null); Patches val = ((methodBase == null) ? null : Harmony.GetPatchInfo(methodBase)); if (val == null) { continue; } foreach (Patch transpiler in val.Transpilers) { if (transpiler.owner != "EnigmaPrime.EnigmasSnugFit") { list.Add(transpiler.owner + " (transpiler on Player." + text + ")"); } } foreach (Patch prefix in val.Prefixes) { if (prefix.owner != "EnigmaPrime.EnigmasSnugFit") { list2.Add(prefix.owner + " (prefix on Player." + text + ")"); } } foreach (Patch postfix in val.Postfixes) { if (postfix.owner != "EnigmaPrime.EnigmasSnugFit") { list2.Add(postfix.owner + " (postfix on Player." + text + ")"); } } } bool flag = (PlacementState.RotationConflict = Plugin.ConflictCheckEnabled.Value && list.Count > 0); string text2 = (flag ? ("Another mod rewrites the placement rotation code: " + string.Join(", ", list.ToArray()) + ". Spin step and tilt are switched off; nudge still works. Remove one of the mods, or set the conflict option in the config to false to force Snug Fit on.") : ((list2.Count > 0) ? ("Other mods also patch placement (no rotation rewrite, so no conflict assumed): " + string.Join(", ", list2.ToArray())) : "No other mod patches the placement code.")); if (text2 != _lastReport) { _lastReport = text2; if (flag) { Plugin.Log.LogWarning((object)text2); } else { Plugin.Log.LogInfo((object)text2); } } SnugKeyHints.Refresh(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Conflict check failed: " + ex.Message)); } } } [HarmonyPatch(typeof(Player), "Awake")] internal static class PlayerAwakeConflictPatch { private static void Postfix() { ConflictCheck.Run(); } } internal static class SnapCenter { internal static readonly FieldInfo GhostField = AccessTools.Field(typeof(Player), "m_placementGhost"); internal static readonly FieldInfo ManualField = AccessTools.Field(typeof(Player), "m_manualSnapPoint"); private static readonly Dictionary<int, Transform> Points = new Dictionary<int, Transform>(); internal static bool Applies(GameObject go) { if (Plugin.EnableSnapCenter.Value && (Object)(object)go != (Object)null) { return PlacementState.MatchesPieceList(go, Plugin.SnapCenterCategories.Value, Plugin.SnapCenterExtraPieces.Value); } return false; } internal static int RealPointCount(GameObject go) { int num = 0; Transform transform = go.transform; for (int i = 0; i < transform.childCount; i++) { if (((Component)transform.GetChild(i)).CompareTag("snappoint")) { num++; } } return num; } internal static Transform GetPoint(Piece piece, bool forGhost) { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown //IL_0108: Unknown result type (might be due to invalid IL or missing references) int instanceID = ((Object)((Component)piece).gameObject).GetInstanceID(); if (Points.TryGetValue(instanceID, out var value) && (Object)(object)value != (Object)null) { return value; } if (Points.Count > 3000) { List<int> list = new List<int>(); foreach (KeyValuePair<int, Transform> point in Points) { if ((Object)(object)point.Value == (Object)null) { list.Add(point.Key); } } foreach (int item in list) { Points.Remove(item); } } if (!LocalBounds(((Component)piece).transform, out var bounds)) { return null; } GameObject val = new GameObject(forGhost ? "Center" : "EP_Center"); val.transform.SetParent(((Component)piece).transform, false); val.transform.localPosition = ((Bounds)(ref bounds)).center; Points[instanceID] = val.transform; return val.transform; } private static bool LocalBounds(Transform root, out Bounds bounds) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: 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) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) bounds = new Bounds(Vector3.zero, Vector3.zero); bool flag = false; MeshFilter[] componentsInChildren = ((Component)root).GetComponentsInChildren<MeshFilter>(false); foreach (MeshFilter val in componentsInChildren) { if ((Object)(object)val == (Object)null || (Object)(object)val.sharedMesh == (Object)null || (Object)(object)((Component)val).GetComponent<MeshRenderer>() == (Object)null) { continue; } Bounds bounds2 = val.sharedMesh.bounds; Vector3 center = ((Bounds)(ref bounds2)).center; Vector3 extents = ((Bounds)(ref bounds2)).extents; for (int j = 0; j < 8; j++) { Vector3 val2 = center + new Vector3(((j & 1) == 0) ? (0f - extents.x) : extents.x, ((j & 2) == 0) ? (0f - extents.y) : extents.y, ((j & 4) == 0) ? (0f - extents.z) : extents.z); Vector3 val3 = root.InverseTransformPoint(((Component)val).transform.TransformPoint(val2)); if (!flag) { bounds = new Bounds(val3, Vector3.zero); flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(val3); } } } return flag; } } [HarmonyPatch] internal static class PieceGetSnapPointsPatch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(Piece), "GetSnapPoints", new Type[1] { typeof(List<Transform>) }, (Type[])null); } private static bool Prepare() { if (TargetMethod() == null) { Plugin.Log.LogWarning((object)"Snap center: Piece.GetSnapPoints(List<Transform>) not found, snap center is switched off."); return false; } return true; } private static void Postfix(Piece __instance, List<Transform> points) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown if (!Plugin.EnableSnapCenter.Value || (Object)(object)__instance == (Object)null || points == null) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } GameObject val = (GameObject)SnapCenter.GhostField.GetValue(localPlayer); if ((Object)(object)val == (Object)null) { return; } int num = (int)SnapCenter.ManualField.GetValue(localPlayer); if (num == -1) { return; } if ((Object)(object)((Component)__instance).gameObject == (Object)(object)val) { if (SnapCenter.Applies(val)) { Transform point = SnapCenter.GetPoint(__instance, forGhost: true); if ((Object)(object)point != (Object)null) { points.Add(point); } } } else if (SnapCenter.Applies(val) && num == SnapCenter.RealPointCount(val) && SnapCenter.Applies(((Component)__instance).gameObject)) { Transform point2 = SnapCenter.GetPoint(__instance, forGhost: false); if ((Object)(object)point2 != (Object)null) { points.Add(point2); } } } } [HarmonyPatch(typeof(KeyHints), "Start")] internal static class KeyHintsStartPatch { private static void Postfix(KeyHints __instance) { SnugKeyHints.Create(__instance); HudStrip.Attach(__instance); } } [HarmonyPatch(typeof(KeyHints), "SetGamepadRotateText")] internal static class KeyHintsRotateTextPatch { private static void Postfix() { SnugKeyHints.Refresh(); } } internal static class SnugKeyHints { private static TextMeshProUGUI _tilt; private static TextMeshProUGUI _nudge; private static readonly List<TextMeshProUGUI[]> _kbRows = new List<TextMeshProUGUI[]>(); private static readonly List<GameObject> _kbRoots = new List<GameObject>(); internal static void Create(KeyHints hints) { //IL_004f: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) try { TextMeshProUGUI buildRotateKey = hints.m_buildRotateKey; if ((Object)(object)buildRotateKey == (Object)null) { Plugin.Log.LogWarning((object)"Key hints: vanilla rotate line not found, no hint lines added."); return; } Transform parent = ((TMP_Text)buildRotateKey).transform.parent; bool laidOut = (Object)(object)parent != (Object)null && (Object)(object)((Component)parent).GetComponent<LayoutGroup>() != (Object)null; float num = ((TMP_Text)buildRotateKey).rectTransform.anchoredPosition.y; float num2 = num; int num3 = 0; if ((Object)(object)parent != (Object)null) { foreach (Transform item in parent) { Transform val = item; if (!((Object)(object)((Component)val).GetComponent<TextMeshProUGUI>() == (Object)null)) { float y = ((RectTransform)val).anchoredPosition.y; num = Mathf.Max(num, y); num2 = Mathf.Min(num2, y); num3++; } } } Rect rect = ((TMP_Text)buildRotateKey).rectTransform.rect; float num4; if (!(((Rect)(ref rect)).height > 1f)) { num4 = 24f; } else { rect = ((TMP_Text)buildRotateKey).rectTransform.rect; num4 = ((Rect)(ref rect)).height; } float num5 = num4; Plugin.Log.LogInfo((object)("Key hints: parent " + (((Object)(object)parent != (Object)null) ? ((Object)parent).name : "none") + ", layout group " + laidOut + ", " + num3 + " text lines, y from " + num2 + " to " + num + ", line height " + num5 + ".")); _tilt = Clone(buildRotateKey, "EP_SnugTiltHint", laidOut, num + num5 * 1f); _nudge = Clone(buildRotateKey, "EP_SnugNudgeHint", laidOut, num + num5 * 2f); CreateKeyboardRows(hints); Refresh(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Key hints: could not add lines: " + ex.Message)); } } private static void CreateKeyboardRows(KeyHints hints) { //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Expected O, but got Unknown _kbRows.Clear(); _kbRoots.Clear(); if (hints.m_buildMenuHintsKB == null || hints.m_buildMenuHintsKB.Length == 0 || (Object)(object)hints.m_buildMenuHintsKB[0] == (Object)null) { Plugin.Log.LogWarning((object)"Key hints: no keyboard hint rows found."); return; } GameObject val = null; Transform parent = hints.m_buildMenuHintsKB[0].transform.parent; Transform val2 = (((Object)(object)parent != (Object)null) ? parent.Find("Remove") : null); if ((Object)(object)val2 != (Object)null) { val = ((Component)val2).gameObject; } if ((Object)(object)val == (Object)null) { GameObject[] buildMenuHintsKB = hints.m_buildMenuHintsKB; foreach (GameObject val3 in buildMenuHintsKB) { if ((Object)(object)val3 != (Object)null && ((Object)val3).name == "Remove") { val = val3; break; } } } if ((Object)(object)val == (Object)null) { val = hints.m_buildMenuHintsKB[hints.m_buildMenuHintsKB.Length - 1]; Plugin.Log.LogWarning((object)("Key hints: Remove row not found, copying " + ((Object)val).name + " instead.")); } Transform parent2 = val.transform.parent; TextMeshProUGUI[] componentsInChildren = val.GetComponentsInChildren<TextMeshProUGUI>(true); foreach (TextMeshProUGUI val4 in componentsInChildren) { Plugin.Log.LogInfo((object)("Key hints sample " + ((Object)val).name + ": text '" + ((Object)val4).name + "' under '" + ((Object)((TMP_Text)val4).transform.parent).name + "', size " + ((TMP_Text)val4).fontSize + ", text '" + ((TMP_Text)val4).text + "'.")); } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("Key hints keyboard group: parent ").Append(((Object)parent2).name).Append(", rows:"); foreach (Transform item2 in parent2) { Transform val5 = item2; stringBuilder.Append(" [").Append(((Object)val5).name).Append(" tmp=") .Append(((Component)val5).GetComponentsInChildren<TextMeshProUGUI>(true).Length) .Append("]"); } Plugin.Log.LogInfo((object)stringBuilder.ToString()); string[] array = new string[2] { "EP_SnugKbTilt", "EP_SnugKbNudge" }; foreach (string name in array) { GameObject val6 = Object.Instantiate<GameObject>(val, parent2); ((Object)val6).name = name; TextMeshProUGUI[] item = OrderLabelKey(val6); _kbRows.Add(item); _kbRoots.Add(val6); } } private static TextMeshProUGUI[] OrderLabelKey(GameObject row) { TextMeshProUGUI[] componentsInChildren = row.GetComponentsInChildren<TextMeshProUGUI>(true); if (componentsInChildren.Length < 2) { return componentsInChildren; } TextMeshProUGUI val = null; TextMeshProUGUI[] array = componentsInChildren; foreach (TextMeshProUGUI val2 in array) { if (((Object)val2).name.ToLowerInvariant().Contains("key")) { val = val2; break; } } if ((Object)(object)val == (Object)null) { array = componentsInChildren; foreach (TextMeshProUGUI val3 in array) { if ((Object)(object)((TMP_Text)val3).transform.parent != (Object)(object)row.transform) { val = val3; break; } } } if ((Object)(object)val == (Object)null) { val = componentsInChildren[^1]; } TextMeshProUGUI val4 = (((Object)(object)componentsInChildren[0] == (Object)(object)val) ? componentsInChildren[1] : componentsInChildren[0]); return (TextMeshProUGUI[])(object)new TextMeshProUGUI[2] { val4, val }; } private static void SetKeyboardRow(int index, bool visible, string label, string keys) { if (index >= _kbRows.Count || _kbRows[index] == null || _kbRows[index].Length == 0 || (Object)(object)_kbRows[index][0] == (Object)null) { return; } TextMeshProUGUI[] array = _kbRows[index]; if ((Object)(object)_kbRoots[index] != (Object)null) { _kbRoots[index].SetActive(visible); } TextMeshProUGUI[] array2 = array; foreach (TextMeshProUGUI val in array2) { if ((Object)(object)val != (Object)null) { ((TMP_Text)val).enableWordWrapping = false; } } if (array.Length >= 2) { ((TMP_Text)array[0]).text = label; ((TMP_Text)array[1]).text = keys; } else { ((TMP_Text)array[0]).text = label + " <mspace=0.6em> " + keys + "</mspace>"; } } private static TextMeshProUGUI Clone(TextMeshProUGUI template, string name, bool laidOut, float y) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject, ((TMP_Text)template).transform.parent); ((Object)val).name = name; if (!laidOut) { val.GetComponent<RectTransform>().anchoredPosition = new Vector2(((TMP_Text)template).rectTransform.anchoredPosition.x, y); } return val.GetComponent<TextMeshProUGUI>(); } internal static void Refresh() { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_tilt == (Object)null) && !((Object)(object)_nudge == (Object)null) && Plugin.TiltModifierKey != null) { bool flag = ZInput.IsGamepadActive(); bool flag2 = Plugin.ShowKeyHints.Value && Plugin.EnableTilt.Value && PlacementState.RotationActive && PlacementState.TiltAllowed; bool flag3 = Plugin.ShowKeyHints.Value && Plugin.EnableNudge.Value; ((Component)_tilt).gameObject.SetActive(flag2); ((Component)_nudge).gameObject.SetActive(flag3); ((TMP_Text)_tilt).text = "Tilt <mspace=0.6em> " + (flag ? "Alt + Rotate" : (KeyName(Plugin.TiltModifierKey.Value) + " + Scroll")) + "</mspace>"; ((TMP_Text)_nudge).text = "Nudge <mspace=0.6em> Alt + R Stick</mspace>"; SetKeyboardRow(0, flag2, "Tilt", KeyName(Plugin.TiltModifierKey.Value) + " + Scroll"); SetKeyboardRow(1, flag3, "Nudge", KeyName(Plugin.NudgeUpDownKey.Value) + "/" + KeyName(Plugin.NudgeLeftRightKey.Value) + "/" + KeyName(Plugin.NudgeForwardBackKey.Value) + " + Scroll"); } } private unsafe static string KeyName(KeyCode k) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected I4, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected I4, but got Unknown return (k - 273) switch { 3 => "Left", 2 => "Right", 0 => "Up", 1 => "Down", _ => (k - 303) switch { 1 => "Shift", 0 => "R-Shift", 3 => "Ctrl", 2 => "R-Ctrl", _ => ((object)(*(KeyCode*)(&k))/*cast due to .constrained prefix*/).ToString(), }, }; } } internal class HudStrip : MonoBehaviour { private struct Moved { public Vector2 Written; public float Delta; } private struct Item { public RectTransform Rt; public float B; public float T; public float L; public float R; public float Delta; } private readonly Dictionary<RectTransform, Moved> _moved = new Dictionary<RectTransform, Moved>(); private readonly List<Item> _items = new List<Item>(); private readonly HashSet<string> _logged = new HashSet<string>(); private readonly Vector3[] _c = (Vector3[])(object)new Vector3[4]; private RectTransform _root; private KeyHints _hints; private HashSet<string> _skip = new HashSet<string>(); private string _skipText; private Vector3 _hintWritten; private float _hintDx; private bool _hintShifted; private Vector3 _hintBaseScale = Vector3.one; private bool _hintScaleKnown; private Vector3 _buildWritten; private float _buildDy; private bool _buildShifted; private bool _buildLogged; private static readonly FieldInfo BuildHudField = AccessTools.Field(typeof(Hud), "m_buildHud"); private static readonly FieldInfo HealthRootField = AccessTools.Field(typeof(Hud), "m_pieceHealthRoot"); private static GameObject AsObject(FieldInfo f) { if (f == null || (Object)(object)Hud.instance == (Object)null) { return null; } object value = f.GetValue(Hud.instance); GameObject val = (GameObject)((value is GameObject) ? value : null); if ((Object)(object)val != (Object)null) { return val; } Component val2 = (Component)((value is Component) ? value : null); if (!((Object)(object)val2 != (Object)null)) { return null; } return val2.gameObject; } internal static void Attach(KeyHints hints) { if (!((Object)(object)hints == (Object)null)) { HudStrip hudStrip = ((Component)hints).GetComponent<HudStrip>(); if ((Object)(object)hudStrip == (Object)null) { hudStrip = ((Component)hints).gameObject.AddComponent<HudStrip>(); } hudStrip._hints = hints; } } private void LateUpdate() { //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) try { Undo(); UndoHintShift(); UndoBuildShift(); Canvas componentInParent = ((Component)this).GetComponentInParent<Canvas>(); if ((Object)(object)componentInParent == (Object)null) { return; } ref RectTransform root = ref _root; Transform transform = ((Component)componentInParent.rootCanvas).transform; root = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)_root == (Object)null) { return; } _root.GetWorldCorners(_c); float y = _c[0].y; float num = _c[1].y - _c[0].y; float x = _c[0].x; float x2 = _c[2].x; if (!(num <= 0f)) { if (Plugin.ReserveStrip.Value) { RunStrip(y, num); } RunHintBar(x, x2); if (Plugin.MoveBuildPanel.Value) { RunBuildPanel(y + Plugin.StripHeight.Value * ((Transform)_root).lossyScale.y, ((Transform)_root).lossyScale.y); } HidePieceHealth(); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Reserved strip: " + ex.Message)); ((Behaviour)this).enabled = false; } } private void RunStrip(float bottom, float height) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) if (_skipText != Plugin.StripSkip.Value) { _skipText = Plugin.StripSkip.Value; _skip = new HashSet<string>(); string[] array = _skipText.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length > 0) { _skip.Add(text); } } } float y = ((Transform)_root).lossyScale.y; float num = bottom + Plugin.StripHeight.Value * y; _items.Clear(); Collect((Transform)(object)_root, 0, bottom, height); _items.Sort((Item a, Item b) => a.B.CompareTo(b.B)); float num2 = 40f * y; for (int num3 = 0; num3 < _items.Count; num3++) { Item value = _items[num3]; float num4 = Mathf.Max(0f, num - value.B); for (int num5 = 0; num5 < num3; num5++) { Item item = _items[num5]; if (!(item.Delta <= 0f) && value.L < item.R && item.L < value.R && value.B >= item.B - 0.001f && value.B - item.T <= num2) { num4 = Mathf.Max(num4, item.Delta); } } value.Delta = num4; _items[num3] = value; if (num4 <= 0f) { continue; } RectTransform rt = value.Rt; float num6 = num4 / (((Object)(object)((Transform)rt).parent != (Object)null) ? Mathf.Max(0.0001f, ((Transform)rt).parent.lossyScale.y) : 1f); rt.anchoredPosition += new Vector2(0f, num6); _moved[rt] = new Moved { Written = rt.anchoredPosition, Delta = num6 }; if (Plugin.StripLog.Value) { string text2 = PathOf((Transform)(object)rt); if (_logged.Add(text2)) { Plugin.Log.LogInfo((object)("Reserved strip: moved up " + num6.ToString("0.#") + " units: " + text2)); } } } } private void Undo() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair<RectTransform, Moved> item in _moved) { RectTransform key = item.Key; if (!((Object)(object)key == (Object)null)) { Vector2 val = key.anchoredPosition - item.Value.Written; if (((Vector2)(ref val)).sqrMagnitude < 0.0001f) { key.anchoredPosition -= new Vector2(0f, item.Value.Delta); } } } _moved.Clear(); } private void Collect(Transform parent, int depth, float canvasBottom, float canvasHeight) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown GameObject val = (Plugin.MoveBuildPanel.Value ? AsObject(BuildHudField) : null); foreach (Transform item in parent) { Transform val2 = item; RectTransform val3 = (RectTransform)(object)((val2 is RectTransform) ? val2 : null); if ((Object)(object)val3 == (Object)null || !((Component)val2).gameObject.activeInHierarchy || (Object)(object)val2 == (Object)(object)((Component)this).transform || ((Object)(object)val != (Object)null && (Object)(object)((Component)val2).gameObject == (Object)(object)val) || ((Object)val2).name.StartsWith("EP_") || _skip.Contains(((Object)val2).name) || ((Object)val2).name.IndexOf("KeyHints", StringComparison.OrdinalIgnoreCase) >= 0) { continue; } Canvas component = ((Component)val2).GetComponent<Canvas>(); if ((Object)(object)component != (Object)null && component.isRootCanvas) { continue; } val3.GetWorldCorners(_c); float y = _c[0].y; float y2 = _c[1].y; float num = y2 - y; if (((Component)this).transform.IsChildOf(val2) || num > canvasHeight * 0.5f) { if (depth < 4) { Collect(val2, depth + 1, canvasBottom, canvasHeight); } } else if (!(num <= 0f) && !(y2 <= canvasBottom)) { _items.Add(new Item { Rt = val3, B = y, T = y2, L = _c[0].x, R = _c[2].x }); } } } private void UndoHintShift() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_007e: Unknown result type (might be due to invalid IL or missing references) if (!_hintShifted || (Object)(object)_hints == (Object)null || (Object)(object)_hints.m_buildHints == (Object)null) { _hintShifted = false; return; } Transform transform = _hints.m_buildHints.transform; Vector3 val = transform.position - _hintWritten; if (((Vector3)(ref val)).sqrMagnitude < 1E-08f) { transform.position -= new Vector3(_hintDx, 0f, 0f); } _hintShifted = false; } private void RunHintBar(float screenLeft, float screenRight) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_hints == (Object)null || (Object)(object)_hints.m_buildHints == (Object)null) { return; } GameObject buildHints = _hints.m_buildHints; Transform transform = buildHints.transform; if (!_hintScaleKnown) { _hintBaseScale = transform.localScale; _hintScaleKnown = true; } float num = Mathf.Clamp(Plugin.HintScale.Value, 0.5f, 1.5f); Vector3 val = _hintBaseScale * num; Vector3 val2 = transform.localScale - val; if (((Vector3)(ref val2)).sqrMagnitude > 1E-08f) { transform.localScale = val; } if (!Plugin.CenterHints.Value || !buildHints.activeInHierarchy) { return; } float num2 = float.MaxValue; float num3 = float.MinValue; TextMeshProUGUI[] componentsInChildren = buildHints.GetComponentsInChildren<TextMeshProUGUI>(false); foreach (TextMeshProUGUI val3 in componentsInChildren) { if (!((Object)(object)val3 == (Object)null) && !string.IsNullOrEmpty(((TMP_Text)val3).text) && ((Component)val3).gameObject.activeInHierarchy) { Bounds textBounds = ((TMP_Text)val3).textBounds; if (!(((Bounds)(ref textBounds)).size.x <= 0f)) { float x = ((TMP_Text)val3).transform.TransformPoint(new Vector3(((Bounds)(ref textBounds)).min.x, 0f, 0f)).x; float x2 = ((TMP_Text)val3).transform.TransformPoint(new Vector3(((Bounds)(ref textBounds)).max.x, 0f, 0f)).x; num2 = Mathf.Min(num2, Mathf.Min(x, x2)); num3 = Mathf.Max(num3, Mathf.Max(x, x2)); } } } if (!(num2 > num3)) { float num4 = (screenLeft + screenRight) * 0.5f - (num2 + num3) * 0.5f + Plugin.HintOffset.Value * ((Transform)_root).lossyScale.x; if (!(Mathf.Abs(num4) < 0.0001f)) { transform.position += new Vector3(num4, 0f, 0f); _hintWritten = transform.position; _hintDx = num4; _hintShifted = true; } } } private void UndoBuildShift() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) if (!_buildShifted) { return; } GameObject val = AsObject(BuildHudField); if ((Object)(object)val != (Object)null) { Vector3 val2 = val.transform.position - _buildWritten; if (((Vector3)(ref val2)).sqrMagnitude < 1E-08f) { Transform transform = val.transform; transform.position -= new Vector3(0f, _buildDy, 0f); } } _buildShifted = false; } private void RunBuildPanel(float stripTop, float scaleY) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: 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) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) GameObject val = AsObject(BuildHudField); if ((Object)(object)val == (Object)null || !val.activeInHierarchy) { return; } float num = float.MaxValue; Image val2 = null; Image[] componentsInChildren = val.GetComponentsInChildren<Image>(false); foreach (Image val3 in componentsInChildren) { if (!((Object)(object)val3 == (Object)null) && ((Behaviour)val3).enabled && !(((Graphic)val3).color.a < 0.02f)) { ((Graphic)val3).rectTransform.GetWorldCorners(_c); if (_c[0].y < num) { num = _c[0].y; val2 = val3; } } } if ((Object)(object)val2 == (Object)null) { return; } float num2 = stripTop + Plugin.BuildPanelGap.Value * scaleY - num; if (!(Mathf.Abs(num2) < 0.0001f)) { Transform transform = val.transform; transform.position += new Vector3(0f, num2, 0f); _buildWritten = val.transform.position; _buildDy = num2; _buildShifted = true; if (!_buildLogged && Plugin.StripLog.Value) { _buildLogged = true; Plugin.Log.LogInfo((object)("Build panel: moved " + (num2 / scaleY).ToString("0.#") + " units to sit above the strip; lowest image " + PathOf(((Component)val2).transform))); } } } private void HidePieceHealth() { if (!Plugin.HidePieceHealth.Value) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || !((Character)localPlayer).InPlaceMode()) { return; } Piece selectedPiece = localPlayer.GetSelectedPiece(); if (!((Object)(object)selectedPiece == (Object)null) && !selectedPiece.m_repairPiece) { GameObject val = AsObject(HealthRootField); if ((Object)(object)val != (Object)null && val.activeSelf) { val.SetActive(false); } } } private static string PathOf(Transform t) { string text = ((Object)t).name; int num = 0; while ((Object)(object)t.parent != (Object)null && num++ < 6) { t = t.parent; text = ((Object)t).name + "/" + text; } return text; } } }