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 ESvK TerrainAdjuster v0.3.0
BepInEx/plugins/ESvK_TerrainAdjuster/ESvK_TerrainAdjuster.dll
Decompiled a month agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ESvK.TerrainAdjuster.Config; using ESvK.TerrainAdjuster.Pieces; using ESvK.TerrainAdjuster.Terrain; using ESvK.TerrainAdjuster.UI; using ESvK.TerrainAdjuster.Utilities; using HarmonyLib; using Jotunn.Entities; using Jotunn.Extensions; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.InputSystem; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ESvK Terrain Adjuster")] [assembly: AssemblyDescription("Original vanilla Hoe extension with Super Flat")] [assembly: AssemblyFileVersion("0.3.0.0")] [assembly: TargetFramework(".NETStandard,Version=v2.1")] [assembly: AssemblyVersion("0.3.0.0")] [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 ESvK.TerrainAdjuster { [BepInPlugin("esvk.valheim.terrainadjuster", "ESvK Terrain Adjuster", "0.3.0")] [BepInDependency("com.jotunn.jotunn", "2.30.0")] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "esvk.valheim.terrainadjuster"; public const string Name = "ESvK Terrain Adjuster"; public const string Version = "0.3.0"; private Harmony patches; private bool registered; private void Awake() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown Log.Initialize(((BaseUnityPlugin)this).Logger); ModConfig.Initialize(((BaseUnityPlugin)this).Config); TerrainBrush.Reset(); patches = new Harmony("esvk.valheim.terrainadjuster"); patches.PatchAll(typeof(Plugin).Assembly); PrefabManager.OnVanillaPrefabsAvailable += RegisterContent; ((BaseUnityPlugin)this).Logger.LogInfo((object)"ESvK Terrain Adjuster 0.3.0 loaded: Harmony patches installed; waiting for vanilla prefabs."); } private void RegisterContent() { if (registered) { return; } try { TerrainTool.Register(); registered = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)"ESvK tool, native Hoe menu, Super Flat and Restore Terrain registered."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("ESvK registration failed: " + ex)); } } private void Update() { EquippedSpeed.Update(); RestoreTerrainAction.UpdateSelection(); if (registered) { TerrainMenu.RefreshSettings(); if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { TerrainTool.RefreshLocalSettings(); TerrainBrush.Update(); } } } private void OnDestroy() { PrefabManager.OnVanillaPrefabsAvailable -= RegisterContent; Harmony obj = patches; if (obj != null) { obj.UnpatchSelf(); } } } } namespace ESvK.TerrainAdjuster.Utilities { internal static class BorderedIcon { internal static Sprite Create(Sprite source) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_007a: 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_00b9: Expected O, but got Unknown //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_015a: 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) if (!Object.op_Implicit((Object)(object)source) || (int)SystemInfo.graphicsDeviceType == 4) { return source; } Rect textureRect = source.textureRect; int num = Mathf.RoundToInt(((Rect)(ref textureRect)).width); int num2 = Mathf.RoundToInt(((Rect)(ref textureRect)).height); RenderTexture temporary = RenderTexture.GetTemporary(((Texture)source.texture).width, ((Texture)source.texture).height, 0, (RenderTextureFormat)0); RenderTexture active = RenderTexture.active; Texture2D val = null; try { Graphics.Blit((Texture)(object)source.texture, temporary); RenderTexture.active = temporary; val = new Texture2D(num, num2, (TextureFormat)4, false); val.ReadPixels(textureRect, 0, 0); val.Apply(); int num3 = Mathf.Max(3, Mathf.RoundToInt((float)Mathf.Min(num, num2) * 0.06f)); Texture2D val2 = new Texture2D(num + num3 * 2, num2 + num3 * 2, (TextureFormat)4, false); ((Object)val2).name = "ESvK_SuperFlat_RuntimeBorder"; ((Texture)val2).wrapMode = (TextureWrapMode)1; Color[] array = (Color[])(object)new Color[((Texture)val2).width * ((Texture)val2).height]; for (int i = 0; i < array.Length; i++) { array[i] = new Color(1f, 0f, 0.75f, 1f); } val2.SetPixels(array); val2.SetPixels(num3, num3, num, num2, val.GetPixels()); val2.Apply(false, true); return Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), new Vector2(0.5f, 0.5f), source.pixelsPerUnit); } finally { RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); if (Object.op_Implicit((Object)(object)val)) { Object.Destroy((Object)(object)val); } } } } internal static class DevelopmentIcon { internal static Sprite Create() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_016f: 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_0054: 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_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false); ((Object)val).name = "ESvK_OriginalDevelopmentIcon"; Color[] array = (Color[])(object)new Color[4096]; for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { float num = (float)j - 31.5f; float num2 = (float)i - 31.5f; bool num3 = num * num + num2 * num2 < 900f; Color val2 = (Color)(num3 ? new Color(0.035f, 0.11f, 0.13f, 1f) : Color.clear); float num4 = (float)i - 6f * Mathf.Sin((float)j * 0.09f); if (num3 && j > 9 && j < 54 && i > 10 && i < 54 && Mathf.Repeat(num4, 10f) < 2f) { ((Color)(ref val2))..ctor(0.3f, 0.88f, 0.68f, 1f); } if (num3 && ((j >= 29 && j <= 33 && i > 12 && i < 52) || (j > 23 && j < 40 && i > 34 && i < 40))) { ((Color)(ref val2))..ctor(1f, 0.72f, 0.25f, 1f); } array[i * 64 + j] = val2; } } val.SetPixels(array); val.Apply(); return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f); } } [HarmonyPatch] internal static class EquippedSpeed { private static bool previousEquipped; private static bool previousBoost; private static float previousMultiplier; internal static bool Holding(Player player) { if (Object.op_Implicit((Object)(object)player) && !((Character)player).IsDead() && !((Character)player).IsTeleporting()) { return TerrainTool.IsEquipped(player); } return false; } [HarmonyPostfix] [HarmonyPatch(typeof(SEMan), "ApplyStatusEffectSpeedMods")] private static void Apply(Character ___m_character, ref float speed) { Player val = (Player)(object)((___m_character is Player) ? ___m_character : null); if (val != null && Holding(val) && ModConfig.EnableEquippedSpeedBoost.Value) { speed *= ModConfig.EquippedSpeedMultiplier.Value; } } internal static void Update() { bool flag = Holding(Player.m_localPlayer); bool flag2 = flag && ModConfig.EnableEquippedSpeedBoost.Value; if (flag != previousEquipped) { Log.Debug(flag ? "Tool equipped" : "Tool unequipped"); } if (flag2 != previousBoost || (flag2 && previousMultiplier != ModConfig.EquippedSpeedMultiplier.Value)) { Log.Debug(flag2 ? ("Equipped speed boost applied: x" + ModConfig.EquippedSpeedMultiplier.Value) : "Equipped speed boost removed"); } previousEquipped = flag; previousBoost = flag2; previousMultiplier = ModConfig.EquippedSpeedMultiplier.Value; } } internal static class Log { private static ManualLogSource source; internal static void Initialize(ManualLogSource logger) { source = logger; } internal static void Error(string message) { source.LogError((object)("[ESvK Terrain] " + message)); } internal static void Warn(string message) { source.LogWarning((object)("[ESvK Terrain] " + message)); } internal static void Debug(string message) { if (ModConfig.DebugLogging.Value) { source.LogInfo((object)("[ESvK Terrain] " + message)); } } } internal static class RestoreIcon { internal static Sprite Create() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: 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) //IL_00e0: 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_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false); ((Object)val).name = "ESvK_Restore_Original_R"; ((Texture)val).wrapMode = (TextureWrapMode)1; Color[] array = (Color[])(object)new Color[4096]; string[] array2 = new string[7] { "11110", "10001", "10001", "11110", "10100", "10010", "10001" }; for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { Color val2 = ((j < 4 || j >= 60 || i < 4 || i >= 60) ? new Color(0.62f, 0.2f, 1f, 1f) : (((float)i < 19f + 4f * Mathf.Sin((float)j * 0.13f)) ? new Color(0.13f, 0.21f, 0.17f, 1f) : new Color(0.06f, 0.08f, 0.12f, 1f))); int index = (j - 17) / 6; int num = (52 - i) / 6; if (j >= 17 && j < 47 && i > 10 && i <= 52 && num < 7 && array2[num][index] == '1') { ((Color)(ref val2))..ctor(0.94f, 0.9f, 1f, 1f); } array[i * 64 + j] = val2; } } val.SetPixels(array); val.Apply(); return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f); } } } namespace ESvK.TerrainAdjuster.UI { internal static class RadiusDisplay { internal static void Show(float radius) { if (Object.op_Implicit((Object)(object)MessageHud.instance)) { MessageHud.instance.ShowMessage((MessageType)2, "Super Flat Radius: " + radius.ToString("0.#", CultureInfo.InvariantCulture) + "m", 0, (Sprite)null, false, true); Log.Debug("Super Flat radius=" + radius.ToString(CultureInfo.InvariantCulture)); } } } } namespace ESvK.TerrainAdjuster.Pieces { [HarmonyPatch] internal static class RestoreActionCost { private sealed class CostState { internal SharedData Data; internal float Stamina; internal bool Durability; } [HarmonyPrefix] [HarmonyPatch(typeof(Player), "UpdatePlacement")] private static void BeforePlacement(Player __instance, out CostState __state) { __state = null; if (!TerrainTool.IsEquipped(__instance)) { return; } Piece selectedPiece = __instance.GetSelectedPiece(); if (Object.op_Implicit((Object)(object)selectedPiece) && RestoreTerrainAction.IsRestore(((Component)selectedPiece).gameObject)) { ItemData rightItem = ((Humanoid)__instance).RightItem; if (rightItem?.m_shared?.m_attack != null) { __state = new CostState { Data = rightItem.m_shared, Stamina = rightItem.m_shared.m_attack.m_attackStamina, Durability = rightItem.m_shared.m_useDurability }; rightItem.m_shared.m_attack.m_attackStamina = 0f; rightItem.m_shared.m_useDurability = false; } } } [HarmonyFinalizer] [HarmonyPatch(typeof(Player), "UpdatePlacement")] private static void AfterPlacement(CostState __state) { if (__state != null) { __state.Data.m_attack.m_attackStamina = __state.Stamina; __state.Data.m_useDurability = __state.Durability; } } } [HarmonyPatch] internal static class RestoreTerrainAction { internal const string PrefabName = "ESvK_TerrainAdjuster_RestoreTerrain"; private static bool wasSelected; internal static TerrainOp Operation { get; private set; } internal static bool IsRestore(GameObject prefab) { if (Object.op_Implicit((Object)(object)prefab)) { return Utils.GetPrefabName(((Object)prefab).name) == "ESvK_TerrainAdjuster_RestoreTerrain"; } return false; } internal static void Register(PieceTable table, GameObject superFlatPrefab) { PrefabManager instance = PrefabManager.Instance; GameObject val = instance.CreateClonedPrefab("ESvK_TerrainAdjuster_RestoreTerrain", superFlatPrefab); if (!Object.op_Implicit((Object)(object)val) || val.activeInHierarchy) { throw new InvalidOperationException("Restore Terrain needs an inactive native template."); } Piece component = val.GetComponent<Piece>(); component.m_name = "Restore Terrain"; component.m_description = "Restore terrain within the selected radius to its original state."; component.m_icon = RestoreIcon.Create(); component.m_resources = Array.Empty<Requirement>(); component.m_craftingStation = null; component.m_allowAltGroundPlacement = false; Operation = val.GetComponent<TerrainOp>(); Operation.m_settings = RestoreTerrainNetworking.NewSettings(TerrainBrush.EffectiveRadius); Operation.m_spawnOnPlaced = null; instance.AddPrefab(val); table.m_pieces.Add(val); RegisterOperation(ObjectDB.instance); } [HarmonyPostfix] [HarmonyPatch(typeof(ObjectDB), "UpdateRegisters")] private static void RegisterOperation(ObjectDB __instance) { if (Object.op_Implicit((Object)(object)__instance) && Object.op_Implicit((Object)(object)Operation)) { int stableHashCode = StringExtensionMethods.GetStableHashCode("ESvK_TerrainAdjuster_RestoreTerrain"); if (__instance.m_terrainOpsByHash.TryGetValue(stableHashCode, out var value) && (Object)(object)value != (Object)(object)Operation) { throw new InvalidOperationException("Restore Terrain prefab hash collision."); } if (!__instance.m_terrainOps.Contains(Operation)) { __instance.m_terrainOps.Add(Operation); } __instance.m_terrainOpsByHash[stableHashCode] = Operation; } } internal static void UpdateSelection() { Player localPlayer = Player.m_localPlayer; Piece val = ((Object.op_Implicit((Object)(object)localPlayer) && TerrainTool.IsEquipped(localPlayer)) ? localPlayer.GetSelectedPiece() : null); int num; if (Object.op_Implicit((Object)(object)val)) { num = (IsRestore(((Component)val).gameObject) ? 1 : 0); if (num != 0 && !wasSelected) { Log.Debug("Restore Terrain selected"); } } else { num = 0; } wasSelected = (byte)num != 0; } } [HarmonyPatch] internal static class TerrainMenu { internal const string TableName = "ESvK_TerrainAdjuster_Table"; internal const string SuperFlatName = "ESvK_TerrainAdjuster_SuperFlat"; private static Piece superFlat; private static Requirement[] paidRequirements; private static CraftingStation workbench; internal static TerrainOp Operation { get; private set; } internal static PieceTable Register(Sprite fallbackIcon) { //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Expected O, but got Unknown PrefabManager instance = PrefabManager.Instance; PieceTable buildPieces = instance.GetPrefab("Hoe").GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces; if (!Object.op_Implicit((Object)(object)buildPieces) || buildPieces.m_pieces.Count == 0) { throw new InvalidOperationException("Current Hoe table is missing."); } GameObject val = ((IEnumerable<GameObject>)buildPieces.m_pieces).FirstOrDefault((Func<GameObject, bool>)IsLevelingTemplate); if (!Object.op_Implicit((Object)(object)val)) { throw new InvalidOperationException("No native leveling/smoothing template found. Hoe entries: " + string.Join("; ", buildPieces.m_pieces.Select(DescribeTemplate))); } GameObject val2 = instance.CreateClonedPrefab("ESvK_TerrainAdjuster_Table", ((Component)buildPieces).gameObject); PieceTable component = val2.GetComponent<PieceTable>(); component.m_pieces = new List<GameObject>(buildPieces.m_pieces); component.m_categories = new List<PieceCategory>(buildPieces.m_categories); component.m_categoryLabels = new List<string>(buildPieces.m_categoryLabels); instance.AddPrefab(val2); GameObject val3 = instance.CreateClonedPrefab("ESvK_TerrainAdjuster_SuperFlat", val); superFlat = val3.GetComponent<Piece>(); superFlat.m_name = "Super Flat"; superFlat.m_description = "Flatten the full circle to your standing level. Hold Shift for aimed height. Ctrl + wheel adjusts radius."; superFlat.m_enabled = true; superFlat.m_groundPiece = true; superFlat.m_allowAltGroundPlacement = true; superFlat.m_canBeRemoved = false; superFlat.m_icon = BorderedIcon.Create(val.GetComponent<Piece>().m_icon) ?? fallbackIcon; Operation = val3.GetComponent<TerrainOp>(); if (!Object.op_Implicit((Object)(object)Operation)) { if (val3.activeInHierarchy) { throw new InvalidOperationException("Super Flat template must be inactive during registration."); } TerrainModifier component2 = val3.GetComponent<TerrainModifier>(); Operation = val3.AddComponent<TerrainOp>(); if (Object.op_Implicit((Object)(object)component2)) { Operation.m_onPlacedEffect = component2.m_onPlacedEffect; } ZNetView component3 = val3.GetComponent<ZNetView>(); if (Object.op_Implicit((Object)(object)component3)) { Object.DestroyImmediate((Object)(object)component3); } } Operation.m_settings = SuperFlatNetworking.NewSettings(ModConfig.DefaultRadius.Value); Operation.m_spawnOnPlaced = null; SuperFlatPreview.Configure(val3); TerrainModifier[] components = val3.GetComponents<TerrainModifier>(); for (int i = 0; i < components.Length; i++) { Object.DestroyImmediate((Object)(object)components[i]); } paidRequirements = (Requirement[])(object)new Requirement[1] { new Requirement { m_resItem = instance.GetPrefab("Stone").GetComponent<ItemDrop>(), m_amount = 2, m_recover = false } }; workbench = instance.GetPrefab("piece_workbench").GetComponent<CraftingStation>(); RefreshSettings(); instance.AddPrefab(val3); component.m_pieces.Add(val3); RegisterOperation(ObjectDB.instance); RestoreTerrainAction.Register(component, val3); Log.Debug("Copied " + buildPieces.m_pieces.Count + " native Hoe entries; appended Super Flat and Restore Terrain. Leveling template: " + ((Object)val).name); return component; } internal static bool IsSuperFlat(GameObject prefab) { if (Object.op_Implicit((Object)(object)prefab)) { return Utils.GetPrefabName(((Object)prefab).name) == "ESvK_TerrainAdjuster_SuperFlat"; } return false; } private static bool IsLevelingTemplate(GameObject prefab) { if (!Object.op_Implicit((Object)(object)prefab) || !Object.op_Implicit((Object)(object)prefab.GetComponent<Piece>())) { return false; } TerrainOp component = prefab.GetComponent<TerrainOp>(); if (Object.op_Implicit((Object)(object)component)) { if (component.m_settings != null) { if (!component.m_settings.m_level) { return component.m_settings.m_smooth; } return true; } return false; } TerrainModifier component2 = prefab.GetComponent<TerrainModifier>(); if (Object.op_Implicit((Object)(object)component2)) { if (!component2.m_level) { return component2.m_smooth; } return true; } return false; } private static string DescribeTemplate(GameObject prefab) { if (!Object.op_Implicit((Object)(object)prefab)) { return "<missing>"; } TerrainOp component = prefab.GetComponent<TerrainOp>(); TerrainModifier component2 = prefab.GetComponent<TerrainModifier>(); return ((Object)prefab).name + " TerrainOp=" + Object.op_Implicit((Object)(object)component) + " level=" + (Object.op_Implicit((Object)(object)component) && component.m_settings != null && component.m_settings.m_level) + " smooth=" + (Object.op_Implicit((Object)(object)component) && component.m_settings != null && component.m_settings.m_smooth) + " TerrainModifier=" + Object.op_Implicit((Object)(object)component2); } internal static void RefreshSettings() { if (Object.op_Implicit((Object)(object)superFlat)) { superFlat.m_resources = (ModConfig.RequiresResources.Value ? paidRequirements : Array.Empty<Requirement>()); superFlat.m_craftingStation = (ModConfig.RequireWorkbench.Value ? workbench : null); } } [HarmonyPostfix] [HarmonyPatch(typeof(ObjectDB), "UpdateRegisters")] private static void RegisterOperation(ObjectDB __instance) { if (Object.op_Implicit((Object)(object)__instance) && Object.op_Implicit((Object)(object)Operation)) { int stableHashCode = StringExtensionMethods.GetStableHashCode("ESvK_TerrainAdjuster_SuperFlat"); if (__instance.m_terrainOpsByHash.TryGetValue(stableHashCode, out var value) && (Object)(object)value != (Object)(object)Operation) { throw new InvalidOperationException("Super Flat TerrainOp hash collision."); } if (!__instance.m_terrainOps.Contains(Operation)) { __instance.m_terrainOps.Add(Operation); } __instance.m_terrainOpsByHash[stableHashCode] = Operation; } } } internal static class TerrainTool { internal const string PrefabName = "ESvK_TerrainAdjuster"; private const string DisplayName = "ESvK Terrain Adjuster"; private static CustomItem tool; private static Recipe recipe; private static float vanillaStamina; private static float vanillaDrain; internal static bool IsEquipped(Player player) { if (Object.op_Implicit((Object)(object)player) && !((Character)player).IsDead() && !((Character)player).IsTeleporting() && Object.op_Implicit((Object)(object)player.GetBuildTool())) { return ((Object)player.GetBuildTool()).name == "ESvK_TerrainAdjuster_Table"; } return false; } internal static void Register() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Expected O, but got Unknown Sprite val = DevelopmentIcon.Create(); PieceTable buildPieces = TerrainMenu.Register(val); tool = new CustomItem("ESvK_TerrainAdjuster", "Hoe"); if (!Object.op_Implicit((Object)(object)tool.ItemPrefab)) { throw new InvalidOperationException("Vanilla Hoe prefab unavailable."); } SharedData shared = tool.ItemDrop.m_itemData.m_shared; SharedData shared2 = PrefabManager.Instance.GetPrefab("Hoe").GetComponent<ItemDrop>().m_itemData.m_shared; if (shared == shared2 || shared.m_attack == shared2.m_attack) { throw new InvalidOperationException("Vanilla hoe clone did not isolate mutable item settings."); } vanillaStamina = shared.m_attack.m_attackStamina; vanillaDrain = shared.m_useDurabilityDrain; shared.m_name = "ESvK Terrain Adjuster"; shared.m_description = "Vanilla Hoe tools plus Super Flat. Hold Ctrl and scroll to adjust Super Flat radius."; shared.m_icons = (Sprite[])(object)new Sprite[1] { val }; shared.m_buildPieces = buildPieces; shared.m_maxQuality = 1; shared.m_equipStatusEffect = null; tool.ItemDrop.m_itemData.m_dropPrefab = tool.ItemPrefab; recipe = ScriptableObject.CreateInstance<Recipe>(); ((Object)recipe).name = "Recipe_ESvK_TerrainAdjuster"; recipe.m_item = tool.ItemDrop; recipe.m_amount = 1; recipe.m_enabled = true; recipe.m_minStationLevel = 1; recipe.m_resources = Array.Empty<Requirement>(); tool.Recipe = new CustomRecipe(recipe, false, false); ApplyItemSettings(shared); if (!ItemManager.Instance.AddItem(tool)) { throw new InvalidOperationException("Could not register ESvK tool."); } Log.Debug("Vanilla Hoe cloned at runtime; standalone ESvK tool and recipe registered."); } private static void ApplyItemSettings(SharedData data) { data.m_useDurability = ModConfig.UseDurability.Value; data.m_useDurabilityDrain = (ModConfig.UseDurability.Value ? vanillaDrain : 0f); data.m_attack.m_attackStamina = (ModConfig.UseStamina.Value ? vanillaStamina : 0f); } internal static void RefreshLocalSettings() { if (tool == null) { return; } ApplyItemSettings(tool.ItemDrop.m_itemData.m_shared); foreach (ItemData allItem in ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems()) { if (allItem.m_shared.m_name == "ESvK Terrain Adjuster") { ApplyItemSettings(allItem.m_shared); } } } } } namespace ESvK.TerrainAdjuster.Terrain { internal static class FlatGrid { internal static bool Finite(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } internal static int Apply(int width, float scale, float originX, float originZ, float centerX, float centerZ, float targetLocalY, float radius, float[] baseline, float[] level, float[] smooth, bool[] modified, bool[] mask) { int num = width + 1; int num2 = num * num; int num3 = 0; if (baseline.Length != num2 || level.Length != num2 || smooth.Length != num2 || modified.Length != num2 || mask.Length != num2) { throw new ArgumentException("Terrain grid size mismatch."); } if (!Finite(targetLocalY) || !Finite(radius) || radius <= 0f || !Finite(scale) || scale <= 0f) { throw new ArgumentException("Invalid terrain grid parameters."); } for (int i = 0; i <= width; i++) { for (int j = 0; j <= width; j++) { float num4 = originX + (float)j * scale - centerX; float num5 = originZ + (float)i * scale - centerZ; if (!(num4 * num4 + num5 * num5 > radius * radius + 0.0001f)) { int num6 = i * num + j; level[num6] = targetLocalY - baseline[num6]; smooth[num6] = 0f; modified[num6] = (mask[num6] = true); num3++; } } } return num3; } internal static byte[] Encode(bool[] mask) { using MemoryStream memoryStream = new MemoryStream(); using BinaryWriter binaryWriter = new BinaryWriter(memoryStream); binaryWriter.Write(1); binaryWriter.Write(mask.Length); for (int i = 0; i < mask.Length; i += 8) { byte b = 0; for (int j = 0; j < 8 && i + j < mask.Length; j++) { if (mask[i + j]) { b |= (byte)(1 << j); } } binaryWriter.Write(b); } return memoryStream.ToArray(); } internal static bool[] Decode(byte[] bytes, int count) { if (bytes == null || bytes.Length == 0) { return null; } if (count < 1 || bytes.Length != 8 + (count + 7) / 8) { throw new InvalidDataException("Invalid Super Flat mask length."); } using BinaryReader binaryReader = new BinaryReader(new MemoryStream(bytes)); if (binaryReader.ReadInt32() != 1 || binaryReader.ReadInt32() != count) { throw new InvalidDataException("Unsupported Super Flat mask version/grid."); } bool[] array = new bool[count]; for (int i = 0; i < count; i += 8) { byte b = binaryReader.ReadByte(); for (int j = 0; j < 8 && i + j < count; j++) { array[i + j] = (b & (1 << j)) != 0; } } return array; } } internal static class PreviewRadiusMath { internal static float Diameter(float radius) { return radius * 2f; } } internal static class RadiusMath { internal static float Clamp(float value, float minimum, float maximum) { if (float.IsNaN(minimum) || float.IsInfinity(minimum)) { minimum = 1f; } if (float.IsNaN(maximum) || float.IsInfinity(maximum)) { maximum = 20f; } minimum = Math.Max(0.1f, minimum); maximum = Math.Max(minimum, maximum); if (float.IsNaN(value) || float.IsInfinity(value)) { value = minimum; } return Math.Max(minimum, Math.Min(maximum, value)); } } internal static class RestoreGrid { internal static List<int> Select(int width, float scale, float originX, float originZ, float centerX, float centerZ, float radius) { if (width < 1 || width > 1024 || !Finite(scale) || scale <= 0f || !Finite(radius) || radius < 1f || radius > 20f || !Finite(originX) || !Finite(originZ) || !Finite(centerX) || !Finite(centerZ)) { throw new ArgumentException("Invalid restore grid or radius."); } List<int> list = new List<int>(); int num = width + 1; for (int i = 0; i <= width; i++) { for (int j = 0; j <= width; j++) { float num2 = originX + (float)j * scale - centerX; float num3 = originZ + (float)i * scale - centerZ; if (num2 * num2 + num3 * num3 <= radius * radius) { list.Add(i * num + j); } } } return list; } internal static void Clear(List<int> indices, float[] level, float[] smooth, bool[] height, bool[] paint, bool[] flatMask, out int heights, out int paints) { int num = level.Length; if (smooth.Length != num || height.Length != num || paint.Length != num || (flatMask != null && flatMask.Length != num)) { throw new ArgumentException("Restore array mismatch."); } foreach (int index in indices) { if (index < 0 || index >= num) { throw new ArgumentOutOfRangeException("indices"); } } heights = (paints = 0); foreach (int index2 in indices) { if (height[index2] || level[index2] != 0f || smooth[index2] != 0f || (flatMask != null && flatMask[index2])) { heights++; } if (paint[index2]) { paints++; } level[index2] = (smooth[index2] = 0f); height[index2] = (paint[index2] = false); if (flatMask != null) { flatMask[index2] = false; } } } private static bool Finite(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } } [HarmonyPatch] internal static class RestoreTerrainExecution { private static readonly int FlatMaskKey = StringExtensionMethods.GetStableHashCode("esvk.terrainadjuster.flatmask.v1"); private static readonly FieldRef<Heightmap, HMBuildData> BuildData = AccessTools.FieldRefAccess<Heightmap, HMBuildData>("m_buildData"); [HarmonyPrefix] [HarmonyPatch(typeof(TerrainComp), "InternalDoOperation")] private unsafe static bool Apply(Settings modifier, Vector3 pos, Heightmap ___m_hmap, ZNetView ___m_nview, bool ___m_initialized, float[] ___m_levelDelta, float[] ___m_smoothDelta, bool[] ___m_modifiedHeight, bool[] ___m_modifiedPaint, Color[] ___m_paintMask, ref int ___m_operations, ref Vector3 ___m_lastOpPoint, ref float ___m_lastOpRadius) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) if (!RestoreTerrainNetworking.TryGet(modifier, out var request)) { return true; } try { if (!___m_initialized || !Object.op_Implicit((Object)(object)___m_hmap) || !Object.op_Implicit((Object)(object)___m_nview) || !___m_nview.IsValid() || !___m_nview.IsOwner() || !FlatGrid.Finite(pos.x) || !FlatGrid.Finite(pos.y) || !FlatGrid.Finite(pos.z)) { throw new InvalidOperationException("Missing initialized Heightmap/owned terrain ZDO or invalid center."); } ___m_hmap.Poke(0, false); HMBuildData val = BuildData.Invoke(___m_hmap); int width = ___m_hmap.m_width; int num = (width + 1) * (width + 1); if (val == null || val.m_baseHeights == null || val.m_baseMask == null || val.m_baseHeights.Count != num || val.m_baseMask.Length != num || ___m_levelDelta.Length != num || ___m_paintMask.Length != num) { throw new InvalidOperationException("Original generated height/paint grid unavailable; restoration skipped."); } float scale = ___m_hmap.m_scale; Vector3 position = ((Component)___m_hmap).transform.position; float originX = position.x - (float)width * scale * 0.5f; float originZ = position.z - (float)width * scale * 0.5f; List<int> list = RestoreGrid.Select(width, scale, originX, originZ, pos.x, pos.z, modifier.m_levelRadius); request.Skipped = ExcludeLegacy(list, width, scale, originX, originZ); if (request.Skipped > 0) { Log.Warn("Restore Terrain: skipped " + request.Skipped + " vertices overlapping legacy player TerrainModifier state. No legacy objects were removed or converted."); } bool[] array = FlatGrid.Decode(___m_nview.GetZDO().GetByteArray(FlatMaskKey, (byte[])null), num); RestoreGrid.Clear(list, ___m_levelDelta, ___m_smoothDelta, ___m_modifiedHeight, ___m_modifiedPaint, array, out request.Heights, out request.Paint); foreach (int item in list) { ___m_paintMask[item] = val.m_baseMask[item]; } if (array != null) { ___m_nview.GetZDO().Set(FlatMaskKey, FlatGrid.Encode(array)); } ___m_hmap.Poke(0, false); foreach (int item2 in list) { ___m_paintMask[item2] = ___m_hmap.GetPaintMask(item2 % (width + 1), item2 / (width + 1)); } ___m_operations++; ___m_lastOpPoint = pos; ___m_lastOpRadius = modifier.m_levelRadius; request.Applied = true; string[] obj = new string[8] { "Terrain vertices restored: ", request.Heights.ToString(), "; Terrain paint restored: ", request.Paint.ToString(), "; Heightmap=", null, null, null }; Vector3 val2 = position; obj[5] = ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString(); obj[6] = "; legacy vertices skipped="; obj[7] = request.Skipped.ToString(); Log.Debug(string.Concat(obj)); } catch (Exception ex) { Log.Error("Restore Terrain skipped/failed: " + ex); } return false; } private static int ExcludeLegacy(List<int> indices, int width, float scale, float originX, float originZ) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) int count = indices.Count; foreach (TerrainModifier allInstance in TerrainModifier.GetAllInstances()) { if (Object.op_Implicit((Object)(object)allInstance) && ((Behaviour)allInstance).enabled && ((Component)allInstance).gameObject.activeInHierarchy && allInstance.m_playerModifiction && (allInstance.m_level || allInstance.m_smooth || allInstance.m_paintCleared)) { Vector3 center = ((Component)allInstance).transform.position; float extent = allInstance.GetRadius() * Mathf.Sqrt(2f) + scale; indices.RemoveAll(delegate(int i) { float num = originX + (float)(i % (width + 1)) * scale - center.x; float num2 = originZ + (float)(i / (width + 1)) * scale - center.z; return num * num + num2 * num2 <= extent * extent; }); } } return count - indices.Count; } [HarmonyPostfix] [HarmonyPatch(typeof(TerrainComp), "DoOperation")] private static void Completed(Settings modifier, ZNetView ___m_nview) { if (RestoreTerrainNetworking.TryGet(modifier, out var request) && request.Applied) { Log.Debug("Restore operation completed: native terrain save returned; ZDO revision=" + ___m_nview.GetZDO().DataRevision + "; vertices=" + request.Heights + "; paint=" + request.Paint); } } } [HarmonyPatch] internal static class RestoreTerrainNetworking { internal sealed class Request { internal bool Applied; internal int Heights; internal int Paint; internal int Skipped; } private const int Protocol = 1163067905; private static readonly ConditionalWeakTable<Settings, Request> requests = new ConditionalWeakTable<Settings, Request>(); internal static bool TryGet(Settings settings, out Request request) { request = null; if (settings != null) { return requests.TryGetValue(settings, out request); } return false; } internal static Settings NewSettings(float radius) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown return new Settings { m_level = true, m_levelRadius = radius, m_square = false, m_raise = false, m_smooth = false, m_paintCleared = false, m_rotation = false, m_levelOffset = 0f, m_halfOffset = false }; } [HarmonyPrefix] [HarmonyPatch(typeof(TerrainOp), "Awake")] private static void BeforeRestoreAwake(TerrainOp __instance) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)__instance) && !TerrainOp.m_forceDisableTerrainOps && RestoreTerrainAction.IsRestore(((Component)__instance).gameObject)) { float effectiveRadius = TerrainBrush.EffectiveRadius; __instance.m_settings = NewSettings(effectiveRadius); List<Heightmap> list = new List<Heightmap>(); Heightmap.FindHeightmap(((Component)__instance).transform.position, effectiveRadius, list); Log.Debug("Restore center: " + ((object)((Component)__instance).transform.position/*cast due to .constrained prefix*/).ToString() + "; Restore radius: " + effectiveRadius + "; Heightmaps affected: " + list.Count); } } [HarmonyPostfix] [HarmonyPatch(typeof(Settings), "Serialize")] private static void Serialize(Settings __instance, ZPackage pkg, GameObject prefab) { if (RestoreTerrainAction.IsRestore(prefab)) { pkg.Write(1163067905); pkg.Write(__instance.m_levelRadius); } } [HarmonyPostfix] [HarmonyPatch(typeof(Settings), "Deserialize")] private static void Deserialize(ZPackage pkg, ref Settings __result) { if (!Object.op_Implicit((Object)(object)RestoreTerrainAction.Operation) || __result != RestoreTerrainAction.Operation.m_settings) { return; } try { if (pkg.ReadInt() != 1163067905) { throw new InvalidOperationException("Unsupported restore RPC version."); } float num = pkg.ReadSingle(); if (!FlatGrid.Finite(num) || num < 1f || num > 20f) { throw new InvalidOperationException("Invalid restore radius."); } num = RadiusMath.Clamp(num, ModConfig.MinimumRadius.Value, ModConfig.MaximumRadius.Value); __result = NewSettings(num); requests.Add(__result, new Request()); Log.Debug("Restore Terrain RPC received; radius=" + num); } catch (Exception ex) { __result = null; Log.Error("Restore Terrain RPC rejected: " + ex.Message); } } [HarmonyPostfix] [HarmonyPatch(typeof(TerrainComp), "ApplyOperation")] private static void Sent(TerrainOp modifier) { if (Object.op_Implicit((Object)(object)modifier) && RestoreTerrainAction.IsRestore(((Component)modifier).gameObject)) { Log.Debug("Restore Terrain RPC sent to terrain owner."); } } } [HarmonyPatch] internal static class SuperFlatNetworking { private sealed class Marker { } private const int Protocol = 1163067649; private static readonly ConditionalWeakTable<Settings, Marker> received = new ConditionalWeakTable<Settings, Marker>(); internal static bool IsReceived(Settings settings) { Marker value; if (settings != null) { return received.TryGetValue(settings, out value); } return false; } internal static Settings NewSettings(float radius) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown return new Settings { m_level = true, m_levelRadius = radius, m_levelOffset = 0f, m_square = false, m_raise = false, m_smooth = false, m_paintCleared = false, m_rotation = false, m_halfOffset = false }; } [HarmonyPrefix] [HarmonyPatch(typeof(TerrainOp), "Awake")] private static void BeforeTerrainOpAwake(TerrainOp __instance) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)__instance) && !TerrainOp.m_forceDisableTerrainOps && TerrainMenu.IsSuperFlat(((Component)__instance).gameObject)) { float effectiveRadius = TerrainBrush.EffectiveRadius; __instance.m_settings = NewSettings(effectiveRadius); Log.Debug("Super Flat target position: " + ((object)((Component)__instance).transform.position/*cast due to .constrained prefix*/).ToString() + "; target height: " + ((Component)__instance).transform.position.y + "; radius: " + effectiveRadius); } } [HarmonyPostfix] [HarmonyPatch(typeof(Settings), "Serialize")] private static void Serialize(Settings __instance, ZPackage pkg, GameObject prefab) { if (TerrainMenu.IsSuperFlat(prefab)) { pkg.Write(1163067649); pkg.Write(__instance.m_levelRadius); } } [HarmonyPostfix] [HarmonyPatch(typeof(Settings), "Deserialize")] private static void Deserialize(ZPackage pkg, ref Settings __result) { if (!Object.op_Implicit((Object)(object)TerrainMenu.Operation) || __result != TerrainMenu.Operation.m_settings) { return; } try { if (pkg.ReadInt() != 1163067649) { throw new InvalidOperationException("Unsupported Super Flat RPC version."); } float num = pkg.ReadSingle(); if (!FlatGrid.Finite(num) || num < 1f || num > 20f) { throw new InvalidOperationException("Invalid Super Flat RPC radius."); } num = RadiusMath.Clamp(num, ModConfig.MinimumRadius.Value, ModConfig.MaximumRadius.Value); __result = NewSettings(num); received.Add(__result, new Marker()); Log.Debug("Terrain RPC received: Super Flat radius=" + num); } catch (Exception ex) { __result = null; Log.Error("Super Flat RPC rejected: " + ex.Message); } } [HarmonyPostfix] [HarmonyPatch(typeof(TerrainComp), "ApplyOperation")] private static void Sent(TerrainOp modifier, ZNetView ___m_nview, Heightmap ___m_hmap) { if (Object.op_Implicit((Object)(object)modifier) && TerrainMenu.IsSuperFlat(((Component)modifier).gameObject)) { Log.Debug("Terrain RPC sent: RPC_ApplyOperation; Heightmap=" + Object.op_Implicit((Object)(object)___m_hmap) + "; TerrainComp/ZDO valid=" + (Object.op_Implicit((Object)(object)___m_nview) && ___m_nview.IsValid()) + "; local owner=" + (Object.op_Implicit((Object)(object)___m_nview) && ___m_nview.IsOwner())); } } } internal static class SuperFlatPreview { internal static void Configure(GameObject prefab) { Transform val = prefab.transform.Find("_GhostOnly"); if (!Object.op_Implicit((Object)(object)val)) { Log.Error("Super Flat is missing its native _GhostOnly preview."); } else if (!Object.op_Implicit((Object)(object)((Component)val).GetComponent<NativeHoeRingPreview>())) { ((Component)val).gameObject.AddComponent<NativeHoeRingPreview>(); } } } internal sealed class NativeHoeRingPreview : MonoBehaviour { private sealed class Ring { internal ParticleSystem System; internal Particle[] Particles; } private Ring[] rings; private Piece piece; private float previousRadius = -1f; private void LateUpdate() { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)piece)) { piece = ((Component)this).GetComponentInParent<Piece>(); } if (!Object.op_Implicit((Object)(object)piece) || (!TerrainMenu.IsSuperFlat(((Component)piece).gameObject) && !RestoreTerrainAction.IsRestore(((Component)piece).gameObject)) || !Player.IsPlacementGhost(((Component)piece).gameObject)) { return; } if (rings == null) { InitializeRings(); } float effectiveRadius = TerrainBrush.EffectiveRadius; float num = PreviewRadiusMath.Diameter(effectiveRadius); Ring[] array = rings; foreach (Ring ring in array) { ParticleSystem system = ring.System; if (Object.op_Implicit((Object)(object)system) && ((Component)system).gameObject.activeInHierarchy) { MainModule main = system.main; ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(num); if (!system.isPlaying) { system.Play(false); } int particles = system.GetParticles(ring.Particles); if (particles == 0) { system.Emit(1); particles = system.GetParticles(ring.Particles); } for (int j = 0; j < particles; j++) { ((Particle)(ref ring.Particles[j])).startSize = num; ((Particle)(ref ring.Particles[j])).position = Vector3.zero; ((Particle)(ref ring.Particles[j])).velocity = Vector3.zero; } system.SetParticles(ring.Particles, particles); } } if (effectiveRadius != previousRadius) { Log.Debug("Native particle preview: radius=" + effectiveRadius + "m; diameter=" + num + "m; ring systems=" + rings.Length); previousRadius = effectiveRadius; } } private void InitializeRings() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Invalid comparison between Unknown and I4 //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_0044: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Invalid comparison between Unknown and I4 //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013d: 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) List<Ring> list = new List<Ring>(); ParticleSystem[] componentsInChildren = ((Component)this).GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem val in componentsInChildren) { ParticleSystemRenderer component = ((Component)val).GetComponent<ParticleSystemRenderer>(); if (Object.op_Implicit((Object)(object)component) && (int)component.renderMode == 2) { MainModule main = val.main; Vector3 val2 = (((int)((MainModule)(ref main)).scalingMode == 0) ? ((Component)val).transform.lossyScale : ((Component)val).transform.localScale); MinMaxCurve startSize = ((MainModule)(ref main)).startSize; float num = ((MinMaxCurve)(ref startSize)).constantMax * (((int)((MainModule)(ref main)).scalingMode == 2) ? 1f : Mathf.Abs(val2.x)); string[] obj = new string[6] { "Measured native ring ", ((Object)val).name, ": full-size world radius=", (num * 0.5f).ToString(), "m; texture=", null }; Material sharedMaterial = ((Renderer)component).sharedMaterial; object obj2; if (sharedMaterial == null) { obj2 = null; } else { Texture mainTexture = sharedMaterial.mainTexture; obj2 = ((mainTexture != null) ? ((Object)mainTexture).name : null); } obj[5] = (string)obj2; Log.Debug(string.Concat(obj)); val.Stop(false, (ParticleSystemStopBehavior)0); ((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)2; ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)0; ((MainModule)(ref main)).startSize3D = false; ShapeModule shape = val.shape; ((ShapeModule)(ref shape)).enabled = false; SizeOverLifetimeModule sizeOverLifetime = val.sizeOverLifetime; ((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled = false; SizeBySpeedModule sizeBySpeed = val.sizeBySpeed; ((SizeBySpeedModule)(ref sizeBySpeed)).enabled = false; list.Add(new Ring { System = val, Particles = (Particle[])(object)new Particle[Math.Max(1, ((MainModule)(ref main)).maxParticles)] }); } } rings = list.ToArray(); if (rings.Length == 0) { Log.Error("Super Flat native preview has no horizontal particle ring."); } } } [HarmonyPatch] internal static class SuperFlatTerrain { private sealed class State { internal bool Capture; internal float[] Baseline; internal bool[] Mask; } private static readonly int MaskKey = StringExtensionMethods.GetStableHashCode("esvk.terrainadjuster.flatmask.v1"); private static readonly ConditionalWeakTable<TerrainComp, State> states = new ConditionalWeakTable<TerrainComp, State>(); [HarmonyPrefix] [HarmonyPatch(typeof(TerrainComp), "ApplyToHeightmap")] private static void BeforeRebuild(TerrainComp __instance, List<float> heights, ZNetView ___m_nview, bool ___m_initialized, out float[] __state) { __state = null; if (___m_initialized && Object.op_Implicit((Object)(object)___m_nview) && ___m_nview.IsValid()) { State value = states.GetValue(__instance, (TerrainComp _) => new State()); try { value.Mask = FlatGrid.Decode(___m_nview.GetZDO().GetByteArray(MaskKey, (byte[])null), heights.Count); } catch (Exception ex) { value.Mask = null; Log.Error("Cannot read persistent Super Flat mask: " + ex.Message); } if (value.Capture || value.Mask != null) { value.Baseline = heights.ToArray(); } if (value.Mask != null) { __state = value.Baseline; } } } [HarmonyPostfix] [HarmonyPatch(typeof(TerrainComp), "ApplyToHeightmap")] private static void AfterRebuild(TerrainComp __instance, List<float> heights, float[] ___m_levelDelta, float[] ___m_smoothDelta, float[] __state) { if (__state == null || !states.TryGetValue(__instance, out var value) || value.Mask == null) { return; } for (int i = 0; i < heights.Count; i++) { if (value.Mask[i]) { heights[i] = __state[i] + ___m_levelDelta[i] + ___m_smoothDelta[i]; } } } [HarmonyPrefix] [HarmonyPatch(typeof(TerrainComp), "InternalDoOperation")] private unsafe static bool Apply(TerrainComp __instance, Vector3 pos, Settings modifier, Heightmap ___m_hmap, ZNetView ___m_nview, float[] ___m_levelDelta, float[] ___m_smoothDelta, bool[] ___m_modifiedHeight, ref int ___m_operations, ref Vector3 ___m_lastOpPoint, ref float ___m_lastOpRadius) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: 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) //IL_0108: 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_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) if (!SuperFlatNetworking.IsReceived(modifier)) { return true; } if (!Object.op_Implicit((Object)(object)___m_hmap) || !Object.op_Implicit((Object)(object)___m_nview) || !___m_nview.IsValid() || !___m_nview.IsOwner() || !FlatGrid.Finite(pos.x) || !FlatGrid.Finite(pos.y) || !FlatGrid.Finite(pos.z)) { Log.Error("Super Flat rejected: missing Heightmap/owned ZDO or invalid target."); return false; } State value = states.GetValue(__instance, (TerrainComp _) => new State()); try { value.Capture = true; value.Baseline = null; ___m_hmap.Poke(0, false); if (value.Baseline == null) { throw new InvalidOperationException("Terrain compiler baseline was not rebuilt."); } if (value.Mask == null) { value.Mask = new bool[___m_levelDelta.Length]; } Vector3 position = ((Component)___m_hmap).transform.position; float num = (float)___m_hmap.m_width * ___m_hmap.m_scale * 0.5f; int num2 = FlatGrid.Apply(___m_hmap.m_width, ___m_hmap.m_scale, position.x - num, position.z - num, pos.x, pos.z, pos.y - position.y, modifier.m_levelRadius, value.Baseline, ___m_levelDelta, ___m_smoothDelta, ___m_modifiedHeight, value.Mask); ___m_nview.GetZDO().Set(MaskKey, FlatGrid.Encode(value.Mask)); ___m_operations++; ___m_lastOpPoint = pos; ___m_lastOpRadius = modifier.m_levelRadius; string[] obj = new string[8] { "Terrain operation applied on owning peer: vertices=", num2.ToString(), "; Heightmap=", null, null, null, null, null }; Vector3 val = position; obj[3] = ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString(); obj[4] = "; target height="; obj[5] = pos.y.ToString(); obj[6] = "; radius="; obj[7] = modifier.m_levelRadius.ToString(); Log.Debug(string.Concat(obj)); } catch (Exception ex) { Log.Error("Super Flat operation failed: " + ex); } finally { value.Capture = false; } return false; } [HarmonyPostfix] [HarmonyPatch(typeof(TerrainComp), "DoOperation")] private static void Saved(Settings modifier, ZNetView ___m_nview) { if (SuperFlatNetworking.IsReceived(modifier)) { Log.Debug("Super Flat native save/refresh returned; ZDO revision=" + ___m_nview.GetZDO().DataRevision); } } } [HarmonyPatch] internal static class TerrainBrush { private static bool wasEquipped; private static bool wasSuperFlat; private static int updatedFrame = -1; internal static float Radius { get; private set; } internal static float EffectiveRadius => RadiusMath.Clamp(Radius, ModConfig.MinimumRadius.Value, ModConfig.MaximumRadius.Value); internal static void Reset() { Radius = ModConfig.DefaultRadius.Value; } internal static bool CanAdjust() { Player localPlayer = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)localPlayer) && !((Character)localPlayer).IsDead() && TerrainTool.IsEquipped(localPlayer) && !Console.IsVisible() && (!Object.op_Implicit((Object)(object)Chat.instance) || !Chat.instance.HasFocus()) && !InventoryGui.IsVisible() && !Menu.IsVisible() && !Minimap.IsOpen() && !TextInput.IsVisible()) { return !Hud.IsPieceSelectionVisible(); } return false; } internal static bool ModifierHeld() { if (!ZInput.GetKey((KeyCode)306, false)) { return ZInput.GetKey((KeyCode)305, false); } return true; } internal static void Update() { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) if (updatedFrame == Time.frameCount) { return; } updatedFrame = Time.frameCount; Radius = EffectiveRadius; bool num = TerrainTool.IsEquipped(Player.m_localPlayer); if (num && !wasEquipped) { RadiusDisplay.Show(Radius); } wasEquipped = num; Piece val = (num ? Player.m_localPlayer.GetSelectedPiece() : null); int num2; if (Object.op_Implicit((Object)(object)val)) { num2 = (TerrainMenu.IsSuperFlat(((Component)val).gameObject) ? 1 : 0); if (num2 != 0 && !wasSuperFlat) { Log.Debug("Super Flat selected"); } } else { num2 = 0; } wasSuperFlat = (byte)num2 != 0; if (CanAdjust() && ModifierHeld() && Mouse.current != null) { float y = ((InputControl<Vector2>)(object)Mouse.current.scroll).ReadValue().y; if (y != 0f) { Radius = RadiusMath.Clamp(Radius + Mathf.Sign(y) * 1f, ModConfig.MinimumRadius.Value, ModConfig.MaximumRadius.Value); RadiusDisplay.Show(Radius); } } } [HarmonyPrefix] [HarmonyPatch(typeof(ZInput), "GetMouseScrollWheel")] private static bool ReserveWheel(ref float __result) { if (!CanAdjust() || !ModifierHeld()) { return true; } __result = 0f; return false; } } } namespace ESvK.TerrainAdjuster.Config { internal static class ModConfig { internal static ConfigEntry<bool> UseStamina; internal static ConfigEntry<bool> UseDurability; internal static ConfigEntry<bool> RequiresResources; internal static ConfigEntry<bool> RequireWorkbench; internal static ConfigEntry<bool> DebugLogging; internal static ConfigEntry<bool> EnableEquippedSpeedBoost; internal static ConfigEntry<float> MinimumRadius; internal static ConfigEntry<float> MaximumRadius; internal static ConfigEntry<float> DefaultRadius; internal static ConfigEntry<float> EquippedSpeedMultiplier; internal static void Initialize(ConfigFile config) { UseStamina = ConfigFileExtensions.BindConfig<bool>(config, "General", "UseStamina", false, "Use vanilla Hoe action stamina costs on the ESvK tool only.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); UseDurability = ConfigFileExtensions.BindConfig<bool>(config, "General", "UseDurability", false, "Enable ESvK tool durability.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); RequiresResources = ConfigFileExtensions.BindConfig<bool>(config, "SuperFlat", "RequiresResources", false, "Require two Stone per Super Flat action when enabled. Normal Hoe entries keep their native costs.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); RequireWorkbench = ConfigFileExtensions.BindConfig<bool>(config, "SuperFlat", "RequireWorkbench", false, "Require a workbench for Super Flat when enabled.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); AcceptableValueBase val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f); MinimumRadius = ConfigFileExtensions.BindConfig<float>(config, "SuperFlat", "MinimumRadius", 1f, "Minimum radius in metres.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f); MaximumRadius = ConfigFileExtensions.BindConfig<float>(config, "SuperFlat", "MaximumRadius", 20f, "Maximum radius; minimum wins if the range is reversed.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f); DefaultRadius = ConfigFileExtensions.BindConfig<float>(config, "SuperFlat", "DefaultRadius", 5f, "Initial radius, clamped to the allowed range.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); EnableEquippedSpeedBoost = ConfigFileExtensions.BindConfig<bool>(config, "Movement", "EnableEquippedSpeedBoost", true, "Enable movement/sprint boost only while holding the ESvK tool.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3f); EquippedSpeedMultiplier = ConfigFileExtensions.BindConfig<float>(config, "Movement", "EquippedSpeedMultiplier", 1.35f, "1.35 means +35% speed. Does not change sprint stamina.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); DebugLogging = ConfigFileExtensions.BindConfig<bool>(config, "Debug", "DebugLogging", false, "Local diagnostic logging.", false, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); } } }