Decompiled source of BasicItemSync v0.1.4

BasicItemSync.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BasicItemSync.Data;
using BasicItemSync.Modules;
using BasicItemSync.Modules.Hooks;
using BasicItemSync.Modules.Mocks;
using BasicItemSync.Modules.Network.Client;
using BasicItemSync.Modules.Network.Server;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GenericVariableExtension;
using HarmonyLib;
using HutongGames.PlayMaker;
using HutongGames.PlayMaker.Actions;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using SSMP.Api.Client;
using SSMP.Api.Client.Networking;
using SSMP.Api.Command;
using SSMP.Api.Command.Client;
using SSMP.Api.Command.Server;
using SSMP.Api.Server;
using SSMP.Api.Server.Networking;
using SSMP.Logging;
using SSMP.Networking.Packet;
using SSMP.Networking.Packet.Data;
using Silksong.AssetHelper.ManagedAssets;
using TeamCherry.Localization;
using UnityEngine;
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BasicItemSync")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.1.4.0")]
[assembly: AssemblyInformationalVersion("0.1.4+10c83be3909b0405b5ddfcf3e06e82b6dd61e136")]
[assembly: AssemblyProduct("BasicItemSync")]
[assembly: AssemblyTitle("BasicItemSync")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/BobbyTheCatfish/BasicItemSync")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.4.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class ExtensionMarkerAttribute : Attribute
	{
		private readonly string <Name>k__BackingField;

		public string Name => <Name>k__BackingField;

		public ExtensionMarkerAttribute(string name)
		{
			<Name>k__BackingField = name;
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BasicItemSync
{
	internal class Common
	{
		internal const string AddonName = "BasicItemSync";

		internal const string AddonVersion = "0.1.4";

		internal const int AddonApiVersion = 1;
	}
	internal enum FlagType
	{
		Ability,
		Map,
		Pin,
		Bellshrine,
		Boss,
		Arena,
		Progression,
		Collectable,
		Bellway,
		Ventrica,
		Mask,
		Spool,
		Pouch,
		CraftingKit,
		SilkHeart,
		Needle,
		Quest,
		QuestStart,
		QuestItem,
		Tool,
		Crest,
		Currency,
		Shortcut,
		Bench,
		Flea,
		DoNotSync
	}
	internal enum InternalCurrencyType
	{
		Rosary,
		ShellShard
	}
	internal enum Packets
	{
		BoolPlayerData,
		IntPlayerData,
		FloatPlayerData,
		Collectable,
		Currency,
		Quest,
		Tool,
		Upgrade,
		Settings,
		PersistentBool,
		PersistentInt
	}
	internal class FakeLogger : ILogger
	{
		public void Debug(string message)
		{
		}

		public void Error(string message)
		{
		}

		public void Info(string message)
		{
		}

		public void Message(string message)
		{
		}

		public void Warn(string message)
		{
		}
	}
	internal static class Log
	{
		private static ILogger logger = (ILogger)(object)new FakeLogger();

		private static IModSettings settings = new MockModSettings();

		public static void SetLogger(ILogger log)
		{
			logger = log;
			try
			{
				ModSettings modSettings = new ModSettings();
				bool instanceDebugLogs = modSettings.InstanceDebugLogs;
				settings = modSettings;
			}
			catch
			{
				logger.Warn("Unable to load ModSettings. Likely using standalone server.");
			}
		}

		private static bool ShouldLog(LogEventArgs log)
		{
			if (log.Source.SourceName == "SSMP" && log.Data is string text && text.StartsWith("[BasicItemSync"))
			{
				return true;
			}
			return false;
		}

		public static void LogInfo(params object[] data)
		{
			foreach (object obj in data)
			{
				logger.Info(obj.ToString());
			}
		}

		public static void LogWarning(params object[] data)
		{
			foreach (object obj in data)
			{
				logger.Warn(obj.ToString());
			}
		}

		public static void LogError(params object[] data)
		{
			foreach (object obj in data)
			{
				logger.Error(obj.ToString());
			}
		}

		public static void LogFatal(params object[] data)
		{
			foreach (object obj in data)
			{
				logger.Error(obj.ToString());
			}
		}

		public static void LogDebug(params object[] data)
		{
			if (settings.InstanceDebugLogs)
			{
				foreach (object obj in data)
				{
					logger.Debug(obj.ToString());
				}
			}
		}

		public static void LogMessage(params object[] data)
		{
			foreach (object obj in data)
			{
				logger.Message(obj.ToString());
			}
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("io.github.bobbythecatfish.basicitemsync", "BasicItemSync", "0.1.4")]
	public class SyncPlugin : BaseUnityPlugin
	{
		private static List<Action> CurrentFrameActions = new List<Action>();

		private static List<Action> NextFrameActions = new List<Action>();

		internal static SyncPlugin Instance;

		internal static Dictionary<string, ManagedAsset<FakeCollectable>> Collectables = new Dictionary<string, ManagedAsset<FakeCollectable>>();

		public const string Id = "io.github.bobbythecatfish.basicitemsync";

		public static string Name => "BasicItemSync";

		public static string Version => "0.1.4";

		private void Awake()
		{
			Instance = this;
			ModSettings.Init(((BaseUnityPlugin)this).Config);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Plugin " + Name + " (io.github.bobbythecatfish.basicitemsync) has loaded!"));
			ClientAddon.RegisterAddon((ClientAddon)(object)new ClientAddon());
			ServerAddon.RegisterAddon((ServerAddon)(object)new ServerAddon());
			Collectables["Mask"] = ManagedAsset<FakeCollectable>.FromNonSceneAsset("Assets/Data Assets/Collectables/Fake Collectables/Heart Piece.asset", "dataassets_assets_assets/dataassets/collectables/fakecollectables");
			Collectables["Spool"] = ManagedAsset<FakeCollectable>.FromNonSceneAsset("Assets/Data Assets/Collectables/Fake Collectables/Silk Spool.asset", "dataassets_assets_assets/dataassets/collectables/fakecollectables");
			Collectables["Pouch"] = ManagedAsset<FakeCollectable>.FromNonSceneAsset("Assets/Data Assets/Collectables/Fake Collectables/Tool Pouch Pickup.asset", "dataassets_assets_assets/dataassets/collectables/fakecollectables");
			Collectables["CraftKit"] = ManagedAsset<FakeCollectable>.FromNonSceneAsset("Assets/Data Assets/Collectables/Fake Collectables/Tool Kit Pickup.asset", "dataassets_assets_assets/dataassets/collectables/fakecollectables");
			Collectables["SilkHeart"] = ManagedAsset<FakeCollectable>.FromNonSceneAsset("Assets/Data Assets/Collectables/Fake Collectables/Silk Heart.asset", "dataassets_assets_assets/dataassets/collectables/fakecollectables");
			Collectables["Needle"] = ManagedAsset<FakeCollectable>.FromNonSceneAsset("Assets/Data Assets/Collectables/Fake Collectables/Needle Upgrade.asset", "dataassets_assets_assets/dataassets/collectables/fakecollectables");
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
		}

		internal static void AddNextFrameAction(Action action)
		{
			NextFrameActions.Add(action);
		}

		private void Update()
		{
			if (CurrentFrameActions.Count > 0)
			{
				Action[] array = CurrentFrameActions.ToArray();
				CurrentFrameActions.Clear();
				Action[] array2 = array;
				foreach (Action action in array2)
				{
					action();
				}
			}
		}

		private void LateUpdate()
		{
			if (NextFrameActions.Count > 0)
			{
				CurrentFrameActions = NextFrameActions.ToList();
				NextFrameActions.Clear();
			}
		}
	}
}
namespace BasicItemSync.Modules
{
	internal class BattleManager
	{
		private static BattleScene? GetBattleScene(string keyName)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			GameObject[] rootGameObjects = ((Scene)(ref activeScene)).GetRootGameObjects();
			GameObject[] array = rootGameObjects;
			DeactivateIfPlayerdataTrue val3 = default(DeactivateIfPlayerdataTrue);
			foreach (GameObject val in array)
			{
				BattleScene[] componentsInChildren = val.GetComponentsInChildren<BattleScene>();
				BattleScene[] array2 = componentsInChildren;
				foreach (BattleScene val2 in array2)
				{
					if (((Component)val2).TryGetComponent<DeactivateIfPlayerdataTrue>(ref val3) && val3.boolName == keyName)
					{
						return val2;
					}
				}
			}
			return null;
		}

		public static void DefeatBattleScene(string keyName)
		{
			if (keyName == "defeatedBellBeast")
			{
				OnBellBeast();
				return;
			}
			BattleScene battleScene = GetBattleScene(keyName);
			if (Object.op_Implicit((Object)(object)battleScene))
			{
				DefeatBattleScene(battleScene);
			}
		}

		public static void DefeatBattleScene(BattleScene battle)
		{
			if (battle.started)
			{
				int currentWave = battle.currentWave;
				battle.DoEndBattle();
				HealthManager[] componentsInChildren = ((Component)battle.waves[currentWave]).gameObject.GetComponentsInChildren<HealthManager>();
				foreach (HealthManager val in componentsInChildren)
				{
					if (!val.isDead)
					{
						val.Die((float?)0f, (AttackTypes)0, true);
					}
				}
				return;
			}
			battle.BattleCompleted();
			battle.completed = true;
			if (!string.IsNullOrEmpty(battle.setPDBoolOnEnd))
			{
				VariableExtensionsGeneric.SetVariable<bool>((object)PlayerData.instance, battle.setPDBoolOnEnd, true);
			}
			if (!string.IsNullOrEmpty(battle.setExtraPDBoolOnEnd))
			{
				VariableExtensionsGeneric.SetVariable<bool>((object)PlayerData.instance, battle.setExtraPDBoolOnEnd, true);
			}
			if (Object.op_Implicit((Object)(object)battle.camLocks) && !battle.dontDisableCamlocksOnEnd)
			{
				battle.camLocks.SetActive(false);
			}
			if (battle.openGatesOnEnd)
			{
				battle.SendEventToChildren("BG OPEN");
			}
			if (Object.op_Implicit((Object)(object)battle.endScene))
			{
				battle.SendEventToChildren("BATTLE END");
			}
			if (Object.op_Implicit((Object)(object)battle.activeDuringBattle))
			{
				battle.activeDuringBattle.SetActive(false);
			}
			if (battle.disableActiveBeforeBattleAtEnd)
			{
				battle.activeBeforeBattle.SetActive(false);
			}
			if (!string.IsNullOrEmpty(battle.battleEndEventRegister))
			{
				EventRegister.SendEvent(battle.battleEndEventRegister, (GameObject)null);
			}
		}

		private static void OnBellBeast()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			SceneData.instance.PersistentBools.SetValue(new PersistentItemData<bool>
			{
				ID = "Silk Heart",
				SceneName = "Bone_05",
				IsSemiPersistent = false,
				Value = false,
				Mutator = (PersistentMutatorTypes)0
			});
			Scene activeScene = SceneManager.GetActiveScene();
			bool flag = ClientAddon.Settings.FlagAllowed(FlagType.SilkHeart);
			if (!(((Scene)(ref activeScene)).name == "Bone_05"))
			{
				return;
			}
			Scene sceneByName = SceneManager.GetSceneByName("Bone_05_boss");
			if (((Scene)(ref sceneByName)).IsValid())
			{
				GameObject[] rootGameObjects = ((Scene)(ref sceneByName)).GetRootGameObjects();
				foreach (GameObject val in rootGameObjects)
				{
					val.SetActive(false);
				}
			}
			if (flag)
			{
				return;
			}
			GameObject val2 = ((Scene)(ref sceneByName)).GetRootGameObjects()[0];
			for (int j = 0; j < val2.transform.childCount; j++)
			{
				Transform child = val2.transform.GetChild(j);
				if (((Object)child).name == "Silk Heart")
				{
					((Component)child).gameObject.SetActive(true);
					break;
				}
			}
		}
	}
	internal class ClientState
	{
		public static string LastItem = "";

		public static string LastPlayerData = "";

		public static string LastPersistent = "";

		public static int LastCurrency = 0;

		public static FlagType LastUpgrade = FlagType.Currency;

		public static bool WasItemReceived(string item)
		{
			return LastItem == item;
		}

		public static bool WasCurrencyReceived(int amount)
		{
			return LastCurrency == amount;
		}

		public static bool WasUpgradeReceived(FlagType flagType)
		{
			return LastUpgrade == flagType;
		}

		public static bool WasPersistentReceived(string key)
		{
			return LastPersistent == key;
		}
	}
	internal class ModSettings : IModSettings
	{
		private static ConfigEntry<bool> _debugPlayerData;

		private static ConfigEntry<bool> _debugLogs;

		public bool InstanceDebugPlayerData => DebugPlayerData;

		public static bool DebugPlayerData => _debugPlayerData?.Value ?? false;

		public bool InstanceDebugLogs => DebugLogs;

		public static bool DebugLogs => _debugLogs?.Value ?? false;

		public static void Init(ConfigFile config)
		{
			_debugLogs = config.Bind<bool>("Debug", "Enable debug logs", true, (ConfigDescription)null);
			_debugPlayerData = config.Bind<bool>("Debug", "Enable PlayerData logs", false, (ConfigDescription)null);
		}
	}
	internal static class ObjectHelper
	{
		[SpecialName]
		public sealed class <G>$DA70E330990F800FE2D4138C4621F754
		{
			[SpecialName]
			public static class <M>$8E4C3D964507E1AE94619A23CAEF85BC
			{
			}

			[ExtensionMarker("<M>$8E4C3D964507E1AE94619A23CAEF85BC")]
			public static string GetLocal(LocalisedString str)
			{
				throw new NotSupportedException();
			}
		}

		public static PersistentItem<T>? FindPersistent<T>(string sceneName, string id) where T : IEquatable<T>
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			Scene scene = SceneManager.GetActiveScene();
			return ((IEnumerable<PersistentItem<T>>)Resources.FindObjectsOfTypeAll<PersistentItem<T>>()).FirstOrDefault((Func<PersistentItem<T>, bool>)((PersistentItem<T> p) => p.ItemData.ID == id && p.ItemData.SceneName == sceneName && ((Component)p).gameObject.scene == scene));
		}

		public static string GetLocal(LocalisedString str)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return Language.Get(str.Key, str.Sheet);
		}
	}
	internal class PersistentHandler
	{
		private static readonly List<string> FsmEvents = new List<string>(5) { "QUICK BREAK", "ACTIVATE", "ACTIVATED", "DESTROY", "UNLOCK" };

		public static void SetPersistentIntData(string sceneName, string id, int status, FlagType flagType)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			PersistentItemData<int> val = default(PersistentItemData<int>);
			if (SceneData.instance.PersistentInts.TryGetValue(sceneName, id, ref val))
			{
				val.Value = status;
			}
			else
			{
				PersistentItemData<int> value = new PersistentItemData<int>
				{
					SceneName = sceneName,
					ID = id,
					IsSemiPersistent = false,
					Value = status
				};
				SceneData.instance.PersistentInts.SetValue(value);
			}
			if (flagType == FlagType.Currency)
			{
				Scene activeScene = SceneManager.GetActiveScene();
				if (((Scene)(ref activeScene)).name != sceneName)
				{
					return;
				}
			}
			PersistentItem<int> val2 = ObjectHelper.FindPersistent<int>(sceneName, id);
			if (!((Object)(object)val2 == (Object)null))
			{
				PersistentIntItem val3 = (PersistentIntItem)(object)((val2 is PersistentIntItem) ? val2 : null);
				if (val3 != null)
				{
					((PersistentItem<int>)(object)val3).ItemData.Value = status;
					((PersistentItem<int>)(object)val3).Start();
				}
			}
		}

		public static void SetPersistentBoolData(string sceneName, string id, bool status, bool forceDisable = false)
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			PersistentItemData<bool> val = default(PersistentItemData<bool>);
			if (SceneData.instance.PersistentBools.TryGetValue(sceneName, id, ref val))
			{
				val.Value = status;
			}
			else
			{
				PersistentItemData<bool> value = new PersistentItemData<bool>
				{
					SceneName = sceneName,
					ID = id,
					IsSemiPersistent = false,
					Value = status
				};
				SceneData.instance.PersistentBools.SetValue(value);
			}
			PersistentItem<bool> val2 = ObjectHelper.FindPersistent<bool>(sceneName, id);
			if (!((Object)(object)val2 == (Object)null))
			{
				PersistentBoolItem val3 = (PersistentBoolItem)(object)((val2 is PersistentBoolItem) ? val2 : null);
				if (val3 != null)
				{
					((PersistentItem<bool>)(object)val3).ItemData.Value = status;
					Lever val4 = default(Lever);
					Lever_tk2d val5 = default(Lever_tk2d);
					PersistentBoolItemResponder val6 = default(PersistentBoolItemResponder);
					CollectableItemPickup val7 = default(CollectableItemPickup);
					BattleScene battle = default(BattleScene);
					if (((Component)val3).TryGetComponent<Lever>(ref val4))
					{
						TrackTriggerObjects canHitTrigger = val4.canHitTrigger;
						val4.canHitTrigger = null;
						val4.Hit(new HitInstance
						{
							IsFirstHit = true,
							IsNailTag = true,
							Direction = 0f
						});
						val4.canHitTrigger = canHitTrigger;
					}
					else if (((Component)val3).TryGetComponent<Lever_tk2d>(ref val5))
					{
						TrackTriggerObjects canHitTrigger2 = val5.canHitTrigger;
						val5.canHitTrigger = null;
						val5.Hit(new HitInstance
						{
							IsFirstHit = true,
							IsNailTag = true,
							Direction = 0f
						});
						val5.canHitTrigger = canHitTrigger2;
					}
					else if (Object.op_Implicit((Object)(object)((PersistentItem<bool>)(object)val3).fsm))
					{
						((PersistentItem<bool>)(object)val3).SetValueOnFSM(((PersistentItem<bool>)(object)val3).fsm, status);
						string activeStateName = ((PersistentItem<bool>)(object)val3).fsm.ActiveStateName;
						foreach (string fsmEvent in FsmEvents)
						{
							if (((PersistentItem<bool>)(object)val3).fsm.ActiveStateName == activeStateName)
							{
								((PersistentItem<bool>)(object)val3).fsm.SendEvent(fsmEvent);
							}
						}
					}
					else if (((Component)val3).TryGetComponent<PersistentBoolItemResponder>(ref val6))
					{
						val6.InvokeEvents(status);
					}
					else if (((Component)val3).TryGetComponent<CollectableItemPickup>(ref val7))
					{
						forceDisable = true;
					}
					else if (((Component)val3).TryGetComponent<BattleScene>(ref battle))
					{
						BattleManager.DefeatBattleScene(battle);
					}
					if (Object.op_Implicit((Object)(object)val3.disablePrefabIfActivated))
					{
						val3.disablePrefabIfActivated.SetActive(false);
					}
					if (val3.disableIfActivated || forceDisable)
					{
						((Component)val3).gameObject.SetActive(false);
					}
					return;
				}
			}
			Scene activeScene = SceneManager.GetActiveScene();
			if (sceneName == ((Scene)(ref activeScene)).name)
			{
				Log.LogWarning("Unable to find persistent " + sceneName + " " + id);
			}
		}
	}
	internal class QuestHandler
	{
		public static void EndQuest(string name)
		{
			FullQuestBase quest = QuestManager.GetQuest(name);
			if (Object.op_Implicit((Object)(object)quest))
			{
				quest.SilentlyComplete();
				quest.ConsumeTarget();
				UI.ShowPopup((ICollectableUIMsgItem)(object)new PopupItem(quest));
			}
		}

		public static void EndQuestSilent(string name)
		{
			FullQuestBase quest = QuestManager.GetQuest(name);
			if (Object.op_Implicit((Object)(object)quest))
			{
				quest.SilentlyComplete();
			}
		}
	}
	internal class UI
	{
		public static void ShowPopup(ICollectableUIMsgItem item)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			CollectableUIMsg.Spawn(item, Color.white, (CollectableUIMsg)null, false);
		}

		public static void ShowPopup(FlagType flagType, string key, string name)
		{
			if (!string.IsNullOrEmpty(name))
			{
				if (1 == 0)
				{
				}
				PopupItem popupItem = flagType switch
				{
					FlagType.Ability => GetAbilityIcon(key), 
					FlagType.Map => GetMap(name), 
					FlagType.Pin => GetPin(key, name), 
					_ => null, 
				};
				if (1 == 0)
				{
				}
				PopupItem popupItem2 = popupItem;
				if (popupItem2 != null)
				{
					ShowPopup((ICollectableUIMsgItem)(object)popupItem2);
				}
			}
		}

		private static PopupItem? GetAbilityIcon(string key)
		{
			Transform inv = GetInventory();
			Transform layout = inv.GetChild(1).GetChild(0).GetChild(1)
				.GetChild(2)
				.GetChild(2);
			if (1 == 0)
			{
			}
			PopupItem result = key switch
			{
				"hasDash" => GetIcon(0, "Swift Step"), 
				"hasHarpoonDash" => GetIcon(1, "Clawline"), 
				"HasBoundCrestUpgrader" => GetIcon(2, "Sylphsong"), 
				"hasSuperJump" => GetIcon(3, "Sillk Soar"), 
				"hasWalljump" => GetIcon(4, "Cling Grip"), 
				"hasNeedolin" => GetIcon(5, "Needolin"), 
				"UnlockedFastTravelTeleport" => GetIcon(5, "Beastling Call"), 
				"hasBrolly" => GetCloakIcon(1), 
				"hasDoubleJump" => GetCloakIcon(2), 
				"hasChargeSlash" => GetNeedleStrike(), 
				_ => null, 
			};
			if (1 == 0)
			{
			}
			return result;
			static PopupItem? GetCloakIcon(int state)
			{
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: 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)
				CollectableItem byName = ((NamedScriptableObjectList<CollectableItem>)(object)ManagerSingleton<CollectableItemManager>.Instance.masterList).GetByName("Dresses");
				CollectableItemStates val = (CollectableItemStates)(object)((byName is CollectableItemStates) ? byName : null);
				if (val == null)
				{
					return null;
				}
				ItemState val2 = val.states[state];
				return new PopupItem(ObjectHelper.GetLocal(val2.DisplayName), val2.Icon);
			}
			PopupItem GetIcon(int index, string text)
			{
				SpriteRenderer component = ((Component)layout.GetChild(index)).GetComponent<SpriteRenderer>();
				return new PopupItem(text, component.sprite);
			}
			PopupItem GetNeedleStrike()
			{
				SpriteRenderer component = ((Component)inv.GetChild(1).GetChild(0).GetChild(0)
					.GetChild(1)).GetComponent<SpriteRenderer>();
				return new PopupItem("Needle Strike", component.sprite);
			}
		}

		private static PopupItem GetMap(string name)
		{
			Transform inventory = GetInventory();
			InventoryPane component = ((Component)inventory.GetChild(2)).GetComponent<InventoryPane>();
			return new PopupItem(name + " Map", component.ListIcon);
		}

		private static PopupItem? GetPin(string key, string name)
		{
			Transform inventory = GetInventory();
			Transform map = inventory.GetChild(2);
			if (1 == 0)
			{
			}
			PopupItem result = key switch
			{
				"hasPinBench" => GetSpecialPin(0), 
				"hasPinCocoon" => GetSpecialPin(1), 
				"hasPinShop" => GetSpecialPin(4), 
				"hasPinSpa" => GetSpecialPin(1), 
				"hasPinStag" => GetSpecialPin(1), 
				"hasPinTube" => GetSpecialPin(5), 
				"hasPinFleaMarrowlands" => GetSpecialPin(3), 
				"hasPinFleaMidlands" => GetSpecialPin(3), 
				"hasPinFleaBlastedlands" => GetSpecialPin(3), 
				"hasPinFleaCitadel" => GetSpecialPin(3), 
				"hasPinFleaPeaklands" => GetSpecialPin(3), 
				"hasPinFleaMucklands" => GetSpecialPin(3), 
				"hasMarker_a" => GetMarkerPin(0), 
				"hasMarker_b" => GetMarkerPin(1), 
				"hasMarker_c" => GetMarkerPin(2), 
				"hasMarker_d" => GetMarkerPin(3), 
				"hasMarker_e" => GetMarkerPin(4), 
				_ => null, 
			};
			if (1 == 0)
			{
			}
			return result;
			PopupItem GetMarkerPin(int index)
			{
				Transform child = map.GetChild(1).GetChild(5);
				int num = child.childCount - 1;
				Transform child2 = child.GetChild(num).GetChild(index);
				SpriteRenderer componentInChildren = ((Component)child2).GetComponentInChildren<SpriteRenderer>(true);
				return new PopupItem(name, componentInChildren.sprite);
			}
			PopupItem GetSpecialPin(int index)
			{
				Transform child = map.GetChild(3).GetChild(0).GetChild(index);
				SpriteRenderer componentInChildren = ((Component)child).GetComponentInChildren<SpriteRenderer>(true);
				return new PopupItem(name, componentInChildren.sprite);
			}
		}

		private static Transform GetInventory()
		{
			GameObject gameObject = ((Component)GameCameras.instance.hudCamera).gameObject;
			return gameObject.transform.GetChild(0).GetChild(4);
		}
	}
	internal class PopupItem : ICollectableUIMsgItem, IUIMsgPopupItem
	{
		public string Name;

		public Sprite Sprite;

		public Object Object;

		public PopupItem(FullQuestBase quest)
		{
			//IL_0011: 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)
			Object = (Object)(object)quest;
			Name = Language.Get(((BasicQuestBase)quest).DisplayName.Key, ((BasicQuestBase)quest).DisplayName.Sheet);
			Sprite = ((BasicQuestBase)quest).QuestType.Icon;
		}

		public PopupItem(string name, Sprite sprite)
		{
			Name = name;
			Sprite = sprite;
			Object = (Object)(object)sprite;
		}

		public Object GetRepresentingObject()
		{
			return Object;
		}

		public float GetUIMsgIconScale()
		{
			return 1f;
		}

		public string GetUIMsgName()
		{
			return Name;
		}

		public Sprite GetUIMsgSprite()
		{
			return Sprite;
		}

		public bool HasUpgradeIcon()
		{
			return false;
		}
	}
	internal class Upgrader
	{
		private static FakeCollectable? MaskCollectable;

		private static FakeCollectable? SpoolCollectable;

		private static FakeCollectable? PouchCollectable;

		private static FakeCollectable? CraftingKitCollectable;

		private static FakeCollectable? SilkHeartCollectable;

		private static FakeCollectable? NeedleUpgrade;

		public static bool UpgradeMask(string sceneName)
		{
			string text = "Heart Piece";
			if (sceneName == "Bone_East_LavaChallenge")
			{
				text += " (1)";
			}
			PersistentHandler.SetPersistentBoolData(sceneName, text, status: true, forceDisable: true);
			PlayerData instance = PlayerData.instance;
			instance.heartPieces++;
			if (PlayerData.instance.heartPieces >= 4)
			{
				PlayerData.instance.heartPieces = 0;
				HeroController.instance.AddToMaxHealth(1);
				HeroController.instance.MaxHealth();
				EventRegister.SendEvent("MAX HP UP", (GameObject)null);
			}
			LoadAndDisplay(ref MaskCollectable, "Mask", "UI", "SHOP_SHELLFRAG_NAME");
			return Save();
		}

		public static bool UpgradeSpool(string sceneName)
		{
			PersistentHandler.SetPersistentBoolData(sceneName, "Silk Spool", status: true, forceDisable: true);
			PlayerData instance = PlayerData.instance;
			instance.silkSpoolParts++;
			if (PlayerData.instance.silkSpoolParts >= 2)
			{
				PlayerData.instance.silkSpoolParts = 0;
				HeroController.instance.AddToMaxSilk(1);
				EventRegister.SendEvent("SPOOL MAX UP", (GameObject)null);
			}
			LoadAndDisplay(ref SpoolCollectable, "Spool", "UI", "SHOP_SPOOL_SEGMENT_NAME");
			return Save();
		}

		public static bool GiveCollectable(string itemKey, int amount)
		{
			CollectableItem itemByName = CollectableItemManager.GetItemByName(itemKey);
			if (!Object.op_Implicit((Object)(object)itemByName))
			{
				CollectableRelic relic = CollectableRelicManager.GetRelic(itemKey);
				if (!Object.op_Implicit((Object)(object)relic))
				{
					Log.LogError("Unknown collectable " + itemKey);
					return false;
				}
				((SavedItem)relic).Get(false);
				return Save();
			}
			itemByName.AddAmount(amount);
			UI.ShowPopup((ICollectableUIMsgItem)(object)itemByName);
			return Save();
		}

		public static bool UpgradePouch()
		{
			PlayerData instance = PlayerData.instance;
			instance.ToolPouchUpgrades++;
			LoadAndDisplay(ref PouchCollectable, "Pouch", "UI", "INV_NAME_TOOLPOUCH");
			return Save();
		}

		public static bool UpgradeCraftingKit()
		{
			PlayerData instance = PlayerData.instance;
			instance.ToolKitUpgrades++;
			LoadAndDisplay(ref CraftingKitCollectable, "CraftKit", "UI", "INV_MSG_TOOLKIT");
			return Save();
		}

		public static bool UpgradeSilkHeart(string scene)
		{
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			PersistentItemData<bool> val = default(PersistentItemData<bool>);
			if (SceneData.instance.PersistentBools.TryGetValue(scene, "Silk Heart", ref val) && val.Value)
			{
				Log.LogDebug("[CLI: Upgrade Silk Heart] Already collected silk heart for " + scene);
				return false;
			}
			PlayerData instance = PlayerData.instance;
			instance.silkRegenMax++;
			Log.LogDebug("[CLI: Upgrade Silk Heart] Collecting silk heart for " + scene);
			SceneData.instance.PersistentBools.SetValue(new PersistentItemData<bool>
			{
				ID = "Silk Heart",
				SceneName = scene,
				IsSemiPersistent = false,
				Value = true,
				Mutator = (PersistentMutatorTypes)0
			});
			LoadAndDisplay(ref SilkHeartCollectable, "SilkHeart", "UI", "INV_DESC_SPOOL_SILKHEARTS");
			return Save();
		}

		public static bool UpgradeNeedle()
		{
			PlayerData instance = PlayerData.instance;
			instance.nailUpgrades++;
			LoadAndDisplay(ref NeedleUpgrade, "Needle", "UI", "INV_MSG_NEEDLE_UPGRADE");
			return Save();
		}

		private static void LoadAndDisplay(ref FakeCollectable? assetRef, string dictKey, string langSheet, string langKey)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)assetRef == (Object)null)
			{
				if (!SyncPlugin.Collectables.TryGetValue(dictKey, out ManagedAsset<FakeCollectable> value))
				{
					return;
				}
				if (!((ManagedAssetBase<FakeCollectable>)(object)value).IsLoaded)
				{
					((MonoBehaviour)SyncPlugin.Instance).StartCoroutine(Coroutine(value));
					return;
				}
				assetRef = ((ManagedAssetBase<FakeCollectable>)(object)value).Handle.Result;
			}
			UI.ShowPopup((ICollectableUIMsgItem)(object)assetRef);
			IEnumerator Coroutine(ManagedAsset<FakeCollectable> asset)
			{
				if (asset != null)
				{
					((ManagedAssetBase<FakeCollectable>)(object)asset).Load();
					yield return ((ManagedAssetBase<FakeCollectable>)(object)asset).Handle;
					if (((ManagedAssetBase<FakeCollectable>)(object)asset).Handle.OperationException != null)
					{
						Debug.LogError((object)$"Error loading asset: {((ManagedAssetBase<FakeCollectable>)(object)asset).Handle.OperationException}");
					}
					else
					{
						FakeCollectable result = ((ManagedAssetBase<FakeCollectable>)(object)asset).Handle.Result;
						result.uiMsgName = new LocalisedString
						{
							Sheet = langSheet,
							Key = langKey
						};
						UI.ShowPopup((ICollectableUIMsgItem)(object)result);
					}
				}
			}
		}

		public static bool Save()
		{
			if (!Object.op_Implicit((Object)(object)HeroController.SilentInstance))
			{
				Log.LogError("[CLI: SAVE] Not in save file. Cannot save data.");
				return false;
			}
			GameManager.instance.SaveGame((Action<bool>)delegate
			{
			});
			return true;
		}

		public static bool NoOp()
		{
			return false;
		}
	}
}
namespace BasicItemSync.Modules.Patches
{
	[HarmonyPatch(typeof(SceneLoad))]
	internal class ScenePatches
	{
		[HarmonyPatch("Begin")]
		[HarmonyPrefix]
		private static void Begin(SceneLoad __instance)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			__instance.Finish += (FinishDelegate)delegate
			{
				OnFinish(__instance);
			};
		}

