Decompiled source of ChilloutSeneaLIntegration v1.0.6

plugins/ChilloutSeneaLIntegration/ChilloutSeneaLIntegration.dll

Decompiled 5 hours 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;
using UnityEngine;

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

[BepInPlugin("chillout.seneal.integration", "Chillout SeneaL Integration", "1.0.6")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class Plugin : BaseUnityPlugin
{
	public const string PluginGuid = "chillout.seneal.integration";

	public const string PluginName = "Chillout SeneaL Integration";

	public const string PluginVersion = "1.0.6";

	internal static ManualLogSource PluginLog;

	private Harmony _harmony;

	private void Awake()
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Expected O, but got Unknown
		PluginLog = ((BaseUnityPlugin)this).Logger;
		_harmony = new Harmony("chillout.seneal.integration");
		InstallQuietRulesPatch(_harmony);
		InstallPathRequirementOrderPatch(_harmony);
		InstallPathConsumptionOrderPatch(_harmony);
		InstallEfficientAutoSmelterPatch(_harmony);
		InstallRecipeCacheInvalidationPatch(_harmony);
	}

	private void InstallPathRequirementOrderPatch(Harmony harmony)
	{
		//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Expected O, but got Unknown
		Type type = AccessTools.TypeByName("PassiveTree.Conveniences+Player_HaveRequirementItems");
		Type type2 = AccessTools.TypeByName("SeneaLUI.Patches.StockPatches");
		MethodInfo methodInfo = AccessTools.Method(typeof(Player), "HaveRequirementItems", new Type[4]
		{
			typeof(Recipe),
			typeof(bool),
			typeof(int),
			typeof(int)
		}, (Type[])null);
		MethodInfo methodInfo2 = ((type == null) ? null : AccessTools.Method(type, "Prefix", (Type[])null, (Type[])null));
		MethodInfo methodInfo3 = ((type2 == null) ? null : AccessTools.Method(type2, "HaveRequirementItems", (Type[])null, (Type[])null));
		if (methodInfo == null || methodInfo2 == null || methodInfo3 == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"Path or SeneaL material-check patches were not found; their original order remains active.");
			return;
		}
		Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo);
		bool flag = false;
		bool flag2 = false;
		if (patchInfo != null)
		{
			foreach (Patch prefix in patchInfo.Prefixes)
			{
				if (prefix.PatchMethod == methodInfo2)
				{
					flag = true;
				}
				if (prefix.PatchMethod == methodInfo3)
				{
					flag2 = true;
				}
			}
		}
		if (!flag || !flag2)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"Path and SeneaL material checks are not both installed; their order was not changed.");
			return;
		}
		harmony.Unpatch((MethodBase)methodInfo, methodInfo2);
		HarmonyMethod val = new HarmonyMethod(methodInfo2);
		val.priority = 0;
		val.after = new string[1] { "seneaL.valheim.ui" };
		HarmonyMethod val2 = val;
		harmony.Patch((MethodBase)methodInfo, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"SeneaL now checks inventory and backpack before Path falls back to its authorized nearby chests.");
	}

	private void InstallPathConsumptionOrderPatch(Harmony harmony)
	{
		//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ad: Expected O, but got Unknown
		Type type = AccessTools.TypeByName("PassiveTree.Conveniences+Player_ConsumeResources_Chests");
		Type type2 = AccessTools.TypeByName("SeneaLUI.Patches.StockPatches");
		MethodInfo methodInfo = AccessTools.Method(typeof(Player), "ConsumeResources", new Type[4]
		{
			typeof(Requirement[]),
			typeof(int),
			typeof(int),
			typeof(int)
		}, (Type[])null);
		MethodInfo methodInfo2 = ((type == null) ? null : AccessTools.Method(type, "Prefix", (Type[])null, (Type[])null));
		MethodInfo methodInfo3 = ((type2 == null) ? null : AccessTools.Method(type2, "ConsumeResources", (Type[])null, (Type[])null));
		if (methodInfo == null || methodInfo2 == null || methodInfo3 == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"Path or SeneaL material-consumption patches were not found; their original order remains active.");
			return;
		}
		Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo);
		bool flag = false;
		bool flag2 = false;
		if (patchInfo != null)
		{
			foreach (Patch prefix in patchInfo.Prefixes)
			{
				if (prefix.PatchMethod == methodInfo2)
				{
					flag = true;
				}
				if (prefix.PatchMethod == methodInfo3)
				{
					flag2 = true;
				}
			}
		}
		if (!flag || !flag2)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"Path and SeneaL material consumption are not both installed; their order was not changed.");
			return;
		}
		harmony.Unpatch((MethodBase)methodInfo, methodInfo3);
		HarmonyMethod val = new HarmonyMethod(methodInfo3);
		val.priority = 0;
		val.after = new string[1] { "treextr.pathofvalheiman" };
		HarmonyMethod val2 = val;
		harmony.Patch((MethodBase)methodInfo, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Path records nearby-chest material bills before SeneaL consumes inventory and backpack stock.");
	}

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

	private void InstallQuietRulesPatch(Harmony harmony)
	{
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Expected O, but got Unknown
		Type type = AccessTools.TypeByName("SeneaLUI.Net.PolicyNotice");
		Type type2 = AccessTools.TypeByName("SeneaLUI.Net.Policy");
		Type type3 = AccessTools.TypeByName("SeneaLUI.Net.Policy+Limits");
		if (type == null || type2 == null || type3 == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"SeneaL UI policy types were not found; the patch was not applied.");
			return;
		}
		MethodInfo methodInfo = AccessTools.Method(type, "Check", (Type[])null, (Type[])null);
		QuietRulesPatch.ShownField = AccessTools.Field(type, "_shown");
		QuietRulesPatch.StateProperty = AccessTools.Property(type2, "State");
		QuietRulesPatch.LimitsProperty = AccessTools.Property(type2, "Cur");
		QuietRulesPatch.LockedField = AccessTools.Field(type3, "Locked");
		if (methodInfo == null || QuietRulesPatch.ShownField == null || QuietRulesPatch.StateProperty == null || QuietRulesPatch.LimitsProperty == null || QuietRulesPatch.LockedField == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"SeneaL UI's policy structure has changed; the patch was not applied.");
			return;
		}
		HarmonyMethod val = new HarmonyMethod(typeof(QuietRulesPatch), "Prefix", (Type[])null);
		harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"The routine server-rules summary is hidden; synchronization and critical warnings remain active.");
	}

	private void InstallEfficientAutoSmelterPatch(Harmony harmony)
	{
		//IL_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_015d: Expected O, but got Unknown
		//IL_0173: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Expected O, but got Unknown
		Type type = AccessTools.TypeByName("SeneaLUI.Patches.SmelterPatches");
		Type type2 = AccessTools.TypeByName("Valheiman.Api.Conveniences");
		Type type3 = AccessTools.TypeByName("PassiveTree.Conveniences");
		if (type == null || type2 == null || type3 == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"SeneaL UI or Path of Valheiman autosmelter types were not found; the efficient autosmelter patch was not applied.");
			return;
		}
		MethodInfo methodInfo = AccessTools.Method(type, "Chests", new Type[1] { typeof(Component) }, (Type[])null);
		MethodInfo methodInfo2 = AccessTools.Method(type, "AutoTick", new Type[2]
		{
			typeof(Player),
			typeof(float)
		}, (Type[])null);
		PathAutoSmelterChestsPatch.CraftFromChestsProperty = AccessTools.Property(type2, "CraftFromChests");
		PathAutoSmelterChestsPatch.PathChestsMethod = AccessTools.Method(type3, "Chests", new Type[1] { typeof(Player) }, (Type[])null);
		if (methodInfo == null || methodInfo2 == null || PathAutoSmelterChestsPatch.CraftFromChestsProperty == null || PathAutoSmelterChestsPatch.PathChestsMethod == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"SeneaL UI or Path of Valheiman autosmelter methods have changed; the efficient autosmelter patch was not applied.");
			return;
		}
		harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(PathAutoSmelterChestsPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(AutoSmelterIntervalPatch), "Transpiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Automatic station refilling uses Path-owned nearby storage and a five-second work interval.");
	}

	private void InstallRecipeCacheInvalidationPatch(Harmony harmony)
	{
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Expected O, but got Unknown
		Type type = AccessTools.TypeByName("SeneaLUI.Inv.CraftView");
		RecipeCacheInvalidationPatch.DirtyField = ((type == null) ? null : AccessTools.Field(type, "Dirty"));
		MethodInfo methodInfo = AccessTools.Method(typeof(Player), "Load", new Type[1] { typeof(ZPackage) }, (Type[])null);
		MethodInfo methodInfo2 = AccessTools.Method(typeof(Player), "UpdateKnownRecipesList", Type.EmptyTypes, (Type[])null);
		if (RecipeCacheInvalidationPatch.DirtyField == null || RecipeCacheInvalidationPatch.DirtyField.FieldType != typeof(bool) || !RecipeCacheInvalidationPatch.DirtyField.IsStatic || methodInfo == null || methodInfo2 == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"SeneaL UI's crafting cache or Valheim's recipe events changed; the recipe-display refresh patch was not applied.");
			return;
		}
		HarmonyMethod val = new HarmonyMethod(typeof(RecipeCacheInvalidationPatch), "Postfix", (Type[])null);
		harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"SeneaL's crafting list refreshes after character recipe state changes.");
	}
}
internal static class RecipeCacheInvalidationPatch
{
	internal static FieldInfo DirtyField;

