Decompiled source of FrelsiBuildCameraCompat v0.1.0

plugins\FrelsiBuildCameraCompat\FrelsiBuildCameraCompat.dll

Decompiled a day ago
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using HarmonyLib;
using UnityEngine;

[assembly: AssemblyDescription("Compatibility bridge between Frelsi Hammer and BuildCameraCHE 1.3.3")]
[assembly: AssemblyCompany("Daishi11")]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyTitle("FrelsiBuildCameraCompat")]
[assembly: AssemblyProduct("FrelsiBuildCameraCompat")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("0.1.0.0")]
namespace Daishi11.FrelsiBuildCameraCompat;

[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("daishi11.valheim.frelsibuildcameracompat", "Frelsi Hammer BuildCamera Compat", "0.1.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class Plugin : BaseUnityPlugin
{
	public const string PluginGuid = "daishi11.valheim.frelsibuildcameracompat";

	public const string PluginName = "Frelsi Hammer BuildCamera Compat";

	public const string PluginVersion = "0.1.0";

	private const string BuildCameraGuid = "Azumatt.BuildCameraCHE";

	private const string FrelsiGuid = "com.zeecamelsnake.frelsihammer";

	private const string SupportedBuildCameraVersion = "1.3.3";

	private Harmony harmony;

	private static Type buildCameraUtilsType;

	private static Type buildCameraPluginType;

	private static FieldInfo buildCameraActiveField;

	private static FieldInfo distanceFromWorkbenchField;

	private static FieldInfo cameraRangeMultiplierField;

	private static bool insideEnableBuildMode;

	private static bool lookupBypassedDuringEnable;

	private static bool stationlessCameraActive;

	private static Vector3 stationlessAnchor;

	private void Awake()
	{
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Expected O, but got Unknown
		try
		{
			Version pluginVersion = GetPluginVersion("Azumatt.BuildCameraCHE");
			Version pluginVersion2 = GetPluginVersion("com.zeecamelsnake.frelsihammer");
			if (pluginVersion == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"BuildCameraCHE is not loaded. Compat disabled.");
				return;
			}
			if (pluginVersion2 == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Frelsi Hammer is not loaded. Compat disabled.");
				return;
			}
			if (!string.Equals(pluginVersion.ToString(), "1.3.3", StringComparison.Ordinal))
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Concat("Unsupported BuildCameraCHE version ", pluginVersion, ". This compat was written for 1.3.3 and will not patch an unknown version."));
				return;
			}
			ResolveBuildCameraRuntime();
			harmony = new Harmony("daishi11.valheim.frelsibuildcameracompat");
			PatchBuildCamera();
			((BaseUnityPlugin)this).Logger.LogInfo((object)string.Concat("Frelsi/BuildCamera compatibility active. BuildCameraCHE ", pluginVersion, ", Frelsi Hammer ", pluginVersion2, "."));
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Failed to initialize Frelsi/BuildCamera compatibility: " + ex));
		}
	}

	private void OnDestroy()
	{
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		ResetStationlessState();
	}

	private static Version GetPluginVersion(string guid)
	{
		if (!Chainloader.PluginInfos.TryGetValue(guid, out var value) || value == null || value.Metadata == null)
		{
			return null;
		}
		return value.Metadata.Version;
	}

	private static void ResolveBuildCameraRuntime()
	{
		buildCameraUtilsType = AccessTools.TypeByName("Valheim_Build_Camera.Utils");
		buildCameraPluginType = AccessTools.TypeByName("Valheim_Build_Camera.Valheim_Build_CameraPlugin");
		if (buildCameraUtilsType == null)
		{
			throw new MissingMemberException("Valheim_Build_Camera.Utils was not found.");
		}
		if (buildCameraPluginType == null)
		{
			throw new MissingMemberException("Valheim_Build_Camera.Valheim_Build_CameraPlugin was not found.");
		}
		buildCameraActiveField = RequireField(buildCameraPluginType, "BuildCameraActive");
		distanceFromWorkbenchField = RequireField(buildCameraPluginType, "distanceCanBuildFromWorkbench");
		cameraRangeMultiplierField = RequireField(buildCameraPluginType, "cameraRangeMultiplier");
	}

	private void PatchBuildCamera()
	{
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Expected O, but got Unknown
		//IL_0081: 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_00a3: Expected O, but got Unknown
		//IL_00a3: Expected O, but got Unknown
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Expected O, but got Unknown
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Expected O, but got Unknown
		MethodInfo methodInfo = RequireMethod(buildCameraUtilsType, "TryFindCameraStation", 2);
		MethodInfo methodInfo2 = RequireMethod(buildCameraUtilsType, "EnableBuildMode", 0);
		MethodInfo methodInfo3 = RequireMethod(buildCameraUtilsType, "DisableBuildMode", 0);
		MethodInfo methodInfo4 = RequireMethod(buildCameraUtilsType, "ClampToStationRange", 1);
		harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "TryFindCameraStationPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(Plugin), "EnableBuildModePrefix", (Type[])null), new HarmonyMethod(typeof(Plugin), "EnableBuildModePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "DisableBuildModePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		harmony.Patch((MethodBase)methodInfo4, new HarmonyMethod(typeof(Plugin), "ClampToStationRangePrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
	}

	private static MethodInfo RequireMethod(Type type, string name, int parameterCount)
	{
		MethodInfo methodInfo = null;
		MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (MethodInfo methodInfo2 in methods)
		{
			if (!(methodInfo2.Name != name) && methodInfo2.GetParameters().Length == parameterCount)
			{
				if (methodInfo != null)
				{
					throw new AmbiguousMatchException("Multiple BuildCamera methods matched " + name + " with " + parameterCount + " parameters.");
				}
				methodInfo = methodInfo2;
			}
		}
		if (methodInfo == null)
		{
			throw new MissingMethodException(type.FullName, name);
		}
		return methodInfo;
	}

	private static FieldInfo RequireField(Type type, string name)
	{
		FieldInfo field = type.GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		if (field == null)
		{
			throw new MissingFieldException(type.FullName, name);
		}
		return field;
	}

	private static void TryFindCameraStationPostfix(ref bool __result, ref CraftingStation __1)
	{
		if (!__result)
		{
			__result = true;
			__1 = null;
			if (insideEnableBuildMode)
			{
				lookupBypassedDuringEnable = true;
			}
		}
	}

	private static void EnableBuildModePrefix()
	{
		insideEnableBuildMode = true;
		lookupBypassedDuringEnable = false;
		stationlessCameraActive = false;
	}

	private static void EnableBuildModePostfix()
	{
		//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_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		insideEnableBuildMode = false;
		if (lookupBypassedDuringEnable && IsBuildCameraActive() && Object.op_Implicit((Object)(object)Player.m_localPlayer))
		{
			stationlessCameraActive = true;
			if (Object.op_Implicit((Object)(object)GameCamera.instance))
			{
				stationlessAnchor = ((Component)GameCamera.instance).transform.position;
			}
			else
			{
				stationlessAnchor = ((Component)Player.m_localPlayer).transform.position;
			}
		}
	}

	private static void DisableBuildModePostfix()
	{
		ResetStationlessState();
	}

	private static bool ClampToStationRangePrefix(Vector3 __0, ref Vector3 __result)
	{
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: 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_0096: Unknown result type (might be due to invalid IL or missing references)
		//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_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		if (!stationlessCameraActive || !IsBuildCameraActive())
		{
			return true;
		}
		float num = ReadConfigFloat(distanceFromWorkbenchField, 100f);
		float num2 = ReadConfigFloat(cameraRangeMultiplierField, 1f);
		float num3 = Mathf.Max(0f, num) * Mathf.Max(0f, num2);
		if (num3 <= 0f)
		{
			__result = stationlessAnchor;
			return false;
		}
		Vector3 val = __0 - stationlessAnchor;
		float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
		float num4 = num3 * num3;
		if (sqrMagnitude <= num4)
		{
			__result = __0;
			return false;
		}
		__result = stationlessAnchor + val * (num3 / Mathf.Sqrt(sqrMagnitude));
		return false;
	}

	private static bool IsBuildCameraActive()
	{
		if (buildCameraActiveField == null)
		{
			return false;
		}
		object value = buildCameraActiveField.GetValue(null);
		if (value is bool)
		{
			return (bool)value;
		}
		return false;
	}

	private static float ReadConfigFloat(FieldInfo field, float fallback)
	{
		if (field == null)
		{
			return fallback;
		}
		object value = field.GetValue(null);
		if (value == null)
		{
			return fallback;
		}
		PropertyInfo property = value.GetType().GetProperty("Value", BindingFlags.Instance | BindingFlags.Public);
		if (property == null)
		{
			return fallback;
		}
		object value2 = property.GetValue(value, null);
		if (value2 == null)
		{
			return fallback;
		}
		try
		{
			return Convert.ToSingle(value2);
		}
		catch
		{
			return fallback;
		}
	}

	private static void ResetStationlessState()
	{
		//IL_0012: 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)
		insideEnableBuildMode = false;
		lookupBypassedDuringEnable = false;
		stationlessCameraActive = false;
		stationlessAnchor = Vector3.zero;
	}
}