		private static void OnFinish(SceneLoad __instance)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			SceneInstance result = __instance.OperationHandle.Result;
			Scene scene = ((SceneInstance)(ref result)).Scene;
			if (((Scene)(ref scene)).IsValid() && ((Scene)(ref scene)).name == "Bone_05")
			{
				OnBellBeast(scene);
			}
		}

		private static void OnBellBeast(Scene scene)
		{
			bool flag = ClientAddon.Settings.FlagAllowed(FlagType.SilkHeart);
			bool flag2 = ClientAddon.Settings.FlagAllowed(FlagType.Boss);
			PersistentItemData<bool> val = default(PersistentItemData<bool>);
			if (!flag && flag2 && SceneData.instance.PersistentBools.TryGetValue(((Scene)(ref scene)).name, "Silk Heart", ref val) && !val.Value)
			{
				GameObject val2 = ((IEnumerable<GameObject>)((Scene)(ref scene)).GetRootGameObjects()).FirstOrDefault((Func<GameObject, bool>)((GameObject obj) => ((Object)obj).name == "Silk Heart"));
				if (Object.op_Implicit((Object)(object)val2))
				{
					val2.SetActive(true);
				}
			}
		}
	}
}
namespace BasicItemSync.Modules.Network
{
	internal class Packet : IPacketData
	{
		public virtual bool IsReliable => true;

