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