Decompiled source of TidyTerrain v1.4.0
TidyTerrain.dll
Decompiled 3 weeks 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.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using AskaShared.Game; using AwesomeTechnologies.VegetationSystem; using BepInEx; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using Fusion; using HarmonyLib; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Microsoft.CodeAnalysis; using SSSGame; using SSSGame.Combat; using SSSGame.Pathfinding; using SandSailorStudio.Render; using SandSailorStudio.TerrainTools; using Unity.Collections; using Unity.Mathematics; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("TidyTerrain")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.4.0")] [assembly: AssemblyInformationalVersion("1.4.0+03d3833ed921e714abd93ef8b53f39dc1beca10f")] [assembly: AssemblyProduct("Tidy Terrain")] [assembly: AssemblyTitle("TidyTerrain")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.4.0.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 AskaTidyTerrain { internal static class ArmingReport { internal static int Armed; internal static int Attempted; internal static bool TryPatch(Harmony harmony, MethodBase target, string label, HarmonyMethod prefix = null, HarmonyMethod postfix = null) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown Attempted++; bool flag = default(bool); if (target == null) { ManualLogSource log = Plugin.Log; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(36, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[arm-fail] "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(label); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": target method not found"); } log.LogWarning(val); return false; } try { harmony.Patch(target, prefix, postfix, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Armed++; ManualLogSource log2 = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(8, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[armed] "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(label); } log2.LogInfo(val2); return true; } catch (Exception ex) { ManualLogSource log3 = Plugin.Log; bool flag2 = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(13, 2, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[arm-fail] "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(label); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message); } log3.LogWarning(val); return false; } } internal static void LogTotal() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(30, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] armed "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Armed); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("/"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Attempted); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" patches."); } log.LogInfo(val); } } internal enum BoulderAction { Resnap, Destroy } internal static class BoulderService { private const string BouldersSection = "TidyTerrain.Boulders"; private const string ActionDescription = "Resnap = move this boulder onto the new ground, half-buried; Destroy = blow it up instead. Destroyed boulders drop nothing."; private const string ExplosionEffectsDescription = "Play the game's rock-destruction explosion when a boulder set to Destroy is removed. False removes it silently."; private const bool DefaultExplosionEffects = true; private const float GrowthCheckIntervalSeconds = 1f; private static bool _initialized; private static int _descriptorCountAtInit; private static float _nextGrowthCheckTime; private static bool _initFailureLogged; private static bool _lookupFailureLogged; private static bool _knownLookupFailureLogged; private static bool _explosionEffectsBound; private static ConfigEntry<bool> _explosionEffects; private static readonly Dictionary<IntPtr, ConfigEntry<BoulderAction>> _actionsByDescriptor = new Dictionary<IntPtr, ConfigEntry<BoulderAction>>(); private static readonly HashSet<IntPtr> _boulderDescriptors = new HashSet<IntPtr>(); internal static bool ExplosionEffects { get { if (_explosionEffects == null) { return true; } return _explosionEffects.Value; } } internal static void BindGlobalConfig() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown if (_explosionEffectsBound) { return; } _explosionEffectsBound = true; try { _explosionEffects = Plugin.PublicConfig.Bind<bool>("TidyTerrain.Boulders", "ExplosionEffects", true, "Play the game's rock-destruction explosion when a boulder set to Destroy is removed. False removes it silently."); } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(84, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] boulders: binding ["); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("TidyTerrain.Boulders"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] ExplosionEffects failed; destruction FX stay on: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogError(val); } } internal static void EnsureInitialized() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown if (_initialized && !DescriptorTableChanged()) { return; } try { TryInitialize(); } catch (Exception ex) { if (!_initFailureLogged) { _initFailureLogged = true; ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(101, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] boulder init failed; boulder handling is inactive and further attempts will be silent: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogError(val); } } } internal static bool TryGetAction(BiomeItemDescriptor descriptor, out BoulderAction action) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown action = BoulderAction.Resnap; if (!_initialized || descriptor == null) { return false; } try { if (!_actionsByDescriptor.TryGetValue(((Il2CppObjectBase)descriptor).Pointer, out var value)) { return false; } action = value.Value; return true; } catch (Exception ex) { if (!_lookupFailureLogged) { _lookupFailureLogged = true; ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(121, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] boulder action lookup failed; affected boulders keep vanilla behavior and further failures will be silent: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogError(val); } return false; } } internal static bool IsKnownBoulderDescriptor(BiomeItemDescriptor descriptor) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown if (descriptor == null) { return false; } if (!_initialized) { return true; } try { return _boulderDescriptors.Contains(((Il2CppObjectBase)descriptor).Pointer); } catch (Exception ex) { if (!_knownLookupFailureLogged) { _knownLookupFailureLogged = true; ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(117, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] boulder identity lookup failed; affected instances are left alone and further failures will be silent: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogError(val); } return true; } } private static bool DescriptorTableChanged() { float time = Time.time; if (time < _nextGrowthCheckTime) { return false; } _nextGrowthCheckTime = time + 1f; try { BiomeProceduralDataHandler handler = BiomeItemInstance.Handler; if (handler == null) { return false; } Dictionary<int, BiomeItemDescriptor> descriptorsTable = handler._descriptorsTable; if (descriptorsTable == null) { return false; } return descriptorsTable.Count != _descriptorCountAtInit; } catch (Exception) { return false; } } private static void TryInitialize() { //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Expected O, but got Unknown //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Expected O, but got Unknown //IL_0329: Unknown result type (might be due to invalid IL or missing references) //IL_0330: Expected O, but got Unknown //IL_03b7: Unknown result type (might be due to invalid IL or missing references) //IL_03be: Expected O, but got Unknown if (RetentionService.IsWindowOpen) { return; } BiomeProceduralDataHandler handler = BiomeItemInstance.Handler; if (handler == null) { return; } Dictionary<int, BiomeItemDescriptor> descriptorsTable = handler._descriptorsTable; if (descriptorsTable == null) { return; } int count = descriptorsTable.Count; if (count == 0) { return; } Dictionary<string, List<BiomeItemDescriptor>> dictionary = new Dictionary<string, List<BiomeItemDescriptor>>(); HashSet<IntPtr> hashSet = new HashSet<IntPtr>(); int num = 0; int num2 = 0; int num3 = 0; Enumerator<int, BiomeItemDescriptor> enumerator = descriptorsTable.GetEnumerator(); while (enumerator.MoveNext()) { BiomeItemDescriptor value = enumerator.Current.Value; if (value == null) { continue; } num++; if (!IsBoulder(value)) { continue; } try { hashSet.Add(((Il2CppObjectBase)value).Pointer); } catch (Exception) { } string text = DescriptorName(value); if (string.IsNullOrEmpty(text)) { num3++; continue; } num2++; if (!dictionary.TryGetValue(text, out var value2)) { value2 = new List<BiomeItemDescriptor>(); dictionary.Add(text, value2); } value2.Add(value); } if (num == 0) { return; } List<string> unbindable = null; Dictionary<string, ConfigEntry<BoulderAction>> entries = new Dictionary<string, ConfigEntry<BoulderAction>>(); List<string> names = new List<string>(dictionary.Keys); names.Sort(StringComparer.Ordinal); ConfigBatch.Run(Plugin.PublicConfig, delegate { int num5 = 0; foreach (string item in names) { try { bool num6 = ConfigBatch.IsNew(Plugin.PublicConfig, "TidyTerrain.Boulders", item); entries[item] = Plugin.PublicConfig.Bind<BoulderAction>("TidyTerrain.Boulders", item, BoulderAction.Resnap, "Resnap = move this boulder onto the new ground, half-buried; Destroy = blow it up instead. Destroyed boulders drop nothing."); if (num6) { num5++; } } catch (Exception) { entries.Remove(item); if (unbindable == null) { unbindable = new List<string>(); } unbindable.Add(item); } } return num5; }); Dictionary<IntPtr, ConfigEntry<BoulderAction>> dictionary2 = new Dictionary<IntPtr, ConfigEntry<BoulderAction>>(); int num4 = 0; foreach (string item2 in names) { if (!entries.TryGetValue(item2, out var value3)) { continue; } foreach (BiomeItemDescriptor item3 in dictionary[item2]) { if (item3 != null) { try { dictionary2[((Il2CppObjectBase)item3).Pointer] = value3; } catch (Exception) { num4++; } } } } _actionsByDescriptor.Clear(); foreach (KeyValuePair<IntPtr, ConfigEntry<BoulderAction>> item4 in dictionary2) { _actionsByDescriptor.Add(item4.Key, item4.Value); } _boulderDescriptors.Clear(); foreach (IntPtr item5 in hashSet) { _boulderDescriptors.Add(item5); } bool initialized = _initialized; int descriptorCountAtInit = _descriptorCountAtInit; _initialized = true; _descriptorCountAtInit = count; bool flag = default(bool); if (num3 > 0) { ManualLogSource log = Plugin.Log; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(93, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] boulders: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num3); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" boulder descriptor(s) had no readable name and cannot be configured."); } log.LogWarning(val); } if (unbindable != null) { ManualLogSource log2 = Plugin.Log; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(110, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] boulders: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(unbindable.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" type(s) have names BepInEx cannot use as config keys and will keep vanilla behavior: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(string.Join(", ", unbindable)); } log2.LogWarning(val); } if (num4 > 0) { ManualLogSource log3 = Plugin.Log; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(102, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] boulders: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num4); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" descriptor(s) could not be indexed for lookup and will keep vanilla behavior."); } log3.LogWarning(val); } string text2 = (initialized ? $"re-enumerated (descriptor table changed {descriptorCountAtInit} -> {count})" : "initialized"); ManualLogSource log4 = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(106, 6, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[TidyTerrain] boulders "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text2); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" descriptor(s) walked, "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num2); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" boulder descriptor(s) across "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(dictionary.Count); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" type(s), "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(entries.Count); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ["); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("TidyTerrain.Boulders"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("] entries bound."); } log4.LogInfo(val2); } private static bool IsBoulder(BiomeItemDescriptor descriptor) { try { return !descriptor.IsHarvestable && !descriptor._removableByTerraforming && !descriptor.HasHealthData(); } catch (Exception) { return false; } } internal static string DescriptorName(BiomeItemDescriptor descriptor) { try { GameObject biomeItemPrefab = descriptor._biomeItemPrefab; if ((Object)(object)biomeItemPrefab != (Object)null) { return ((Object)biomeItemPrefab).name; } } catch (Exception) { } try { VegetationItemInfoPro biomeInfo = descriptor.GetBiomeInfo(); if (biomeInfo != null && !string.IsNullOrEmpty(biomeInfo.Name)) { return biomeInfo.Name; } } catch (Exception) { } return null; } } [HarmonyPatch(typeof(Character))] public static class CharacterSpawnPatch { [HarmonyPostfix] [HarmonyPatch("Spawned")] public static void Spawned(Character __instance) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) LocalPlayerTool.AttachOnSpawn(__instance, Plugin.Log, "TidyTerrain_Tool", Vector3.zero, typeof(TidyTerrainTool)); } } internal static class ConfigBatch { internal static void Run(ConfigFile config, Func<int> bindAll) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown bool saveOnConfigSet = config.SaveOnConfigSet; config.SaveOnConfigSet = false; int num; try { num = bindAll(); } finally { config.SaveOnConfigSet = saveOnConfigSet; } if (!(num > 0 && saveOnConfigSet)) { return; } try { config.Save(); } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(120, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] saving the config after binding "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" new entr(ies) threw; they apply this session but may not be in the file: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogError(val); } } internal static bool IsNew(ConfigFile config, string section, string key) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown return !config.ContainsKey(new ConfigDefinition(section, key)); } } internal readonly struct QueryCircle { internal float X { get; } internal float Z { get; } internal float Radius { get; } internal QueryCircle(float x, float z, float radius) { X = x; Z = z; Radius = radius; } } internal sealed class Footprint { private struct Tile { public float CenterX; public float CenterZ; public float HalfWidth; public float HalfHeight; public float Cos; public float Sin; } private const float ClusterJoinMeters = 10f; private readonly List<Tile> _tiles = new List<Tile>(); internal bool IsEmpty => _tiles.Count == 0; internal void AddTile(float centerX, float centerZ, float width, float height, float blend, float rotationDegrees) { double num = (double)rotationDegrees * Math.PI / 180.0; _tiles.Add(new Tile { CenterX = centerX, CenterZ = centerZ, HalfWidth = width * 0.5f + blend, HalfHeight = height * 0.5f + blend, Cos = (float)Math.Cos(num), Sin = (float)Math.Sin(num) }); } internal bool Contains(float x, float z) { for (int i = 0; i < _tiles.Count; i++) { Tile tile = _tiles[i]; float num = x - tile.CenterX; float num2 = z - tile.CenterZ; float value = num * tile.Cos - num2 * tile.Sin; float value2 = num * tile.Sin + num2 * tile.Cos; if (Math.Abs(value) <= tile.HalfWidth && Math.Abs(value2) <= tile.HalfHeight) { return true; } } return false; } internal List<QueryCircle> QueryCircles() { int count = _tiles.Count; float[] array = new float[count]; float[] array2 = new float[count]; float[] array3 = new float[count]; float[] array4 = new float[count]; for (int i = 0; i < count; i++) { Tile tile = _tiles[i]; float num = Math.Abs(tile.HalfWidth * tile.Cos) + Math.Abs(tile.HalfHeight * tile.Sin); float num2 = Math.Abs(tile.HalfWidth * tile.Sin) + Math.Abs(tile.HalfHeight * tile.Cos); array[i] = tile.CenterX - num; array2[i] = tile.CenterX + num; array3[i] = tile.CenterZ - num2; array4[i] = tile.CenterZ + num2; } int[] array5 = new int[count]; for (int j = 0; j < count; j++) { array5[j] = j; } for (int k = 0; k < count; k++) { for (int l = k + 1; l < count; l++) { if (array[l] - array2[k] <= 10f && array[k] - array2[l] <= 10f && array3[l] - array4[k] <= 10f && array3[k] - array4[l] <= 10f) { array5[Root(array5, k)] = Root(array5, l); } } } Dictionary<int, float[]> dictionary = new Dictionary<int, float[]>(); List<int> list = new List<int>(); for (int m = 0; m < count; m++) { int num3 = Root(array5, m); if (!dictionary.TryGetValue(num3, out var value)) { dictionary.Add(num3, new float[4] { array[m], array2[m], array3[m], array4[m] }); list.Add(num3); } else { value[0] = Math.Min(value[0], array[m]); value[1] = Math.Max(value[1], array2[m]); value[2] = Math.Min(value[2], array3[m]); value[3] = Math.Max(value[3], array4[m]); } } List<QueryCircle> list2 = new List<QueryCircle>(list.Count); foreach (int item in list) { float[] array6 = dictionary[item]; float num4 = (array6[1] - array6[0]) * 0.5f; float num5 = (array6[3] - array6[2]) * 0.5f; list2.Add(new QueryCircle(array6[0] + num4, array6[2] + num5, (float)Math.Sqrt(num4 * num4 + num5 * num5))); } return list2; } internal void Clear() { _tiles.Clear(); } private static int Root(int[] parent, int i) { while (parent[i] != i) { parent[i] = parent[parent[i]]; i = parent[i]; } return i; } } internal static class GridCellCompletion { private struct AwaitingGrid { public TerraformingGridState State; public float GiveUpTime; } private static bool _warnedMarkThrow; private static bool _warnedSpawnThrow; private static bool _warnedShape; private static bool _marking; private const float LinkWaitSeconds = 10f; private static readonly List<AwaitingGrid> _awaiting = new List<AwaitingGrid>(); private const int SamplesPerSide = 5; private const float SampleSpanFraction = 0.8f; public static void RefreshCellsHeightsPostfix(TerraformingGrid __instance) { if (_marking || !Plugin.ConfigEnabled.Value || !Plugin.ConfigAutoCompleteLevelCells.Value) { return; } try { MarkAlreadyLevel(__instance); } catch (Exception ex) { WarnOnce(ref _warnedMarkThrow, "marking already-level grid cells", ex); } } public static void SpawnedPostfix(TerraformingGridState __instance) { if (!((Object)(object)__instance == (Object)null) && Plugin.ConfigEnabled.Value && Plugin.ConfigAutoCompleteLevelCells.Value) { _awaiting.Add(new AwaitingGrid { State = __instance, GiveUpTime = Time.time + 10f }); } } internal static void Tick() { for (int num = _awaiting.Count - 1; num >= 0; num--) { AwaitingGrid awaitingGrid = _awaiting[num]; try { if ((Object)(object)awaitingGrid.State == (Object)null) { _awaiting.RemoveAt(num); } else { TerraformingGrid grid = awaitingGrid.State._grid; if ((Object)(object)grid == (Object)null || grid.GetCellsCount() == 0) { if (Time.time >= awaitingGrid.GiveUpTime) { _awaiting.RemoveAt(num); } } else { _awaiting.RemoveAt(num); grid.RefreshCellsHeights(false, true); } } } catch (Exception ex) { _awaiting.RemoveAt(num); WarnOnce(ref _warnedSpawnThrow, "refreshing a newly spawned leveling grid", ex); } } } internal static void Reset() { _awaiting.Clear(); } private static void WarnOnce(ref bool warned, string what, Exception ex) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown if (!warned) { warned = true; ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(50, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(what); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" threw (further throws suppressed): "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogWarning(val); } } private static void MarkAlreadyLevel(TerraformingGrid grid) { if ((Object)(object)grid == (Object)null) { return; } TerraformingGridState state = grid._state; if ((Object)(object)state == (Object)null || !((SimulationBehaviour)state).HasStateAuthority) { return; } int cellsCount = grid.GetCellsCount(); if (cellsCount == 0) { return; } Il2CppStructArray<int> gridInteractMap = grid.gridInteractMap; Il2CppStructArray<bool> grid2 = ((PlacementGrid)grid).grid; if (gridInteractMap == null || grid2 == null || ((Il2CppArrayBase<int>)(object)gridInteractMap).Length < cellsCount || ((Il2CppArrayBase<bool>)(object)grid2).Length < cellsCount) { WarnShapeOnce(cellsCount, gridInteractMap, grid2); return; } int[] array = new int[cellsCount]; bool[] array2 = new bool[cellsCount]; float[][] array3 = new float[cellsCount][]; bool[] array4 = new bool[cellsCount]; float cellSize = CellSize(grid); for (int i = 0; i < cellsCount; i++) { array[i] = ((Il2CppArrayBase<int>)(object)gridInteractMap)[i]; array2[i] = ((Il2CppArrayBase<bool>)(object)grid2)[i]; if (array2[i] && array[i] == 0) { GatherCandidate(grid, gridInteractMap, i, cellSize, out array4[i], out array3[i]); } } List<int> list = LevelCellSelection.SelectAlreadyLevel(array, array2, array3, grid.ReferenceLevel, grid.levelError, array4); if (list.Count == 0) { return; } _marking = true; try { foreach (int item in list) { grid.MarkCellInteracted(item, true); } } finally { _marking = false; } } internal static void GatherCandidate(TerraformingGrid grid, Il2CppStructArray<int> interactMap, int cell, float cellSize, out bool accepted, out float[] samples) { samples = null; accepted = false; if (!(Math.Abs(grid.GetCellAverageHeight(cell) - grid.ReferenceLevel) > grid.levelError)) { accepted = GameAcceptsIfHoed(grid, interactMap, cell); if (accepted && cellSize > 0f) { samples = SampleCell(grid, cell, cellSize); } } } private static float[] SampleCell(TerraformingGrid grid, int cell, float cellSize) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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) Vector3 cellPosition = ((DynamicPlacementGrid)grid).GetCellPosition(cell); Transform transform = ((Component)grid).transform; Vector3 right = transform.right; Vector3 forward = transform.forward; float num = cellSize * 0.8f; float num2 = num / 4f; float[] array = new float[25]; int num3 = 0; for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { float num4 = (float)i * num2 - num * 0.5f; float num5 = (float)j * num2 - num * 0.5f; array[num3++] = TerrainSampler.SampleHeight(cellPosition + right * num4 + forward * num5); } } return array; } internal static float CellSize(TerraformingGrid grid) { PlacementGridConstants constants = ((PlacementGrid)grid).constants; if (!((Object)(object)constants != (Object)null)) { return 0f; } return constants.tileSize; } internal static bool GameAcceptsIfHoed(TerraformingGrid grid, Il2CppStructArray<int> interactMap, int cell) { int num = ((Il2CppArrayBase<int>)(object)interactMap)[cell]; ((Il2CppArrayBase<int>)(object)interactMap)[cell] = 1; try { return grid.IsCellLeveled(cell); } finally { ((Il2CppArrayBase<int>)(object)interactMap)[cell] = num; } } private static void WarnShapeOnce(int count, Il2CppStructArray<int> interactMap, Il2CppStructArray<bool> realMap) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown if (!_warnedShape) { _warnedShape = true; ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(139, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] a leveling grid's cell arrays do not match its "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" cells "); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("(stroke counts: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>((interactMap == null) ? "missing" : ((Il2CppArrayBase<int>)(object)interactMap).Length.ToString()); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", "); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("cell mask: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>((realMap == null) ? "missing" : ((Il2CppArrayBase<bool>)(object)realMap).Length.ToString()); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("); its already-level cells are not marked."); } log.LogWarning(val); } } } internal sealed class GroundSample { private readonly Vector3 _at; private readonly Transform _selfExclude; private bool _taken; private bool _found; private float _groundY; internal GroundSample(Vector3 at, Transform selfExclude) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) _at = at; _selfExclude = selfExclude; } internal bool TryGetY(out float groundY) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (!_taken) { _found = GroundHeight.TrySampleGroundY(_at, _selfExclude, out _groundY); _taken = true; } groundY = _groundY; return _found; } } internal static class GroundHeight { private const float RaycastStartHeightMeters = 200f; private const float RaycastMaxDistanceMeters = 400f; private const int InitialHitCapacity = 64; private static Il2CppStructArray<RaycastHit> _hits; private static readonly Dictionary<int, bool> _isTerrainByCollider = new Dictionary<int, bool>(); private const float SupportProbeMarginMeters = 0.25f; private const float SupportClearanceMeters = 0.1f; internal static void BeginPass() { _isTerrainByCollider.Clear(); } public static bool TrySampleGroundY(Vector3 atPos, Transform selfExclude, out float groundY) { //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Expected O, but got Unknown //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) groundY = 0f; try { int num = CastDown(new Vector3(atPos.x, atPos.y + 200f, atPos.z), 400f); bool flag = false; float num2 = float.NegativeInfinity; bool flag2 = false; float num3 = float.NegativeInfinity; for (int i = 0; i < num; i++) { RaycastHit val = ((Il2CppArrayBase<RaycastHit>)(object)_hits)[i]; Collider collider = ((RaycastHit)(ref val)).collider; if (!IsSameOrRelatedTransform(((Object)(object)collider != (Object)null) ? ((Component)collider).transform : null, selfExclude)) { if ((Object)(object)collider != (Object)null && IsTerrain(collider) && (!flag || ((RaycastHit)(ref val)).point.y > num2)) { flag = true; num2 = ((RaycastHit)(ref val)).point.y; } if (!flag2 || ((RaycastHit)(ref val)).point.y > num3) { flag2 = true; num3 = ((RaycastHit)(ref val)).point.y; } } } if (flag) { groundY = num2; return true; } if (flag2) { groundY = num3; return true; } } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag3 = default(bool); BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(43, 3, ref flag3); if (flag3) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[TidyTerrain] ground raycast at ("); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(atPos.x, "F2"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(","); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(atPos.z, "F2"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(") threw: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex); } log.LogError(val2); } return false; } internal static bool TryFindSupportBetween(Vector3 atPos, Transform selfExclude, float currentY, float groundY, out string supportName) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) supportName = null; float num = Mathf.Max(currentY, groundY); float num2 = Mathf.Min(currentY, groundY); Vector3 origin = new Vector3(atPos.x, num + 0.25f, atPos.z); float distance = num - num2 + 0.25f; int num3 = CastDown(origin, distance); for (int i = 0; i < num3; i++) { RaycastHit val = ((Il2CppArrayBase<RaycastHit>)(object)_hits)[i]; Collider collider = ((RaycastHit)(ref val)).collider; if (!((Object)(object)collider == (Object)null) && !IsSameOrRelatedTransform(((Component)collider).transform, selfExclude) && !IsTerrain(collider) && !(((RaycastHit)(ref val)).point.y <= num2 + 0.1f)) { supportName = ((Object)((Component)collider).gameObject).name; return true; } } return false; } private static int CastDown(Vector3 origin, float distance) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (_hits == null) { _hits = new Il2CppStructArray<RaycastHit>(64L); } int num; while (true) { num = Physics.RaycastNonAlloc(origin, Vector3.down, _hits, distance, -5, (QueryTriggerInteraction)0); if (num < ((Il2CppArrayBase<RaycastHit>)(object)_hits).Length) { break; } _hits = new Il2CppStructArray<RaycastHit>((long)(((Il2CppArrayBase<RaycastHit>)(object)_hits).Length * 2)); } return num; } private static bool IsTerrain(Collider collider) { int instanceID = ((Object)collider).GetInstanceID(); if (!_isTerrainByCollider.TryGetValue(instanceID, out var value)) { value = (Object)(object)((Component)collider).gameObject.GetComponent<Terrain>() != (Object)null; _isTerrainByCollider.Add(instanceID, value); } return value; } private static bool IsSameOrRelatedTransform(Transform hitTransform, Transform selfExclude) { if ((Object)(object)hitTransform == (Object)null || (Object)(object)selfExclude == (Object)null) { return false; } if ((Object)(object)hitTransform == (Object)(object)selfExclude) { return true; } if (hitTransform.IsChildOf(selfExclude)) { return true; } if (selfExclude.IsChildOf(hitTransform)) { return true; } return false; } } internal static class LevelCellSelection { internal static List<int> SelectAlreadyLevel(int[] hoes, bool[] real, float[][] samples, float target, float tolerance, bool[] acceptedIfHoed) { List<int> list = new List<int>(); for (int i = 0; i < hoes.Length; i++) { if (real[i] && hoes[i] == 0 && acceptedIfHoed[i] && AllWithin(samples[i], target, tolerance)) { list.Add(i); } } return list; } private static bool AllWithin(float[] samples, float target, float tolerance) { if (samples == null || samples.Length == 0) { return false; } for (int i = 0; i < samples.Length; i++) { if (Math.Abs(samples[i] - target) > tolerance) { return false; } } return true; } } internal static class LevelingCompletionPatch { private struct PendingPass { public IntPtr Grid; public Footprint Footprint; public float Y; public float DueTime; } private const float BlendBandMeters = 1.5f; private const float FallbackCellSizeMeters = 2f; private static readonly List<PendingPass> _pending = new List<PendingPass>(); private static bool _warnedCellSize; private static bool _warnedCellMask; internal static void OnRunOnAreaPrefix(TerraformingToolOperation operation) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown try { if ((int)operation == 2) { RetentionService.OnLevelTile(); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(62, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] LevelingCompletionPatch RunOnArea prefix threw: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogError(val); } } public static void OnGridCompletedPrefix(TerraformingGridState __instance) { //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected O, but got Unknown try { if (!Plugin.ConfigEnabled.Value || !Plugin.AutoResnap) { return; } TerraformingGrid val = (((Object)(object)__instance != (Object)null) ? __instance._grid : null); if ((Object)(object)val == (Object)null) { return; } IntPtr pointer = ((Il2CppObjectBase)val).Pointer; foreach (PendingPass item in _pending) { if (item.Grid == pointer) { return; } } Footprint footprint = BuildGridFootprint(val); if (!footprint.IsEmpty) { _pending.Add(new PendingPass { Grid = pointer, Footprint = footprint, Y = val.ReferenceLevel, DueTime = Time.time + Plugin.AutoResnapDelay }); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(68, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[TidyTerrain] LevelingCompletionPatch grid-completion prefix threw: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex); } log.LogError(val2); } } private static Footprint BuildGridFootprint(TerraformingGrid grid) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) float num = 2f; PlacementGridConstants constants = ((PlacementGrid)grid).constants; if ((Object)(object)constants != (Object)null) { num = constants.tileSize; } else if (!_warnedCellSize) { _warnedCellSize = true; ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(95, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] a leveling grid has no PlacementGridConstants; its re-snap pass assumes "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(2f, "F1"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" m cells."); } log.LogWarning(val); } Footprint footprint = new Footprint(); int cellsCount = grid.GetCellsCount(); Il2CppStructArray<bool> grid2 = ((PlacementGrid)grid).grid; bool flag2 = grid2 != null && ((Il2CppArrayBase<bool>)(object)grid2).Length >= cellsCount; if (!flag2 && !_warnedCellMask) { _warnedCellMask = true; Plugin.Log.LogWarning((object)($"[TidyTerrain] a completed leveling grid's cell mask does not match its {cellsCount} cells; " + "its re-snap pass covers every cell of the grid.")); } for (int i = 0; i < cellsCount; i++) { if (!flag2 || ((Il2CppArrayBase<bool>)(object)grid2)[i]) { Vector3 cellPosition = ((DynamicPlacementGrid)grid).GetCellPosition(i); footprint.AddTile(cellPosition.x, cellPosition.z, num, num, 1.5f, 0f); } } return footprint; } internal static void Tick() { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown if (_pending.Count == 0) { return; } float time = Time.time; bool flag = default(bool); for (int num = _pending.Count - 1; num >= 0; num--) { PendingPass pendingPass = _pending[num]; if (!(time < pendingPass.DueTime)) { _pending.RemoveAt(num); try { if (Plugin.ConfigEnabled.Value && Plugin.AutoResnap) { TidyTerrainService.ResnapRegion(pendingPass.Footprint, pendingPass.Y); StructureResnapService.ResnapRegion(pendingPass.Footprint, pendingPass.Y); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(52, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] LevelingCompletionPatch Tick() threw: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogError(val); } } } } internal static void Reset() { _pending.Clear(); } } internal static class MovedWorldGenRegistry { private struct Entry { public float Y; public bool Logged; } private const float XZMatchEpsilonMeters = 0.05f; private static readonly XzIndex<Entry> _entries = new XzIndex<Entry>(0.05f); internal static int Count => _entries.Count; internal static Vector3 PositionAt(int i) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) return new Vector3(_entries.XAt(i), _entries.ValueAt(i).Y, _entries.ZAt(i)); } internal static void Record(Vector3 newPos) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) _entries.Record(newPos.x, newPos.z, new Entry { Y = newPos.y }); } internal static bool TryGetRecordedY(Vector3 pos, out float recordedY) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (!_entries.TryGet(pos.x, pos.z, out var value)) { recordedY = 0f; return false; } recordedY = value.Y; return true; } internal static bool TryMarkLogged(Vector3 pos) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) int num = _entries.IndexOf(pos.x, pos.z); if (num < 0 || _entries.ValueAt(num).Logged) { return false; } Entry value = _entries.ValueAt(num); value.Logged = true; _entries.SetValueAt(num, value); return true; } internal static void Clear() { _entries.Clear(); } } [BepInPlugin("mugsy33.tidyterrain", "Tidy Terrain", "1.4.0")] public class Plugin : BasePlugin { public const string PluginGuid = "mugsy33.tidyterrain"; public const string PluginName = "Tidy Terrain"; public const string PluginVersion = "1.4.0"; internal static ManualLogSource Log; internal static ConfigEntry<bool> ConfigEnabled; internal static ConfigEntry<bool> ConfigResnapStructures; internal static ConfigEntry<bool> ConfigAutoCompleteLevelCells; internal static ConfigFile PublicConfig; internal static readonly bool Vegetation = true; internal static readonly bool WorldGen = true; internal static readonly bool Corpses = true; internal static readonly float Tolerance = 0.1f; internal static readonly float SinkOffset = 0.25f; internal static readonly bool AutoResnap = true; internal static readonly float AutoResnapDelay = 0.75f; internal static readonly float CaveMargin = 0f; internal static readonly bool CaveExclusion = true; internal static readonly float BoulderSinkFraction = 0.5f; internal static readonly float SinkCapFraction = 0.15f; internal static readonly float StructureRadiusMargin = 10f; public override void Load() { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Expected O, but got Unknown //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Expected O, but got Unknown //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Expected O, but got Unknown //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Expected O, but got Unknown //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Expected O, but got Unknown //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Expected O, but got Unknown //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Expected O, but got Unknown Log = ((BasePlugin)this).Log; ConfigEnabled = ((BasePlugin)this).Config.Bind<bool>("TidyTerrain", "Enabled", true, "Master on/off switch for Tidy Terrain."); ConfigResnapStructures = ((BasePlugin)this).Config.Bind<bool>("TidyTerrain", "ResnapStructures", true, "Move player-built structures vertically onto the new ground height after a leveling job, so buildings are not left floating or half-buried. Only the height changes - position and rotation are untouched."); ConfigAutoCompleteLevelCells = ((BasePlugin)this).Config.Bind<bool>("TidyTerrain", "AutoCompleteLevelCells", true, "Cells of a Terrain Level Field or building floor plan that are already at the target height count as done without hoeing."); PublicConfig = ((BasePlugin)this).Config; BoulderService.BindGlobalConfig(); ClassInjector.RegisterTypeInIl2Cpp<TidyTerrainTool>(); Harmony harmony = new Harmony("mugsy33.tidyterrain"); Harmony.CreateAndPatchAll(typeof(CharacterSpawnPatch), (string)null); HarmonyMethod postfix = null; ArmingReport.TryPatch(harmony, AccessTools.Method(typeof(HeightmapTool), "RunOnArea", new Type[6] { typeof(TerraformingToolOperation), typeof(float), typeof(float), typeof(float), typeof(Vector3), typeof(float) }, (Type[])null), "SSSGame.HeightmapTool.RunOnArea", new HarmonyMethod(typeof(LevelingCompletionPatch), "OnRunOnAreaPrefix", (Type[])null), postfix); ArmingReport.TryPatch(harmony, AccessTools.Method(typeof(TerraformingGridState), "Rpc_TurnIntoResultStructure", (Type[])null, (Type[])null), "SSSGame.TerraformingGridState.Rpc_TurnIntoResultStructure", new HarmonyMethod(typeof(LevelingCompletionPatch), "OnGridCompletedPrefix", (Type[])null)); ArmingReport.TryPatch(harmony, AccessTools.Method(typeof(BiomeItemInstance), "_OnActivateInstance", (Type[])null, (Type[])null), "SSSGame.BiomeItemInstance._OnActivateInstance", null, new HarmonyMethod(typeof(ProxyActivationPatch), "OnActivateInstancePostfix", (Type[])null)); ArmingReport.TryPatch(harmony, AccessTools.Method(typeof(BiomeItemInstance), "_RefreshGameObject", (Type[])null, (Type[])null), "SSSGame.BiomeItemInstance._RefreshGameObject", null, new HarmonyMethod(typeof(ProxyActivationPatch), "RefreshGameObjectPostfix", (Type[])null)); ArmingReport.TryPatch(harmony, AccessTools.Method(typeof(TerraformingGrid), "RefreshCellsHeights", (Type[])null, (Type[])null), "SSSGame.TerraformingGrid.RefreshCellsHeights", null, new HarmonyMethod(typeof(GridCellCompletion), "RefreshCellsHeightsPostfix", (Type[])null)); ArmingReport.TryPatch(harmony, AccessTools.Method(typeof(TerraformingGridState), "Spawned", (Type[])null, (Type[])null), "SSSGame.TerraformingGridState.Spawned", null, new HarmonyMethod(typeof(GridCellCompletion), "SpawnedPostfix", (Type[])null)); ArmingReport.LogTotal(); ManualLogSource log = Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(10, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("Tidy Terrain"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" v"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.4.0"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded."); } log.LogInfo(val); } } internal static class ProxyActivationPatch { private static bool _warnedThrow; public static void OnActivateInstancePostfix(BiomeItemInstance __instance) { Align(__instance); } public static void RefreshGameObjectPostfix(BiomeItemInstance __instance) { Align(__instance); } private static void Align(BiomeItemInstance instance) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown if (!Plugin.ConfigEnabled.Value || !Plugin.WorldGen) { return; } try { if (instance == null || MovedWorldGenRegistry.Count == 0) { return; } GameObject gameObject = ((WorldItemInstance)instance).gameObject; if (!((Object)(object)gameObject == (Object)null)) { Transform transform = gameObject.transform; if (!((Object)(object)transform == (Object)null)) { ProxyAlignment.Align(instance, transform, "activation"); } } } catch (Exception ex) { if (!_warnedThrow) { _warnedThrow = true; ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(64, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] proxy re-align threw (further throws suppressed): "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogWarning(val); } } } } internal enum ProxyAlignResult { Unregistered, Aligned, Corrected } internal static class ProxyAlignment { internal static ProxyAlignResult Align(BiomeItemInstance instance, Transform t, string source) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) Vector3 position = t.position; if (!MovedWorldGenRegistry.TryGetRecordedY(position, out var recordedY)) { return ProxyAlignResult.Unregistered; } bool num = Mathf.Abs(position.y - recordedY) > Plugin.Tolerance; if (num) { t.position = new Vector3(position.x, recordedY, position.z); } if (!num) { return ProxyAlignResult.Aligned; } return ProxyAlignResult.Corrected; } } internal static class ProxySweepService { private const float SweepIntervalSeconds = 2f; private const float SweepRangeMeters = 120f; private const float QueryRadiusMeters = 1f; private const float XZMatchEpsilonMeters = 0.05f; private const int HasGameObjectContexts = 311; private static int _cursor; private static bool _warnedThrow; private static List<WorldItemInstance> _scratch; private static readonly HashSet<int> _refreshPending = new HashSet<int>(); internal static void Reset() { _refreshPending.Clear(); _cursor = 0; } internal static void Tick(Vector3 playerPos) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) int count = MovedWorldGenRegistry.Count; if (!Plugin.WorldGen || count == 0) { return; } int num = (int)Math.Ceiling((float)count * Time.unscaledDeltaTime / 2f); if (num < 1) { num = 1; } else if (num > count) { num = count; } try { Sweep(playerPos, count, num); } catch (Exception ex) { if (!_warnedThrow) { _warnedThrow = true; ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(61, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] proxy sweep threw (further throws suppressed): "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogWarning(val); } } } private static void Sweep(Vector3 playerPos, int count, int budget) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: 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_0100: Unknown result type (might be due to invalid IL or missing references) ResourceManager resourceManager = TidyTerrainService.GetResourceManager(); if ((Object)(object)resourceManager == (Object)null) { return; } if (_scratch == null) { _scratch = new List<WorldItemInstance>(); } float num = 14400f; for (int i = 0; i < budget; i++) { if (_cursor >= count) { _cursor = 0; } int num2 = _cursor++; Vector3 val = MovedWorldGenRegistry.PositionAt(num2); float num3 = val.x - playerPos.x; float num4 = val.z - playerPos.z; if (num3 * num3 + num4 * num4 > num) { continue; } _scratch.Clear(); resourceManager.GetAllInstancesList(_scratch, val, Quaternion.identity, new Vector3(1f, 1f, 1f), (SDFShape)1, (IWorldItemInstanceFilter)null, (InstanceActivationContext)1024, false); int count2 = _scratch.Count; for (int j = 0; j < count2; j++) { BiomeItemInstance val2 = TidyTerrainService.AsBiomeItemInstance(_scratch[j]); if (val2 == null) { continue; } GameObject gameObject = ((WorldItemInstance)val2).gameObject; if ((Object)(object)gameObject == (Object)null) { if (IsOnEntry(val2, val)) { RestoreProxy(num2, val, val2); } continue; } Transform transform = gameObject.transform; if (!((Object)(object)transform == (Object)null)) { if (IsOnEntry(val2, val)) { _refreshPending.Remove(num2); } ProxyAlignment.Align(val2, transform, "sweep"); } } } } private static bool IsOnEntry(BiomeItemInstance instance, Vector3 entry) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((WorldItemInstance)instance).GetPosition(); if (Mathf.Abs(position.x - entry.x) <= 0.05f) { return Mathf.Abs(position.z - entry.z) <= 0.05f; } return false; } private static void RestoreProxy(int entryIndex, Vector3 entry, BiomeItemInstance instance) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_008e: 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) if (!_refreshPending.Contains(entryIndex) && (((WorldItemInstance)instance).GetContexts() & 0x137) != 0) { _refreshPending.Add(entryIndex); instance.ForceRefreshGameObject(); bool flag = (Object)(object)((WorldItemInstance)instance).gameObject != (Object)null; string text = (((Object)(object)((WorldItemInstance)instance).gameObject != (Object)null) ? ((Object)((WorldItemInstance)instance).gameObject).name : "world-gen object"); ManualLogSource log = Plugin.Log; bool flag2 = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(109, 4, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] proxy sweep: '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' at ("); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(entry.x, "F1"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(","); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(entry.z, "F1"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(") had no proxy in a GameObject context; "); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("ForceRefreshGameObject() -> proxy "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(flag ? "restored" : "still missing"); } log.LogInfo(val); } } } internal static class RetentionService { private const string RetentionSection = "TidyTerrain.Retention"; private const string RetentionDescription = "Keep this type when leveling (re-snapped to new ground); false = vanilla deletion. Other tools always remove it."; private const float CloseDelayPadSeconds = 0.25f; private const float GrowthCheckIntervalSeconds = 1f; private static bool _initialized; private static int _descriptorCountAtInit; private static float _nextGrowthCheckTime; private static bool _initFailureLogged; private static bool _windowOpen; private static float _lastLevelTileTime; private static readonly Dictionary<string, List<BiomeItemDescriptor>> _deletable = new Dictionary<string, List<BiomeItemDescriptor>>(); private static readonly Dictionary<string, ConfigEntry<bool>> _keepEntries = new Dictionary<string, ConfigEntry<bool>>(); private static readonly List<BiomeItemDescriptor> _flipped = new List<BiomeItemDescriptor>(); internal static bool IsWindowOpen => _windowOpen; internal static void OnLevelTile() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown try { EnsureInitialized(); if (_windowOpen) { _lastLevelTileTime = Time.time; } else if (_initialized && Plugin.ConfigEnabled.Value) { OpenWindow(); _lastLevelTileTime = Time.time; } } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(50, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] RetentionService.OnLevelTile threw: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogError(val); } } internal static void Tick() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown try { EnsureInitialized(); if (_windowOpen) { float num = Plugin.AutoResnapDelay + 0.25f; if (!(Time.time - _lastLevelTileTime < num)) { CloseWindow(); } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(43, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] RetentionService.Tick threw: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogError(val); } } internal static void ForceClose() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown try { if (_windowOpen) { CloseWindow(); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(49, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] RetentionService.ForceClose threw: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogError(val); } } private static void EnsureInitialized() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown if (_initialized && !DescriptorTableChanged()) { return; } try { TryInitialize(); } catch (Exception ex) { if (!_initFailureLogged) { _initFailureLogged = true; ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(96, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] retention init failed; retention is inactive and further attempts will be silent: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogError(val); } } } private static bool DescriptorTableChanged() { float time = Time.time; if (time < _nextGrowthCheckTime) { return false; } _nextGrowthCheckTime = time + 1f; try { BiomeProceduralDataHandler handler = BiomeItemInstance.Handler; if (handler == null) { return false; } Dictionary<int, BiomeItemDescriptor> descriptorsTable = handler._descriptorsTable; if (descriptorsTable == null) { return false; } return descriptorsTable.Count != _descriptorCountAtInit; } catch (Exception) { return false; } } private static void TryInitialize() { //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Expected O, but got Unknown //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Expected O, but got Unknown //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Expected O, but got Unknown if (_windowOpen) { return; } BiomeProceduralDataHandler handler = BiomeItemInstance.Handler; if (handler == null) { return; } Dictionary<int, BiomeItemDescriptor> descriptorsTable = handler._descriptorsTable; if (descriptorsTable == null) { return; } int count = descriptorsTable.Count; if (count == 0) { return; } Dictionary<string, List<BiomeItemDescriptor>> dictionary = new Dictionary<string, List<BiomeItemDescriptor>>(); int num = 0; int num2 = 0; int num3 = 0; Enumerator<int, BiomeItemDescriptor> enumerator = descriptorsTable.GetEnumerator(); while (enumerator.MoveNext()) { BiomeItemDescriptor value = enumerator.Current.Value; if (value == null) { continue; } num++; GameObject biomeItemPrefab = value._biomeItemPrefab; string text = (((Object)(object)biomeItemPrefab != (Object)null) ? ((Object)biomeItemPrefab).name : null); bool removableByTerraforming = value._removableByTerraforming; if (removableByTerraforming && string.IsNullOrEmpty(text)) { num3++; } else if (removableByTerraforming) { num2++; if (!dictionary.TryGetValue(text, out var value2)) { value2 = new List<BiomeItemDescriptor>(); dictionary.Add(text, value2); } value2.Add(value); } } if (num == 0) { return; } _deletable.Clear(); _keepEntries.Clear(); foreach (KeyValuePair<string, List<BiomeItemDescriptor>> item in dictionary) { _deletable.Add(item.Key, item.Value); } List<string> unbindable = null; List<string> names = new List<string>(_deletable.Keys); names.Sort(StringComparer.Ordinal); ConfigBatch.Run(Plugin.PublicConfig, delegate { int num4 = 0; foreach (string item2 in names) { try { bool num5 = ConfigBatch.IsNew(Plugin.PublicConfig, "TidyTerrain.Retention", item2); _keepEntries[item2] = Plugin.PublicConfig.Bind<bool>("TidyTerrain.Retention", item2, true, "Keep this type when leveling (re-snapped to new ground); false = vanilla deletion. Other tools always remove it."); if (num5) { num4++; } } catch (Exception) { _keepEntries.Remove(item2); if (unbindable == null) { unbindable = new List<string>(); } unbindable.Add(item2); } } return num4; }); bool initialized = _initialized; int descriptorCountAtInit = _descriptorCountAtInit; _initialized = true; _descriptorCountAtInit = count; bool flag = default(bool); if (num3 > 0) { ManualLogSource log = Plugin.Log; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(94, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] retention: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num3); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" deletable descriptor(s) had no prefab name and cannot be configured."); } log.LogWarning(val); } if (unbindable != null) { ManualLogSource log2 = Plugin.Log; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(111, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] retention: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(unbindable.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" type(s) have names BepInEx cannot use as config keys and will keep vanilla behavior: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(string.Join(", ", unbindable)); } log2.LogWarning(val); } string text2 = (initialized ? $"re-enumerated (descriptor table changed {descriptorCountAtInit} -> {count})" : "initialized"); ManualLogSource log3 = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(72, 5, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[TidyTerrain] retention "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text2); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" descriptor(s), "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num2); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" deletable, "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(_keepEntries.Count); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ["); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("TidyTerrain.Retention"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("] entries bound."); } log3.LogInfo(val2); } private static void OpenWindow() { _flipped.Clear(); foreach (KeyValuePair<string, ConfigEntry<bool>> keepEntry in _keepEntries) { if (!keepEntry.Value.Value || !_deletable.TryGetValue(keepEntry.Key, out var value)) { continue; } foreach (BiomeItemDescriptor item in value) { if (item != null && item._removableByTerraforming) { item._removableByTerraforming = false; _flipped.Add(item); } } } _windowOpen = true; } private static void CloseWindow() { int num = 0; foreach (BiomeItemDescriptor item in _flipped) { if (item != null) { item._removableByTerraforming = true; num++; } } _flipped.Clear(); _windowOpen = false; } } internal static class StructureResnapService { private static SettlementManager _settlementManager; internal static int ResnapRegion(Footprint footprint, float y) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.ConfigEnabled.Value || !Plugin.ConfigResnapStructures.Value) { return 0; } if (footprint.IsEmpty) { return 0; } Settlement playerSettlement = GetPlayerSettlement(); if ((Object)(object)playerSettlement == (Object)null) { return 0; } Structure settlementCore = GetSettlementCore(playerSettlement); HashSet<IntPtr> handled = new HashSet<IntPtr>(); int num = 0; foreach (QueryCircle item in footprint.QueryCircles()) { num += ResnapCircle(playerSettlement, settlementCore, new Vector3(item.X, y, item.Z), item.Radius, handled); } return num; } private static int ResnapCircle(Settlement settlement, Structure core, Vector3 center, float radius, HashSet<IntPtr> handled) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Expected O, but got Unknown //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0138: 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_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014d: 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_0186: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) float num = radius + Plugin.StructureRadiusMargin; List<Structure> val = new List<Structure>(); bool flag = default(bool); try { Vector3 val2 = center; float num2 = num; settlement.FindStructuresInRange(ref val2, ref num2, val, (Predicate<Structure>)null); } catch (Exception ex) { ManualLogSource log = Plugin.Log; BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(93, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[TidyTerrain] Settlement.FindStructuresInRange threw; structures were not handled this pass: "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Exception>(ex); } log.LogError(val3); return 0; } int count; try { count = val.Count; } catch (Exception ex2) { ManualLogSource log2 = Plugin.Log; BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(63, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[TidyTerrain] reading the structure result list's Count threw: "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Exception>(ex2); } log2.LogError(val3); return 0; } if (count <= 0) { return 0; } float num3 = num * num; int num4 = 0; for (int i = 0; i < count; i++) { string text = "<unknown>"; try { Structure val4 = val[i]; if ((Object)(object)val4 == (Object)null) { continue; } text = SafeName(val4); if (!val4.IsActive || val4.Dismantled || IsSettlementCore(val4, core)) { continue; } Transform transform = ((Component)val4).transform; if ((Object)(object)transform == (Object)null || IsStackedOnAnotherStructure(transform, out var _)) { continue; } Vector3 position = transform.position; float num5 = position.x - center.x; float num6 = position.z - center.z; if (num5 * num5 + num6 * num6 > num3 || !handled.Add(((Il2CppObjectBase)val4).Pointer)) { continue; } GroundSample groundSample = new GroundSample(position, transform); if (!TidyTerrainService.IsInsideCave(position, groundSample, out var _, out var _) && groundSample.TryGetY(out var groundY)) { float num7 = groundY - position.y; if (!(Mathf.Abs(num7) <= Plugin.Tolerance) && !IsSupportedFromBelow(transform, position, groundY, out var _)) { transform.position = new Vector3(position.x, groundY, position.z); UpdateNavigation(val4, text); ShiftPlacementGrid(val4, text, num7); num4++; } } } catch (Exception ex3) { ManualLogSource log3 = Plugin.Log; BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(45, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[TidyTerrain] error processing structure '"); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("': "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Exception>(ex3); } log3.LogError(val3); } } return num4; } private static bool IsStackedOnAnotherStructure(Transform t, out string carrierLabel) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown carrierLabel = "<unknown>"; try { Transform parent = t.parent; while ((Object)(object)parent != (Object)null) { Structure component = ((Component)parent).GetComponent<Structure>(); if ((Object)(object)component != (Object)null) { carrierLabel = SafeName(component); return true; } parent = parent.parent; } return false; } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(75, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] structure parent-chain check threw; skipping this structure: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogError(val); carrierLabel = "<parent-chain check threw>"; return true; } } private static bool IsSupportedFromBelow(Transform t, Vector3 pos, float groundY, out string supportLabel) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) supportLabel = "<unknown>"; try { if (!GroundHeight.TryFindSupportBetween(pos, t, pos.y, groundY, out var supportName)) { return false; } supportLabel = (string.IsNullOrEmpty(supportName) ? "<unnamed>" : supportName); return true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(70, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] structure support probe threw; skipping this structure: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogError(val); supportLabel = "<support probe threw>"; return true; } } private static void UpdateNavigation(Structure structure, string structureLabel) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown try { StructureNavigation componentInChildren = ((Component)structure).GetComponentInChildren<StructureNavigation>(); if (!((Object)(object)componentInChildren == (Object)null)) { ((NavMeshStructure)componentInChildren).UpdateLocalNavMesh(); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(97, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] structure '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(structureLabel); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("': navmesh update after the move threw (the structure was still moved): "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogError(val); } } private static void ShiftPlacementGrid(Structure structure, string structureLabel, float deltaY) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown try { PlacementGrid componentInChildren = ((Component)structure).GetComponentInChildren<PlacementGrid>(); if (!((Object)(object)componentInChildren == (Object)null)) { componentInChildren.gridY += deltaY; } } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(94, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] structure '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(structureLabel); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("': PlacementGrid.gridY fix-up threw (the structure was still moved): "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogError(val); } } private static bool IsSettlementCore(Structure structure, Structure core) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown if ((Object)(object)core == (Object)null) { return false; } try { return ((Il2CppObjectBase)structure).Pointer == ((Il2CppObjectBase)core).Pointer; } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(71, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] comparing a structure against the settlement core threw: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogError(val); return false; } } private static Structure GetSettlementCore(Settlement settlement) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown try { return settlement._settlementCore; } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(93, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] reading Settlement._settlementCore threw; the core is not protected this pass: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogError(val); return null; } } internal static Settlement GetPlayerSettlement() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown try { if ((Object)(object)_settlementManager == (Object)null) { _settlementManager = Object.FindObjectOfType<SettlementManager>(); } if ((Object)(object)_settlementManager == (Object)null) { return null; } return _settlementManager.GetPlayerSettlement(); } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(91, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] locating the player settlement threw; structures were not handled this pass: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex); } log.LogError(val); return null; } } private static string SafeName(Structure structure) { string text = "<unknown>"; try { if ((Object)(object)((Component)structure).gameObject != (Object)null) { text = ((Object)((Component)structure).gameObject).name; } } catch (Exception) { } try { string structureName = structure.StructureName; if (!string.IsNullOrEmpty(structureName)) { return text + " (" + structureName + ")"; } } catch (Exception) { } return text; } } internal static class TidyTerrainService { private const float PositionMatchEpsilonMeters = 0.05f; private static VegetationSystemPro _vegetationSystemPro; private static CavesManager _cavesManager; private static ResourceManager _resourceManager; private static GlobalSpellManager _globalSpellManager; private static bool _caveQueryUnavailableLogged; private static bool _boulderQueryUnavailableLogged; private static bool _boulderFxUnavailableLogged; private static readonly HashSet<string> _boulderMeshWarnedTypes = new HashSet<string>(); private static readonly HashSet<string> _worldGenMeshWarnedTypes = new HashSet<string>(); private static readonly XzIndex<float> _movedWorldGenPositions = new XzIndex<float>(0.05f); private const string CaveMeshLayerName = "Interior"; private static int _caveMeshLayer = -2; private const float RoofProbeStartOffsetMeters = 0.1f; private const float RoofProbeMarginMeters = 0.25f; private const float CellCenterMatchEpsilonMeters = 0.01f; public static int ResnapRegion(Footprint footprint, float y) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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_00c2: 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) _movedWorldGenPositions.Clear(); GroundHeight.BeginPass(); if (footprint.IsEmpty) { return 0; } List<QueryCircle> circles = footprint.QueryCircles(); Il2CppArrayBase<ItemObject> val; bool movedWorldGen = default(bool); try { val = Object.FindObjectsOfType<ItemObject>(); } catch (Exception ex) { ManualLogSource log = Plugin.Log; BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(53, 1, ref movedWorldGen); if (movedWorldGen) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[TidyTerrain] FindObjectsOfType<ItemObject>() threw: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex); } log.LogError(val2); return 0; } int num = 0; foreach (ItemObject item in val) { if ((Object)(object)item == (Object)null) { continue; } try { Transform transform = ((Component)item).transform; if ((Object)(object)transform == (Object)null) { continue; } Vector3 position = transform.position; if (footprint.Contains(position.x, position.z)) { GroundSample ground = new GroundSample(position, transform); if (!IsInsideCave(position, ground, out var _, out var _) && ResnapOne(item, ground, out movedWorldGen)) { num++; } } } catch (Exception ex2) { ManualLogSource log2 = Plugin.Log; BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(35, 2, ref movedWorldGen); if (movedWorldGen) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[TidyTerrain] error processing '"); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(SafeName(item)); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("': "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex2); } log2.LogError(val2); } } if (Plugin.Corpses) { num += ResnapCorpsesInRegion(footprint); } int num2 = 0; int destroyedCount = 0; int worldGenResnapped = 0; if (Plugin.WorldGen) { num2 = ResnapSupplementaryInstancesInRegion(footprint, circles, y, out destroyedCount, out worldGenResnapped); num += num2 + worldGenResnapped; } if (_movedWorldGenPositions.Count > 0) { RefreshMovedWorldGenCells(); } return num; } internal static bool IsInsideCave(Vector3 pos, GroundSample ground, out float ceilingY, out bool caveFoundAtXZ) { //IL_0028: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) ceilingY = 0f; caveFoundAtXZ = false; bool flag = false; try { CavesManager cavesManager = GetCavesManager(); float num = default(float); if ((Object)(object)cavesManager == (Object)null) { WarnCaveQueryUnavailableOnce("no CavesManager found in scene"); } else if (cavesManager.GetCaveCeilingHeight(pos.x, pos.z, Plugin.CaveMargin, ref num)) { caveFoundAtXZ = true; ceilingY = num; flag = pos.y < num; } if (!flag) { flag = IsUnderCaveRoof(pos, ground); } } catch (Exception value) { WarnCaveQueryUnavailableOnce($"GetCaveCeilingHeight threw: {value}"); return false; } if (!Plugin.CaveExclusion) { return false; } return flag; } private static bool IsUnderCaveRoof(Vector3 pos, GroundSample ground) { //IL_0046: 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_005e: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) if (_caveMeshLayer == -2) { _caveMeshLayer = LayerMask.NameToLayer("Interior"); if (_caveMeshLayer < 0) { Plugin.Log.LogWarning((object)"[TidyTerrain] no 'Interior' layer in this build; cave-roof detection is off and objects in a cave the ceiling query does not cover may be re-snapped to the surface."); } } if (_caveMeshLayer < 0) { return false; } if (!ground.TryGetY(out var groundY)) { return false; } float num = groundY - pos.y; if (num <= 0f) { return false; } return Physics.Raycast(new Vector3(pos.x, pos.y + 0.1f, pos.z), Vector3.up, num + 0.25f, 1 << _caveMeshLayer, (QueryTriggerInteraction)2); } private static void WarnCaveQueryUnavailableOnce(string reason) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (!_caveQueryUnavailableLogged) { _caveQueryUnavailableLogged = true; ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(99, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[TidyTerrain] cave detection unavailable ("); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(reason); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("); objects inside caves may be re-snapped to the surface."); } log.LogWarning(val); } } internal static CavesManager GetCavesManager() { if ((Object)(object)_cavesManager == (Object)null) { _cavesManager = Object.FindObjectOfType<CavesManager>(); } return _cavesManager; } internal static ResourceManager GetResourceManager() { if ((Object)(object)_resourceManager == (Object)null) { _resourceManager = Object.FindObjectOfType<ResourceManager>(); } return _resourceManager; } private static GlobalSpellManager GetGlobalSpellManager() { if ((Object)(object)_globalSpellManager == (Object)null) { _globalSpellManager = Object.FindObjectOfType<GlobalSpellManager>(); } return _globalSpellManager; } private static VegetationSystemPro GetVegetationSystemPro() { if ((Object)(object)_vegetationSystemPro == (Object)null) { _vegetationSystemPro = Object.FindObjectOfType<VegetationSystemPro>(); } return _vegetationSystemPro; } private static void RefreshMovedWorldGenCells() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Expected O, but got Unknown //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Expected O, but got Unknown //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Expected O, but got Unknown //IL_0363: Unknown result type (might be due to invalid IL or missing references) //IL_036a: Expected O, but got Unknown //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_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) bool flag = default(bool); try { VegetationSystemPro vegetationSystemPro = GetVegetationSystemPro(); if ((Object)(object)vegetationSystemPro == (Object)null) { Plugin.Log.LogWarning((object)"[TidyTerrain] no VegetationSystemPro found in scene; world-gen array writes were made but not marked dirty."); _movedWorldGenPositions.Clear(); return; } List<VegetationCell> val; try { val = vegetationSystemPro.VegetationCellList; } catch (Exception ex) { ManualLogSource log = Plugin.Log; BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(68, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[TidyTerrain] reading VegetationSystemPro.VegetationCellList threw: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex); } log.LogError(val2); val = null; } if (val == null || val.Count == 0) { Plugin.Log.LogWarning((object)"[TidyTerrain] VegetationCellList unavailable/empty; falling back to global SetVegetationCellsDirty()."); try { vegetationSystemPro.SetVegetationCellsDirty(); } catch (Exception ex2) { ManualLogSource log2 = Plugin.Log; BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(56, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[TidyTerrain] fallback SetVegetationCellsDirty() threw: "); ((BepInExLogInterpolatedS