Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of TerrainShaperPlus v1.0.15
plugins\TerrainShaperPlus.dll
Decompiled 5 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using TerrainShaperPlus.Farm; using TerrainShaperPlus.Localization; using TerrainShaperPlus.Patches; using TerrainShaperPlus.Terrain; using TerrainShaperPlus.Tools; using TerrainShaperPlus.UI; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("PONEIS")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Terrain Shaper Plus for Valheim 1.0 — craftable workbench tool combining ValheimTooler + TerrainTools features")] [assembly: AssemblyFileVersion("1.0.15.0")] [assembly: AssemblyInformationalVersion("1.0.15+23e5840dc7b00833bb4c5e233e059a8db4612a41")] [assembly: AssemblyProduct("TerrainShaperPlus")] [assembly: AssemblyTitle("TerrainShaperPlus")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.15.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace TerrainShaperPlus { internal static class ModConfig { internal static ConfigEntry<string> Language; internal static ConfigEntry<bool> HoverInfo; internal static ConfigEntry<bool> EnableRadiusModifier; internal static ConfigEntry<KeyCode> RadiusModKey; internal static ConfigEntry<float> RadiusScrollScale; internal static ConfigEntry<float> MaxRadius; internal static ConfigEntry<bool> EnableSharpnessModifier; internal static ConfigEntry<KeyCode> SharpnessModKey; internal static ConfigEntry<float> SharpnessScrollScale; internal static ConfigEntry<bool> EnableHeightModifier; internal static ConfigEntry<KeyCode> HeightModKey; internal static ConfigEntry<float> HeightScrollStep; internal static ConfigEntry<float> MinHeightMeters; internal static ConfigEntry<float> MaxHeightMeters; internal static ConfigEntry<KeyCode> PanelToggleKey; internal static ConfigEntry<KeyCode> PanelModifierKey; internal static ConfigEntry<bool> EnableTool; internal static ConfigEntry<int> MinWorkbenchLevel; internal static ConfigEntry<int> RecipeWood; internal static ConfigEntry<int> RecipeStone; internal static ConfigEntry<float> MaxDurability; internal static ConfigEntry<float> DurabilityPerLevel; internal static ConfigEntry<float> DurabilityDrain; internal static ConfigEntry<bool> EnableGridSnap; internal static ConfigEntry<bool> GridSnapAlways; internal static ConfigEntry<KeyCode> GridSnapHoldKey; internal static ConfigEntry<bool> GridFollowPieceRotation; internal static ConfigEntry<float> GridRotationSnapDegrees; internal static ConfigEntry<bool> RequireWorkbenchToPlace; internal static ConfigEntry<bool> StaminaDrainEnabled; internal static ConfigEntry<float> StaminaDrainPerUse; internal static ConfigEntry<bool> SoftSquareEdges; internal static ConfigEntry<bool> SoftSquareEdgesAlways; internal static ConfigEntry<float> SoftSquareBevel; internal static ConfigEntry<bool> ShowBrushOutline; internal static ConfigEntry<bool> ShowBrushGrid; internal static ConfigEntry<bool> FarmGridEnabled; internal static ConfigEntry<bool> FarmShowGrid; internal static ConfigEntry<bool> FarmBlockOverlap; internal static ConfigEntry<float> FarmPlantSpacing; internal static ConfigEntry<int> FarmGridSections; internal static ConfigEntry<KeyCode> FarmSizeModKey; internal static ConfigEntry<int> FarmSizeScrollStep; internal static ConfigEntry<float> FarmGridYOffset; internal static ConfigEntry<Color> FarmGridColor; internal static ConfigEntry<int> FarmGridFixedRotation; internal static ConfigEntry<string> FarmPlantObjectMasks; internal static ConfigEntry<string> FarmCustomPlants; internal static readonly Dictionary<string, ConfigEntry<bool>> ToolToggles = new Dictionary<string, ConfigEntry<bool>>(); internal static void Bind(ConfigFile config) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Expected O, but got Unknown //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Expected O, but got Unknown //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Expected O, but got Unknown //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Expected O, but got Unknown //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Expected O, but got Unknown //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Expected O, but got Unknown //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_0380: Expected O, but got Unknown //IL_03e4: Unknown result type (might be due to invalid IL or missing references) //IL_03ee: Expected O, but got Unknown //IL_04a3: Unknown result type (might be due to invalid IL or missing references) //IL_04ad: Expected O, but got Unknown //IL_04cf: Unknown result type (might be due to invalid IL or missing references) //IL_04d9: Expected O, but got Unknown //IL_051a: Unknown result type (might be due to invalid IL or missing references) //IL_0524: Expected O, but got Unknown //IL_0552: Unknown result type (might be due to invalid IL or missing references) //IL_055c: Expected O, but got Unknown //IL_0580: Unknown result type (might be due to invalid IL or missing references) //IL_07c4: Unknown result type (might be due to invalid IL or missing references) //IL_07ce: Expected O, but got Unknown //IL_07f2: Unknown result type (might be due to invalid IL or missing references) //IL_07fc: Expected O, but got Unknown //IL_0820: Unknown result type (might be due to invalid IL or missing references) //IL_082a: Expected O, but got Unknown //IL_0858: Unknown result type (might be due to invalid IL or missing references) //IL_0862: Expected O, but got Unknown //IL_0890: Unknown result type (might be due to invalid IL or missing references) //IL_089a: Expected O, but got Unknown //IL_08c8: Unknown result type (might be due to invalid IL or missing references) //IL_08d2: Expected O, but got Unknown Language = config.Bind<string>("Localization", "Language", "Auto", "Language for TerrainShaperPlus UI strings. Auto follows the game language. Values: Auto, English, Portuguese. JSON files live in BepInEx/config/TerrainShaperPlus/lang/"); HoverInfo = config.Bind<bool>("Global", "HoverInfo", true, "Show terrain height while placing square / precision tools."); EnableRadiusModifier = config.Bind<bool>("Radius", "Enabled", true, "Allow changing tool radius with modifier key + scroll wheel."); RadiusModKey = config.Bind<KeyCode>("Radius", "ModifierKey", (KeyCode)304, "Key held while scrolling to change radius. Default Shift (Ctrl is used with Q/E to rotate)."); RadiusScrollScale = config.Bind<float>("Radius", "ScrollScale", 0.1f, new ConfigDescription("Scroll sensitivity for radius.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 1f), Array.Empty<object>())); MaxRadius = config.Bind<float>("Radius", "MaxRadius", 10f, new ConfigDescription("Maximum tool radius.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(4f, 50f), Array.Empty<object>())); EnableSharpnessModifier = config.Bind<bool>("Sharpness", "Enabled", true, "Allow changing tool hardness with modifier key + scroll wheel."); SharpnessModKey = config.Bind<KeyCode>("Sharpness", "ModifierKey", (KeyCode)306, "Key held while scrolling to change hardness."); SharpnessScrollScale = config.Bind<float>("Sharpness", "ScrollScale", 0.1f, new ConfigDescription("Scroll sensitivity for hardness.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 1f), Array.Empty<object>())); EnableHeightModifier = config.Bind<bool>("Height", "Enabled", true, "Allow changing raise/lower height in meters (like ValheimTooler Terrain Shaper depth)."); HeightModKey = config.Bind<KeyCode>("Height", "ModifierKey", (KeyCode)0, "Optional extra key for height scroll. Default None = scroll alone on raise/lower (recommended). Do NOT use LeftShift — it conflicts with vanilla level aim."); HeightScrollStep = config.Bind<float>("Height", "ScrollStep", 0.5f, new ConfigDescription("Height change per scroll tick (meters). Use 0.5 or 1 for 1m/5m style steps.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 5f), Array.Empty<object>())); MinHeightMeters = config.Bind<float>("Height", "MinMeters", 0.5f, new ConfigDescription("Minimum raise/lower height in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 20f), Array.Empty<object>())); MaxHeightMeters = config.Bind<float>("Height", "MaxMeters", 8f, new ConfigDescription("Maximum raise/lower height in meters (game clamps ±8).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 8f), Array.Empty<object>())); PanelToggleKey = config.Bind<KeyCode>("Panel", "ToggleKey", (KeyCode)103, "Main key for the Height × Width panel (used with ModifierKey)."); PanelModifierKey = config.Bind<KeyCode>("Panel", "ModifierKey", (KeyCode)306, "Held with ToggleKey to open/close the panel. Default LeftControl → Ctrl+G. Set to None for a single key."); EnableGridSnap = config.Bind<bool>("Grid", "Enabled", true, "Allow Width-based grid snap for square placement (free aim by default)."); GridSnapHoldKey = config.Bind<KeyCode>("Grid", "HoldKey", (KeyCode)308, "Hold this key while placing to snap to the tile grid. Free placement when not held. Set to None to always snap when Enabled."); GridSnapAlways = config.Bind<bool>("Grid", "Always", false, "Also snap circular brushes (not only square tools), when snap is active."); GridFollowPieceRotation = config.Bind<bool>("Grid", "FollowPieceRotation", true, "Square brush, snap grid and preview follow piece yaw (vanilla Q/E). Makes rotated basements easy."); GridRotationSnapDegrees = config.Bind<float>("Grid", "RotationSnapDegrees", 15f, new ConfigDescription("While placing square tools, snap ghost yaw to this step (0 = free rotation). 15 or 45 works well with builds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 90f), Array.Empty<object>())); RequireWorkbenchToPlace = config.Bind<bool>("Placement", "RequireWorkbench", false, "If true, TSP pieces need a nearby Workbench (vanilla Hoe raise style). Default false = usable from boats / shores."); StaminaDrainEnabled = config.Bind<bool>("Stamina", "Enabled", true, "Drain stamina when placing with Terrain Shaper Plus."); StaminaDrainPerUse = config.Bind<float>("Stamina", "DrainPerUse", -1f, new ConfigDescription("Stamina cost per place. -1 = use the tool's built-in attack stamina (Hoe clone). 0 = free. Typical Hoe is ~5–10.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 50f), Array.Empty<object>())); SoftSquareEdges = config.Bind<bool>("Terrain", "SoftSquareEdges", true, "Bevel square raise/lower edges so platforms don't create black void cliffs (limbo)."); SoftSquareEdgesAlways = config.Bind<bool>("Terrain", "SoftSquareEdgesAlways", false, "Apply soft square edges to all terrain mods, not only Terrain Shaper Plus."); SoftSquareBevel = config.Bind<float>("Terrain", "SoftSquareBevel", 0.35f, new ConfigDescription("Edge bevel size as a fraction of brush radius (higher = softer ramp, less void).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.15f, 0.6f), Array.Empty<object>())); ShowBrushOutline = config.Bind<bool>("Preview", "ShowBrushOutline", true, "While placing a Terrain Shaper piece, draw a wireframe of Width (and Height for raise/lower)."); ShowBrushGrid = config.Bind<bool>("Preview", "ShowBrushGrid", true, "Draw a light grid inside the brush footprint outline."); FarmGridEnabled = config.Bind<bool>("Farm", "Enabled", true, "Cultivator farm grid (FarmGrid-style): snap plants to spacing + optional visual grid. Disable FarmGrid mod to avoid double-patching."); FarmShowGrid = config.Bind<bool>("Farm", "ShowGrid", true, "Draw the plant spacing grid while placing with the Cultivator."); FarmBlockOverlap = config.Bind<bool>("Farm", "BlockOverlap", true, "Prevent placing plants that would overlap another plant."); FarmPlantSpacing = config.Bind<float>("Farm", "PlantSpacing", 0.01f, new ConfigDescription("Extra space between plants on top of growth radius.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); FarmGridSections = config.Bind<int>("Farm", "GridSections", 2, new ConfigDescription("Grid lines on each side of the axis (visual size). Adjust in-game with SizeModKey + scroll.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 8), Array.Empty<object>())); FarmSizeModKey = config.Bind<KeyCode>("Farm", "SizeModKey", (KeyCode)306, "Hold this key and scroll while placing plants with the Cultivator to change farm grid size (GridSections)."); FarmSizeScrollStep = config.Bind<int>("Farm", "SizeScrollStep", 1, new ConfigDescription("How many grid sections to add/remove per scroll tick.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 2), Array.Empty<object>())); FarmGridYOffset = config.Bind<float>("Farm", "GridYOffset", 0.2f, new ConfigDescription("Grid height above ground.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); FarmGridColor = config.Bind<Color>("Farm", "GridColor", new Color(0.8f, 0.8f, 0.8f, 0.2f), "Color of the farm grid lines."); FarmGridFixedRotation = config.Bind<int>("Farm", "FixedRotationDegrees", 0, "Fixed grid rotation in degrees (0 = auto from nearby plants). Use 360 for a fixed 0° axis."); FarmPlantObjectMasks = config.Bind<string>("Farm", "PlantObjectMasks", "piece,piece_nonsolid", "Layer masks for plant overlap detection. Planting Plus tip: piece,piece_nonsolid,item"); FarmCustomPlants = config.Bind<string>("Farm", "CustomPlants", "", "Non-Plant objects treated as plants: Name:size, Name:size (see FarmGrid/Planting Plus docs)."); FarmGridEnabled.SettingChanged += delegate { RefreshFarm(); }; FarmShowGrid.SettingChanged += delegate { RefreshFarm(); }; FarmPlantSpacing.SettingChanged += delegate { RefreshFarm(); }; FarmGridSections.SettingChanged += delegate { RefreshFarm(); }; FarmGridYOffset.SettingChanged += delegate { RefreshFarm(); }; FarmGridColor.SettingChanged += delegate { RefreshFarm(); }; FarmGridFixedRotation.SettingChanged += delegate { RefreshFarm(); }; FarmPlantObjectMasks.SettingChanged += delegate { RefreshFarm(); }; FarmCustomPlants.SettingChanged += delegate { RefreshFarm(); }; RefreshFarm(); RequireWorkbenchToPlace.SettingChanged += delegate { PieceFactory.ApplyPlacementRules(); }; EnableTool = config.Bind<bool>("Crafting", "EnableRecipe", true, "Allow crafting Terrain Shaper Plus at the Workbench."); MinWorkbenchLevel = config.Bind<int>("Crafting", "MinWorkbenchLevel", 1, new ConfigDescription("Minimum Workbench level required to craft Terrain Shaper Plus. Default 1 (basic Workbench).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 5), Array.Empty<object>())); RecipeWood = config.Bind<int>("Crafting", "WoodCost", 10, new ConfigDescription("Wood required.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50), Array.Empty<object>())); RecipeStone = config.Bind<int>("Crafting", "StoneCost", 10, new ConfigDescription("Stone required.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 50), Array.Empty<object>())); MaxDurability = config.Bind<float>("Durability", "MaxDurability", 800f, new ConfigDescription("Maximum durability of Terrain Shaper Plus (Hoe vanilla is ~200).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(50f, 10000f), Array.Empty<object>())); DurabilityPerLevel = config.Bind<float>("Durability", "PerQualityLevel", 100f, new ConfigDescription("Extra durability per quality level above 1.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2000f), Array.Empty<object>())); DurabilityDrain = config.Bind<float>("Durability", "DrainPerUse", 0.5f, new ConfigDescription("Durability lost per use (1 = vanilla Hoe). Lower lasts longer.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 5f), Array.Empty<object>())); foreach (string allId in ToolDefs.AllIds) { ToolToggles[allId] = config.Bind<bool>("Tools", allId, true, "Enable piece '" + allId + "' on the Terrain Shaper Plus."); } Language.SettingChanged += delegate { Loc.ApplyLanguagePreference(); }; static void RefreshFarm() { FarmGridPatch.ApplyConfig(); } } internal static bool IsToolEnabled(string id) { if (ToolToggles.TryGetValue(id, out var value)) { return value.Value; } return false; } internal static bool IsPanelToggleDown() { //IL_0005: 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_0026: Unknown result type (might be due to invalid IL or missing references) if ((int)PanelToggleKey.Value == 0) { return false; } if (!Input.GetKeyDown(PanelToggleKey.Value)) { return false; } return IsModifierHeld(PanelModifierKey.Value); } internal static bool IsGridSnapActive() { //IL_0013: 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) if (!EnableGridSnap.Value) { return false; } if ((int)GridSnapHoldKey.Value == 0) { return true; } return IsModifierHeld(GridSnapHoldKey.Value); } internal static string FormatPanelHotkey() { //IL_0005: 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_0033: 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_0023: Unknown result type (might be due to invalid IL or missing references) if ((int)PanelToggleKey.Value == 0) { return "—"; } if ((int)PanelModifierKey.Value == 0) { return ShortKey(PanelToggleKey.Value); } return ShortKey(PanelModifierKey.Value) + "+" + ShortKey(PanelToggleKey.Value); } internal static string FormatGridSnapHotkey() { //IL_0017: 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) if (!EnableGridSnap.Value) { return "off"; } if ((int)GridSnapHoldKey.Value == 0) { return "always"; } return ShortKey(GridSnapHoldKey.Value); } internal static string FormatRadiusHotkey() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (!EnableRadiusModifier.Value) { return "off"; } return ShortKey(RadiusModKey.Value) + "+scroll"; } internal static string FormatFarmSizeHotkey() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (!FarmGridEnabled.Value) { return "off"; } return ShortKey(FarmSizeModKey.Value) + "+scroll"; } internal static bool IsKeyHeld(KeyCode mod) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return IsModifierHeld(mod); } private static bool IsModifierHeld(KeyCode mod) { //IL_0000: 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_000b: Invalid comparison between Unknown and I4 //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Invalid comparison between Unknown and I4 //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Invalid comparison between Unknown and I4 //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Invalid comparison between Unknown and I4 //IL_0080: Unknown result type (might be due to invalid IL or missing references) if ((int)mod == 0) { return true; } if ((int)mod == 306 || (int)mod == 305) { if (!Input.GetKey((KeyCode)306)) { return Input.GetKey((KeyCode)305); } return true; } if ((int)mod == 308 || (int)mod == 307) { if (!Input.GetKey((KeyCode)308)) { return Input.GetKey((KeyCode)307); } return true; } if ((int)mod == 304 || (int)mod == 303) { if (!Input.GetKey((KeyCode)304)) { return Input.GetKey((KeyCode)303); } return true; } return Input.GetKey(mod); } private unsafe static string ShortKey(KeyCode key) { //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_0024: Expected I4, but got Unknown switch (key - 303) { case 2: case 3: return "Ctrl"; case 4: case 5: return "Alt"; case 0: case 1: return "Shift"; default: return ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString(); } } } [BepInPlugin("poneis.valheim.TerrainShaperPlus", "TerrainShaperPlus", "1.0.15")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGUID = "poneis.valheim.TerrainShaperPlus"; public const string PluginName = "TerrainShaperPlus"; public const string PluginVersion = "1.0.15"; internal static Plugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; ModConfig.Bind(((BaseUnityPlugin)this).Config); Loc.Init(); Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "poneis.valheim.TerrainShaperPlus"); PrefabManager.OnVanillaPrefabsAvailable += ShaperItem.Create; PieceManager.OnPiecesRegistered += PieceFactory.InitPieces; ((Component)this).gameObject.AddComponent<ShapePanel>(); Log.LogInfo((object)"TerrainShaperPlus 1.0.15 loaded."); } } internal static class ShapeSettings { internal const float MaxMeters = 8f; internal const float MinMeters = 0.5f; internal static float Height = 1f; internal static float Width = 2f; internal static bool Square = true; internal static void Clamp() { Height = Mathf.Clamp(Height, 0.5f, 8f); Width = Mathf.Clamp(Width, 0.5f, 8f); } internal static void ApplyToTerrainOp(TerrainOp op, bool isLower) { if ((Object)(object)op == (Object)null) { return; } Clamp(); Settings settings = op.m_settings; if (settings.m_raise) { settings.m_raiseDelta = (isLower ? (0f - Height) : Height); settings.m_raiseRadius = Width; settings.m_square = Square; if (Square) { settings.m_raisePower = ((Height >= 3f) ? 1.2f : 1.5f); } else if (Height >= 3f) { settings.m_raisePower = Mathf.Lerp(2.2f, 1.15f, Mathf.InverseLerp(3f, 8f, Height)); } } if (settings.m_level) { settings.m_levelRadius = Width; settings.m_square = Square; } if (settings.m_smooth) { settings.m_smoothRadius = Width; settings.m_square = Square; } if (settings.m_paintCleared || (!settings.m_level && !settings.m_raise && !settings.m_smooth)) { settings.m_paintRadius = Width; settings.m_square = Square; } } internal static void ApplyToAllRegisteredPieces() { Clamp(); foreach (KeyValuePair<string, GameObject> prefab in PieceFactory.Prefabs) { GameObject value = prefab.Value; if (!((Object)(object)value == (Object)null)) { TerrainOp componentInChildren = value.GetComponentInChildren<TerrainOp>(true); if (!((Object)(object)componentInChildren == (Object)null)) { bool isLower = (Object)(object)value.GetComponent<LowerTerrainMarker>() != (Object)null; ApplyToTerrainOp(componentInChildren, isLower); } } } HeightDeltaModifier.CurrentHeightMeters = Height; Plugin.Log.LogInfo((object)$"ShapeSettings applied: {Height:0.##}m high × {Width:0.##}m wide, square={Square}"); } internal static void ApplyToSelectedPiece(Player player) { if ((Object)(object)player == (Object)null) { return; } Piece selectedPiece = player.GetSelectedPiece(); if (!((Object)(object)selectedPiece == (Object)null)) { TerrainOp componentInChildren = ((Component)selectedPiece).GetComponentInChildren<TerrainOp>(true); if (!((Object)(object)componentInChildren == (Object)null)) { bool isLower = (Object)(object)((Component)selectedPiece).GetComponent<LowerTerrainMarker>() != (Object)null; ApplyToTerrainOp(componentInChildren, isLower); } } } } } namespace TerrainShaperPlus.UI { internal static class BrushOutlinePreview { private const int CircleSegments = 48; private static GameObject _root; private static LineRenderer _footprint; private static LineRenderer _top; private static readonly List<LineRenderer> Segments = new List<LineRenderer>(); private static Material _mat; private static int _segUsed; internal static void Hide() { if ((Object)(object)_root != (Object)null) { _root.SetActive(false); } } internal static void Show(Vector3 center, float width, float height, bool square, bool showHeightVolume, bool lower, float yawDegrees = 0f) { //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_0040: 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_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.ShowBrushOutline.Value) { Hide(); return; } Ensure(); _root.SetActive(true); _segUsed = 0; float num = Mathf.Max(0.25f, width); float num2 = SampleY(center.x, center.z, center.y); float num3 = 0.08f; float y = num2 + num3; bool rotate = square && ModConfig.GridFollowPieceRotation.Value && Mathf.Abs(Mathf.DeltaAngle(0f, yawDegrees)) > 0.5f; if (square) { DrawLoop(_footprint, SquarePoints(center.x, center.z, num, y, yawDegrees, rotate), new Color(0.25f, 0.95f, 1f, 0.95f), 0.045f); } else { DrawLoop(_footprint, CirclePoints(center.x, center.z, num, y), new Color(0.25f, 0.95f, 1f, 0.95f), 0.045f); } if (ModConfig.ShowBrushGrid.Value) { DrawInnerGrid(center.x, center.z, num, y, square, yawDegrees, rotate); } if (showHeightVolume && height > 0.05f) { float topY = (lower ? (num2 - height) : (num2 + height)); DrawHeightVolume(center.x, center.z, num, num2, topY, square, yawDegrees, rotate); ((Renderer)_top).enabled = true; } else { ((Renderer)_top).enabled = false; } DisableExtraSegments(); } private static void DrawInnerGrid(float cx, float cz, float half, float y, bool square, float yaw, bool rotate) { //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: 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_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0112: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) Color c = default(Color); ((Color)(ref c))..ctor(0.35f, 0.75f, 0.95f, 0.4f); if (square) { float num = Mathf.Clamp(half / 2f, 0.5f, 2f); for (float num2 = 0f - half + num; num2 < half - 0.01f; num2 += num) { Vector3 a = LocalToWorld(cx, cz, y, num2, 0f - half, yaw, rotate); Vector3 b = LocalToWorld(cx, cz, y, num2, half, yaw, rotate); AddSegment(a, b, c, 0.02f); } for (float num3 = 0f - half + num; num3 < half - 0.01f; num3 += num) { Vector3 a2 = LocalToWorld(cx, cz, y, 0f - half, num3, yaw, rotate); Vector3 b2 = LocalToWorld(cx, cz, y, half, num3, yaw, rotate); AddSegment(a2, b2, c, 0.02f); } } else { AddSegment(new Vector3(cx - half, y, cz), new Vector3(cx + half, y, cz), c, 0.02f); AddSegment(new Vector3(cx, y, cz - half), new Vector3(cx, y, cz + half), c, 0.02f); DrawLoop(NextSegment(), CirclePoints(cx, cz, half * 0.5f, y), c, 0.02f); } } private static void DrawHeightVolume(float cx, float cz, float half, float groundY, float topY, bool square, float yaw, bool rotate) { //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) Color c = default(Color); ((Color)(ref c))..ctor(1f, 0.85f, 0.25f, 0.9f); if (square) { float[] array = new float[4] { 0f - half, half, half, 0f - half }; float[] array2 = new float[4] { 0f - half, 0f - half, half, half }; for (int i = 0; i < 4; i++) { Vector3 val = LocalToWorld(cx, cz, groundY, array[i], array2[i], yaw, rotate); float num = SampleY(val.x, val.z, groundY) + 0.05f; AddSegment(new Vector3(val.x, num, val.z), new Vector3(val.x, topY, val.z), c, 0.035f); } DrawLoop(_top, SquarePoints(cx, cz, half, topY, yaw, rotate), c, 0.035f); } else { for (int j = 0; j < 4; j++) { float num2 = (float)j * (float)Math.PI * 0.5f; float num3 = cx + Mathf.Cos(num2) * half; float num4 = cz + Mathf.Sin(num2) * half; float num5 = SampleY(num3, num4, groundY) + 0.05f; AddSegment(new Vector3(num3, num5, num4), new Vector3(num3, topY, num4), c, 0.035f); } DrawLoop(_top, CirclePoints(cx, cz, half, topY), c, 0.035f); } } private static Vector3[] SquarePoints(float cx, float cz, float half, float y, float yaw = 0f, bool rotate = false) { //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_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_003e: 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_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) return (Vector3[])(object)new Vector3[4] { LocalToWorld(cx, cz, y, 0f - half, 0f - half, yaw, rotate), LocalToWorld(cx, cz, y, half, 0f - half, yaw, rotate), LocalToWorld(cx, cz, y, half, half, yaw, rotate), LocalToWorld(cx, cz, y, 0f - half, half, yaw, rotate) }; } private static Vector3 LocalToWorld(float cx, float cz, float y, float lx, float lz, float yaw, bool rotate) { //IL_003c: 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) if (!rotate) { return new Vector3(cx + lx, y, cz + lz); } float num = yaw * ((float)Math.PI / 180f); float num2 = Mathf.Cos(num); float num3 = Mathf.Sin(num); return new Vector3(cx + lx * num2 - lz * num3, y, cz + lx * num3 + lz * num2); } private static Vector3[] CirclePoints(float cx, float cz, float radius, float y) { //IL_0038: 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) Vector3[] array = (Vector3[])(object)new Vector3[48]; for (int i = 0; i < 48; i++) { float num = (float)i / 48f * (float)Math.PI * 2f; array[i] = new Vector3(cx + Mathf.Cos(num) * radius, y, cz + Mathf.Sin(num) * radius); } return array; } private static void DrawLoop(LineRenderer lr, Vector3[] pts, Color c, float width) { //IL_001f: 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_0042: Unknown result type (might be due to invalid IL or missing references) ((Renderer)lr).enabled = true; lr.loop = true; lr.positionCount = pts.Length; for (int i = 0; i < pts.Length; i++) { lr.SetPosition(i, pts[i]); } lr.widthMultiplier = width; lr.startColor = c; lr.endColor = c; } private static void AddSegment(Vector3 a, Vector3 b, Color c, float width) { //IL_0015: 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_002b: 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) LineRenderer obj = NextSegment(); obj.loop = false; obj.positionCount = 2; obj.SetPosition(0, a); obj.SetPosition(1, b); obj.widthMultiplier = width; obj.startColor = c; obj.endColor = c; } private static LineRenderer NextSegment() { //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) while (Segments.Count <= _segUsed) { GameObject val = new GameObject("Seg_" + Segments.Count); val.transform.SetParent(_root.transform, false); LineRenderer val2 = val.AddComponent<LineRenderer>(); ((Renderer)val2).sharedMaterial = _mat; val2.useWorldSpace = true; ((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)val2).receiveShadows = false; val2.alignment = (LineAlignment)0; Segments.Add(val2); } LineRenderer obj = Segments[_segUsed++]; ((Component)obj).gameObject.SetActive(true); ((Renderer)obj).enabled = true; return obj; } private static void DisableExtraSegments() { for (int i = _segUsed; i < Segments.Count; i++) { ((Renderer)Segments[i]).enabled = false; ((Component)Segments[i]).gameObject.SetActive(false); } } private static float SampleY(float x, float z, float fallback) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) float result = default(float); if (Heightmap.GetHeight(new Vector3(x, fallback, z), ref result)) { return result; } return fallback; } private static void Ensure() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown if (!((Object)(object)_root != (Object)null)) { _root = new GameObject("TerrainShaperPlus_BrushOutline"); Object.DontDestroyOnLoad((Object)(object)_root); _mat = CreateMat(); _footprint = CreateLr("Footprint"); _top = CreateLr("Top"); _root.SetActive(false); } } private static LineRenderer CreateLr(string name) { //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) GameObject val = new GameObject(name); val.transform.SetParent(_root.transform, false); LineRenderer obj = val.AddComponent<LineRenderer>(); ((Renderer)obj).sharedMaterial = _mat; obj.useWorldSpace = true; ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)obj).receiveShadows = false; obj.numCapVertices = 2; obj.alignment = (LineAlignment)0; return obj; } private static Material CreateMat() { //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_0045: Expected O, but got Unknown return new Material(Shader.Find("Sprites/Default") ?? Shader.Find("UI/Default") ?? Shader.Find("Hidden/Internal-Colored") ?? Shader.Find("Standard")) { color = Color.cyan }; } } internal class ShapePanel : MonoBehaviour { private bool _visible; private string _heightStr = "1"; private string _widthStr = "2"; private Rect _win = new Rect(40f, 120f, 320f, 240f); private int _winId = 718273; internal static ShapePanel Instance { get; private set; } private void Awake() { Instance = this; _heightStr = ShapeSettings.Height.ToString("0.##"); _widthStr = ShapeSettings.Width.ToString("0.##"); } private void Update() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || !ShaperItem.IsEquipped(localPlayer)) { _visible = false; return; } if (ModConfig.IsPanelToggleDown()) { _visible = !_visible; if (_visible) { _heightStr = ShapeSettings.Height.ToString("0.##"); _widthStr = ShapeSettings.Width.ToString("0.##"); } } if (!_visible && ShaperItem.IsEquipped(localPlayer) && Time.frameCount % 30 == 0) { ShapeSettings.ApplyToSelectedPiece(localPlayer); } } private void OnGUI() { //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_0065: 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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && ShaperItem.IsEquipped(localPlayer)) { if (!_visible) { float num = Mathf.Max(8f, (float)Screen.height - 200f); Rect val = new Rect(16f, num, Mathf.Min(920f, (float)Screen.width - 32f), 28f); Color color = GUI.color; GUI.color = new Color(0f, 0f, 0f, 0.45f); GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture); GUI.color = color; GUI.Label(val, " " + Loc.Tf("tsp_panel_hint", ModConfig.FormatPanelHotkey(), ModConfig.FormatGridSnapHotkey(), ModConfig.FormatRadiusHotkey())); } else { _win = GUI.Window(_winId, _win, new WindowFunction(DrawWindow), Loc.T("tsp_panel_title")); } } } private void DrawWindow(int id) { //IL_0227: Unknown result type (might be due to invalid IL or missing references) GUILayout.Space(4f); GUILayout.Label(Loc.T("tsp_panel_subtitle"), Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(Loc.T("tsp_panel_height"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) }); _heightStr = GUILayout.TextField(_heightStr, 8, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }); GUILayout.Label("m", Array.Empty<GUILayoutOption>()); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(Loc.T("tsp_panel_width"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) }); _widthStr = GUILayout.TextField(_widthStr, 8, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }); GUILayout.Label("m", Array.Empty<GUILayoutOption>()); GUILayout.EndHorizontal(); ShapeSettings.Square = GUILayout.Toggle(ShapeSettings.Square, Loc.T("tsp_panel_square"), Array.Empty<GUILayoutOption>()); GUILayout.Label(Loc.Tf("tsp_panel_preview", ParseOr(ShapeSettings.Height, _heightStr), ParseOr(ShapeSettings.Width, _widthStr)), Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button(Loc.T("tsp_panel_apply"), Array.Empty<GUILayoutOption>())) { ApplyFromFields(); } if (GUILayout.Button("1×2", Array.Empty<GUILayoutOption>())) { SetPreset(1f, 2f); } if (GUILayout.Button("5×2", Array.Empty<GUILayoutOption>())) { SetPreset(5f, 2f); } if (GUILayout.Button("5×3", Array.Empty<GUILayoutOption>())) { SetPreset(5f, 3f); } if (GUILayout.Button("8×3", Array.Empty<GUILayoutOption>())) { SetPreset(8f, 3f); } GUILayout.EndHorizontal(); GUILayout.Label(Loc.T("tsp_panel_help"), Array.Empty<GUILayoutOption>()); GUI.DragWindow(new Rect(0f, 0f, 10000f, 20f)); } private void ApplyFromFields() { if (float.TryParse(_heightStr.Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { ShapeSettings.Height = result; } if (float.TryParse(_widthStr.Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) { ShapeSettings.Width = result2; } ShapeSettings.Clamp(); _heightStr = ShapeSettings.Height.ToString("0.##"); _widthStr = ShapeSettings.Width.ToString("0.##"); ShapeSettings.ApplyToAllRegisteredPieces(); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, Loc.Tf("tsp_panel_applied", ShapeSettings.Height, ShapeSettings.Width), 0, (Sprite)null, false); } } private void SetPreset(float h, float w) { ShapeSettings.Height = h; ShapeSettings.Width = w; ShapeSettings.Square = true; ShapeSettings.Clamp(); _heightStr = ShapeSettings.Height.ToString("0.##"); _widthStr = ShapeSettings.Width.ToString("0.##"); ShapeSettings.ApplyToAllRegisteredPieces(); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, Loc.Tf("tsp_panel_applied", ShapeSettings.Height, ShapeSettings.Width), 0, (Sprite)null, false); } } private static float ParseOr(float fallback, string s) { if (float.TryParse(s.Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return Mathf.Clamp(result, 0.5f, 8f); } return fallback; } } } namespace TerrainShaperPlus.Tools { internal static class PieceFactory { private static bool _initialized; internal static readonly Dictionary<string, GameObject> Prefabs = new Dictionary<string, GameObject>(); internal static void InitPieces() { if (_initialized) { return; } Loc.ApplyLanguagePreference(); foreach (ToolDef item in ToolDefs.All) { try { GameObject val = MakePiece(item); if (!((Object)(object)val == (Object)null)) { Prefabs[item.Id] = val; if (ModConfig.IsToolEnabled(item.Id)) { RegisterInTable(val); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Failed to create piece " + item.Id + ": " + ex.Message)); } } _initialized = true; Plugin.Log.LogInfo((object)$"Registered {Prefabs.Count} Terrain Shaper Plus pieces."); ApplyPlacementRules(); if ((Object)(object)ObjectDB.instance != (Object)null) { ObjectDBTerrainOpPatch.RegisterTerrainOps(ObjectDB.instance); } ShapeSettings.ApplyToAllRegisteredPieces(); } private static GameObject MakePiece(ToolDef def) { //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) if (PieceManager.Instance.GetPiece(def.Id) != null) { return null; } GameObject val = PrefabManager.Instance.CreateClonedPrefab(def.Id, def.BasePrefab); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)("Missing base prefab " + def.BasePrefab + " for " + def.Id)); return null; } ((Object)val).name = def.Id; Piece component = val.GetComponent<Piece>(); if ((Object)(object)component != (Object)null) { component.m_name = Loc.Token(def.NameToken); component.m_description = Loc.Token(def.DescToken); component.m_resources = Array.Empty<Requirement>(); component.m_icon = ToolIcons.Create(def.Icon); component.m_canRotate = true; ApplyWorkbenchRequirement(component); } TerrainOp componentInChildren = val.GetComponentInChildren<TerrainOp>(true); if ((Object)(object)componentInChildren != (Object)null) { if ((Object)(object)((Component)componentInChildren).gameObject != (Object)(object)val) { ((Object)((Component)componentInChildren).gameObject).name = def.Id; } Settings settings = componentInChildren.m_settings; if (def.Level.HasValue) { settings.m_level = def.Level.Value; } if (def.LevelRadius.HasValue) { settings.m_levelRadius = def.LevelRadius.Value; } if (def.Raise.HasValue) { settings.m_raise = def.Raise.Value; } if (def.RaiseRadius.HasValue) { settings.m_raiseRadius = def.RaiseRadius.Value; } if (def.RaisePower.HasValue) { settings.m_raisePower = def.RaisePower.Value; } if (def.RaiseDelta.HasValue) { settings.m_raiseDelta = def.RaiseDelta.Value; } if (def.Smooth.HasValue) { settings.m_smooth = def.Smooth.Value; } if (def.SmoothRadius.HasValue) { settings.m_smoothRadius = def.SmoothRadius.Value; } if (def.SmoothPower.HasValue) { settings.m_smoothPower = def.SmoothPower.Value; } if (def.PaintCleared.HasValue) { settings.m_paintCleared = def.PaintCleared.Value; } if (def.PaintRadius.HasValue) { settings.m_paintRadius = def.PaintRadius.Value; } settings.m_square = def.Square; if (def.IsReset) { settings.m_level = false; settings.m_smooth = false; settings.m_raise = false; settings.m_paintCleared = false; } } else { Plugin.Log.LogWarning((object)("No TerrainOp on " + def.Id + " (base " + def.BasePrefab + ")")); } if (def.InvertGhost) { Transform val2 = val.transform.Find("_GhostOnly"); if ((Object)(object)val2 != (Object)null) { val2.localRotation = Quaternion.Euler(270f, 0f, 0f); val2.localPosition += new Vector3(0f, 2f, 0f); } } if (def.IsReset) { val.AddComponent<ResetTerrainMarker>(); } if (def.IsLower) { val.AddComponent<LowerTerrainMarker>(); } if (def.Square) { val.AddComponent<SquareToolMarker>(); } if (def.Raise == true) { val.AddComponent<HeightToolMarker>(); } return val; } private static void RegisterInTable(GameObject prefab) { PieceTable pieceTable = PieceManager.Instance.GetPieceTable("_TSP_PieceTable"); if ((Object)(object)pieceTable == (Object)null) { Plugin.Log.LogWarning((object)"Piece table _TSP_PieceTable not found."); } else if (!pieceTable.m_pieces.Contains(prefab)) { if ((Object)(object)ZNetScene.instance != (Object)null) { PrefabManager.Instance.RegisterToZNetScene(prefab); } pieceTable.m_pieces.Add(prefab); } } internal static void ApplyPlacementRules() { foreach (GameObject value in Prefabs.Values) { if (!((Object)(object)value == (Object)null)) { Piece component = value.GetComponent<Piece>(); if (!((Object)(object)component == (Object)null)) { component.m_canRotate = true; ApplyWorkbenchRequirement(component); } } } Plugin.Log.LogInfo((object)$"Placement rules: RequireWorkbench={ModConfig.RequireWorkbenchToPlace.Value}, canRotate=true"); } private static void ApplyWorkbenchRequirement(Piece piece) { if ((Object)(object)piece == (Object)null) { return; } if (!ModConfig.RequireWorkbenchToPlace.Value) { piece.m_craftingStation = null; return; } CraftingStation val = FindWorkbenchStation(); if ((Object)(object)val != (Object)null) { piece.m_craftingStation = val; } } private static CraftingStation FindWorkbenchStation() { GameObject val = null; if ((Object)(object)ZNetScene.instance != (Object)null) { val = ZNetScene.instance.GetPrefab("piece_workbench"); } if ((Object)(object)val == (Object)null) { val = PrefabManager.Instance.GetPrefab("piece_workbench"); } if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<CraftingStation>(); } } internal class ResetTerrainMarker : MonoBehaviour { } internal class LowerTerrainMarker : MonoBehaviour { } internal class SquareToolMarker : MonoBehaviour { } internal class HeightToolMarker : MonoBehaviour { } internal class PreciseRaiseMarker : MonoBehaviour { } internal static class ShaperItem { internal const string PrefabName = "TSP_TerrainShaperPlus"; internal const string ItemNameToken = "$tsp_item_name"; private static bool _created; internal static void Create() { if (!_created) { CreatePieceTable(); CreateItem(); ItemManager.OnItemsRegistered += EnsureRepairable; _created = true; } } private static void CreatePieceTable() { //IL_0000: 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_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_001b: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown PieceTableConfig val = new PieceTableConfig { CanRemovePieces = false, UseCategories = false, UseCustomCategories = false }; PieceManager.Instance.AddPieceTable(new CustomPieceTable("_TSP_PieceTable", val)); } private static void CreateItem() { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Expected O, but got Unknown //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Expected O, but got Unknown GameObject val = PrefabManager.Instance.CreateClonedPrefab("TSP_TerrainShaperPlus", "Hoe"); if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)"Failed to clone Hoe for Terrain Shaper Plus."); return; } ItemDrop component = val.GetComponent<ItemDrop>(); if (component?.m_itemData?.m_shared != null) { ApplyDurability(component.m_itemData.m_shared); component.m_itemData.m_dropPrefab = val; } List<RequirementConfig> list = new List<RequirementConfig> { new RequirementConfig("Wood", ModConfig.RecipeWood.Value, 0, true), new RequirementConfig("Stone", ModConfig.RecipeStone.Value, 0, true) }; ItemConfig val2 = new ItemConfig { Name = Loc.Token("tsp_item_name"), Description = Loc.Token("tsp_item_desc"), CraftingStation = CraftingStations.Workbench, RepairStation = CraftingStations.Workbench, MinStationLevel = ModConfig.MinWorkbenchLevel.Value, PieceTable = "_TSP_PieceTable", Requirements = list.ToArray() }; CustomItem val3 = new CustomItem(val, true, val2); CustomRecipe recipe = val3.Recipe; if ((Object)(object)((recipe != null) ? recipe.Recipe : null) != (Object)null) { val3.Recipe.Recipe.m_enabled = ModConfig.EnableTool.Value; } ItemManager.Instance.AddItem(val3); Plugin.Log.LogInfo((object)string.Format("Registered craftable/repairable item {0} at Workbench (min level {1}).", "TSP_TerrainShaperPlus", ModConfig.MinWorkbenchLevel.Value)); } private static void EnsureRepairable() { GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab("TSP_TerrainShaperPlus") : null); if ((Object)(object)val == (Object)null) { val = PrefabManager.Instance.GetPrefab("TSP_TerrainShaperPlus"); } if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)"EnsureRepairable: prefab not found."); return; } ItemDrop component = val.GetComponent<ItemDrop>(); if (component?.m_itemData?.m_shared == null) { return; } component.m_itemData.m_shared.m_name = "$tsp_item_name"; ApplyDurability(component.m_itemData.m_shared); component.m_itemData.m_dropPrefab = val; CraftingStation val2 = FindWorkbenchStation(); if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogWarning((object)"EnsureRepairable: piece_workbench CraftingStation not found."); return; } Recipe val3 = null; if ((Object)(object)ObjectDB.instance != (Object)null) { foreach (Recipe recipe in ObjectDB.instance.m_recipes) { if (!((Object)(object)recipe == (Object)null) && !((Object)(object)recipe.m_item == (Object)null) && ((Object)(object)recipe.m_item == (Object)(object)component || ((Object)recipe).name == "Recipe_TSP_TerrainShaperPlus" || (recipe.m_item.m_itemData?.m_shared != null && recipe.m_item.m_itemData.m_shared.m_name == "$tsp_item_name"))) { val3 = recipe; break; } } } if ((Object)(object)val3 == (Object)null) { Plugin.Log.LogWarning((object)"EnsureRepairable: recipe not found in ObjectDB."); return; } val3.m_item = component; val3.m_craftingStation = val2; val3.m_repairStation = val2; val3.m_enabled = ModConfig.EnableTool.Value; val3.m_minStationLevel = Mathf.Clamp(ModConfig.MinWorkbenchLevel.Value, 1, 5); if ((Object)(object)ObjectDB.instance != (Object)null) { ObjectDBTerrainOpPatch.RegisterTerrainOps(ObjectDB.instance); } ManualLogSource log = Plugin.Log; string[] obj = new string[8] { "EnsureRepairable OK: recipe=", ((Object)val3).name, ", craft=", null, null, null, null, null }; CraftingStation craftingStation = val3.m_craftingStation; obj[3] = ((craftingStation != null) ? ((Object)craftingStation).name : null); obj[4] = ", "; CraftingStation repairStation = val3.m_repairStation; obj[5] = $"repair={((repairStation != null) ? ((Object)repairStation).name : null)}, minLevel={val3.m_minStationLevel}, "; obj[6] = $"durability={component.m_itemData.m_shared.m_maxDurability:0} "; obj[7] = $"(drain={component.m_itemData.m_shared.m_useDurabilityDrain:0.##})"; log.LogInfo((object)string.Concat(obj)); } internal static void ApplyDurability(SharedData shared) { if (shared != null) { shared.m_canBeReparied = true; shared.m_useDurability = true; shared.m_maxDurability = Mathf.Clamp(ModConfig.MaxDurability.Value, 50f, 10000f); shared.m_durabilityPerLevel = Mathf.Clamp(ModConfig.DurabilityPerLevel.Value, 0f, 2000f); shared.m_useDurabilityDrain = Mathf.Clamp(ModConfig.DurabilityDrain.Value, 0.05f, 5f); } } private static CraftingStation FindWorkbenchStation() { GameObject val = null; if ((Object)(object)ZNetScene.instance != (Object)null) { val = ZNetScene.instance.GetPrefab("piece_workbench"); } if ((Object)(object)val == (Object)null) { val = PrefabManager.Instance.GetPrefab("piece_workbench"); } if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<CraftingStation>(); } internal static bool IsOurItem(ItemData item) { if (item?.m_shared == null) { return false; } if (item.m_shared.m_name == "$tsp_item_name") { return true; } if ((Object)(object)item.m_dropPrefab != (Object)null && Utils.GetPrefabName(((Object)item.m_dropPrefab).name) == "TSP_TerrainShaperPlus") { return true; } return false; } internal static bool IsEquipped(Player player) { if ((Object)(object)player == (Object)null) { return false; } ItemData rightItem = ((Humanoid)player).GetRightItem(); if (rightItem == null) { return false; } if (IsOurItem(rightItem)) { return true; } if ((Object)(object)rightItem.m_dropPrefab != (Object)null) { string prefabName = Utils.GetPrefabName(((Object)rightItem.m_dropPrefab).name); if (prefabName == "TSP_TerrainShaperPlus" || prefabName.StartsWith("TSP_")) { return true; } } if (rightItem.m_shared != null && (Object)(object)rightItem.m_shared.m_buildPieces != (Object)null && ((Object)rightItem.m_shared.m_buildPieces).name != null) { return ((Object)rightItem.m_shared.m_buildPieces).name.IndexOf("TSP_", StringComparison.OrdinalIgnoreCase) >= 0; } return false; } } internal sealed class ToolDef { public string Id; public string BasePrefab; public string NameToken; public string DescToken; public bool? Level; public float? LevelRadius; public bool? Raise; public float? RaiseRadius; public float? RaisePower; public float? RaiseDelta; public bool? Smooth; public float? SmoothRadius; public float? SmoothPower; public bool? PaintCleared; public float? PaintRadius; public bool Square; public bool InvertGhost; public bool IsReset; public bool IsLower; public IconStyle Icon; } internal enum IconStyle { Default, Raise, Lower, Smooth, Reset, Paint } internal static class ToolDefs { internal const string PieceTable = "_TSP_PieceTable"; internal static readonly List<ToolDef> All = new List<ToolDef> { new ToolDef { Id = "TSP_level", BasePrefab = "mud_road_v2", NameToken = "tsp_piece_level", DescToken = "tsp_piece_level_desc", Level = true, Smooth = false, Raise = false, Icon = IconStyle.Default }, new ToolDef { Id = "TSP_level_sq", BasePrefab = "mud_road_v2", NameToken = "tsp_piece_level_sq", DescToken = "tsp_piece_level_sq_desc", Level = true, Smooth = false, Raise = false, Square = true, Icon = IconStyle.Default }, new ToolDef { Id = "TSP_raise", BasePrefab = "raise_v2", NameToken = "tsp_piece_raise", DescToken = "tsp_piece_raise_desc", Raise = true, RaiseDelta = 1f, RaisePower = 0.5f, Icon = IconStyle.Raise }, new ToolDef { Id = "TSP_raise_sq", BasePrefab = "raise_v2", NameToken = "tsp_piece_raise_sq", DescToken = "tsp_piece_raise_sq_desc", Raise = true, RaiseDelta = 1f, RaisePower = 0.5f, Square = true, Icon = IconStyle.Raise }, new ToolDef { Id = "TSP_lower", BasePrefab = "raise_v2", NameToken = "tsp_piece_lower", DescToken = "tsp_piece_lower_desc", Raise = true, RaiseDelta = -1f, RaisePower = 0.5f, RaiseRadius = 1.5f, InvertGhost = true, IsLower = true, Icon = IconStyle.Lower }, new ToolDef { Id = "TSP_lower_sq", BasePrefab = "raise_v2", NameToken = "tsp_piece_lower_sq", DescToken = "tsp_piece_lower_sq_desc", Raise = true, RaiseDelta = -1f, RaisePower = 0.5f, RaiseRadius = 1.5f, InvertGhost = true, IsLower = true, Square = true, Icon = IconStyle.Lower }, new ToolDef { Id = "TSP_smooth", BasePrefab = "mud_road_v2", NameToken = "tsp_piece_smooth", DescToken = "tsp_piece_smooth_desc", Level = false, Smooth = true, Raise = false, SmoothPower = 3f, Icon = IconStyle.Smooth }, new ToolDef { Id = "TSP_reset", BasePrefab = "mud_road_v2", NameToken = "tsp_piece_reset", DescToken = "tsp_piece_reset_desc", Level = false, Smooth = false, Raise = false, PaintCleared = false, IsReset = true, Icon = IconStyle.Reset }, new ToolDef { Id = "TSP_paint_dirt", BasePrefab = "path_v2", NameToken = "tsp_piece_paint_dirt", DescToken = "tsp_piece_paint_dirt_desc", Level = false, Smooth = false, Raise = false, Icon = IconStyle.Paint }, new ToolDef { Id = "TSP_paint_paved", BasePrefab = "paved_road_v2", NameToken = "tsp_piece_paint_paved", DescToken = "tsp_piece_paint_paved_desc", Level = false, Smooth = false, Raise = false, Icon = IconStyle.Paint }, new ToolDef { Id = "TSP_paint_cultivate", BasePrefab = "cultivate_v2", NameToken = "tsp_piece_paint_cultivate", DescToken = "tsp_piece_paint_cultivate_desc", Level = false, Smooth = false, Raise = false, Icon = IconStyle.Paint }, new ToolDef { Id = "TSP_paint_reset", BasePrefab = "replant_v2", NameToken = "tsp_piece_paint_reset", DescToken = "tsp_piece_paint_reset_desc", Level = false, Smooth = false, Raise = false, Icon = IconStyle.Paint } }; internal static IEnumerable<string> AllIds { get { foreach (ToolDef item in All) { yield return item.Id; } } } } internal static class ToolIcons { internal static Sprite Create(IconStyle style) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0020: 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_007b: 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_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_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false); new Color(0f, 0f, 0f, 0f); Color val2 = default(Color); ((Color)(ref val2))..ctor(0.18f, 0.14f, 0.1f, 0.92f); Color val3 = (Color)(style switch { IconStyle.Raise => new Color(0.35f, 0.85f, 0.35f, 1f), IconStyle.Lower => new Color(0.95f, 0.45f, 0.2f, 1f), IconStyle.Smooth => new Color(0.35f, 0.65f, 0.95f, 1f), IconStyle.Reset => new Color(0.95f, 0.3f, 0.3f, 1f), IconStyle.Paint => new Color(0.85f, 0.7f, 0.3f, 1f), _ => new Color(0.75f, 0.7f, 0.55f, 1f), }); for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { val.SetPixel(j, i, val2); } } FillCircle(val, 32, 32, 30, val3 * 0.25f); switch (style) { case IconStyle.Raise: DrawArrow(val, up: true, val3); break; case IconStyle.Lower: DrawArrow(val, up: false, val3); break; case IconStyle.Smooth: DrawWave(val, val3); break; case IconStyle.Reset: DrawX(val, val3); break; case IconStyle.Paint: DrawBrush(val, val3); break; default: DrawFlat(val, val3); break; } val.Apply(); return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f)); } private static void FillCircle(Texture2D tex, int cx, int cy, int r, Color c) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) int num = r * r; for (int i = cy - r; i <= cy + r; i++) { for (int j = cx - r; j <= cx + r; j++) { if (j >= 0 && i >= 0 && j < ((Texture)tex).width && i < ((Texture)tex).height) { int num2 = j - cx; int num3 = i - cy; if (num2 * num2 + num3 * num3 <= num) { tex.SetPixel(j, i, c); } } } } } private static void DrawArrow(Texture2D tex, bool up, Color c) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) int num = ((Texture)tex).width / 2; for (int i = 18; i <= 46; i++) { for (int j = num - 4; j <= num + 4; j++) { tex.SetPixel(j, i, c); } } if (up) { for (int k = 0; k < 16; k++) { for (int l = num - k; l <= num + k; l++) { tex.SetPixel(l, 46 + (16 - k) / 2, c); } } return; } for (int m = 0; m < 16; m++) { for (int n = num - m; n <= num + m; n++) { tex.SetPixel(n, 18 - (16 - m) / 2, c); } } } private static void DrawWave(Texture2D tex, Color c) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) for (int i = 10; i < ((Texture)tex).width - 10; i++) { int num = ((Texture)tex).height / 2 + (int)(Mathf.Sin((float)i * 0.35f) * 10f); for (int j = -2; j <= 2; j++) { tex.SetPixel(i, num + j, c); } } } private static void DrawX(Texture2D tex, Color c) { //IL_0008: 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_002d: Unknown result type (might be due to invalid IL or missing references) for (int i = 14; i < 50; i++) { tex.SetPixel(i, i, c); tex.SetPixel(i + 1, i, c); tex.SetPixel(i, 63 - i, c); tex.SetPixel(i + 1, 63 - i, c); } } private static void DrawBrush(Texture2D tex, Color c) { //IL_002c: 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) for (int i = 12; i < 40; i++) { for (int j = 28; j < 36; j++) { tex.SetPixel(j, i, c); } } FillCircle(tex, 32, 48, 10, c); } private static void DrawFlat(Texture2D tex, Color c) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) for (int i = 28; i <= 36; i++) { for (int j = 12; j < 52; j++) { tex.SetPixel(j, i, c); } } } } } namespace TerrainShaperPlus.Terrain { internal static class ResetTerrain { internal static void Apply(Vector3 position, float radiusMeters, bool square, float yawDegrees = 0f) { //IL_0053: 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_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) radiusMeters = Mathf.Clamp(radiusMeters, 0.5f, ModConfig.MaxRadius.Value); bool rotate = square && ModConfig.GridFollowPieceRotation.Value && Mathf.Abs(Mathf.DeltaAngle(0f, yawDegrees)) > 0.5f; Plugin.Log.LogInfo((object)$"ResetTerrain.Apply at {position}, radius={radiusMeters:0.##}m square={square} yaw={yawDegrees:0.#}"); int num = 0; foreach (TerrainModifier allInstance in TerrainModifier.GetAllInstances()) { if (!((Object)(object)allInstance == (Object)null) && InBrush(position, ((Component)allInstance).transform.position, radiusMeters, square, yawDegrees, rotate)) { ZNetView component = ((Component)allInstance).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null)) { component.ClaimOwnership(); component.Destroy(); num++; } } } List<Heightmap> list = new List<Heightmap>(); Heightmap.FindHeightmap(position, radiusMeters + 50f, list); bool flag = false; int num2 = 0; int cx = default(int); int cy = default(int); foreach (Heightmap item in list) { if ((Object)(object)item == (Object)null) { continue; } TerrainComp val = TerrainComp.FindTerrainCompiler(((Component)item).transform.position); if ((Object)(object)val == (Object)null || !val.m_initialized) { continue; } if (!val.IsOwner()) { ZNetView component2 = ((Component)val).GetComponent<ZNetView>(); if (component2 != null) { component2.ClaimOwnership(); } } item.WorldToVertex(position, ref cx, ref cy); float num3 = Mathf.Max(0.01f, item.m_scale); float vertexRadius = radiusMeters / num3; int width = val.m_width; float[] levelDelta = val.m_levelDelta; float[] smoothDelta = val.m_smoothDelta; bool[] modifiedHeight = val.m_modifiedHeight; Color[] paintMask = val.m_paintMask; bool[] modifiedPaint = val.m_modifiedPaint; if (levelDelta == null || modifiedHeight == null) { continue; } bool flag2 = false; for (int i = 0; i <= width; i++) { for (int j = 0; j <= width; j++) { if (!InBrushVertex(cx, cy, j, i, vertexRadius, square, item.m_scale, yawDegrees, rotate)) { continue; } int num4 = j + i * (width + 1); if (num4 >= 0 && num4 < modifiedHeight.Length && modifiedHeight[num4]) { modifiedHeight[num4] = false; levelDelta[num4] = 0f; if (smoothDelta != null && num4 < smoothDelta.Length) { smoothDelta[num4] = 0f; } flag2 = true; flag = true; } if (i < width && j < width && modifiedPaint != null && paintMask != null) { int num5 = j + i * width; if (num5 >= 0 && num5 < modifiedPaint.Length && modifiedPaint[num5]) { modifiedPaint[num5] = false; paintMask[num5] = Color.clear; flag2 = true; flag = true; } } } } if (flag2) { num2++; val.m_levelDelta = levelDelta; val.m_smoothDelta = smoothDelta; val.m_modifiedHeight = modifiedHeight; val.m_paintMask = paintMask; val.m_modifiedPaint = modifiedPaint; val.Save(false); item.Poke(0, false); ZNetView component3 = ((Component)val).GetComponent<ZNetView>(); ZDO val2 = ((component3 != null) ? component3.GetZDO() : null); if (val2 != null) { ZDOMan.instance.ForceSendZDO(val2.m_uid); } } } if ((Object)(object)ClutterSystem.instance != (Object)null && flag) { ClutterSystem.instance.ResetGrass(position, radiusMeters); } Plugin.Log.LogInfo((object)$"ResetTerrain done: modifiersRemoved={num}, heightmapsTouched={num2}"); } private static bool InBrush(Vector3 center, Vector3 point, float radius, bool square, float yaw, bool rotate) { //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_000e: 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) float num = point.x - center.x; float num2 = point.z - center.z; if (square) { if (rotate) { RotatedBrush.ToLocal(num, num2, yaw, out var localX, out var localZ); return RotatedBrush.InSquareLocal(localX, localZ, radius); } return Mathf.Max(Mathf.Abs(num), Mathf.Abs(num2)) <= radius; } return num * num + num2 * num2 <= radius * radius; } private static bool InBrushVertex(int cx, int cy, int x, int y, float vertexRadius, bool square, float scale, float yaw, bool rotate) { float num = x - cx; float num2 = y - cy; if (square) { if (rotate) { float worldDx = num * scale; float worldDz = num2 * scale; RotatedBrush.ToLocal(worldDx, worldDz, yaw, out var localX, out var localZ); return Mathf.Max(Mathf.Abs(localX), Mathf.Abs(localZ)) / Mathf.Max(0.01f, scale) <= vertexRadius; } return Mathf.Max(Mathf.Abs(num), Mathf.Abs(num2)) <= vertexRadius; } return num * num + num2 * num2 <= vertexRadius * vertexRadius; } } internal static class RotatedBrush { internal static float NextYawDegrees; internal static bool HasYaw => Mathf.Abs(Mathf.DeltaAngle(0f, NextYawDegrees)) > 0.5f; internal static void Clear() { NextYawDegrees = 0f; } internal static void SetFromTransform(Transform t) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) NextYawDegrees = (((Object)(object)t != (Object)null) ? t.eulerAngles.y : 0f); } internal static void ToLocal(float worldDx, float worldDz, float yawDegrees, out float localX, out float localZ) { float num = (0f - yawDegrees) * ((float)Math.PI / 180f); float num2 = Mathf.Cos(num); float num3 = Mathf.Sin(num); localX = worldDx * num2 - worldDz * num3; localZ = worldDx * num3 + worldDz * num2; } internal static bool InSquareLocal(float localX, float localZ, float halfExtent) { return Mathf.Max(Mathf.Abs(localX), Mathf.Abs(localZ)) <= halfExtent; } internal static bool InCircleLocal(float localX, float localZ, float radius) { return localX * localX + localZ * localZ <= radius * radius; } internal static float SnapYaw(float yawDegrees, float stepDegrees) { if (stepDegrees <= 0.01f) { return yawDegrees; } return Mathf.Round(yawDegrees / stepDegrees) * stepDegrees; } } } namespace TerrainShaperPlus.Patches { [HarmonyPatch] internal static class BrushOutlinePatch { [HarmonyPostfix] [HarmonyPatch(typeof(Player), "UpdatePlacementGhost")] private static void UpdatePlacementGhostPostfix(Player __instance) { //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.ShowBrushOutline.Value) { BrushOutlinePreview.Hide(); RestoreGhostVisuals(__instance); } else { if ((Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } if (!ShaperItem.IsEquipped(__instance) || !((Character)__instance).InPlaceMode()) { BrushOutlinePreview.Hide(); return; } if ((Object)(object)__instance.m_placementGhost == (Object)null || !__instance.m_placementGhost.activeInHierarchy) { BrushOutlinePreview.Hide(); return; } Piece selectedPiece = __instance.GetSelectedPiece(); if ((Object)(object)selectedPiece == (Object)null || (Object)(object)((Component)selectedPiece).gameObject == (Object)null) { BrushOutlinePreview.Hide(); RestoreGhostVisuals(__instance); return; } string prefabName = Utils.GetPrefabName(((Object)((Component)selectedPiece).gameObject).name); if (!prefabName.StartsWith("TSP_")) { BrushOutlinePreview.Hide(); RestoreGhostVisuals(__instance); return; } bool flag = ShapeSettings.Square || (Object)(object)((Component)selectedPiece).gameObject.GetComponent<SquareToolMarker>() != (Object)null || prefabName.IndexOf("_sq", StringComparison.OrdinalIgnoreCase) >= 0; bool showHeightVolume = (Object)(object)((Component)selectedPiece).gameObject.GetComponent<HeightToolMarker>() != (Object)null || prefabName.IndexOf("raise", StringComparison.OrdinalIgnoreCase) >= 0 || prefabName.IndexOf("lower", StringComparison.OrdinalIgnoreCase) >= 0; bool lower = (Object)(object)((Component)selectedPiece).gameObject.GetComponent<LowerTerrainMarker>() != (Object)null || prefabName.IndexOf("lower", StringComparison.OrdinalIgnoreCase) >= 0; if (flag) { SetGhostVisuals(__instance, visible: false); } else { SetGhostVisuals(__instance, visible: true); } BrushOutlinePreview.Show(__instance.m_placementGhost.transform.position, yawDegrees: __instance.m_placementGhost.transform.eulerAngles.y, width: ShapeSettings.Width, height: ShapeSettings.Height, square: flag, showHeightVolume: showHeightVolume, lower: lower); } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "Update")] private static void PlayerUpdatePostfix(Player __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && (!ShaperItem.IsEquipped(__instance) || !((Character)__instance).InPlaceMode())) { BrushOutlinePreview.Hide(); } } private static void RestoreGhostVisuals(Player player) { if ((Object)(object)player != (Object)null) { SetGhostVisuals(player, visible: true); } } private static void SetGhostVisuals(Player player, bool visible) { if ((Object)(object)player.m_placementGhost != (Object)null) { SetRenderers(player.m_placementGhost, visible); } if ((Object)(object)player.m_placementMarkerInstance != (Object)null) { SetRenderers(player.m_placementMarkerInstance, visible); } } private static void SetRenderers(GameObject go, bool visible) { if ((Object)(object)go == (Object)null) { return; } Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null) { componentsInChildren[i].enabled = visible; } } } } [HarmonyPatch] internal static class CameraZoomBlockPatch { private static float _savedDistance; private static bool _restore; [HarmonyPrefix] [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] private static void Prefix(GameCamera __instance) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) _restore = false; Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && ((Character)localPlayer).InPlaceMode() && Input.mouseScrollDelta.y != 0f && (ShouldBlockZoomForShaper(localPlayer) || ShouldBlockZoomForFarm(localPlayer))) { _savedDistance = __instance.m_distance; _restore = true; } } [HarmonyPostfix] [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] private static void Postfix(GameCamera __instance) { if (_restore) { __instance.m_distance = _savedDistance; } } private static bool ShouldBlockZoomForShaper(Player player) { //IL_004e: 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_008a: 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) if (!ShaperItem.IsEquipped(player)) { return false; } Piece selectedPiece = player.GetSelectedPiece(); bool flag = (Object)(object)selectedPiece != (Object)null && (Object)(object)((Component)selectedPiece).gameObject != (Object)null && (Object)(object)((Component)selectedPiece).gameObject.GetComponent<HeightToolMarker>() != (Object)null; if ((!ModConfig.EnableRadiusModifier.Value || !ModConfig.IsKeyHeld(ModConfig.RadiusModKey.Value)) && (!ModConfig.EnableSharpnessModifier.Value || !ModConfig.IsKeyHeld(ModConfig.SharpnessModKey.Value))) { if (ModConfig.EnableHeightModifier.Value && flag && !ModConfig.IsKeyHeld(ModConfig.RadiusModKey.Value)) { return !ModConfig.IsKeyHeld(ModConfig.SharpnessModKey.Value); } return false; } return true; } private static bool ShouldBlockZoomForFarm(Player player) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.FarmGridEnabled.Value) { return false; } if (!ModConfig.IsKeyHeld(ModConfig.FarmSizeModKey.Value)) { return false; } ItemData rightItem = ((Humanoid)player).GetRightItem(); if (rightItem?.m_shared != null) { return rightItem.m_shared.m_name == "$item_cultivator"; } return false; } } [HarmonyPatch] internal static class GridSnapPatch { private static Vector3? _anchor; private static float _nextHint; private static float _nextOpsEnsure; [HarmonyPostfix] [HarmonyPatch(typeof(Player), "UpdatePlacementGhost")] private static void UpdatePlacementGhostPostfix(Player __instance) { //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !ShaperItem.IsEquipped(__instance) || !((Character)__instance).InPlaceMode()) { return; } if (Time.time >= _nextOpsEnsure) { _nextOpsEnsure = Time.time + 2f; ObjectDBTerrainOpPatch.EnsureRegistered(); } if ((Object)(object)__instance.m_placementGhost == (Object)null || !__instance.m_placementGhost.activeInHierarchy) { return; } Piece selectedPiece = __instance.GetSelectedPiece(); if ((Object)(object)selectedPiece == (Object)null) { return; } bool flag = ShapeSettings.Square || (Object)(object)((Component)selectedPiece).gameObject.GetComponent<SquareToolMarker>() != (Object)null || Utils.GetPrefabName(((Object)((Component)selectedPiece).gameObject).name).IndexOf("_sq", StringComparison.OrdinalIgnoreCase) >= 0; if (ModConfig.GridFollowPieceRotation.Value && flag && !selectedPiece.m_canRotate) { selectedPiece.m_canRotate = true; } Transform transform = __instance.m_placementGhost.transform; if (flag && ModConfig.GridFollowPieceRotation.Value && ModConfig.GridRotationSnapDegrees.Value > 0.01f) { float y = transform.eulerAngles.y; float num = RotatedBrush.SnapYaw(y, ModConfig.GridRotationSnapDegrees.Value); if (Mathf.Abs(Mathf.DeltaAngle(y, num)) > 0.05f) { transform.rotation = Quaternion.Euler(0f, num, 0f); } } if (!ModConfig.IsGridSnapActive() || (!flag && !ModConfig.GridSnapAlways.Value)) { return; } float num2 = Mathf.Max(0.5f, ShapeSettings.Width * 2f); Vector3 position = transform.position; float y2 = position.y; float num3 = (ModConfig.GridFollowPieceRotation.Value ? transform.eulerAngles.y : 0f); bool flag2 = Mathf.Abs(Mathf.DeltaAngle(0f, num3)) > 0.5f; Vector3 origin = (Vector3)(((??)_anchor) ?? SnapPoint(position, num2, num3, flag2)); Vector3 val = SnapRelative(position, origin, num2, num3, flag2); val.y = y2; float num4 = Mathf.Clamp(num2 * 0.4f, 0.75f, 2.5f); if (!((val.x - position.x) * (val.x - position.x) + (val.z - position.z) * (val.z - position.z) > num4 * num4)) { position.x = val.x; position.z = val.z; position.y = y2; transform.position = position; if ((Object)(object)__instance.m_placementMarkerInstance != (Object)null) { Vector3 position2 = __instance.m_placementMarkerInstance.transform.position; position2.x = position.x; position2.z = position.z; __instance.m_placementMarkerInstance.transform.position = position2; } if (Time.time >= _nextHint) { _nextHint = Time.time + 1.5f; string arg = (flag2 ? $", {num3:0}°" : ""); ((Character)__instance).Message((MessageType)1, $"Grid snap ({num2:0.##} m{arg})", 0, (Sprite)null, false); } } } private static Vector3 SnapPoint(Vector3 pos, float tile, float yaw, bool rotate) { //IL_002c: 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_007f: 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_0017: 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) if (!rotate) { return new Vector3(Mathf.Round(pos.x / tile) * tile, 0f, Mathf.Round(pos.z / tile) * tile); } RotatedBrush.ToLocal(pos.x, pos.z, yaw, out var localX, out var localZ); localX = Mathf.Round(localX / tile) * tile; localZ = Mathf.Round(localZ / tile) * tile; float num = yaw * ((float)Math.PI / 180f); float num2 = Mathf.Cos(num); float num3 = Mathf.Sin(num); return new Vector3(localX * num2 - localZ * num3, 0f, localX * num3 + localZ * num2); } private static Vector3 SnapRelative(Vector3 pos, Vector3 origin, float tile, float yaw, bool rotate) { //IL_0052: 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_005f: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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) //IL_0004: 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_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_0022: 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_004c: Unknown result type (might be due to invalid IL or missing references) if (!rotate) { float num = pos.x - origin.x; float num2 = pos.z - origin.z; return new Vector3(origin.x + Mathf.Round(num / tile) * tile, pos.y, origin.z + Mathf.Round(num2 / tile) * tile); } RotatedBrush.ToLocal(pos.x - origin.x, pos.z - origin.z, yaw, out var localX, out var localZ); localX = Mathf.Round(localX / tile) * tile; localZ = Mathf.Round(localZ / tile) * tile; float num3 = yaw * ((float)Math.PI / 180f); float num4 = Mathf.Cos(num3); float num5 = Mathf.Sin(num3); return new Vector3(origin.x + localX * num4 - localZ * num5, pos.y, origin.z + localX * num5 + localZ * num4); } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "PlacePiece", new Type[] { typeof(Piece), typeof(Vector3), typeof(Quaternion), typeof(bool), typeof(bool) })] private static void PlacePiecePostfix(Player __instance, Piece piece, Vector3 pos) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && ShaperItem.IsEquipped(__instance) && !((Object)(object)piece == (Object)null) && Utils.GetPrefabName(((Object)((Component)piece).gameObject).name).StartsWith("TSP_")) { _anchor = pos; } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "Update")] private static void PlayerUpdatePostfix(Player __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !ShaperItem.IsEquipped(__instance)) { _anchor = null; } } } [HarmonyPatch] internal static class HeightDeltaModifier { internal static float CurrentHeightMeters = 1f; private static float _nextMsg; [HarmonyPrefix] [HarmonyPatch(typeof(Player), "Update")] private static void PlayerUpdatePrefix(Player __instance) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !ShaperItem.IsEquipped(__instance) || !((Character)__instance).InPlaceMode() || Hud.IsPieceSelectionVisible() || ModConfig.IsKeyHeld(ModConfig.RadiusModKey.Value) || ModConfig.IsKeyHeld(ModConfig.SharpnessModKey.Value) || !ModConfig.EnableHeightModifier.Value || Input.mouseScrollDelta.y == 0f) { return; } Piece selectedPiece = __instance.GetSelectedPiece(); if ((Object)(object)selectedPiece == (Object)null || (Object)(object)((Component)selectedPiece).gameObject == (Object)null || (Object)(object)((Component)selectedPiece).gameObject.GetComponent<HeightToolMarker>() == (Object)null) { return; } TerrainOp componentInChildren = ((Component)selectedPiece).gameObject.GetComponentInChildren<TerrainOp>(true); if (!((Object)(object)componentInChildren == (Object)null) && componentInChildren.m_settings.m_raise) { float value = ModConfig.HeightScrollStep.Value; float num = ((Input.mouseScrollDelta.y > 0f) ? value : (0f - value)); CurrentHeightMeters = Mathf.Clamp(SnapHeight(CurrentHeightMeters + num), 0.5f, 8f); ShapeSettings.Height = CurrentHeightMeters; ShapeSettings.ApplyToSelectedPiece(__instance); ShapeSettings.ApplyToAllRegisteredPieces(); if (Time.time >= _nextMsg) { _nextMsg = Time.time + 0.05f; string text = Loc.Tf("tsp_msg_height_meters", CurrentHeightMeters); ((Character)__instance).Message((MessageType)2, text, 0, (Sprite)null, false); Plugin.Log.LogInfo((object)text); } } } internal static void ApplyHeightToPiece(Piece piece, TerrainOp op) { bool flag = (Object)(object)((Component)piece).gameObject.GetComponent<LowerTerrainMarker>() != (Object)null || Utils.GetPrefabName(((Object)((Component)piece).gameObject).name).IndexOf("lower", StringComparison.OrdinalIgnoreCase) >= 0; op.m_settings.m_raiseDelta = (flag ? (0f - CurrentHeightMeters) : CurrentHeightMeters); } private static float SnapHeight(float value) { float num = Mathf.Max(0.05f, ModConfig.HeightScrollStep.Value); return Mathf.Round(value / num) * num; } } [HarmonyPatch] internal static class HoverInfoPatch { private static float _nextHover; [HarmonyPostfix] [HarmonyPatch(typeof(Player), "UpdatePlacementGhost")] private static void UpdatePlacementGhostPostfix(Player __instance) { //IL_00b2: 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) if (!ModConfig.HoverInfo.Value || (Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !ShaperItem.IsEquipped(__instance) || !((Character)__instance).InPlaceMode() || (Object)(object)__instance.m_placementGhost == (Object)null) { return; } Piece selectedPiece = __instance.GetSelectedPiece(); if (!((Object)(object)selectedPiece == (Object)null) && !((Object)(object)((Component)selectedPiece).gameObject == (Object)null) && (!((Object)(object)((Component)selectedPiece).gameObject.GetComponent<SquareToolMarker>() == (Object)null) || !((Object)(object)((Component)selectedPiece).gameObject.GetComponent<HeightToolMarker>() == (Object)null)) && !(Time.time < _nextHover)) { _nextHover = Time.time + 0.25f; Vector3 position = __instance.m_placementGhost.transform.position; float num = position.y; float num2 = default(float); if (Heightmap.GetHeight(positi