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 FurnitureGrid v1.0.2
DumbassStuff.FurnitureEnhanced.dll
Decompiled 7 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using App1.Patches.Furniture; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using LethalCompanyInputUtils.Api; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.InputSystem; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("ClientNetworkTransform")] [assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")] [assembly: IgnoresAccessChecksTo("DissonanceVoip")] [assembly: IgnoresAccessChecksTo("EasyTextEffects")] [assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")] [assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")] [assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")] [assembly: IgnoresAccessChecksTo("Unity.Burst")] [assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")] [assembly: IgnoresAccessChecksTo("Unity.Collections")] [assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")] [assembly: IgnoresAccessChecksTo("Unity.Jobs")] [assembly: IgnoresAccessChecksTo("Unity.Mathematics")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")] [assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")] [assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")] [assembly: IgnoresAccessChecksTo("Unity.Services.QoS")] [assembly: IgnoresAccessChecksTo("Unity.Services.Relay")] [assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")] [assembly: IgnoresAccessChecksTo("Unity.Timeline")] [assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")] [assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UI")] [assembly: AssemblyCompany("DumbassStuff.FurnitureEnhanced")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("App1")] [assembly: AssemblyTitle("DumbassStuff.FurnitureEnhanced")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace App1 { [BepInPlugin("DumbassStuff.FurnitureEnhanced", "App1", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class App1 : BaseUnityPlugin { internal static ConfigEntry<bool>? GridEnabled; internal static ConfigEntry<float>? GridSize; internal static ConfigEntry<bool>? SnapOnWalls; internal static ConfigEntry<float>? GridSizeStep; internal static ConfigEntry<bool>? RotationSnapEnabled; internal static ConfigEntry<float>? RotationSnapAngle; internal static ConfigEntry<float>? RotationSnapAngleStep; internal static ConfigEntry<float>? GridDisplayExtent; internal static ConfigEntry<Color>? GridLineColor; internal static ConfigEntry<float>? GridMinorLineWidth; internal static ConfigEntry<float>? GridMajorLineWidth; internal static ConfigEntry<int>? GridMajorLineEvery; internal static ConfigEntry<bool>? ShowGridOverlay; internal GridOverlay overlay; internal static GridSnapInputs Inputs { get; private set; } public static App1 Instance { get; private set; } internal static ManualLogSource Logger { get; private set; } internal static Harmony? Harmony { get; set; } private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; Instance = this; BindConfiguration(); InitializeInputs(); InitializeOverlay(); Patch(); Logger.LogInfo((object)"DumbassStuff.FurnitureEnhanced v1.0.0 has loaded!"); } internal static void Patch() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown if (Harmony == null) { Harmony = new Harmony("DumbassStuff.FurnitureEnhanced"); } Logger.LogDebug((object)"Patching..."); Harmony.PatchAll(); Logger.LogDebug((object)"Finished patching!"); } internal static void Unpatch() { Logger.LogDebug((object)"Unpatching..."); Harmony? harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } Logger.LogDebug((object)"Finished unpatching!"); } private void BindConfiguration() { //IL_0159: Unknown result type (might be due to invalid IL or missing references) GridEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Grid", "Enabled", true, "Enable grid snapping in ship build mode"); GridSize = ((BaseUnityPlugin)this).Config.Bind<float>("Grid", "Size", 0.5f, "Grid cell size in meters"); GridSizeStep = ((BaseUnityPlugin)this).Config.Bind<float>("Grid", "SizeStep", 0.05f, "Grid size adjustment increment"); SnapOnWalls = ((BaseUnityPlugin)this).Config.Bind<bool>("Grid", "SnapOnWalls", false, "Enable grid snapping on walls"); RotationSnapEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Rotation", "Enabled", true, "Enable rotation snapping"); RotationSnapAngle = ((BaseUnityPlugin)this).Config.Bind<float>("Rotation", "AngleStep", 45f, "Rotation snap angle in degrees"); RotationSnapAngleStep = ((BaseUnityPlugin)this).Config.Bind<float>("Rotation", "AngleStepIncrement", 15f, "Rotation angle adjustment"); ShowGridOverlay = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowOverlay", true, "Show visual grid overlay"); GridDisplayExtent = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Extent", 15f, "Grid display radius in meters"); GridLineColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Display", "LineColor", new Color(1f, 1f, 0f, 0.4f), "Grid line color"); GridMinorLineWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "MinorLineWidth", 0.01f, "Minor grid line thickness"); GridMajorLineWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "MajorLineWidth", 0.03f, "Major grid line thickness"); GridMajorLineEvery = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "MajorLineEvery", 4, "Major line frequency"); } private void InitializeOverlay() { overlay = new GridOverlay(); } internal static void UpdateBuildModeTip() { if ((Object)(object)ShipBuildModeManager.Instance == (Object)null || !ShipBuildModeManager.Instance.InBuildMode || GridSize == null || RotationSnapAngle == null) { return; } HUDManager instance = HUDManager.Instance; if (!((Object)(object)instance?.buildModeControlTip == (Object)null)) { string text = ((TMP_Text)instance.buildModeControlTip).text; int num = text.IndexOf(" | Grid:", StringComparison.Ordinal); if (num >= 0) { text = text.Substring(0, num); } ConfigEntry<bool> gridEnabled = GridEnabled; string text2 = ((gridEnabled != null && gridEnabled.Value) ? "ON" : "OFF"); gridEnabled = RotationSnapEnabled; string text3 = ((gridEnabled != null && gridEnabled.Value) ? "ON" : "OFF"); string text4 = $"Grid: {text2} ({GridSize.Value:F2}m) | Rot: {text3} ({RotationSnapAngle.Value:F0}°)"; ((TMP_Text)instance.buildModeControlTip).text = text + " | " + text4; } } private void InitializeInputs() { Inputs = new GridSnapInputs(); ((LcInputActions)Inputs).Enable(); SetupInputHandlers(); } private void SetupInputHandlers() { Inputs.ToggleGrid.performed += delegate { ToggleGrid(); }; Inputs.IncreaseGrid.performed += delegate { AdjustGridSize(increase: true); }; Inputs.DecreaseGrid.performed += delegate { AdjustGridSize(increase: false); }; Inputs.ToggleRotationSnap.performed += delegate { ToggleRotationSnap(); }; Inputs.IncreaseRotationSnapAngle.performed += delegate { AdjustRotationAngle(increase: true); }; Inputs.DecreaseRotationSnapAngle.performed += delegate { AdjustRotationAngle(increase: false); }; } private void ToggleGrid() { if (GridEnabled != null) { GridEnabled.Value = !GridEnabled.Value; } UpdateBuildModeTip(); ManualLogSource logger = Logger; ConfigEntry<bool> gridEnabled = GridEnabled; logger.LogInfo((object)("Grid snapping " + ((gridEnabled != null && gridEnabled.Value) ? "enabled" : "disabled"))); if ((Object)(object)ShipBuildModeManager.Instance != (Object)null && ShipBuildModeManager.Instance.InBuildMode) { overlay?.UpdateVisibility(); } } private void AdjustGridSize(bool increase) { if (GridSizeStep != null && GridSize != null) { float value = (increase ? (GridSize.Value + GridSizeStep.Value) : Mathf.Max(GridSizeStep.Value, GridSize.Value - GridSizeStep.Value)); GridSize.Value = value; } overlay.Rebuild(); UpdateBuildModeTip(); if (GridSize != null) { Logger.LogInfo((object)$"Grid size: {GridSize.Value:F2}m"); } } private static void ToggleRotationSnap() { if (RotationSnapEnabled != null) { RotationSnapEnabled.Value = !RotationSnapEnabled.Value; } UpdateBuildModeTip(); ManualLogSource logger = Logger; ConfigEntry<bool> rotationSnapEnabled = RotationSnapEnabled; logger.LogInfo((object)("Rotation snapping " + ((rotationSnapEnabled != null && rotationSnapEnabled.Value) ? "enabled" : "disabled"))); } private static void AdjustRotationAngle(bool increase) { if (RotationSnapAngleStep != null && RotationSnapAngle != null) { float value = (increase ? (RotationSnapAngle.Value + RotationSnapAngleStep.Value) : Mathf.Max(0f, RotationSnapAngle.Value - RotationSnapAngleStep.Value)); RotationSnapAngle.Value = value; } UpdateBuildModeTip(); if (RotationSnapAngle != null) { Logger.LogInfo((object)$"Rotation angle: {RotationSnapAngle.Value:F0}°"); } } } public static class MyPluginInfo { public const string PLUGIN_GUID = "DumbassStuff.FurnitureEnhanced"; public const string PLUGIN_NAME = "App1"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace App1.Patches.Furniture { [HarmonyPatch(typeof(ShipBuildModeManager))] public class FurnitureEvents { private static readonly FieldInfo PlacingObjectField; private static readonly FieldInfo CurrentColliderField; private static readonly FieldInfo PlacementMaskAndBlockersField; private static readonly FieldInfo CanConfirmPositionField; static FurnitureEvents() { Type typeFromHandle = typeof(ShipBuildModeManager); PlacingObjectField = AccessTools.Field(typeFromHandle, "placingObject"); CurrentColliderField = AccessTools.Field(typeFromHandle, "currentCollider"); PlacementMaskAndBlockersField = AccessTools.Field(typeFromHandle, "placementMaskAndBlockers"); CanConfirmPositionField = AccessTools.Field(typeFromHandle, "CanConfirmPosition"); } private static PlaceableShipObject? GetPlacingObject(ShipBuildModeManager instance) { object? value = PlacingObjectField.GetValue(instance); return (PlaceableShipObject?)((value is PlaceableShipObject) ? value : null); } private static bool GetReloadBatteriesInput() { InputAction obj = IngamePlayerSettings.Instance.playerInput.actions.FindAction("ReloadBatteries", false); return obj != null && obj.WasPressedThisFrame(); } private static BoxCollider? GetCurrentCollider(ShipBuildModeManager instance, PlaceableShipObject placingObject) { object? value = CurrentColliderField.GetValue(instance); BoxCollider val = (BoxCollider)((value is BoxCollider) ? value : null); return (BoxCollider?)(((object)val) ?? ((object)/*isinst with value type is only supported in some contexts*/)); } private static int GetPlacementMask(ShipBuildModeManager instance) { return (int)(PlacementMaskAndBlockersField.GetValue(instance) ?? ((object)0)); } private static bool CheckCollisions(Transform ghost, BoxCollider collider, PlaceableShipObject placingObject, int placementMask) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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_0062: 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_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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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_00aa: Unknown result type (might be due to invalid IL or missing references) bool flag = Physics.CheckBox(ghost.position, collider.size * 0.5f * 0.5f, ghost.rotation, placementMask, (QueryTriggerInteraction)1); if (flag || !placingObject.doCollisionPointCheck) { return flag; } Vector3 val = ghost.position + ghost.forward * placingObject.collisionPointCheck.z + ghost.right * placingObject.collisionPointCheck.x + ghost.up * placingObject.collisionPointCheck.y; return Physics.CheckSphere(val, 1f * ((Component)ghost).transform.localScale.x, placementMask, (QueryTriggerInteraction)1); } private static bool IsWithinShipBounds(Vector3 position) { //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_0031: Unknown result type (might be due to invalid IL or missing references) StartOfRound instance = StartOfRound.Instance; bool? obj; if (instance == null) { obj = null; } else { Collider shipInnerRoomBounds = instance.shipInnerRoomBounds; if (shipInnerRoomBounds == null) { obj = null; } else { Bounds bounds = shipInnerRoomBounds.bounds; obj = ((Bounds)(ref bounds)).Contains(position); } } bool? flag = obj; return flag.GetValueOrDefault(); } private static void SetCanConfirmPosition(ShipBuildModeManager instance, bool canConfirm) { CanConfirmPositionField?.SetValue(instance, canConfirm); } private static void UpdateGhostMaterial(ShipBuildModeManager instance, bool blocked) { if ((Object)(object)instance.ghostObjectRenderer != (Object)null) { ((Renderer)instance.ghostObjectRenderer).sharedMaterial = (blocked ? instance.ghostObjectRed : instance.ghostObjectGreen); } } private static void ValidatePlacement(ShipBuildModeManager instance, PlaceableShipObject placingObject) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) Transform ghostObject = instance.ghostObject; if (!((Object)(object)ghostObject == (Object)null)) { BoxCollider currentCollider = GetCurrentCollider(instance, placingObject); if (!((Object)(object)currentCollider == (Object)null)) { int placementMask = GetPlacementMask(instance); bool flag = CheckCollisions(ghostObject, currentCollider, placingObject, placementMask); bool flag2 = IsWithinShipBounds(ghostObject.position); bool canConfirm = !flag && flag2; SetCanConfirmPosition(instance, canConfirm); UpdateGhostMaterial(instance, flag); } } } [HarmonyPatch("Update")] [HarmonyPrefix] public static void Update_Prefix(ShipBuildModeManager __instance) { //IL_0058: 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) if (!__instance.InBuildMode) { return; } PlaceableShipObject placingObject = GetPlacingObject(__instance); if (!((Object)(object)placingObject == (Object)null) && GetReloadBatteriesInput()) { Transform ghostObject = __instance.ghostObject; if ((Object)(object)ghostObject != (Object)null && App1.RotationSnapAngle != null) { ghostObject.eulerAngles += new Vector3(0f, App1.RotationSnapAngle.Value, 0f); } } } private static void ApplyGridSnapping(Transform ghost) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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_0077: Unknown result type (might be due to invalid IL or missing references) Transform val = StartOfRound.Instance?.elevatorTransform; if (!((Object)(object)val == (Object)null) && App1.GridSize != null) { float value = App1.GridSize.Value; Vector3 val2 = val.InverseTransformPoint(ghost.position); val2.x = Mathf.Round(val2.x / value) * value; val2.z = Mathf.Round(val2.z / value) * value; ghost.position = val.TransformPoint(val2); } } private static void ApplyRotationSnapping(Transform ghost) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_0038: Unknown result type (might be due to invalid IL or missing references) if (App1.RotationSnapAngle != null) { float value = App1.RotationSnapAngle.Value; Vector3 eulerAngles = ghost.eulerAngles; eulerAngles.y = Mathf.Round(eulerAngles.y / value) * value; ghost.eulerAngles = eulerAngles; } } [HarmonyPatch("Update")] [HarmonyPostfix] public static void Update_Postfix(ShipBuildModeManager __instance) { if (!__instance.InBuildMode) { return; } PlaceableShipObject placingObject = GetPlacingObject(__instance); if ((Object)(object)placingObject == (Object)null) { return; } Transform ghostObject = __instance.ghostObject; if (!((Object)(object)ghostObject == (Object)null)) { if (App1.GridEnabled != null && App1.GridEnabled.Value && App1.SnapOnWalls != null && (!placingObject.AllowPlacementOnWalls || App1.SnapOnWalls.Value)) { ApplyGridSnapping(ghostObject); } if (App1.RotationSnapEnabled != null && App1.RotationSnapEnabled.Value) { ApplyRotationSnapping(ghostObject); } ValidatePlacement(__instance, placingObject); } } [HarmonyPatch("CancelBuildMode")] [HarmonyPostfix] public static void CancelBuildMode_Postfix(ShipBuildModeManager __instance) { App1.Instance.overlay.Hide(); } [HarmonyPatch("CreateGhostObjectAndHighlight")] [HarmonyPostfix] public static void CreateGhostObjectAndHighlight_Postfix(ShipBuildModeManager __instance) { App1.UpdateBuildModeTip(); Transform val = StartOfRound.Instance?.elevatorTransform; if ((Object)(object)val != (Object)null) { App1.Instance.overlay.Show(val); } } } public class GridOverlay { private GameObject? _root; private readonly List<LineRenderer> _lineRenderers = new List<LineRenderer>(); private Material? _lineMaterial; private static Material? _cachedLineMaterial; internal void UpdateVisibility() { if (!((Object)(object)_root == (Object)null)) { bool flag = App1.ShowGridOverlay != null && App1.ShowGridOverlay.Value && App1.GridEnabled != null && App1.GridEnabled.Value; _root.SetActive(flag); if (flag) { Rebuild(); } } } public void Show(Transform elevator) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) EnsureRootExists(); GameObject? root = _root; if (root != null) { root.transform.SetParent(elevator, false); } if ((Object)(object)_root != (Object)null) { _root.transform.localPosition = Vector3.zero; } if ((Object)(object)_root != (Object)null) { _root.transform.localRotation = Quaternion.identity; } UpdateVisibility(); } public void Hide() { if ((Object)(object)_root != (Object)null) { _root.SetActive(false); } } internal void Rebuild() { if (!((Object)(object)_root == (Object)null) && _root.activeSelf) { ClearLines(); CreateGridLines(); } } private void EnsureRootExists() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown if (!((Object)(object)_root != (Object)null)) { _root = new GameObject("GridSnapOverlay"); int num = LayerMask.NameToLayer("TransparentFX"); if (num != -1) { _root.layer = num; } _root.SetActive(false); CreateLineMaterial(); } } private void CreateLineMaterial() { //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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown if ((Object)(object)_cachedLineMaterial == (Object)null && App1.GridLineColor != null) { Shader val = Shader.Find("Unlit/Color"); if ((Object)(object)val == (Object)null) { ManualLogSource logger = App1.Logger; if (logger != null) { logger.LogWarning((object)"Could not find suitable shader for grid lines"); } return; } _cachedLineMaterial = new Material(val) { color = App1.GridLineColor.Value }; } _lineMaterial = _cachedLineMaterial; } private void ClearLines() { foreach (LineRenderer lineRenderer in _lineRenderers) { if ((Object)(object)lineRenderer != (Object)null && (Object)(object)((Component)lineRenderer).gameObject != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)lineRenderer).gameObject); } } _lineRenderers.Clear(); } private void CreateGridLines() { //IL_00b9: 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_011d: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) if (App1.GridSize == null) { return; } float value = App1.GridSize.Value; if (value <= 0f || App1.GridDisplayExtent == null) { return; } float value2 = App1.GridDisplayExtent.Value; if (App1.GridMajorLineEvery == null) { return; } int value3 = App1.GridMajorLineEvery.Value; int num = Mathf.CeilToInt(value2 * 2f / value); float num2 = 0f - value2; for (int i = 0; i <= num; i++) { float num3 = num2 + (float)i * value; if (!(Mathf.Abs(num3) > value2)) { bool isMajor = i % value3 == 0; CreateLine(new Vector3(num2, 0.01f, num3), new Vector3(value2, 0.01f, num3), isMajor); } } for (int j = 0; j <= num; j++) { float num4 = num2 + (float)j * value; if (!(Mathf.Abs(num4) > value2)) { bool isMajor2 = j % value3 == 0; CreateLine(new Vector3(num4, 0.01f, num2), new Vector3(num4, 0.01f, value2), isMajor2); } } } private void CreateLine(Vector3 start, Vector3 end, bool isMajor) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("GridLine"); Transform transform = val.transform; GameObject? root = _root; transform.SetParent((root != null) ? root.transform : null, false); if ((Object)(object)_root != (Object)null) { val.layer = _root.layer; } LineRenderer val2 = val.AddComponent<LineRenderer>(); if ((Object)(object)_lineMaterial != (Object)null) { ((Renderer)val2).material = _lineMaterial; } if (App1.GridMajorLineWidth != null && App1.GridMinorLineWidth != null) { float startWidth = (val2.endWidth = (isMajor ? App1.GridMajorLineWidth.Value : App1.GridMinorLineWidth.Value)); val2.startWidth = startWidth; } val2.positionCount = 2; val2.SetPosition(0, start); val2.SetPosition(1, end); val2.useWorldSpace = false; val2.numCapVertices = 0; val2.numCornerVertices = 0; _lineRenderers.Add(val2); } public void Cleanup() { ClearLines(); if ((Object)(object)_root != (Object)null) { Object.DestroyImmediate((Object)(object)_root); } if ((Object)(object)_lineMaterial != (Object)null) { Object.DestroyImmediate((Object)(object)_lineMaterial); } } } public class GridSnapInputs : LcInputActions { [InputAction("<Keyboard>/z", Name = "Toggle Grid Snap")] public InputAction ToggleGrid { get; set; } [InputAction("<Keyboard>/equals", Name = "Increase Grid Size")] public InputAction IncreaseGrid { get; set; } [InputAction("<Keyboard>/minus", Name = "Decrease Grid Size")] public InputAction DecreaseGrid { get; set; } [InputAction("<Keyboard>/c", Name = "Toggle Rotation Snap")] public InputAction ToggleRotationSnap { get; set; } [InputAction("<Keyboard>/f1", Name = "Increase Rotation Angle")] public InputAction IncreaseRotationSnapAngle { get; set; } [InputAction("<Keyboard>/f2", Name = "Decrease Rotation Angle")] public InputAction DecreaseRotationSnapAngle { get; set; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }