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 TerraHoe v2.0.0
TerraHoe.dll
Decompiled 2 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: InternalsVisibleTo("TerraHoe.WireTest")] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("TerraHoe")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("TerraHoe")] [assembly: AssemblyTitle("TerraHoe")] [assembly: AssemblyVersion("1.0.0.0")] namespace TerraHoe; [BepInPlugin("terrahoe", "TerraHoe", "2.0.0")] [BepInProcess("valheim.exe")] public class TerraHoePlugin : BaseUnityPlugin { [HarmonyPatch(typeof(TerrainComp), "LevelTerrain")] private static class LevelTerrainPatch { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { return RewriteClamp(instructions, "TerraformDelta"); } } [HarmonyPatch(typeof(TerrainComp), "RaiseTerrain")] private static class RaiseTerrainPatch { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { return RewriteClamp(instructions, "TerraformDelta"); } } [HarmonyPatch(typeof(TerrainComp), "ApplyToHeightmap")] private static class ApplyToHeightmapPatch { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { return RewriteClamp(instructions, "TerraformHeight"); } } private static class RadiusWire { internal const int Magic = 1413829170; internal const int Version = 2; internal const int PayloadBytes = 33; internal const int MaxScanBytes = 96; internal const float MaxSaneRadius = 500f; internal const float MaxSaneOffset = 200f; private const int FlagLevel = 1; private const int FlagRaise = 2; private const int FlagSmooth = 4; private const int FlagPaint = 8; private const int FlagSquare = 16; private static readonly MethodInfo _clone = typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic); private static bool _failureLogged; internal static void LogFailure(Exception ex) { if (!_failureLogged) { _failureLogged = true; if (_log != null) { _log.LogWarning((object)("RadiusWire failed, terrain falls back to the vanilla radius sync: " + ex)); } } } internal static void Write(Settings settings, ZPackage pkg) { if (settings != null && pkg != null && !(_clone == null)) { pkg.Write(1413829170); pkg.Write(2); pkg.Write(FlagsOf(settings)); pkg.Write(settings.m_levelRadius); pkg.Write(settings.m_raiseRadius); pkg.Write(settings.m_smoothRadius); pkg.Write(settings.m_paintRadius); pkg.Write(settings.m_square); pkg.Write(settings.m_levelOffset); if (NetworkLogEnabled()) { DebugLog($"wire sent: level={settings.m_level}/{settings.m_levelRadius:0.###}, " + $"raise={settings.m_raise}/{settings.m_raiseRadius:0.###}, " + $"smooth={settings.m_smooth}/{settings.m_smoothRadius:0.###}, " + $"paint={settings.m_paintCleared}/{settings.m_paintRadius:0.###}, square={settings.m_square}"); } } } internal static Settings Read(ZPackage pkg, Settings fallback) { if (pkg == null || fallback == null || _clone == null) { return fallback; } int pos = pkg.GetPos(); int num = pkg.Size(); try { int num2 = Mathf.Min(pos + 96, num - 33); for (int i = pos; i <= num2; i++) { pkg.SetPos(i); if (pkg.ReadInt() == 1413829170) { int num3 = pkg.ReadInt(); if (num3 != 2) { DebugLog($"wire payload version {num3} ignored, expected {2}"); break; } int num4 = pkg.ReadInt(); float num5 = pkg.ReadSingle(); float num6 = pkg.ReadSingle(); float num7 = pkg.ReadSingle(); float num8 = pkg.ReadSingle(); bool flag = pkg.ReadBool(); float num9 = pkg.ReadSingle(); if (!SaneRadius(num5) || !SaneRadius(num6) || !SaneRadius(num7) || !SaneRadius(num8) || !SaneOffset(num9)) { DebugWarning("wire payload rejected by validation, vanilla settings kept"); break; } if (NetworkLogEnabled()) { DebugLog($"wire received at +{i - pos}: level={num5:0.###}, " + $"raise={num6:0.###}, smooth={num7:0.###}, " + $"paint={num8:0.###}, square={flag}, flags={num4}"); } return WithSettings(fallback, num4, num5, num6, num7, num8, flag, num9); } } } catch (Exception ex) { LogFailure(ex); } pkg.SetPos(pos); return fallback; } private static int FlagsOf(Settings s) { int num = 0; if (s.m_level) { num |= 1; } if (s.m_raise) { num |= 2; } if (s.m_smooth) { num |= 4; } if (s.m_paintCleared) { num |= 8; } if (s.m_square) { num |= 0x10; } return num; } private static Settings WithSettings(Settings src, int flags, float levelRadius, float raiseRadius, float smoothRadius, float paintRadius, bool square, float levelOffset) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown Settings val = (Settings)_clone.Invoke(src, null); if (val == null) { return src; } val.m_level = (flags & 1) != 0; val.m_raise = (flags & 2) != 0; val.m_smooth = (flags & 4) != 0; val.m_paintCleared = (flags & 8) != 0; val.m_square = square; val.m_levelRadius = levelRadius; val.m_raiseRadius = raiseRadius; val.m_smoothRadius = smoothRadius; val.m_paintRadius = paintRadius; val.m_levelOffset = levelOffset; return val; } private static bool SaneRadius(float radius) { if (!float.IsNaN(radius) && !float.IsInfinity(radius) && radius >= 0f) { return radius <= 500f; } return false; } private static bool SaneOffset(float offset) { if (!float.IsNaN(offset) && !float.IsInfinity(offset) && offset >= -200f) { return offset <= 200f; } return false; } } [HarmonyPatch(typeof(Settings), "Serialize")] private static class SettingsSerializePatch { private static void Postfix(Settings __instance, ZPackage pkg) { if (!IsActive()) { return; } try { RadiusWire.Write(__instance, pkg); } catch (Exception ex) { RadiusWire.LogFailure(ex); } } } [HarmonyPatch(typeof(Settings), "Deserialize")] private static class SettingsDeserializePatch { private static void Postfix(ZPackage pkg, ref Settings __result) { if (!IsActive()) { return; } try { __result = RadiusWire.Read(pkg, __result); } catch (Exception ex) { RadiusWire.LogFailure(ex); } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] private static class ZNetSceneAwakePatch { [HarmonyPriority(0)] private static void Postfix(ZNetScene __instance) { if (!_suppressHoeDust.Value || (Object)(object)__instance == (Object)null || __instance.m_prefabs == null) { return; } int num = 0; for (int i = 0; i < __instance.m_prefabs.Count; i++) { GameObject val = __instance.m_prefabs[i]; if (!((Object)(object)val == (Object)null)) { Piece component = val.GetComponent<Piece>(); if ((Object)(object)component != (Object)null) { num += StripHoeDust(component); } } } if (num > 0 && !_dustStripLogged) { _dustStripLogged = true; _log.LogInfo((object)$"Dust suppression: removed {num} dust vfx entr(ies) from the hoe build pieces."); } } } [HarmonyPatch(typeof(Player), "PlacePiece")] private static class PlayerPlacePiecePatch { private static void Prefix(ref Piece piece) { StripHoeDust(piece); } } public const string PluginGuid = "terrahoe"; public const string PluginName = "TerraHoe"; public const string PluginVersion = "2.0.0"; internal const float VanillaDeltaLimit = 8f; internal const float VanillaHeightRange = 16f; internal const float Epsilon = 0.001f; private static ConfigEntry<bool> _enabled; private static ConfigEntry<KeyboardShortcut> _scrollModifier; private static ConfigEntry<float> _scrollStep; private static ConfigEntry<float> _minRadius; private static ConfigEntry<float> _maxRadius; private static ConfigEntry<bool> _showMessage; private static ConfigEntry<bool> _fullTerraformingEnabled; private static ConfigEntry<KeyboardShortcut> _fullTerraformingToggle; private static ConfigEntry<float> _minTerraformHeight; private static ConfigEntry<float> _maxTerraformHeight; private static ConfigEntry<bool> _suppressHoeDust; private static ConfigEntry<bool> _debugLogging; private static ConfigEntry<bool> _debugInput; private static ConfigEntry<bool> _debugSelection; private static ConfigEntry<bool> _debugNetwork; private static ConfigEntry<KeyboardShortcut> _debugToggle; private static ManualLogSource _log; private static FieldInfo _buildPieces; private static FieldInfo _placementGhost; private static TerrainOp _activeOperation; private static float _baseLevel; private static float _baseRaise; private static float _baseSmooth; private static float _basePaint; private static float _baseRadius; private static bool _baseLevelEnabled; private static bool _baseRaiseEnabled; private static bool _baseSmoothEnabled; private static bool _basePaintEnabled; private static float _currentRadius; private static float _lastMessageRadius = -1f; private static bool _lastModifierState; private static string _lastSelectionName; private static bool _fullTerraformingActive; private static bool _lastToggleState; private static bool _lastAppliedFullMode; private static bool _narrowClampWarned; private static bool _dustStripLogged; private void Awake() { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_030a: 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_0377: Unknown result type (might be due to invalid IL or missing references) //IL_037c: Unknown result type (might be due to invalid IL or missing references) //IL_037f: Unknown result type (might be due to invalid IL or missing references) _log = ((BaseUnityPlugin)this).Logger; _enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable TerraHoe radius control."); _fullTerraformingEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "FullTerraformingEnabled", true, "Allow terrain edits far beyond the vanilla +/-8 m limit. This is part of the terrain data contract: use the same value (and the same FullTerraforming.MinHeight/MaxHeight) on the server and on every client, otherwise the stored terrain cannot match everywhere."); _fullTerraformingToggle = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "FullTerraformingToggle", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Local toggle: place the flatten (level) operation only, instead of the selected hoe mode."); _scrollModifier = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Radius", "ScrollModifier", new KeyboardShortcut((KeyCode)306, Array.Empty<KeyCode>()), "Modifier held while scrolling the mouse wheel."); _scrollStep = ((BaseUnityPlugin)this).Config.Bind<float>("Radius", "ScrollStepMeters", 0.5f, "Radius change per mouse-wheel notch."); _minRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Radius", "MinRadius", 0.5f, "Minimum radius in metres."); _maxRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Radius", "MaxRadius", 100f, "Maximum radius in metres."); _showMessage = ((BaseUnityPlugin)this).Config.Bind<bool>("Radius", "ShowRadiusMessage", true, "Show the current radius in the top-left corner."); _minTerraformHeight = ((BaseUnityPlugin)this).Config.Bind<float>("FullTerraforming", "MinHeight", -200f, "Lowest per-vertex terrain delta in metres (negative = dig down). Values above -8 are ignored so the vanilla limit is never tightened."); _maxTerraformHeight = ((BaseUnityPlugin)this).Config.Bind<float>("FullTerraforming", "MaxHeight", 200f, "Highest per-vertex terrain delta in metres. Values below 8 are ignored so the vanilla limit is never tightened."); _suppressHoeDust = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects", "SuppressHoeDust", false, "Strip the dust vfx from the vanilla hoe pieces (road/raise/path/paved). Leave this OFF when NoHoeDust or MyDirtyHoe is installed: NoHoeDust does exactly the same work, and MyDirtyHoe replaces those effect lists with its own."); _debugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableDebugLogging", true, "Write TerraHoe diagnostic events to the BepInEx log."); _debugInput = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogInput", true, "When debug logging is enabled, log modifier and wheel events."); _debugSelection = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogSelection", true, "When debug logging is enabled, log selected TerrainOp changes."); _debugNetwork = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogNetwork", false, "Log the terrain settings that TerraHoe sends to and receives from the heightmap owner."); _debugToggle = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Debug", "DebugToggle", new KeyboardShortcut((KeyCode)290, Array.Empty<KeyCode>()), "Toggle diagnostic logging while playing."); _buildPieces = AccessTools.Field(typeof(Player), "m_buildPieces"); _placementGhost = AccessTools.Field(typeof(Player), "m_placementGhost"); _currentRadius = 0f; _fullTerraformingActive = false; new Harmony("terrahoe").PatchAll(typeof(TerraHoePlugin).Assembly); _log.LogInfo((object)"TerraHoe v2.0.0 loaded. RadiusWire network sync active."); ManualLogSource log = _log; object[] obj = new object[4] { _minRadius.Value, _maxRadius.Value, _scrollStep.Value, null }; KeyboardShortcut value = _scrollModifier.Value; obj[3] = ((KeyboardShortcut)(ref value)).MainKey; log.LogInfo((object)string.Format("Radius: {0:0.###}-{1:0.###} m, step {2:0.###} m, modifier {3}", obj)); _log.LogInfo((object)$"Terrain clamps: delta {ClampLow():0.#}..{ClampHigh():0.#} m (FullTerraformingEnabled={_fullTerraformingEnabled.Value})"); _log.LogInfo((object)"Terrain clamps are a multiplayer contract: identical config on the server and on every client."); ManualLogSource log2 = _log; value = _fullTerraformingToggle.Value; log2.LogInfo((object)$"Flatten-only toggle: {((KeyboardShortcut)(ref value)).MainKey}, active={_fullTerraformingActive}"); _log.LogInfo((object)$"Dust suppression: {_suppressHoeDust.Value}"); _log.LogInfo((object)$"Debug config: enabled={_debugLogging.Value}, input={_debugInput.Value}, selection={_debugSelection.Value}, network={_debugNetwork.Value}"); DebugLog($"Reflection: m_buildPieces={_buildPieces != null}, m_placementGhost={_placementGhost != null}"); LogModConflicts(); } private static void LogModConflicts() { bool flag = false; bool flag2 = false; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { string name = assemblies[i].GetName().Name; if (name == "MyDirtyHoe") { flag = true; } else if (name == "NoHoeDust") { flag2 = true; } } if (flag) { _log.LogWarning((object)"MyDirtyHoe is loaded and patches the same terrain methods as TerraHoe (TerrainOp.Settings.Serialize/Deserialize, TerrainComp.ApplyOperation, TerrainOp.Awake). Terrain operations can be applied twice and the radius payloads compete. Run only one of the two mods."); } if (flag2) { string text = (_suppressHoeDust.Value ? "SuppressHoeDust is enabled as well, so both mods strip the same dust vfx. Drop one." : "Dust stays with NoHoeDust, TerraHoe does not touch any effect list."); _log.LogInfo((object)("NoHoeDust is loaded: " + text)); } else if (!_suppressHoeDust.Value) { _log.LogInfo((object)"No dust-removal mod detected and SuppressHoeDust is off: vanilla hoe dust stays active."); } } private static bool IsActive() { if (_enabled != null) { return _enabled.Value; } return false; } private static void DebugLog(string message) { if (_debugLogging != null && _debugLogging.Value) { _log.LogInfo((object)("[Debug] " + message)); } } private static void DebugWarning(string message) { if (_debugLogging != null && _debugLogging.Value) { _log.LogWarning((object)("[Debug] " + message)); } } internal static bool NetworkLogEnabled() { if (_debugNetwork != null) { return _debugNetwork.Value; } return false; } internal static bool WideTerraforming() { if (_fullTerraformingEnabled != null) { return _fullTerraformingEnabled.Value; } return false; } internal static float ClampLow() { if (!WideTerraforming() || _minTerraformHeight == null) { return -8f; } return Mathf.Min(-8f, _minTerraformHeight.Value); } internal static float ClampHigh() { if (!WideTerraforming() || _maxTerraformHeight == null) { return 8f; } return Mathf.Max(8f, _maxTerraformHeight.Value); } private static void WarnNarrowClamp(float delta) { if (!_narrowClampWarned && _log != null) { _narrowClampWarned = true; _log.LogWarning((object)($"A terrain edit of {delta:0.#} m arrived while FullTerraformingEnabled is off, so the " + $"vanilla +/-{8f:0.#} m clamp trims it on this machine. Enable " + "General.FullTerraformingEnabled and use the same FullTerraforming.MinHeight/MaxHeight on the server and on every client, otherwise the terrain cannot match.")); } } private void Update() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: 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_0102: 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) if (!IsActive()) { return; } try { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } KeyboardShortcut value = _fullTerraformingToggle.Value; bool num = ((KeyboardShortcut)(ref value)).IsDown(); if (num && !_lastToggleState) { if (_fullTerraformingEnabled.Value) { _fullTerraformingActive = !_fullTerraformingActive; string text = (_fullTerraformingActive ? "ON" : "OFF"); ((Character)localPlayer).Message((MessageType)1, "TerraHoe full terraforming: " + text, 0, (Sprite)null, false); _log.LogInfo((object)("Full terraforming toggled " + text + ".")); } else { _log.LogInfo((object)"Full terraforming toggle ignored: disabled by global config."); } } _lastToggleState = num; if (_debugLogging.Value) { value = _debugToggle.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { _debugLogging.Value = false; ((Character)localPlayer).Message((MessageType)1, "TerraHoe debug logging: OFF", 0, (Sprite)null, false); ManualLogSource log = _log; value = _debugToggle.Value; log.LogInfo((object)$"Debug logging toggled OFF by {((KeyboardShortcut)(ref value)).MainKey}."); } } value = _scrollModifier.Value; bool flag = ((KeyboardShortcut)(ref value)).IsPressed(); if (flag != _lastModifierState) { _lastModifierState = flag; if (_debugLogging.Value && _debugInput.Value) { _log.LogInfo((object)("[Debug] modifier " + (flag ? "PRESSED" : "RELEASED"))); } } TerrainOp selectedTerrainOp = GetSelectedTerrainOp(localPlayer); TrackSelection(selectedTerrainOp); if ((Object)(object)selectedTerrainOp == (Object)null) { RestoreActiveOperation(); return; } EnsureActiveOperation(selectedTerrainOp); ApplyFullTerraformingMode(selectedTerrainOp); float y = Input.mouseScrollDelta.y; if (!(Mathf.Abs(y) < 0.001f)) { if (_debugLogging.Value && _debugInput.Value) { _log.LogInfo((object)$"[Debug] wheel={y:0.###}, modifierHeld={flag}, radiusBefore={_currentRadius:0.###}"); } if (flag) { ChangeRadius(y * _scrollStep.Value); } } } catch (Exception ex) { DebugWarning("Update failed: " + ex); } } private static TerrainOp GetSelectedTerrainOp(Player player) { if (_buildPieces == null) { return null; } object? value = _buildPieces.GetValue(player); PieceTable val = (PieceTable)((value is PieceTable) ? value : null); Piece val2 = (((Object)(object)val != (Object)null) ? val.GetSelectedPiece() : null); if ((Object)(object)val2 == (Object)null) { return null; } return ((Component)val2).gameObject.GetComponent<TerrainOp>(); } private static void TrackSelection(TerrainOp operation) { string text = (((Object)(object)operation == (Object)null) ? "<none>" : ((Object)((Component)operation).gameObject).name); if (!(text == _lastSelectionName)) { _lastSelectionName = text; if (_debugLogging != null && _debugLogging.Value && _debugSelection.Value) { _log.LogInfo((object)("[Debug] selected TerrainOp=" + text)); } } } private static void EnsureActiveOperation(TerrainOp operation) { if (!((Object)(object)_activeOperation == (Object)(object)operation)) { RestoreActiveOperation(); _activeOperation = operation; Settings settings = operation.m_settings; if (settings == null) { DebugWarning("Selected TerrainOp has null settings: " + ((Object)((Component)operation).gameObject).name); _activeOperation = null; return; } _baseLevel = settings.m_levelRadius; _baseRaise = settings.m_raiseRadius; _baseSmooth = settings.m_smoothRadius; _basePaint = settings.m_paintRadius; _baseLevelEnabled = settings.m_level; _baseRaiseEnabled = settings.m_raise; _baseSmoothEnabled = settings.m_smooth; _basePaintEnabled = settings.m_paintCleared; _baseRadius = PickRadius(settings); _currentRadius = _baseRadius; ScalePreview(1f); DebugLog($"Captured settings: baseRadius={_baseRadius:0.###}, level={_baseLevel:0.###}, raise={_baseRaise:0.###}, smooth={_baseSmooth:0.###}, paint={_basePaint:0.###}"); } } private static void ApplyFullTerraformingMode(TerrainOp operation) { Settings settings = operation.m_settings; if (settings == null) { return; } if (_fullTerraformingActive && _fullTerraformingEnabled.Value) { settings.m_level = true; settings.m_raise = false; settings.m_smooth = false; settings.m_paintCleared = false; if (!_lastAppliedFullMode) { DebugLog("Full mode applied to " + ((Object)((Component)operation).gameObject).name + ": LevelTerrain only"); } _lastAppliedFullMode = true; } else { settings.m_level = _baseLevelEnabled; settings.m_raise = _baseRaiseEnabled; settings.m_smooth = _baseSmoothEnabled; settings.m_paintCleared = _basePaintEnabled; _lastAppliedFullMode = false; } } private static void ChangeRadius(float delta) { if ((Object)(object)_activeOperation == (Object)null || _baseRadius <= 0.001f) { return; } float num = Mathf.Clamp(_currentRadius + delta, _minRadius.Value, _maxRadius.Value); if (!(Mathf.Abs(num - _currentRadius) < 0.001f)) { _currentRadius = num; Settings settings = _activeOperation.m_settings; float num2 = _currentRadius / _baseRadius; settings.m_levelRadius = _baseLevel * num2; settings.m_raiseRadius = _baseRaise * num2; settings.m_smoothRadius = _baseSmooth * num2; settings.m_paintRadius = _basePaint * num2; ScalePreview(num2); if (_showMessage.Value && (Object)(object)Player.m_localPlayer != (Object)null && Mathf.Abs(_currentRadius - _lastMessageRadius) >= 0.01f) { _lastMessageRadius = _currentRadius; ((Character)Player.m_localPlayer).Message((MessageType)1, $"TerraHoe radius: {_currentRadius:0.##} m", 0, (Sprite)null, false); } DebugLog($"radius changed: {_currentRadius:0.###} m, factor={num2:0.###}"); } } private static void ScalePreview(float factor) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) GameObject val = (GameObject)((_placementGhost != null && (Object)(object)Player.m_localPlayer != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); if (!((Object)(object)val == (Object)null)) { Transform val2 = val.transform.Find("_GhostOnly"); if ((Object)(object)val2 == (Object)null) { val2 = val.transform.Find("GhostOnly"); } if ((Object)(object)val2 == (Object)null) { val2 = val.transform; } val2.localScale = new Vector3(factor, factor, factor); } } private static float PickRadius(Settings s) { float num = 0f; if (s.m_level && s.m_levelRadius > num) { num = s.m_levelRadius; } if (s.m_raise && s.m_raiseRadius > num) { num = s.m_raiseRadius; } if (s.m_smooth && s.m_smoothRadius > num) { num = s.m_smoothRadius; } if (s.m_paintCleared && s.m_paintRadius > num) { num = s.m_paintRadius; } return num; } private static void RestoreActiveOperation() { if (!((Object)(object)_activeOperation == (Object)null)) { Settings settings = _activeOperation.m_settings; if (settings != null) { settings.m_levelRadius = _baseLevel; settings.m_raiseRadius = _baseRaise; settings.m_smoothRadius = _baseSmooth; settings.m_paintRadius = _basePaint; settings.m_level = _baseLevelEnabled; settings.m_raise = _baseRaiseEnabled; settings.m_smooth = _baseSmoothEnabled; settings.m_paintCleared = _basePaintEnabled; } ScalePreview(1f); _activeOperation = null; _currentRadius = 0f; _lastMessageRadius = -1f; } } internal static float TerraformDelta(float value, float min, float max) { if (!WideTerraforming() && TerrainClamp.IsVanillaDeltaBounds(min, max) && Mathf.Abs(value) > 8.001f) { WarnNarrowClamp(value); } return TerrainClamp.Delta(value, min, max, WideTerraforming(), ClampLow(), ClampHigh()); } internal static float TerraformHeight(float value, float min, float max) { float num = (min + max) * 0.5f; if (!WideTerraforming() && TerrainClamp.IsVanillaHeightBounds(min, max) && Mathf.Abs(value - num) > 8.001f) { WarnNarrowClamp(value - num); } return TerrainClamp.Height(value, min, max, WideTerraforming(), ClampLow(), ClampHigh()); } private static bool IsFloatClamp(MethodInfo method) { if (method == null || method.Name != "Clamp" || method.DeclaringType != typeof(Mathf)) { return false; } if (method.ReturnType != typeof(float)) { return false; } ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length == 3 && parameters[0].ParameterType == typeof(float) && parameters[1].ParameterType == typeof(float)) { return parameters[2].ParameterType == typeof(float); } return false; } private static IEnumerable<CodeInstruction> RewriteClamp(IEnumerable<CodeInstruction> instructions, string replacement) { MethodInfo target = AccessTools.Method(typeof(TerraHoePlugin), replacement, (Type[])null, (Type[])null); if (target == null) { _log.LogWarning((object)("TerraHoe could not resolve " + replacement + "; the terrain clamp stays vanilla.")); foreach (CodeInstruction instruction in instructions) { yield return instruction; } yield break; } foreach (CodeInstruction instruction2 in instructions) { if (instruction2.opcode == OpCodes.Call && instruction2.operand is MethodInfo method && IsFloatClamp(method)) { yield return new CodeInstruction(OpCodes.Call, (object)target); } else { yield return instruction2; } } } private static int StripHoeDust(Piece piece) { if (!_suppressHoeDust.Value || (Object)(object)piece == (Object)null) { return 0; } string text = (((Object)(object)((Component)piece).gameObject != (Object)null) ? ((Object)((Component)piece).gameObject).name : string.Empty); if (text.IndexOf("road", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("raise", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("path_", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("paved", StringComparison.OrdinalIgnoreCase) < 0) { return 0; } EffectList placeEffect = piece.m_placeEffect; if (placeEffect == null || placeEffect.m_effectPrefabs == null || placeEffect.m_effectPrefabs.Length == 0) { return 0; } List<EffectData> list = new List<EffectData>(placeEffect.m_effectPrefabs.Length); int num = 0; for (int i = 0; i < placeEffect.m_effectPrefabs.Length; i++) { EffectData val = placeEffect.m_effectPrefabs[i]; GameObject val2 = val?.m_prefab; if ((Object)(object)val2 != (Object)null && ((Object)val2).name.IndexOf("vfx", StringComparison.OrdinalIgnoreCase) >= 0) { num++; } else { list.Add(val); } } if (num == 0) { return 0; } placeEffect.m_effectPrefabs = list.ToArray(); DebugLog($"Stripped {num} dust vfx from {text}"); return num; } } internal static class TerrainClamp { internal static bool IsVanillaDeltaBounds(float min, float max) { if (Mathf.Abs(min + 8f) <= 0.001f) { return Mathf.Abs(max - 8f) <= 0.001f; } return false; } internal static bool IsVanillaHeightBounds(float min, float max) { return Mathf.Abs(max - min - 16f) <= 0.001f; } internal static float Delta(float value, float min, float max, bool wide, float low, float high) { if (!wide || !IsVanillaDeltaBounds(min, max)) { return Mathf.Clamp(value, min, max); } return Mathf.Clamp(value, low, high); } internal static float Height(float value, float min, float max, bool wide, float low, float high) { if (!wide || !IsVanillaHeightBounds(min, max)) { return Mathf.Clamp(value, min, max); } float num = (min + max) * 0.5f; return Mathf.Clamp(value, num + low, num + high); } }