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 FlipIt v0.3.7
FlipIt.dll
Decompiled 12 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("FlipIt")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Shift + scroll to tilt hammer placement pieces on the horizontal axis.")] [assembly: AssemblyFileVersion("0.3.3.0")] [assembly: AssemblyInformationalVersion("0.3.3+889b28dd83d35f0fe1c5ba4de79c6e36d8725391")] [assembly: AssemblyProduct("FlipIt")] [assembly: AssemblyTitle("FlipIt")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.3.3.0")] [module: UnverifiableCode] [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 FlipIt { [BepInPlugin("hardwire99.flipit", "Flip It", "0.3.7")] public sealed class FlipItPlugin : BaseUnityPlugin { internal static ManualLogSource Log; private Harmony harmony; private void Awake() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; ModConfig.Bind(((BaseUnityPlugin)this).Config); if (!ModConfig.Enabled.Value) { Log.LogInfo((object)"Flip It 0.3.7 is disabled in config."); return; } harmony = new Harmony("hardwire99.flipit"); harmony.PatchAll(typeof(FlipItPlugin).Assembly); Log.LogInfo((object)("Flip It 0.3.7 loaded (reset-key-j, dll " + GetDllTimestamp() + ").")); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } private static string GetDllTimestamp() { string location = Assembly.GetExecutingAssembly().Location; if (!File.Exists(location)) { return "unknown"; } return File.GetLastWriteTime(location).ToString("yyyy-MM-dd HH:mm:ss"); } } internal static class ModConfig { internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> DebugLogging; internal static ConfigEntry<float> RotationStepDegrees; internal static ConfigEntry<bool> MatchVanillaYawStep; internal static ConfigEntry<bool> AllowAnySurface; internal static ConfigEntry<bool> AlignToSurface; internal static ConfigEntry<bool> SuppressSnapWhileRotating; internal static ConfigEntry<KeyCode> ResetRotationKey; internal static void Bind(ConfigFile config) { Enabled = config.Bind<bool>("General", "Enabled", true, "Enable free placement rotation while building."); DebugLogging = config.Bind<bool>("General", "DebugLogging", false, "Log rotation changes to BepInEx."); RotationStepDegrees = config.Bind<float>("Placement", "RotationStepDegrees", 22.5f, "Degrees per Shift/Ctrl+scroll step on pitch and roll. Used when MatchVanillaYawStep is false (for example, set to 90 for quarter-turn steps)."); MatchVanillaYawStep = config.Bind<bool>("Placement", "MatchVanillaYawStep", true, "Use the game's native rotation step (22.5 by default) for Shift/Ctrl+scroll. Set false to use RotationStepDegrees instead."); AllowAnySurface = config.Bind<bool>("Placement", "AllowAnySurface", true, "Allow placing on walls, ceilings, slopes, and other surfaces vanilla would reject."); AlignToSurface = config.Bind<bool>("Placement", "AlignToSurface", true, "Align the placement ghost to the surface you are aiming at."); SuppressSnapWhileRotating = config.Bind<bool>("Placement", "SuppressSnapWhileRotating", true, "While Shift or Ctrl is held, skip surface snap so rotation does not jump to a new attach point."); ResetRotationKey = config.Bind<KeyCode>("Controls", "ResetRotationKey", (KeyCode)106, "While placing, press this key to reset the current piece to vanilla upright orientation."); } internal static void LogRotation(Player player, PlacementAxis axis, float delta) { if (DebugLogging.Value) { float rotationStep = PlacementSurfaceHelper.GetRotationStep(player); string text = ((axis == PlacementAxis.X) ? "pitch (Shift+scroll)" : "roll (Ctrl+scroll)"); FlipItPlugin.Log.LogInfo((object)string.Format("{0} {1}{2} deg -> pitch {3}, roll {4}", text, (delta > 0f) ? "+" : "-", rotationStep, PlacementRotationState.GetPitchDegrees(player), PlacementRotationState.GetRollDegrees(player))); } } } internal static class ModConstants { public const string ModGuid = "hardwire99.flipit"; public const string ModName = "Flip It"; public const string ModVersion = "0.3.7"; public const string BuildLabel = "reset-key-j"; } internal struct PiecePlacementFlagsBackup { internal bool HasBackup; internal bool GroundOnly; internal bool GroundPiece; internal bool CultivatedGroundOnly; internal bool VegetationGroundOnly; internal bool NotOnFloor; internal bool InCeilingOnly; internal bool NotOnTiltingSurface; } internal static class PiecePlacementFlags { internal static PiecePlacementFlagsBackup Relax(Player player, Piece piece) { PiecePlacementFlagsBackup result = default(PiecePlacementFlagsBackup); if ((Object)(object)piece == (Object)null || !ModConfig.AllowAnySurface.Value || !PlacementRotationState.HasExtraRotation(player)) { return result; } result.HasBackup = true; result.GroundOnly = piece.m_groundOnly; result.GroundPiece = piece.m_groundPiece; result.CultivatedGroundOnly = piece.m_cultivatedGroundOnly; result.VegetationGroundOnly = piece.m_vegetationGroundOnly; result.NotOnFloor = piece.m_notOnFloor; result.InCeilingOnly = piece.m_inCeilingOnly; result.NotOnTiltingSurface = piece.m_notOnTiltingSurface; piece.m_groundOnly = false; piece.m_groundPiece = false; piece.m_cultivatedGroundOnly = false; piece.m_vegetationGroundOnly = false; piece.m_notOnFloor = false; piece.m_inCeilingOnly = false; piece.m_notOnTiltingSurface = false; return result; } internal static void Restore(Piece piece, PiecePlacementFlagsBackup backup) { if (!((Object)(object)piece == (Object)null) && backup.HasBackup) { piece.m_groundOnly = backup.GroundOnly; piece.m_groundPiece = backup.GroundPiece; piece.m_cultivatedGroundOnly = backup.CultivatedGroundOnly; piece.m_vegetationGroundOnly = backup.VegetationGroundOnly; piece.m_notOnFloor = backup.NotOnFloor; piece.m_inCeilingOnly = backup.InCeilingOnly; piece.m_notOnTiltingSurface = backup.NotOnTiltingSurface; } } } internal static class PlacementCompatibility { private static readonly string[] SkippedPieceNameTokens = new string[6] { "prefab", "blueprint", "planbuild", "plan_", "_plan", "infinityhammer" }; internal static bool ShouldSkipFlipIt(Player player, GameObject ghost) { if ((Object)(object)player == (Object)null || (Object)(object)ghost == (Object)null) { return false; } if (HasSkippedComponent(ghost)) { return true; } Piece component = ghost.GetComponent<Piece>(); if ((Object)(object)component == (Object)null) { return CountChildPieces(ghost) > 1; } if (ContainsSkippedToken(component.m_name) || ContainsSkippedToken(((Object)ghost).name)) { return true; } return CountChildPieces(ghost) > 1; } internal static void ClearRotationIfSkipped(Player player, GameObject ghost) { if (ShouldSkipFlipIt(player, ghost)) { PlacementRotationState.Reset(player); } } private static bool HasSkippedComponent(GameObject ghost) { MonoBehaviour[] componentsInChildren = ghost.GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { string text = ((object)val).GetType().FullName ?? string.Empty; if (text.IndexOf("PrefabHammer", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("PlanBuild", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Blueprint", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } } return false; } private static int CountChildPieces(GameObject ghost) { return ghost.GetComponentsInChildren<Piece>(true).Length; } private static bool ContainsSkippedToken(string value) { if (string.IsNullOrEmpty(value)) { return false; } string[] skippedPieceNameTokens = SkippedPieceNameTokens; foreach (string value2 in skippedPieceNameTokens) { if (value.IndexOf(value2, StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } } internal static class PlacementFrameState { internal static int SavedPlaceRotation; internal static bool ShiftActive; internal static bool CtrlActive; internal static bool ModifierActive { get { if (!ShiftActive) { return CtrlActive; } return true; } } internal static void BeginFrame(int placeRotation, bool shiftActive, bool ctrlActive) { SavedPlaceRotation = placeRotation; ShiftActive = shiftActive; CtrlActive = ctrlActive; } } internal static class PlacementInputHelper { internal static bool IsShiftHeld() { if (!ZInput.GetButton("AltPlace") && !ZInput.GetButton("LShift") && !ZInput.GetKey((KeyCode)304, true)) { return ZInput.GetKey((KeyCode)303, true); } return true; } internal static bool IsCtrlHeld() { if (!ZInput.GetKey((KeyCode)306, true)) { return ZInput.GetKey((KeyCode)305, true); } return true; } internal static bool IsRotationModifierHeld() { if (!IsShiftHeld()) { return IsCtrlHeld(); } return true; } internal static bool TryResetRotation(Player player) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || !ModConfig.Enabled.Value || !((Character)player).InPlaceMode() || Hud.IsPieceSelectionVisible()) { return false; } if (!Input.GetKeyDown(ModConfig.ResetRotationKey.Value)) { return false; } PlacementResetHelper.ResetToVanilla(player); return true; } } internal static class PlacementPieceTracker { private static readonly Dictionary<long, int> LastPieceIdByPlayer = new Dictionary<long, int>(); internal static void Clear(Player player) { if (!((Object)(object)player == (Object)null)) { LastPieceIdByPlayer.Remove(player.GetPlayerID()); } } internal static void OnGhostSetup(Player player, GameObject ghost) { if (!((Object)(object)player == (Object)null) && !((Object)(object)ghost == (Object)null)) { int pieceId = GetPieceId(ghost.GetComponent<Piece>()); long playerID = player.GetPlayerID(); if (!LastPieceIdByPlayer.TryGetValue(playerID, out var value) || value != pieceId) { LastPieceIdByPlayer[playerID] = pieceId; PlacementResetHelper.ResetToVanilla(player); } } } private static int GetPieceId(Piece piece) { if ((Object)(object)piece == (Object)null) { return 0; } if (!string.IsNullOrEmpty(piece.m_name)) { return piece.m_name.GetHashCode(); } return ((Object)piece).name.GetHashCode(); } } internal static class PlacementResetHelper { internal static void ResetToVanilla(Player player) { if (!((Object)(object)player == (Object)null)) { PlacementRotationState.Reset(player); Traverse.Create((object)player).Field("m_placeRotation").SetValue((object)0); } } } internal static class PlacementRotation { internal static Quaternion GetGhostRotation(Player player) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) Traverse obj = Traverse.Create((object)player); float value = obj.Field("m_placeRotationDegrees").GetValue<float>(); int value2 = obj.Field("m_placeRotation").GetValue<int>(); float num = value * (float)value2; object value3 = obj.Field("m_placementGhost").GetValue(); GameObject val = (GameObject)((value3 is GameObject) ? value3 : null); if (PlacementCompatibility.ShouldSkipFlipIt(player, val)) { PlacementCompatibility.ClearRotationIfSkipped(player, val); return Quaternion.Euler(0f, num, 0f); } if (!ModConfig.Enabled.Value || !PlacementRotationState.HasExtraRotation(player)) { return Quaternion.Euler(0f, num, 0f); } if (ShouldUseFreeRotation(player)) { return Quaternion.Euler(PlacementRotationState.GetPitchDegrees(player), num, PlacementRotationState.GetRollDegrees(player)); } if ((Object)(object)val != (Object)null && PlacementSurfaceHelper.TryRayTest(player, val, out var _, out var normal)) { return PlacementSurfaceHelper.BuildRotation(player, normal); } return Quaternion.Euler(PlacementRotationState.GetPitchDegrees(player), num, PlacementRotationState.GetRollDegrees(player)); } private static bool ShouldUseFreeRotation(Player player) { if (ModConfig.SuppressSnapWhileRotating.Value) { if (!PlacementFrameState.ModifierActive) { return PlacementInputHelper.IsRotationModifierHeld(); } return true; } return false; } } internal static class PlacementRotationState { private static readonly Dictionary<long, Vector2> ExtraEulerByPlayer = new Dictionary<long, Vector2>(); internal static Vector2 GetExtraEuler(Player player) { //IL_0009: 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_0023: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return Vector2.zero; } if (!ExtraEulerByPlayer.TryGetValue(player.GetPlayerID(), out var value)) { return Vector2.zero; } return value; } internal static bool HasExtraRotation(Player player) { //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_0007: 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) Vector2 extraEuler = GetExtraEuler(player); if (Mathf.Approximately(extraEuler.x, 0f)) { return !Mathf.Approximately(extraEuler.y, 0f); } return true; } internal static void Reset(Player player) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null)) { ExtraEulerByPlayer[player.GetPlayerID()] = Vector2.zero; } } internal static void AddAxisRotation(Player player, PlacementAxis axis, float delta) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null) && !Mathf.Approximately(delta, 0f)) { float num = PlacementSurfaceHelper.GetRotationStep(player) * delta; Vector2 extraEuler = GetExtraEuler(player); switch (axis) { case PlacementAxis.X: extraEuler.x = NormalizeAngle(extraEuler.x + num); break; case PlacementAxis.Z: extraEuler.y = NormalizeAngle(extraEuler.y + num); break; } ExtraEulerByPlayer[player.GetPlayerID()] = extraEuler; } } internal static float GetPitchDegrees(Player player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return GetExtraEuler(player).x; } internal static float GetRollDegrees(Player player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return GetExtraEuler(player).y; } private static float NormalizeAngle(float angle) { angle %= 360f; if (angle < 0f) { angle += 360f; } return angle; } } internal enum PlacementAxis { None, X, Z } internal static class PlacementSurfaceHelper { private static readonly MethodInfo PieceRayTestMethod = AccessTools.Method(typeof(Player), "PieceRayTest", (Type[])null, (Type[])null); private static readonly MethodInfo SetPlacementGhostValidMethod = AccessTools.Method(typeof(Player), "SetPlacementGhostValid", (Type[])null, (Type[])null); internal static bool TryRayTest(Player player, GameObject ghost, out Vector3 point, out Vector3 normal) { //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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: 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_00ae: 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_00b6: Unknown result type (might be due to invalid IL or missing references) point = Vector3.zero; normal = Vector3.up; if ((Object)(object)player == (Object)null || (Object)(object)ghost == (Object)null || PieceRayTestMethod == null) { return false; } Piece component = ghost.GetComponent<Piece>(); bool flag = (Object)(object)component != (Object)null && (component.m_waterPiece || component.m_noInWater); object[] array = new object[6] { Vector3.zero, Vector3.up, null, null, null, flag }; bool num = (bool)PieceRayTestMethod.Invoke(player, array); point = (Vector3)array[0]; Vector3 val = (Vector3)array[1]; normal = ((Vector3)(ref val)).normalized; if (num) { return ((Vector3)(ref normal)).sqrMagnitude > 0.001f; } return false; } internal static float GetRotationStep(Player player) { if (ModConfig.MatchVanillaYawStep.Value && (Object)(object)player != (Object)null) { return Traverse.Create((object)player).Field("m_placeRotationDegrees").GetValue<float>(); } return ModConfig.RotationStepDegrees.Value; } internal static Quaternion BuildRotation(Player player, Vector3 surfaceNormal) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) Traverse obj = Traverse.Create((object)player); float value = obj.Field("m_placeRotationDegrees").GetValue<float>(); int value2 = obj.Field("m_placeRotation").GetValue<int>(); float num = value * (float)value2; float pitchDegrees = PlacementRotationState.GetPitchDegrees(player); float rollDegrees = PlacementRotationState.GetRollDegrees(player); Quaternion val = Quaternion.Euler(pitchDegrees, num, rollDegrees); if (!ModConfig.AlignToSurface.Value || !PlacementRotationState.HasExtraRotation(player) || ((Vector3)(ref surfaceNormal)).sqrMagnitude < 0.001f) { return val; } return Quaternion.FromToRotation(Vector3.up, surfaceNormal) * val; } internal static bool ShouldBypassPlacementStatus(PlacementStatus status) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Invalid comparison between Unknown and I4 //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 if (!ModConfig.AllowAnySurface.Value) { return false; } if ((int)status <= 5) { if ((int)status == 1 || (int)status == 5) { goto IL_0028; } } else if (status - 9 <= 1 || (int)status == 12) { goto IL_0028; } return false; IL_0028: return true; } internal static void ApplySurfacePlacement(Player player, GameObject ghost, ref PlacementStatus placementStatus) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (ModConfig.Enabled.Value && !((Object)(object)ghost == (Object)null) && ((Character)player).InPlaceMode() && PlacementRotationState.HasExtraRotation(player) && !ShouldSuppressSnap() && TryRayTest(player, ghost, out var point, out var normal) && ShouldBypassPlacementStatus(placementStatus)) { Piece component = ghost.GetComponent<Piece>(); ghost.SetActive(true); ghost.transform.rotation = BuildRotation(player, normal); SnapGhostToPoint(ghost, point, normal, component); placementStatus = (PlacementStatus)0; SetPlacementGhostValidMethod?.Invoke(player, new object[1] { true }); } } internal static void SnapGhostToPoint(GameObject ghost, Vector3 point, Vector3 normal, Piece piece) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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_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_0011: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: 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_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00da: 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_0079: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0081: 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_0090: 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) Collider[] componentsInChildren = ghost.GetComponentsInChildren<Collider>(); if (componentsInChildren.Length == 0) { ghost.transform.position = point; return; } ghost.transform.position = point + normal * 50f; Vector3 val = Vector3.zero; float num = float.MaxValue; Collider[] array = componentsInChildren; foreach (Collider val2 in array) { if (val2.isTrigger || !val2.enabled) { continue; } MeshCollider val3 = (MeshCollider)(object)((val2 is MeshCollider) ? val2 : null); if (val3 == null || val3.convex) { Vector3 val4 = val2.ClosestPoint(point); float num2 = Vector3.Distance(val4, point); if (num2 < num) { val = val4; num = num2; } } } Vector3 val5 = ghost.transform.position - val; if ((Object)(object)piece != (Object)null && piece.m_waterPiece) { val5.y = 3f; } ghost.transform.position = point + val5; } private static bool ShouldSuppressSnap() { if (ModConfig.SuppressSnapWhileRotating.Value) { if (!PlacementFrameState.ModifierActive) { return PlacementInputHelper.IsRotationModifierHeld(); } return true; } return false; } } } namespace FlipIt.Patches { [HarmonyPatch(typeof(Player), "FindClosestSnappoint")] internal static class PlayerFindClosestSnappointPatch { [HarmonyPrefix] private static bool Prefix(ref bool __result) { if (!ModConfig.Enabled.Value || !ModConfig.SuppressSnapWhileRotating.Value || !PlacementRotationState.HasExtraRotation(Player.m_localPlayer)) { return true; } if (!PlacementFrameState.ModifierActive && !PlacementInputHelper.IsRotationModifierHeld()) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(Player), "PlacePiece")] internal static class PlayerPlacePiecePatch { [HarmonyPostfix] private static void Postfix(Player __instance, GameObject ___m_placementGhost) { if (ModConfig.Enabled.Value && !((Object)(object)__instance == (Object)null) && PlacementCompatibility.ShouldSkipFlipIt(__instance, ___m_placementGhost)) { PlacementRotationState.Reset(__instance); } } } [HarmonyPatch(typeof(Player), "SetPlaceMode")] internal static class PlayerSetPlaceModePatch { [HarmonyPostfix] private static void Postfix(Player __instance) { PlacementPieceTracker.Clear(__instance); PlacementResetHelper.ResetToVanilla(__instance); } } [HarmonyPatch(typeof(Player), "SetupPlacementGhost")] internal static class PlayerSetupPlacementGhostPatch { [HarmonyPostfix] private static void Postfix(Player __instance, GameObject ___m_placementGhost) { PlacementPieceTracker.OnGhostSetup(__instance, ___m_placementGhost); } } [HarmonyPatch(typeof(Player), "UpdatePlacementGhost")] internal static class PlayerUpdatePlacementGhostPatch { private static readonly MethodInfo QuaternionEulerMethod = AccessTools.Method(typeof(Quaternion), "Euler", new Type[3] { typeof(float), typeof(float), typeof(float) }, (Type[])null); private static readonly MethodInfo GetGhostRotationMethod = AccessTools.Method(typeof(PlacementRotation), "GetGhostRotation", (Type[])null, (Type[])null); [HarmonyPrefix] private static void Prefix(Player __instance, GameObject ___m_placementGhost, ref PiecePlacementFlagsBackup __state) { if (!((Object)(object)___m_placementGhost == (Object)null)) { PlacementCompatibility.ClearRotationIfSkipped(__instance, ___m_placementGhost); if (!PlacementCompatibility.ShouldSkipFlipIt(__instance, ___m_placementGhost)) { __state = PiecePlacementFlags.Relax(__instance, ___m_placementGhost.GetComponent<Piece>()); } } } [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown List<CodeInstruction> list = instructions.ToList(); for (int i = 0; i < list.Count; i++) { if (CodeInstructionExtensions.Calls(list[i], QuaternionEulerMethod)) { list[i - 1] = new CodeInstruction(OpCodes.Ldarg_0, (object)null); list[i] = new CodeInstruction(OpCodes.Call, (object)GetGhostRotationMethod); list.RemoveRange(i - 8, 7); break; } } return list; } [HarmonyPostfix] private static void Postfix(Player __instance, GameObject ___m_placementGhost, ref PlacementStatus ___m_placementStatus, PiecePlacementFlagsBackup __state) { PiecePlacementFlags.Restore(((Object)(object)___m_placementGhost != (Object)null) ? ___m_placementGhost.GetComponent<Piece>() : null, __state); if (ModConfig.Enabled.Value && ((Character)__instance).InPlaceMode() && !((Object)(object)___m_placementGhost == (Object)null) && !PlacementCompatibility.ShouldSkipFlipIt(__instance, ___m_placementGhost)) { PlacementSurfaceHelper.ApplySurfacePlacement(__instance, ___m_placementGhost, ref ___m_placementStatus); } } } [HarmonyPatch(typeof(Player), "UpdatePlacement")] internal static class PlayerUpdatePlacementPatch { [HarmonyPrefix] private static void Prefix(Player __instance, ref int ___m_placeRotation) { bool flag = ModConfig.Enabled.Value && ((Character)__instance).InPlaceMode() && PlacementInputHelper.IsShiftHeld(); bool ctrlActive = ModConfig.Enabled.Value && ((Character)__instance).InPlaceMode() && PlacementInputHelper.IsCtrlHeld() && !flag; PlacementFrameState.BeginFrame(___m_placeRotation, flag, ctrlActive); } [HarmonyPostfix] private static void Postfix(Player __instance, bool takeInput, ref int ___m_placeRotation, ref float ___m_scrollCurrAmount) { if (ModConfig.Enabled.Value && ((Character)__instance).InPlaceMode() && takeInput && !PlacementInputHelper.TryResetRotation(__instance) && !Hud.IsPieceSelectionVisible() && PlacementFrameState.ModifierActive) { PlacementAxis axis = (PlacementFrameState.ShiftActive ? PlacementAxis.X : PlacementAxis.Z); float axis2 = Input.GetAxis("Mouse ScrollWheel"); int num = ___m_placeRotation - PlacementFrameState.SavedPlaceRotation; float num2 = 0f; if (!Mathf.Approximately(axis2, 0f)) { num2 = ((axis2 > 0f) ? 1f : (-1f)); } else if (num != 0) { num2 = ((num > 0) ? 1f : (-1f)); } if (!Mathf.Approximately(num2, 0f)) { PlacementRotationState.AddAxisRotation(__instance, axis, num2); ModConfig.LogRotation(__instance, axis, num2); } ___m_placeRotation = PlacementFrameState.SavedPlaceRotation; ___m_scrollCurrAmount = 0f; } } } }