Decompiled source of NoLossyCookingStations v1.1.0

NoLossyCookingStations.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
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: AssemblyTitle("NoLossyCookingStations")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Riintouge")]
[assembly: AssemblyProduct("NoLossyCookingStations")]
[assembly: AssemblyCopyright("Copyright © 2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e41966f3-8caf-49e5-b87d-ea41867f24e4")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.1.0.0")]
namespace NoLossyCookingStations;

[BepInPlugin("com.riintouge.nolossycookingstations", "No Lossy Cooking Stations", "1.0.1")]
[BepInProcess("valheim.exe")]
public class NoLossyCookingStations : BaseUnityPlugin
{
	internal class Common
	{
		private const double NetworkClaimDelay = 0.5;

		private const double NetworkOwnershipDelay = 0.1;

		private const double DelayFudgeFactor = 0.01;

		public static bool? SanityCheckInteraction(ZNetView netView, ref bool result, ref double rateLimitTimeout)
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			if (!IsEnabled.Value)
			{
				return true;
			}
			if (Time.timeAsDouble < rateLimitTimeout)
			{
				result = false;
				return false;
			}
			if (!netView.HasOwner() || netView.IsOwner())
			{
				rateLimitTimeout = Time.timeAsDouble + 0.1;
				return true;
			}
			rateLimitTimeout = Time.timeAsDouble + 0.5;
			long num = ((ZDOID)(ref netView.GetZDO().m_uid)).ID;
			netView.ClaimOwnership();
			ZDOMan.instance.ForceSendZDO(num, netView.GetZDO().m_uid);
			result = false;
			return null;
		}

		public static IEnumerator DelayedInteraction<T>(WeakReference<Humanoid> userReference, WeakReference<T> interactableReference, string methodName, params WeakReference<object>[] argReferences) where T : MonoBehaviour
		{
			yield return (object)new WaitForSecondsRealtime(0.51f);
			Humanoid target = null;
			if (!interactableReference.TryGetTarget(out var target2) || !((Object)(object)target2 != (Object)null) || (userReference != null && !userReference.TryGetTarget(out target)))
			{
				yield break;
			}
			object[] array = new object[argReferences.Length];
			for (int i = 0; i < argReferences.Length; i++)
			{
				argReferences[i].TryGetTarget(out array[i]);
			}
			if (Traverse.Create((object)target2).Method(methodName, array).GetValue<bool>(array) && (Object)(object)target != (Object)null)
			{
				ZSyncAnimation value = Traverse.Create((object)target).Field("m_zanim").GetValue<ZSyncAnimation>();
				if (value != null)
				{
					value.SetTrigger("interact");
				}
			}
		}
	}

	[HarmonyPatch(typeof(CookingStation))]
	private class CookingStationPatch
	{
		private static double RateLimitTimeout;

		[HarmonyPatch("CookItem")]
		[HarmonyPrefix]
		private static bool CookItemPrefix(ref CookingStation __instance, ref ZNetView ___m_nview, ref bool __result, ref Humanoid user)
		{
			bool? flag = Common.SanityCheckInteraction(___m_nview, ref __result, ref RateLimitTimeout);
			if (flag.HasValue)
			{
				return flag == true;
			}
			((MonoBehaviour)__instance).StartCoroutine(Common.DelayedInteraction<CookingStation>(new WeakReference<Humanoid>(user), new WeakReference<CookingStation>(__instance), "OnInteract", new WeakReference<object>[1]
			{
				new WeakReference<object>(user)
			}));
			return false;
		}

		[HarmonyPatch("RPC_AddItem")]
		[HarmonyPrefix]
		private static bool RPC_AddItemPrefix(ref CookingStation __instance, ref ZNetView ___m_nview, ref long sender, ref string itemName)
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			if (!IsEnabled.Value || !___m_nview.IsOwner())
			{
				return true;
			}
			bool value = Traverse.Create((object)__instance).Method("IsItemAllowed", new Type[1] { typeof(string) }, (object[])null).GetValue<bool>(new object[1] { itemName });
			int value2 = Traverse.Create((object)__instance).Method("GetFreeSlot", Array.Empty<object>()).GetValue<int>();
			if (!value || value2 != -1)
			{
				return true;
			}
			long derefSender = sender;
			PlayerInfo val = ((IEnumerable<PlayerInfo>)ZNet.instance.GetPlayerList()).FirstOrDefault((Func<PlayerInfo, bool>)((PlayerInfo x) => derefSender == ((ZDOID)(ref x.m_characterID)).ID));
			Traverse.Create((object)__instance).Method("SpawnItem", new Type[3]
			{
				typeof(string),
				typeof(int),
				typeof(Vector3)
			}, (object[])null).GetValue(new object[3]
			{
				itemName,
				__instance.m_slots.Length - 1,
				val.m_position
			});
			return false;
		}
	}

	[HarmonyPatch(typeof(Fermenter))]
	private class FermenterPatch
	{
		private static double RateLimitTimeout;

		[HarmonyPatch("Interact")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> InteractTranspiler(IEnumerable<CodeInstruction> instructionsIn)
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructionsIn);
			for (int i = 0; i + 1 < list.Count; i++)
			{
				if (list[i].opcode == OpCodes.Call && list[i + 1].opcode == OpCodes.Pop)
				{
					MethodInfo methodInfo = (MethodInfo)list[i].operand;
					if (methodInfo.DeclaringType == typeof(Fermenter) && methodInfo.Name.CompareTo("AddItem") == 0 && methodInfo.ReturnType == typeof(bool))
					{
						list[i + 1] = new CodeInstruction(OpCodes.Ret, (object)null);
						break;
					}
				}
			}
			return list;
		}

		[HarmonyPatch("AddItem")]
		[HarmonyPrefix]
		private static bool AddItemPrefix(ref Fermenter __instance, ref ZNetView ___m_nview, ref bool __result, ref Humanoid user, ref ItemData item)
		{
			bool? flag = Common.SanityCheckInteraction(___m_nview, ref __result, ref RateLimitTimeout);
			if (flag.HasValue)
			{
				return flag == true;
			}
			((MonoBehaviour)__instance).StartCoroutine(Common.DelayedInteraction<Fermenter>(new WeakReference<Humanoid>(user), new WeakReference<Fermenter>(__instance), "AddItem", new WeakReference<object>[2]
			{
				new WeakReference<object>(user),
				new WeakReference<object>(item)
			}));
			return false;
		}

		[HarmonyPatch("RPC_AddItem")]
		[HarmonyPrefix]
		private static bool RPC_AddItemPrefix(ref Fermenter __instance, ref ZNetView ___m_nview, ref string name)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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)
			if (!IsEnabled.Value || !___m_nview.IsOwner())
			{
				return true;
			}
			bool value = Traverse.Create((object)__instance).Method("IsItemAllowed", new Type[1] { typeof(string) }, (object[])null).GetValue<bool>(new object[1] { name });
			string value2 = Traverse.Create((object)__instance).Method("GetContent", Array.Empty<object>()).GetValue<string>();
			if (value && !Utility.IsNullOrWhiteSpace(value2))
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(name);
				Vector3 val = __instance.m_outputPoint.position + Vector3.up;
				Object.Instantiate<GameObject>(itemPrefab, val, Quaternion.identity);
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Smelter))]
	private class SmelterPatch
	{
		private static double RateLimitTimeout;

		[HarmonyPatch("OnAddFuel")]
		[HarmonyPrefix]
		private static bool OnAddFuelPrefix(ref Smelter __instance, ref ZNetView ___m_nview, ref bool __result, ref Switch sw, ref Humanoid user, ref ItemData item)
		{
			bool? flag = Common.SanityCheckInteraction(___m_nview, ref __result, ref RateLimitTimeout);
			if (flag.HasValue)
			{
				return flag == true;
			}
			((MonoBehaviour)__instance).StartCoroutine(Common.DelayedInteraction<Smelter>(new WeakReference<Humanoid>(user), new WeakReference<Smelter>(__instance), "OnAddFuel", new WeakReference<object>[3]
			{
				new WeakReference<object>(sw),
				new WeakReference<object>(user),
				new WeakReference<object>(item)
			}));
			return false;
		}

		[HarmonyPatch("OnAddOre")]
		[HarmonyPrefix]
		private static bool OnAddOrePrefix(ref Smelter __instance, ref ZNetView ___m_nview, ref bool __result, ref Switch sw, ref Humanoid user, ref ItemData item)
		{
			bool? flag = Common.SanityCheckInteraction(___m_nview, ref __result, ref RateLimitTimeout);
			if (flag.HasValue)
			{
				return flag == true;
			}
			((MonoBehaviour)__instance).StartCoroutine(Common.DelayedInteraction<Smelter>(new WeakReference<Humanoid>(user), new WeakReference<Smelter>(__instance), "OnAddOre", new WeakReference<object>[3]
			{
				new WeakReference<object>(sw),
				new WeakReference<object>(user),
				new WeakReference<object>(item)
			}));
			return false;
		}

		[HarmonyPatch("RPC_AddFuel")]
		[HarmonyPrefix]
		private static bool RPC_AddFuelPrefix(ref Smelter __instance, ref ZNetView ___m_nview, ref int ___m_maxFuel, ref ItemDrop ___m_fuelItem, ref long sender)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			if (!IsEnabled.Value || !___m_nview.IsOwner())
			{
				return true;
			}
			if (Traverse.Create((object)__instance).Method("GetFuel", Array.Empty<object>()).GetValue<float>() > (float)(___m_maxFuel - 1))
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(___m_fuelItem.m_itemData.m_shared);
				Vector3 val = __instance.m_outputPoint.position + Vector3.up;
				Object.Instantiate<GameObject>(itemPrefab, val, Quaternion.identity);
				return false;
			}
			return true;
		}

		[HarmonyPatch("RPC_AddOre")]
		[HarmonyPrefix]
		private static bool RPC_AddOrePrefix(ref Smelter __instance, ref ZNetView ___m_nview, ref int ___m_maxOre, ref long sender, ref string name)
		{
			//IL_004c: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			if (!IsEnabled.Value || !___m_nview.IsOwner())
			{
				return true;
			}
			if ((float)Traverse.Create((object)__instance).Method("GetQueueSize", Array.Empty<object>()).GetValue<int>() > (float)___m_maxOre)
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(name);
				Vector3 val = __instance.m_outputPoint.position + Vector3.up;
				Object.Instantiate<GameObject>(itemPrefab, val, Quaternion.identity);
				return false;
			}
			return true;
		}
	}

	public static ConfigEntry<bool> IsEnabled;

	public static ConfigEntry<bool> LoadOnStart;

	private readonly Harmony Harmony = new Harmony("com.riintouge.nolossycookingstations");

	private void Awake()
	{
		IsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Core", "Enable", true, "Whether this plugin has any effect when loaded.");
		LoadOnStart = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Core", "LoadOnStart", true, "Whether this plugin loads on game start.");
		if (LoadOnStart.Value)
		{
			Harmony.PatchAll();
		}
	}
}