Decompiled source of FlattenheimDigDeeperCompatibility v1.0.1

BepInEx/plugins/FlattenheimDigDeeperCompatibility/FlattenheimDigDeeperCompatibility.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace FlattenheimDigDeeperCompatibility;

[BepInPlugin("com.codex.flattenheim.digdeeper.compatibility", "Flattenheim Dig Deeper Compatibility", "1.0.0")]
[BepInProcess("valheim.exe")]
[BepInProcess("valheim_server.exe")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class CompatibilityPlugin : BaseUnityPlugin
{
	public const string PluginGuid = "com.codex.flattenheim.digdeeper.compatibility";

	public const string PluginName = "Flattenheim Dig Deeper Compatibility";

	public const string PluginVersion = "1.0.0";

	private static ManualLogSource PluginLog;

	private static Func<float> ReadMaximumDepth;

	private static Func<float> ReadMaximumHeight;

	private void Awake()
	{
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Expected O, but got Unknown
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Expected O, but got Unknown
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Expected O, but got Unknown
		PluginLog = ((BaseUnityPlugin)this).Logger;
		bool flag;
		try
		{
			flag = InitializeConfigReaders();
		}
		catch (Exception ex)
		{
			PluginLog.LogError((object)("Could not initialize Dig Deeper configuration readers: " + ex));
			return;
		}
		if (!flag)
		{
			PluginLog.LogError((object)"Dig Deeper configuration could not be read; Flattenheim was left unpatched.");
			return;
		}
		Type type = AccessTools.TypeByName("Flattenheim.FlattenheimPlugin");
		if (type == null)
		{
			PluginLog.LogError((object)"Flattenheim.FlattenheimPlugin was not found; no compatibility patches were applied.");
			return;
		}
		MethodInfo methodInfo = AccessTools.Method(type, "ApplyFlatten", (Type[])null, (Type[])null);
		MethodInfo methodInfo2 = AccessTools.Method(type, "ApplyRampTerrain", (Type[])null, (Type[])null);
		if (methodInfo == null || methodInfo2 == null)
		{
			PluginLog.LogError((object)"The expected Flattenheim terrain methods were not found; no compatibility patches were applied.");
			return;
		}
		try
		{
			Harmony val = new Harmony("com.codex.flattenheim.digdeeper.compatibility");
			val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(CompatibilityPlugin), "TranspileApplyFlatten", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(CompatibilityPlugin), "TranspileApplyRampTerrain", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null);
			PluginLog.LogInfo((object)"Registered compatibility patches for Flattenheim's flatten and ramp terrain methods.");
		}
		catch (Exception ex2)
		{
			PluginLog.LogError((object)("Could not apply the Flattenheim compatibility patches: " + ex2));
		}
	}

	private static bool InitializeConfigReaders()
	{
		Type type = AccessTools.TypeByName("DigDeeper.DigDeeperPlugin");
		if (type == null)
		{
			return false;
		}
		FieldInfo field = type.GetField("MaximumDepth", BindingFlags.Static | BindingFlags.Public);
		FieldInfo field2 = type.GetField("MaximumHeight", BindingFlags.Static | BindingFlags.Public);
		if (field == null || field2 == null)
		{
			return false;
		}
		object value = field.GetValue(null);
		object value2 = field2.GetValue(null);
		if (value == null || value2 == null)
		{
			return false;
		}
		ReadMaximumDepth = CreateFloatReader(value);
		ReadMaximumHeight = CreateFloatReader(value2);
		if (ReadMaximumDepth != null)
		{
			return ReadMaximumHeight != null;
		}
		return false;
	}

	private static Func<float> CreateFloatReader(object configEntry)
	{
		PropertyInfo property = configEntry.GetType().GetProperty("Value", BindingFlags.Instance | BindingFlags.Public);
		if (property == null)
		{
			return null;
		}
		MethodInfo getMethod = property.GetGetMethod();
		if (getMethod == null || getMethod.ReturnType != typeof(float) || getMethod.GetParameters().Length != 0)
		{
			return null;
		}
		return (Func<float>)Delegate.CreateDelegate(typeof(Func<float>), configEntry, getMethod);
	}

	public static float GetLowerTerrainDelta()
	{
		return 0f - ReadMaximumDepth();
	}

	public static float GetUpperTerrainDelta()
	{
		return ReadMaximumHeight();
	}

	private static IEnumerable<CodeInstruction> TranspileApplyFlatten(IEnumerable<CodeInstruction> instructions)
	{
		return ReplaceTerrainClamp(instructions, "ApplyFlatten");
	}

	private static IEnumerable<CodeInstruction> TranspileApplyRampTerrain(IEnumerable<CodeInstruction> instructions)
	{
		return ReplaceTerrainClamp(instructions, "ApplyRampTerrain");
	}

	private static IEnumerable<CodeInstruction> ReplaceTerrainClamp(IEnumerable<CodeInstruction> instructions, string methodName)
	{
		List<CodeInstruction> list = new List<CodeInstruction>(instructions);
		List<int> list2 = new List<int>();
		for (int i = 2; i < list.Count; i++)
		{
			MethodInfo method = list[i].operand as MethodInfo;
			if (list[i].opcode == OpCodes.Call && IsMathfClamp(method) && IsFloatConstant(list[i - 2], -8f) && IsFloatConstant(list[i - 1], 8f))
			{
				list2.Add(i - 2);
			}
		}
		if (list2.Count != 1)
		{
			if (PluginLog != null)
			{
				PluginLog.LogError((object)("Expected one Flattenheim ±8 terrain clamp in " + methodName + ", found " + list2.Count + "; original method behavior was kept."));
			}
			return list;
		}
		int num = list2[0];
		list[num].opcode = OpCodes.Call;
		list[num].operand = typeof(CompatibilityPlugin).GetMethod("GetLowerTerrainDelta", BindingFlags.Static | BindingFlags.Public);
		list[num + 1].opcode = OpCodes.Call;
		list[num + 1].operand = typeof(CompatibilityPlugin).GetMethod("GetUpperTerrainDelta", BindingFlags.Static | BindingFlags.Public);
		if (PluginLog != null)
		{
			PluginLog.LogInfo((object)("Updated only the terrain delta clamp in Flattenheim." + methodName + "."));
		}
		return list;
	}

	private static bool IsMathfClamp(MethodInfo method)
	{
		if (method == null || method.Name != "Clamp" || method.DeclaringType == null || method.DeclaringType.FullName != "UnityEngine.Mathf")
		{
			return false;
		}
		ParameterInfo[] parameters = method.GetParameters();
		if (parameters.Length == 3 && parameters[0].ParameterType == typeof(float) && parameters[1].ParameterType == typeof(float) && parameters[2].ParameterType == typeof(float))
		{
			return method.ReturnType == typeof(float);
		}
		return false;
	}

	private static bool IsFloatConstant(CodeInstruction instruction, float expected)
	{
		if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float)
		{
			return (float)instruction.operand == expected;
		}
		return false;
	}
}