		public virtual bool DropReliableDataIfNewerExists => false;

		public virtual void ReadData(IPacket packet)
		{
		}

		public virtual void WriteData(IPacket packet)
		{
		}
	}
	internal class SendFlagPacket : Packet
	{
		public string Key = "";

		public string Name = "";

		public FlagType FlagType;

		public override void WriteData(IPacket packet)
		{
			packet.Write(Key);
			packet.Write(Name);
			packet.Write((int)FlagType);
		}

		public override void ReadData(IPacket packet)
		{
			Key = packet.ReadString();
			Name = packet.ReadString();
			FlagType = (FlagType)packet.ReadInt();
		}
	}
	internal class SendBoolItemPacket : SendFlagPacket
	{
		public bool State = true;

		public override void WriteData(IPacket packet)
		{
			base.WriteData(packet);
			packet.Write(State);
		}

		public override void ReadData(IPacket packet)
		{
			base.ReadData(packet);
			State = packet.ReadBool();
		}
	}
	internal class SendUpgradeItemPacket : SendFlagPacket
	{
		private FlagType UpgradeType;

		public override void WriteData(IPacket packet)
		{
			base.WriteData(packet);
			packet.Write((int)UpgradeType);
		}

		public override void ReadData(IPacket packet)
		{
			base.ReadData(packet);
			UpgradeType = (FlagType)packet.ReadInt();
		}
	}
	internal class SendPersistentPacket : SendFlagPacket
	{
		public string PersistentScene = "";

		public string PersistentObject = "";

		public override void WriteData(IPacket packet)
		{
			base.WriteData(packet);
			packet.Write(PersistentScene);
			packet.Write(PersistentObject);
		}

		public override void ReadData(IPacket packet)
		{
			base.ReadData(packet);
			PersistentScene = packet.ReadString();
			PersistentObject = packet.ReadString();
		}
	}
	internal class SendPersistentBoolsPacket : Packet
	{
		public Dictionary<(string, string), (bool, FlagType)> Values = new Dictionary<(string, string), (bool, FlagType)>();

		public override void WriteData(IPacket packet)
		{
			packet.Write(Values.Count);
			foreach (KeyValuePair<(string, string), (bool, FlagType)> value in Values)
			{
				string item = value.Key.Item1;
				string item2 = value.Key.Item2;
				bool item3 = value.Value.Item1;
				FlagType item4 = value.Value.Item2;
				packet.Write(item);
				packet.Write(item2);
				packet.Write(item3);
				packet.Write((byte)item4);
			}
		}

		public override void ReadData(IPacket packet)
		{
			int num = packet.ReadInt();
			for (int i = 0; i < num; i++)
			{
				string item = packet.ReadString();
				string item2 = packet.ReadString();
				bool item3 = packet.ReadBool();
				FlagType item4 = (FlagType)packet.ReadByte();
				Values.Add((item, item2), (item3, item4));
			}
		}
	}
	internal class SendPersistentIntsPacket : Packet
	{
		public Dictionary<(string, string), (int, FlagType)> Values = new Dictionary<(string, string), (int, FlagType)>();

		public override void WriteData(IPacket packet)
		{
			packet.Write(Values.Count);
			foreach (KeyValuePair<(string, string), (int, FlagType)> value in Values)
			{
				string item = value.Key.Item1;
				string item2 = value.Key.Item2;
				int item3 = value.Value.Item1;
				FlagType item4 = value.Value.Item2;
				packet.Write(item);
				packet.Write(item2);
				packet.Write(item3);
				packet.Write((byte)item4);
			}
		}

		public override void ReadData(IPacket packet)
		{
			int num = packet.ReadInt();
			for (int i = 0; i < num; i++)
			{
				string item = packet.ReadString();
				string item2 = packet.ReadString();
				int item3 = packet.ReadInt();
				FlagType item4 = (FlagType)packet.ReadByte();
				Values.Add((item, item2), (item3, item4));
			}
		}
	}
	internal class SendIntItemPacket : SendFlagPacket
	{
		public int Number = 0;

		public override void WriteData(IPacket packet)
		{
			base.WriteData(packet);
			packet.Write(Number);
		}

		public override void ReadData(IPacket packet)
		{
			base.ReadData(packet);
			Number = packet.ReadInt();
		}
	}
	internal class SendFloatItemPacket : SendFlagPacket
	{
		public float Number = 0f;

		public override void WriteData(IPacket packet)
		{
			base.WriteData(packet);
			packet.Write(Number);
		}

		public override void ReadData(IPacket packet)
		{
			base.ReadData(packet);
			Number = packet.ReadFloat();
		}
	}
	internal class SendCurrencyPacket : Packet
	{
		public short Rosaries;

		public short Shards;

		public override bool IsReliable => false;

		public override void WriteData(IPacket packet)
		{
			packet.Write(Rosaries);
			packet.Write(Shards);
		}

		public override void ReadData(IPacket packet)
		{
			Rosaries = packet.ReadShort();
			Shards = packet.ReadShort();
		}
	}
	internal class SettingsUpdatePacket : Packet
	{
		public SyncServerSettings Settings = new SyncServerSettings();

		public override bool IsReliable => true;

		public override bool DropReliableDataIfNewerExists => true;

		public override void WriteData(IPacket packet)
		{
			List<bool> list = Settings.ToValues();
			packet.Write(list.Count);
			foreach (bool item in list)
			{
				packet.Write(item);
			}
		}