	private static bool _failed;

	public static void Postfix()
	{
		if (_failed || DirtyField == null)
		{
			return;
		}
		try
		{
			DirtyField.SetValue(null, true);
		}
		catch (Exception ex)
		{
			_failed = true;
			Plugin.PluginLog.LogError((object)("SeneaL's crafting cache could not be invalidated; its original behavior remains active: " + ex));
		}
	}
}
internal static class QuietRulesPatch
{
	internal static FieldInfo ShownField;

	internal static PropertyInfo StateProperty;

	internal static PropertyInfo LimitsProperty;

	internal static FieldInfo LockedField;

	private static bool _logged;

	public static bool Prefix()
	{
		try
		{
			object value = StateProperty.GetValue(null, null);
			if (value == null || !string.Equals(value.ToString(), "Server", StringComparison.Ordinal))
			{
				return true;
			}
			object value2 = LimitsProperty.GetValue(null, null);
			if (value2 == null)
			{
				return true;
			}
			object value3 = LockedField.GetValue(value2);
			if (value3 is bool && (bool)value3)
			{
				return true;
			}
			ShownField.SetValue(null, true);
			if (!_logged)
			{
				Plugin.PluginLog.LogInfo((object)"Valid server rules received; only the repetitive informational dialog was skipped.");
				_logged = true;
			}
			return false;
		}
		catch (Exception ex)
		{
			Plugin.PluginLog.LogError((object)("The rules notice could not be evaluated; SeneaL UI will keep its normal behavior: " + ex));
			return true;
		}
	}
}
internal static class PathAutoSmelterChestsPatch
{
	internal static PropertyInfo CraftFromChestsProperty;

