Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of GradualTerrain v1.0.2
plugins/GradualTerrain.dll
Decompiled a month agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GradualTerrain.modules; using HarmonyLib; using Jotunn.Utils; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("GradualTerrain")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("GradualTerrain")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("1.0.2")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.2.0")] namespace GradualTerrain { internal class Logger { public static LogLevel Level = (LogLevel)16; public static void enableDebugLogging(object sender, EventArgs e) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (ValConfig.EnableDebugMode.Value) { Level = (LogLevel)32; } else { Level = (LogLevel)16; } } public static void setDebugLogging(bool state) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (state) { Level = (LogLevel)32; } else { Level = (LogLevel)16; } } public static void LogDebug(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)Level >= 32) { GradualTerrain.Log.LogInfo((object)message); } } public static void LogInfo(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)Level >= 16) { GradualTerrain.Log.LogInfo((object)message); } } public static void LogWarning(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)Level >= 4) { GradualTerrain.Log.LogWarning((object)message); } } public static void LogError(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)Level >= 2) { GradualTerrain.Log.LogError((object)message); } } } internal class ValConfig { public static ConfigFile cfg; public static ConfigEntry<bool> EnableDebugMode; public static ConfigEntry<float> MaxTerrainHeightAdjustment; public static ConfigEntry<float> MinTerrainHeightAdjustment; public static ConfigEntry<int> AdjustmentRange; public static ConfigEntry<float> MaxAdjustmentMineSlope; public static ConfigEntry<float> MaxAdjustmentHillSlope; public static ConfigEntry<float> RingIncrements; public static ConfigEntry<float> OffsetFromCenter; public static ConfigEntry<float> CircularGranularity; public static ConfigEntry<float> OperationRadius; public static ConfigEntry<int> ChangesPerInterval; public static ConfigEntry<float> TerrainSmoothingModifier; public static ConfigEntry<float> TerrainSmoothingPower; public static ConfigEntry<bool> PaintTerrainDuringChange; public static ConfigEntry<bool> SmoothTerrainOnChange; public static ConfigEntry<bool> AdjustmentSquare; public static ConfigEntry<float> AdjustmentPower; public static ConfigEntry<bool> EnableBiomeSpecificHeightAdjustments; public static Dictionary<Biome, ConfigEntry<float>> BiomeBasedMinTerrainAdjust = new Dictionary<Biome, ConfigEntry<float>>(); public static Dictionary<Biome, ConfigEntry<float>> BiomeBasedMaxTerrainAdjust = new Dictionary<Biome, ConfigEntry<float>>(); public ValConfig(ConfigFile cf) { cfg = cf; cfg.SaveOnConfigSet = true; CreateConfigValues(cf); Logger.setDebugLogging(EnableDebugMode.Value); SetupMainFileWatcher(); } private void CreateConfigValues(ConfigFile Config) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Expected I4, but got Unknown //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) EnableDebugMode = Config.Bind<bool>("Client config", "EnableDebugMode", false, new ConfigDescription("Enables Debug logging.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdvanced = true } })); EnableDebugMode.SettingChanged += Logger.enableDebugLogging; MaxTerrainHeightAdjustment = BindServerConfig("Terrain Height Adjustment", "MaxTerrainHeightAdjustment", 12f, "The height terrain can be raised compared to its original position (vanilla default 8).", advanced: false, 0f, 2000f); MinTerrainHeightAdjustment = BindServerConfig("Terrain Height Adjustment", "MinTerrainHeightAdjustment", -12f, "The depth terrain can be lowered to compared to its original position (vanilla default 8).", advanced: false, -2000f, 0f); EnableBiomeSpecificHeightAdjustments = BindServerConfig("Gradual Digging", "EnableBiomeSpecificHeightAdjustments", value: true, "Uses biome-specific configurations for height map adjustments. This allows for things such as, leveling mountains but not turning plains into an ocean.", null, advanced: true); EnableBiomeSpecificHeightAdjustments.SettingChanged += delegate { BiomeConfiguration.ClearCache(); }; foreach (Biome value in Enum.GetValues(typeof(Biome))) { int num = (int)value; if (num != 0 && (num & (num - 1)) == 0) { Tuple<float, float> biomeDefaultHeightAdjustments = GetBiomeDefaultHeightAdjustments(value); ConfigEntry<float> val2 = BindServerConfig($"Terrain Height Adjustment Per Biome - {(object)value}", "MinTerrainHeightAdjustment", biomeDefaultHeightAdjustments.Item2, $"Minimum terrain height adjustment for {(object)value}.", advanced: true, -2000f, 0f); ConfigEntry<float> val3 = BindServerConfig($"Terrain Height Adjustment Per Biome - {(object)value}", "MaxTerrainHeightAdjustment", biomeDefaultHeightAdjustments.Item1, $"Maximum terrain height adjustment for {(object)value}.", advanced: true, 0f, 2000f); val2.SettingChanged += delegate { BiomeConfiguration.ClearCache(); }; val3.SettingChanged += delegate { BiomeConfiguration.ClearCache(); }; BiomeBasedMinTerrainAdjust.Add(value, val2); BiomeBasedMaxTerrainAdjust.Add(value, val3); } } AdjustmentRange = BindServerConfig("Gradual Digging", "AdjustmentRange", 60, "The range that gradual terrain modifications will be applied", advanced: false, 0, 100); MaxAdjustmentMineSlope = BindServerConfig("Gradual Digging", "MaxAdjustmentMineSlope", 0.5f, "The force that smoothing is applied outward from the target operation."); MaxAdjustmentHillSlope = BindServerConfig("Gradual Digging", "MaxAdjustmentHillSlope", 0.75f, "The force that smoothing is applied outward from the target operation."); } private static Tuple<float, float> GetBiomeDefaultHeightAdjustments(Biome targetBiome) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Invalid comparison between Unknown and I4 //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Invalid comparison between Unknown and I4 //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Invalid comparison between Unknown and I4 //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Invalid comparison between Unknown and I4 //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Invalid comparison between Unknown and I4 //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 Tuple<float, float> tuple = new Tuple<float, float>(0f, 0f); if ((int)targetBiome <= 16) { if ((int)targetBiome <= 4) { if ((int)targetBiome == 1) { goto IL_0066; } if ((int)targetBiome == 4) { goto IL_0054; } } else if ((int)targetBiome == 8 || (int)targetBiome == 16) { return new Tuple<float, float>(10f, -10f); } } else if ((int)targetBiome <= 64) { if ((int)targetBiome == 32) { goto IL_0066; } if ((int)targetBiome == 64) { goto IL_0054; } } else { if ((int)targetBiome == 256) { return new Tuple<float, float>(300f, -300f); } if ((int)targetBiome == 512) { return new Tuple<float, float>(10f, -20f); } } return new Tuple<float, float>(8f, -8f); IL_0054: return new Tuple<float, float>(6f, -50f); IL_0066: return new Tuple<float, float>(8f, -8f); } internal static void SetupMainFileWatcher() { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(); fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite; fileSystemWatcher.Path = Path.GetDirectoryName(cfg.ConfigFilePath); fileSystemWatcher.Filter = "MidnightsFX.GradualTerrain.cfg"; fileSystemWatcher.Changed += OnConfigFileChanged; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; } private static void OnConfigFileChanged(object sender, FileSystemEventArgs e) { if (ZNet.instance.IsServer()) { Logger.LogInfo("Configuration file has been changed, reloading settings."); cfg.Reload(); } } public static ConfigEntry<float[]> BindServerConfig(string catagory, string key, float[] value, string description, bool advanced = false, float valmin = 0f, float valmax = 150f) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown return cfg.Bind<float[]>(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(valmin, valmax), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry<bool> BindServerConfig(string catagory, string key, bool value, string description, AcceptableValueBase acceptableValues = null, bool advanced = false) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown return cfg.Bind<bool>(catagory, key, value, new ConfigDescription(description, acceptableValues, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry<int> BindServerConfig(string catagory, string key, int value, string description, bool advanced = false, int valmin = 0, int valmax = 150) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown return cfg.Bind<int>(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<int>(valmin, valmax), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry<float> BindServerConfig(string catagory, string key, float value, string description, bool advanced = false, float valmin = 0f, float valmax = 150f) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown return cfg.Bind<float>(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(valmin, valmax), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry<string> BindServerConfig(string catagory, string key, string value, string description, AcceptableValueList<string> acceptableValues = null, bool advanced = false) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown return cfg.Bind<string>(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)acceptableValues, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } } [BepInPlugin("MidnightsFX.GradualTerrain", "GradualTerrain", "1.0.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal class GradualTerrain : BaseUnityPlugin { public const string PluginGUID = "MidnightsFX.GradualTerrain"; public const string PluginName = "GradualTerrain"; public const string PluginVersion = "1.0.2"; internal static ManualLogSource Log; internal ValConfig cfg; public void Awake() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; cfg = new ValConfig(((BaseUnityPlugin)this).Config); Log.LogInfo((object)"Breaking things down smoothly."); Assembly executingAssembly = Assembly.GetExecutingAssembly(); new Harmony("MidnightsFX.GradualTerrain").PatchAll(executingAssembly); } } } namespace GradualTerrain.modules { internal static class BiomeConfiguration { internal class HeightLimits { public float Min; public float Max; } private static ConditionalWeakTable<Heightmap, HeightLimits> cache = new ConditionalWeakTable<Heightmap, HeightLimits>(); internal static float CurrentMin = -8f; internal static float CurrentMax = 8f; private static HeightLimits envelopeLimits; internal static HeightLimits GetHeightLimits(Heightmap hmap) { if ((Object)(object)hmap == (Object)null || !ValConfig.EnableBiomeSpecificHeightAdjustments.Value) { return new HeightLimits { Min = ValConfig.MinTerrainHeightAdjustment.Value, Max = ValConfig.MaxTerrainHeightAdjustment.Value }; } if (cache.TryGetValue(hmap, out var value)) { return value; } HeightLimits heightLimits = ComputeLimits(hmap); cache.Add(hmap, heightLimits); return heightLimits; } internal static HeightLimits GetHeightLimitsAt(Vector3 worldPos, Heightmap fallback) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Heightmap val = Heightmap.FindHeightmap(worldPos); return GetHeightLimits(((Object)(object)val != (Object)null) ? val : fallback); } internal static void SetCurrentLimits(Vector3 worldPos, Heightmap fallback) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) HeightLimits heightLimitsAt = GetHeightLimitsAt(worldPos, fallback); CurrentMin = heightLimitsAt.Min; CurrentMax = heightLimitsAt.Max; } internal static void SetEnvelopeLimits() { HeightLimits heightLimits = GetEnvelopeLimits(); CurrentMin = heightLimits.Min; CurrentMax = heightLimits.Max; } private static HeightLimits GetEnvelopeLimits() { if (!ValConfig.EnableBiomeSpecificHeightAdjustments.Value) { return new HeightLimits { Min = ValConfig.MinTerrainHeightAdjustment.Value, Max = ValConfig.MaxTerrainHeightAdjustment.Value }; } if (envelopeLimits != null) { return envelopeLimits; } float num = ValConfig.MinTerrainHeightAdjustment.Value; float num2 = ValConfig.MaxTerrainHeightAdjustment.Value; foreach (ConfigEntry<float> value in ValConfig.BiomeBasedMinTerrainAdjust.Values) { num = Mathf.Min(num, value.Value); } foreach (ConfigEntry<float> value2 in ValConfig.BiomeBasedMaxTerrainAdjust.Values) { num2 = Mathf.Max(num2, value2.Value); } envelopeLimits = new HeightLimits { Min = num, Max = num2 }; return envelopeLimits; } internal static void ClearCache() { cache = new ConditionalWeakTable<Heightmap, HeightLimits>(); envelopeLimits = null; } private static HeightLimits ComputeLimits(Heightmap hmap) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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) BiomeSector[] cornerBiomes = hmap.m_cornerBiomes; float num = 0f; float num2 = 0f; int num3 = 0; for (int i = 0; i < cornerBiomes.Length; i++) { if (cornerBiomes[i] == null) { continue; } Biome biome = cornerBiomes[i].Biome; bool flag = false; for (int j = 0; j < i; j++) { if (cornerBiomes[j] != null && cornerBiomes[j].Biome == biome) { flag = true; break; } } if (!flag && ValConfig.BiomeBasedMinTerrainAdjust.TryGetValue(biome, out var value) && ValConfig.BiomeBasedMaxTerrainAdjust.TryGetValue(biome, out var value2)) { num += value.Value; num2 += value2.Value; num3++; } } if (num3 == 0) { return new HeightLimits { Min = ValConfig.MinTerrainHeightAdjustment.Value, Max = ValConfig.MaxTerrainHeightAdjustment.Value }; } return new HeightLimits { Min = num / (float)num3, Max = num2 / (float)num3 }; } } internal static class GradualDigging { [HarmonyPatch(typeof(TerrainComp))] internal static class OwnerSmoothing { internal sealed class SmoothRequest { public Vector3 Center; public float CenterHeight; public int Range; public float MinAdjust; public float MaxAdjust; public float MineSlope; public float HillSlope; public float AffectedRadius; } private struct SeamVertex { public int Index; public long Key; public float Distance; } private const string SmoothRpc = "GradualTerrain_RPC_SmoothTerrain"; private const int SmoothRpcVersion = 1; [HarmonyPostfix] [HarmonyPatch("Initialize")] private static void RegisterSmoothRpc(TerrainComp __instance) { ZNetView nview = __instance.m_nview; if (!((Object)(object)nview == (Object)null)) { nview.Unregister("GradualTerrain_RPC_SmoothTerrain"); nview.Register<ZPackage>("GradualTerrain_RPC_SmoothTerrain", (Action<long, ZPackage>)delegate(long sender, ZPackage pkg) { RPC_SmoothTerrain(__instance, sender, pkg); }); } } [HarmonyPostfix] [HarmonyPatch("DoOperation")] private static void QueueSmoothing(TerrainComp __instance, Vector3 pos, Settings modifier) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (modifier != null && modifier.m_raise && ValConfig.AdjustmentRange.Value > 0 && __instance.m_initialized && __instance.IsOwner() && ContainsCenter(__instance, pos)) { ((MonoBehaviour)__instance).StartCoroutine(SmoothAfterOperation(__instance, pos, modifier.GetRadius())); } } private static IEnumerator SmoothAfterOperation(TerrainComp centerComp, Vector3 center, float opRadius) { //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) yield return null; if (!((Object)(object)centerComp == (Object)null) && centerComp.m_initialized && centerComp.IsOwner()) { CoordinateSmoothing(centerComp, center, opRadius); } } private static void CoordinateSmoothing(TerrainComp centerComp, Vector3 center, float opRadius) { //IL_002a: 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_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_014a: 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_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0345: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) int value = ValConfig.AdjustmentRange.Value; if (value <= 0) { return; } Heightmap hmap = centerComp.m_hmap; if ((Object)(object)hmap == (Object)null || hmap.m_buildData == null) { return; } int num = default(int); int num2 = default(int); hmap.WorldToVertex(center, ref num, ref num2); int num3 = hmap.m_width + 1; int num4 = num2 * num3 + num; if (num4 < 0 || num4 >= hmap.m_buildData.m_baseHeights.Count) { Logger.LogWarning($"Got invalid index for centerpoint: pos: {center} idx: {num4} x: {num} y: {num2} rowlen: {num3}"); return; } BiomeConfiguration.HeightLimits heightLimitsAt = BiomeConfiguration.GetHeightLimitsAt(center, hmap); SmoothRequest smoothRequest = new SmoothRequest { Center = center, CenterHeight = hmap.m_buildData.m_baseHeights[num4] + ((Component)hmap).transform.position.y + centerComp.m_levelDelta[num4], Range = value, MinAdjust = heightLimitsAt.Min, MaxAdjust = heightLimitsAt.Max, MineSlope = ValConfig.MaxAdjustmentMineSlope.Value, HillSlope = ValConfig.MaxAdjustmentHillSlope.Value, AffectedRadius = Mathf.Max(opRadius, (float)value) }; Logger.LogDebug($"Starting gradual terrain change from {center} at height {smoothRequest.CenterHeight} with limits -> max:{heightLimitsAt.Max} min:{heightLimitsAt.Min}, coordinated on tile {((Component)hmap).transform.position}"); List<Heightmap> list = new List<Heightmap>(); Heightmap.FindHeightmap(center, (float)value, list); list.RemoveAll((Heightmap h) => h.IsDistantLod || h.m_buildData == null); float freshRadius = opRadius * 1.5f + 2f * hmap.m_scale; Dictionary<long, float> settled = SettleSeamVertices(list, center, value, freshRadius); bool flag = false; foreach (Heightmap item in list) { Dictionary<int, float> seamStarts = SeamStartsFor(item, center, value, settled); TerrainComp val = TerrainComp.FindTerrainCompiler(((Component)item).transform.position); if ((Object)(object)val == (Object)null) { flag |= ApplySmoothing(item, null, smoothRequest, seamStarts); } else if (val.m_initialized && !((Object)(object)val.m_nview == (Object)null) && val.m_nview.IsValid()) { if (!val.m_nview.HasOwner()) { val.m_nview.ClaimOwnership(); } if (val.m_nview.IsOwner()) { flag |= ApplySmoothing(item, val, smoothRequest, seamStarts); continue; } Logger.LogDebug($"Sending terrain smoothing for tile {((Component)item).transform.position} to its owner {val.m_nview.GetZDO().GetOwner()}."); val.m_nview.InvokeRPC("GradualTerrain_RPC_SmoothTerrain", new object[1] { WriteRequest(smoothRequest, seamStarts) }); } } if (flag && Object.op_Implicit((Object)(object)ClutterSystem.instance)) { ClutterSystem.instance.ResetGrass(center, smoothRequest.AffectedRadius); } } private static void RPC_SmoothTerrain(TerrainComp comp, long sender, ZPackage pkg) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) if (!comp.m_initialized || !comp.IsOwner()) { Logger.LogDebug($"Dropping terrain smoothing for {((Component)comp).transform.position}: not the owner here."); return; } if (!ReadRequest(pkg, out var request, out var seamStarts)) { Logger.LogWarning($"Ignoring terrain smoothing for {((Component)comp).transform.position} from {sender}: it was sent by an incompatible version of GradualTerrain."); return; } Heightmap hmap = comp.m_hmap; if (!((Object)(object)hmap == (Object)null) && !hmap.IsDistantLod && hmap.m_buildData != null) { Logger.LogDebug($"Smoothing tile {((Component)hmap).transform.position} for a dig at {request.Center}, sent by {sender}."); if (ApplySmoothing(hmap, comp, request, seamStarts) && Object.op_Implicit((Object)(object)ClutterSystem.instance)) { ClutterSystem.instance.ResetGrass(request.Center, request.AffectedRadius); } } } private static bool ApplySmoothing(Heightmap hmap, TerrainComp comp, SmoothRequest request, Dictionary<int, float> seamStarts) { TerrainComp val = SmoothHeightmap(hmap, comp, request, seamStarts); if ((Object)(object)val == (Object)null) { return false; } val.m_lastOpRadius = request.AffectedRadius; val.Save(false); val.m_hmap.Poke(0, false); return true; } private static bool ContainsCenter(TerrainComp comp, Vector3 point) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_004f: Unknown result type (might be due to invalid IL or missing references) float num = comp.m_size / 2f; Vector3 position = ((Component)comp).transform.position; if (point.x >= position.x - num && point.x < position.x + num && point.z >= position.z - num) { return point.z < position.z + num; } return false; } private static ZPackage WriteRequest(SmoothRequest request, Dictionary<int, float> seamStarts) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_000f: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); val.Write(1); val.Write(request.Center); val.Write(request.CenterHeight); val.Write(request.Range); val.Write(request.MinAdjust); val.Write(request.MaxAdjust); val.Write(request.MineSlope); val.Write(request.HillSlope); val.Write(request.AffectedRadius); val.Write(seamStarts.Count); foreach (KeyValuePair<int, float> seamStart in seamStarts) { val.Write(seamStart.Key); val.Write(seamStart.Value); } return val; } private static bool ReadRequest(ZPackage pkg, out SmoothRequest request, out Dictionary<int, float> seamStarts) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) request = null; seamStarts = null; if (pkg.ReadInt() != 1) { return false; } request = new SmoothRequest { Center = pkg.ReadVector3(), CenterHeight = pkg.ReadSingle(), Range = pkg.ReadInt(), MinAdjust = pkg.ReadSingle(), MaxAdjust = pkg.ReadSingle(), MineSlope = pkg.ReadSingle(), HillSlope = pkg.ReadSingle(), AffectedRadius = pkg.ReadSingle() }; int num = pkg.ReadInt(); seamStarts = new Dictionary<int, float>(num); for (int i = 0; i < num; i++) { int key = pkg.ReadInt(); seamStarts[key] = pkg.ReadSingle(); } return true; } internal static Dictionary<long, float> SettleSeamVertices(List<Heightmap> reachable, Vector3 center, int range, float freshRadius) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) Dictionary<long, Vector2> dictionary = new Dictionary<long, Vector2>(); foreach (Heightmap item in reachable) { TerrainComp val = TerrainComp.FindTerrainCompiler(((Component)item).transform.position); if ((Object)(object)val == (Object)null || !val.m_initialized) { continue; } bool flag = val.m_lastOpPoint == center; foreach (SeamVertex item2 in SeamVerticesInRange(item, center, range)) { if (val.m_modifiedHeight[item2.Index] && (flag || !(item2.Distance <= freshRadius))) { float num = val.m_levelDelta[item2.Index]; dictionary[item2.Key] = (dictionary.TryGetValue(item2.Key, out var value) ? new Vector2(Mathf.Min(value.x, num), Mathf.Max(value.y, num)) : new Vector2(num, num)); } } } Dictionary<long, float> dictionary2 = new Dictionary<long, float>(dictionary.Count); foreach (KeyValuePair<long, Vector2> item3 in dictionary) { dictionary2[item3.Key] = ((item3.Value.x == item3.Value.y) ? item3.Value.x : ((item3.Value.x + item3.Value.y) * 0.5f)); } return dictionary2; } private static Dictionary<int, float> SeamStartsFor(Heightmap hmap, Vector3 center, int range, Dictionary<long, float> settled) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) Dictionary<int, float> dictionary = new Dictionary<int, float>(); if (settled.Count == 0) { return dictionary; } foreach (SeamVertex item in SeamVerticesInRange(hmap, center, range)) { if (settled.TryGetValue(item.Key, out var value)) { dictionary[item.Index] = value; } } return dictionary; } private static IEnumerable<SeamVertex> SeamVerticesInRange(Heightmap hmap, Vector3 center, int range) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) float scale = hmap.m_scale; int width = hmap.m_width; int rowLength = width + 1; int half = width / 2; Vector3 pos = ((Component)hmap).transform.position; GetVertexWindow(hmap, center, range, out var x0, out var x1, out var y, out var y2); for (int i = y; i <= y2; i++) { bool edgeRow = i == 0 || i == width; for (int j = x0; j <= x1; j++) { if (edgeRow || j == 0 || j == width) { float num = pos.x + (float)(j - half) * scale; float num2 = pos.z + (float)(i - half) * scale; float num3 = center.x - num; float num4 = center.z - num2; float num5 = Mathf.Sqrt(num3 * num3 + num4 * num4); if (!(num5 > (float)range)) { yield return new SeamVertex { Index = i * rowLength + j, Key = SeamKey(num, num2, scale), Distance = num5 }; } } } } } private static long SeamKey(float worldX, float worldZ, float scale) { long num = Mathf.RoundToInt(worldX / scale); long num2 = Mathf.RoundToInt(worldZ / scale); return (num << 32) ^ (num2 & 0xFFFFFFFFu); } private static void GetVertexWindow(Heightmap hmap, Vector3 center, int range, out int x0, out int x1, out int y0, out int y1) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) int num = default(int); int num2 = default(int); hmap.WorldToVertex(center, ref num, ref num2); int num3 = Mathf.CeilToInt((float)range / hmap.m_scale); x0 = Mathf.Max(0, num - num3); x1 = Mathf.Min(hmap.m_width, num + num3); y0 = Mathf.Max(0, num2 - num3); y1 = Mathf.Min(hmap.m_width, num2 + num3); } internal static TerrainComp SmoothHeightmap(Heightmap hmap, TerrainComp comp, SmoothRequest request, Dictionary<int, float> seamStarts) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_018e: 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) if (hmap.m_buildData == null) { return null; } List<float> baseHeights = hmap.m_buildData.m_baseHeights; float scale = hmap.m_scale; int width = hmap.m_width; int num = width + 1; int num2 = width / 2; Vector3 position = ((Component)hmap).transform.position; Vector3 center = request.Center; float centerHeight = request.CenterHeight; GetVertexWindow(hmap, center, request.Range, out var x, out var x2, out var y, out var y2); float minAdjust = request.MinAdjust; float maxAdjust = request.MaxAdjust; bool flag = false; for (int i = y; i <= y2; i++) { for (int j = x; j <= x2; j++) { float num3 = position.x + (float)(j - num2) * scale; float num4 = position.z + (float)(i - num2) * scale; float num5 = center.x - num3; float num6 = center.z - num4; float num7 = Mathf.Sqrt(num5 * num5 + num6 * num6); if (num7 > (float)request.Range) { continue; } int num8 = i * num + j; float num9 = baseHeights[num8]; float num10 = (((Object)(object)comp != (Object)null) ? comp.m_levelDelta[num8] : 0f); float num11 = num10; if ((j == 0 || j == width || i == 0 || i == width) && seamStarts.TryGetValue(num8, out var value)) { num11 = value; } float num12 = num9 + position.y + num11; float num13 = num7 * request.MineSlope; float num14 = num7 * request.HillSlope; float num15; if (num12 > centerHeight + num13) { num15 = Mathf.Clamp(centerHeight + num13 - position.y - num9, minAdjust, maxAdjust); } else if (num12 < centerHeight - num14) { num15 = Mathf.Clamp(centerHeight - num14 - position.y - num9, minAdjust, maxAdjust); } else { if (num11 == num10) { continue; } num15 = num11; } if ((Object)(object)comp == (Object)null) { if ((Object)(object)ZoneSystem.instance == (Object)null || !ZoneSystem.instance.IsZoneLoaded(position)) { return null; } comp = hmap.GetAndCreateTerrainCompiler(); if ((Object)(object)comp == (Object)null || !comp.m_initialized) { return null; } } comp.m_levelDelta[num8] = num15; comp.m_modifiedHeight[num8] = true; flag = true; } } if (!flag) { return null; } return comp; } } } internal class HeightmapPatches { [HarmonyPatch(typeof(TerrainComp))] internal static class TerrainCompositionPatches { [HarmonyTranspiler] [HarmonyPatch("ApplyToHeightmap")] private static IEnumerable<CodeInstruction> ApplyToHeightmap(IEnumerable<CodeInstruction> instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)8f, (string)null) }).RemoveInstructions(1).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { Transpilers.EmitDelegate<Func<float>>((Func<float>)MinTerrainAdjustNoNeg) }) .ThrowIfNotMatch("Unable to patch min terrain adjustment.", Array.Empty<CodeMatch>()) .Advance(1) .MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)8f, (string)null) }) .RemoveInstructions(1) .InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { Transpilers.EmitDelegate<Func<float>>((Func<float>)MaxTerrainAdjust) }) .ThrowIfNotMatch("Unable to patch max terrain adjustment.", Array.Empty<CodeMatch>()); return val.Instructions(); } [HarmonyTranspiler] [HarmonyPatch("LevelTerrain")] private static IEnumerable<CodeInstruction> LevelTerrain(IEnumerable<CodeInstruction> instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)(-8f), (string)null), new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)8f, (string)null) }).RemoveInstructions(2).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2] { Transpilers.EmitDelegate<Func<float>>((Func<float>)MinTerrainAdjust), Transpilers.EmitDelegate<Func<float>>((Func<float>)MaxTerrainAdjust) }) .ThrowIfNotMatch("Unable to patch terrain level height adjustments.", Array.Empty<CodeMatch>()); return val.Instructions(); } [HarmonyTranspiler] [HarmonyPatch("RaiseTerrain")] private static IEnumerable<CodeInstruction> RaiseTerrain(IEnumerable<CodeInstruction> instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)(-8f), (string)null), new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)8f, (string)null) }).RemoveInstructions(2).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2] { Transpilers.EmitDelegate<Func<float>>((Func<float>)MinTerrainAdjust), Transpilers.EmitDelegate<Func<float>>((Func<float>)MaxTerrainAdjust) }) .ThrowIfNotMatch("Unable to patch terrain level height adjustments.", Array.Empty<CodeMatch>()); return val.Instructions(); } [HarmonyPrefix] [HarmonyPatch("LevelTerrain")] private static void LevelTerrainPrefix(TerrainComp __instance, Vector3 worldPos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) BiomeConfiguration.SetCurrentLimits(worldPos, __instance.m_hmap); } [HarmonyPrefix] [HarmonyPatch("RaiseTerrain")] private static void RaiseTerrainPrefix(TerrainComp __instance, Vector3 worldPos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) BiomeConfiguration.SetCurrentLimits(worldPos, __instance.m_hmap); } [HarmonyPrefix] [HarmonyPatch("ApplyToHeightmap")] private static void ApplyToHeightmapPrefix() { BiomeConfiguration.SetEnvelopeLimits(); } internal static float MinTerrainAdjustNoNeg() { return Mathf.Abs(BiomeConfiguration.CurrentMin); } internal static float MinTerrainAdjust() { return BiomeConfiguration.CurrentMin; } internal static float MaxTerrainAdjust() { return BiomeConfiguration.CurrentMax; } } } }