		public override void ReadData(IPacket packet)
		{
			List<bool> list = new List<bool>();
			int num = packet.ReadInt();
			for (int i = 0; i < num; i++)
			{
				list.Add(packet.ReadBool());
			}
			Settings = SyncServerSettings.PopulateFromValues(list);
		}
	}
	internal class SendQuestItemPacket : SendBoolItemPacket
	{
	}
	internal static class PacketInstantiate
	{
		internal static IPacketData Instantiate(Packets packetID)
		{
			Log.LogDebug($"[PACKETS] Received {packetID}");
			if (1 == 0)
			{
			}
			IPacketData result = (IPacketData)(packetID switch
			{
				Packets.BoolPlayerData => new PacketDataCollection<SendBoolItemPacket>(), 
				Packets.IntPlayerData => new PacketDataCollection<SendIntItemPacket>(), 
				Packets.FloatPlayerData => new PacketDataCollection<SendFloatItemPacket>(), 
				Packets.Currency => new PacketDataCollection<SendCurrencyPacket>(), 
				Packets.Quest => new PacketDataCollection<SendBoolItemPacket>(), 
				Packets.Tool => new PacketDataCollection<SendBoolItemPacket>(), 
				Packets.Upgrade => new PacketDataCollection<SendFlagPacket>(), 
				Packets.Collectable => new PacketDataCollection<SendIntItemPacket>(), 
				Packets.PersistentBool => new PacketDataCollection<SendPersistentBoolsPacket>(), 
				Packets.PersistentInt => new PacketDataCollection<SendPersistentIntsPacket>(), 
				Packets.Settings => new SettingsUpdatePacket(), 
				_ => new ErrorThrowingPacket(packetID, server: true), 
			});
			if (1 == 0)
			{
			}
			return result;
		}
	}
	internal class ErrorThrowingPacket : Packet
	{
		public ErrorThrowingPacket(Packets id, bool server)
		{
			Log.LogError(id.ToString(), server);
			throw new NotImplementedException(id.ToString());
		}
	}
}
namespace BasicItemSync.Modules.Network.Server
{
	internal class NetworkForwarder
	{
		private static IServerAddonNetworkReceiver<Packets> Receiver;

		private static IServerAddonNetworkSender<Packets> Sender;

		public static void Initialize()
		{
			Sender = ServerAddon.api.NetServer.GetNetworkSender<Packets>((ServerAddon)(object)ServerAddon.Instance);
			Receiver = ServerAddon.api.NetServer.GetNetworkReceiver<Packets>((ServerAddon)(object)ServerAddon.Instance, (Func<Packets, IPacketData>)PacketInstantiate.Instantiate);
			Receiver.RegisterPacketHandler<SendBoolItemPacket>(Packets.BoolPlayerData, (GenericServerPacketHandler<SendBoolItemPacket>)OnBool);
			Receiver.RegisterPacketHandler<SendIntItemPacket>(Packets.IntPlayerData, (GenericServerPacketHandler<SendIntItemPacket>)OnInt);
			Receiver.RegisterPacketHandler<SendFloatItemPacket>(Packets.FloatPlayerData, (GenericServerPacketHandler<SendFloatItemPacket>)OnFloat);
			Receiver.RegisterPacketHandler<SendCurrencyPacket>(Packets.Currency, (GenericServerPacketHandler<SendCurrencyPacket>)OnCurrency);
			Receiver.RegisterPacketHandler<SendBoolItemPacket>(Packets.Quest, (GenericServerPacketHandler<SendBoolItemPacket>)OnQuest);
			Receiver.RegisterPacketHandler<SendBoolItemPacket>(Packets.Tool, (GenericServerPacketHandler<SendBoolItemPacket>)OnTool);
			Receiver.RegisterPacketHandler<SendFlagPacket>(Packets.Upgrade, (GenericServerPacketHandler<SendFlagPacket>)OnUpgrade);
			Receiver.RegisterPacketHandler<SendIntItemPacket>(Packets.Collectable, (GenericServerPacketHandler<SendIntItemPacket>)OnCollectable);
			Receiver.RegisterPacketHandler<SendPersistentBoolsPacket>(Packets.PersistentBool, (GenericServerPacketHandler<SendPersistentBoolsPacket>)OnPersistentBool);
			Receiver.RegisterPacketHandler<SendPersistentIntsPacket>(Packets.PersistentInt, (GenericServerPacketHandler<SendPersistentIntsPacket>)OnPersistentInt);
			Receiver.RegisterPacketHandler<SettingsUpdatePacket>(Packets.Settings, (GenericServerPacketHandler<SettingsUpdatePacket>)OnSettings);
		}

		private static void Broadcast(ushort senderId, Packets type, Packet packet)
		{
			if (Sender == null)
			{
				return;
			}
			foreach (IServerPlayer player in ServerAddon.api.ServerManager.Players)
			{
				if (player.Id != senderId)
				{
					Sender.SendCollectionData<Packet>(type, packet, player.Id);
				}
			}
		}

		public static void SendSettingsUpdate()
		{
			SettingsUpdatePacket settingsUpdatePacket = new SettingsUpdatePacket
			{
				Settings = ServerAddon.Settings
			};
			ServerAddon.api.ServerManager.BroadcastMessage("Sync settings have been updated");
			Sender.BroadcastSingleData(Packets.Settings, (IPacketData)(object)settingsUpdatePacket);
		}

		public static void SendSettingsUpdate(ushort id)
		{
			SettingsUpdatePacket settingsUpdatePacket = new SettingsUpdatePacket
			{
				Settings = ServerAddon.Settings
			};
			Sender.SendSingleData(Packets.Settings, (IPacketData)(object)settingsUpdatePacket, id);
		}

		private static void OnCurrency(ushort id, SendCurrencyPacket packet)
		{
			if (ServerAddon.Settings.FlagAllowed(FlagType.Currency))
			{
				Broadcast(id, Packets.Currency, packet);
			}
		}

		private static void OnBool(ushort id, SendBoolItemPacket packet)
		{
			OnFlag(id, packet, Packets.BoolPlayerData, isPD: true);
		}

		private static void OnInt(ushort id, SendIntItemPacket packet)
		{
			OnFlag(id, packet, Packets.IntPlayerData, isPD: true);
		}

		private static void OnFloat(ushort id, SendFloatItemPacket packet)
		{
			OnFlag(id, packet, Packets.FloatPlayerData, isPD: true);
		}

		private static void OnQuest(ushort id, SendBoolItemPacket packet)
		{
			OnFlag(id, packet, Packets.Quest, isPD: false);
		}

		private static void OnTool(ushort id, SendBoolItemPacket packet)
		{
			OnFlag(id, packet, Packets.Tool, isPD: false);
		}

		private static void OnUpgrade(ushort id, SendFlagPacket packet)
		{
			OnFlag(id, packet, Packets.Upgrade, isPD: false);
		}

		private static void OnCollectable(ushort id, SendIntItemPacket packet)
		{
			OnFlag(id, packet, Packets.Collectable, isPD: false);
		}

		private static void OnPersistentBool(ushort id, SendPersistentBoolsPacket packet)
		{
			SendPersistentBoolsPacket sendPersistentBoolsPacket = new SendPersistentBoolsPacket();
			foreach (KeyValuePair<(string, string), (bool, FlagType)> value in packet.Values)
			{
				if (ServerAddon.Settings.FlagAllowed(value.Value.Item2))
				{
					sendPersistentBoolsPacket.Values.Add(value.Key, value.Value);
				}
			}
			if (sendPersistentBoolsPacket.Values.Count != 0)
			{
				Broadcast(id, Packets.PersistentBool, sendPersistentBoolsPacket);
			}
		}

		private static void OnPersistentInt(ushort id, SendPersistentIntsPacket packet)
		{
			SendPersistentIntsPacket sendPersistentIntsPacket = new SendPersistentIntsPacket();
			foreach (KeyValuePair<(string, string), (int, FlagType)> value in packet.Values)
			{
				if (ServerAddon.Settings.FlagAllowed(value.Value.Item2))
				{
					sendPersistentIntsPacket.Values.Add(value.Key, value.Value);
				}
			}
			if (sendPersistentIntsPacket.Values.Count != 0)
			{
				Broadcast(id, Packets.PersistentInt, sendPersistentIntsPacket);
			}
		}

		private static void Announce(ushort id, SendFlagPacket packet, bool isPossiblySilent)
		{
			FlagType flagType = packet.FlagType;
			Log.LogDebug($"[SERVER: Network Forwarder Announce] Received {flagType}");
			if (!isPossiblySilent || !string.IsNullOrEmpty(packet.Name))
			{
				if (1 == 0)
				{
				}
				string text = flagType switch
				{
					FlagType.Ability => "obtained $", 
					FlagType.Map => "obtained $ Map", 
					FlagType.Pin => "obtained $", 
					FlagType.Bellshrine => "activated the $ Bellshrine", 
					FlagType.Boss => "defeated $", 
					FlagType.Arena => "defeated $", 
					FlagType.Progression => "obtained the $", 
					FlagType.Collectable => "collected a $", 
					FlagType.Bellway => "unlocked the $ Bellway Station", 
					FlagType.Ventrica => "unlocked the $ Ventrica", 
					FlagType.Mask => "obtained the Mask Shard in $", 
					FlagType.Spool => "obtained the Spool Fragment in $", 
					FlagType.Pouch => "obtained a Tool Pouch from $", 
					FlagType.CraftingKit => "obtained a Crafting Kit from $", 
					FlagType.SilkHeart => "obtained a Silk Heart", 
					FlagType.Needle => "upgraded their needle", 
					FlagType.Quest => "finished the $ quest", 
					FlagType.QuestItem => "", 
					FlagType.Tool => "obtained $", 
					FlagType.Crest => "obtained $ Crest", 
					FlagType.Currency => "", 
					FlagType.Bench => "unlocked a bench", 
					FlagType.Flea => "saved a flea from $", 
					_ => "", 
				};
				if (1 == 0)
				{
				}
				string text2 = text;
				if (!string.IsNullOrEmpty(text2))
				{
					IServerPlayer player = ServerAddon.api.ServerManager.GetPlayer(id);
					string newValue = (string.IsNullOrEmpty(packet.Name) ? packet.Key : packet.Name);
					string text3 = (((player != null) ? player.Username : null) ?? "Unknown Player") + " " + text2.Replace("$", newValue);
					ServerAddon.api.ServerManager.BroadcastMessage(text3);
				}
			}
		}

		private static void OnFlag(ushort id, SendFlagPacket packet, Packets type, bool isPD)
		{
			if (ServerAddon.Settings.FlagAllowed(packet.FlagType))
			{
				Announce(id, packet, isPD);
				Broadcast(id, type, packet);
			}
		}

		private static void OnSettings(ushort id, SettingsUpdatePacket packet)
		{
			IServerPlayer val = default(IServerPlayer);
			if (ServerAddon.api.ServerManager.TryGetPlayer(id, ref val))
			{
				if (!val.IsAuthorized)
				{
					ServerAddon.api.ServerManager.SendMessage(val, "You aren't authorized to change settings.");
					return;
				}
				ServerAddon.Settings.CopyFrom(packet.Settings);
				ServerAddon.Settings.SaveToFile();
				SendSettingsUpdate();
			}
		}
	}
	internal class ServerAddon : ServerAddon
	{
		public static IServerApi api;

		public static ServerAddon Instance;

		public static SyncServerSettings Settings;

		public override bool NeedsNetwork => true;

		public override uint ApiVersion => 1u;

		protected override string Name => "BasicItemSync";

		protected override string Version => "0.1.4";

		public override void Initialize(IServerApi serverApi)
		{
			Log.SetLogger(((ServerAddon)this).Logger);
			Log.LogInfo("Item Sync Server Addon enabled");
			Instance = this;
			api = serverApi;
			Settings = SyncServerSettings.ReadFromFile();
			NetworkForwarder.Initialize();
			((ICommandManager<IServerCommand>)(object)((ServerAddon)this).ServerApi.CommandManager).RegisterCommand((IServerCommand)(object)new SettingCommand(Settings));
			api.ServerManager.PlayerConnectEvent += OnPlayerConnect;
		}

		private void OnPlayerConnect(IServerPlayer player)
		{
			NetworkForwarder.SendSettingsUpdate(player.Id);
		}
	}
	internal class SettingCommand : IServerCommand, ICommand
	{
		private readonly SyncServerSettings Settings;

		public bool AuthorizedOnly => true;

		public string Trigger => "/sync";

		public string[] Aliases => Array.Empty<string>();

		public SettingCommand(SyncServerSettings settings)
		{
			Settings = settings;
		}

		public void Execute(ICommandSender commandSender, string[] arguments)
		{
			if (arguments.Length < 2)
			{
				SendUsage();
				return;
			}
			string settingName = "Sync" + arguments[1];
			FieldInfo[] fields = typeof(SyncServerSettings).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			FieldInfo fieldInfo = fields.FirstOrDefault((FieldInfo s) => s.Name.Equals(settingName, StringComparison.CurrentCultureIgnoreCase));
			if (fieldInfo == null)
			{
				commandSender.SendMessage("Unknown setting '" + arguments[1] + "'");
				return;
			}
			if (arguments.Length == 2)
			{
				bool flag = (bool)fieldInfo.GetValue(Settings);
				commandSender.SendMessage($"Setting '{fieldInfo.Name}' is currently {flag}");
				return;
			}
			bool flag2;
			if (arguments[2] == "true")
			{
				flag2 = true;
			}
			else
			{
				if (!(arguments[2] == "false"))
				{
					SendUsage();
					return;
				}
				flag2 = false;
			}
			fieldInfo.SetValue(Settings, flag2);
			Settings.SaveToFile();
			NetworkForwarder.SendSettingsUpdate();
			void SendUsage()
			{
				commandSender.SendMessage("Invalid usage: " + Trigger + " <setting> <true/false>");
			}
		}
	}
	internal class SyncServerSettings
	{
		public bool KillSwitch = false;

		public bool SyncAbilities = true;

		public bool SyncMaps = true;

