Decompiled source of Cooked Clean v1.1.0

tony4twentys-Cooked Clean.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyTitle("Cooked Clean")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Cooked Clean")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("9ef79194-5328-4415-9481-0fda8c5fd49a")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace CookedClean
{
	internal static class CookedCleanDataEntryKey
	{
		public static readonly DataEntryKey CookedPositiveEffect = (DataEntryKey)161;
	}
	[BepInPlugin("tony4twents.CookedClean", "Cooked Clean", "1.1.0")]
	[BepInProcess("PEAK.exe")]
	public class CookedCleanPlugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(ItemCooking), "UpdateCookedBehavior")]
		private static class ItemCooking_UpdateCookedBehavior_Patch
		{
			private static void Postfix(ItemCooking __instance)
			{
				try
				{
					if (!((Object)(object)__instance == (Object)null) && Object.op_Implicit((Object)(object)((ItemComponent)__instance).item))
					{
						ApplyClean(((ItemComponent)__instance).item);
					}
				}
				catch (Exception ex)
				{
					LogOnce(ref _loggedCookError, "[Cooked Clean] UpdateCookedBehavior postfix failed.", ex);
				}
			}
		}

		[HarmonyPatch(typeof(Action_InflictPoison), "RunAction")]
		private static class Action_InflictPoison_RunAction_Patch
		{
			private static bool Prefix(Action_InflictPoison __instance)
			{
				try
				{
					if ((Object)(object)__instance != (Object)null && IsCooked(((ItemActionBase)__instance).item))
					{
						Log.LogInfo((object)("Blocked cooked poison inflict on " + ((Object)((ItemActionBase)__instance).item).name));
						return false;
					}
				}
				catch (Exception ex)
				{
					LogOnce(ref _loggedInflictSkipError, "[Cooked Clean] InflictPoison skip failed.", ex);
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Action_RandomMushroomEffect), "RunRandomEffect")]
		private static class Action_RandomMushroomEffect_RunRandomEffect_Patch
		{
			private static void Prefix(Action_RandomMushroomEffect __instance, ref int effect)
			{
				try
				{
					Item item = (((Object)(object)__instance != (Object)null) ? ((ItemActionBase)__instance).item : null);
					if (!IsCooked(item))
					{
						return;
					}
					if (TryGetStoredPositiveEffect(item, out var effect2))
					{
						effect = effect2;
						return;
					}
					int viewId = GetViewId(item);
					if (viewId > 0 && (Object)(object)CookedCleanNet.Instance != (Object)null && CookedCleanNet.Instance.TryGetRemembered(viewId, out effect2))
					{
						effect = effect2;
					}
					else
					{
						effect = RemapToGood(effect);
					}
				}
				catch (Exception ex)
				{
					LogOnce(ref _loggedShroomError, "[Cooked Clean] Shroomberry effect override failed.", ex);
				}
			}
		}

		public const string PluginGuid = "tony4twents.CookedClean";

		public const string PluginName = "Cooked Clean";

		public const string PluginVersion = "1.1.0";

		internal const byte EventCode = 161;

		internal const int ProtocolVersion = 1;

		internal const string EventMagic = "tony4twents.CookedClean";

		private static Harmony _harmony;

		internal static ManualLogSource Log;

		private static bool _loggedCookError;

		private static bool _loggedInflictSkipError;

		private static bool _loggedShroomError;

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			_harmony = new Harmony("tony4twents.CookedClean");
			_harmony.PatchAll();
			CookedCleanNet.Ensure();
			SceneManager.sceneLoaded += OnSceneLoaded;
			Log.LogInfo((object)("Loaded v1.1.0 — poison mushrooms + cooked shroomberry good effects, Photon " + (byte)161 + "."));
		}

		private void OnDestroy()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			CookedCleanNet.Ensure();
		}

		internal static bool IsCooked(Item item)
		{
			if (!Object.op_Implicit((Object)(object)item))
			{
				return false;
			}
			if (!item.HasData((DataEntryKey)1))
			{
				return false;
			}
			return item.GetData<IntItemData>((DataEntryKey)1).Value > 0;
		}

		internal static void ApplyClean(Item item)
		{
			if (Object.op_Implicit((Object)(object)item) && IsCooked(item))
			{
				Action_InflictPoison component = ((Component)item).GetComponent<Action_InflictPoison>();
				if ((Object)(object)component != (Object)null && ((Behaviour)component).enabled)
				{
					((Behaviour)component).enabled = false;
					Log.LogInfo((object)("Disabled Action_InflictPoison on cooked " + ((Object)item).name));
				}
				EnsureCookedShroomberryEffect(item);
			}
		}

		internal static void EnsureCookedShroomberryEffect(Item item)
		{
			if (!Object.op_Implicit((Object)(object)item))
			{
				return;
			}
			Action_RandomMushroomEffect component = ((Component)item).GetComponent<Action_RandomMushroomEffect>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			if (TryGetStoredPositiveEffect(item, out var effect))
			{
				RememberAndMaybeBroadcast(item, effect, broadcast: false);
				return;
			}
			int viewId = GetViewId(item);
			if (viewId > 0 && (Object)(object)CookedCleanNet.Instance != (Object)null && CookedCleanNet.Instance.TryGetRemembered(viewId, out effect))
			{
				StorePositiveEffect(item, effect, broadcast: false);
				return;
			}
			if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient)
			{
				CookedCleanNet.RequestSync();
				return;
			}
			int num = ChooseGoodEffect(component);
			if (num < 0)
			{
				Log.LogWarning((object)("Failed to choose a good shroomberry effect for " + ((Object)item).name));
				return;
			}
			StorePositiveEffect(item, num, broadcast: true);
			Log.LogInfo((object)("Cooked shroomberry " + ((Object)item).name + " locked to good effect " + num));
		}

		internal static void StorePositiveEffect(Item item, int effect, bool broadcast)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)item))
			{
				effect = Mathf.Clamp(effect, 0, 4);
				try
				{
					item.GetData<IntItemData>(CookedCleanDataEntryKey.CookedPositiveEffect).Value = effect;
				}
				catch (Exception ex)
				{
					Log.LogWarning((object)("Failed to store cooked shroomberry effect: " + ex.Message));
				}
				RememberAndMaybeBroadcast(item, effect, broadcast);
			}
		}

		internal static bool TryGetStoredPositiveEffect(Item item, out int effect)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			effect = -1;
			if (!Object.op_Implicit((Object)(object)item) || !item.HasData(CookedCleanDataEntryKey.CookedPositiveEffect))
			{
				return false;
			}
			effect = item.GetData<IntItemData>(CookedCleanDataEntryKey.CookedPositiveEffect).Value;
			if (effect >= 0)
			{
				return effect <= 4;
			}
			return false;
		}

		private static void RememberAndMaybeBroadcast(Item item, int effect, bool broadcast)
		{
			int viewId = GetViewId(item);
			if (viewId > 0 && !((Object)(object)CookedCleanNet.Instance == (Object)null))
			{
				CookedCleanNet.Instance.Remember(viewId, effect);
				if (broadcast && PhotonNetwork.IsMasterClient)
				{
					CookedCleanNet.Instance.BroadcastEffect(viewId, effect);
				}
			}
		}

		private static int ChooseGoodEffect(Action_RandomMushroomEffect component)
		{
			int num = ReadVanillaEffect(component);
			if (IsGoodEffect(num))
			{
				return num;
			}
			int[] goodEffects = Action_RandomMushroomEffect.GoodEffects;
			if (goodEffects != null && goodEffects.Length != 0)
			{
				return goodEffects[Random.Range(0, goodEffects.Length)];
			}
			if (num >= 5)
			{
				return num % 5;
			}
			return -1;
		}

		private static int ReadVanillaEffect(Action_RandomMushroomEffect component)
		{
			MushroomManager instance = MushroomManager.instance;
			if ((Object)(object)instance == (Object)null || instance.mushroomEffects == null || instance.mushroomEffects.Length == 0)
			{
				return -1;
			}
			int num = Mathf.Abs(component.mushroomTypeIndex) % instance.mushroomEffects.Length;
			return instance.mushroomEffects[num];
		}

		internal static bool IsGoodEffect(int effect)
		{
			int[] goodEffects = Action_RandomMushroomEffect.GoodEffects;
			if (goodEffects == null)
			{
				if (effect >= 0)
				{
					return effect <= 4;
				}
				return false;
			}
			for (int i = 0; i < goodEffects.Length; i++)
			{
				if (goodEffects[i] == effect)
				{
					return true;
				}
			}
			return false;
		}

		internal static int RemapToGood(int effect)
		{
			if (IsGoodEffect(effect))
			{
				return effect;
			}
			if (effect < 0)
			{
				return 0;
			}
			return effect % 5;
		}

		internal static int GetViewId(Item item)
		{
			if (!Object.op_Implicit((Object)(object)item))
			{
				return 0;
			}
			try
			{
				PhotonView photonView = ((MonoBehaviourPun)item).photonView;
				if ((Object)(object)photonView != (Object)null)
				{
					return photonView.ViewID;
				}
			}
			catch
			{
			}
			PhotonView component = ((Component)item).GetComponent<PhotonView>();
			if (!((Object)(object)component != (Object)null))
			{
				return 0;
			}
			return component.ViewID;
		}

		internal static void LogOnce(ref bool logged, string message, Exception ex)
		{
			if (!logged)
			{
				logged = true;
				Log.LogError((object)(message + " " + ex.Message));
			}
		}
	}
	internal sealed class CookedCleanNet : MonoBehaviourPunCallbacks, IOnEventCallback
	{
		internal const byte SubEffect = 1;

		internal const byte SubRequest = 2;

		internal const byte SubSnapshot = 3;

		private readonly Dictionary<int, int> _effectByViewId = new Dictionary<int, int>();

		internal static CookedCleanNet Instance { get; private set; }

		internal static void Ensure()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if ((Object)(object)Instance != (Object)null)
			{
				return;
			}
			GameObject val = new GameObject("CookedClean_Net");
			Object.DontDestroyOnLoad((Object)val);
			Instance = val.AddComponent<CookedCleanNet>();
			try
			{
				if (PhotonNetwork.InRoom)
				{
					Instance.HandleJoinedRoom();
				}
			}
			catch
			{
			}
		}

		public override void OnEnable()
		{
			((MonoBehaviourPunCallbacks)this).OnEnable();
			PhotonNetwork.AddCallbackTarget((object)this);
		}

		public override void OnDisable()
		{
			PhotonNetwork.RemoveCallbackTarget((object)this);
			((MonoBehaviourPunCallbacks)this).OnDisable();
		}

		public override void OnJoinedRoom()
		{
			HandleJoinedRoom();
		}

		public override void OnLeftRoom()
		{
			_effectByViewId.Clear();
		}

		public override void OnPlayerEnteredRoom(Player newPlayer)
		{
			if (PhotonNetwork.IsMasterClient)
			{
				((MonoBehaviour)this).StartCoroutine(BroadcastAfterJoin());
			}
		}

		public void OnEvent(EventData photonEvent)
		{
			if (photonEvent == null || photonEvent.Code != 161 || !(photonEvent.CustomData is object[] array) || array.Length < 3 || !(array[0] is string text) || text != "tony4twents.CookedClean" || ToInt(array[1]) != 1)
			{
				return;
			}
			byte b = ToByte(array[2]);
			if (b == 2 && PhotonNetwork.IsMasterClient)
			{
				BroadcastSnapshot();
			}
			else
			{
				if (PhotonNetwork.IsMasterClient)
				{
					return;
				}
				if (b == 1 && array.Length >= 5)
				{
					ApplyRemote(ToInt(array[3]), ToInt(array[4]));
				}
				else
				{
					if (b != 3 || array.Length < 5)
					{
						return;
					}
					int[] array2 = array[3] as int[];
					int[] array3 = array[4] as int[];
					if (array2 != null && array3 != null && array2.Length == array3.Length)
					{
						for (int i = 0; i < array2.Length; i++)
						{
							ApplyRemote(array2[i], array3[i]);
						}
					}
				}
			}
		}

		internal void Remember(int viewId, int effect)
		{
			if (viewId > 0)
			{
				_effectByViewId[viewId] = effect;
			}
		}

		internal bool TryGetRemembered(int viewId, out int effect)
		{
			return _effectByViewId.TryGetValue(viewId, out effect);
		}

		internal void BroadcastEffect(int viewId, int effect)
		{
			Remember(viewId, effect);
			if (PhotonNetwork.InRoom)
			{
				Raise((ReceiverGroup)0, 1, viewId, effect);
			}
		}

		internal static void RequestSync()
		{
			if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient)
			{
				Raise((ReceiverGroup)2, 2);
			}
		}

		private void HandleJoinedRoom()
		{
			if (!PhotonNetwork.IsMasterClient)
			{
				RequestSync();
			}
		}

		private void BroadcastSnapshot()
		{
			if (_effectByViewId.Count == 0)
			{
				return;
			}
			int[] array = new int[_effectByViewId.Count];
			int[] array2 = new int[_effectByViewId.Count];
			int num = 0;
			foreach (KeyValuePair<int, int> item in _effectByViewId)
			{
				array[num] = item.Key;
				array2[num] = item.Value;
				num++;
			}
			Raise((ReceiverGroup)0, 3, array, array2);
		}

		private IEnumerator BroadcastAfterJoin()
		{
			yield return (object)new WaitForSeconds(0.5f);
			BroadcastSnapshot();
		}

		private static void Raise(ReceiverGroup group, byte sub, params object[] extra)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			object[] array = new object[3 + extra.Length];
			array[0] = "tony4twents.CookedClean";
			array[1] = 1;
			array[2] = sub;
			for (int i = 0; i < extra.Length; i++)
			{
				array[3 + i] = extra[i];
			}
			try
			{
				PhotonNetwork.RaiseEvent((byte)161, (object)array, new RaiseEventOptions
				{
					Receivers = group
				}, SendOptions.SendReliable);
			}
			catch (Exception ex)
			{
				ManualLogSource log = CookedCleanPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[Cooked Clean] RaiseEvent failed: " + ex.Message));
				}
			}
		}

		private void ApplyRemote(int viewId, int effect)
		{
			Remember(viewId, effect);
			PhotonView val = PhotonView.Find(viewId);
			if (!((Object)(object)val == (Object)null))
			{
				Item component = ((Component)val).GetComponent<Item>();
				if (!((Object)(object)component == (Object)null))
				{
					CookedCleanPlugin.StorePositiveEffect(component, effect, broadcast: false);
					CookedCleanPlugin.ApplyClean(component);
				}
			}
		}

		private static int ToInt(object value)
		{
			if (value is int)
			{
				return (int)value;
			}
			if (value is byte)
			{
				return (byte)value;
			}
			if (value is short)
			{
				return (short)value;
			}
			return Convert.ToInt32(value);
		}

		private static byte ToByte(object value)
		{
			if (value is byte)
			{
				return (byte)value;
			}
			return (byte)ToInt(value);
		}
	}
}