using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
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.Configuration;
using ExitGames.Client.Photon;
using HarmonyLib;
using Peak;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.SceneManagement;
using Zorro.Core;
using Zorro.Core.Serizalization;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyTitle("Self To Shelf")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Self To Shelf")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e8ea1f77-f217-4354-81c5-cbe5a7eb2cdd")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.0.0.0")]
[module: UnverifiableCode]
public static class UniqueShelfShroomDataEntryKey
{
public static readonly DataEntryKey IsUnique = (DataEntryKey)180;
}
[BepInPlugin("tony4twentys.Self_To_Shelf", "Self to Shelf", "2.0.0")]
public class SelfToShelf : BaseUnityPlugin
{
private struct PendingFungusWarp
{
public Character thrower;
public Vector3 destination;
public Vector3 spawnSearchPos;
public bool isUnique;
public bool isCloud;
public bool shouldWarp;
}
[HarmonyPatch(typeof(ShelfShroom), "Break")]
private static class ShelfShroom_Break_Patch
{
private static void Prefix(ShelfShroom __instance, Collision coll, ref PendingFungusWarp __state)
{
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
__state = default(PendingFungusWarp);
try
{
if (!((Object)(object)__instance == (Object)null) && !__instance.alreadyBroke)
{
Item item = __instance.item;
if (ItemHasTeleportPower(item) && coll != null && coll.contactCount > 0)
{
ContactPoint val = coll.contacts[0];
__state.shouldWarp = true;
__state.thrower = GetThrower(item);
__state.spawnSearchPos = ((ContactPoint)(ref val)).point;
__state.destination = ((ContactPoint)(ref val)).point + ((ContactPoint)(ref val)).normal * GetWarpOffWallDistance();
__state.isUnique = ItemIsUnique(item);
__state.isCloud = false;
}
}
}
catch (Exception ex)
{
LogOnce(ref _loggedShelfBreakError, "ShelfShroom.Break prefix failed", ex);
}
}
private static void Postfix(PendingFungusWarp __state)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
try
{
if (__state.shouldWarp)
{
TeleportThrowerAndNearby(__state.thrower, __state.destination);
if (__state.isUnique)
{
FungusNetworkSync.SchedulePaintSpawn(__state.spawnSearchPos, isCloud: false);
}
}
}
catch (Exception ex)
{
LogOnce(ref _loggedShelfBreakError, "ShelfShroom.Break postfix failed", ex);
}
}
}
[HarmonyPatch(typeof(CloudFungus), "Break")]
private static class CloudFungus_Break_Patch
{
private static void Prefix(CloudFungus __instance, ref PendingFungusWarp __state)
{
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: 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_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
__state = default(PendingFungusWarp);
try
{
if (!((Object)(object)__instance == (Object)null) && !__instance.alreadyBroke)
{
Item item = __instance.item;
if (ItemHasTeleportPower(item))
{
Vector3 position = ((Component)__instance).transform.position;
__state.shouldWarp = true;
__state.thrower = GetThrower(item);
__state.spawnSearchPos = position;
__state.destination = position + Vector3.up * GetWarpOffWallDistance();
__state.isUnique = ItemIsUnique(item);
__state.isCloud = true;
}
}
}
catch (Exception ex)
{
LogOnce(ref _loggedCloudBreakError, "CloudFungus.Break prefix failed", ex);
}
}
private static void Postfix(PendingFungusWarp __state)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
try
{
if (__state.shouldWarp)
{
TeleportThrowerAndNearby(__state.thrower, __state.destination);
if (__state.isUnique)
{
FungusNetworkSync.SchedulePaintSpawn(__state.spawnSearchPos, isCloud: true);
}
}
}
catch (Exception ex)
{
LogOnce(ref _loggedCloudBreakError, "CloudFungus.Break postfix failed", ex);
}
}
}
[HarmonyPatch(typeof(Item), "Start")]
private static class Item_Start_Patch
{
private static void Postfix(Item __instance)
{
try
{
FungusSpawnHelper.Initialize(__instance);
}
catch (Exception ex)
{
LogOnce(ref _loggedItemStartError, "Item.Start postfix failed", ex);
}
}
}
[HarmonyPatch(typeof(Item), "OnInstanceDataRecieved")]
private static class Item_OnInstanceDataRecieved_Patch
{
private static void Postfix(Item __instance)
{
try
{
if (IsShelfFungus(__instance) && ShelfToShelfRuntime.ShouldApplyModEffects())
{
FungusNetworkSync.TryApplyRemembered(__instance);
FungusVisuals.ApplyFromItemData(__instance);
}
}
catch (Exception ex)
{
LogOnce(ref _loggedInstanceDataError, "Item.OnInstanceDataRecieved postfix failed", ex);
}
}
}
[HarmonyPatch(typeof(Item), "GetName")]
private static class Item_GetName_Patch
{
private static bool Prefix(Item __instance, ref string __result)
{
try
{
if (!IsShelfFungus(__instance))
{
return true;
}
if (!ShelfToShelfRuntime.ShouldApplyModEffects())
{
return true;
}
if (!FungusNetworkSync.GetIsUnique(__instance))
{
return true;
}
__result = FungusVisuals.UniqueName(__instance);
return false;
}
catch (Exception ex)
{
LogOnce(ref _loggedGetItemNameError, "Item.GetName prefix failed", ex);
return true;
}
}
}
[HarmonyPatch(typeof(Item), "GetItemName")]
[HarmonyPriority(0)]
private static class Item_GetItemName_Patch
{
private static void Postfix(Item __instance, ItemInstanceData data, ref string __result)
{
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
try
{
if (IsShelfFungus(__instance) && ShelfToShelfRuntime.ShouldApplyModEffects())
{
bool flag = FungusNetworkSync.GetIsUnique(__instance);
IntItemData val = default(IntItemData);
if (!flag && data != null && data.TryGetDataEntry<IntItemData>(UniqueShelfShroomDataEntryKey.IsUnique, ref val) && val != null && val.Value == 1)
{
flag = true;
}
if (flag)
{
__result = FungusVisuals.UniqueName(__instance);
}
}
}
catch (Exception ex)
{
LogOnce(ref _loggedGetItemNameError, "Item.GetItemName postfix failed", ex);
}
}
}
[HarmonyPatch(typeof(RunManager), "StartRun")]
private static class Patch_RunManager_StartRun
{
private static void Postfix()
{
if (ShelfToShelfRuntime.ShouldApplyModEffects() && PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient)
{
ShelfToShelfNetProxy.BroadcastNow();
FungusNetworkSync.BroadcastAll();
FungusSpawnHelper.RetagUntaggedFungus();
}
}
}
internal const byte EventCode = 163;
internal const int ProtocolVersion = 203;
internal const string EventMagic = "tony4twentys.Self_To_Shelf";
private static Harmony _harmony;
internal static SelfToShelf Instance;
private ConfigEntry<bool> pullOtherPlayers;
private ConfigEntry<float> huddlePullMultiplier;
private ConfigEntry<float> uniqueShelfShroomChance;
private ConfigEntry<float> uniqueCloudFungusChance;
internal static bool syncedPullOtherPlayers;
internal static float syncedHuddlePullMultiplier;
internal static float syncedUniqueShelfShroomChance;
internal static float syncedUniqueCloudFungusChance;
internal static bool IsSyncingFromNet;
private static float _warpOffWallDistance;
private static bool _loggedItemStartError;
private static bool _loggedGetItemNameError;
private static bool _loggedShelfBreakError;
private static bool _loggedCloudBreakError;
private static bool _loggedWarpError;
private static bool _loggedInstanceDataError;
internal static void LogInfo(string msg)
{
if ((Object)(object)Instance != (Object)null)
{
((BaseUnityPlugin)Instance).Logger.LogInfo((object)msg);
}
else
{
Debug.Log((object)msg);
}
}
private static void LogOnce(ref bool flag, string message, Exception ex)
{
if (!flag)
{
flag = true;
LogInfo("[Self To Shelf] " + message + ": " + ex);
}
}
internal static float NormalizeChance(float raw)
{
if (raw > 1f)
{
raw *= 0.01f;
}
if (raw < 0f)
{
return 0f;
}
if (raw > 1f)
{
return 1f;
}
return raw;
}
internal static bool RollChance(float chance)
{
chance = NormalizeChance(chance);
if (chance <= 0f)
{
return false;
}
if (chance >= 1f)
{
return true;
}
return Random.value < chance;
}
internal static float ClampMultiplier(float raw)
{
if (raw < 0f)
{
return 0f;
}
if (raw > 20f)
{
return 20f;
}
return raw;
}
internal static bool IsHostAuthority()
{
return !PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient;
}
internal void RefreshSyncedFromLocal()
{
if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient)
{
syncedPullOtherPlayers = pullOtherPlayers.Value;
syncedHuddlePullMultiplier = ClampMultiplier(huddlePullMultiplier.Value);
syncedUniqueShelfShroomChance = NormalizeChance(uniqueShelfShroomChance.Value);
syncedUniqueCloudFungusChance = NormalizeChance(uniqueCloudFungusChance.Value);
}
}
internal static void ApplyNetworkSnapshot(bool pullOthers, float huddleMultiplier, float shelfChance, float cloudChance)
{
syncedPullOtherPlayers = pullOthers;
syncedHuddlePullMultiplier = ClampMultiplier(huddleMultiplier);
syncedUniqueShelfShroomChance = NormalizeChance(shelfChance);
syncedUniqueCloudFungusChance = NormalizeChance(cloudChance);
}
internal static object[] PackEvent(byte sub, params object[] rest)
{
int num = ((rest != null) ? rest.Length : 0);
object[] array = new object[3 + num];
array[0] = "tony4twentys.Self_To_Shelf";
array[1] = 203;
array[2] = sub;
if (rest != null)
{
for (int i = 0; i < rest.Length; i++)
{
array[3 + i] = rest[i];
}
}
return array;
}
internal static bool TryReadEvent(object[] arr, out byte sub)
{
sub = 0;
if (arr == null || arr.Length < 3)
{
return false;
}
string text = arr[0] as string;
if (text != "tony4twentys.Self_To_Shelf")
{
return false;
}
if (Convert.ToInt32(arr[1]) != 203)
{
return false;
}
sub = Convert.ToByte(arr[2]);
return true;
}
private void OnLocalConfigChanged(object sender, EventArgs args)
{
if (!IsSyncingFromNet && IsHostAuthority())
{
RefreshSyncedFromLocal();
ShelfToShelfNetProxy.ScheduleBroadcast();
LogInfo("[Self To Shelf] Config updated. Huddle pull x" + syncedHuddlePullMultiplier + ", shelf unique " + syncedUniqueShelfShroomChance + ", cloud unique " + syncedUniqueCloudFungusChance);
}
}
internal static float GetUniqueChance(Item item)
{
if (FungusVisuals.IsCloud(item))
{
return (IsHostAuthority() && (Object)(object)Instance != (Object)null) ? NormalizeChance(Instance.uniqueCloudFungusChance.Value) : syncedUniqueCloudFungusChance;
}
return (IsHostAuthority() && (Object)(object)Instance != (Object)null) ? NormalizeChance(Instance.uniqueShelfShroomChance.Value) : syncedUniqueShelfShroomChance;
}
private void Awake()
{
//IL_0103: Unknown result type (might be due to invalid IL or missing references)
//IL_010d: Expected O, but got Unknown
//IL_011d: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: Expected O, but got Unknown
Instance = this;
pullOtherPlayers = ((BaseUnityPlugin)this).Config.Bind<bool>("Teleport", "Pull Other Players", true, "Teleport nearby players with you when a Warp Shelf or Warp Cloud fungus places.");
huddlePullMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Teleport", "Huddle Pull Multiplier", 2f, "How many times the in-game huddle warming radius to pull nearby scouts. 2 = twice the player-heat huddle. Increase to pull a wider group.");
uniqueShelfShroomChance = ((BaseUnityPlugin)this).Config.Bind<float>("Unique", "Unique ShelfShroom Chance", 0.2f, "Chance a shelf fungus is Warp Shelf Fungus (teleports). 0 = never, 1 or 100 = always, or 0-100 percent.");
uniqueCloudFungusChance = ((BaseUnityPlugin)this).Config.Bind<float>("Unique", "Unique Cloud Fungus Chance", 0.2f, "Chance a cloud fungus is Warp Cloud Fungus (teleports). 0 = never, 1 or 100 = always, or 0-100 percent.");
RefreshSyncedFromLocal();
pullOtherPlayers.SettingChanged += OnLocalConfigChanged;
huddlePullMultiplier.SettingChanged += OnLocalConfigChanged;
uniqueShelfShroomChance.SettingChanged += OnLocalConfigChanged;
uniqueCloudFungusChance.SettingChanged += OnLocalConfigChanged;
_harmony = new Harmony("tony4twentys.Self_To_Shelf");
_harmony.PatchAll();
GameObject val = new GameObject("SelfToShelf_NetProxy");
Object.DontDestroyOnLoad((Object)(object)val);
val.AddComponent<ShelfToShelfNetProxy>();
SceneManager.sceneLoaded += OnSceneLoaded;
((BaseUnityPlugin)this).Logger.LogInfo((object)("[Self To Shelf] 2.0.0 loaded. Photon " + (byte)163 + "."));
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
if (ShelfToShelfRuntime.ShouldApplyModEffects())
{
if (PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient)
{
ShelfToShelfNetProxy.BroadcastNow();
FungusNetworkSync.BroadcastAll();
FungusSpawnHelper.RetagUntaggedFungus();
}
else if (!PhotonNetwork.InRoom)
{
RefreshSyncedFromLocal();
FungusSpawnHelper.RetagUntaggedFungus();
}
}
}
private void OnDestroy()
{
if (pullOtherPlayers != null)
{
pullOtherPlayers.SettingChanged -= OnLocalConfigChanged;
}
if (huddlePullMultiplier != null)
{
huddlePullMultiplier.SettingChanged -= OnLocalConfigChanged;
}
if (uniqueShelfShroomChance != null)
{
uniqueShelfShroomChance.SettingChanged -= OnLocalConfigChanged;
}
if (uniqueCloudFungusChance != null)
{
uniqueCloudFungusChance.SettingChanged -= OnLocalConfigChanged;
}
try
{
SceneManager.sceneLoaded -= OnSceneLoaded;
}
catch
{
}
if (_harmony != null)
{
_harmony.UnpatchSelf();
}
}
internal static bool IsShelfFungus(Item item)
{
if (!Object.op_Implicit((Object)(object)item))
{
return false;
}
if ((Object)(object)((Component)item).GetComponent<CloudFungus>() != (Object)null)
{
return NameContains(item, "CloudFungus");
}
if ((Object)(object)((Component)item).GetComponent<ShelfShroom>() == (Object)null)
{
return false;
}
if (NameContains(item, "HealingPuff"))
{
return false;
}
return NameContains(item, "ShelfShroom");
}
internal static bool IsLiveWorldItem(Item item)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Invalid comparison between Unknown and I4
if ((Object)(object)item == (Object)null || (Object)(object)((Component)item).gameObject == (Object)null)
{
return false;
}
Scene scene = ((Component)item).gameObject.scene;
if (!((Scene)(ref scene)).IsValid())
{
return false;
}
if ((((Object)((Component)item).gameObject).hideFlags & 0x3D) > 0)
{
return false;
}
return true;
}
private static bool NameContains(Item item, string token)
{
if (((Object)item).name != null && ((Object)item).name.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0)
{
return true;
}
if (item.UIData != null && item.UIData.itemName != null && item.UIData.itemName.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0)
{
return true;
}
return false;
}
internal static bool IsTeleportSpawn(Transform spawn)
{
if ((Object)(object)spawn == (Object)null)
{
return false;
}
return ((Object)spawn).name.Contains("ShelfShroomSpawn") || ((Object)spawn).name.Contains("CloudFungusPlaced");
}
internal static bool IsCharacterDead(Character character)
{
return (Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null || character.data.dead;
}
internal static bool ItemHasTeleportPower(Item item)
{
if (!ShelfToShelfRuntime.ShouldApplyModEffects())
{
return false;
}
if (!IsShelfFungus(item))
{
return false;
}
return FungusNetworkSync.GetIsUnique(item);
}
internal static bool ItemIsUnique(Item item)
{
return FungusNetworkSync.GetIsUnique(item);
}
internal static Vector3 GetHuddleOrigin(Character character)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: 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_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)character == (Object)null)
{
return Vector3.zero;
}
if (character.refs != null)
{
if ((Object)(object)character.refs.heatEmission != (Object)null)
{
return ((Component)character.refs.heatEmission).transform.position;
}
if ((Object)(object)character.refs.hip != (Object)null)
{
return character.refs.hip.transform.position;
}
}
return character.Center;
}
internal static float GetHuddleWarmRadius(Character character)
{
if ((Object)(object)character != (Object)null && character.refs != null && (Object)(object)character.refs.heatEmission != (Object)null && character.refs.heatEmission.radius > 0f)
{
return character.refs.heatEmission.radius;
}
return 1f;
}
internal static float GetPullRadius(Character character)
{
return GetHuddleWarmRadius(character) * syncedHuddlePullMultiplier;
}
internal static bool IsInHuddlePullRange(Character thrower, Character other)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)thrower == (Object)null || (Object)(object)other == (Object)null)
{
return false;
}
return Vector3.Distance(GetHuddleOrigin(thrower), other.Center) < GetPullRadius(thrower);
}
internal static Character GetThrower(Item item)
{
if (!Object.op_Implicit((Object)(object)item))
{
return null;
}
if (Object.op_Implicit((Object)(object)item.lastThrownCharacter))
{
return item.lastThrownCharacter;
}
if (Object.op_Implicit((Object)(object)item.holderCharacter))
{
return item.holderCharacter;
}
return Character.localCharacter;
}
internal static float GetWarpOffWallDistance()
{
if (_warpOffWallDistance > 0f)
{
return _warpOffWallDistance;
}
GameObject val = Resources.Load<GameObject>("0_Items/WarpFungus");
if ((Object)(object)val != (Object)null)
{
WarpOnThrow val2 = val.GetComponent<WarpOnThrow>();
if ((Object)(object)val2 == (Object)null)
{
val2 = val.GetComponentInChildren<WarpOnThrow>(true);
}
if ((Object)(object)val2 != (Object)null && val2.moveAwayFromWallDistance > 0.01f)
{
_warpOffWallDistance = val2.moveAwayFromWallDistance;
}
}
if (_warpOffWallDistance <= 0f)
{
_warpOffWallDistance = 1.5f;
}
return _warpOffWallDistance;
}
internal static void WarpLikeFungus(Character character, Vector3 position)
{
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
if (!IsCharacterDead(character) && !((Object)(object)((MonoBehaviourPun)character).photonView == (Object)null))
{
((MonoBehaviourPun)character).photonView.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2] { position, true });
}
}
internal static void TeleportThrowerAndNearby(Character thrower, Vector3 destination)
{
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
try
{
if (IsCharacterDead(thrower))
{
return;
}
List<Character> list = new List<Character>();
list.Add(thrower);
if (syncedPullOtherPlayers && Character.AllCharacters != null)
{
foreach (Character allCharacter in Character.AllCharacters)
{
if (!((Object)(object)allCharacter == (Object)null) && !((Object)(object)allCharacter == (Object)(object)thrower) && !IsCharacterDead(allCharacter) && IsInHuddlePullRange(thrower, allCharacter))
{
list.Add(allCharacter);
}
}
}
foreach (Character item in list)
{
WarpLikeFungus(item, destination);
}
}
catch (Exception ex)
{
LogOnce(ref _loggedWarpError, "Teleport failed", ex);
}
}
}
internal static class FungusIcons
{
private static Texture2D _shelfIcon;
private static Texture2D _cloudIcon;
private static bool _refreshQueued;
private static bool _loggedShelfMissing;
private static bool _loggedCloudMissing;
private static bool _loggedError;
internal static void QueueLiveRefresh()
{
if ((Object)(object)SelfToShelf.Instance == (Object)null)
{
ApplyLiveNow();
}
else if (!_refreshQueued)
{
_refreshQueued = true;
((MonoBehaviour)SelfToShelf.Instance).StartCoroutine(LiveRefreshDeferred());
}
}
private static IEnumerator LiveRefreshDeferred()
{
yield return null;
_refreshQueued = false;
ApplyLiveNow();
}
private static void ApplyLiveNow()
{
try
{
RefreshVisibleSlots();
}
catch (Exception ex)
{
LogOnce(ref _loggedError, "[Self To Shelf] inventory icon refresh failed", ex);
}
}
private static void RefreshVisibleSlots()
{
GUIManager instance = GUIManager.instance;
if ((Object)(object)instance == (Object)null)
{
return;
}
Character val = (((Object)(object)Character.observedCharacter != (Object)null) ? Character.observedCharacter : Character.localCharacter);
if ((Object)(object)val == (Object)null || (Object)(object)val.player == (Object)null)
{
return;
}
InventoryItemUI[] items = instance.items;
ItemSlot[] itemSlots = val.player.itemSlots;
if (items != null && itemSlots != null)
{
int num = Mathf.Min(items.Length, itemSlots.Length);
for (int i = 0; i < num; i++)
{
RefreshSlot(items[i], itemSlots[i]);
}
}
if ((Object)(object)instance.temporaryItem != (Object)null)
{
RefreshSlot(instance.temporaryItem, val.player.tempFullSlot);
}
RefreshBackpackWheel(instance.backpackWheel);
}
internal static void RefreshSlot(InventoryItemUI slot, ItemSlot itemSlot)
{
if (!((Object)(object)slot == (Object)null) && itemSlot != null && !itemSlot.IsEmpty())
{
ApplyToUi(slot, itemSlot.prefab, itemSlot.data);
}
}
private static void ApplyToUi(InventoryItemUI slot, Item prefab, ItemInstanceData data)
{
if (!((Object)(object)slot == (Object)null) && !((Object)(object)slot.icon == (Object)null) && !((Object)(object)prefab == (Object)null) && SelfToShelf.IsShelfFungus(prefab) && ShelfToShelfRuntime.ShouldApplyModEffects() && IsUnique(prefab, data))
{
Texture2D icon = GetIcon(FungusVisuals.IsCloud(prefab));
if (!((Object)(object)icon == (Object)null))
{
slot.icon.texture = (Texture)(object)icon;
((Behaviour)slot.icon).enabled = true;
ApplyVanillaScale(slot, prefab);
}
}
}
private static void ApplyVanillaScale(InventoryItemUI slot, Item prefab)
{
//IL_0048: 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)
float num = 1f;
if ((Object)(object)prefab != (Object)null && prefab.UIData != null && prefab.UIData.iconScaleOffset > 0.01f)
{
num = prefab.UIData.iconScaleOffset;
}
((Component)slot.icon).transform.localScale = Vector3.one * num;
}
private static void RefreshBackpackWheel(BackpackWheel wheel)
{
if ((Object)(object)wheel == (Object)null || (Object)(object)wheel.currentlyHeldItem == (Object)null)
{
return;
}
Character localCharacter = Character.localCharacter;
Item val = (((Object)(object)localCharacter != (Object)null && (Object)(object)localCharacter.data != (Object)null) ? localCharacter.data.currentItem : null);
if (!((Object)(object)val == (Object)null) && SelfToShelf.IsShelfFungus(val) && FungusNetworkSync.GetIsUnique(val))
{
Texture2D icon = GetIcon(FungusVisuals.IsCloud(val));
if ((Object)(object)icon != (Object)null)
{
wheel.currentlyHeldItem.texture = (Texture)(object)icon;
}
}
}
internal static bool IsUnique(Item prefab, ItemInstanceData data)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
IntItemData val = default(IntItemData);
if (data != null && data.TryGetDataEntry<IntItemData>(UniqueShelfShroomDataEntryKey.IsUnique, ref val) && val != null)
{
return val.Value == 1;
}
return false;
}
internal static Texture2D GetIcon(bool isCloud)
{
if (isCloud)
{
return GetOrLoadIcon(ref _cloudIcon, "WarpCloudFungus.png", "Warp Cloud Fungus", ref _loggedCloudMissing);
}
return GetOrLoadIcon(ref _shelfIcon, "WarpShelfFungus.png", "Warp Shelf Fungus", ref _loggedShelfMissing);
}
private static Texture2D GetOrLoadIcon(ref Texture2D cached, string fileName, string label, ref bool loggedMissing)
{
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Expected O, but got Unknown
if ((Object)(object)cached != (Object)null)
{
return cached;
}
try
{
byte[] array = ReadEmbeddedPng(fileName);
if (array == null || array.Length == 0)
{
LogMissing(ref loggedMissing, fileName);
return null;
}
Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
((Texture)val).wrapMode = (TextureWrapMode)1;
((Texture)val).filterMode = (FilterMode)1;
if (!LoadImage(val, array))
{
Object.Destroy((Object)(object)val);
LogMissing(ref loggedMissing, fileName);
return null;
}
cached = CopyToRgba(val);
if ((Object)(object)cached != (Object)(object)val)
{
Object.Destroy((Object)(object)val);
}
PunchBlackToAlpha(cached);
((Object)cached).hideFlags = (HideFlags)61;
}
catch (Exception ex)
{
LogOnce(ref _loggedError, "[Self To Shelf] " + label + " icon load failed", ex);
}
return cached;
}
private static bool LoadImage(Texture2D tex, byte[] bytes)
{
Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule");
if (type == null)
{
return false;
}
MethodInfo method = type.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
{
typeof(Texture2D),
typeof(byte[])
}, null);
if (method == null)
{
return false;
}
object obj = method.Invoke(null, new object[2] { tex, bytes });
return obj is bool && (bool)obj;
}
private static byte[] ReadEmbeddedPng(string fileName)
{
Assembly assembly = typeof(FungusIcons).Assembly;
string[] manifestResourceNames = assembly.GetManifestResourceNames();
string text = null;
for (int i = 0; i < manifestResourceNames.Length; i++)
{
if (manifestResourceNames[i] != null && manifestResourceNames[i].EndsWith(fileName, StringComparison.OrdinalIgnoreCase))
{
text = manifestResourceNames[i];
break;
}
}
if (text == null)
{
return null;
}
using Stream stream = assembly.GetManifestResourceStream(text);
if (stream == null)
{
return null;
}
byte[] array = new byte[stream.Length];
int num;
for (int j = 0; j < array.Length; j += num)
{
num = stream.Read(array, j, array.Length - j);
if (num <= 0)
{
break;
}
}
return array;
}
private static Texture2D CopyToRgba(Texture2D src)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Expected O, but got Unknown
Texture2D val = new Texture2D(((Texture)src).width, ((Texture)src).height, (TextureFormat)4, false);
((Texture)val).wrapMode = (TextureWrapMode)1;
((Texture)val).filterMode = (FilterMode)1;
val.SetPixels32(src.GetPixels32());
val.Apply(false, false);
return val;
}
private static void PunchBlackToAlpha(Texture2D tex)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
Color32[] pixels = tex.GetPixels32();
for (int i = 0; i < pixels.Length; i++)
{
Color32 val = pixels[i];
if (val.r < 18 && val.g < 18 && val.b < 18)
{
val.a = 0;
pixels[i] = val;
}
}
tex.SetPixels32(pixels);
tex.Apply(false, false);
}
private static void LogMissing(ref bool flagged, string fileName)
{
if (!flagged)
{
flagged = true;
SelfToShelf.LogInfo("[Self To Shelf] Embedded " + fileName + " was missing.");
}
}
private static void LogOnce(ref bool flagged, string message, Exception ex)
{
if (!flagged)
{
flagged = true;
SelfToShelf.LogInfo(message + ": " + ex);
}
}
}
[HarmonyPatch(typeof(InventoryItemUI), "SetItem")]
internal static class InventoryItemUI_SetItem_FungusIconPatch
{
private static void Postfix(InventoryItemUI __instance, ItemSlot slot)
{
try
{
FungusIcons.RefreshSlot(__instance, slot);
}
catch
{
}
}
}
[HarmonyPatch(typeof(BackpackWheelSlice), "SetItemIcon")]
internal static class BackpackWheelSlice_SetItemIcon_FungusIconPatch
{
private static void Postfix()
{
try
{
FungusIcons.QueueLiveRefresh();
}
catch
{
}
}
}
internal static class ShelfToShelfRuntime
{
internal static bool HostModConfirmed;
internal static bool VanillaHostMode;
internal static bool IsAwaitingHostSync => PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient && !HostModConfirmed && !VanillaHostMode;
internal static bool ShouldApplyModEffects()
{
if (VanillaHostMode)
{
return false;
}
if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient && !HostModConfirmed)
{
return false;
}
return true;
}
internal static void OnJoinedRoom(bool isMaster)
{
VanillaHostMode = false;
HostModConfirmed = isMaster;
if (isMaster)
{
if ((Object)(object)SelfToShelf.Instance != (Object)null)
{
SelfToShelf.Instance.RefreshSyncedFromLocal();
}
FungusSpawnHelper.RetagUntaggedFungus();
SelfToShelf.LogInfo("[Self To Shelf] Host joined — unique fungi and teleports enabled.");
}
}
internal static void OnHostSyncReceived()
{
HostModConfirmed = true;
VanillaHostMode = false;
FungusSpawnHelper.RetagUntaggedFungus();
SelfToShelf.LogInfo("[Self To Shelf] Host config snapshot applied.");
}
internal static void OnLeftRoom()
{
HostModConfirmed = false;
VanillaHostMode = false;
FungusNetworkSync.ClearRoomState();
FungusSpawnHelper.ClearPending();
if ((Object)(object)SelfToShelf.Instance != (Object)null)
{
SelfToShelf.Instance.RefreshSyncedFromLocal();
}
}
internal static void OnHostModMissing()
{
HostModConfirmed = false;
VanillaHostMode = true;
FungusSpawnHelper.ClearPending();
SelfToShelf.LogInfo("[Self To Shelf] Host does not appear to have Self To Shelf — unique fungi and teleports disabled.");
}
}
internal class ShelfToShelfNetProxy : MonoBehaviourPunCallbacks, IOnEventCallback
{
internal const byte SubConfig = 0;
internal const byte SubConfigRequest = 1;
internal const byte SubUniqueSync = 2;
internal const byte SubUniqueRequest = 3;
internal const byte SubSpawnSync = 4;
private const float HostSyncTimeoutSeconds = 12f;
private const float HostSyncRetrySeconds = 2f;
internal static ShelfToShelfNetProxy Instance;
private Coroutine _debounce;
private Coroutine _hostSyncWatch;
private void Awake()
{
Instance = this;
}
private void Start()
{
if (PhotonNetwork.InRoom)
{
((MonoBehaviourPunCallbacks)this).OnJoinedRoom();
}
}
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()
{
if (PhotonNetwork.IsMasterClient)
{
ShelfToShelfRuntime.OnJoinedRoom(isMaster: true);
BroadcastNow();
((MonoBehaviour)this).StartCoroutine(BroadcastAfterDelay(0.5f));
}
else
{
ShelfToShelfRuntime.OnJoinedRoom(isMaster: false);
RequestHostSync();
RestartHostSyncWatch();
}
}
public override void OnLeftRoom()
{
StopHostSyncWatch();
ShelfToShelfRuntime.OnLeftRoom();
}
public override void OnMasterClientSwitched(Player newMasterClient)
{
if (PhotonNetwork.IsMasterClient)
{
ShelfToShelfRuntime.OnJoinedRoom(isMaster: true);
BroadcastNow();
StopHostSyncWatch();
((MonoBehaviour)this).StartCoroutine(BroadcastAfterDelay(0.5f));
}
else
{
ShelfToShelfRuntime.OnJoinedRoom(isMaster: false);
RequestHostSync();
RestartHostSyncWatch();
}
}
public override void OnPlayerEnteredRoom(Player newPlayer)
{
if (PhotonNetwork.IsMasterClient)
{
((MonoBehaviour)this).StartCoroutine(BroadcastAfterDelay(0.5f));
}
}
public void OnEvent(EventData e)
{
if (e == null || e.Code != 163)
{
return;
}
object[] array = e.CustomData as object[];
if (SelfToShelf.TryReadEvent(array, out var sub))
{
if (sub == 1 && PhotonNetwork.IsMasterClient)
{
BroadcastNow();
FungusNetworkSync.BroadcastAll();
}
else if (sub == 0)
{
ApplyConfigSnapshot(array);
}
else
{
FungusNetworkSync.HandleGameplayEvent(sub, array);
}
}
}
internal static void ScheduleBroadcast()
{
if (!((Object)(object)Instance == (Object)null) && PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient)
{
if (Instance._debounce != null)
{
((MonoBehaviour)Instance).StopCoroutine(Instance._debounce);
}
Instance._debounce = ((MonoBehaviour)Instance).StartCoroutine(Instance.DebounceBroadcast());
}
}
internal static void RequestHostSync()
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Expected O, but got Unknown
if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient)
{
PhotonNetwork.RaiseEvent((byte)163, (object)SelfToShelf.PackEvent(1), new RaiseEventOptions
{
Receivers = (ReceiverGroup)2
}, SendOptions.SendReliable);
}
}
internal void StartRoutine(IEnumerator routine)
{
if (routine != null)
{
((MonoBehaviour)this).StartCoroutine(routine);
}
}
private void RestartHostSyncWatch()
{
StopHostSyncWatch();
if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient)
{
_hostSyncWatch = ((MonoBehaviour)this).StartCoroutine(WatchForHostSync());
}
}
private void StopHostSyncWatch()
{
if (_hostSyncWatch != null)
{
((MonoBehaviour)this).StopCoroutine(_hostSyncWatch);
_hostSyncWatch = null;
}
}
private IEnumerator WatchForHostSync()
{
float elapsed = 0f;
float nextRetry = 2f;
while (elapsed < 12f)
{
if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient || ShelfToShelfRuntime.HostModConfirmed)
{
yield break;
}
elapsed += Time.unscaledDeltaTime;
if (elapsed >= nextRetry)
{
RequestHostSync();
nextRetry += 2f;
}
yield return null;
}
if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient && !ShelfToShelfRuntime.HostModConfirmed)
{
ShelfToShelfRuntime.OnHostModMissing();
}
_hostSyncWatch = null;
}
private IEnumerator DebounceBroadcast()
{
yield return (object)new WaitForSeconds(0.25f);
BroadcastNow();
_debounce = null;
}
private IEnumerator BroadcastAfterDelay(float seconds)
{
yield return (object)new WaitForSeconds(seconds);
BroadcastNow();
FungusNetworkSync.BroadcastAll();
FungusSpawnHelper.RetagUntaggedFungus();
}
private static void ApplyConfigSnapshot(object[] arr)
{
if (arr == null || arr.Length < 7 || PhotonNetwork.IsMasterClient)
{
return;
}
try
{
SelfToShelf.IsSyncingFromNet = true;
if ((Object)(object)Instance != (Object)null)
{
Instance.StopHostSyncWatch();
}
SelfToShelf.ApplyNetworkSnapshot(Convert.ToBoolean(arr[3]), Convert.ToSingle(arr[4]), Convert.ToSingle(arr[5]), Convert.ToSingle(arr[6]));
ShelfToShelfRuntime.OnHostSyncReceived();
}
catch (Exception ex)
{
SelfToShelf.LogInfo("[Self To Shelf] Config snapshot error: " + ex.Message);
}
finally
{
SelfToShelf.IsSyncingFromNet = false;
}
}
internal static void BroadcastNow()
{
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Expected O, but got Unknown
if (PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient)
{
if ((Object)(object)SelfToShelf.Instance != (Object)null)
{
SelfToShelf.Instance.RefreshSyncedFromLocal();
}
PhotonNetwork.RaiseEvent((byte)163, (object)SelfToShelf.PackEvent(0, SelfToShelf.syncedPullOtherPlayers, SelfToShelf.syncedHuddlePullMultiplier, SelfToShelf.syncedUniqueShelfShroomChance, SelfToShelf.syncedUniqueCloudFungusChance), new RaiseEventOptions
{
Receivers = (ReceiverGroup)0
}, SendOptions.SendReliable);
}
}
}
internal static class FungusMaterials
{
private const string WarpName = "M_Mushroom_Warp";
private const string WeirdName = "M_Mushroom_Weird";
private static Material _warp;
private static Material _weird;
private static bool _loggedWarpFail;
private static bool _loggedWeirdFail;
public static Material Warp
{
get
{
if ((Object)(object)_warp == (Object)null)
{
_warp = FindMaterial("M_Mushroom_Warp", new string[1] { "WarpFungus" });
}
if ((Object)(object)_warp == (Object)null && !_loggedWarpFail)
{
_loggedWarpFail = true;
SelfToShelf.LogInfo("[Self To Shelf] Could not load M_Mushroom_Warp");
}
return _warp;
}
}
public static Material Weird
{
get
{
if ((Object)(object)_weird == (Object)null)
{
_weird = FindMaterial("M_Mushroom_Weird", new string[2] { "CloudFungus", "WarpFungus" });
}
if ((Object)(object)_weird == (Object)null && !_loggedWeirdFail)
{
_loggedWeirdFail = true;
SelfToShelf.LogInfo("[Self To Shelf] Could not load M_Mushroom_Weird");
}
return _weird;
}
}
public static Material ForShelf()
{
return Warp;
}
public static Material ForCloud()
{
return Weird;
}
private static Material FindMaterial(string materialName, string[] prefabGuesses)
{
Material val = FindLoaded(materialName);
if ((Object)(object)val != (Object)null)
{
return val;
}
if (prefabGuesses != null)
{
for (int i = 0; i < prefabGuesses.Length; i++)
{
GameObject go = Resources.Load<GameObject>("0_Items/" + prefabGuesses[i]);
val = FindOnObject(go, materialName);
if ((Object)(object)val != (Object)null)
{
return val;
}
}
}
GameObject[] array = Resources.LoadAll<GameObject>("0_Items/");
if (array != null)
{
for (int j = 0; j < array.Length; j++)
{
val = FindOnObject(array[j], materialName);
if ((Object)(object)val != (Object)null)
{
return val;
}
}
}
return FindLoaded(materialName);
}
private static Material FindLoaded(string materialName)
{
Material[] array = Resources.FindObjectsOfTypeAll<Material>();
if (array == null)
{
return null;
}
for (int i = 0; i < array.Length; i++)
{
if (NameMatches(array[i], materialName))
{
return array[i];
}
}
return null;
}
private static Material FindOnObject(GameObject go, string materialName)
{
if ((Object)(object)go == (Object)null)
{
return null;
}
MeshRenderer[] componentsInChildren = go.GetComponentsInChildren<MeshRenderer>(true);
foreach (MeshRenderer val in componentsInChildren)
{
if ((Object)(object)val == (Object)null)
{
continue;
}
if (NameMatches(((Renderer)val).sharedMaterial, materialName))
{
return ((Renderer)val).sharedMaterial;
}
Material[] sharedMaterials = ((Renderer)val).sharedMaterials;
if (sharedMaterials == null)
{
continue;
}
for (int j = 0; j < sharedMaterials.Length; j++)
{
if (NameMatches(sharedMaterials[j], materialName))
{
return sharedMaterials[j];
}
}
}
return null;
}
private static bool NameMatches(Material mat, string materialName)
{
if ((Object)(object)mat == (Object)null || string.IsNullOrEmpty(((Object)mat).name))
{
return false;
}
return ((Object)mat).name == materialName || ((Object)mat).name.StartsWith(materialName + " ", StringComparison.Ordinal);
}
}
internal static class FungusItemDataHelper
{
public static void SetIntEntry(ItemInstanceData data, DataEntryKey key, int value)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Expected O, but got Unknown
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
if (data != null)
{
IntItemData val = default(IntItemData);
if (data.TryGetDataEntry<IntItemData>(key, ref val) && val != null)
{
val.Value = value;
return;
}
IntItemData val2 = new IntItemData();
((DataEntryValue)val2).Init();
val2.Value = value;
data.RegisterEntry<IntItemData>(key, val2);
}
}
}
internal static class FungusVisuals
{
public static bool IsCloud(Item item)
{
return (Object)(object)item != (Object)null && (Object)(object)((Component)item).GetComponent<CloudFungus>() != (Object)null;
}
public static bool IsCloudSpawn(Transform spawn)
{
return (Object)(object)spawn != (Object)null && ((Object)spawn).name.Contains("CloudFungusPlaced");
}
public static string UniqueName(Item item)
{
return UniqueName(IsCloud(item));
}
public static string UniqueName(bool isCloud)
{
return isCloud ? "WARP CLOUD FUNGUS" : "WARP SHELF FUNGUS";
}
public static void ApplyToItem(Item item, bool isUnique)
{
if (Object.op_Implicit((Object)(object)item))
{
ApplyMaterial(((Component)item).gameObject, isUnique, IsCloud(item));
if (isUnique)
{
FungusIcons.QueueLiveRefresh();
}
}
}
public static void ApplyToSpawn(Transform spawn, bool isCloud)
{
if (!((Object)(object)spawn == (Object)null))
{
ApplyMaterial(((Component)spawn).gameObject, isUnique: true, isCloud);
}
}
public static void ApplyFromItemData(Item item)
{
if (ShelfToShelfRuntime.ShouldApplyModEffects() && SelfToShelf.IsShelfFungus(item))
{
ApplyToItem(item, FungusNetworkSync.GetIsUnique(item));
}
}
private static void ApplyMaterial(GameObject go, bool isUnique, bool isCloud)
{
if ((Object)(object)go == (Object)null || !isUnique)
{
return;
}
Material val = (isCloud ? FungusMaterials.ForCloud() : FungusMaterials.ForShelf());
if ((Object)(object)val == (Object)null)
{
return;
}
MeshRenderer[] componentsInChildren = go.GetComponentsInChildren<MeshRenderer>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
if ((Object)(object)componentsInChildren[i] != (Object)null)
{
((Renderer)componentsInChildren[i]).sharedMaterial = val;
}
}
}
}
internal static class FungusInventoryHelper
{
public static ItemSlot FindSlotForItem(Item item)
{
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
Character val = (((Object)(object)item != (Object)null) ? item.holderCharacter : null);
if ((Object)(object)val == (Object)null || (Object)(object)val.player == (Object)null)
{
return null;
}
if (item.data != null && item.data.guid != Guid.Empty)
{
ItemSlot val2 = FindSlotByGuid(val, item.data.guid);
if (val2 != null)
{
return val2;
}
}
if ((Object)(object)val.data != (Object)null && (Object)(object)val.data.currentItem == (Object)(object)item && val.refs != null && (Object)(object)val.refs.items != (Object)null)
{
Optionable<byte> currentSelectedSlot = val.refs.items.currentSelectedSlot;
if (currentSelectedSlot.IsSome)
{
ItemSlot itemSlot = val.player.GetItemSlot(currentSelectedSlot.Value);
if (itemSlot != null && !itemSlot.IsEmpty() && (Object)(object)itemSlot.prefab != (Object)null && itemSlot.prefab.itemID == item.itemID)
{
return itemSlot;
}
}
}
return null;
}
private static ItemSlot FindSlotByGuid(Character holder, Guid guid)
{
ItemSlot val = FindSlotByGuid(holder.player.itemSlots, guid);
if (val != null)
{
return val;
}
if (SlotHasGuid(holder.player.tempFullSlot, guid))
{
return holder.player.tempFullSlot;
}
if (SlotHasGuid((ItemSlot)(object)holder.player.backpackSlot, guid))
{
return (ItemSlot)(object)holder.player.backpackSlot;
}
return null;
}
private static ItemSlot FindSlotByGuid(ItemSlot[] slots, Guid guid)
{
if (slots == null)
{
return null;
}
for (int i = 0; i < slots.Length; i++)
{
if (SlotHasGuid(slots[i], guid))
{
return slots[i];
}
}
return null;
}
private static bool SlotHasGuid(ItemSlot slot, Guid guid)
{
return slot != null && !slot.IsEmpty() && slot.data != null && slot.data.guid == guid;
}
}
internal static class FungusNetworkSync
{
private static readonly Dictionary<int, int> UniqueByViewId = new Dictionary<int, int>();
private static readonly Dictionary<int, bool> UniqueSpawnIsCloud = new Dictionary<int, bool>();
private static readonly HashSet<int> DeferredTagInFlight = new HashSet<int>();
public static bool CanTagItems()
{
if (!ShelfToShelfRuntime.ShouldApplyModEffects())
{
return false;
}
return !PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient;
}
public static PhotonView GetItemView(Item item)
{
if ((Object)(object)item == (Object)null)
{
return null;
}
try
{
if ((Object)(object)((MonoBehaviourPun)item).photonView != (Object)null)
{
return ((MonoBehaviourPun)item).photonView;
}
}
catch
{
}
return ((Component)item).GetComponent<PhotonView>();
}
public static PhotonView GetView(Component component)
{
if ((Object)(object)component == (Object)null)
{
return null;
}
PhotonView component2 = component.GetComponent<PhotonView>();
if ((Object)(object)component2 != (Object)null)
{
return component2;
}
return component.GetComponentInParent<PhotonView>();
}
public static void ClearRoomState()
{
UniqueByViewId.Clear();
UniqueSpawnIsCloud.Clear();
DeferredTagInFlight.Clear();
}
public static void RememberUnique(int viewId, int unique)
{
if (viewId > 0)
{
UniqueByViewId[viewId] = unique;
}
}
public static bool TryGetRememberedUnique(int viewId, out int unique)
{
return UniqueByViewId.TryGetValue(viewId, out unique);
}
public static bool TryGetRememberedUnique(Item item, out int unique)
{
unique = 0;
PhotonView itemView = GetItemView(item);
return (Object)(object)itemView != (Object)null && TryGetRememberedUnique(itemView.ViewID, out unique);
}
public static bool HasExplicitUnique(Item item)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
return (Object)(object)item != (Object)null && item.HasData(UniqueShelfShroomDataEntryKey.IsUnique);
}
public static bool GetIsUnique(Item item)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)item != (Object)null && item.HasData(UniqueShelfShroomDataEntryKey.IsUnique))
{
return item.GetData<IntItemData>(UniqueShelfShroomDataEntryKey.IsUnique).Value == 1;
}
if (TryGetRememberedUnique(item, out var unique))
{
return unique == 1;
}
ItemSlot val = FungusInventoryHelper.FindSlotForItem(item);
IntItemData val2 = default(IntItemData);
if (val != null && val.data != null && val.data.TryGetDataEntry<IntItemData>(UniqueShelfShroomDataEntryKey.IsUnique, ref val2) && val2 != null)
{
return val2.Value == 1;
}
return false;
}
public static void SetUnique(Item item, bool isUnique)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)item == (Object)null))
{
IntItemData data = item.GetData<IntItemData>(UniqueShelfShroomDataEntryKey.IsUnique);
data.Value = (isUnique ? 1 : 0);
PhotonView itemView = GetItemView(item);
if ((Object)(object)itemView != (Object)null)
{
RememberUnique(itemView.ViewID, data.Value);
}
ItemSlot slot = FungusInventoryHelper.FindSlotForItem(item);
CopyUniqueToSlot(item, slot);
}
}
public static void CopyUniqueToSlot(Item item, ItemSlot slot)
{
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Expected O, but got Unknown
if (!((Object)(object)item == (Object)null) && slot != null)
{
int value = (GetIsUnique(item) ? 1 : 0);
if (slot.data == null)
{
slot.data = new ItemInstanceData((item.data != null) ? item.data.guid : Guid.NewGuid());
}
FungusItemDataHelper.SetIntEntry(slot.data, UniqueShelfShroomDataEntryKey.IsUnique, value);
}
}
public static bool TryApplyRemembered(Item item)
{
if (!TryGetRememberedUnique(item, out var unique))
{
return false;
}
PhotonView itemView = GetItemView(item);
if ((Object)(object)itemView != (Object)null)
{
UniqueByViewId.Remove(itemView.ViewID);
}
SetUnique(item, unique == 1);
return true;
}
public static void ForgetUnique(int viewId)
{
if (viewId > 0)
{
UniqueByViewId.Remove(viewId);
}
}
public static void ForgetUnique(Item item)
{
PhotonView itemView = GetItemView(item);
if ((Object)(object)itemView != (Object)null)
{
ForgetUnique(itemView.ViewID);
}
}
public static void PushUniqueState(Item item)
{
if ((Object)(object)item != (Object)null)
{
CopyUniqueToSlot(item, FungusInventoryHelper.FindSlotForItem(item));
}
PushItemInstanceData(item);
BroadcastUnique(item);
SyncHolderInventory(((Object)(object)item != (Object)null) ? item.holderCharacter : null);
}
public static void PushItemInstanceData(Item item)
{
if ((Object)(object)item == (Object)null || item.data == null || !PhotonNetwork.InRoom)
{
return;
}
PhotonView itemView = GetItemView(item);
if (!((Object)(object)itemView == (Object)null) && (itemView.IsMine || PhotonNetwork.IsMasterClient) && HasExplicitUnique(item))
{
RememberUnique(itemView.ViewID, GetIsUnique(item) ? 1 : 0);
try
{
itemView.RPC("SetItemInstanceDataRPC", (RpcTarget)1, new object[1] { item.data });
}
catch (Exception ex)
{
SelfToShelf.LogInfo("[Self To Shelf] SetItemInstanceDataRPC failed: " + ex.Message);
}
BroadcastUnique(item);
}
}
public static void BroadcastUnique(Item item)
{
if (!((Object)(object)item == (Object)null) && PhotonNetwork.InRoom)
{
PhotonView itemView = GetItemView(item);
if (!((Object)(object)itemView == (Object)null) && (itemView.IsMine || PhotonNetwork.IsMasterClient) && HasExplicitUnique(item))
{
int num = (GetIsUnique(item) ? 1 : 0);
RememberUnique(itemView.ViewID, num);
Raise(2, itemView.ViewID, num, (ReceiverGroup)0);
}
}
}
public static void BroadcastSpawn(int spawnViewId, bool isCloud)
{
if (spawnViewId <= 0)
{
return;
}
UniqueSpawnIsCloud[spawnViewId] = isCloud;
if (!PhotonNetwork.InRoom)
{
return;
}
if (!PhotonNetwork.IsMasterClient)
{
PhotonView val = PhotonView.Find(spawnViewId);
if ((Object)(object)val == (Object)null || !val.IsMine)
{
return;
}
}
Raise(4, spawnViewId, isCloud ? 1 : 0, (ReceiverGroup)0);
}
public static void ApplyRemoteUnique(int itemViewId, int unique)
{
RememberUnique(itemViewId, unique);
if (!ShelfToShelfRuntime.ShouldApplyModEffects())
{
return;
}
PhotonView val = PhotonView.Find(itemViewId);
if (!((Object)(object)val == (Object)null))
{
Item component = ((Component)val).GetComponent<Item>();
if (SelfToShelf.IsShelfFungus(component))
{
SetUnique(component, unique == 1);
FungusVisuals.ApplyToItem(component, unique == 1);
}
}
}
public static void ApplyRemoteSpawn(int spawnViewId, bool isCloud)
{
UniqueSpawnIsCloud[spawnViewId] = isCloud;
if (ShelfToShelfRuntime.ShouldApplyModEffects())
{
PhotonView val = PhotonView.Find(spawnViewId);
if ((Object)(object)val == (Object)null)
{
StartRoutine(SpawnCatchupRoutine(spawnViewId, isCloud));
}
else
{
FungusVisuals.ApplyToSpawn(((Component)val).transform, isCloud);
}
}
}
public static void RequestUniqueFromHost(Item item)
{
if (!((Object)(object)item == (Object)null) && PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient)
{
PhotonView itemView = GetItemView(item);
if (!((Object)(object)itemView == (Object)null))
{
Raise(3, itemView.ViewID, 0, (ReceiverGroup)2);
}
}
}
public static void RespondToUniqueRequest(int itemViewId)
{
if (!PhotonNetwork.IsMasterClient)
{
return;
}
PhotonView val = PhotonView.Find(itemViewId);
Item item = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<Item>() : null);
if (SelfToShelf.IsShelfFungus(item))
{
if (!HasExplicitUnique(item))
{
FungusSpawnHelper.ScheduleDeferredTag(item);
return;
}
BroadcastUnique(item);
PushItemInstanceData(item);
}
}
public static void BroadcastAll()
{
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
if (!PhotonNetwork.IsMasterClient)
{
return;
}
Item[] array = Resources.FindObjectsOfTypeAll<Item>();
if (array != null)
{
foreach (Item val in array)
{
if (SelfToShelf.IsShelfFungus(val) && !((Object)(object)((Component)val).gameObject == (Object)null))
{
Scene scene = ((Component)val).gameObject.scene;
if (((Scene)(ref scene)).IsValid() && HasExplicitUnique(val))
{
BroadcastUnique(val);
PushItemInstanceData(val);
}
}
}
}
foreach (KeyValuePair<int, bool> item in UniqueSpawnIsCloud)
{
Raise(4, item.Key, item.Value ? 1 : 0, (ReceiverGroup)0);
}
}
public static void SyncHolderInventory(Character character)
{
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)character == (Object)null || (Object)(object)character.player == (Object)null || !PhotonNetwork.InRoom || !character.IsLocal)
{
return;
}
PhotonView component = ((Component)character.player).GetComponent<PhotonView>();
if ((Object)(object)component == (Object)null)
{
return;
}
try
{
InventorySyncData val = default(InventorySyncData);
((InventorySyncData)(ref val))..ctor(character.player.itemSlots, character.player.backpackSlot, character.player.tempFullSlot);
component.RPC("SyncInventoryRPC", (RpcTarget)1, new object[2]
{
IBinarySerializable.ToManagedArray<InventorySyncData>(val),
false
});
}
catch (Exception ex)
{
SelfToShelf.LogInfo("[Self To Shelf] SyncInventoryRPC failed: " + ex.Message);
}
}
public static void PreserveOnStash(Item item)
{
if (SelfToShelf.IsShelfFungus(item) && !((Object)(object)item.holderCharacter == (Object)null) && !((Object)(object)item.holderCharacter.player == (Object)null))
{
ItemSlot val = FungusInventoryHelper.FindSlotForItem(item);
if (val != null && !val.IsEmpty())
{
CopyUniqueToSlot(item, val);
SyncHolderInventory(item.holderCharacter);
}
}
}
public static void PreserveBeforeDrop(Item item)
{
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
if (!SelfToShelf.IsShelfFungus(item) || (Object)(object)item.holderCharacter == (Object)null || (Object)(object)item.holderCharacter.player == (Object)null || !item.HasData(UniqueShelfShroomDataEntryKey.IsUnique))
{
return;
}
ItemSlot val = FungusInventoryHelper.FindSlotForItem(item);
if (val == null || val.IsEmpty())
{
return;
}
try
{
CopyUniqueToSlot(item, val);
}
catch (Exception ex)
{
SelfToShelf.LogInfo("[Self To Shelf] preserve unique before drop failed: " + ex.Message);
}
}
public static void ScheduleSpawnResync(Item item)
{
StartRoutine(SpawnResyncRoutine(item));
}
public static void ScheduleClientCatchup(Item item)
{
StartRoutine(ClientCatchupRoutine(item));
}
public static void SchedulePaintSpawn(Vector3 searchPos, bool isCloud)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
StartRoutine(PaintSpawnRoutine(searchPos, isCloud));
}
public static bool TryBeginDeferredTag(int viewId)
{
return DeferredTagInFlight.Add(viewId);
}
public static void EndDeferredTag(int viewId)
{
DeferredTagInFlight.Remove(viewId);
}
public static void StartRoutine(IEnumerator routine)
{
if (routine != null)
{
if ((Object)(object)ShelfToShelfNetProxy.Instance != (Object)null)
{
ShelfToShelfNetProxy.Instance.StartRoutine(routine);
}
else if ((Object)(object)SelfToShelf.Instance != (Object)null)
{
((MonoBehaviour)SelfToShelf.Instance).StartCoroutine(routine);
}
}
}
private static IEnumerator SpawnResyncRoutine(Item item)
{
yield return null;
if ((Object)(object)item != (Object)null)
{
PushItemInstanceData(item);
}
yield return (object)new WaitForSeconds(0.35f);
if ((Object)(object)item != (Object)null)
{
PushItemInstanceData(item);
}
}
private static IEnumerator ClientCatchupRoutine(Item item)
{
float[] waits = new float[3] { 0.05f, 0.2f, 0.5f };
for (int i = 0; i < waits.Length; i++)
{
yield return (object)new WaitForSeconds(waits[i]);
if ((Object)(object)item == (Object)null)
{
break;
}
if (TryApplyRemembered(item) || HasExplicitUnique(item))
{
FungusVisuals.ApplyFromItemData(item);
break;
}
RequestUniqueFromHost(item);
}
}
private static IEnumerator SpawnCatchupRoutine(int viewId, bool isCloud)
{
float[] waits = new float[4] { 0.05f, 0.2f, 0.5f, 1f };
for (int i = 0; i < waits.Length; i++)
{
yield return (object)new WaitForSeconds(waits[i]);
PhotonView view = PhotonView.Find(viewId);
if (!((Object)(object)view == (Object)null))
{
FungusVisuals.ApplyToSpawn(((Component)view).transform, isCloud);
break;
}
}
}
private static IEnumerator PaintSpawnRoutine(Vector3 searchPos, bool isCloud)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
yield return null;
yield return null;
Transform spawn = FindSpawnNear(searchPos);
if ((Object)(object)spawn == (Object)null)
{
yield return (object)new WaitForSeconds(0.25f);
spawn = FindSpawnNear(searchPos);
}
if (!((Object)(object)spawn == (Object)null))
{
FungusVisuals.ApplyToSpawn(spawn, isCloud);
PhotonView view = GetView((Component)(object)spawn);
if ((Object)(object)view != (Object)null)
{
BroadcastSpawn(view.ViewID, isCloud);
}
}
}
private static Transform FindSpawnNear(Vector3 searchPos)
{
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
Transform[] array = Object.FindObjectsByType<Transform>((FindObjectsSortMode)0);
Transform result = null;
float num = 0.9f;
foreach (Transform val in array)
{
if (SelfToShelf.IsTeleportSpawn(val))
{
float num2 = Vector3.Distance(val.position, searchPos);
if (num2 < num)
{
num = num2;
result = val;
}
}
}
return result;
}
private static void Raise(byte sub, int viewId, int value, ReceiverGroup receivers)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Expected O, but got Unknown
try
{
PhotonNetwork.RaiseEvent((byte)163, (object)SelfToShelf.PackEvent(sub, viewId, value), new RaiseEventOptions
{
Receivers = receivers
}, SendOptions.SendReliable);
}
catch (Exception ex)
{
SelfToShelf.LogInfo("[Self To Shelf] RaiseEvent failed: " + ex.Message);
}
}
internal static void HandleGameplayEvent(byte sub, object[] payload)
{
if (payload == null || payload.Length < 4)
{
return;
}
int num = Convert.ToInt32(payload[3]);
if (sub == 3)
{
RespondToUniqueRequest(num);
}
else if (payload.Length >= 5)
{
int num2 = Convert.ToInt32(payload[4]);
switch (sub)
{
case 2:
ApplyRemoteUnique(num, num2);
break;
case 4:
ApplyRemoteSpawn(num, num2 == 1);
break;
}
}
}
}
internal static class FungusSpawnHelper
{
private static bool _loggedInitError;
private static readonly List<Item> _pendingHandshake = new List<Item>();
public static void Initialize(Item item)
{
try
{
InitializeInner(item);
}
catch (Exception ex)
{
if (!_loggedInitError)
{
_loggedInitError = true;
SelfToShelf.LogInfo("[Self To Shelf] fungus spawn init failed: " + ex);
}
}
}
private static void InitializeInner(Item item)
{
if (!SelfToShelf.IsShelfFungus(item) || !SelfToShelf.IsLiveWorldItem(item))
{
return;
}
if (!ShelfToShelfRuntime.ShouldApplyModEffects())
{
if (ShelfToShelfRuntime.IsAwaitingHostSync)
{
QueueUntilHandshake(item);
}
}
else if (FungusNetworkSync.HasExplicitUnique(item))
{
FungusVisuals.ApplyFromItemData(item);
if (FungusNetworkSync.CanTagItems())
{
FungusNetworkSync.PushItemInstanceData(item);
}
}
else if (!FungusNetworkSync.CanTagItems())
{
FungusNetworkSync.TryApplyRemembered(item);
if (FungusNetworkSync.HasExplicitUnique(item))
{
FungusVisuals.ApplyFromItemData(item);
return;
}
FungusNetworkSync.RequestUniqueFromHost(item);
FungusNetworkSync.ScheduleClientCatchup(item);
}
else
{
FungusNetworkSync.ForgetUnique(item);
ScheduleDeferredTag(item);
}
}
public static void QueueUntilHandshake(Item item)
{
if (!((Object)(object)item == (Object)null) && !_pendingHandshake.Contains(item))
{
_pendingHandshake.Add(item);
}
}
public static void ClearPending()
{
_pendingHandshake.Clear();
}
public static void RetagUntaggedFungus()
{
if (!ShelfToShelfRuntime.ShouldApplyModEffects())
{
return;
}
for (int num = _pendingHandshake.Count - 1; num >= 0; num--)
{
Item val = _pendingHandshake[num];
_pendingHandshake.RemoveAt(num);
if ((Object)(object)val != (Object)null)
{
Initialize(val);
}
}
Item[] array = Resources.FindObjectsOfTypeAll<Item>();
if (array == null)
{
return;
}
foreach (Item item in array)
{
if (SelfToShelf.IsShelfFungus(item) && SelfToShelf.IsLiveWorldItem(item))
{
if (FungusNetworkSync.HasExplicitUnique(item))
{
FungusVisuals.ApplyFromItemData(item);
}
else
{
Initialize(item);
}
}
}
}
public static void ScheduleDeferredTag(Item item)
{
if (!((Object)(object)item == (Object)null) && FungusNetworkSync.CanTagItems())
{
PhotonView itemView = FungusNetworkSync.GetItemView(item);
int viewId = (((Object)(object)itemView != (Object)null) ? itemView.ViewID : ((Object)item).GetInstanceID());
if (FungusNetworkSync.TryBeginDeferredTag(viewId))
{
FungusNetworkSync.StartRoutine(DeferredTagRoutine(item, viewId));
}
}
}
private static IEnumerator DeferredTagRoutine(Item item, int viewId)
{
yield return null;
yield return null;
try
{
if (!((Object)(object)item == (Object)null))
{
if (FungusNetworkSync.HasExplicitUnique(item))
{
FungusVisuals.ApplyFromItemData(item);
FungusNetworkSync.PushItemInstanceData(item);
yield break;
}
bool unique = SelfToShelf.RollChance(SelfToShelf.GetUniqueChance(item));
FungusNetworkSync.SetUnique(item, unique);
FungusVisuals.ApplyToItem(item, unique);
FungusNetworkSync.PushUniqueState(item);
FungusNetworkSync.ScheduleSpawnResync(item);
}
}
finally
{
FungusNetworkSync.EndDeferredTag(viewId);
}
}
}
[HarmonyPatch(typeof(Item), "SetItemInstanceDataRPC")]
internal static class Item_SetItemInstanceDataRPC_Fungus_Patch
{
private static bool _loggedError;
private static void Postfix(Item __instance)
{
try
{
if (!SelfToShelf.IsShelfFungus(__instance))
{
return;
}
if (!ShelfToShelfRuntime.ShouldApplyModEffects())
{
if (ShelfToShelfRuntime.IsAwaitingHostSync)
{
FungusSpawnHelper.QueueUntilHandshake(__instance);
}
return;
}
if (FungusNetworkSync.CanTagItems())
{
if (FungusNetworkSync.HasExplicitUnique(__instance))
{
FungusVisuals.ApplyFromItemData(__instance);
}
else
{
FungusSpawnHelper.ScheduleDeferredTag(__instance);
}
return;
}
FungusNetworkSync.TryApplyRemembered(__instance);
FungusVisuals.ApplyFromItemData(__instance);
if (!FungusNetworkSync.HasExplicitUnique(__instance))
{
FungusNetworkSync.RequestUniqueFromHost(__instance);
FungusNetworkSync.ScheduleClientCatchup(__instance);
}
}
catch (Exception ex)
{
if (!_loggedError)
{
_loggedError = true;
SelfToShelf.LogInfo("[Self To Shelf] SetItemInstanceDataRPC postfix failed: " + ex);
}
}
}
}
[HarmonyPatch(typeof(Item), "OnDestroy")]
internal static class Item_OnDestroy_Fungus_Patch
{
private static void Prefix(Item __instance)
{
if (SelfToShelf.IsShelfFungus(__instance))
{
FungusNetworkSync.ForgetUnique(__instance);
}
}
}
[HarmonyPatch(typeof(Item), "OnStash")]
internal static class Item_OnStash_Fungus_Patch
{
private static void Prefix(Item __instance)
{
FungusNetworkSync.PreserveOnStash(__instance);
}
}
[HarmonyPatch(typeof(CharacterItems), "DoDropping")]
internal static class CharacterItems_DoDropping_Fungus_Patch
{
private static void Prefix()
{
try
{
Item item = (((Object)(object)Character.localCharacter != (Object)null && (Object)(object)Character.localCharacter.data != (Object)null) ? Character.localCharacter.data.currentItem : null);
FungusNetworkSync.PreserveBeforeDrop(item);
}
catch
{
}
}
}
namespace System.Runtime.CompilerServices;
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}