		public bool SyncPins = true;

		public bool SyncCurrency = true;

		public bool SyncSpendingCurrency = false;

		public bool SyncQuests = true;

		public bool SyncQuestItems = false;

		public bool SyncBosses = true;

		public bool SyncArenas = true;

		public bool SyncProgression = true;

		public bool SyncFleas = true;

		public bool SyncCollectables = true;

		public bool SyncUpgrades = true;

		public bool SyncTools = true;

		public bool SyncCrests = true;

		public bool SyncTransit = true;

		public bool SyncShortcuts = true;

		public bool FlagAllowed(FlagType flag)
		{
			if (ServerAddon.Settings.KillSwitch)
			{
				return false;
			}
			if (1 == 0)
			{
			}
			bool result = flag switch
			{
				FlagType.Ability => SyncAbilities, 
				FlagType.Map => SyncMaps, 
				FlagType.Pin => SyncPins, 
				FlagType.Bellshrine => SyncProgression, 
				FlagType.Boss => SyncBosses, 
				FlagType.Arena => SyncArenas, 
				FlagType.Progression => SyncProgression, 
				FlagType.Flea => SyncFleas, 
				FlagType.Collectable => SyncCollectables, 
				FlagType.Bellway => SyncTransit, 
				FlagType.Ventrica => SyncTransit, 
				FlagType.Currency => SyncCurrency, 
				FlagType.Mask => SyncUpgrades, 
				FlagType.Spool => SyncUpgrades, 
				FlagType.Pouch => SyncUpgrades, 
				FlagType.CraftingKit => SyncUpgrades, 
				FlagType.Quest => SyncQuests, 
				FlagType.QuestStart => SyncQuestItems, 
				FlagType.QuestItem => SyncQuestItems, 
				FlagType.Tool => SyncTools, 
				FlagType.Crest => SyncCrests, 
				FlagType.SilkHeart => SyncUpgrades, 
				FlagType.Needle => SyncUpgrades, 
				FlagType.Bench => SyncProgression, 
				FlagType.Shortcut => SyncShortcuts, 
				FlagType.DoNotSync => false, 
				_ => false, 
			};
			if (1 == 0)
			{
			}
			return result;
		}

		public List<bool> ToValues()
		{
			List<FieldInfo> properties = GetProperties();
			List<bool> list = new List<bool>();
			foreach (FieldInfo item in properties)
			{
				list.Add((bool)item.GetValue(this));
			}
			return list;
		}

		public static List<FieldInfo> GetProperties()
		{
			List<FieldInfo> list = typeof(SyncServerSettings).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList();
			list.Sort((FieldInfo a, FieldInfo b) => a.Name.CompareTo(b.Name));
			return list;
		}

		public void CopyFrom(SyncServerSettings settings)
		{
			List<FieldInfo> properties = GetProperties();
			foreach (FieldInfo item in properties)
			{
				item.SetValue(this, item.GetValue(settings));
			}
		}

		public static SyncServerSettings PopulateFromValues(List<bool> values)
		{
			SyncServerSettings syncServerSettings = new SyncServerSettings();
			List<FieldInfo> properties = GetProperties();
			if (properties.Count != values.Count)
			{
				Log.LogWarning("Mismatched server setting property count");
			}
			for (int i = 0; i < properties.Count; i++)
			{
				FieldInfo fieldInfo = properties[i];
				bool flag = values[i];
				fieldInfo.SetValue(syncServerSettings, flag);
			}
			return syncServerSettings;
		}

		public static SyncServerSettings ReadFromFile()
		{
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			string text = Path.Combine(directoryName, "ServerSettings.json");
			if (!File.Exists(text))
			{
				Log.LogWarning("[SERVER: SETTINGS] " + text + " doesn't exist");
				SyncServerSettings syncServerSettings = new SyncServerSettings();
				syncServerSettings.SaveToFile();
				return syncServerSettings;
			}
			try
			{
				string text2 = File.ReadAllText(text);
				SyncServerSettings syncServerSettings2 = JsonConvert.DeserializeObject<SyncServerSettings>(text2);
				return syncServerSettings2 ?? new SyncServerSettings();
			}
			catch (Exception arg)
			{
				Log.LogError($"[SERVER: SETTINGS] Could not load server settings from file:\n{arg}");
				return new SyncServerSettings();
			}
		}

		public void SaveToFile()
		{
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			string text = Path.Combine(directoryName, "ServerSettings.json");
			if (!Directory.Exists(Path.GetDirectoryName(text)))
			{
				Log.LogWarning("[SERVER: SETTINGS] " + text + " directory doesn't exist");
				return;
			}
			string text2 = JsonConvert.SerializeObject((object)this, (Formatting)1);
			if (text2 == null)
			{
				return;
			}
			try
			{
				File.WriteAllText(text, text2);
			}
			catch (Exception arg)
			{
				Log.LogError($"[SERVER: SETTINGS] Could not write server settings to file:\n{arg}");
			}
		}
	}
}
namespace BasicItemSync.Modules.Network.Client
{
	internal class ClientAddon : ClientAddon
	{
		public static IClientApi api;

		public static ClientAddon Instance;

		public static SyncServerSettings Settings = new SyncServerSettings();

		private static readonly WaitForSeconds CurrencyTimer = new WaitForSeconds(4f);

		private static Coroutine? CurrencyRoutine;

		public override bool NeedsNetwork => true;

		public override uint ApiVersion => 1u;

		protected override string Name => "BasicItemSync";

		protected override string Version => "0.1.4";

		public override void Initialize(IClientApi clientApi)
		{
			Log.SetLogger(((ClientAddon)this).Logger);
			Log.LogInfo("Sync Client Addon enabled");
			Settings = new SyncServerSettings();
			Instance = this;
			api = clientApi;
			NetworkSender.Initialize();
			NetworkReceiver.Initialize();
			((ICommandManager<IClientCommand>)(object)api.CommandManager).RegisterCommand((IClientCommand)(object)new SettingUICommand(Settings));
			api.ClientManager.ConnectEvent += OnConnect;
			api.ClientManager.DisconnectEvent += OnDisconnect;
		}

		private void OnConnect()
		{
			EventHooks.Initialize();
			Settings.CopyFrom(new SyncServerSettings());
			api.UiManager.ChatBox.AddMessage("BasicItemSync is in beta. Please report any bugs to the link on the mod page.");
			CurrencyRoutine = ((MonoBehaviour)SyncPlugin.Instance).StartCoroutine(CurrencySender());
		}

		private void OnDisconnect()
		{
			EventHooks.Uninitialize();
			if (CurrencyRoutine != null)
			{
				NetworkSender.SendPendingCurrency();
				((MonoBehaviour)SyncPlugin.Instance).StopCoroutine(CurrencyRoutine);
			}
		}

		public static void LocalChat(string message)
		{
			api.UiManager.ChatBox.AddMessage(message);
		}

		private static IEnumerator CurrencySender()
		{
			while (true)
			{
				NetworkSender.SendPendingCurrency();
				yield return CurrencyTimer;
			}
		}
	}
	internal class NetworkReceiver
	{
		private static IClientAddonNetworkReceiver<Packets> Receiver;

		public static void Initialize()
		{
			Receiver = ClientAddon.api.NetClient.GetNetworkReceiver<Packets>((ClientAddon)(object)ClientAddon.Instance, (Func<Packets, IPacketData>)PacketInstantiate.Instantiate);
			Receiver.RegisterPacketHandler<SettingsUpdatePacket>(Packets.Settings, (GenericClientPacketHandler<SettingsUpdatePacket>)OnSettingsUpdate);
			Receiver.RegisterPacketHandler<SendBoolItemPacket>(Packets.BoolPlayerData, (GenericClientPacketHandler<SendBoolItemPacket>)OnBoolFlag);
			Receiver.RegisterPacketHandler<SendIntItemPacket>(Packets.IntPlayerData, (GenericClientPacketHandler<SendIntItemPacket>)OnIntFlag);
			Receiver.RegisterPacketHandler<SendFloatItemPacket>(Packets.FloatPlayerData, (GenericClientPacketHandler<SendFloatItemPacket>)OnFloatFlag);
			Receiver.RegisterPacketHandler<SendCurrencyPacket>(Packets.Currency, (GenericClientPacketHandler<SendCurrencyPacket>)OnCurrency);
			Receiver.RegisterPacketHandler<SendBoolItemPacket>(Packets.Quest, (GenericClientPacketHandler<SendBoolItemPacket>)OnQuestItem);
			Receiver.RegisterPacketHandler<SendBoolItemPacket>(Packets.Tool, (GenericClientPacketHandler<SendBoolItemPacket>)OnTool);
			Receiver.RegisterPacketHandler<SendFlagPacket>(Packets.Upgrade, (GenericClientPacketHandler<SendFlagPacket>)OnUpgrade);
			Receiver.RegisterPacketHandler<SendIntItemPacket>(Packets.Collectable, (GenericClientPacketHandler<SendIntItemPacket>)OnCollectable);
			Receiver.RegisterPacketHandler<SendPersistentBoolsPacket>(Packets.PersistentBool, (GenericClientPacketHandler<SendPersistentBoolsPacket>)OnPersistentBools);
			Receiver.RegisterPacketHandler<SendPersistentIntsPacket>(Packets.PersistentInt, (GenericClientPacketHandler<SendPersistentIntsPacket>)OnPersistentInt);
		}

		private static bool HandleSpecialData(SendFlagPacket packet)
		{
			UI.ShowPopup(packet.FlagType, packet.Key, packet.Name);
			return false;
		}

		private static void OnIntFlag(SendIntItemPacket packet)
		{
			SyncPlugin.AddNextFrameAction(delegate
			{
				ClientState.LastItem = packet.Key;
				if (!HandleSpecialData(packet))
				{
					PlayerData.instance.SetInt(packet.Key, packet.Number);
				}
				ClientState.LastItem = "";
			});
		}

		private static void OnFloatFlag(SendFloatItemPacket packet)
		{
			SyncPlugin.AddNextFrameAction(delegate
			{
				ClientState.LastItem = packet.Key;
				if (!HandleSpecialData(packet))
				{
					PlayerData.instance.SetFloat(packet.Key, packet.Number);
				}
				ClientState.LastItem = "";
			});
		}

		private static void OnBoolFlag(SendBoolItemPacket packet)
		{
			SyncPlugin.AddNextFrameAction(delegate
			{
				ClientState.LastItem = packet.Key;
				if (!HandleSpecialData(packet))
				{
					PlayerData.instance.SetBool(packet.Key, packet.State);
				}
				ClientState.LastItem = "";
				if (packet.FlagType == FlagType.Boss || packet.FlagType == FlagType.Arena)
				{
					BattleManager.DefeatBattleScene(packet.Key);
				}
			});
		}

		private static void OnCurrency(SendCurrencyPacket packet)
		{
			SyncPlugin.AddNextFrameAction(delegate
			{
				ClientState.LastCurrency = packet.Rosaries;
				if (packet.Rosaries != 0)
				{
					CurrencyManager.AddGeo((int)packet.Rosaries);
				}
				ClientState.LastCurrency = packet.Shards;
				if (packet.Shards != 0)
				{
					CurrencyManager.AddShards((int)packet.Shards);
				}
				ClientState.LastCurrency = 0;
			});
		}

		private static void OnQuestItem(SendBoolItemPacket packet)
		{
			SyncPlugin.AddNextFrameAction(delegate
			{
				ClientState.LastItem = packet.Key;
				if (!HandleSpecialData(packet))
				{
					QuestHandler.EndQuest(packet.Key);
				}
				ClientState.LastItem = "";
			});
		}

		private static void OnTool(SendBoolItemPacket packet)
		{
			SyncPlugin.AddNextFrameAction(delegate
			{
				//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c3: Invalid comparison between Unknown and I4
				ClientState.LastItem = packet.Key;
				if (!HandleSpecialData(packet))
				{
					if (packet.FlagType == FlagType.Crest)
					{
						ToolCrest crestByName = ToolItemManager.GetCrestByName(packet.Key);
						if (Object.op_Implicit((Object)(object)crestByName))
						{
							crestByName.Unlock();
						}
					}
					else
					{
						ToolItem toolByName = ToolItemManager.GetToolByName(packet.Key);
						if (Object.op_Implicit((Object)(object)toolByName))
						{
							PlayerData.instance.SeenToolGetPrompt = true;
							PlayerData.instance.SeenToolWeaponGetPrompt = true;
							if (packet.State)
							{
								toolByName.Unlock((Action)null, (PopupFlags)3);
								if ((int)toolByName.Type == 3 && !ToolItemManager.GetCurrentEquippedTools().Any((ToolItem t) => (int)t.Type == 3))
								{
									ToolItemManager.AutoEquip(toolByName);
								}
							}
							else
							{
								toolByName.Lock();
							}
						}
					}
				}
				ClientState.LastItem = "";
			});
		}

		private static void OnUpgrade(SendFlagPacket packet)
		{
			if (!string.IsNullOrEmpty(packet.Name))
			{
				SyncPlugin.AddNextFrameAction(delegate
				{
					ClientState.LastItem = packet.Name;
					if (!HandleSpecialData(packet))
					{
						QuestHandler.EndQuestSilent(packet.Name);
					}
					ClientState.LastItem = "";
				});
			}
			SyncPlugin.AddNextFrameAction(delegate
			{
				ClientState.LastUpgrade = packet.FlagType;
				if (!HandleSpecialData(packet))
				{
					FlagType flagType = packet.FlagType;
					if (1 == 0)
					{
					}
					switch (flagType)
					{
					case FlagType.Mask:
						Upgrader.UpgradeMask(packet.Key);
						break;
					case FlagType.Spool:
						Upgrader.UpgradeSpool(packet.Key);
						break;
					case FlagType.Pouch:
						Upgrader.UpgradePouch();
						break;
					case FlagType.CraftingKit:
						Upgrader.UpgradeCraftingKit();
						break;
					case FlagType.SilkHeart:
						Upgrader.UpgradeSilkHeart(packet.Key);
						break;
					case FlagType.Needle:
						Upgrader.UpgradeNeedle();
						break;
					default:
						Upgrader.NoOp();
						break;
					}
					if (true)
					{
					}
				}
				ClientState.LastUpgrade = FlagType.DoNotSync;
			});
		}

		private static void OnCollectable(SendIntItemPacket packet)
		{
			SyncPlugin.AddNextFrameAction(delegate
			{
				ClientState.LastItem = packet.Key;
				if (!HandleSpecialData(packet))
				{
					Upgrader.GiveCollectable(packet.Key, packet.Number);
				}
				ClientState.LastItem = "";
			});
		}

		private static void OnPersistentBools(SendPersistentBoolsPacket packet)
		{
			foreach (KeyValuePair<(string, string), (bool, FlagType)> value in packet.Values)
			{
				string item = value.Key.Item1;
				string item2 = value.Key.Item2;
				bool item3 = value.Value.Item1;
				PersistentHandler.SetPersistentBoolData(item, item2, item3);
			}
		}

		private static void OnPersistentInt(SendPersistentIntsPacket packet)
		{
			foreach (KeyValuePair<(string, string), (int, FlagType)> value in packet.Values)
			{
				string item = value.Key.Item1;
				string item2 = value.Key.Item2;
				int item3 = value.Value.Item1;
				FlagType item4 = value.Value.Item2;
				PersistentHandler.SetPersistentIntData(item, item2, item3, item4);
			}
		}

		private static void OnSettingsUpdate(SettingsUpdatePacket packet)
		{
			ClientAddon.Settings.CopyFrom(packet.Settings);
			Log.LogInfo("[CLI] Received new settings");
		}
	}
	internal class NetworkSender
	{
		private static IClientAddonNetworkSender<Packets>? Sender;

		private static int RosariesToSend = 0;

		private static int ShardsToSend = 0;

		private static SendPersistentBoolsPacket PersistentBoolsToSend = new SendPersistentBoolsPacket();

		private static SendPersistentIntsPacket PersistentIntsToSend = new SendPersistentIntsPacket();

		public static void Initialize()
		{
			Sender = ClientAddon.api.NetClient.GetNetworkSender<Packets>((ClientAddon)(object)ClientAddon.Instance);
		}

		private static void SendCollectionData(Packets type, Packet packet)
		{
			if (!ClientAddon.api.NetClient.IsConnected || Sender == null)
			{
				Log.LogDebug("[CLI: Network Sender Collection] Not connected");
			}
			else if (!(packet is SendFlagPacket sendFlagPacket) || CanSync(sendFlagPacket.FlagType))
			{
				Log.LogDebug($"[CLI: Network Sender Collection] Sending {type}");
				Sender.SendCollectionData<Packet>(type, packet);
			}
		}

		private static void SendSingleData(Packets type, Packet packet)
		{
			if (!ClientAddon.api.NetClient.IsConnected || Sender == null)
			{
				Log.LogDebug("[CLI: Network Sender Single] Not connected");
			}
			else if (!(packet is SendFlagPacket sendFlagPacket) || CanSync(sendFlagPacket.FlagType))
			{
				Log.LogDebug($"[CLI: Network Sender Single] Sending {type}");
				Sender.SendSingleData(type, (IPacketData)(object)packet);
			}
		}

		private static bool CanSync(FlagType flagType)
		{
			if (!ClientAddon.Settings.FlagAllowed(flagType))
			{
				Log.LogDebug($"[CLI] Syncing {flagType} is disabled.");
				return false;
			}
			return true;
		}

		public static void AddCurrency(InternalCurrencyType currencyType, int amount)
		{
			if (CanSync(FlagType.Currency))
			{
				if (currencyType == InternalCurrencyType.Rosary)
				{
					RosariesToSend += amount;
				}
				else
				{
					ShardsToSend += amount;
				}
			}
		}

		public static void SendPendingCurrency()
		{
			if (RosariesToSend != 0 || ShardsToSend != 0)
			{
				SendCollectionData(Packets.Currency, new SendCurrencyPacket
				{
					Rosaries = (short)RosariesToSend,
					Shards = (short)ShardsToSend
				});
				RosariesToSend = 0;
				ShardsToSend = 0;
			}
		}

		public static void SendPendingPersistents()
		{
			if (PersistentBoolsToSend.Values.Count > 0)
			{
				SendCollectionData(Packets.PersistentBool, PersistentBoolsToSend);
			}
			if (PersistentIntsToSend.Values.Count > 0)
			{
				SendCollectionData(Packets.PersistentInt, PersistentIntsToSend);
			}
			PersistentBoolsToSend = new SendPersistentBoolsPacket();
			PersistentIntsToSend = new SendPersistentIntsPacket();
		}

		public static void SendFlag(string playerDataKey, FlagType flagType, string name, bool state = true)
		{
			SendCollectionData(Packets.BoolPlayerData, new SendBoolItemPacket
			{
				Key = playerDataKey,
				Name = name,
				FlagType = flagType,
				State = state
			});
		}

		public static void SendInt(string playerDataKey, FlagType flagType, string name, int state)
		{
			SendCollectionData(Packets.IntPlayerData, new SendIntItemPacket
			{
				Key = playerDataKey,
				Name = name,
				FlagType = flagType,
				Number = state
			});
		}

		public static void SendQuestComplete(string internalName, string displayName)
		{
			SendCollectionData(Packets.Quest, new SendBoolItemPacket
			{
				Key = internalName,
				Name = displayName,
				FlagType = FlagType.Quest,
				State = true
			});
		}

		public static void SendTool(string toolName, string displayName, bool state, bool isCrest)
		{
			SendCollectionData(Packets.Tool, new SendBoolItemPacket
			{
				Key = toolName,
				Name = displayName,
				FlagType = (isCrest ? FlagType.Crest : FlagType.Tool),
				State = state
			});
		}

		public static void SendUpgrade(string sceneName, FlagType upgradeType)
		{
			SendCollectionData(Packets.Upgrade, new SendFlagPacket
			{
				Key = sceneName,
				Name = "",
				FlagType = upgradeType
			});
		}

		public static void SendCollectable(string key, string itemName, int amount, FlagType flagType = FlagType.Collectable)
		{
			SendCollectionData(Packets.Collectable, new SendIntItemPacket
			{
				Key = key,
				Name = itemName,
				Number = amount,
				FlagType = flagType
			});
		}

		public static void AddPersistentIntData(string id, string scene, int value, FlagType flagType)
		{
			if (!PersistentIntsToSend.Values.ContainsKey((scene, id)) && CanSync(flagType))
			{
				PersistentIntsToSend.Values[(scene, id)] = (value, flagType);
				if (PersistentIntsToSend.Values.Count == 1 && PersistentBoolsToSend.Values.Count == 0)
				{
					SyncPlugin.AddNextFrameAction(SendPendingPersistents);
				}
			}
		}

		public static void AddPersistentBoolData(string id, string scene, bool value, FlagType flagType)
		{
			if (!PersistentBoolsToSend.Values.ContainsKey((scene, id)) && CanSync(flagType))
			{
				PersistentBoolsToSend.Values[(scene, id)] = (value, flagType);
				if (PersistentBoolsToSend.Values.Count == 1 && PersistentIntsToSend.Values.Count == 0)
				{
					SyncPlugin.AddNextFrameAction(SendPendingPersistents);
				}
			}
		}

		public static void SendSettings(Dictionary<string, bool> settings)
		{
			SettingsUpdatePacket packet = new SettingsUpdatePacket
			{
				Settings = SyncServerSettings.PopulateFromValues(settings.Values.ToList())
			};
			SendSingleData(Packets.Settings, packet);
		}
	}
	internal class SettingsUI : MonoBehaviour
	{
		public bool ShowSettings = false;

		private const int width = 500;

		private const int x = 710;

		private Rect WindowRect = new Rect(710f, 20f, 500f, 360f);

		private Vector2 ScrollPosition = Vector2.zero;

		public SyncServerSettings Settings;

		public Dictionary<string, bool> SettingValues = new Dictionary<string, bool>();

		public void SetProps()
		{
			foreach (FieldInfo property in SyncServerSettings.GetProperties())
			{
				SettingValues[property.Name] = VariableExtensionsGeneric.GetVariable<bool>((object)Settings, property.Name);
			}
		}

		private void OnGUI()
		{
			//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_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if (ShowSettings)
			{
				Color backgroundColor = GUI.backgroundColor;
				GUI.backgroundColor = Color.black;
				WindowRect = GUI.Window(987, WindowRect, new WindowFunction(DrawUI), "BasicItemSync Settings");
				GUI.backgroundColor = backgroundColor;
			}
		}

		private void DrawUI(int id)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_013b: Unknown result type (might be due to invalid IL or missing references)
			ScrollPosition = GUILayout.BeginScrollView(ScrollPosition, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(500f),
				GUILayout.Height(300f)
			});
			foreach (KeyValuePair<string, bool> item in SettingValues.ToList())
			{
				SettingValues[item.Key] = GUILayout.Toggle(item.Value, item.Key, Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndScrollView();
			GUILayout.Box("", (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Height(1f),
				GUILayout.ExpandWidth(true)
			});
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Save", Array.Empty<GUILayoutOption>()))
			{
				ShowSettings = false;
				NetworkSender.SendSettings(SettingValues);
				Object.Destroy((Object)(object)this);
			}
			else if (GUILayout.Button("Cancel", Array.Empty<GUILayoutOption>()))
			{
				ShowSettings = false;
				Object.Destroy((Object)(object)this);
			}
			else
			{
				GUILayout.EndHorizontal();
				GUI.DragWindow(new Rect(0f, 0f, 1920f, 1080f));
			}
		}
	}
	internal class SettingUICommand : IClientCommand, ICommand
	{
		private readonly SyncServerSettings Settings;

		private static SettingsUI? UI;

		public string Trigger => "/sync-ui";

		public string[] Aliases => Array.Empty<string>();

		public SettingUICommand(SyncServerSettings settings)
		{
			Settings = settings;
		}

		public void Execute(string[] arguments)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			if (!((Object)(object)UI != (Object)null))
			{
				GameObject val = new GameObject("Sync Settings UI");
				UI = val.AddComponent<SettingsUI>();
				UI.Settings = Settings;
				UI.SetProps();
				UI.ShowSettings = true;
			}
		}
	}
}
namespace BasicItemSync.Modules.Mocks
{
	internal interface IModSettings
	{
		bool InstanceDebugPlayerData { get; }

		bool InstanceDebugLogs { get; }
	}
	internal class MockModSettings : IModSettings
	{
		public bool InstanceDebugPlayerData => false;