	internal static MethodInfo PathChestsMethod;

	private static bool _logged;

	private static bool _failed;

	public static bool Prefix(ref List<Container> __result)
	{
		if (_failed || (Object)(object)Player.m_localPlayer == (Object)null)
		{
			return true;
		}
		try
		{
			if (!(bool)CraftFromChestsProperty.GetValue(null, null))
			{
				return true;
			}
			if (!(PathChestsMethod.Invoke(null, new object[1] { Player.m_localPlayer }) is List<Container> list))
			{
				return true;
			}
			__result = list;
			if (!_logged)
			{
				Plugin.PluginLog.LogInfo((object)"Automatic stations are drawing from Path's cached, accessible nearby containers.");
				_logged = true;
			}
			return false;
		}
		catch (Exception ex)
		{
			_failed = true;
			Plugin.PluginLog.LogError((object)("Path's nearby containers could not be supplied to automatic stations; SeneaL will keep its original behavior: " + ex));
			return true;
		}
	}
}
internal static class AutoSmelterIntervalPatch
{
	internal const float OriginalIntervalSeconds = 1.5f;

	internal const float EfficientIntervalSeconds = 5f;

	public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		List<CodeInstruction> list = new List<CodeInstruction>(instructions);
		List<int> list2 = new List<int>();
		for (int i = 0; i < list.Count; i++)
		{
			object operand = list[i].operand;
			if (list[i].opcode == OpCodes.Ldc_R4 && operand is float && Math.Abs((float)operand - 1.5f) < 0.0001f)
			{
				list2.Add(i);
			}
		}
		if (list2.Count != 1)
		{
			Plugin.PluginLog.LogError((object)"SeneaL UI's automatic-refill interval structure changed; the original interval remains active.");
			return list;
		}
		list[list2[0]].operand = 5f;
		return list;
	}
}