Please disclose if your mod was created primarily 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 TerrainTools v1.1.0
TerrainTools.dll
Decompiled 2 years agousing System; using System.CodeDom.Compiler; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Managers; using Jotunn.Utils; using TerrainTools.Configs; using TerrainTools.Extensions; using TerrainTools.Helpers; using TerrainTools.Properties; using TerrainTools.Visualization; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("TerrainTools")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("TerrainTools")] [assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("1.1.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.0.0")] [module: UnverifiableCode] namespace TerrainTools { [BepInPlugin("Searica.Valheim.TerrainTools", "TerrainTools", "1.1.0")] [BepInDependency("com.jotunn.jotunn", "2.14.6")] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal class TerrainTools : BaseUnityPlugin { internal const string Author = "Searica"; public const string PluginName = "TerrainTools"; public const string PluginGUID = "Searica.Valheim.TerrainTools"; public const string PluginVersion = "1.1.0"; private static readonly string MainSection = ConfigManager.SetStringPriority("Global", 3); private static readonly string RadiusSection = ConfigManager.SetStringPriority("Radius", 2); private static readonly string HardnessSection = ConfigManager.SetStringPriority("Hardness", 1); private static readonly string ToolsSection = ConfigManager.SetStringPriority("Tools", 0); private static ConfigEntry<bool> hoverInfoEnabled; private static readonly Dictionary<string, ConfigEntry<bool>> ToolConfigEntries = new Dictionary<string, ConfigEntry<bool>>(); private static bool UpdateTools = false; private static ConfigEntry<bool> enableRadiusModifier; private static ConfigEntry<KeyCode> radiusModKey; private static ConfigEntry<float> radiusScrollScale; private static ConfigEntry<float> maxRadius; private static ConfigEntry<bool> enableHardnessModifier; private static ConfigEntry<KeyCode> hardnessModKey; private static ConfigEntry<float> hardnessScrollScale; internal static bool IsHoverInforEnabled => hoverInfoEnabled.Value; internal static bool IsEnableRadiusModifier => enableRadiusModifier.Value; internal static float MaxRadius => maxRadius.Value; internal static KeyCode RadiusKey => radiusModKey.Value; internal static float RadiusScrollScale => radiusScrollScale.Value; internal static bool IsEnableHardnessModifier => enableHardnessModifier.Value; internal static KeyCode HardnessKey => hardnessModKey.Value; internal static float HardnessScrollScale => hardnessScrollScale.Value; internal static Sprite LoadEmbeddedTextureAsSprite(string fileName) { //IL_0042: 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) Texture2D val = LoadTextureFromResources(fileName); if ((Object)(object)val == (Object)null) { return null; } Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0.5f, 0.5f); float num = 100f; return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), val2, num); } internal static Texture2D LoadTextureFromResources(string fileName) { //IL_0080: 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_008c: Expected O, but got Unknown //IL_008f: Expected O, but got Unknown string text = Path.GetExtension(fileName).ToLower(); if (text != ".png" && text != ".jpg") { Log.LogWarning("LoadTextureFromResources can only load png or jpg textures"); return null; } fileName = Path.GetFileNameWithoutExtension(fileName); object? @object = Resources.ResourceManager.GetObject(fileName); Bitmap val = (Bitmap)((@object is Bitmap) ? @object : null); using MemoryStream memoryStream = new MemoryStream(); ((Image)val).Save((Stream)memoryStream, ImageFormat.Png); byte[] array = new byte[memoryStream.Length]; memoryStream.Position = 0L; memoryStream.Read(array, 0, array.Length); Texture2D val2 = new Texture2D(0, 0); ImageConversion.LoadImage(val2, array); return val2; } internal static bool IsToolEnabled(string toolName) { if (ToolConfigEntries.TryGetValue(toolName, out var value) && value != null) { return value.Value; } return false; } public void Awake() { Log.Init(((BaseUnityPlugin)this).Logger); ConfigManager.Init("Searica.Valheim.TerrainTools", ((BaseUnityPlugin)this).Config); SetUpConfigEntries(); Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "Searica.Valheim.TerrainTools"); Game.isModded = true; PieceManager.OnPiecesRegistered += InitManager.InitToolPieces; _ = GUIManager.Instance; ConfigManager.SetupWatcher(); ConfigManager.CheckForConfigManager(); ConfigManager.OnConfigFileReloaded += delegate { if (UpdateTools) { InitManager.UpdatePlugin(); UpdateTools = false; } }; ConfigManager.OnConfigWindowClosed += delegate { if (UpdateTools) { InitManager.UpdatePlugin(); ConfigManager.Save(); UpdateTools = false; } }; SynchronizationManager.OnConfigurationSynchronized += delegate { if (UpdateTools) { InitManager.UpdatePlugin(); ConfigManager.Save(); UpdateTools = false; } }; } public void OnDestroy() { ConfigManager.Save(); } internal static void SetUpConfigEntries() { Log.Verbosity = ConfigManager.BindConfig(MainSection, "Verbosity", LogLevel.Low, "Low will log basic information about the mod. Medium will log information that is useful for troubleshooting. High will log a lot of information, do not set it to this without good reason as it will slow Down your game.", null, synced: false); enableRadiusModifier = ConfigManager.BindConfig(RadiusSection, ConfigManager.SetStringPriority("RadiusModifier", 1), value: true, "Set to true/enabled to allow modifying the radius of terrain tools using the scroll wheel. Note: Radius cannot be changed on square terraforming tools."); radiusModKey = ConfigManager.BindConfig<KeyCode>(RadiusSection, "RadiusModKey", (KeyCode)308, "Modifier key that must be held down when using scroll wheel to change the radius of terrain tools."); radiusScrollScale = ConfigManager.BindConfig(RadiusSection, "RadiusScrollScale", 0.1f, "Scroll wheel change scale", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 2f)); maxRadius = ConfigManager.BindConfig(RadiusSection, "MaxRadius", 10f, "Maximum radius of terrain tools.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(4f, 20f)); enableHardnessModifier = ConfigManager.BindConfig(HardnessSection, ConfigManager.SetStringPriority("HardnessModifier", 1), value: true, "Set to true/enabled to allow modifying the hardness of terrain tools using the scroll wheel. Note: Hardness cannot be changed on square terraforming tools and tools that do not alter ground height do not have a hardness."); hardnessModKey = ConfigManager.BindConfig<KeyCode>(HardnessSection, "HardnessModKey", (KeyCode)306, "Modifier key that must be held down when using scroll wheel to change the hardness of terrain tools."); hardnessScrollScale = ConfigManager.BindConfig(HardnessSection, "HardnessScrollScale", 0.1f, "Scroll wheel change scale", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 2f)); hoverInfoEnabled = ConfigManager.BindConfig(ToolsSection, ConfigManager.SetStringPriority("HoverInfo", 1), value: true, "Set to true/enabled to show terrain height when using square terrain tools."); foreach (string key in ToolConfigs.ToolConfigsMap.Keys) { ConfigEntry<bool> val = ConfigManager.BindConfig(ToolsSection, key, value: true, "Set to true/enabled to add this terrain tool. Set to false/disabled to remove it."); val.SettingChanged += delegate { UpdateTools = !UpdateTools || UpdateTools; }; ToolConfigEntries.Add(key, val); } ConfigManager.Save(); } } internal enum LogLevel { Low, Medium, High } internal static class Log { internal static ManualLogSource _logSource; internal static ConfigEntry<LogLevel> Verbosity { get; set; } internal static LogLevel VerbosityLevel => Verbosity.Value; internal static void Init(ManualLogSource logSource) { _logSource = logSource; } internal static void LogDebug(object data) { _logSource.LogDebug(data); } internal static void LogError(object data) { _logSource.LogError(data); } internal static void LogFatal(object data) { _logSource.LogFatal(data); } internal static void LogMessage(object data) { _logSource.LogMessage(data); } internal static void LogWarning(object data) { _logSource.LogWarning(data); } internal static void LogInfo(object data, LogLevel level = LogLevel.Low) { if (Verbosity == null || VerbosityLevel >= level) { _logSource.LogInfo(data); } } internal static void LogGameObject(GameObject prefab, bool includeChildren = false) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown LogInfo("***** " + ((Object)prefab).name + " *****"); Component[] components = prefab.GetComponents<Component>(); for (int i = 0; i < components.Length; i++) { LogComponent(components[i]); } if (!includeChildren) { return; } LogInfo("***** " + ((Object)prefab).name + " (children) *****"); foreach (Transform item in prefab.transform) { Transform val = item; LogInfo(" - " + ((Object)((Component)val).gameObject).name); components = ((Component)val).gameObject.GetComponents<Component>(); for (int i = 0; i < components.Length; i++) { LogComponent(components[i]); } } } internal static void LogComponent(Component compo) { LogInfo("--- " + ((object)compo).GetType().Name + ": " + ((Object)compo).name + " ---"); PropertyInfo[] properties = ((object)compo).GetType().GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty); foreach (PropertyInfo propertyInfo in properties) { LogInfo($" - {propertyInfo.Name} = {propertyInfo.GetValue(compo)}"); } FieldInfo[] fields = ((object)compo).GetType().GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty); foreach (FieldInfo fieldInfo in fields) { LogInfo($" - {fieldInfo.Name} = {fieldInfo.GetValue(compo)}"); } } } } namespace TerrainTools.Visualization { public class HoverInfo { private readonly GameObject _gameObject; private readonly Transform _transform; private readonly TextMesh _textMesh; public string Text { get { return _textMesh.text; } set { _textMesh.text = value; } } public bool Enabled { get { return _gameObject.activeSelf; } set { _gameObject.SetActive(value); } } public Color Color { get { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return _textMesh.color; } set { //IL_0006: Unknown result type (might be due to invalid IL or missing references) _textMesh.color = value; } } public HoverInfo(Transform parentTransform) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: 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) _gameObject = new GameObject(); _gameObject.transform.parent = parentTransform; _transform = _gameObject.transform; _textMesh = _gameObject.AddComponent<TextMesh>(); ((Component)_textMesh).transform.localPosition = Vector3.zero; ((Component)_textMesh).transform.localScale = new Vector3(0.1f / parentTransform.localScale.x, 0.1f / parentTransform.localScale.y, 0.1f / parentTransform.localScale.z); _textMesh.anchor = (TextAnchor)4; _textMesh.alignment = (TextAlignment)1; _textMesh.fontSize = 16; } public void RotateToPlayer() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(((Component)GameCamera.m_instance).transform.position.x, _transform.position.y, ((Component)GameCamera.m_instance).transform.position.z); _transform.LookAt(val, Vector3.up); _transform.Rotate(90f, 180f, 0f); } } internal class IconCache { private static Texture2D _remove; private static Texture2D _cross; private static Texture2D _undo; private static Texture2D _redo; private static Texture2D _box; private static Texture2D _pavedRoadSquare; private static Texture2D _pavedRoadPath; private static Texture2D _pavedRoadPathSquare; private static Texture2D _mudRoadSquare; private static Texture2D _mudRoadPathSquare; private static Texture2D _replantSquare; private static Texture2D _cultivateSquare; private static Texture2D _cultivatePath; private static Texture2D _cultivatePathSquare; private static Texture2D _raiseSquare; internal static Texture2D CultivateSquare { get { if ((Object)(object)_cultivateSquare == (Object)null) { _cultivateSquare = TerrainTools.LoadTextureFromResources("cultivate_v2_square.png"); } return _cultivateSquare; } } internal static Texture2D CultivatePathSquare { get { if ((Object)(object)_cultivatePathSquare == (Object)null) { _cultivatePathSquare = TerrainTools.LoadTextureFromResources("cultivate_v2_path_square.png"); } return _cultivatePathSquare; } } internal static Texture2D CultivatePath { get { if ((Object)(object)_cultivatePath == (Object)null) { _cultivatePath = TerrainTools.LoadTextureFromResources("cultivate_v2_path.png"); } return _cultivatePath; } } internal static Texture2D ReplantSquare { get { if ((Object)(object)_replantSquare == (Object)null) { _replantSquare = TerrainTools.LoadTextureFromResources("replant_v2_square.png"); } return _replantSquare; } } internal static Texture2D RaiseSquare { get { if ((Object)(object)_raiseSquare == (Object)null) { _raiseSquare = TerrainTools.LoadTextureFromResources("raise_v2_square.png"); } return _raiseSquare; } } internal static Texture2D MudRoadPathSquare { get { if ((Object)(object)_mudRoadPathSquare == (Object)null) { _mudRoadPathSquare = TerrainTools.LoadTextureFromResources("path_v2_square.png"); } return _mudRoadPathSquare; } } internal static Texture2D MudRoadSquare { get { if ((Object)(object)_mudRoadSquare == (Object)null) { _mudRoadSquare = TerrainTools.LoadTextureFromResources("mud_road_v2_square.png"); } return _mudRoadSquare; } } internal static Texture2D PavedRoadPath { get { if ((Object)(object)_pavedRoadPath == (Object)null) { _pavedRoadPath = TerrainTools.LoadTextureFromResources("paved_road_v2_path.png"); } return _pavedRoadPath; } } internal static Texture2D PavedRoadPathSquare { get { if ((Object)(object)_pavedRoadPathSquare == (Object)null) { _pavedRoadPathSquare = TerrainTools.LoadTextureFromResources("paved_road_v2_path_square.png"); } return _pavedRoadPathSquare; } } internal static Texture2D PavedRoadSquare { get { if ((Object)(object)_pavedRoadSquare == (Object)null) { _pavedRoadSquare = TerrainTools.LoadTextureFromResources("paved_road_v2_square.png"); } return _pavedRoadSquare; } } internal static Texture2D Remove { get { if ((Object)(object)_remove == (Object)null) { _remove = TerrainTools.LoadTextureFromResources("remove.png"); } return _remove; } } internal static Texture2D Cross { get { if ((Object)(object)_cross == (Object)null) { _cross = TerrainTools.LoadTextureFromResources("cross.png"); } return _cross; } } internal static Texture2D Undo { get { if ((Object)(object)_undo == (Object)null) { _undo = TerrainTools.LoadTextureFromResources("undo.png"); } return _undo; } } internal static Texture2D Redo { get { if ((Object)(object)_redo == (Object)null) { _redo = TerrainTools.LoadTextureFromResources("redo.png"); } return _redo; } } internal static Texture2D Box { get { if ((Object)(object)_box == (Object)null) { _box = TerrainTools.LoadTextureFromResources("box.png"); } return _box; } } } public class Overlay { private GameObject GameObject { get; } private Particle[] Particles => (Particle[])(object)new Particle[2]; private Transform Transform { get; } public ParticleSystem ps { get; } public ParticleSystemRenderer psr { get; } public MainModule psm { get; } public bool Enabled { get { return GameObject.activeSelf; } set { GameObject.SetActive(value); } } public Vector3 Position { get { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return Transform.position; } set { //IL_0006: Unknown result type (might be due to invalid IL or missing references) Transform.position = value; } } public Vector3 LocalPosition { get { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return Transform.localPosition; } set { //IL_0006: Unknown result type (might be due to invalid IL or missing references) Transform.localPosition = value; } } public Quaternion Rotation { get { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return Transform.rotation; } set { //IL_0006: Unknown result type (might be due to invalid IL or missing references) Transform.rotation = value; } } public Color Color { get { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) ps.GetParticles(Particles, 2); return Color32.op_Implicit(((Particle)(ref Particles[1])).GetCurrentColor(ps)); } } public Color StartColor { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) MainModule val = psm; MinMaxGradient startColor = ((MainModule)(ref val)).startColor; return ((MinMaxGradient)(ref startColor)).color; } set { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) MainModule val = psm; MinMaxGradient startColor = ((MainModule)(ref val)).startColor; ((MinMaxGradient)(ref startColor)).color = value; } } public float StartSize { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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) MainModule val = psm; MinMaxCurve startSize = ((MainModule)(ref val)).startSize; return ((MinMaxCurve)(ref startSize)).constant; } set { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) MainModule main = ps.main; ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(value); } } public float StartSpeed { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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) MainModule val = psm; MinMaxCurve startSize = ((MainModule)(ref val)).startSize; return ((MinMaxCurve)(ref startSize)).constant; } set { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) MainModule main = ps.main; ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(value); } } public float StartLifetime { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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) MainModule val = psm; MinMaxCurve startLifetime = ((MainModule)(ref val)).startLifetime; return ((MinMaxCurve)(ref startLifetime)).constant; } set { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) MainModule main = ps.main; ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(value); } } public bool SizeOverLifetimeEnabled { get { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) SizeOverLifetimeModule sizeOverLifetime = ps.sizeOverLifetime; return ((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled; } set { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) SizeOverLifetimeModule sizeOverLifetime = ps.sizeOverLifetime; ((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled = value; } } public MinMaxCurve SizeOverLifetime { get { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) SizeOverLifetimeModule sizeOverLifetime = ps.sizeOverLifetime; return ((SizeOverLifetimeModule)(ref sizeOverLifetime)).size; } set { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) SizeOverLifetimeModule sizeOverLifetime = ps.sizeOverLifetime; ((SizeOverLifetimeModule)(ref sizeOverLifetime)).size = value; } } public Overlay(Transform transform) { Transform = transform; GameObject = ((Component)transform).gameObject; ps = ((Component)transform).GetComponentInChildren<ParticleSystem>(); psr = ((Component)transform).GetComponentInChildren<ParticleSystemRenderer>(); } } public abstract class OverlayVisualizer : MonoBehaviour { protected Overlay primary; protected Overlay secondary; protected Overlay tertiary; protected HoverInfo hoverInfo; internal static readonly Vector3 VerticalOffset = new Vector3(0f, 0.075f, 0f); private void Update() { //IL_007b: Unknown result type (might be due to invalid IL or missing references) if (primary == null) { Transform val = ((Component)this).transform.Find("_GhostOnly"); Transform val2 = Object.Instantiate<Transform>(val, ((Component)this).transform); Transform transform = Object.Instantiate<Transform>(val2, ((Component)this).transform); primary = new Overlay(val); secondary = new Overlay(val2); tertiary = new Overlay(transform); hoverInfo = new HoverInfo(val2); tertiary.StartColor = new Color(255f, 255f, 255f); primary.Enabled = false; secondary.Enabled = false; tertiary.Enabled = false; Initialize(); } OnRefresh(); } protected abstract void Initialize(); protected abstract void OnRefresh(); protected void SpeedUp(Overlay overlay) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) AnimationCurve val = new AnimationCurve(); val.AddKey(0f, 0f); val.AddKey(0.5f, 1f); MinMaxCurve sizeOverLifetime = default(MinMaxCurve); ((MinMaxCurve)(ref sizeOverLifetime))..ctor(1f, val); overlay.StartLifetime = 2f; overlay.SizeOverLifetime = sizeOverLifetime; } protected void Freeze(Overlay overlay) { overlay.StartSpeed = 0f; overlay.SizeOverLifetimeEnabled = false; } protected void VisualizeTerraformingBounds(Overlay overlay) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) overlay.StartSize = 3f; ((Renderer)overlay.psr).material.mainTexture = (Texture)(object)IconCache.Box; overlay.LocalPosition = VerticalOffset; } protected void VisualizeIconInsideTerraformingBounds(Overlay overlay, Texture iconTexture) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) overlay.StartSize = 2.5f; ((Renderer)overlay.psr).material.mainTexture = iconTexture; overlay.LocalPosition = VerticalOffset; } protected void VisualizeRecoloringBounds(Overlay overlay) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) overlay.StartSize = 4f; ((Renderer)overlay.psr).material.mainTexture = (Texture)(object)IconCache.Box; overlay.LocalPosition = VerticalOffset; } protected void VisualizeIconInsideRecoloringBounds(Overlay overlay, Texture iconTexture) { //IL_0023: 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_002d: Unknown result type (might be due to invalid IL or missing references) overlay.StartSize = 3f; ((Renderer)overlay.psr).material.mainTexture = iconTexture; overlay.Position = ((Component)this).transform.position + VerticalOffset; } } public abstract class HoverInfoEnabled : OverlayVisualizer { protected override void Initialize() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) hoverInfo.Color = secondary.StartColor; } protected override void OnRefresh() { //IL_002e: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_005f: Unknown result type (might be due to invalid IL or missing references) hoverInfo.Enabled = TerrainTools.IsHoverInforEnabled; if (hoverInfo.Enabled) { hoverInfo.RotateToPlayer(); Vector3 val = secondary.Position - OverlayVisualizer.VerticalOffset; hoverInfo.Text = $"x: {val.x:0}, y: {val.y:0.000}, z: {val.z:0}"; } } } [HarmonyPatch(typeof(Piece), "SetInvalidPlacementHeightlight")] public static class OverlayVisualizationRedshiftHeigthlightBlocker { private static bool Prefix(Piece __instance) { return (Object)(object)((Component)__instance).GetComponentInChildren<OverlayVisualizer>() == (Object)null; } } public class LevelGroundOverlayVisualizer : HoverInfoEnabled { protected override void Initialize() { base.Initialize(); SpeedUp(secondary); VisualizeTerraformingBounds(secondary); } protected override void OnRefresh() { base.OnRefresh(); primary.Enabled = false; secondary.Enabled = true; } } public class RaiseGroundOverlayVisualizer : HoverInfoEnabled { protected override void Initialize() { base.Initialize(); Freeze(secondary); Freeze(tertiary); VisualizeTerraformingBounds(secondary); VisualizeTerraformingBounds(tertiary); } protected override void OnRefresh() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) base.OnRefresh(); primary.Enabled = true; secondary.Enabled = true; GroundLevelSpinner.Refresh(); secondary.LocalPosition = new Vector3(0f, GroundLevelSpinner.Value, 0f); Vector3 val = secondary.Position - OverlayVisualizer.VerticalOffset; if (GroundLevelSpinner.Value > 0f) { float y = secondary.LocalPosition.y; hoverInfo.Text = $"x: {val.x:0}, y: {val.y - y:0.000}, z: {val.z:0}\n\nh: +{y:0.000}"; } else { hoverInfo.Text = $"x: {val.x:0}, y: {val.y:0.000}, z: {val.z:0}"; } tertiary.Enabled = true; } } public class SquarePathOverlayVisualizer : HoverInfoEnabled { protected override void Initialize() { base.Initialize(); SpeedUp(secondary); VisualizeRecoloringBounds(secondary); } protected override void OnRefresh() { base.OnRefresh(); primary.Enabled = false; secondary.Enabled = true; } } public class CultivateOverlayVisualizer : HoverInfoEnabled { protected override void Initialize() { base.Initialize(); SpeedUp(secondary); VisualizeRecoloringBounds(secondary); } protected override void OnRefresh() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) base.OnRefresh(); primary.Enabled = false; secondary.Enabled = true; hoverInfo.Color = secondary.Color; } } public class SeedGrassOverlayVisualizer : HoverInfoEnabled { protected override void Initialize() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) base.Initialize(); Freeze(secondary); VisualizeRecoloringBounds(secondary); primary.StartSize = 4f; primary.LocalPosition = new Vector3(0f, 2.5f, 0f); } protected override void OnRefresh() { base.OnRefresh(); primary.Enabled = true; secondary.Enabled = true; } } public class RemoveModificationsOverlayVisualizer : OverlayVisualizer { protected override void Initialize() { Freeze(primary); SpeedUp(secondary); VisualizeTerraformingBounds(primary); VisualizeIconInsideTerraformingBounds(secondary, (Texture)(object)IconCache.Cross); } protected override void OnRefresh() { primary.Enabled = true; secondary.Enabled = true; } } public abstract class UndoRedoModificationsOverlayVisualizer : OverlayVisualizer { protected override void Initialize() { Freeze(primary); Freeze(secondary); VisualizeRecoloringBounds(primary); VisualizeIconInsideRecoloringBounds(secondary, (Texture)(object)Icon()); } protected override void OnRefresh() { primary.Enabled = true; secondary.Enabled = true; } protected abstract Texture2D Icon(); } public class UndoModificationsOverlayVisualizer : UndoRedoModificationsOverlayVisualizer { protected override Texture2D Icon() { return IconCache.Undo; } } public class RedoModificationsOverlayVisualizer : UndoRedoModificationsOverlayVisualizer { protected override Texture2D Icon() { return IconCache.Redo; } } } namespace TerrainTools.Properties { [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [DebuggerNonUserCode] [CompilerGenerated] internal class Resources { private static ResourceManager resourceMan; private static CultureInfo resourceCulture; [EditorBrowsable(EditorBrowsableState.Advanced)] internal static ResourceManager ResourceManager { get { if (resourceMan == null) { resourceMan = new ResourceManager("TerrainTools.Properties.Resources", typeof(Resources).Assembly); } return resourceMan; } } [EditorBrowsable(EditorBrowsableState.Advanced)] internal static CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } internal static Bitmap box => (Bitmap)ResourceManager.GetObject("box", resourceCulture); internal static Bitmap cross => (Bitmap)ResourceManager.GetObject("cross", resourceCulture); internal static Bitmap cultivate_v2_path => (Bitmap)ResourceManager.GetObject("cultivate_v2_path", resourceCulture); internal static Bitmap cultivate_v2_path_square => (Bitmap)ResourceManager.GetObject("cultivate_v2_path_square", resourceCulture); internal static Bitmap cultivate_v2_square => (Bitmap)ResourceManager.GetObject("cultivate_v2_square", resourceCulture); internal static Bitmap mud_road_v2_square => (Bitmap)ResourceManager.GetObject("mud_road_v2_square", resourceCulture); internal static Bitmap path_v2_square => (Bitmap)ResourceManager.GetObject("path_v2_square", resourceCulture); internal static Bitmap paved_road_v2_path => (Bitmap)ResourceManager.GetObject("paved_road_v2_path", resourceCulture); internal static Bitmap paved_road_v2_path_square => (Bitmap)ResourceManager.GetObject("paved_road_v2_path_square", resourceCulture); internal static Bitmap paved_road_v2_square => (Bitmap)ResourceManager.GetObject("paved_road_v2_square", resourceCulture); internal static Bitmap raise => (Bitmap)ResourceManager.GetObject("raise", resourceCulture); internal static Bitmap raise_v2_square => (Bitmap)ResourceManager.GetObject("raise_v2_square", resourceCulture); internal static Bitmap redo => (Bitmap)ResourceManager.GetObject("redo", resourceCulture); internal static Bitmap remove => (Bitmap)ResourceManager.GetObject("remove", resourceCulture); internal static Bitmap replant_v2_square => (Bitmap)ResourceManager.GetObject("replant_v2_square", resourceCulture); internal static Bitmap smooth => (Bitmap)ResourceManager.GetObject("smooth", resourceCulture); internal static Bitmap undo => (Bitmap)ResourceManager.GetObject("undo", resourceCulture); internal Resources() { } } } namespace TerrainTools.Patches { [HarmonyPatch(typeof(GameCamera))] internal class GameCameraPatch { [HarmonyTranspiler] [HarmonyPatch("UpdateCamera")] private static IEnumerable<CodeInstruction> UpdateCameraTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.Method(typeof(Player), "CanRotatePiece", (Type[])null, (Type[])null), (string)null) }).SetInstructionAndAdvance(Transpilers.EmitDelegate<Func<Player, bool>>((Func<Player, bool>)UpdateCamera_BlockScroll_Delegate)).InstructionEnumeration(); } private static bool UpdateCamera_BlockScroll_Delegate(Player localPlayer) { Piece val = ((localPlayer != null) ? localPlayer.GetSelectedPiece() : null); if ((Object)(object)((val != null) ? ((Component)val).gameObject : null) != (Object)null && (((Component)val).gameObject.HasComponentInChildren<RaiseGroundOverlayVisualizer>(includeInactive: false) || RadiusModifier.ShouldModifyRadius() || HardnessModifier.ShouldModifyHardness())) { return true; } return localPlayer.CanRotatePiece(); } } [HarmonyPatch(typeof(Player))] internal class RenamedNotice { [HarmonyPostfix] [HarmonyPatch("OnSpawned")] private static void OnSpawned(Player __instance) { //IL_002a: 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_0063: 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) if (!((Object)(object)__instance == (Object)null)) { string text = "This mod has been renamed \"AdvancedTerrainModifiers\"\nPlease download that version instead!"; MessageHud instance = MessageHud.m_instance; instance.m_messageCenterText.text = text; instance._crossFadeTextBuffer.Add(new CrossFadeText { text = instance.m_messageCenterText, alpha = 1f, time = 0f }); instance._crossFadeTextBuffer.Add(new CrossFadeText { text = instance.m_messageCenterText, alpha = 0f, time = 15f }); } } } } namespace TerrainTools.Helpers { public static class GroundLevelSpinner { public const string MouseScrollWheel = "Mouse ScrollWheel"; public const float ScrollPrecision = 0.05f; public const float SuperiorScrollPrecisionMultiplier = 0.2f; public const float MaxSpinner = 1f; public const float MinSpinner = 0f; public static float Value { get; private set; } = 1f; public static void Refresh() { float num = ScrollDelta(); if (num > 0f) { Up(num); } if (num < 0f) { Down(num); } } private static float ScrollDelta() { float num = Input.GetAxis("Mouse ScrollWheel"); if (num != 0f) { num = ((num > 0f) ? 0.05f : (-0.05f)); } return num; } private static void Up(float scrollDelta) { if (Value + scrollDelta > 1f) { Value = 1f; } else { Value = Mathf.Round((Value + scrollDelta) * 100f) / 100f; } } private static void Down(float scrollDelta) { if (Value + scrollDelta < 0f) { Value = 0f; } else { Value = Mathf.Round((Value + scrollDelta) * 100f) / 100f; } } } [HarmonyPatch] internal class HardnessModifier { [HarmonyPatch(typeof(Player))] internal class PlayerPatch { [HarmonyPrefix] [HarmonyPriority(300)] [HarmonyPatch("Update")] private static void UpdatePrefix(Player __instance) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || !((Character)__instance).InPlaceMode() || Hud.IsPieceSelectionVisible()) { if (lastOriginalPower != 0f) { lastOriginalPower = 0f; lastModdedPower = 0f; lastTotalDelta = 0f; SetPower(__instance, 0f); } } else if (ShouldModifyHardness()) { SetPower(__instance, Input.mouseScrollDelta.y * TerrainTools.RadiusScrollScale); } } } [HarmonyPatch(typeof(TerrainOp))] internal class TerrainOpPatch { [HarmonyPrefix] [HarmonyPriority(600)] [HarmonyPatch("Awake")] private static void AwakePrefix(TerrainOp __instance) { if (__instance != null && ((Component)__instance).gameObject != null && !((Component)__instance).gameObject.HasComponent<OverlayVisualizer>()) { if (__instance.m_settings.m_raise) { __instance.m_settings.m_raisePower = ModifyPower(__instance.m_settings.m_raisePower, lastTotalDelta); Log.LogInfo($"Applying raise Power {__instance.m_settings.m_raisePower}", LogLevel.Medium); } if (__instance.m_settings.m_smooth) { __instance.m_settings.m_smoothPower = ModifyPower(__instance.m_settings.m_smoothPower, lastTotalDelta); Log.LogInfo($"Applying smooth Power {__instance.m_settings.m_smoothPower}", LogLevel.Medium); } } } } internal static float lastOriginalPower; internal static float lastModdedPower; internal static float lastTotalDelta; private static float lastDisplayedPower; private const float MinPower = 1f; private const float MaxPower = 30f; internal static bool ShouldModifyHardness() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (TerrainTools.IsEnableHardnessModifier && Input.GetKey(TerrainTools.HardnessKey)) { return Input.mouseScrollDelta.y != 0f; } return false; } private static float ModifyPower(float power, float delta) { return Mathf.Clamp(power + delta, 1f, 30f); } private static void SetPower(Player player, float delta) { Piece selectedPiece = player.GetSelectedPiece(); if (selectedPiece == null || ((Component)selectedPiece).gameObject == null || ((Component)selectedPiece).gameObject.HasComponent<OverlayVisualizer>()) { return; } TerrainOp component = ((Component)selectedPiece).gameObject.GetComponent<TerrainOp>(); if ((Object)(object)component == (Object)null) { return; } Log.LogInfo($"Adjusting Power by {delta}", LogLevel.Medium); float num = 0f; float num2 = ModifyPower(lastModdedPower, delta); lastTotalDelta += delta; if (lastOriginalPower == 0f) { if (component.m_settings.m_raise && num < component.m_settings.m_raisePower) { num = component.m_settings.m_raisePower; num2 = ModifyPower(component.m_settings.m_raisePower, delta); } if (component.m_settings.m_smooth && num < component.m_settings.m_smoothPower) { num = component.m_settings.m_smoothPower; num2 = ModifyPower(component.m_settings.m_smoothPower, delta); } lastOriginalPower = num; } lastModdedPower = num2; if (lastOriginalPower > 0f && Mathf.Abs(lastDisplayedPower - lastModdedPower) >= 1f) { Log.LogInfo($"total delta {lastTotalDelta}", LogLevel.Medium); GameObject placementGhost = player.m_placementGhost; Sprite val = ((placementGhost == null) ? null : placementGhost.GetComponent<Piece>()?.m_icon); if ((Object)(object)val != (Object)null) { lastDisplayedPower = Mathf.Round(num2); ((Character)player).Message((MessageType)2, $"Terrain tool hardness: {lastDisplayedPower}", 0, val); } } } } internal class InitManager { private static bool HasInitialized = false; internal static readonly Dictionary<string, GameObject> ToolRefs = new Dictionary<string, GameObject>(); private static readonly Dictionary<string, List<int>> InsertionIndexes = new Dictionary<string, List<int>> { { PieceTables.Hoe, new List<int>() }, { PieceTables.Cultivator, new List<int>() } }; internal static void InitToolPieces() { if (HasInitialized) { return; } FixVanillaToolDescriptions(); foreach (string key in ToolConfigs.ToolConfigsMap.Keys) { try { ToolDB toolDB = ToolConfigs.ToolConfigsMap[key]; GameObject val = MakeToolPiece(toolDB); RegisterPieceInPieceTable(val, toolDB.pieceTable, null, toolDB.insertIndex); ToolRefs.Add(key, val); } catch { Log.LogWarning("Failed to create: " + key); } } HasInitialized = true; } internal static void FixVanillaToolDescriptions() { SetDescription("mud_road_v2", "Levels ground. (Use shift + click to level ground based on where you are pointing)"); SetDescription("raise_v2", "Raise ground based on player position. (Use shift + click to raise ground based on where you are pointing)"); SetDescription("path_v2", "Creates a dirt path without affecting ground height."); SetDescription("paved_road_v2", "Creates a paved path and levels ground based on player position. (Use shift+click to level ground based on where you are pointing)"); SetDescription("cultivate_v2", "Cultivates ground and levels ground based on player position. (Use shift + click to level ground based on where you are pointing)"); SetDescription("replant_v2", "Replants terrain without affecting ground height."); } private static void SetDescription(string prefabName, string description) { GameObject prefab = PrefabManager.Instance.GetPrefab(prefabName); Piece val = ((prefab != null) ? prefab.GetComponent<Piece>() : null); if ((Object)(object)val != (Object)null) { val.m_description = description; } else { Log.LogWarning("Could not set description for: " + prefabName); } } internal static void UpdatePlugin() { if (!HasInitialized) { return; } ForceUnequipTerrainTools(); foreach (string key in ToolRefs.Keys) { ToolRefs[key].GetComponent<Piece>().m_enabled = TerrainTools.IsToolEnabled(key); } } private static void ForceUnequipTerrainTools() { Player localPlayer = Player.m_localPlayer; if (((localPlayer == null) ? null : ((Humanoid)localPlayer).GetRightItem()?.m_shared.m_name) == "$item_cultivator") { Log.LogWarning("Terrain Tools updated through config change, unequipping cultivator"); ((Humanoid)Player.m_localPlayer).HideHandItems(); } Player localPlayer2 = Player.m_localPlayer; if (((localPlayer2 == null) ? null : ((Humanoid)localPlayer2).GetRightItem()?.m_shared.m_name) == "$item_hoe") { Log.LogWarning("Terrain Tools updated through config change, unequipping hoe"); ((Humanoid)Player.m_localPlayer).HideHandItems(); } } internal static GameObject MakeToolPiece(ToolDB toolDB) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (PieceManager.Instance.GetPiece(toolDB.pieceName) != null) { return null; } GameObject val = PrefabManager.Instance.CreateClonedPrefab(toolDB.name, toolDB.basePrefab); if (toolDB == null) { return null; } Piece component = val.GetComponent<Piece>(); component.m_icon = Sprite.Create(toolDB.icon, new Rect(0f, 0f, (float)((Texture)toolDB.icon).width, (float)((Texture)toolDB.icon).height), Vector2.zero); component.m_name = toolDB.pieceName; component.m_description = toolDB.pieceDesc; Settings settings = val.GetComponent<TerrainOp>().m_settings; settings.m_level = (toolDB.level.HasValue ? toolDB.level.Value : settings.m_level); settings.m_raise = (toolDB.raise.HasValue ? toolDB.raise.Value : settings.m_raise); settings.m_smooth = (toolDB.smooth.HasValue ? toolDB.smooth.Value : settings.m_smooth); settings.m_paintCleared = (toolDB.clearPaint.HasValue ? toolDB.clearPaint.Value : settings.m_paintCleared); if (toolDB.overlayType != null) { val.AddComponent(toolDB.overlayType); } return val; } private static void RegisterPieceInPieceTable(GameObject prefab, string pieceTable, string category, int position = -1) { //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) Piece component = prefab.GetComponent<Piece>(); if ((Object)(object)component == (Object)null) { throw new Exception("Prefab " + ((Object)prefab).name + " has no Piece component attached"); } PieceTable pieceTable2 = PieceManager.Instance.GetPieceTable(pieceTable); if ((Object)(object)pieceTable2 == (Object)null) { throw new Exception("Could not find PieceTable " + pieceTable); } if (pieceTable2.m_pieces.Contains(prefab)) { Log.LogDebug("Already added piece " + ((Object)prefab).name); return; } int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)prefab).name); if ((Object)(object)ZNetScene.instance != (Object)null && !ZNetScene.instance.m_namedPrefabs.ContainsKey(stableHashCode)) { PrefabManager.Instance.RegisterToZNetScene(prefab); } if (!string.IsNullOrEmpty(category)) { component.m_category = PieceManager.Instance.AddPieceCategory(pieceTable, category); } if (position < 0) { pieceTable2.m_pieces.Add(prefab); InsertionIndexes[pieceTable].Add(pieceTable2.m_pieces.Count - 1); } else { int index = position + InsertionIndexes[pieceTable].Where((int x) => x <= position).Count(); pieceTable2.m_pieces.Insert(index, prefab); InsertionIndexes[pieceTable].Add(position); } Log.LogDebug("Added piece " + ((Object)prefab).name + " | Token: " + PieceExtension.TokenName(component)); } } [HarmonyPatch(typeof(TerrainComp))] public static class PreciseTerrainModifier { public const int SizeInTiles = 1; [HarmonyPrefix] [HarmonyPatch("InternalDoOperation")] private static bool InternalDoOperationPrefix(TerrainComp __instance, Vector3 pos, Settings modifier) { //IL_0020: 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) if (!modifier.m_level && !modifier.m_raise && !modifier.m_smooth && !modifier.m_paintCleared) { RemoveTerrainModifications(pos, __instance.m_hmap, __instance.m_width, ref __instance.m_levelDelta, ref __instance.m_smoothDelta, ref __instance.m_modifiedHeight); RecolorTerrain(pos, (PaintType)3, __instance.m_hmap, __instance.m_width, ref __instance.m_paintMask, ref __instance.m_modifiedPaint); } return true; } [HarmonyPrefix] [HarmonyPatch("SmoothTerrain")] private static bool SmoothTerrianPrefix(TerrainComp __instance, Vector3 worldPos, float radius) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (IsGridModeEnabled(radius)) { SmoothenTerrain(__instance, worldPos, __instance.m_hmap, __instance.m_width, ref __instance.m_smoothDelta, ref __instance.m_modifiedHeight); return false; } return true; } [HarmonyPrefix] [HarmonyPatch("RaiseTerrain")] private static bool RaiseTerrainPrefix(TerrainComp __instance, Vector3 worldPos, float radius, float delta) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (IsGridModeEnabled(radius)) { RaiseTerrain(__instance, worldPos, __instance.m_hmap, __instance.m_width, delta, ref __instance.m_levelDelta, ref __instance.m_smoothDelta, ref __instance.m_modifiedHeight); return false; } return true; } [HarmonyPrefix] [HarmonyPatch("PaintCleared")] private static bool PreciseColorModificaton(TerrainComp __instance, Vector3 worldPos, float radius, PaintType paintType) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (IsGridModeEnabled(radius)) { RecolorTerrain(worldPos, paintType, __instance.m_hmap, __instance.m_width, ref __instance.m_paintMask, ref __instance.m_modifiedPaint); return false; } return true; } [HarmonyPrefix] [HarmonyPatch("ApplyOperation")] private static void ClientSideGridModeOverride(TerrainOp modifier) { if (!((Object)(object)((modifier != null) ? ((Component)modifier).gameObject : null) == (Object)null) && ((Component)modifier).gameObject.HasComponentInChildren<OverlayVisualizer>(includeInactive: false)) { if (modifier.m_settings.m_smooth) { modifier.m_settings.m_smoothRadius = float.NegativeInfinity; } if (modifier.m_settings.m_raise && modifier.m_settings.m_raiseDelta >= 0f) { modifier.m_settings.m_raiseRadius = float.NegativeInfinity; modifier.m_settings.m_raiseDelta = GroundLevelSpinner.Value; } if (modifier.m_settings.m_paintCleared) { modifier.m_settings.m_paintRadius = float.NegativeInfinity; } } } public static bool IsGridModeEnabled(float radius) { return radius == float.NegativeInfinity; } public static void SmoothenTerrain(TerrainComp compiler, Vector3 worldPos, Heightmap hMap, int worldWidth, ref float[] smoothDelta, ref bool[] modifiedHeight) { //IL_0010: 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_0026: 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) Log.LogInfo("[INIT] Smooth Terrain Modification", LogLevel.Medium); int num = worldWidth + 1; int num2 = default(int); int num3 = default(int); hMap.WorldToVertex(worldPos, ref num2, ref num3); float num4 = worldPos.y - ((Component)compiler).transform.position.y; Log.LogInfo($"worldPos: {worldPos}, xPos: {num2}, yPos: {num3}, referenceH: {num4}", LogLevel.Medium); FindExtrema(num2, num, out var xMin, out var xMax); FindExtrema(num3, num, out var xMin2, out var xMax2); for (int i = xMin; i <= xMax; i++) { for (int j = xMin2; j <= xMax2; j++) { int num5 = j * num + i; float height = hMap.GetHeight(i, j); float num6 = num4 - height; float num7 = smoothDelta[num5]; float num8 = num7 + num6; float num9 = RoundToTwoDecimals(height, num7, num8); float num10 = Mathf.Clamp(num9, -1f, 1f); smoothDelta[num5] = num10; modifiedHeight[num5] = true; Log.LogInfo($"tilePos: ({i}, {j}), tileH: {height}, deltaH: {num6}, oldDeltaH: {num7}, newDeltaH: {num8}, roundedNewDeltaH: {num9}, limDeltaH: {num10}", LogLevel.Medium); } } Log.LogInfo("[SUCCESS] Smooth Terrain Modification", LogLevel.Medium); } public static void RaiseTerrain(TerrainComp compiler, Vector3 worldPos, Heightmap hMap, int worldWidth, float power, ref float[] levelDelta, ref float[] smoothDelta, ref bool[] modifiedHeight) { //IL_0010: 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_0026: 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) Log.LogInfo("[INIT] Raise Terrain Modification", LogLevel.Medium); int num = worldWidth + 1; int num2 = default(int); int num3 = default(int); hMap.WorldToVertex(worldPos, ref num2, ref num3); float num4 = worldPos.y - ((Component)compiler).transform.position.y + power; Log.LogInfo($"worldPos: {worldPos}, xPos: {num2}, yPos: {num3}, power: {power}, referenceH: {num4}", LogLevel.Medium); FindExtrema(num2, num, out var xMin, out var xMax); FindExtrema(num3, num, out var xMin2, out var xMax2); for (int i = xMin; i <= xMax; i++) { for (int j = xMin2; j <= xMax2; j++) { int num5 = j * num + i; float height = hMap.GetHeight(i, j); float num6 = num4 - height; if (num6 >= 0f) { float num7 = levelDelta[num5]; float num8 = smoothDelta[num5]; float num9 = num7 + num8 + num6; float num10 = 0f; float num11 = RoundToTwoDecimals(height, num7 + num8, num9 + num10); float num12 = Mathf.Clamp(num11, -16f, 16f); levelDelta[num5] = num12; smoothDelta[num5] = num10; modifiedHeight[num5] = true; Log.LogInfo($"tilePos: ({i}, {j}), tileH: {height}, deltaH: {num6}, oldLevelDelta: {num7}, oldSmoothDelta: {num8}, newLevelDelta: {num9}, newSmoothDelta: {num10}, roundedNewLevelDelta: {num11}, limitedNewLevelDelta: {num12}", LogLevel.Medium); } else { Log.LogInfo("Declined to process tile: deltaH < 0!", LogLevel.Medium); Log.LogInfo($"tilePos: ({i}, {j}), tileH: {height}, deltaH: {num6}", LogLevel.Medium); } } } Log.LogInfo("[SUCCESS] Raise Terrain Modification", LogLevel.Medium); } public static void RemoveTerrainModifications(Vector3 worldPos, Heightmap hMap, int worldWidth, ref float[] levelDelta, ref float[] smoothDelta, ref bool[] modifiedHeight) { //IL_0010: 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) Log.LogInfo("[INIT] Remove Terrain Modifications", LogLevel.Medium); int num = worldWidth + 1; int num2 = default(int); int num3 = default(int); hMap.WorldToVertex(worldPos, ref num2, ref num3); Log.LogInfo($"worldPos: {worldPos}, vertexPos: ({num2}, {num3})", LogLevel.Medium); FindExtrema(num2, num, out var xMin, out var xMax); FindExtrema(num3, num, out var xMin2, out var xMax2); for (int i = xMin; i <= xMax; i++) { for (int j = xMin2; j <= xMax2; j++) { int num4 = j * num + i; levelDelta[num4] = 0f; smoothDelta[num4] = 0f; modifiedHeight[num4] = false; Log.LogInfo($"tilePos: ({i}, {j}), tileIndex: {num4}", LogLevel.Medium); } } Log.LogInfo("[SUCCESS] Remove Terrain Modifications", LogLevel.Medium); } public static void RecolorTerrain(Vector3 worldPos, PaintType paintType, Heightmap hMap, int worldWidth, ref Color[] paintMask, ref bool[] modifiedPaint) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_003e: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) Log.LogInfo("[INIT] Color Terrain Modification", LogLevel.Medium); int num = default(int); int num2 = default(int); hMap.WorldToVertex(worldPos, ref num, ref num2); Log.LogInfo($"worldPos: {worldPos}, vertexPos: ({num}, {num2})", LogLevel.Medium); Color val = ResolveColor(paintType); bool flag = val == Color.black; FindExtrema(num, worldWidth, out var xMin, out var xMax); FindExtrema(num2, worldWidth, out var xMin2, out var xMax2); for (int i = xMin; i <= xMax; i++) { for (int j = xMin2; j <= xMax2; j++) { int num3 = j * worldWidth + i; paintMask[num3] = val; modifiedPaint[num3] = !flag; Log.LogInfo($"tilePos: ({i}, {j}), tileIndex: {num3}, tileColor: {val}", LogLevel.Medium); } } Log.LogInfo("[SUCCESS] Color Terrain Modification", LogLevel.Medium); } public static Color ResolveColor(PaintType paintType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_0003: 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_0015: Invalid comparison between Unknown and I4 //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) if ((int)paintType == 0) { return Color.red; } if ((int)paintType == 2) { return Color.blue; } if ((int)paintType == 1) { return Color.green; } return Color.black; } public static void FindExtrema(int x, int worldSize, out int xMin, out int xMax) { xMin = Mathf.Max(0, x - 1); xMax = Mathf.Min(x + 1, worldSize - 1); } public static float RoundToTwoDecimals(float oldH, float oldDeltaH, float newDeltaH) { float num = oldH - oldDeltaH + newDeltaH; float num2 = Mathf.Round(num * 100f) / 100f; float num3 = num2 - oldH + oldDeltaH; Log.LogInfo($"oldH: {oldH}, oldDeltaH: {oldDeltaH}, newDeltaH: {newDeltaH}, newH: {num}, roundedNewH: {num2}, roundedNewDeltaH: {num3}", LogLevel.Medium); return num3; } } [HarmonyPatch] internal class RadiusModifier { [HarmonyPatch(typeof(Player))] internal class PlayerPatch { [HarmonyPrefix] [HarmonyPatch("Update")] private static void UpdatePrefix(Player __instance) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || !((Character)__instance).InPlaceMode() || Hud.IsPieceSelectionVisible()) { if (lastOriginalRadius != 0f) { lastOriginalRadius = 0f; lastModdedRadius = 0f; lastTotalDelta = 0f; SetRadius(__instance, 0f); } } else if (ShouldModifyRadius()) { SetRadius(__instance, Input.mouseScrollDelta.y * TerrainTools.RadiusScrollScale); } } } [HarmonyPatch(typeof(TerrainOp))] internal class TerrainOpPatch { [HarmonyPrefix] [HarmonyPriority(700)] [HarmonyPatch("Awake")] private static void AwakePrefix(TerrainOp __instance) { if (__instance != null && ((Component)__instance).gameObject != null && !((Component)__instance).gameObject.HasComponent<OverlayVisualizer>()) { if (__instance.m_settings.m_level) { __instance.m_settings.m_levelRadius = ModifyRadius(__instance.m_settings.m_levelRadius, lastTotalDelta); Log.LogInfo($"Applying level radius {__instance.m_settings.m_levelRadius}", LogLevel.Medium); } if (__instance.m_settings.m_raise) { __instance.m_settings.m_raiseRadius = ModifyRadius(__instance.m_settings.m_raiseRadius, lastTotalDelta); Log.LogInfo($"Applying raise radius {__instance.m_settings.m_raiseRadius}", LogLevel.Medium); } if (__instance.m_settings.m_smooth) { __instance.m_settings.m_smoothRadius = ModifyRadius(__instance.m_settings.m_smoothRadius, lastTotalDelta); Log.LogInfo($"Applying smooth radius {__instance.m_settings.m_smoothRadius}", LogLevel.Medium); } if (__instance.m_settings.m_paintCleared) { __instance.m_settings.m_paintRadius = ModifyRadius(__instance.m_settings.m_paintRadius, lastTotalDelta); Log.LogInfo($"Applying paint radius {__instance.m_settings.m_paintRadius}", LogLevel.Medium); } } } } internal static float lastOriginalRadius; internal static float lastModdedRadius; internal static float lastTotalDelta; private const float MinRadius = 0.5f; internal static bool ShouldModifyRadius() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (TerrainTools.IsEnableRadiusModifier && Input.GetKey(TerrainTools.RadiusKey)) { return Input.mouseScrollDelta.y != 0f; } return false; } private static float ModifyRadius(float radius, float delta) { return Mathf.Clamp(radius + delta, 0.5f, TerrainTools.MaxRadius); } private static void SetRadius(Player player, float delta) { //IL_020c: Unknown result type (might be due to invalid IL or missing references) Piece selectedPiece = player.GetSelectedPiece(); if (selectedPiece == null || ((Component)selectedPiece).gameObject == null || ((Component)selectedPiece).gameObject.HasComponent<OverlayVisualizer>()) { return; } TerrainOp component = ((Component)selectedPiece).gameObject.GetComponent<TerrainOp>(); if ((Object)(object)component == (Object)null) { return; } Log.LogInfo($"Adjusting radius by {delta}", LogLevel.Medium); float num = 0f; float num2 = ModifyRadius(lastModdedRadius, delta); lastTotalDelta += delta; if (lastOriginalRadius == 0f) { if (component.m_settings.m_level && num < component.m_settings.m_levelRadius) { num = component.m_settings.m_levelRadius; num2 = ModifyRadius(component.m_settings.m_levelRadius, delta); } if (component.m_settings.m_raise && num < component.m_settings.m_raiseRadius) { num = component.m_settings.m_raiseRadius; num2 = ModifyRadius(component.m_settings.m_raiseRadius, delta); } if (component.m_settings.m_smooth && num < component.m_settings.m_smoothRadius) { num = component.m_settings.m_smoothRadius; num2 = ModifyRadius(component.m_settings.m_smoothRadius, delta); } if (component.m_settings.m_paintCleared && num < component.m_settings.m_paintRadius) { num = component.m_settings.m_paintRadius; num2 = ModifyRadius(component.m_settings.m_paintRadius, delta); } lastOriginalRadius = num; } lastModdedRadius = num2; if (lastOriginalRadius > 0f && lastModdedRadius > 0f) { Log.LogInfo($"total delta {lastTotalDelta}", LogLevel.Medium); GameObject placementGhost = player.m_placementGhost; Transform val = ((placementGhost != null) ? placementGhost.transform.Find("_GhostOnly") : null); if ((Object)(object)val != (Object)null) { Log.LogInfo($"Adjusting ghost scale to {lastModdedRadius / lastOriginalRadius}x", LogLevel.Medium); val.localScale = new Vector3(lastModdedRadius / lastOriginalRadius, lastModdedRadius / lastOriginalRadius, lastModdedRadius / lastOriginalRadius); } } } } } namespace TerrainTools.Extensions { internal static class EventExtensions { public static void SafeInvoke(this Action events) { if (events == null) { return; } Delegate[] invocationList = events.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { Action action = (Action)invocationList[i]; try { action(); } catch (Exception ex) { Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}"); } } } public static void SafeInvoke<TArg1>(this Action<TArg1> events, TArg1 arg1) { if (events == null) { return; } Delegate[] invocationList = events.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { Action<TArg1> action = (Action<TArg1>)invocationList[i]; try { action(arg1); } catch (Exception ex) { Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}"); } } } public static void SafeInvoke<TArg1, TArg2>(this Action<TArg1, TArg2> events, TArg1 arg1, TArg2 arg2) { if (events == null) { return; } Delegate[] invocationList = events.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { Action<TArg1, TArg2> action = (Action<TArg1, TArg2>)invocationList[i]; try { action(arg1, arg2); } catch (Exception ex) { Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}"); } } } public static void SafeInvoke<TEventArg>(this EventHandler<TEventArg> events, object sender, TEventArg arg1) { if (events == null) { return; } Delegate[] invocationList = events.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { EventHandler<TEventArg> eventHandler = (EventHandler<TEventArg>)invocationList[i]; try { eventHandler(sender, arg1); } catch (Exception ex) { Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {eventHandler.Method.DeclaringType.Name}.{eventHandler.Method.Name}:\n{ex}"); } } } } internal static class GameObjectExtensions { internal static GameObject DeepCopy(this GameObject obj) { bool activeSelf = obj.activeSelf; obj.SetActive(false); GameObject result = Object.Instantiate<GameObject>(obj); obj.SetActive(activeSelf); return result; } public static bool HasComponent<T>(this GameObject gameObject) where T : Component { return (Object)(object)gameObject.GetComponent<T>() != (Object)null; } public static bool HasComponent(this GameObject gameObject, string componentName) { return (Object)(object)gameObject.GetComponent(componentName) != (Object)null; } public static void DestroyComponentsInChildren<T>(this GameObject gameObject, bool includeInactive = false) where T : Component { T[] componentsInChildren = gameObject.GetComponentsInChildren<T>(includeInactive); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } } public static bool HasAnyComponent(this GameObject gameObject, params Type[] components) { foreach (Type type in components) { if ((Object)(object)gameObject.GetComponent(type) != (Object)null) { return true; } } return false; } public static bool HasAnyComponent(this GameObject gameObject, params string[] componentNames) { foreach (string text in componentNames) { if ((Object)(object)gameObject.GetComponent(text) != (Object)null) { return true; } } return false; } public static bool HasAllComponents(this GameObject gameObject, params string[] componentNames) { foreach (string text in componentNames) { if ((Object)(object)gameObject.GetComponent(text) == (Object)null) { return false; } } return true; } public static bool HasAllComponents(this GameObject gameObject, params Type[] components) { foreach (Type type in components) { if ((Object)(object)gameObject.GetComponent(type) == (Object)null) { return false; } } return true; } public static bool HasAnyComponentInChildren(this GameObject gameObject, bool includeInactive = false, params Type[] components) { foreach (Type type in components) { if ((Object)(object)gameObject.GetComponentInChildren(type, includeInactive) != (Object)null) { return true; } } return false; } public static bool HasComponentInChildren<T>(this GameObject gameObject, bool includeInactive = false) where T : Component { return (Object)(object)gameObject.GetComponentInChildren<T>(includeInactive) != (Object)null; } internal static T GetComponentInChildrenByName<T>(this GameObject gameObject, string name, bool includeInactive = false) where T : Component { T[] componentsInChildren = gameObject.GetComponentsInChildren<T>(includeInactive); foreach (T val in componentsInChildren) { if (((Object)(object)val).name == name) { return val; } } Log.LogWarning("No T with name " + name + " found for GameObject: " + ((Object)gameObject).name); return default(T); } internal static Mesh GetMesh(this GameObject gameObject, string meshName) { MeshFilter[] componentsInChildren = gameObject.GetComponentsInChildren<MeshFilter>(); for (int i = 0; i < componentsInChildren.Length; i++) { Mesh mesh = componentsInChildren[i].mesh; if (!((Object)(object)mesh == (Object)null) && ((Object)mesh).name.RemoveSuffix("Instance").Trim() == meshName) { return mesh; } } Log.LogWarning("Could not find Mesh: " + meshName + " for GameObject: " + ((Object)gameObject).name); return null; } } internal static class TypeExtensions { internal static List<T> GetAllPublicConstantValues<T>(this Type type) { return (from fi in type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy) where fi.IsLiteral && !fi.IsInitOnly && fi.FieldType == typeof(T) select fi into x select (T)x.GetRawConstantValue()).ToList(); } internal static List<T> GetAllPublicStaticValues<T>(this Type type) { return (from fi in type.GetFields(BindingFlags.Static | BindingFlags.Public) where fi.FieldType == typeof(T) select fi into x select (T)x.GetValue(null)).ToList(); } } internal static class GenericExtensions { private const BindingFlags AllBindings = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty; public static void CopyFields(this object target, object source) { if (target == null || source == null) { throw new Exception("Target or/and Source Objects are null"); } Type type = source.GetType(); FieldInfo[] fields = target.GetType().GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty); foreach (FieldInfo fieldInfo in fields) { FieldInfo field = type.GetField(fieldInfo.Name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty); if (!(field == null) && field.IsInitOnly && field.FieldType.IsAssignableFrom(fieldInfo.FieldType)) { field.SetValue(source, fieldInfo.GetValue(target)); } } } internal static T Ref<T>(this T o) where T : Object { if (!Object.op_Implicit((Object)(object)o)) { return default(T); } return o; } } internal static class IEnumerableExtensions { internal static void Dispose(this IEnumerable<IDisposable> collection) { foreach (IDisposable item in collection) { if (item != null) { try { item.Dispose(); } catch (Exception) { Log.LogWarning("Could not dispose of item"); } } } } } internal static class ReflectionUtils { public const BindingFlags AllBindings = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty; internal static MethodInfo GetMethod(Type type, string name, Type[] types) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == name && HasMatchingParameterTypes(0, types, methodInfo.GetParameters())) { return methodInfo; } } return null; } internal static MethodInfo GetGenericMethod(Type type, string name, int genericParameterCount, Type[] types) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty); foreach (MethodInfo methodInfo in methods) { if (methodInfo.IsGenericMethod && methodInfo.ContainsGenericParameters && methodInfo.Name == name && HasMatchingParameterTypes(genericParameterCount, types, methodInfo.GetParameters())) { return methodInfo; } } return null; } private static bool HasMatchingParameterTypes(int genericParameterCount, Type[] types, ParameterInfo[] parameters) { if (parameters.Length < genericParameterCount || parameters.Length != types.Length) { return false; } int num = 0; for (int i = 0; i < parameters.Length; i++) { if (parameters[i].ParameterType.IsGenericParameter) { num++; } else if (types[i] != parameters[i].ParameterType) { return false; } } if (num != genericParameterCount) { return false; } return true; } } internal static class StringExtensions { internal static bool ContainsAny(this string str, params string[] substrings) { foreach (string value in substrings) { if (str.Contains(value)) { return true; } } return false; } internal static bool EndsWithAny(this string str, params string[] suffixes) { foreach (string value in suffixes) { if (str.EndsWith(value)) { return true; } } return false; } internal static bool StartsWithAny(this string str, params string[] suffixes) { foreach (string value in suffixes) { if (str.StartsWith(value)) { return true; } } return false; } internal static string RemoveSuffix(this string s, string suffix) { if (s.EndsWith(suffix)) { return s.Substring(0, s.Length - suffix.Length); } return s; } internal static string RemovePrefix(this string s, string prefix) { if (s.StartsWith(prefix)) { return s.Substring(prefix.Length, s.Length - prefix.Length); } return s; } internal static string CapitalizeFirstLetter(this string s) { if (s.Length == 0) { return s; } if (s.Length == 1) { return $"{char.ToUpper(s[0])}"; } return char.ToUpper(s[0]) + s.Substring(1); } internal static string EmptyIfNull(this object value) { if (value == null) { return string.Empty; } return value.ToString(); } } internal static class TransformExtensions { public static Transform FindDeepChild(this Transform transform, string childName, bool breadthFirst = true) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown if (breadthFirst) { Queue<Transform> queue = new Queue<Transform>(); queue.Enqueue(transform); while (queue.Count > 0) { Transform val = queue.Dequeue(); if (((Object)val).name == childName) { return val; } foreach (Transform item2 in val) { Transform item = item2; queue.Enqueue(item); } } return null; } foreach (Transform item3 in transform) { Transform val2 = item3; if (((Object)val2).name == childName) { return val2; } Transform val3 = val2.FindDeepChild(childName); if ((Object)(object)val3 != (Object)null) { return val3; } } return null; } } } namespace TerrainTools.Configs { internal class ConfigManager { private static string ConfigFileName; private static string ConfigFileFullPath; private static ConfigFile configFile; private static BaseUnityPlugin ConfigurationManager; private const string ConfigManagerGUID = "com.bepis.bepinex.configurationmanager"; private static readonly ConfigurationManagerAttributes AdminConfig = new ConfigurationManagerAttributes { IsAdminOnly = true }; private static readonly ConfigurationManagerAttributes ClientConfig = new ConfigurationManagerAttributes { IsAdminOnly = false }; private const char ZWS = '\u200b'; internal static event Action OnConfigWindowClosed; internal static event Action OnConfigFileReloaded; private static void InvokeOnConfigWindowClosed() { ConfigManager.OnConfigWindowClosed?.SafeInvoke(); } private static void InvokeOnConfigFileReloaded() { ConfigManager.OnConfigFileReloaded?.SafeInvoke(); } internal static ConfigEntry<T> BindConfig<T>(string section, string name, T value, string description, AcceptableValueBase acceptVals = null, bool synced = true) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown string extendedDescription = GetExtendedDescription(description, synced); return configFile.Bind<T>(section, name, value, new ConfigDescription(extendedDescription, acceptVals, new object[1] { synced ? AdminConfig : ClientConfig })); } internal static string SetStringPriority(string sectionName, int priority) { if (priority == 0) { return sectionName; } return new string('\u200b', priority) + sectionName; } internal static string GetExtendedDescription(string description, bool synchronizedSetting) { return description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"); } internal static void Init(string GUID, ConfigFile config) { configFile = config; configFile.SaveOnConfigSet = false; ConfigFileName = GUID + ".cfg"; ConfigFileFullPath = Path.Combine(Paths.ConfigPath, ConfigFileName); } private static bool DisableSaveOnConfigSet() { bool saveOnConfigSet = configFile.SaveOnConfigSet; configFile.SaveOnConfigSet = false; return saveOnConfigSet; } internal static void SaveOnConfigSet(bool value) { configFile.SaveOnConfigSet = value; } internal static void Save() { configFile.Save(); } internal static void SetupWatcher() { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName); fileSystemWatcher.Changed += ReloadConfigFile; fileSystemWatcher.Created += ReloadConfigFile; fileSystemWatcher.Renamed += ReloadConfigFile; fileSystemWatcher.IncludeSubdirectories = true; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; } private static void ReloadConfigFile(object sender, FileSystemEventArgs e) { if (!File.Exists(ConfigFileFullPath)) { return; } try { Log.LogInfo("Reloading config file"); bool value = DisableSaveOnConfigSet(); configFile.Reload(); SaveOnConfigSet(value); InvokeOnConfigFileReloaded(); } catch { Log.LogError("There was an issue loading your " + ConfigFileName); Log.LogError("Please check your config entries for spelling and format!"); } } internal static void CheckForConfigManager() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)SystemInfo.graphicsDeviceType != 4 && Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value) && Object.op_Implicit((Object)(object)value.Instance)) { ConfigurationManager = value.Instance; Log.LogDebug("Configuration manager found, hooking DisplayingWindowChanged"); EventInfo @event = ((object)ConfigurationManager).GetType().GetEvent("DisplayingWindowChanged"); if (@event != null) { Action<object, object> action = OnConfigManagerDisplayingWindowChanged; Delegate handler = Delegate.CreateDelegate(@event.EventHandlerType, action.Target, action.Method); @event.AddEventHandler(ConfigurationManager, handler); } } } private static void OnConfigManagerDisplayingWindowChanged(object sender, object e) { if (!(bool)((object)ConfigurationManager).GetType().GetProperty("DisplayingWindow").GetValue(ConfigurationManager, null)) { InvokeOnConfigWindowClosed(); } } } internal class ToolConfigs { internal static Dictionary<string, ToolDB> ToolConfigsMap; static ToolConfigs() { Dictionary<string, ToolDB> obj = new Dictionary<string, ToolDB> { { "mud_road_v2_sq", new ToolDB("mud_road_v2_sq", "mud_road_v2", "Level ground(square)", "Levels ground according to the world grid based on player position. (Use shift+click to level ground based on where you are pointing instead)", IconCache.MudRoadSquare, PieceTables.Hoe, 1, typeof(LevelGroundOverlayVisualizer)) }, { "raise_v2_precise", new ToolDB("raise_v2_precise", "raise_v2", "Raise ground (precision)", "Raise ground with precision accuracy by using scroll wheel to set ground height.", IconCache.RaiseSquare, PieceTables.Hoe, 2, typeof(RaiseGroundOverlayVisualizer)) }, { "path_v2_square", new ToolDB("path_v2_square", "path_v2", "Pathen (square)", "Creates a dirt path according to the world grid without affecting ground height.", IconCache.MudRoadPathSquare, PieceTables.Hoe, 3, typeof(SquarePathOverlayVisualizer)) }, { "paved_road_v2_square", new ToolDB("Paved road (Square)", "paved_road_v2", "Paved road (square)", "Creates a paved path according to the world grid and levels ground based on player position. (Use shift+click to level ground based on where you are pointing)", IconCache.PavedRoadSquare, PieceTables.Hoe, -1, typeof(SquarePathOverlayVisualizer)) } }; Texture2D pavedRoadPath = IconCache.PavedRoadPath; string hoe = PieceTables.Hoe; bool? smooth = false; obj.Add("paved_road_v2_path", new ToolDB("paved_road_v2_path", "paved_road_v2", "Paved road (path)", "Creates a paved path without affecting ground height", pavedRoadPath, hoe, -1, null, null, null, smooth)); Texture2D pavedRoadPathSquare = IconCache.PavedRoadPathSquare; string hoe2 = PieceTables.Hoe; Type typeFromHandle = typeof(SquarePathOverlayVisualizer); smooth = false; obj.Add("paved_road_v2_path_square", new ToolDB("paved_road_v2_path_square", "paved_road_v2", "Paved road (path, square)", "Created a paved path according to the world grid without affecting ground height", pavedRoadPathSquare, hoe2, -1, typeFromHandle, null, null, smooth)); obj.Add("remove_terrain_mods", new ToolDB("remove_terrain_mods", "mud_road_v2", "Remove Terrain Modifications", "Resets ground height and paint", IconCache.Remove, PieceTables.Hoe, -1, typeof(RemoveModificationsOverlayVisualizer), smooth: false, level: false, raise: false, clearPaint: false)); obj.Add("cultivate_v2_square", new ToolDB("cultivate_v2_square", "cultivate_v2", "Cultivate (square)", "Cultivates ground according to the world grid and levels terrain based on player position. (Use shift+click to level ground based on where you are pointing)", IconCache.CultivateSquare, PieceTables.Cultivator, 1, typeof(CultivateOverlayVisualizer))); Texture2D cultivatePath = IconCache.CultivatePath; string cultivator = PieceTables.Cultivator; smooth = false; obj.Add("cultivate_v2_path", new ToolDB("cultivate_v2_path", "cultivate_v2", "Cultivate (path)", "Cultivates ground without affecting ground height.", cultivatePath, cultivator, 1, null, null, null, smooth)); Texture2D cultivatePathSquare = IconCache.CultivatePathSquare; string cultivator2 = PieceTables.Cultivator; Type typeFromHandle3 = typeof(CultivateOverlayVisualizer); smooth = false; obj.Add("cultivate_v2_path_square", new ToolDB("cultivate_v2_path_square", "cultivate_v2", "Cultivate (path, square)", "Cultivates ground according to the world grid without affecting ground height.", cultivatePathSquare, cultivator2, 1, typeFromHandle3, null, null, smooth)); obj.Add("replant_v2_square", new ToolDB("replant_v2_square", "replant_v2", "Replant (square)", "Replants terrain according to world grid without affecting ground height.", IconCache.ReplantSquare, PieceTables.Cultivator, 2, typeof(SeedGrassOverlayVisualizer))); ToolConfigsMap = obj; } } internal class ToolDB { public string name; public string basePrefab; public string pieceName; public string pieceDesc; public Texture2D icon; public string pieceTable; public int insertIndex; public Type overlayType; public bool? level; public bool? raise; public bool? smooth; public bool? clearPaint; public ToolDB(string name, string basePrefab, string pieceName, string pieceDesc, Texture2D icon, string pieceTable, int insertIndex = -1, Type overlayType = null, bool? level = null, bool? raise = null, bool? smooth = null, bool? clearPaint = null) { this.name = name; this.basePrefab = basePrefab; this.pieceName = pieceName; this.pieceDesc = pieceDesc; this.icon = icon; this.pieceTable = pieceTable; this.insertIndex = insertIndex; if (overlayType != null) { this.overlayType = overlayType; } this.level = level; this.raise = raise; this.smooth = smooth; this.clearPaint = clearPaint; } } }