		public bool InstanceDebugLogs => true;
	}
}
namespace BasicItemSync.Modules.Hooks
{
	[HarmonyPatch(typeof(CollectableItemPickup))]
	internal class CollectableItemPickupHook
	{
		public static readonly Dictionary<string, FlagType> CollectableTypes = new Dictionary<string, FlagType>
		{
			{
				"Ant Trapper Item",
				FlagType.QuestItem
			},
			{
				"Architect Key",
				FlagType.Progression
			},
			{
				"Beastfly Remains",
				FlagType.QuestItem
			},
			{
				"Belltown House Key",
				FlagType.Progression
			},
			{
				"Blue Goop Jar",
				FlagType.QuestItem
			},
			{
				"Broken SilkShot",
				FlagType.Tool
			},
			{
				"Broodmother Remains",
				FlagType.QuestItem
			},
			{
				"Clover Heart",
				FlagType.Progression
			},
			{
				"Cog Heart Pieces",
				FlagType.Progression
			},
			{
				"Common Spine",
				FlagType.QuestItem
			},
			{
				"Conchfly Remains",
				FlagType.QuestItem
			},
			{
				"Coral Chunk",
				FlagType.QuestItem
			},
			{
				"Coral Heart",
				FlagType.Progression
			},
			{
				"Coral Ingredient",
				FlagType.QuestItem
			},
			{
				"Courier Supplies",
				FlagType.DoNotSync
			},
			{
				"Courier Supplies Gourmand",
				FlagType.DoNotSync
			},
			{
				"Courier Supplies Mask Maker",
				FlagType.DoNotSync
			},
			{
				"Courier Supplies Slave",
				FlagType.DoNotSync
			},
			{
				"Craw Summons",
				FlagType.Progression
			},
			{
				"Crawbell",
				FlagType.Collectable
			},
			{
				"Crest Socket Unlocker",
				FlagType.Collectable
			},
			{
				"Crow Feather",
				FlagType.QuestItem
			},
			{
				"Crowman Memento",
				FlagType.Collectable
			},
			{
				"Dock Demo Key",
				FlagType.DoNotSync
			},
			{
				"Dock Key",
				FlagType.Progression
			},
			{
				"Dresses",
				FlagType.DoNotSync
			},
			{
				"Enemy Morsel Seared",
				FlagType.QuestItem
			},
			{
				"Enemy Morsel Shredded",
				FlagType.QuestItem
			},
			{
				"Enemy Morsel Speared",
				FlagType.QuestItem
			},
			{
				"Extractor Machine Pins",
				FlagType.QuestItem
			},
			{
				"Farsight",
				FlagType.Collectable
			},
			{
				"Fine Pins",
				FlagType.QuestItem
			},
			{
				"Fixer Idol",
				FlagType.Quest
			},
			{
				"Flower Heart",
				FlagType.Progression
			},
			{
				"Great Shard",
				FlagType.Collectable
			},
			{
				"Grey Memento",
				FlagType.Collectable
			},
			{
				"Growstone",
				FlagType.Quest
			},
			{
				"Hunter Heart",
				FlagType.Collectable
			},
			{
				"Hunter Memento",
				FlagType.Collectable
			},
			{
				"Materium",
				FlagType.Collectable
			},
			{
				"Memento Garmond",
				FlagType.Collectable
			},
			{
				"Memento Seth",
				FlagType.Collectable
			},
			{
				"Memento Surface",
				FlagType.Collectable
			},
			{
				"Mossberry",
				FlagType.QuestItem
			},
			{
				"Mossberry Stew",
				FlagType.QuestItem
			},
			{
				"Pale_Oil",
				FlagType.Collectable
			},
			{
				"Pickled Roach Egg",
				FlagType.QuestItem
			},
			{
				"Pilgrim Rag",
				FlagType.QuestItem
			},
			{
				"Plasmium",
				FlagType.QuestItem
			},
			{
				"Plasmium Blood",
				FlagType.QuestItem
			},
			{
				"Plasmium Gland",
				FlagType.Quest
			},
			{
				"Pristine Core",
				FlagType.Progression
			},
			{
				"Quill",
				FlagType.Collectable
			},
			{
				"R Ancient Egg",
				FlagType.Collectable
			},
			{
				"R Bone Record",
				FlagType.Collectable
			},
			{
				"R Librarian Melody Cylinder",
				FlagType.Progression
			},
			{
				"R Psalm Cylinder",
				FlagType.Collectable
			},
			{
				"R Seal Chit",
				FlagType.Collectable
			},
			{
				"R Weaver Record",
				FlagType.Collectable
			},
			{
				"R Weaver Totem",
				FlagType.Collectable
			},
			{
				"Roach Corpse Item",
				FlagType.QuestItem
			},
			{
				"Rock Roller Item",
				FlagType.QuestItem
			},
			{
				"Rosary_Set_Frayed",
				FlagType.Collectable
			},
			{
				"Rosary_Set_Huge_White",
				FlagType.Collectable
			},
			{
				"Rosary_Set_Large",
				FlagType.Collectable
			},
			{
				"Rosary_Set_Medium",
				FlagType.Collectable
			},
			{
				"Rosary_Set_Small",
				FlagType.Collectable
			},
			{
				"Shard Pouch",
				FlagType.Collectable
			},
			{
				"Shell Flower",
				FlagType.QuestItem
			},
			{
				"Shining Cog",
				FlagType.QuestItem
			},
			{
				"Silk Grub",
				FlagType.Collectable
			},
			{
				"Silver Bellclapper",
				FlagType.QuestItem
			},
			{
				"Simple Key",
				FlagType.Collectable
			},
			{
				"Skull King Fragment",
				FlagType.QuestItem
			},
			{
				"Slab Key",
				FlagType.Progression
			},
			{
				"Snare Soul Bell Hermit",
				FlagType.Progression
			},
			{
				"Snare Soul Churchkeeper",
				FlagType.Progression
			},
			{
				"Snare Soul Swamp Bug",
				FlagType.Progression
			},
			{
				"Song Pilgrim Cloak",
				FlagType.QuestItem
			},
			{
				"Sprintmaster Memento",
				FlagType.Collectable
			},
			{
				"Tool Metal",
				FlagType.Collectable
			},
			{
				"Vintage Nectar",
				FlagType.QuestItem
			},
			{
				"Ward Boss Key",
				FlagType.Progression
			},
			{
				"Ward Key",
				FlagType.Progression
			},
			{
				"White Flower",
				FlagType.Progression
			},
			{
				"Wood Witch Item",
				FlagType.Progression
			},
			{
				"Ancient Egg Abyss Middle",
				FlagType.Collectable
			},
			{
				"Bone Record Bone_East_14",
				FlagType.Collectable
			},
			{
				"Bone Record Greymoor_flooded_corridor",
				FlagType.Collectable
			},
			{
				"Bone Record Understore_Map_Room",
				FlagType.Collectable
			},
			{
				"Bone Record Wisp Top",
				FlagType.Collectable
			},
			{
				"Librarian Melody Cylinder",
				FlagType.Collectable
			},
			{
				"Psalm Cylinder Grindle",
				FlagType.Collectable
			},
			{
				"Psalm Cylinder Hang",
				FlagType.Collectable
			},
			{
				"Psalm Cylinder Librarian",
				FlagType.Collectable
			},
			{
				"Psalm Cylinder Library Roof",
				FlagType.Collectable
			},
			{
				"Psalm Cylinder Ward",
				FlagType.Collectable
			},
			{
				"Seal Chit Aspid_01",
				FlagType.Collectable
			},
			{
				"Seal Chit City Merchant",
				FlagType.Collectable
			},
			{
				"Seal Chit Silk Siphon",
				FlagType.Collectable
			},
			{
				"Seal Chit Ward Corpse",
				FlagType.Collectable
			},
			{
				"Weaver Record Conductor",
				FlagType.Collectable
			},
			{
				"Weaver Record Sprint_Challenge",
				FlagType.Collectable
			},
			{
				"Weaver Record Weave_08",
				FlagType.Collectable
			},
			{
				"Weaver Totem Bonetown_upper_room",
				FlagType.Collectable
			},
			{
				"Weaver Totem Slab_Bottom",
				FlagType.Collectable
			},
			{
				"Weaver Totem Witch",
				FlagType.Collectable
			}
		};

		[HarmonyPatch("DoPickupAction")]
		[HarmonyPostfix]
		public static void DoPickupAction(CollectableItemPickup __instance, ref bool __result)
		{
			string name = ((Object)__instance.Item).name;
			if (ClientState.WasItemReceived(name) || !__result || !Object.op_Implicit((Object)(object)__instance.Item))
			{
				return;
			}
			if (!CollectableTypes.TryGetValue(name, out var value))
			{
				if (!(__instance.Item is CollectableRelic))
				{
					Log.LogWarning("Unknown item " + name);
					return;
				}
				value = FlagType.Collectable;
			}
			if (value != FlagType.DoNotSync)
			{
				string playerDataBool = __instance.playerDataBool;
				PlayerDataHook.BoolUpdated(playerDataBool, value: true, (Operation)0);
				string popupName = __instance.Item.GetPopupName();
				NetworkSender.SendCollectable(name, popupName, 1, value);
				if (Object.op_Implicit((Object)(object)__instance.persistent))
				{
					PersistentBoolItemHook.UpdateValue(__instance.persistent);
				}
			}
		}
	}
	[HarmonyPatch(typeof(CurrencyManager))]
	internal class CurrencyManagerHook
	{
		[HarmonyPatch("ChangeCurrency")]
		[HarmonyPostfix]
		public static void ChangeCurrency(int amount, CurrencyType type)
		{
			//IL_0014: 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)
			Log.LogDebug($"[CLI: CURRENCY] {amount} {type}s added");
			if ((amount >= 1 || (ClientAddon.Settings.SyncSpendingCurrency && PlayerData.instance.health != 0 && !PlayerData.instance.atBench)) && !ClientState.WasCurrencyReceived(amount))
			{
				InternalCurrencyType currencyType = (((int)type != 0) ? InternalCurrencyType.ShellShard : InternalCurrencyType.Rosary);
				NetworkSender.AddCurrency(currencyType, amount);
			}
		}
	}
	internal class EventHooks
	{
		private static GameObject? HookObj;

		private static readonly List<EventRegister> Hooks = new List<EventRegister>();

		private static bool CollectedRecently = false;

		public static void Initialize()
		{
			AddHook("HEART PIECE COLLECTED", OnMask);
			AddHook("SILK SPOOL SAVE", OnSilkSpool);
			AddHook("BEAST DEFEATED", OnBellBeastDefeated);
		}

		public static void Uninitialize()
		{
			foreach (EventRegister hook in Hooks)
			{
				EventRegister.UnsubscribeEvent(hook);
			}
			if (Object.op_Implicit((Object)(object)HookObj))
			{
				Object.Destroy((Object)(object)HookObj);
			}
		}

