Decompiled source of TrueLevel v0.1.3

BepInEx/plugins/TrueLevel/TrueLevel.dll

Decompiled 5 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("TrueLevel")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.3.0")]
[assembly: AssemblyInformationalVersion("0.1.3")]
[assembly: AssemblyProduct("TrueLevel")]
[assembly: AssemblyTitle("TrueLevel")]
[assembly: AssemblyVersion("0.1.3.0")]
namespace TrueLevel;

[BepInPlugin("local.valheim.truelevel", "True Level", "0.1.3")]
public sealed class Plugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(Terminal), "TryRunCommand", new Type[]
	{
		typeof(string),
		typeof(bool),
		typeof(bool)
	})]
	private static class CommandPatch
	{
		private static bool Prefix(Terminal __instance, string __0)
		{
			string[] array = (__0 ?? "").Trim().Split(new char[2] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
			if (array.Length == 0 || !array[0].Equals("truelevel", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (!Object.op_Implicit((Object)(object)Instance) || !((Behaviour)Instance).enabled)
			{
				__instance.AddString("True Level is unavailable.");
				return false;
			}
			if (array.Length > 2)
			{
				__instance.AddString("Usage: /truelevel [on|off]");
				return false;
			}
			string text = ((array.Length == 1) ? "" : array[1].ToLowerInvariant());
			switch (text)
			{
			default:
				if (text.Length != 0)
				{
					goto case null;
				}
				Instance.SetMode(!Instance.enabledMode.Value);
				break;
			case "on":
				Instance.SetMode(value: true);
				break;
			case "off":
				Instance.SetMode(value: false);
				break;
			case null:
				__instance.AddString("Usage: /truelevel [on|off]");
				return false;
			}
			__instance.AddString("True Level: " + (Instance.enabledMode.Value ? "ON" : "OFF"));
			return false;
		}
	}

	[HarmonyPatch(typeof(Player), "PlacePiece")]
	private static class PlacementPatch
	{
		private static void Prefix(Player __instance, Piece __0, out float? __state)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			__state = PlacementHeight;
			PlacementHeight = null;
			if (Object.op_Implicit((Object)(object)Instance) && ((Behaviour)Instance).enabled && Instance.enabledMode.Value && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && Object.op_Implicit((Object)(object)__0) && IsLevelGround(((Object)((Component)__0).gameObject).name))
			{
				PlacementHeight = ((Component)__instance).transform.position.y;
			}
		}

		private static Exception Finalizer(Exception __exception, float? __state)
		{
			PlacementHeight = __state;
			return __exception;
		}
	}

	[HarmonyPatch(typeof(TerrainComp), "ApplyOperation")]
	private static class OperationPatch
	{
		private static bool Prefix(TerrainComp __instance, TerrainOp __0, ZNetView ___m_nview)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_00cd: 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_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			if (!PlacementHeight.HasValue || !IsLevelGround(((Object)((Component)__0).gameObject).name))
			{
				return true;
			}
			if (!Object.op_Implicit((Object)(object)___m_nview) || !___m_nview.IsValid())
			{
				return false;
			}
			___m_nview.ClaimOwnership();
			if (!___m_nview.IsOwner())
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "True Level: terrain unavailable; try again.", 0, (Sprite)null, false);
				return false;
			}
			CheckLoad.Invoke(__instance, null);
			Settings val = new Settings();
			FieldInfo[] fields = typeof(Settings).GetFields(BindingFlags.Instance | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				fieldInfo.SetValue(val, fieldInfo.GetValue(__0.m_settings));
			}
			val.m_level = true;
			val.m_raise = false;
			val.m_smooth = false;
			val.m_levelOffset = 0f;
			Vector3 position = ((Component)__0).transform.position;
			position.y = PlacementHeight.Value;
			bool applying = Applying;
			try
			{
				Applying = true;
				DoOperation.Invoke(__instance, new object[3]
				{
					position,
					((Component)__0).transform.forward,
					val
				});
				((BaseUnityPlugin)Instance).Logger.LogDebug((object)("True Level applied at feet height " + position.y));
			}
			finally
			{
				Applying = applying;
			}
			return false;
		}
	}

	[HarmonyPatch(typeof(TerrainComp), "LevelTerrain")]
	private static class LevelPatch
	{
		private static bool Prefix(TerrainComp __instance, Vector3 __0, float __1, bool __2, Heightmap ___m_hmap, int ___m_width, float[] ___m_levelDelta, float[] ___m_smoothDelta, bool[] ___m_modifiedHeight)
		{
			//IL_000b: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			if (!Applying)
			{
				return true;
			}
			int num = default(int);
			int num2 = default(int);
			___m_hmap.WorldToVertex(__0, ref num, ref num2);
			float num3 = __1 / ___m_hmap.m_scale;
			int num4 = Mathf.CeilToInt(num3);
			int num5 = ___m_width + 1;
			float num6 = __0.y - ((Component)__instance).transform.position.y;
			for (int i = Math.Max(0, num2 - num4); i <= Math.Min(___m_width, num2 + num4); i++)
			{
				for (int j = Math.Max(0, num - num4); j <= Math.Min(___m_width, num + num4); j++)
				{
					if (__2 || !((float)((j - num) * (j - num) + (i - num2) * (i - num2)) > num3 * num3))
					{
						int num7 = i * num5 + j;
						___m_levelDelta[num7] += num6 - ___m_hmap.GetHeight(j, i) + ___m_smoothDelta[num7];
						___m_smoothDelta[num7] = 0f;
						___m_modifiedHeight[num7] = true;
					}
				}
			}
			return false;
		}
	}

	[HarmonyPatch(typeof(TerrainComp), "ApplyToHeightmap")]
	private static class DisplayPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = instructions.ToList();
			MethodInfo methodInfo = AccessTools.Method(typeof(Mathf), "Clamp", new Type[3]
			{
				typeof(float),
				typeof(float),
				typeof(float)
			}, (Type[])null);
			int num = 0;
			foreach (CodeInstruction item in list)
			{
				if (CodeInstructionExtensions.Calls(item, methodInfo))
				{
					item.opcode = OpCodes.Call;
					item.operand = AccessTools.Method(typeof(DisplayPatch), "Unclamped", (Type[])null, (Type[])null);
					num++;
				}
			}
			if (num != 1)
			{
				throw new InvalidOperationException("Terrain display layout changed; expected exactly one Clamp, found " + num);
			}
			return list;
		}

		private static float Unclamped(float value, float min, float max)
		{
			return value;
		}
	}

	public const string Id = "local.valheim.truelevel";

	internal static Plugin Instance;

	private ConfigEntry<KeyboardShortcut> toggle;

	private ConfigEntry<bool> enabledMode;

	private Harmony harmony;

	internal static float? PlacementHeight;

	internal static bool Applying;

	internal static readonly MethodInfo DoOperation = AccessTools.Method(typeof(TerrainComp), "DoOperation", (Type[])null, (Type[])null);

	internal static readonly MethodInfo CheckLoad = AccessTools.Method(typeof(TerrainComp), "CheckLoad", (Type[])null, (Type[])null);

	private void Awake()
	{
		//IL_0042: 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_00e0: Expected O, but got Unknown
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Invalid comparison between Unknown and I4
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		Instance = this;
		enabledMode = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", false, "True Level mode. F9 or /truelevel toggles this and saves the setting.");
		toggle = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "ToggleKey", new KeyboardShortcut((KeyCode)290, Array.Empty<KeyCode>()), "Toggle True Level while playing.");
		ConfigEntry<int> val = ((BaseUnityPlugin)this).Config.Bind<int>("General", "KeyMigrationVersion", 0, "Internal setting for the one-time F8 to F9 upgrade.");
		if (val.Value < 1)
		{
			KeyboardShortcut value = toggle.Value;
			if ((int)((KeyboardShortcut)(ref value)).MainKey == 289)
			{
				value = toggle.Value;
				if (!((KeyboardShortcut)(ref value)).Modifiers.Any())
				{
					toggle.Value = new KeyboardShortcut((KeyCode)290, Array.Empty<KeyCode>());
				}
			}
			val.Value = 1;
		}
		harmony = new Harmony("local.valheim.truelevel");
		try
		{
			harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"True Level 0.1.3 loaded. F9 or /truelevel toggles hoe leveling.");
		}
		catch (Exception ex)
		{
			harmony.UnpatchSelf();
			((Behaviour)this).enabled = false;
			((BaseUnityPlugin)this).Logger.LogError((object)("Unsupported game or patch conflict; True Level disabled. " + ex));
		}
	}

	private void Update()
	{
		//IL_0040: 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)
		if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && (!Object.op_Implicit((Object)(object)Chat.instance) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !Menu.IsVisible() && !InventoryGui.IsVisible())
		{
			KeyboardShortcut value = toggle.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				SetMode(!enabledMode.Value);
			}
		}
	}

	private void SetMode(bool value)
	{
		enabledMode.Value = value;
		if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
		{
			((Character)Player.m_localPlayer).Message((MessageType)2, "True Level: " + (value ? "ON" : "OFF"), 0, (Sprite)null, false);
		}
	}

	private void OnDestroy()
	{
		Harmony obj = harmony;
		if (obj != null)
		{
			obj.UnpatchSelf();
		}
		Instance = null;
	}

	internal static bool IsLevelGround(string name)
	{
		if (name == null)
		{
			return false;
		}
		if (name.EndsWith("(Clone)", StringComparison.Ordinal))
		{
			name = name.Substring(0, name.Length - "(Clone)".Length);
		}
		if (!(name == "mud_road"))
		{
			return name == "mud_road_v2";
		}
		return true;
	}
}