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();
}
}
}