		private static void AddHook(string eventName, Action action)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)HookObj))
			{
				HookObj = new GameObject("BasicItemSync Event Hooks");
				Object.DontDestroyOnLoad((Object)(object)HookObj);
			}
			EventRegister val = HookObj.AddComponent<EventRegister>();
			val.SubscribedEvent = eventName;
			((EventBase)val).ReceivedEvent += action;
			EventRegister.SubscribeEvent(val);
			Hooks.Add(val);
		}

		private static void SendUpgrade(FlagType upgradeType)
		{
			//IL_001e: 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 (!CollectedRecently && !ClientState.WasUpgradeReceived(upgradeType))
			{
				CollectedRecently = true;
				Scene activeScene = SceneManager.GetActiveScene();
				NetworkSender.SendUpgrade(((Scene)(ref activeScene)).name, upgradeType);
				SyncPlugin.AddNextFrameAction(delegate
				{
					CollectedRecently = false;
				});
			}
		}

		private static void OnMask()
		{
			SendUpgrade(FlagType.Mask);
		}

		private static void OnSilkSpool()
		{
			SendUpgrade(FlagType.Spool);
		}

		private static void OnBellBeastDefeated()
		{
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			PlayerData.instance.SetBool("defeatedBellBeast", true);
			bool flag = ClientAddon.Settings.FlagAllowed(FlagType.SilkHeart);
			bool flag2 = ClientAddon.Settings.FlagAllowed(FlagType.Boss);
			if (!flag || flag2)
			{
				return;
			}
			PersistentItemData<bool> val = default(PersistentItemData<bool>);
			if (!SceneData.instance.PersistentBools.TryGetValue("Bone_05", "Silk Heart", ref val))
			{
				Log.LogDebug("[CLI: EventHook.OBBD] No silk heart persistent for Bone_05");
				return;
			}
			if (!val.Value)
			{
				Log.LogDebug("[CLI: EventHook.OBBD] Haven't accepted silk heart for Bone_05");
				return;
			}
			Scene sceneByName = SceneManager.GetSceneByName("Bone_05_boss");
			if (((Scene)(ref sceneByName)).IsValid())
			{
				Log.LogDebug("[CLI: EventHook.OBBD] Deactivating bell beast");
				GameObject[] rootGameObjects = ((Scene)(ref sceneByName)).GetRootGameObjects();
				foreach (GameObject val2 in rootGameObjects)
				{
					val2.SetActive(false);
				}
				PlayerData.instance.UnlockedFastTravel = true;
			}
		}
	}
	[HarmonyPatch(typeof(HeroController))]
	internal class HeroControllerHook
	{
		[HarmonyPatch("CocoonBroken", new Type[]
		{
			typeof(bool),
			typeof(bool)
		})]
		[HarmonyPrefix]
		public static void CocoonBrokenPrefix(out int __state)
		{
			__state = ClientState.LastCurrency;
			int heroCorpseMoneyPool = PlayerData.instance.HeroCorpseMoneyPool;
			if (heroCorpseMoneyPool != 0)
			{
				ClientState.LastCurrency = heroCorpseMoneyPool;
			}
		}

		[HarmonyPatch("CocoonBroken", new Type[]
		{
			typeof(bool),
			typeof(bool)
		})]
		[HarmonyPostfix]
		public static void CocoonBrokenPostfix(int __state)
		{
			ClientState.LastCurrency = __state;
		}

		[HarmonyPatch("AddToMaxSilkRegen")]
		[HarmonyPrefix]
		public static void AddToMaxSilkRegen()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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)
			if (!ClientState.WasUpgradeReceived(FlagType.SilkHeart))
			{
				Scene activeScene = SceneManager.GetActiveScene();
				string text = ((Scene)(ref activeScene)).name;
				if (text == "Memory_Silk_Heart_BellBeast")
				{
					text = "Bone_05";
				}
				SceneData.instance.PersistentBools.SetValue(new PersistentItemData<bool>
				{
					ID = "Silk Heart",
					SceneName = text,
					IsSemiPersistent = false,
					Value = true,
					Mutator = (PersistentMutatorTypes)0
				});
				NetworkSender.SendUpgrade(text, FlagType.SilkHeart);
			}
		}
	}
	[HarmonyPatch(typeof(PersistentItem<bool>))]
	internal class PersistentBoolItemHook
	{
		private static readonly Dictionary<string, FlagType> PersistentTypes = new Dictionary<string, FlagType>
		{
			{
				"moss vine cluster",
				FlagType.Shortcut
			},
			{
				"abyss_collapse_wall_bot",
				FlagType.Shortcut
			},
			{
				"shaman_collapse_wall",
				FlagType.Shortcut
			},
			{
				"explode_wall",
				FlagType.Shortcut
			},
			{
				"explode_wall 4",
				FlagType.Shortcut
			},
			{
				"explode_wall fake",
				FlagType.Shortcut
			},
			{
				"abyss_collapse_wall",
				FlagType.Shortcut
			},
			{
				"weaver_lift_power_chamber",
				FlagType.Shortcut
			},
			{
				"ant_lever_persistent",
				FlagType.Shortcut
			},
			{
				"one way wall",
				FlagType.Shortcut
			},
			{
				"collapser small",
				FlagType.Shortcut
			},
			{
				"collapser small_bell_type",
				FlagType.Shortcut
			},
			{
				"breakable wall aqueduct start",
				FlagType.Shortcut
			},
			{
				"breakable wall",
				FlagType.Shortcut
			},
			{
				"breakable wall bot mid",
				FlagType.Shortcut
			},
			{
				"breakable wall_silhouette",
				FlagType.Shortcut
			},
			{
				"drop_planks",
				FlagType.Shortcut
			},
			{
				"inverse remasker",
				FlagType.Shortcut
			},
			{
				"grouped remasker",
				FlagType.Shortcut
			},
			{
				"grouped remasker_large",
				FlagType.Shortcut
			},
			{
				"secret mask",
				FlagType.Shortcut
			},
			{
				"secret mask new",
				FlagType.Shortcut
			},
			{
				"secret mask new sharp ultra",
				FlagType.Shortcut
			},
			{
				"secret mask new gate",
				FlagType.Shortcut
			},
			{
				"slab_vent_mask",
				FlagType.Shortcut
			},
			{
				"breakable window",
				FlagType.Shortcut
			},
			{
				"breakable window arborium",
				FlagType.Shortcut
			},
			{
				"coral crust wall sphere",
				FlagType.Shortcut
			},
			{
				"crust wall",
				FlagType.Shortcut
			},
			{
				"coral crust wall tall",
				FlagType.Shortcut
			},
			{
				"coral crust wall mid",
				FlagType.Shortcut
			},
			{
				"coral crust wall small",
				FlagType.Shortcut
			},
			{
				"song_lever_side old",
				FlagType.Shortcut
			},
			{
				"song_lever_side",
				FlagType.Shortcut
			},
			{
				"song_lever_side right",
				FlagType.Shortcut
			},
			{
				"bell wall tall",
				FlagType.Shortcut
			},
			{
				"mines lift",
				FlagType.Shortcut
			},
			{
				"act3_bellway_01_breakable_wall",
				FlagType.Shortcut
			},
			{
				"wind rock",
				FlagType.Shortcut
			},
			{
				"plank_wall_cluster",
				FlagType.Shortcut
			},
			{
				"understore lever",
				FlagType.Shortcut
			},
			{
				"gg_breakable_junk_pile_red",
				FlagType.Shortcut
			},
			{
				"charm_break_wall",
				FlagType.Shortcut
			},
			{
				"bone lever",
				FlagType.Shortcut
			},
			{
				"chain drop platform",
				FlagType.Shortcut
			},
			{
				"bone gate",
				FlagType.Shortcut
			},
			{
				"fall_platform_barrels",
				FlagType.Shortcut
			},
			{
				"lever",
				FlagType.Shortcut
			},
			{
				"song_gate_small",
				FlagType.Shortcut
			},
			{
				"trapdoor lever",
				FlagType.Shortcut
			},
			{
				"plate",
				FlagType.Shortcut
			},
			{
				"bone carriage",
				FlagType.Shortcut
			},
			{
				"barrel plat lift",
				FlagType.Shortcut
			},
			{
				"dockdashexploderock",
				FlagType.Shortcut
			},
			{
				"explode_wall (7) - boneeast07_openedmidroof",
				FlagType.Shortcut
			},
			{
				"bone_east_10_church",
				FlagType.Shortcut
			},
			{
				"toll door",
				FlagType.Shortcut
			},
			{
				"toll door breakable cog",
				FlagType.Shortcut
			},
			{
				"dropbomb rock",
				FlagType.Shortcut
			},
			{
				"bone east 11 cross over group",
				FlagType.Shortcut
			},
			{
				"coal bucket plat",
				FlagType.Shortcut
			},
			{
				"explode_wall_norck",
				FlagType.Shortcut
			},
			{
				"hornet_pressure_plate_small_persistent",
				FlagType.Shortcut
			},
			{
				"clover gate",
				FlagType.Shortcut
			},
			{
				"cog_lever",
				FlagType.Shortcut
			},
			{
				"active",
				FlagType.Shortcut
			},
			{
				"cog_junk_pile_break",
				FlagType.Shortcut
			},
			{
				"pipe_vent_hatch broken",
				FlagType.Shortcut
			},
			{
				"plank_wall_cluster_metal",
				FlagType.Shortcut
			},
			{
				"slide_gate_ring",
				FlagType.Shortcut
			},
			{
				"coral10rightsidegate",
				FlagType.Shortcut
			},
			{
				"coral crust mask",
				FlagType.Shortcut
			},
			{
				"coral_gate_large",
				FlagType.Shortcut
			},
			{
				"stalactite group bottom",
				FlagType.Shortcut
			},
			{
				"stalactite group top",
				FlagType.Shortcut
			},
			{
				"breakable blocker struts",
				FlagType.Shortcut
			},
			{
				"cradle_plat",
				FlagType.Shortcut
			},
			{
				"cradle_spike_plat",
				FlagType.Shortcut
			},
			{
				"aspid_sealed_gate_stone",
				FlagType.Shortcut
			},
			{
				"harpoon ring pull switch",
				FlagType.Shortcut
			},
			{
				"dock_pressure_plate_lock",
				FlagType.Shortcut
			},
			{
				"greymoor_lever_simple_edited",
				FlagType.Shortcut
			},
			{
				"dust_02gate",
				FlagType.Shortcut
			},
			{
				"greymoor_lever_simple",
				FlagType.Shortcut
			},
			{
				"break wall dustpen cage",
				FlagType.Shortcut
			},
			{
				"plat collider",
				FlagType.Shortcut
			},
			{
				"bell chain plat",
				FlagType.Shortcut
			},
			{
				"greymoor stand lever - bridge",
				FlagType.Shortcut
			},
			{
				"greymoor stand lever - crane",
				FlagType.Shortcut
			},
			{
				"hornet_cage_rect_lift_greymoor",
				FlagType.Shortcut
			},
			{
				"propeller",
				FlagType.Shortcut
			},
			{
				"greymoor_breakable_plat",
				FlagType.Shortcut
			},
			{
				"belltown_lever_drop_plat",
				FlagType.Shortcut
			},
			{
				"greymoor_drop_propeller",
				FlagType.Shortcut
			},
			{
				"grey_wood_chain_plat_mid_breakable",
				FlagType.Shortcut
			},
			{
				"greymoor stand lever",
				FlagType.Shortcut
			},
			{
				"greystore_floor_shortcut",
				FlagType.Shortcut
			},
			{
				"bank_door",
				FlagType.Shortcut
			},
			{
				"bot blocker",
				FlagType.Shortcut
			},
			{
				"innerworks_lever",
				FlagType.Shortcut
			},
			{
				"top shortcut",
				FlagType.Shortcut
			},
			{
				"attic_ladder",
				FlagType.Shortcut
			},
			{
				"understore propeller",
				FlagType.Shortcut
			},
			{
				"gg_breakable_junk_pile_gold",
				FlagType.Shortcut
			},
			{
				"understore big plate gate",
				FlagType.Shortcut
			},
			{
				"barrel plat lift thin",
				FlagType.Shortcut
			},
			{
				"plug_gate",
				FlagType.Shortcut
			},
			{
				"stalactite group",
				FlagType.Shortcut
			},
			{
				"vine platform",
				FlagType.Shortcut
			},
			{
				"bone lever 2",
				FlagType.Shortcut
			},
			{
				"thick silk vines",
				FlagType.Shortcut
			},
			{
				"shellwood twig wall",
				FlagType.Shortcut
			},
			{
				"hornet_cage_rect_lift_organ",
				FlagType.Shortcut
			},
			{
				"organ_lift_broken_drop",
				FlagType.Shortcut
			},
			{
				"one way wall crystal",
				FlagType.Shortcut
			},
			{
				"junk_pile_break_peak",
				FlagType.Shortcut
			},
			{
				"crystal break chunk",
				FlagType.Shortcut
			},
			{
				"drop pillar_chunk",
				FlagType.Shortcut
			},
			{
				"sack_multi_breakable",
				FlagType.Shortcut
			},
			{
				"diving_bell_door_breakable",
				FlagType.Shortcut
			},
			{
				"dock_sealed_gate",
				FlagType.Shortcut
			},
			{
				"cage_mid_small_long_sway drop",
				FlagType.Shortcut
			},
			{
				"breakablewallswampbenchshortcut",
				FlagType.Shortcut
			},
			{
				"plank_wall_cluster_swamp",
				FlagType.Shortcut
			},
			{
				"witch cluster vine",
				FlagType.Shortcut
			},
			{
				"drop_planks_horizontal",
				FlagType.Shortcut
			},
			{
				"gloom_lift_destroy",
				FlagType.Shortcut
			},
			{
				"hornet_pressure_plate",
				FlagType.Shortcut
			},
			{
				"shellwood hive",
				FlagType.Shortcut
			},
			{
				"hornet_cage_rect_lift",
				FlagType.Shortcut
			},
			{
				"plank solid 2",
				FlagType.Shortcut
			},
			{
				"shellwood twig wall start",
				FlagType.Shortcut
			},
			{
				"shellwood twig wall top",
				FlagType.Shortcut
			},
			{
				"slab_jail_lever",
				FlagType.Shortcut
			},
			{
				"door_slabcaged",
				FlagType.Shortcut
			},
			{
				"slab lock",
				FlagType.Shortcut
			},
			{
				"slab_cage_plat_thin_fall",
				FlagType.Shortcut
			},
			{
				"slab lock l",
				FlagType.Shortcut
			},
			{
				"slab lock r",
				FlagType.Shortcut
			},
			{
				"breakable wall waterways",
				FlagType.Shortcut
			},
			{
				"jail gate door - persistent",
				FlagType.Shortcut
			},
			{
				"breakable floor_basic song_01",
				FlagType.Shortcut
			},
			{
				"breakable wall entrance secret",
				FlagType.Shortcut
			},
			{
				"breakable wall ruin lift",
				FlagType.Shortcut
			},
			{
				"chain platform breaker",
				FlagType.Shortcut
			},
			{
				"breakable wall  second",
				FlagType.Shortcut
			},
			{
				"propeller understore propeller",
				FlagType.Shortcut
			},
			{
				"hatch",
				FlagType.Shortcut
			},
			{
				"song_lever_side - merchant quest accepted",
				FlagType.Shortcut
			},
			{
				"breakable floor_basic",
				FlagType.Shortcut
			},
			{
				"cradle_pipe_trapdoor",
				FlagType.Shortcut
			},
			{
				"one way vinewall",
				FlagType.Shortcut
			},
			{
				"snail_collapse_wall",
				FlagType.Shortcut
			},
			{
				"pipe_cog_lever",
				FlagType.Shortcut
			},
			{
				"barrel plat lift dropper bottom",
				FlagType.Shortcut
			},
			{
				"barrel plat lift dropper",
				FlagType.Shortcut
			},
			{
				"collapser small understore grate",
				FlagType.Shortcut
			},
			{
				"fall_platform_barrel wide",
				FlagType.Shortcut
			},
			{
				"cog_05_shortcut",
				FlagType.Shortcut
			},
			{
				"innerworks trap bridge large",
				FlagType.Shortcut
			},
			{
				"architect shrine door",
				FlagType.Shortcut
			},
			{
				"fall platform support pole",
				FlagType.Shortcut
			},
			{
				"fall_platform_barrel",
				FlagType.Shortcut
			},
			{
				"understore lever l main",
				FlagType.Shortcut
			},
			{
				"under_lift_large",
				FlagType.Shortcut
			},
			{
				"lock_machine",
				FlagType.Shortcut
			},
			{
				"pipe_vent_hatch",
				FlagType.Shortcut
			},
			{
				"ward_junk_pile_break",
				FlagType.Shortcut
			},
			{
				"ward_junk_pile_break 1",
				FlagType.Shortcut
			},
			{
				"ward_junk_pile_break 2",
				FlagType.Shortcut
			},
			{
				"ward_junk_pile_break 3",
				FlagType.Shortcut
			},
			{
				"ward_junk_pile_break 4",
				FlagType.Shortcut
			},
			{
				"junk hatch",
				FlagType.Shortcut
			},
			{
				"crest_shrine_break_tube",
				FlagType.Shortcut
			},
			{
				"loom_room_jar2",
				FlagType.Shortcut
			},
			{
				"ant_item_string",
				FlagType.Collectable
			},
			{
				"tool_metal_deposit",
				FlagType.Collectable
			},
			{
				"ladybug craft pickup",
				FlagType.CraftingKit
			},
			{
				"silk grub large cocoon",
				FlagType.Collectable
			},
			{
				"silk grub small cocoon 1",
				FlagType.Collectable
			},
			{
				"silk grub small cocoon 2",
				FlagType.Collectable
			},
			{
				"breakable hang sack memory locket",
				FlagType.Collectable
			},
			{
				"collectable item pickup",
				FlagType.Collectable
			},
			{
				"slab_item_chain",
				FlagType.Collectable
			},
			{
				"breakable hang sack 3",
				FlagType.Collectable
			},
			{
				"heart piece",
				FlagType.Mask
			},
			{
				"library_glass_heart_piece",
				FlagType.Mask
			},
			{
				"silk spool",
				FlagType.Spool
			},
			{