using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using OCDheim.Utilities; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("OCDheim")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("OCDheim")] [assembly: AssemblyCopyright("Copyright \ufffd 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("0.0.2.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.2.0")] [module: UnverifiableCode] namespace OCDheim { public class GroundLevelSpinner { public static readonly GroundLevelSpinner RaiseGroundSpinner = new GroundLevelSpinner(1f, 0f, 1f); public static readonly GroundLevelSpinner LowerGroundSpinner = new GroundLevelSpinner(-0.5f, -1f, 0f); public float value { get; private set; } private float maxValue { get; } private float minValue { get; } private GroundLevelSpinner(float value, float minValue, float maxValue) { this.value = value; this.minValue = minValue; this.maxValue = maxValue; } public void Refresh() { float num = KeyBinder.ScrollΔ(); if (num > 0f) { Up(num); } if (num < 0f) { Down(num); } } private void Up(float scrollΔ) { if (value + scrollΔ > maxValue) { value = maxValue; } else { value = Mathf.Round((value + scrollΔ) * 100f) / 100f; } } private void Down(float scrollΔ) { if (value + scrollΔ < minValue) { value = minValue; } else { value = Mathf.Round((value + scrollΔ) * 100f) / 100f; } } } [HarmonyPatch] public static class BlockCameraZoom { [HarmonyPrefix] [HarmonyPatch(typeof(ZInput))] [HarmonyPatch("GetMouseScrollWheel")] public static bool Prefix(ref float __result) { if (PlayerHelpers.player.HasRaiseGroundTerraformToolEquipped()) { __result = 0f; return false; } return true; } } [HarmonyPatch] public class KeyBinder : MonoBehaviour { private static readonly ButtonConfig SnapModeKey = new ButtonConfig { Name = "SnapModeKey", Key = (KeyCode)304 }; private static readonly ButtonConfig SnapModeJoy = new ButtonConfig { Name = "SnapModeJoy", GamepadButton = (GamepadButton)10 }; private static readonly ButtonConfig GridModeKey = new ButtonConfig { Name = "GridModeKey", Key = (KeyCode)308 }; private static readonly ButtonConfig GridModeJoy = new ButtonConfig { Name = "GridModeJoy", GamepadButton = (GamepadButton)16 }; private static readonly ButtonConfig PrecisionModeKey = new ButtonConfig { Name = "PrecisionModeKey", Key = (KeyCode)122 }; private static readonly ButtonConfig PrecisionModeJoy = new ButtonConfig { Name = "PrecisionModeJoy", GamepadButton = (GamepadButton)7 }; private const string MouseScrollWheel = "Mouse ScrollWheel"; private const string JoyScrollUnlock = "JoyLTrigger"; private const string JoyScrollDown = "JoyDPadDown"; private const string JoyScrollUp = "JoyDPadUp"; private const float ScrollPrecision = 0.01f; private static bool _gridModeEnabled; private static bool _gridModeFreshlyEnabled; private static bool _gridModeFreshlyDisabled; private static bool snapModeDisabled => ZInput.GetButton(SnapModeKey.Name) || ZInput.GetButton(SnapModeJoy.Name); public static bool snapModeEnabled => !snapModeDisabled; public static bool gridModeEnabled { get { return _gridModeEnabled; } private set { _gridModeEnabled = value; _gridModeFreshlyEnabled = value; _gridModeFreshlyDisabled = !value; } } public static bool gridModeDisabled => !gridModeEnabled; public static bool gridModFreshlyEnabled { get { bool gridModeFreshlyEnabled = _gridModeFreshlyEnabled; _gridModeFreshlyEnabled = false; return gridModeFreshlyEnabled; } } public static bool gridModFreshlyDisabled { get { bool gridModeFreshlyDisabled = _gridModeFreshlyDisabled; _gridModeFreshlyDisabled = false; return gridModeFreshlyDisabled; } } public static PrecisionMode precisionMode { get; private set; } = PrecisionMode.ORDINARY; private void Awake() { InputManager.Instance.AddButton("dymek.dev.OCDheim", SnapModeJoy); InputManager.Instance.AddButton("dymek.dev.OCDheim", SnapModeKey); InputManager.Instance.AddButton("dymek.dev.OCDheim", GridModeKey); InputManager.Instance.AddButton("dymek.dev.OCDheim", GridModeJoy); InputManager.Instance.AddButton("dymek.dev.OCDheim", PrecisionModeKey); InputManager.Instance.AddButton("dymek.dev.OCDheim", PrecisionModeJoy); } private void Update() { bool flag = ((ZInput.GetButtonDown(GridModeKey.Name) || (snapModeEnabled && ZInput.GetButtonDown(GridModeJoy.Name))) && (gridModeEnabled || PlayerHelpers.player.HasConstructionToolEquipped())) || (gridModeEnabled && !PlayerHelpers.player.HasConstructionToolEquipped()); bool flag2 = ((ZInput.GetButtonDown(PrecisionModeKey.Name) || (snapModeEnabled && ZInput.GetButtonDown(PrecisionModeJoy.Name))) && (precisionMode == PrecisionMode.SUPERIOR || PlayerHelpers.player.HasBuildPieceEquipped())) || (precisionMode == PrecisionMode.SUPERIOR && !PlayerHelpers.player.HasBuildPieceEquipped()); if (flag) { gridModeEnabled = !gridModeEnabled; Logger.Info(() => "[" + (gridModeEnabled ? "ENABLED" : "DISABLED") + "] GRID MODE"); } if (flag2) { precisionMode = ((precisionMode != PrecisionMode.ORDINARY) ? PrecisionMode.ORDINARY : PrecisionMode.SUPERIOR); Logger.Info(() => "[" + ((precisionMode == PrecisionMode.SUPERIOR) ? "ENABLED" : "DISABLED") + "] PRECISION MODE"); } } public static float ScrollΔ() { float axis = Input.GetAxis("Mouse ScrollWheel"); if (axis != 0f) { return (axis > 0f) ? 0.01f : (-0.01f); } if (ZInput.GetButton("JoyLTrigger") && ZInput.GetButtonDown("JoyDPadDown")) { return -0.01f; } if (ZInput.GetButton("JoyLTrigger") && ZInput.GetButtonDown("JoyDPadUp")) { return 0.01f; } return axis; } } [HarmonyPatch] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("dymek.dev.OCDheim", "OCDheim", "0.2.0")] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class OCDheim : BaseUnityPlugin { public const string GUID = "dymek.dev.OCDheim"; private const string Name = "OCDheim"; private const string Version = "0.2.0"; public static AssetBundle resourceBundle { get; } = LoadResourceBundle(); private Texture2D brick1x1 { get; } = LoadTextureFromDisk("brick_1x1.png"); private Texture2D brick2x1 { get; } = LoadTextureFromDisk("brick_2x1.png"); private Texture2D brick1x2 { get; } = LoadTextureFromDisk("brick_1x2.png"); private Texture2D brick4x2 { get; } = LoadTextureFromDisk("brick_4x2.png"); private Harmony harmony { get; } = new Harmony("dymek.dev.OCDheim"); private static AssetBundle LoadResourceBundle() { //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_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 RuntimePlatform platform = Application.platform; RuntimePlatform val = platform; if ((int)val <= 2) { if ((int)val <= 1) { return AssetUtils.LoadAssetBundleFromResources(Path.Combine("bundle_osx")); } if ((int)val == 2) { goto IL_002d; } } else { if ((int)val == 7) { goto IL_002d; } if ((int)val == 13 || (int)val == 16) { return AssetUtils.LoadAssetBundleFromResources(Path.Combine("bundle_linux")); } } throw new PlatformNotSupportedException(); IL_002d: return AssetUtils.LoadAssetBundleFromResources(Path.Combine("bundle_windows")); } public static Texture2D LoadTextureFromDisk(string fileName) { string path = Path.GetDirectoryName(typeof(OCDheim).Assembly.Location) ?? throw new InvalidOperationException(); string text = Path.Combine(path, fileName); return AssetUtils.LoadTexture(text, true); } private void Awake() { harmony.PatchAll(); ((Component)this).gameObject.AddComponent(); PrefabManager.OnVanillaPrefabsAvailable += AddOCDheimToolPieces; PrefabManager.OnVanillaPrefabsAvailable += AddOCDheimBuildPieces; PrefabManager.OnVanillaPrefabsAvailable += ModVanillaValheimTools; } [HarmonyPostfix] [HarmonyPatch(typeof(Player))] [HarmonyPatch("OnSpawned")] private static void OnPlayerAvailable() { Refresher.Of(PrecisionDrill.groundLevels); Refresher.Of(PrecisionDrill.floorLevels); } private void AddOCDheimToolPieces() { AddToolPiece("Remove Terrain Modifications", "mud_road_v2", "Hoe", OverlayVisualizer.remove); } private void AddToolPiece(string pieceName, string basePieceName, string pieceTable, Texture2D iconTexture, bool level = false, bool raise = false, bool smooth = false, bool paint = false) where TOverlayVisualizer : OverlayVisualizer { //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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_006d: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown CustomPiece piece = PieceManager.Instance.GetPiece(pieceName); if (piece == null) { Sprite icon = Sprite.Create(iconTexture, new Rect(0f, 0f, (float)((Texture)iconTexture).width, (float)((Texture)iconTexture).height), Vector2.zero); CustomPiece val = new CustomPiece(pieceName, basePieceName, new PieceConfig { Name = pieceName, Icon = icon, PieceTable = pieceTable }); Settings settings = val.PiecePrefab.GetComponent().m_settings; settings.m_level = level; settings.m_raise = raise; settings.m_smooth = smooth; settings.m_paintCleared = paint; val.PiecePrefab.AddComponent(); PieceManager.Instance.AddPiece(val); } } private void AddOCDheimBuildPieces() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_008b: Unknown result type (might be due to invalid IL or missing references) AddBrickBuildPiece("1x1", new Vector3(0.5f, 1f, 0.5f), 3, brick1x1); AddBrickBuildPiece("2x1", new Vector3(1f, 1f, 0.5f), 4, brick2x1); AddBrickBuildPiece("4x2", new Vector3(2f, 2f, 0.5f), 6, brick4x2); AddBrickBuildPiece("1x2", new Vector3(0.5f, 2f, 0.5f), 5, brick1x2); PrefabManager.OnVanillaPrefabsAvailable -= AddOCDheimBuildPieces; } private void AddBrickBuildPiece(string brickSuffix, Vector3 brickScale, int brickPrice, Texture2D iconTexture) { //IL_0060: 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_0076: 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_0084: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown string text = "Smooth stone " + brickSuffix; CustomPiece piece = PieceManager.Instance.GetPiece(text); if (piece == null) { GameObject val = PrefabManager.Instance.CreateClonedPrefab("stone_floor_" + brickSuffix, "stone_floor_2x2"); Sprite icon = Sprite.Create(iconTexture, new Rect(0f, 0f, (float)((Texture)iconTexture).width, (float)((Texture)iconTexture).height), Vector2.zero); val.transform.localScale = brickScale; PieceConfig val2 = new PieceConfig(); val2.Name = text; val2.PieceTable = "Hammer"; val2.Category = "HeavyBuild"; val2.Icon = icon; val2.AddRequirement(new RequirementConfig("Stone", brickPrice, 0, true)); PieceManager.Instance.AddPiece(new CustomPiece(val, false, val2)); } } private void ModVanillaValheimTools() { PrefabManager.Instance.GetPrefab("mud_road_v2").AddComponent(); PrefabManager.Instance.GetPrefab("raise_v2").AddComponent(); PrefabManager.Instance.GetPrefab("path_v2").AddComponent(); PrefabManager.Instance.GetPrefab("paved_road_v2").AddComponent(); PrefabManager.Instance.GetPrefab("cultivate_v2").AddComponent(); PrefabManager.Instance.GetPrefab("replant_v2").AddComponent(); } } [HarmonyPatch] public static class PileUpper { [HarmonyPostfix] [HarmonyPatch(typeof(WearNTear))] [HarmonyPatch("Start")] private static void MakePilesAsDurableAsWood(WearNTear __instance) { if (((Object)__instance).name.Contains("pile") || ((Object)__instance).name.Contains("stack")) { __instance.m_supports = true; } } } [HarmonyPatch] public static class RemoveExpensiveUnnecessaryCalls { private static bool ShouldSuppressVanillaValheim() { return (KeyBinder.gridModeEnabled && PrecisePieceSnapper.GridModeRequirementsSatisfied()) || (KeyBinder.snapModeEnabled && PrecisePieceSnapper.SnapModeRequirementsSatisfied()); } [HarmonyTranspiler] [HarmonyPatch(typeof(Player))] [HarmonyPatch("UpdatePlacementGhost")] private static IEnumerable Transpiler(IEnumerable instructions) { bool foundCodeToRemove = false; bool foundCodeToReplace = false; foreach (CodeInstruction instruction in instructions) { foundCodeToRemove = (foundCodeToRemove ? foundCodeToRemove : (instruction.opcode == OpCodes.Ldstr && (string)instruction.operand == "AltPlace")); if (foundCodeToRemove && !foundCodeToReplace) { foundCodeToReplace = (foundCodeToReplace ? foundCodeToReplace : (instruction.opcode == OpCodes.Call)); if (!foundCodeToReplace) { instruction.opcode = OpCodes.Nop; instruction.operand = null; yield return instruction; continue; } instruction.opcode = OpCodes.Call; instruction.operand = SymbolExtensions.GetMethodInfo((Expression)(() => ShouldSuppressVanillaValheim())); yield return instruction; } else { yield return instruction; } } } } [HarmonyPatch] public static class PrecisePieceSnapper { private const float NeighbourhoodSize = 2.5f; private static readonly int PiecesOnly = LayerMask.GetMask(new string[1] { "piece" }); private static readonly int LayerMask = PlayerHelpers.player.m_placeRayMask - LayerMask.GetMask(new string[1] { "piece_nonsolid" }); private static readonly Collider[] NeighbourColliders = (Collider[])(object)new Collider[255]; private static readonly List NeighbourPieces = new List(); public static bool GridModeRequirementsSatisfied() { return PlayerHelpers.player.HasBuildPieceEquipped() || PlayerHelpers.player.HasOverlayVisible(); } public static bool SnapModeRequirementsSatisfied() { return (Object)(object)PieceHelpers.buildPiece != (Object)null && (PieceHelpers.buildPiece.Type() != 0 || KeyBinder.precisionMode == PrecisionMode.SUPERIOR); } private static bool ShouldUsePlayerPositionAsGroundLevelReference() { return PlayerHelpers.player.HasLevelGroundTerraformToolEquipped() && KeyBinder.snapModeEnabled; } [HarmonyPostfix] [HarmonyPatch(typeof(Player))] [HarmonyPatch("UpdatePlacementGhost")] private static void SnapBuildPiece() { if (KeyBinder.gridModeEnabled && GridModeRequirementsSatisfied()) { SnapToWorldGrid(PieceHelpers.buildPiece); } else if (KeyBinder.snapModeEnabled && SnapModeRequirementsSatisfied()) { SnapToNeighbourPiece(PieceHelpers.buildPiece); } } private static void SnapToWorldGrid(Piece buildPiece) { //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_000d: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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) Vector3 playerPoV = DeterminePlayerPoV(); int precisionMode = (int)KeyBinder.precisionMode; var (num, num2) = SnapToWorldGrid(playerPoV, precisionMode); if (ShouldUsePlayerPositionAsGroundLevelReference()) { ((Component)buildPiece).transform.position = new Vector3(num, PlayerHelpers.playerPos.y, num2); } else { Vector2 drillCoords = default(Vector2); ((Vector2)(ref drillCoords))..ctor(num, num2); Vector3 neighbourPieceExit = ((PlayerHelpers.player.HasOverlayVisible() || buildPiece.IsGroundBound()) ? PrecisionDrill.DrillDownTillGround(drillCoords) : PrecisionDrill.DrillDownTillFloor(drillCoords, ((Component)buildPiece).transform.position.y)); SnapExternallyHelper(buildPiece, neighbourPieceExit, Vector3.up); } if (PlayerHelpers.player.HasOverlayVisible()) { FixVanillaValheimBugWithSpinningTerrainModificationVFX(); } } private static (float xOnGrid, float zOnGrid) SnapToWorldGrid(Vector3 playerPoV, int precision) { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) float item; float item2; if (PlayerHelpers.player.HasColorBrushEquipped()) { float num = Mathf.Floor(playerPoV.x / 64f) * 64f; float num2 = Mathf.Floor(playerPoV.z / 64f) * 64f; float num3 = num - 32f; float num4 = num2 - 32f; float num5 = playerPoV.x - num3; float num6 = playerPoV.z - num4; item = num3 + Mathf.Floor(num5 / (64f / 65f)) * (64f / 65f) + 32f / 65f; item2 = num4 + Mathf.Floor(num6 / (64f / 65f)) * (64f / 65f) + 32f / 65f; } else { item = Mathf.Round(playerPoV.x * (float)precision) / (float)precision; item2 = Mathf.Round(playerPoV.z * (float)precision) / (float)precision; } return (item, item2); } private static void SnapToNeighbourPiece(Piece buildPiece) { //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_0030: Unknown result type (might be due to invalid IL or missing references) Vector3 playerPoV = DeterminePlayerPoV(); List neighbourPieces = FindNeighbourPieces(playerPoV); switch (buildPiece.Type()) { case PieceType.CONSTRUCTION: SnapInternally(buildPiece, neighbourPieces); break; case PieceType.FURNITURE: case PieceType.TABLE: SnapExternally(buildPiece, neighbourPieces, playerPoV); break; } } private static void SnapInternally(Piece buildPiece, List neighbourPieces) { //IL_003b: 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_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_0058: Unknown result type (might be due to invalid IL or missing references) SnapTree.TraversalResult? traversalResult = ((KeyBinder.precisionMode == PrecisionMode.ORDINARY) ? SnapTree.FindNearestOrdinaryPrecisionSnapNodeCombinationOf(buildPiece, neighbourPieces) : SnapTree.FindNearestSuperiorPrecisionSnapNodeCombinationOf(buildPiece, neighbourPieces)); if (traversalResult.HasValue) { SnapTree.TraversalResult valueOrDefault = traversalResult.GetValueOrDefault(); if (true) { Transform transform = ((Component)buildPiece).transform; transform.position += (Vector3)valueOrDefault.neighbourSnapNode - valueOrDefault.buildPieceSnapNode; } } } private static void SnapExternally(Piece buildPiece, List neighbourPieces, Vector3 playerPoV) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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) SnapTree.TraversalResult? traversalResult = ((KeyBinder.precisionMode == PrecisionMode.ORDINARY) ? SnapTree.FindNearestOrdinaryPrecisionSnapNodeTo(playerPoV, neighbourPieces) : SnapTree.FindNearestSuperiorPrecisionSnapNodeTo(playerPoV, neighbourPieces)); if (!traversalResult.HasValue) { return; } SnapTree.TraversalResult valueOrDefault = traversalResult.GetValueOrDefault(); if (true) { var (val, perpendicularToPlayerPoV) = DetermineNeighbourPieceExit(valueOrDefault.neighbourSnapNode, valueOrDefault.neighbourPiece); if (!buildPiece.IsGroundBound()) { SnapExternallyHelper(buildPiece, val, perpendicularToPlayerPoV); } else { ((Component)buildPiece).transform.position = val; } } } private static void SnapExternallyHelper(Piece buildPiece, Vector3 neighbourPieceExit, Vector3 perpendicularToPlayerPoV) { //IL_0007: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_0020: 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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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) ((Component)buildPiece).transform.position = neighbourPieceExit + perpendicularToPlayerPoV * 10f; Vector3 buildPieceExit = DeterminePieceExit(buildPiece, neighbourPieceExit); SnapPiecesByExits(buildPiece, buildPieceExit, neighbourPieceExit, perpendicularToPlayerPoV); } private static (Vector3, Vector3) DetermineNeighbourPieceExit(SnapNode neighbourSnapNode, Piece neighbourPiece) { //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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_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_0024: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) Vector3 snapNode = PokeToMiddle(neighbourSnapNode, neighbourPiece); Vector3 val = DeterminePerpendicularToPlayerPoVOn(snapNode); Vector3 observer = (Vector3)neighbourSnapNode + val; Vector3 item = DeterminePieceExit(neighbourPiece, observer); return (item, val); } private static Vector3 DeterminePlayerPoV() { //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_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_0021: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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) Vector3 position = ((Component)GameCamera.instance).transform.position; Vector3 forward = ((Component)GameCamera.instance).transform.forward; RaycastHit val = default(RaycastHit); Physics.Raycast(position, forward, ref val, 250f, LayerMask); return ((RaycastHit)(ref val)).point; } private static Vector3 DeterminePerpendicularToPlayerPoVOn(Vector3 snapNode) { //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_0011: 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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)GameCamera.instance).transform.position; Vector3 val = snapNode - position; RaycastHit val2 = default(RaycastHit); Physics.Raycast(position, val, ref val2, 250f, LayerMask); return ((RaycastHit)(ref val2)).normal; } private static List FindNeighbourPieces(Vector3 playerPoV) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) NeighbourPieces.Clear(); int num = Physics.OverlapSphereNonAlloc(playerPoV, 2.5f, NeighbourColliders, PiecesOnly); for (int i = 0; i < num; i++) { Collider val = NeighbourColliders[i]; Transform root = ((Component)val).transform.root; Piece val2 = ((root != null) ? ((Component)root).GetComponentInChildren() : null); if ((Object)(object)val2 != (Object)null && val2.Type().IsSnappable()) { NeighbourPieces.Add(val2); } } return NeighbourPieces; } private static Vector3 DeterminePieceExit(Piece piece, Vector3 observer) { //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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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) //IL_0075: 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_008c: Unknown result type (might be due to invalid IL or missing references) float num = float.PositiveInfinity; Vector3 result = ((Component)piece).transform.position; Collider[] componentsInChildren = ((Component)piece).GetComponentsInChildren(); Collider[] array = componentsInChildren; foreach (Collider val in array) { if (!val.enabled || val.isTrigger) { continue; } MeshCollider val2 = (MeshCollider)(object)((val is MeshCollider) ? val : null); if ((Object)(object)val2 == (Object)null || val2.convex) { Vector3 val3 = val.ClosestPoint(observer); float num2 = Vector3.Distance(observer, val3); if (num2 < num) { result = val3; num = num2; } } } return result; } private static Vector3 PokeToMiddle(Vector3 snapNode, Piece piece) { //IL_0007: 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_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_0015: 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_0024: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)piece).transform.position - snapNode; Vector3 val2 = ((Vector3)(ref val)).normalized * 0.05f; return snapNode + val2; } private static void SnapPiecesByExits(Piece buildPiece, Vector3 buildPieceExit, Vector3 neighbourPieceEntry, Vector3 perpendicularToNeighbourPiece) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: 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_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) Vector3 val = neighbourPieceEntry - buildPieceExit; Vector3 val2 = Vector3.Project(val, perpendicularToNeighbourPiece); Transform transform = ((Component)buildPiece).transform; transform.position += val2; } private static void FixVanillaValheimBugWithSpinningTerrainModificationVFX() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) ((Component)PieceHelpers.buildPiece).transform.rotation = Quaternion.Euler(0f, 0f, 0f); } } [HarmonyPatch] public static class PreciseTerrainModifier { private const int AoESize = 1; public const int HTilesPerChunk = 64; private const int PTilesPerChunk = 65; public const float HalfPTilesPerChunk = 32f; public const float PTileSize = 64f / 65f; [HarmonyPrefix] [HarmonyPatch(typeof(TerrainComp))] [HarmonyPatch("InternalDoOperation")] private static bool Prefix(Vector3 pos, Settings modifier, Heightmap ___m_hmap, ref float[] ___m_levelDelta, ref float[] ___m_smoothDelta, ref Color[] ___m_paintMask, ref bool[] ___m_modifiedHeight, ref bool[] ___m_modifiedPaint) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (!modifier.m_level && !modifier.m_raise && !modifier.m_smooth && !modifier.m_paintCleared) { RemoveTerrainModifications(pos, ___m_hmap, ref ___m_levelDelta, ref ___m_smoothDelta, ref ___m_modifiedHeight); RecolorTerrain(pos, (PaintType)3, ___m_hmap, ref ___m_paintMask, ref ___m_modifiedPaint); } return true; } public static void SmoothenTerrain(Vector3 worldPos, Heightmap hMap, TerrainComp compiler, ref float[] smoothΔ, ref bool[] modifiedHeight) { //IL_0007: 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_0035: 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) Logger.Debug(() => "[INIT] Smooth Terrain Modification"); int xPos = default(int); int yPos = default(int); hMap.WorldToVertex(worldPos, ref xPos, ref yPos); float referenceH = worldPos.y - ((Component)compiler).transform.position.y; Logger.Debug(() => $"worldPos: {worldPos}, xPos: {xPos}, yPos: {yPos}, referenceH: {referenceH}"); FindExtremums(xPos, out var minVal, out var maxVal); FindExtremums(yPos, out var minVal2, out var maxVal2); for (int x = minVal; x <= maxVal; x++) { for (int y = minVal2; y <= maxVal2; y++) { int num = y * 65 + x; float tileH = hMap.GetHeight(x, y); float Δh = referenceH - tileH; float oldΔh = smoothΔ[num]; float newΔh = oldΔh + Δh; float roundedNewΔh = RoundToTwoDecimals(tileH, oldΔh, newΔh); float limΔh = Mathf.Clamp(roundedNewΔh, -1f, 1f); smoothΔ[num] = limΔh; modifiedHeight[num] = true; Logger.Debug(() => $"tilePos: ({x}, {y}), tileH: {tileH}, Δh: {Δh}, oldΔh: {oldΔh}, newΔh: {newΔh}, roundedNewΔh: {roundedNewΔh}, limΔh: {limΔh}"); } } Logger.Debug(() => "[SUCCESS] Smooth Terrain Modification"); } public static void RaiseTerrain(Vector3 worldPos, Heightmap hMap, TerrainComp compiler, float power, ref float[] levelΔ, ref float[] smoothΔ, ref bool[] modifiedHeight) { //IL_0007: 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_003c: 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) Logger.Debug(() => "[INIT] Raise Terrain Modification"); int xPos = default(int); int yPos = default(int); hMap.WorldToVertex(worldPos, ref xPos, ref yPos); float referenceH = worldPos.y - ((Component)compiler).transform.position.y + power; Logger.Debug(() => $"worldPos: {worldPos}, xPos: {xPos}, yPos: {yPos}, power: {power}, referenceH: {referenceH}"); FindExtremums(xPos, out var minVal, out var maxVal); FindExtremums(yPos, out var minVal2, out var maxVal2); for (int x = minVal; x <= maxVal; x++) { for (int y = minVal2; y <= maxVal2; y++) { int num = y * 65 + x; float tileH = hMap.GetHeight(x, y); float Δh = referenceH - tileH; if (Δh >= 0f) { float oldLevelΔ = levelΔ[num]; float oldSmoothΔ = smoothΔ[num]; float newLevelΔ = oldLevelΔ + oldSmoothΔ + Δh; float newSmoothΔ = 0f; float roundedNewLevelΔ = RoundToTwoDecimals(tileH, oldLevelΔ + oldSmoothΔ, newLevelΔ + newSmoothΔ); float limitedNewLevelΔ = Mathf.Clamp(roundedNewLevelΔ, -16f, 16f); levelΔ[num] = limitedNewLevelΔ; smoothΔ[num] = newSmoothΔ; modifiedHeight[num] = true; Logger.Debug(() => $"tilePos: ({x}, {y}), tileH: {tileH}, Δh: {Δh}, oldLevelΔ: {oldLevelΔ}, oldSmoothΔ: {oldSmoothΔ}, newLevelΔ: {newLevelΔ}, newSmoothΔ: {newSmoothΔ}, roundedNewLevelΔ: {roundedNewLevelΔ}, limitedNewLevelΔ: {limitedNewLevelΔ}"); } else { Logger.Debug(() => "Declined to process tile: Δh < 0!"); Logger.Debug(() => $"tilePos: ({x}, {y}), tileH: {tileH}, Δh: {Δh}"); } } } Logger.Debug(() => "[SUCCESS] Raise Terrain Modification"); } public static void RecolorTerrain(Vector3 worldPos, PaintType paintType, Heightmap hMap, ref Color[] paintMask, ref bool[] modifiedPaint) { //IL_0007: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) Logger.Info(() => "[INIT] Color Terrain Modification 3x3"); Color tileColor = ResolveColor(paintType); PositionRelativeTo(((Component)hMap).transform.position, worldPos, out var xPos, out var yPos); Logger.Info(() => $"worldPos: {worldPos}, chunkPos: {((Component)hMap).transform.position}, relPos: ({xPos}, {yPos})"); FindExtremums(xPos, out var minVal, out var maxVal); FindExtremums(yPos, out var minVal2, out var maxVal2); for (int i = minVal; i <= maxVal; i++) { for (int j = minVal2; j <= maxVal2; j++) { ApplyColor(i, j, tileColor, ref paintMask, ref modifiedPaint); } } Logger.Info(() => "[SUCCESS] Color Terrain Modification 3x3"); } private static void RemoveTerrainModifications(Vector3 worldPos, Heightmap hMap, ref float[] levelΔ, ref float[] smoothΔ, ref bool[] modifiedHeight) { //IL_0007: 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_0035: Unknown result type (might be due to invalid IL or missing references) Logger.Debug(() => "[INIT] Remove Terrain Modifications"); int xPos = default(int); int yPos = default(int); hMap.WorldToVertex(worldPos, ref xPos, ref yPos); Logger.Debug(() => $"worldPos: {worldPos}, vertexPos: ({xPos}, {yPos})"); FindExtremums(xPos, out var minVal, out var maxVal); FindExtremums(yPos, out var minVal2, out var maxVal2); for (int x = minVal; x <= maxVal; x++) { for (int y = minVal2; y <= maxVal2; y++) { int tileIndex = y * 65 + x; levelΔ[tileIndex] = 0f; smoothΔ[tileIndex] = 0f; modifiedHeight[tileIndex] = false; Logger.Debug(() => $"tilePos: ({x}, {y}), tileIndex: {tileIndex}"); } } Logger.Debug(() => "[SUCCESS] Remove Terrain Modifications"); } private static void FindExtremums(int val, out int minVal, out int maxVal) { minVal = Mathf.Max(0, val - 1); maxVal = Mathf.Min(val + 1, 64); } private static float RoundToTwoDecimals(float oldH, float oldΔh, float newΔh) { float newH = oldH - oldΔh + newΔh; float roundedNewH = Mathf.Round(newH * 100f) / 100f; float roundedNewΔh = roundedNewH - oldH + oldΔh; Logger.Debug(() => $"oldH: {oldH}, oldΔH: {oldΔh}, newΔH: {newΔh}, newH: {newH}, roundedNewH: {roundedNewH}, roundedNewΔh: {roundedNewΔh}"); return roundedNewΔh; } private static void PositionRelativeTo(Vector3 chunkMid, Vector3 worldPos, out int x, out int y) { //IL_0001: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_0025: 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) Vector3 val = chunkMid - new Vector3(32f, 0f, 32f); Vector3 val2 = worldPos - val; x = Mathf.FloorToInt(val2.x / (64f / 65f)); y = Mathf.FloorToInt(val2.z / (64f / 65f)); } private static Color ResolveColor(PaintType paintType) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected I4, but got Unknown //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_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_0039: 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) //IL_0036: Unknown result type (might be due to invalid IL or missing references) return (Color)((int)paintType switch { 0 => Color.red, 2 => Color.blue, 1 => Color.green, _ => Color.black, }); } private static void ApplyColor(int x, int y, Color tileColor, ref Color[] paintMask, ref bool[] modifiedPaint) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //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_0054: Unknown result type (might be due to invalid IL or missing references) int tileIndex = y * 65 + x; paintMask[tileIndex] = tileColor; modifiedPaint[tileIndex] = tileColor != Color.black; Logger.Info(() => $"tilePos: ({x}, {y}), tileIndex: {tileIndex}, tileColor: {tileColor}"); } } [HarmonyPatch] public static class PreciseSmoothTerrainModification { [HarmonyPrefix] [HarmonyPatch(typeof(TerrainComp))] [HarmonyPatch("SmoothTerrain")] private static bool Prefix(Vector3 worldPos, float radius, bool square, float power, TerrainComp __instance, Heightmap ___m_hmap, ref float[] ___m_smoothDelta, ref bool[] ___m_modifiedHeight) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (ClientSideGridModeOverride.IsGridModeEnabled(radius)) { PreciseTerrainModifier.SmoothenTerrain(worldPos, ___m_hmap, __instance, ref ___m_smoothDelta, ref ___m_modifiedHeight); return false; } return true; } } [HarmonyPatch] public static class PreciseRaiseTerrainModification { [HarmonyPrefix] [HarmonyPatch(typeof(TerrainComp))] [HarmonyPatch("RaiseTerrain")] private static bool Prefix(Vector3 worldPos, float radius, float delta, bool square, float power, TerrainComp __instance, Heightmap ___m_hmap, ref float[] ___m_levelDelta, ref float[] ___m_smoothDelta, ref bool[] ___m_modifiedHeight) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (ClientSideGridModeOverride.IsGridModeEnabled(radius)) { PreciseTerrainModifier.RaiseTerrain(worldPos, ___m_hmap, __instance, delta, ref ___m_levelDelta, ref ___m_smoothDelta, ref ___m_modifiedHeight); return false; } return true; } } [HarmonyPatch] public static class PreciseColorTerrainModification { [HarmonyPrefix] [HarmonyPatch(typeof(TerrainComp))] [HarmonyPatch("PaintCleared")] private static bool Prefix(Vector3 worldPos, float radius, PaintType paintType, bool heightCheck, bool apply, Heightmap ___m_hmap, ref Color[] ___m_paintMask, ref bool[] ___m_modifiedPaint) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (ClientSideGridModeOverride.IsGridModeEnabled(radius)) { PreciseTerrainModifier.RecolorTerrain(worldPos, paintType, ___m_hmap, ref ___m_paintMask, ref ___m_modifiedPaint); return false; } return true; } } [HarmonyPatch] public static class ClientSideGridModeOverride { [HarmonyPrefix] [HarmonyPatch(typeof(TerrainComp))] [HarmonyPatch("ApplyOperation")] private static bool Prefix(TerrainOp modifier) { if (KeyBinder.gridModeEnabled) { if (modifier.m_settings.m_smooth) { modifier.m_settings.m_smoothRadius = float.NegativeInfinity; } if (modifier.m_settings.m_raise && modifier.m_settings.m_raiseDelta >= 0f) { modifier.m_settings.m_raiseRadius = float.NegativeInfinity; modifier.m_settings.m_raiseDelta = GroundLevelSpinner.RaiseGroundSpinner.value; } if (modifier.m_settings.m_raise && modifier.m_settings.m_raiseDelta < 0f) { modifier.m_settings.m_raiseDelta = GroundLevelSpinner.LowerGroundSpinner.value; } if (modifier.m_settings.m_paintCleared) { modifier.m_settings.m_paintRadius = float.NegativeInfinity; } } return true; } public static bool IsGridModeEnabled(float radius) { return float.IsNegativeInfinity(radius); } } public static class PrecisionDrill { public const float DropFromExosphere = 250f; private const int MaxDrillsInMemory = 4096; private const float DrillSize = 0.01f; private static readonly int GroundLayerMask = LayerMask.GetMask(new string[1] { "terrain" }); private static readonly int FloorLayerMask = LayerMask.GetMask(new string[3] { "terrain", "piece", "static_solid" }); private static Func roundDrillCoords => (Vector2 drillCoords) => new Vector2(Mathf.Round(drillCoords.x * 10f) / 10f, Mathf.Round(drillCoords.y * 10f) / 10f); public static IRefreshableMemoryRepo groundLevels => new MemoryRepo(DrillDownToGround, 4096).EvictionPolicy(TimeSpan.FromMilliseconds(125.0)); public static IRefreshableMemoryRepo> floorLevels => new MemoryRepo>((Vector2 drillCoords) => DrillDownFloors(drillCoords), roundDrillCoords, 4096).EvictionPolicy(TimeSpan.FromMilliseconds(500.0)); public static Vector3 DrillDownTillGround(Vector2 drillCoords) { //IL_0005: 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) return groundLevels.LookUp(drillCoords); } private static Vector3 DrillDownToGround(Vector2 drillCoords) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: 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_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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_002f: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) Vector3 val = WhereToDrillFrom(drillCoords); RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, Vector3.down, ref val2, 250f, GroundLayerMask)) { return ((RaycastHit)(ref val2)).point; } return FallBack(drillCoords); } private static Vector3 WhereToDrillFrom(Vector2 drillCoords) { //IL_0000: 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_0011: Unknown result type (might be due to invalid IL or missing references) return new Vector3(drillCoords.x, 250f, drillCoords.y); } private static Vector3 FallBack(Vector2 drillCoords) { //IL_0007: 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_0035: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) Logger.Warn(() => $"[FAILED] Precision Drill for: {drillCoords}"); return new Vector3(drillCoords.x, ((Component)PlayerHelpers.player).transform.position.y, drillCoords.y); } public static Vector3 DrillDownTillFloor(Vector2 drillCoords, float referenceLevel) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_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_0081: Unknown result type (might be due to invalid IL or missing references) List list = floorLevels.LookUp(drillCoords); float num = list[0]; float num2 = Math.Abs(referenceLevel - num); foreach (float item in list) { float num3 = Math.Abs(referenceLevel - item); if (num3 < num2) { num2 = num3; num = item; } } return new Vector3(drillCoords.x, num, drillCoords.y); } private static List DrillDownFloors(Vector2 drillCoords, float drillTill = 250f) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) Vector3 val = WhereToDrillFrom(drillCoords); List list = new List(); float roofLevel = val.y; RaycastHit val2 = default(RaycastHit); while (Physics.SphereCast(val, 0.01f, Vector3.down, ref val2, drillTill, FloorLayerMask)) { float y = ((RaycastHit)(ref val2)).point.y; if (!ShouldSkipDueToInsufficientSize(((RaycastHit)(ref val2)).collider) && !ShouldSkipDueToInsufficientRoom(y, roofLevel)) { list.Add(y); } val.y -= ((RaycastHit)(ref val2)).distance + 0.0001f; drillTill -= ((RaycastHit)(ref val2)).distance + 0.0001f; roofLevel = y; } return list; } private static bool ShouldSkipDueToInsufficientSize(Collider collider) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) Piece componentInChildren = ((Component)((Component)collider).transform.root).GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null) { return false; } Bounds bounds = collider.bounds; return ((Bounds)(ref bounds)).max.x - ((Bounds)(ref bounds)).min.x < 0.5f || ((Bounds)(ref bounds)).max.z - ((Bounds)(ref bounds)).min.z < 0.5f; } private static bool ShouldSkipDueToInsufficientRoom(float floorLevel, float roofLevel) { return roofLevel - floorLevel < 0.5f; } } public enum PrecisionMode { ORDINARY = 1, SUPERIOR } public readonly struct Box : ISide { private const double Epsilon = 1E-08; private char name { get; } private Vector3 minMinSnapNode { get; } private Vector3 minMaxSnapNode { get; } private Vector3 maxMinSnapNode { get; } private Vector3 maxMaxSnapNode { get; } private SnapNode.Type primarySnapNodeType { get; } public Box(char name, Vector3 minMinSnapNode, Vector3 minMaxSnapNode, Vector3 maxMinSnapNode, Vector3 maxMaxSnapNode) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) this.name = name; this.minMinSnapNode = minMinSnapNode; this.minMaxSnapNode = minMaxSnapNode; this.maxMinSnapNode = maxMinSnapNode; this.maxMaxSnapNode = maxMaxSnapNode; primarySnapNodeType = SnapNode.Type.PRIMARY; } public Box(Piece piece, Vector2 shift, char name = 'A') { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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_0017: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_0071: 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) //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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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_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_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_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) this.name = name; Vector3 val = piece.TopMiddle(); minMinSnapNode = val + ((Component)piece).transform.rotation * new Vector3(0f - shift.x, 0f, 0f - shift.y); minMaxSnapNode = val + ((Component)piece).transform.rotation * new Vector3(0f - shift.x, 0f, shift.y); maxMinSnapNode = val + ((Component)piece).transform.rotation * new Vector3(shift.x, 0f, 0f - shift.y); maxMaxSnapNode = val + ((Component)piece).transform.rotation * new Vector3(shift.x, 0f, shift.y); primarySnapNodeType = SnapNode.Type.IMPOSED; } public void FillUp(HashSet snapNodes) { //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_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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_0024: 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_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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) Vector3 dimensionΔ = minMaxSnapNode - minMinSnapNode; Vector3 dimensionΔ2 = maxMinSnapNode - minMinSnapNode; (Vector3, int) tuple = RecursiveSplit(dimensionΔ); Vector3 item = tuple.Item1; int item2 = tuple.Item2; (Vector3, int) tuple2 = RecursiveSplit(dimensionΔ2); Vector3 item3 = tuple2.Item1; int item4 = tuple2.Item2; double num = Math.Pow(2.0, item2) + 1.0; double num2 = Math.Pow(2.0, item4) + 1.0; for (int i = 0; (double)i < num; i++) { for (int j = 0; (double)j < num2; j++) { Vector3 position = minMinSnapNode + item * (float)i + item3 * (float)j; if ((i == 0 || Math.Abs((double)i - (num - 1.0)) < 1E-08) && (j == 0 || Math.Abs((double)j - (num2 - 1.0)) < 1E-08)) { snapNodes.Add(new SnapNode(position, primarySnapNodeType, SnapNode.Precision.ORDINARY)); } else if ((float)i % 2f == 0f && (float)j % 2f == 0f) { snapNodes.Add(new SnapNode(position, SnapNode.Type.DERIVED, SnapNode.Precision.ORDINARY)); } else { snapNodes.Add(new SnapNode(position, SnapNode.Type.DERIVED, SnapNode.Precision.SUPERIOR)); } } } } private (Vector3, int) RecursiveSplit(Vector3 dimensionΔ, int splitLevel = 0) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (((Vector3)(ref dimensionΔ)).magnitude > 0.75f) { return RecursiveSplit(dimensionΔ * 0.5f, ++splitLevel); } return (dimensionΔ, splitLevel); } public override string ToString() { //IL_001c: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) return $"Box {name}: ({minMinSnapNode}, {minMaxSnapNode}, {maxMinSnapNode}, {maxMaxSnapNode})"; } } public readonly struct Circle : ISide { private const int CircleDivisions = 8; private char name { get; } private Vector3 midSnapNode { get; } private Vector2 radial { get; } public Circle(Piece piece, Vector2 radial, char name = 'A') { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_0016: Unknown result type (might be due to invalid IL or missing references) this.name = name; this.radial = radial; midSnapNode = piece.TopMiddle(); } public void FillUp(HashSet snapNodes) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_0028: 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_0032: 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_003a: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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_0069: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < 8; i++) { Vector3 val = Quaternion.Euler(new Vector3(0f, 45f * (float)i, 0f)) * Vector2.op_Implicit(radial); Vector3 val2 = midSnapNode + val; snapNodes.Add(new SnapNode(midSnapNode, SnapNode.Type.IMPOSED, SnapNode.Precision.ORDINARY)); snapNodes.Add(new SnapNode(val2, SnapNode.Type.IMPOSED, SnapNode.Precision.ORDINARY)); SnapNode.RecursiveSplit(midSnapNode, val2, snapNodes); } } public override string ToString() { //IL_0011: 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) return $"Circle {name}: {midSnapNode} + {radial} * quaternion rotation"; } } public interface ISide { void FillUp(HashSet snapNodes); } public readonly struct Line : ISide { private char name { get; } private Vector3 minSnapNode { get; } private Vector3 maxSnapNode { get; } public void FillUp(HashSet snapNodes) { //IL_0001: 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) SnapNode.RecursiveSplit(minSnapNode, maxSnapNode, snapNodes); } public Line(char name, Vector3 minSnapNode, Vector3 maxSnapNode) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_0011: Unknown result type (might be due to invalid IL or missing references) this.name = name; this.minSnapNode = minSnapNode; this.maxSnapNode = maxSnapNode; } public override string ToString() { //IL_0011: 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) return $"Line {name}: ({minSnapNode}, {maxSnapNode})"; } } public readonly struct SnapNode : IEquatable { public enum Type { PRIMARY, IMPOSED, DERIVED } public enum Precision { ORDINARY, SUPERIOR } public const float OrdinaryPrecisionSplitThreshold = 1.5f; public const float SuperiorPrecisionMultiplier = 2f; public Precision precision { get; } private Vector3 position { get; } private Type type { get; } private static bool ShouldSplitInOrdinaryPrecisionMode(Vector3 prevSnapNode, Vector3 nextSnapNode) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return Vector3.Distance(prevSnapNode, nextSnapNode) > 1.5f; } private static bool ShouldSplitInSuperiorPrecisionMode(Vector3 prevSnapNode, Vector3 nextSnapNode) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return Vector3.Distance(prevSnapNode, nextSnapNode) > 0.75f; } public SnapNode(Vector3 position, Type type, Precision precision) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) this.position = position; this.type = type; this.precision = precision; } public static void RecursiveSplit(Vector3 snapNodeA, Vector3 snapNodeB, HashSet snapNodes) { //IL_0002: 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_001f: 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) snapNodes.Add(new SnapNode(snapNodeA, Type.PRIMARY, Precision.ORDINARY)); snapNodes.Add(new SnapNode(snapNodeB, Type.PRIMARY, Precision.ORDINARY)); RecursiveSplitInOrdinaryPrecisionMode(snapNodeA, snapNodeB, snapNodes); } private static void RecursiveSplitInOrdinaryPrecisionMode(Vector3 snapNodeA, Vector3 snapNodeB, HashSet snapNodes, int splitLevel = 0) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_0063: 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_006f: 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) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) if (ShouldSplitInOrdinaryPrecisionMode(snapNodeA, snapNodeB)) { Vector3 midSnapNode = (snapNodeA + snapNodeB) * 0.5f; snapNodes.Add(new SnapNode(midSnapNode, Type.DERIVED, Precision.ORDINARY)); Logger.Debug(delegate { //IL_0036: 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_0057: Unknown result type (might be due to invalid IL or missing references) object[] array = new object[4]; int num = splitLevel; splitLevel = num + 1; array[0] = num; array[1] = snapNodeA; array[2] = snapNodeB; array[3] = midSnapNode; return string.Format("[SPLIT LEVEL {0}] Ordinary Precision Child of: {1} & {2}, is: {3}", array); }); RecursiveSplitInOrdinaryPrecisionMode(snapNodeA, midSnapNode, snapNodes, splitLevel); RecursiveSplitInOrdinaryPrecisionMode(midSnapNode, snapNodeB, snapNodes, splitLevel); } else { RecursiveSplitInSuperiorPrecisionMode(snapNodeA, snapNodeB, snapNodes, splitLevel); } } private static void RecursiveSplitInSuperiorPrecisionMode(Vector3 snapNodeA, Vector3 snapNodeB, HashSet snapNodes, int splitLevel) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_0063: 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_006f: 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) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) if (ShouldSplitInSuperiorPrecisionMode(snapNodeA, snapNodeB)) { Vector3 midSnapNode = (snapNodeA + snapNodeB) * 0.5f; snapNodes.Add(new SnapNode(midSnapNode, Type.DERIVED, Precision.SUPERIOR)); Logger.Debug(delegate { //IL_0036: 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_0057: Unknown result type (might be due to invalid IL or missing references) object[] array = new object[4]; int num = splitLevel; splitLevel = num + 1; array[0] = num; array[1] = snapNodeA; array[2] = snapNodeB; array[3] = midSnapNode; return string.Format("[SPLIT LEVEL {0}] Superior Precision Child of: {1} & {2}, is: {3}", array); }); RecursiveSplitInSuperiorPrecisionMode(snapNodeA, midSnapNode, snapNodes, splitLevel); RecursiveSplitInSuperiorPrecisionMode(midSnapNode, snapNodeB, snapNodes, splitLevel); } } public static implicit operator Vector3(SnapNode snapNode) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return snapNode.position; } public override string ToString() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) return $"{type} Snap Node of {precision} precision: {position}"; } public override bool Equals(object other) { return other is SnapNode snapNode && snapNode.Equals(this); } public bool Equals(SnapNode snapNode) { //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) return snapNode.position == position; } public override int GetHashCode() { //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) Vector3 val = position; return ((object)(Vector3)(ref val)).GetHashCode(); } } public readonly struct SnapTree { public struct TraversalResult { public Vector3 buildPieceSnapNode { get; } public SnapNode neighbourSnapNode { get; } public Piece neighbourPiece { get; } public TraversalResult(Vector3 buildPieceSnapNode, SnapNode neighbourSnapNode, Piece neighbourPiece) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) this.buildPieceSnapNode = buildPieceSnapNode; this.neighbourSnapNode = neighbourSnapNode; this.neighbourPiece = neighbourPiece; } } private const int ZeroSidesAllowed = 0; private const int OneSideAllowed = 1; private const int SidesOfCube = 6; private const int SidesOfOctagon = 10; private const float SnapThreshold = 1f; private static readonly List Boxes = new List(6); private static readonly List Lines = new List(10); private static readonly List Sides = new List(1); private static readonly List HorribleOptimization = new List(1); private static readonly HashSet ZeroSnapNodes = new HashSet(0); private static readonly IMemoryRepo SnapTrees = new MemoryRepo((Piece piece) => new SnapTree(piece), 1024); private static readonly Func OrdinaryPrecisionOnly = (SnapNode.Precision precision) => precision == SnapNode.Precision.ORDINARY; private static readonly Func OrdinaryAndSuperiorPrecision = (SnapNode.Precision precision) => precision == SnapNode.Precision.ORDINARY || precision == SnapNode.Precision.SUPERIOR; private HashSet snapNodes { get; } private static bool FormValidTwoDimensionalBoxSide(Vector3 snapNodeA, Vector3 snapNodeB, Vector3 snapNodeC, Vector3 snapNodeD) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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_001a: 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) return snapNodeA != snapNodeB && snapNodeA != snapNodeC && snapNodeB + snapNodeC - snapNodeA == snapNodeD; } private static Func FormValidThreeDimensionalBoxSide(Piece piece) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) Vector3 pieceMid = ((Component)piece).transform.position; return delegate(Vector3 snapNodeA, Vector3 snapNodeB, Vector3 snapNodeC, Vector3 snapNodeD) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //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) Vector3 val = (snapNodeA + snapNodeD) * 0.5f; return FormValidTwoDimensionalBoxSide(snapNodeA, snapNodeB, snapNodeC, snapNodeD) && pieceMid != val; }; } private static bool LiesOnVerticalMiddle(Vector3 snapNode, Piece piece) { //IL_0000: 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) return Mathf.Approximately(snapNode.x, ((Component)piece).transform.position.y); } private static bool LiesOnHorizontalMiddle(Vector3 snapNode, Piece piece) { //IL_0000: 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_001d: 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) return Mathf.Approximately(snapNode.x, ((Component)piece).transform.position.x) && Mathf.Approximately(snapNode.z, ((Component)piece).transform.position.z); } private static bool LiesOnSameVerticalSide(Vector3 snapNodeA, Vector3 snapNodeB) { //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_0013: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) return Mathf.Approximately(snapNodeA.x, snapNodeB.x) && !Mathf.Approximately(snapNodeA.y, snapNodeB.y) && Mathf.Approximately(snapNodeA.z, snapNodeB.z); } private static bool LiesOnSameHorizontalSide(Vector3 snapNodeA, Vector3 snapNodeB) { //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) return !Mathf.Approximately(snapNodeA.y, snapNodeB.y); } private SnapTree(Piece piece) { Logger.Debug(() => $"[INIT] SNAP TREE CONSTRUCTION of piece: '{piece.m_name}' {((Component)piece).transform.position}"); snapNodes = DeriveSnapNodesFrom(piece); SnapTree tree = this; Logger.Debug(() => "SNAP NODES: " + string.Join(", ", tree.snapNodes)); Logger.Debug(() => $"[SUCCESS] SNAP TREE CONSTRUCTION of piece: '{piece.m_name}' {((Component)piece).transform.position}"); } public static TraversalResult? FindNearestOrdinaryPrecisionSnapNodeTo(Vector3 referencePosition, List pieces) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return FindNearestSnapNodeTo(referencePosition, pieces, OrdinaryPrecisionOnly); } public static TraversalResult? FindNearestSuperiorPrecisionSnapNodeTo(Vector3 referencePosition, List pieces) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return FindNearestSnapNodeTo(referencePosition, pieces, OrdinaryAndSuperiorPrecision); } public static TraversalResult? FindNearestOrdinaryPrecisionSnapNodeCombinationOf(Piece buildPiece, List neighbourPieces) { return FindNearestSnapNodeTo(buildPiece.PrimarySnapNodes(), neighbourPieces, OrdinaryPrecisionOnly); } public static TraversalResult? FindNearestSuperiorPrecisionSnapNodeCombinationOf(Piece buildPiece, List neighbourPieces) { return FindNearestSnapNodeTo(buildPiece.PrimarySnapNodes(), neighbourPieces, OrdinaryAndSuperiorPrecision); } private static HashSet DeriveSnapNodesFrom(Piece piece) { switch (piece.Type()) { case PieceType.CONSTRUCTION: switch (piece.Shape()) { case PieceShape.LINE: return DeriveSnapNodesFrom(piece, DeriveLineFrom); case PieceShape.BOX: return DeriveSnapNodesFrom(piece, DeriveBoxFrom); case PieceShape.CUBE: return DeriveSnapNodesFrom(piece, DeriveSidesFromCube); case PieceShape.CYLINDER: return DeriveSnapNodesFrom(piece, DeriveSidesFromCylinder); case PieceShape.UNDEFINED: return DeriveSnapNodesFrom(piece, DeriveSidesFromUndefined); } break; case PieceType.FURNITURE: return ZeroSnapNodes; case PieceType.TABLE: return DeriveSnapNodesFrom(piece, ImposeTopSideOn); } throw new InvalidOperationException("This is supposedly mathematically impossible :D"); } private static HashSet DeriveSnapNodesFrom(Piece piece, Func> deriveSidesFrom) where T : ISide { List sides = deriveSidesFrom(piece); Logger.Debug(() => "SIDES: " + string.Join(", ", sides)); HashSet result = new HashSet(255); foreach (T item in sides) { item.FillUp(result); } return result; } private static List DeriveLineFrom(Piece piece) { List sides = DeriveSidesFromUndefined(piece); if (sides.Count != 1) { Logger.Warn(() => $"EXPECTED SIDES on Piece '{piece.m_name}' {((Component)piece).transform.position}: {1}, ACTUAL SIDES: {sides.Count}"); } return sides; } private static List DeriveBoxFrom(Piece piece) { return FindSidesOfBoxOrCube(piece, FormValidTwoDimensionalBoxSide, 1); } private static List DeriveSidesFromCube(Piece piece) { return FindSidesOfBoxOrCube(piece, FormValidThreeDimensionalBoxSide(piece), 6); } private static List FindSidesOfBoxOrCube(Piece piece, Func isValidSide, int numberOfSides) { //IL_005a: 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_006a: 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_0090: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) Boxes.Clear(); char c = 'A'; List list = piece.PrimarySnapNodes(); for (int i = 0; i < list.Count; i++) { for (int j = i + 1; j < list.Count; j++) { for (int k = j + 1; k < list.Count; k++) { for (int l = k + 1; l < list.Count; l++) { if (isValidSide(list[i], list[j], list[k], list[l])) { Boxes.Add(new Box(c++, list[i], list[j], list[k], list[l])); } } } } } if (Boxes.Count != numberOfSides) { Logger.Warn(() => $"EXPECTED SIDES on Piece '{piece.m_name}' {((Component)piece).transform.position}: {numberOfSides}, ACTUAL SIDES: {Boxes.Count}"); } return Boxes; } private static List DeriveSidesFromCylinder(Piece piece) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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_00dd: 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_00cc: 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_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) Lines.Clear(); char c = 'A'; for (int i = 0; i < piece.PrimarySnapNodes().Count; i++) { Vector3 val = piece.PrimarySnapNodes()[i]; if (LiesOnHorizontalMiddle(val, piece)) { continue; } for (int j = i + 1; j < piece.PrimarySnapNodes().Count; j++) { Vector3 val2 = piece.PrimarySnapNodes()[j]; if (!LiesOnHorizontalMiddle(val2, piece)) { Vector3 snapNode = (val + val2) * 0.5f; if (LiesOnSameVerticalSide(val, val2) && !LiesOnHorizontalMiddle(snapNode, piece)) { Lines.Add(new Line(c++, val, val2)); } else if (LiesOnSameHorizontalSide(val, val2) && LiesOnHorizontalMiddle(snapNode, piece)) { Lines.Add(new Line(c++, val, val2)); } } } } if (Lines.Count != 10) { Logger.Warn(() => $"EXPECTED SIDES on Piece '{piece.m_name}' {((Component)piece).transform.position}: {10}, ACTUAL SIDES: {Lines.Count}"); } return Lines; } private static List DeriveSidesFromUndefined(Piece piece) { //IL_002d: 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) Lines.Clear(); char c = 'A'; for (int i = 0; i < piece.PrimarySnapNodes().Count; i++) { for (int j = i + 1; j < piece.PrimarySnapNodes().Count; j++) { Lines.Add(new Line(c++, piece.PrimarySnapNodes()[i], piece.PrimarySnapNodes()[j])); } } return Lines; } private static List ImposeTopSideOn(Piece piece) { Sides.Clear(); ISide item = piece.TopSide(); Sides.Add(item); return Sides; } private static TraversalResult? FindNearestSnapNodeTo(Vector3 referencePosition, List pieces, Func isDesired) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) HorribleOptimization.Clear(); HorribleOptimization.Add(referencePosition); return FindNearestSnapNodeTo(HorribleOptimization, pieces, isDesired); } private static TraversalResult? FindNearestSnapNodeTo(List buildPieceSnapNodes, List neighborPieces, Func isDesired) { //IL_001e: 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_0066: 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) //IL_009f: Unknown result type (might be due to invalid IL or missing references) float num = float.PositiveInfinity; TraversalResult? result = null; foreach (Vector3 buildPieceSnapNode in buildPieceSnapNodes) { foreach (Piece neighborPiece in neighborPieces) { foreach (SnapNode snapNode in SnapTrees.LookUp(neighborPiece).snapNodes) { float num2 = Vector3.Distance(buildPieceSnapNode, (Vector3)snapNode); if (isDesired(snapNode.precision) && num > num2 && num2 < 1f) { num = num2; result = new TraversalResult(buildPieceSnapNode, snapNode, neighborPiece); } } } } return result; } } public static class Logger { private static LogLevel logLevel => (LogLevel)32; public static void Debug(Func func) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)logLevel >= 32) { Logger.LogDebug((object)func()); } } public static void Info(Func func) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)logLevel >= 16) { Logger.LogInfo((object)func()); } } public static void Warn(Func func) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)logLevel >= 4) { Logger.LogWarning((object)func()); } } } public interface IMemoryRepo { V LookUp(K key); } public interface IRefreshableMemoryRepo : IMemoryRepo, IRefresherable { } public class MemoryRepo : IMemoryRepo { private class TimeBombMemoryRepo : IRefreshableMemoryRepo, IMemoryRepo, IRefresherable { private MemoryRepo innerMemoryRepo { get; } private TimeSpan explosionTime { get; } private Queue timeBomb { get; } public TimeBombMemoryRepo(MemoryRepo innerMemoryRepo, TimeSpan explosionTime) { timeBomb = new Queue(); this.explosionTime = explosionTime; this.innerMemoryRepo = innerMemoryRepo; } public V LookUp(K key) { TK key2 = innerMemoryRepo.transformer(key); if (!innerMemoryRepo.kvs.ContainsKey(key2)) { timeBomb.Enqueue(new Timed(key2, Time.time + (float)explosionTime.TotalSeconds)); } return innerMemoryRepo.LookUp(key); } public void Refresh() { while (timeBomb.Count > 0 && timeBomb.Peek().explosionTime < Time.time) { Timed boom = timeBomb.Dequeue(); innerMemoryRepo.kvs.Remove(boom.key); Logger.Debug(() => $"[MEMORY REPO EVICTION] on key: {boom.key}"); } } } private struct Timed { public float explosionTime { get; } public TK key { get; } public Timed(TK key, float explosionTime) { this.key = key; this.explosionTime = explosionTime; } } protected Func producer { get; } private Dictionary kvs { get; } private Func transformer { get; } public MemoryRepo(Func producer, Func transformer, int capacity) { this.producer = producer; this.transformer = transformer; kvs = new Dictionary(capacity); } public V LookUp(K key) { TK val = transformer(key); bool miss = !kvs.ContainsKey(val); Logger.Debug(() => string.Format("[MEMORY REPO {0}] on key: {1}", miss ? "MISS" : "HIT", key)); if (miss) { kvs[val] = ProduceVal(key, val); } return kvs[val]; } public IRefreshableMemoryRepo EvictionPolicy(TimeSpan explosionTime) { return new TimeBombMemoryRepo(this, explosionTime); } protected virtual V ProduceVal(K key, TK _) { return producer(key); } } public class MemoryRepo : MemoryRepo { public MemoryRepo(Func producer, Func transformer, int capacity) : base(producer, transformer, capacity) { } public MemoryRepo(Func producer, int capacity) : this(producer, (Func)((K key) => key), capacity) { } protected override V ProduceVal(K _, K transformedKey) { return base.producer(transformedKey); } } public static class PieceHelpers { private static readonly IMemoryRepo PieceSizes = new MemoryRepo(BoundsOf, (Piece piece) => piece.m_name, 255); private static readonly IMemoryRepo PieceTypes = new MemoryRepo(TypeOf, (Piece piece) => piece.m_name, 255); private static readonly IMemoryRepo PieceShapes = new MemoryRepo(ShapeOf, (Piece piece) => piece.m_name, 255); private static readonly Dictionary> Tables = new Dictionary> { ["$piece_table_oak"] = (Piece piece) => new Box(piece, new Vector2(3f, 0.8f)), ["$piece_blackmarble_table"] = (Piece piece) => new Box(piece, new Vector2(1.15f, 0.5f)), ["$piece_table"] = (Piece piece) => new Box(piece, new Vector2(1.1f, 0.475f)), ["$piece_table_round"] = (Piece piece) => new Circle(piece, new Vector2(1.15f, 0f)) }; private static readonly List PrimarySPs = new List(); private static readonly List PrimarySNs = new List(); public static Piece buildPiece { get { GameObject placementGhost = PlayerHelpers.player.m_placementGhost; return (placementGhost != null) ? placementGhost.GetComponent() : null; } } public static Bounds Bounds(this Piece piece) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return PieceSizes.LookUp(piece); } public static PieceType Type(this Piece piece) { return PieceTypes.LookUp(piece); } public static PieceShape Shape(this Piece piece) { return PieceShapes.LookUp(piece); } public static ISide TopSide(this Piece piece) { return Tables[piece.m_name](piece); } public static bool IsGroundBound(this Piece piece) { return piece.m_groundPiece || piece.m_clipGround || piece.m_clipEverything; } public static List PrimarySnapNodes(this Piece piece) { piece.FlushPrimarySnapNodes(); piece.PopulatePrimarySnapNodes(); return PrimarySNs; } private static void FlushPrimarySnapNodes(this Piece _) { PrimarySPs.Clear(); PrimarySNs.Clear(); Logger.Debug(() => "[FLUSHED] Primary Snap Nodes of previous piece"); } private static void PopulatePrimarySnapNodes(this Piece piece) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) piece.GetSnapPoints(PrimarySPs); foreach (Transform primarySP in PrimarySPs) { PrimarySNs.Add(((Component)primarySP).transform.position); } Logger.Debug(() => string.Format("PRIMARY SNAP NODES: {0} of Piece: '{1}' {2}", (PrimarySNs.Count > 0) ? string.Join(", ", PrimarySNs) : "NONE", piece.m_name, ((Component)piece).transform.position)); } public static Vector3 TopMiddle(this Piece piece) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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) Collider[] componentsInChildren = ((Component)piece).GetComponentsInChildren(); Bounds bounds = ((Component)piece).GetComponentInChildren().bounds; Collider[] array = componentsInChildren; foreach (Collider val in array) { ((Bounds)(ref bounds)).Encapsulate(val.bounds); } float y = ((Bounds)(ref bounds)).max.y; return new Vector3(((Component)piece).transform.position.x, y, ((Component)piece).transform.position.z); } private static bool EverySnapNodeLiesOnExtremums(List snapNodes) { //IL_0002: 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_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //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_0022: 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_0024: Unknown result type (might be due to invalid IL or missing references) Vector3 minimums = SolveMinimumsOf(snapNodes); Vector3 maximums = SolveMaximumsOf(snapNodes); foreach (Vector3 snapNode in snapNodes) { if (!LiesOnExtremums(snapNode, minimums, maximums)) { return false; } } return true; } private static Vector3 SolveMinimumsOf(List snapNodes) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_008d: 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_0052: 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) float num = float.PositiveInfinity; float num2 = float.PositiveInfinity; float num3 = float.PositiveInfinity; foreach (Vector3 snapNode in snapNodes) { num = ((num > snapNode.x) ? snapNode.x : num); num2 = ((num2 > snapNode.y) ? snapNode.y : num2); num3 = ((num3 > snapNode.z) ? snapNode.z : num3); } return new Vector3(num, num2, num3); } private static Vector3 SolveMaximumsOf(List snapNodes) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_008d: 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_0052: 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) float num = float.NegativeInfinity; float num2 = float.NegativeInfinity; float num3 = float.NegativeInfinity; foreach (Vector3 snapNode in snapNodes) { num = ((num < snapNode.x) ? snapNode.x : num); num2 = ((num2 < snapNode.y) ? snapNode.y : num2); num3 = ((num3 < snapNode.z) ? snapNode.z : num3); } return new Vector3(num, num2, num3); } private static bool LiesOnExtremums(Vector3 snapNode, Vector3 minimums, Vector3 maximums) { //IL_0001: 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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_003a: 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_0067: 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_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) if (!Mathf.Approximately(snapNode.x, minimums.x) && !Mathf.Approximately(snapNode.x, maximums.x)) { return false; } if (!Mathf.Approximately(snapNode.y, minimums.y) && !Mathf.Approximately(snapNode.y, maximums.y)) { return false; } if (!Mathf.Approximately(snapNode.z, minimums.z) && !Mathf.Approximately(snapNode.z, maximums.z)) { return false; } return true; } private static Bounds BoundsOf(Piece piece) { //IL_0007: 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_0022: 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_0038: 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_0046: 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) Quaternion rotation = ((Component)piece).transform.rotation; ((Component)piece).transform.rotation = Quaternion.Euler(0f, 0f, 0f); Bounds bounds = ((Renderer)((Component)piece).GetComponentInChildren()).bounds; ((Component)piece).transform.rotation = rotation; return bounds; } private static PieceType TypeOf(Piece piece) { PieceType type = TypeOf(piece.PrimarySnapNodes(), piece.m_name); Logger.Debug(() => $"Piece '{piece.m_name}' {((Component)piece).transform.position} IS a {type} Piece"); return type; } private static PieceType TypeOf(List primarySNs, string pieceName) { if (Tables.ContainsKey(pieceName)) { return PieceType.TABLE; } return (primarySNs.Count == 0) ? PieceType.FURNITURE : PieceType.CONSTRUCTION; } private static PieceShape ShapeOf(Piece piece) { piece.FlushPrimarySnapNodes(); PieceShape shape = ShapeOf(piece.PrimarySnapNodes()); Logger.Debug(() => $"Piece '{piece.m_name}' {((Component)piece).transform.position} IS a {shape} Piece"); return shape; } private static PieceShape ShapeOf(List primarySNs) { if (primarySNs.Count == 2) { return PieceShape.LINE; } if (primarySNs.Count == 4 && EverySnapNodeLiesOnExtremums(primarySNs)) { return PieceShape.BOX; } if (primarySNs.Count == 8 && EverySnapNodeLiesOnExtremums(primarySNs)) { return PieceShape.CUBE; } if (primarySNs.Count == 18) { return PieceShape.CYLINDER; } return PieceShape.UNDEFINED; } } public enum PieceShape { BOX, LINE, CUBE, CYLINDER, UNDEFINED } public enum PieceType { CONSTRUCTION, FURNITURE, TABLE } public static class PieceTypeHelpers { public static bool IsSnappable(this PieceType type) { return type == PieceType.CONSTRUCTION || type == PieceType.TABLE; } } public static class PlayerHelpers { private const string HoeToolName = "$item_hoe"; private const string HammerToolName = "$item_hammer"; private const string PickaxeToolName = "$item_pickaxe"; private const string CultivatorToolName = "$item_cultivator"; public static Player player => Player.m_localPlayer; public static Vector3 playerPos => ((Component)player).transform.position; private static bool HasHoeEquipped(this Player p) { return ((p != null) ? ((Humanoid)p).GetRightItem() : null) != null && ((Humanoid)p).GetRightItem().m_shared.m_name == "$item_hoe"; } private static bool HasHammerEquipped(this Player p) { return ((p != null) ? ((Humanoid)p).GetRightItem() : null) != null && ((Humanoid)p).GetRightItem().m_shared.m_name == "$item_hammer"; } private static bool HasCultivatorEquipped(this Player p) { return ((p != null) ? ((Humanoid)p).GetRightItem() : null) != null && ((Humanoid)p).GetRightItem().m_shared.m_name == "$item_cultivator"; } private static bool HasPickaxeEquipped(this Player p) { return ((p != null) ? ((Humanoid)p).GetRightItem() : null) != null && ((Humanoid)p).GetRightItem().m_shared.m_name.StartsWith("$item_pickaxe"); } public static bool HasConstructionToolEquipped(this Player p) { return p.HasHoeEquipped() || p.HasHammerEquipped() || p.HasCultivatorEquipped() || p.HasPickaxeEquipped(); } public static bool HasColorBrushEquipped(this Player p) { return p.HasPaveRoadTerraformToolEquipped() || p.HasCultivateTerraformToolEquipped() || p.HasSeedGrassTerraformToolEquipped(); } public static bool HasOverlayVisible(this Player p) { GameObject placementGhost = p.m_placementGhost; return (Object)(object)((placementGhost != null) ? placementGhost.GetComponent() : null) != (Object)null; } public static bool HasBuildPieceEquipped(this Player p) { return Object.op_Implicit((Object)(object)p.m_placementGhost) && !Object.op_Implicit((Object)(object)p.m_placementGhost.GetComponent()); } private static bool HasPaveRoadTerraformToolEquipped(this Player p) { GameObject placementGhost = p.m_placementGhost; return (Object)(object)((placementGhost != null) ? placementGhost.GetComponent() : null) != (Object)null; } private static bool HasCultivateTerraformToolEquipped(this Player p) { GameObject placementGhost = p.m_placementGhost; return (Object)(object)((placementGhost != null) ? placementGhost.GetComponent() : null) != (Object)null; } private static bool HasSeedGrassTerraformToolEquipped(this Player p) { GameObject placementGhost = p.m_placementGhost; return (Object)(object)((placementGhost != null) ? placementGhost.GetComponent() : null) != (Object)null; } public static bool HasLevelGroundTerraformToolEquipped(this Player p) { GameObject placementGhost = p.m_placementGhost; return (Object)(object)((placementGhost != null) ? placementGhost.GetComponent() : null) != (Object)null; } public static bool HasRaiseGroundTerraformToolEquipped(this Player p) { GameObject placementGhost = p.m_placementGhost; return (Object)(object)((placementGhost != null) ? placementGhost.GetComponent() : null) != (Object)null; } } public readonly struct BorderSlicer : ISlicer { private Vector3 mid { get; } private float radius { get; } public BorderSlicer(Vector3 mid, float radius) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) this.mid = mid; this.radius = radius; } private bool IsInsideBorder(float rhs) { return !float.IsNaN(rhs); } public MinMax? SliceZOn(float x) { //IL_0013: 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_0051: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Sqrt(Mathf.Pow(radius, 2f) - Mathf.Pow(x - mid.x, 2f)); return IsInsideBorder(num) ? new MinMax?(new MinMax(mid.z - num, mid.z + num)) : null; } public MinMax? SliceXOn(float z) { //IL_0013: 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_0051: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Sqrt(Mathf.Pow(radius, 2f) - Mathf.Pow(z - mid.z, 2f)); return IsInsideBorder(num) ? new MinMax?(new MinMax(mid.x - num, mid.x + num)) : null; } } public class OrdinaryPrecisionGridVisualizer : GridVisualizer { protected override bool ShouldInflateBorder() { return KeyBinder.gridModeEnabled; } protected override bool ShouldDeflateBorder() { return KeyBinder.gridModeDisabled; } protected override float GridDensity() { return 1f; } } public class SuperiorPrecisionGridVisualizer : GridVisualizer { protected override bool ShouldInflateBorder() { return KeyBinder.gridModeEnabled && KeyBinder.precisionMode == PrecisionMode.SUPERIOR; } protected override bool ShouldDeflateBorder() { return KeyBinder.gridModeDisabled || KeyBinder.precisionMode == PrecisionMode.ORDINARY; } protected override float GridDensity() { return 0.5f; } } [HarmonyPatch] public abstract class GridVisualizer : MonoBehaviour { private const float GridBorderMaxRadius = 8f; private const float BorderExpansionTime = 0.5f; private static readonly int MinColor = Shader.PropertyToID("_MinColor"); private static readonly int MaxColor = Shader.PropertyToID("_MaxColor"); private static readonly int AAThickness = Shader.PropertyToID("_AAThickness"); private static readonly int LineThickness = Shader.PropertyToID("_LineThickness"); private static readonly int BorderThickness = Shader.PropertyToID("_BorderThickness"); private static readonly int GridRadius = Shader.PropertyToID("_GridRadius"); private static readonly int GridResolution = Shader.PropertyToID("_GridResolution"); private static readonly int PlayerPosition = Shader.PropertyToID("_PlayerPosition"); private CommandBuffer cb { get; } = new CommandBuffer { name = "PlayerMask" }; private Material material { get; set; } private Projector renderer { get; set; } private Material playerMask { get; set; } private float borderExpansionTimer { get; set; } private float borderRadius => 8f * borderExpansionTimer / 0.5f; private bool ShouldShowGrid() { return borderRadius > 0f; } protected abstract bool ShouldInflateBorder(); protected abstract bool ShouldDeflateBorder(); protected abstract float GridDensity(); [HarmonyPostfix] [HarmonyPatch(typeof(Player))] [HarmonyPatch("OnSpawned")] private static void Initialize(Player __instance) { ((Component)__instance).gameObject.AddComponent(); ((Component)__instance).gameObject.AddComponent(); } protected void Awake() { InitializeGridRenderer(); InitializePlayerMask(); } private void InitializeGridRenderer() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_001c: 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_006c: Expected O, but got Unknown //IL_008c: 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) GameObject val = new GameObject(); val.transform.rotation = Quaternion.Euler(90f, 0f, 0f); renderer = val.AddComponent(); renderer.orthographicSize = 8f; renderer.orthographic = true; material = new Material(OCDheim.resourceBundle.LoadAsset("assets/worldgrid.mat")); material.SetColor(MinColor, new Color(0.25f, 0.25f, 0.25f, 0.25f)); material.SetColor(MaxColor, new Color(0.45f, 0.45f, 0.45f, 0.45f)); material.SetFloat(AAThickness, 0.02f); material.SetFloat(LineThickness, 0.03f); material.SetFloat(BorderThickness, 0.15f); material.SetFloat(GridResolution, GridDensity()); renderer.material = material; renderer.ignoreLayers = ~LayerMask.GetMask(new string[1] { "terrain" }); } private void InitializePlayerMask() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown playerMask = new Material(OCDheim.resourceBundle.LoadAsset("assets/playermask.mat")); Camera main = Camera.main; if (main != null) { main.AddCommandBuffer((CameraEvent)16, cb); } } private void Update() { //IL_005e: 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_0082: 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_00a7: 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) borderExpansionTimer = RefreshBorderRadius(borderExpansionTimer, ShouldInflateBorder, ShouldDeflateBorder); ((Behaviour)renderer).enabled = ShouldShowGrid(); if (((Behaviour)renderer).enabled) { ((Component)renderer).transform.position = new Vector3(PlayerHelpers.playerPos.x, PlayerHelpers.playerPos.y + 8f, PlayerHelpers.playerPos.z); material.SetVector(PlayerPosition, new Vector4(PlayerHelpers.playerPos.x, 0f, PlayerHelpers.playerPos.z, 0f)); material.SetFloat(GridRadius, borderRadius); } RefreshBuffer(); } private float RefreshBorderRadius(float currentTimer, Func shouldInflate, Func shouldDeflate) { if (shouldInflate() && currentTimer < 0.5f) { return Mathf.Min(0.5f, currentTimer + Time.deltaTime); } if (shouldDeflate() && currentTimer > 0f) { return Mathf.Max(0f, currentTimer - Time.deltaTime); } return currentTimer; } private void RefreshBuffer() { cb.Clear(); if (ShouldShowGrid()) { DrawToBuffer(((Component)PlayerHelpers.player).GetComponentsInChildren()); if (Object.op_Implicit((Object)(object)PlayerHelpers.player.m_placementGhost)) { DrawToBuffer(PlayerHelpers.player.m_placementGhost.GetComponentsInChildren()); } } } private void DrawToBuffer(Renderer[] renderers) { foreach (Renderer val in renderers) { if (val is MeshRenderer || val is SkinnedMeshRenderer) { cb.DrawRenderer(val, playerMask); } } } private void OnDestroy() { if ((Object)(object)material != (Object)null) { Object.Destroy((Object)(object)material); } if ((Object)(object)playerMask != (Object)null) { Object.Destroy((Object)(object)playerMask); } Camera main = Camera.main; if (main != null) { main.RemoveCommandBuffer((CameraEvent)16, cb); } cb.Release(); } } public class HoverInfo { private GameObject hoverInfoGo { get; } private Transform transform { get; } private TextMesh textMesh { get; } public bool enabled { get { return hoverInfoGo.activeSelf; } set { hoverInfoGo.SetActive(value); } } public string text { set { textMesh.text = value; } } public Color color { set { //IL_0006: Unknown result type (might be due to invalid IL or missing references) textMesh.color = value; } } public HoverInfo(Transform parentTransform) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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_009b: Unknown result type (might be due to invalid IL or missing references) hoverInfoGo = new GameObject(); hoverInfoGo.transform.parent = parentTransform; transform = hoverInfoGo.transform; textMesh = hoverInfoGo.AddComponent(); ((Component)textMesh).transform.localPosition = Vector3.zero; ((Component)textMesh).transform.localScale = new Vector3(0.1f / parentTransform.localScale.x, 0.1f / parentTransform.localScale.y, 0.1f / parentTransform.localScale.z); textMesh.anchor = (TextAnchor)4; textMesh.alignment = (TextAlignment)1; textMesh.fontSize = 16; } public void RotateToPlayer() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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) //IL_0046: 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) Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(((Component)GameCamera.m_instance).transform.position.x, transform.position.y, ((Component)GameCamera.m_instance).transform.position.z); transform.LookAt(val, Vector3.up); transform.Rotate(90f, 180f, 0f); } } public interface ISlicer { MinMax? SliceZOn(float x); MinMax? SliceXOn(float z); } public struct MinMax { public float min { get; private set; } public float max { get; private set; } public MinMax(float min, float max) { this.min = min; this.max = max; } } public class Overlay { public ParticleSystemRenderer psr { get; } public bool enabled { set { overlayGo.SetActive(value); } } public Vector3 worldPosition => transform.position; public Vector3 localPosition { get { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return transform.localPosition; } set { //IL_0006: Unknown result type (might be due to invalid IL or missing references) transform.localPosition = value; } } public Vector3 scale { set { //IL_0006: Unknown result type (might be due to invalid IL or missing references) transform.localScale = value; } } public Color color { get { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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) ps.GetParticles(particles, 2); return Color32.op_Implicit(((Particle)(ref particles[1])).GetCurrentColor(ps)); } } public Color startColor { get { //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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) MainModule main = ps.main; MinMaxGradient val = ((MainModule)(ref main)).startColor; return ((MinMaxGradient)(ref val)).color; } set { //IL_0007: 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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //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_002c: Unknown result type (might be due to invalid IL or missing references) MainModule main = ps.main; MainModule main2 = ps.main; MinMaxGradient val = ((MainModule)(ref main2)).startColor; ((MinMaxGradient)(ref val)).color = value; ((MainModule)(ref main)).startColor = val; } } public float startSize { set { //IL_0007: 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_0010: Unknown result type (might be due to invalid IL or missing references) MainModule main = ps.main; ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(value); } } public float startSpeed { set { //IL_0007: 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_0010: Unknown result type (might be due to invalid IL or missing references) MainModule main = ps.main; ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(value); } } public float startLifetime { set { //IL_0007: 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_0010: Unknown result type (might be due to invalid IL or missing references) MainModule main = ps.main; ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(value); } } public bool sizeOverLifetimeEnabled { set { //IL_0007: 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) SizeOverLifetimeModule val = ps.sizeOverLifetime; ((SizeOverLifetimeModule)(ref val)).enabled = value; } } public MinMaxCurve sizeOverLifetime { set { //IL_0007: 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_000f: Unknown result type (might be due to invalid IL or missing references) SizeOverLifetimeModule val = ps.sizeOverLifetime; ((SizeOverLifetimeModule)(ref val)).size = value; } } private GameObject overlayGo { get; } private Transform transform { get; } private ParticleSystem ps { get; } private Particle[] particles { get; } = (Particle[])(object)new Particle[2]; public Overlay(Transform transform) { this.transform = transform; overlayGo = ((Component)transform).gameObject; ps = ((Component)transform).GetComponentInChildren(); psr = ((Component)transform).GetComponentInChildren(); } } public readonly struct OverlaySlicer : ISlicer { private Vector3 boxMid { get; } private float sideSize { get; } private bool IsInsideXBounds(float x) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) return x >= boxMid.x - sideSize * 0.5f && x <= boxMid.x + sideSize * 0.5f; } private bool IsInsideZBounds(float z) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) return z >= boxMid.z - sideSize * 0.5f && z <= boxMid.z + sideSize * 0.5f; } public MinMax? SliceZOn(float x) { //IL_0015: 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) return IsInsideXBounds(x) ? new MinMax?(new MinMax(boxMid.z - sideSize * 0.5f, boxMid.z + sideSize * 0.5f)) : null; } public MinMax? SliceXOn(float z) { //IL_0015: 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) return IsInsideZBounds(z) ? new MinMax?(new MinMax(boxMid.x - sideSize * 0.5f, boxMid.x + sideSize * 0.5f)) : null; } public OverlaySlicer(Vector3 boxMid, float sideSize) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) this.boxMid = boxMid; this.sideSize = sideSize; } } public abstract class OverlayVisualizer : MonoBehaviour { private const int OverlayLayer = 31; public static Texture2D remove { get; } = OCDheim.LoadTextureFromDisk("remove.png"); protected static Texture2D cross { get; } = OCDheim.LoadTextureFromDisk("cross.png"); protected static Texture2D undo { get; } = OCDheim.LoadTextureFromDisk("undo.png"); protected static Texture2D redo { get; } = OCDheim.LoadTextureFromDisk("redo.png"); private static Texture2D box { get; } = OCDheim.LoadTextureFromDisk("box.png"); protected Overlay primary { get; private set; } protected Overlay secondary { get; private set; } protected Overlay tertiary { get; private set; } protected HoverInfo hoverInfo { get; private set; } private Camera mainCamera { get; set; } private Camera overlayCamera { get; set; } private GameObject overlayCameraGo { get; set; } private void Awake() { //IL_007a: Unknown result type (might be due to invalid IL or missing references) Transform val = ((Component)this).transform.Find("_GhostOnly"); Transform val2 = Object.Instantiate(val, ((Component)this).transform); Transform transform = Object.Instantiate(val2, ((Component)this).transform); primary = new Overlay(val); secondary = new Overlay(val2); tertiary = new Overlay(transform); hoverInfo = new HoverInfo(((Component)this).transform); tertiary.startColor = new Color(255f, 255f, 255f); primary.enabled = false; secondary.enabled = false; tertiary.enabled = false; InitializeOverlay(); InitializeCameras(); } private void InitializeCameras() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown mainCamera = Camera.main ?? throw new InvalidOperationException(); overlayCameraGo = new GameObject(); overlayCameraGo.transform.SetParent(((Component)mainCamera).transform, false); overlayCamera = overlayCameraGo.AddComponent(); overlayCamera.CopyFrom(mainCamera); overlayCamera.clearFlags = (CameraClearFlags)3; overlayCamera.depth = mainCamera.depth + 1f; overlayCamera.cullingMask = 0; OverrideLayerRecursively(((Component)primary.psr).gameObject); OverrideLayerRecursively(((Component)secondary.psr).gameObject); OverrideLayerRecursively(((Component)tertiary.psr).gameObject); } private void OverrideLayerRecursively(GameObject go) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown go.layer = 31; foreach (Transform item in go.transform) { Transform val = item; OverrideLayerRecursively(((Component)val).gameObject); } } private void Update() { if (KeyBinder.gridModFreshlyEnabled) { OnEnableGrid(); } if (KeyBinder.gridModFreshlyDisabled) { OnDisableGrid(); } if (KeyBinder.gridModeEnabled) { EnableOverlayCamera(); } if (KeyBinder.gridModeDisabled) { DisableOverlayCamera(); } OnRefresh(); } private void EnableOverlayCamera() { Camera obj = mainCamera; obj.cullingMask &= 0x7FFFFFFF; overlayCamera.cullingMask = int.MinValue; } private void DisableOverlayCamera() { if (Object.op_Implicit((Object)(object)mainCamera) && Object.op_Implicit((Object)(object)overlayCamera)) { Camera obj = mainCamera; obj.cullingMask |= int.MinValue; overlayCamera.cullingMask = 0; } } private void OnDestroy() { DisableOverlayCamera(); Object.Destroy((Object)(object)overlayCameraGo); } protected abstract void InitializeOverlay(); protected abstract void OnRefresh(); protected abstract void OnEnableGrid(); protected abstract void OnDisableGrid(); protected void SpeedUp(Overlay ov) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) AnimationCurve val = new AnimationCurve(); val.AddKey(0f, 0f); val.AddKey(0.5f, 1f); MinMaxCurve sizeOverLifetime = default(MinMaxCurve); ((MinMaxCurve)(ref sizeOverLifetime))..ctor(1f, val); ov.startLifetime = 2f; ov.sizeOverLifetime = sizeOverLifetime; } protected void Freeze(Overlay ov) { ov.startSpeed = 0f; ov.sizeOverLifetimeEnabled = false; } protected void ScaleVertically(Overlay ov) { //IL_0007: 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_0021: 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_002e: 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) int num = 10; Vector2 drillCoords = default(Vector2); ((Vector2)(ref drillCoords))..ctor(ov.worldPosition.x, ov.worldPosition.z); float y = PrecisionDrill.DrillDownTillGround(drillCoords).y; float num2 = ov.worldPosition.y - y; ov.scale = new Vector3(1f, num2 / (float)num, 1f); } protected void VisualizeTerraformingBounds(Overlay ov) { ov.startSize = 3f; ((Renderer)ov.psr).material.mainTexture = (Texture)(object)box; } protected void VisualizeRecoloringBounds(Overlay ov) { ov.startSize = 4.5f; ((Renderer)ov.psr).material.mainTexture = (Texture)(object)box; } protected void VisualizeIconInsideTerraformingBounds(Overlay ov, Texture iconTexture) { ov.startSize = 2.5f; ((Renderer)ov.psr).material.mainTexture = iconTexture; } protected void VisualizeIconInsideRecoloringBounds(Overlay ov, Texture iconTexture) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) ov.startSize = 3f; ((Renderer)ov.psr).material.mainTexture = iconTexture; ov.localPosition = new Vector3(0.5f, 0f, 0.5f); } } public abstract class HoverInfoEnabled : OverlayVisualizer { protected override void InitializeOverlay() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) base.hoverInfo.color = base.secondary.startColor; base.hoverInfo.enabled = KeyBinder.gridModeEnabled; } protected override void OnRefresh() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) if (base.hoverInfo.enabled) { base.hoverInfo.RotateToPlayer(); base.hoverInfo.text = $"x: {base.secondary.worldPosition.x:0}, y: {base.secondary.worldPosition.z:0}\nh: {base.secondary.worldPosition.y:0.0000}"; } } protected override void OnEnableGrid() { base.hoverInfo.enabled = true; } protected override void OnDisableGrid() { base.hoverInfo.enabled = false; } } public abstract class SecondaryEnabledOnGridModePrimaryDisabledOnGridMode : HoverInfoEnabled { protected override void OnRefresh() { base.OnRefresh(); ScaleVertically(base.secondary); base.primary.enabled = KeyBinder.gridModeDisabled; base.secondary.enabled = KeyBinder.gridModeEnabled; } } public abstract class SecondaryEnabledOnGridModePrimaryEnabledAlways : HoverInfoEnabled { protected override void OnRefresh() { base.OnRefresh(); base.primary.enabled = true; base.secondary.enabled = KeyBinder.gridModeEnabled; } } public abstract class SecondaryAndPrimaryEnabledAlways : OverlayVisualizer { protected override void OnRefresh() { base.primary.enabled = true; base.secondary.enabled = true; } protected override void OnEnableGrid() { } protected override void OnDisableGrid() { } } [HarmonyPatch] public static class OverlayVisualizerRedshiftBlocker { [HarmonyPrefix] [HarmonyPatch(typeof(Piece))] [HarmonyPatch("SetInvalidPlacementHeightlight")] private static bool BlockOverlayVisualizerRedshift() { return (Object)(object)((Component)PieceHelpers.buildPiece).GetComponentInChildren() == (Object)null; } } public class LevelGroundOverlayVisualizer : SecondaryEnabledOnGridModePrimaryDisabledOnGridMode { protected override void InitializeOverlay() { base.InitializeOverlay(); SpeedUp(base.secondary); VisualizeTerraformingBounds(base.secondary); } } public class RaiseGroundOverlayVisualizer : ModifyGroundLevelOverlayVisualizer { public RaiseGroundOverlayVisualizer() : base(GroundLevelSpinner.RaiseGroundSpinner) { } } public class LowerGroundOverlayVisualizer : ModifyGroundLevelOverlayVisualizer { public LowerGroundOverlayVisualizer() : base(GroundLevelSpinner.LowerGroundSpinner) { } } public abstract class ModifyGroundLevelOverlayVisualizer : SecondaryEnabledOnGridModePrimaryEnabledAlways { private const float VanillaValheimOverlayBump = 0.05f; private GroundLevelSpinner spinner { get; } protected ModifyGroundLevelOverlayVisualizer(GroundLevelSpinner spinner) { this.spinner = spinner; } protected override void InitializeOverlay() { base.InitializeOverlay(); Freeze(base.secondary); Freeze(base.tertiary); VisualizeTerraformingBounds(base.secondary); VisualizeTerraformingBounds(base.tertiary); } protected override void OnRefresh() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: 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) //IL_007f: 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) base.OnRefresh(); if (KeyBinder.gridModeEnabled) { spinner.Refresh(); base.secondary.localPosition = new Vector3(0f, spinner.value, 0f); base.hoverInfo.text = ((spinner.value > 0f) ? $"h: {base.secondary.worldPosition.y + 0.05f:0.0000}\n(+{base.secondary.localPosition.y:0.00})" : $"x: {base.secondary.worldPosition.x:0}, y: {base.secondary.worldPosition.z:0}\nh: {base.secondary.worldPosition.y + 0.05f:0.00}"); } base.tertiary.enabled = KeyBinder.gridModeEnabled; } } public class PaveRoadOverlayVisualizer : SecondaryEnabledOnGridModePrimaryDisabledOnGridMode { protected override void InitializeOverlay() { base.InitializeOverlay(); SpeedUp(base.secondary); VisualizeRecoloringBounds(base.secondary); } } public class CultivateOverlayVisualizer : PaveRoadOverlayVisualizer { protected override void OnRefresh() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) base.OnRefresh(); base.hoverInfo.color = base.secondary.color; } } public class SeedGrassOverlayVisualizer : SecondaryEnabledOnGridModePrimaryEnabledAlways { protected override void InitializeOverlay() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) base.InitializeOverlay(); Freeze(base.secondary); VisualizeRecoloringBounds(base.secondary); base.primary.localPosition = new Vector3(0f, 2f, 0f); base.secondary.localPosition = new Vector3(0f, 0f, 0f); } protected override void OnRefresh() { base.OnRefresh(); base.primary.startSize = (KeyBinder.gridModeEnabled ? 4f : 5.5f); } protected override void OnEnableGrid() { base.OnEnableGrid(); base.primary.enabled = false; base.primary.startSize = 4f; base.primary.enabled = true; } protected override void OnDisableGrid() { base.primary.enabled = false; base.primary.startSize = 5.5f; base.primary.enabled = true; base.OnDisableGrid(); } } public class RemoveModificationsOverlayVisualizer : SecondaryAndPrimaryEnabledAlways { protected override void InitializeOverlay() { Freeze(base.primary); SpeedUp(base.secondary); VisualizeTerraformingBounds(base.primary); VisualizeIconInsideTerraformingBounds(base.secondary, (Texture)(object)OverlayVisualizer.cross); } protected override void OnRefresh() { base.OnRefresh(); ScaleVertically(base.primary); ScaleVertically(base.secondary); } } public abstract class UndoRedoModificationsOverlayVisualizer : SecondaryAndPrimaryEnabledAlways { protected override void InitializeOverlay() { Freeze(base.primary); Freeze(base.secondary); VisualizeRecoloringBounds(base.primary); VisualizeIconInsideRecoloringBounds(base.secondary, (Texture)(object)Icon()); } protected abstract Texture2D Icon(); } public class UndoModificationsOverlayVisualizer : UndoRedoModificationsOverlayVisualizer { protected override Texture2D Icon() { return OverlayVisualizer.undo; } } public class RedoModificationsOverlayVisualizer : UndoRedoModificationsOverlayVisualizer { protected override Texture2D Icon() { return OverlayVisualizer.redo; } } } namespace OCDheim.Utilities { public interface IRefresherable { void Refresh(); } public class Refresher : MonoBehaviour { private IRefresherable refresherable { get; set; } private Refresher() { } public static Refresher Of(IRefresherable refresherable) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown GameObject val = new GameObject(); Refresher refresher = val.AddComponent(); refresher.refresherable = refresherable; return refresher; } public void Update() { refresherable.Refresh(); } } }