Decompiled source of Archipelago Randomizer for REPO v0.2.1

RepoAP.dll

Decompiled 6 days ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.WebSockets;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Archipelago.MultiClient.Net;
using Archipelago.MultiClient.Net.BounceFeatures.DeathLink;
using Archipelago.MultiClient.Net.Colors;
using Archipelago.MultiClient.Net.ConcurrentCollection;
using Archipelago.MultiClient.Net.Converters;
using Archipelago.MultiClient.Net.DataPackage;
using Archipelago.MultiClient.Net.Enums;
using Archipelago.MultiClient.Net.Exceptions;
using Archipelago.MultiClient.Net.Extensions;
using Archipelago.MultiClient.Net.Helpers;
using Archipelago.MultiClient.Net.MessageLog.Messages;
using Archipelago.MultiClient.Net.MessageLog.Parts;
using Archipelago.MultiClient.Net.Models;
using Archipelago.MultiClient.Net.Packets;
using BepInEx;
using HarmonyLib;
using MenuLib;
using MenuLib.MonoBehaviors;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using Photon.Pun;
using RepoAP.Core;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("RepoAP")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Archipelago Randomizer")]
[assembly: AssemblyTitle("RepoAP")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace RepoAP
{
	[HarmonyPatch(typeof(MainMenuOpen), "Start")]
	internal class APConnectMenu
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Action <>9__0_1;

			public static BuilderDelegate <>9__0_0;

			internal void <Prefix>b__0_0(Transform parent)
			{
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				MenuAPI.CreateREPOButton("Archipelago", (Action)delegate
				{
					MenuBuilder.BuildPopup();
				}, parent, new Vector2(145f, 27f));
			}

			internal void <Prefix>b__0_1()
			{
				MenuBuilder.BuildPopup();
			}
		}

		[HarmonyPrefix]
		private static void Prefix()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			object obj = <>c.<>9__0_0;
			if (obj == null)
			{
				BuilderDelegate val = delegate(Transform parent)
				{
					//IL_0030: Unknown result type (might be due to invalid IL or missing references)
					MenuAPI.CreateREPOButton("Archipelago", (Action)delegate
					{
						MenuBuilder.BuildPopup();
					}, parent, new Vector2(145f, 27f));
				};
				<>c.<>9__0_0 = val;
				obj = (object)val;
			}
			MenuAPI.AddElementToMainMenu((BuilderDelegate)obj);
		}
	}
	public static class MenuBuilder
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static BuilderDelegate <>9__0_0;

			public static BuilderDelegate <>9__0_1;

			public static Action<string> <>9__0_8;

			public static BuilderDelegate <>9__0_2;

			public static Action<string> <>9__0_9;

			public static BuilderDelegate <>9__0_3;

			public static Action<string> <>9__0_10;

			public static BuilderDelegate <>9__0_4;

			public static Action<string> <>9__0_11;

			public static BuilderDelegate <>9__0_5;

			internal void <BuildPopup>b__0_0(Transform parent)
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				MenuAPI.CreateREPOLabel("<size=12>Only host player must be connected to AP Server.", parent, new Vector2(380f, 275f));
			}

			internal void <BuildPopup>b__0_1(Transform parent)
			{
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				MenuAPI.CreateREPOLabel(Plugin.connection.connected ? "<size=12><color=#00ad2e>Connected" : "<size=12><color=#7a000e>Not Connected", parent, new Vector2(400f, 225f));
			}

			internal void <BuildPopup>b__0_2(Transform parent)
			{
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				MenuAPI.CreateREPOInputField("Address", (Action<string>)delegate(string input)
				{
					Plugin.apAdress = input;
				}, parent, new Vector2(400f, 200f), false, Plugin.apAdress, "");
			}

			internal void <BuildPopup>b__0_8(string input)
			{
				Plugin.apAdress = input;
			}

			internal void <BuildPopup>b__0_3(Transform parent)
			{
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				MenuAPI.CreateREPOInputField("Port", (Action<string>)delegate(string input)
				{
					Plugin.apPort = input;
				}, parent, new Vector2(400f, 175f), false, Plugin.apPort, "");
			}

			internal void <BuildPopup>b__0_9(string input)
			{
				Plugin.apPort = input;
			}

			internal void <BuildPopup>b__0_4(Transform parent)
			{
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				MenuAPI.CreateREPOInputField("Password", (Action<string>)delegate(string input)
				{
					Plugin.apPassword = input;
				}, parent, new Vector2(400f, 150f), false, Plugin.apPassword, "");
			}

			internal void <BuildPopup>b__0_10(string input)
			{
				Plugin.apPassword = input;
			}

			internal void <BuildPopup>b__0_5(Transform parent)
			{
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				MenuAPI.CreateREPOInputField("Player Slot", (Action<string>)delegate(string input)
				{
					Plugin.apSlot = input;
				}, parent, new Vector2(400f, 125f), false, Plugin.apSlot, "");
			}

			internal void <BuildPopup>b__0_11(string input)
			{
				Plugin.apSlot = input;
			}
		}

		public static void BuildPopup()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Expected O, but got Unknown
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Expected O, but got Unknown
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Expected O, but got Unknown
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Expected O, but got Unknown
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Expected O, but got Unknown
			Debug.LogWarning((object)"Building Popup");
			REPOPopupPage repoPage = MenuAPI.CreateREPOPopupPage("Archipelago", (PresetSide)1, false, true, 1.5f);
			REPOPopupPage obj = repoPage;
			object obj2 = <>c.<>9__0_0;
			if (obj2 == null)
			{
				BuilderDelegate val = delegate(Transform parent)
				{
					//IL_0010: Unknown result type (might be due to invalid IL or missing references)
					MenuAPI.CreateREPOLabel("<size=12>Only host player must be connected to AP Server.", parent, new Vector2(380f, 275f));
				};
				<>c.<>9__0_0 = val;
				obj2 = (object)val;
			}
			obj.AddElement((BuilderDelegate)obj2);
			REPOPopupPage obj3 = repoPage;
			object obj4 = <>c.<>9__0_1;
			if (obj4 == null)
			{
				BuilderDelegate val2 = delegate(Transform parent)
				{
					//IL_0023: Unknown result type (might be due to invalid IL or missing references)
					MenuAPI.CreateREPOLabel(Plugin.connection.connected ? "<size=12><color=#00ad2e>Connected" : "<size=12><color=#7a000e>Not Connected", parent, new Vector2(400f, 225f));
				};
				<>c.<>9__0_1 = val2;
				obj4 = (object)val2;
			}
			obj3.AddElement((BuilderDelegate)obj4);
			REPOPopupPage obj5 = repoPage;
			object obj6 = <>c.<>9__0_2;
			if (obj6 == null)
			{
				BuilderDelegate val3 = delegate(Transform parent)
				{
					//IL_002f: Unknown result type (might be due to invalid IL or missing references)
					MenuAPI.CreateREPOInputField("Address", (Action<string>)delegate(string input)
					{
						Plugin.apAdress = input;
					}, parent, new Vector2(400f, 200f), false, Plugin.apAdress, "");
				};
				<>c.<>9__0_2 = val3;
				obj6 = (object)val3;
			}
			obj5.AddElement((BuilderDelegate)obj6);
			REPOPopupPage obj7 = repoPage;
			object obj8 = <>c.<>9__0_3;
			if (obj8 == null)
			{
				BuilderDelegate val4 = delegate(Transform parent)
				{
					//IL_002f: Unknown result type (might be due to invalid IL or missing references)
					MenuAPI.CreateREPOInputField("Port", (Action<string>)delegate(string input)
					{
						Plugin.apPort = input;
					}, parent, new Vector2(400f, 175f), false, Plugin.apPort, "");
				};
				<>c.<>9__0_3 = val4;
				obj8 = (object)val4;
			}
			obj7.AddElement((BuilderDelegate)obj8);
			REPOPopupPage obj9 = repoPage;
			object obj10 = <>c.<>9__0_4;
			if (obj10 == null)
			{
				BuilderDelegate val5 = delegate(Transform parent)
				{
					//IL_002f: Unknown result type (might be due to invalid IL or missing references)
					MenuAPI.CreateREPOInputField("Password", (Action<string>)delegate(string input)
					{
						Plugin.apPassword = input;
					}, parent, new Vector2(400f, 150f), false, Plugin.apPassword, "");
				};
				<>c.<>9__0_4 = val5;
				obj10 = (object)val5;
			}
			obj9.AddElement((BuilderDelegate)obj10);
			REPOPopupPage obj11 = repoPage;
			object obj12 = <>c.<>9__0_5;
			if (obj12 == null)
			{
				BuilderDelegate val6 = delegate(Transform parent)
				{
					//IL_002f: Unknown result type (might be due to invalid IL or missing references)
					MenuAPI.CreateREPOInputField("Player Slot", (Action<string>)delegate(string input)
					{
						Plugin.apSlot = input;
					}, parent, new Vector2(400f, 125f), false, Plugin.apSlot, "");
				};
				<>c.<>9__0_5 = val6;
				obj12 = (object)val6;
			}
			obj11.AddElement((BuilderDelegate)obj12);
			repoPage.AddElement((BuilderDelegate)delegate(Transform parent)
			{
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				MenuAPI.CreateREPOButton("Connect", (Action)delegate
				{
					Plugin.connection.TryConnect(Plugin.apAdress, int.Parse(Plugin.apPort), Plugin.apPassword, Plugin.apSlot);
					repoPage.ClosePage(false);
					BuildConnectingPopUp();
				}, parent, new Vector2(378f, 25f));
			});
			repoPage.AddElement((BuilderDelegate)delegate(Transform parent)
			{
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				MenuAPI.CreateREPOButton("Close", (Action)delegate
				{
					repoPage.ClosePage(true);
				}, parent, new Vector2(590f, 25f));
			});
			repoPage.OpenPage(true);
		}

		public static void BuildConnectingPopUp()
		{
			REPOPopupPage val = MenuAPI.CreateREPOPopupPage("Connecting to Server...", (PresetSide)1, false, true, 0f);
			Plugin.connection.connectingPage = val;
			val.OpenPage(true);
		}
	}
	internal class APSaveData
	{
		public APConnectionData connectionData = new APConnectionData();

		public List<long> locationsChecked = new List<long>();

		public List<string> pellysGathered = new List<string>();

		public List<string> valuablesGathered = new List<string>();

		public List<string> monsterSoulsGathered = new List<string>();

		public List<int> shopItemsPurchased = new List<int>();

		public long shopStockSlotData;

		public int shopStockReceived;

		public Dictionary<long, int> itemsReceived = new Dictionary<long, int>();

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

		public int itemReceivedIndex = 0;

		public Dictionary<long, ItemInfo> locationsScouted = new Dictionary<long, ItemInfo>();

		public JArray pellysRequired = new JArray();

		public bool pellySpawning;

		public long levelQuota;

		public long upgradeLocations;

		public bool valuableHunt;

		public bool monsterHunt;
	}
	internal static class APSave
	{
		public static ES3Settings es3Settings;

		public static APSaveData saveData;

		public static string fileName;

		private static string saveKey = "archipelago";

		public static void Init()
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			string text = Application.persistentDataPath + "/archipelago";
			fileName = BuildFileName();
			if (!Directory.Exists(text))
			{
				Directory.CreateDirectory(text);
			}
			text += "/saves";
			if (!Directory.Exists(text))
			{
				Directory.CreateDirectory(text);
			}
			text += fileName;
			if (!File.Exists(text))
			{
				es3Settings = new ES3Settings(text, new Enum[1] { (Enum)(object)(EncryptionType)0 });
				saveData = new APSaveData();
				SaveSlotDataToFile();
				ES3.Save<APSaveData>(saveKey, saveData, es3Settings);
			}
			else
			{
				es3Settings = new ES3Settings(text, new Enum[1] { (Enum)(object)(EncryptionType)0 });
				saveData = ES3.Load<APSaveData>(saveKey, saveData, es3Settings);
				SaveSlotDataToFile();
				ES3.Save<APSaveData>(saveKey, saveData, es3Settings);
			}
		}

		private static string BuildFileName()
		{
			if (Plugin.connection.session == null)
			{
				return null;
			}
			return "/" + Plugin.connection.session.Players.ActivePlayer.Name + "___" + Plugin.connection.session.RoomState.Seed + ".es3";
		}

		private static void SaveSlotDataToFile()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			if (Plugin.connection.session != null)
			{
				saveData.levelQuota = (long)Plugin.connection.slotData["level_quota"];
				saveData.pellysRequired = (JArray)Plugin.connection.slotData["pellys_required"];
				saveData.pellySpawning = (bool)Plugin.connection.slotData["pelly_spawning"];
				saveData.upgradeLocations = (long)Plugin.connection.slotData["upgrade_locations"];
				saveData.shopStockSlotData = (long)Plugin.connection.slotData["shop_stock"];
				saveData.valuableHunt = (bool)Plugin.connection.slotData["valuable_hunt"];
				saveData.monsterHunt = (bool)Plugin.connection.slotData["monster_hunt"];
			}
		}

		public static void SyncServerLocationsToSave()
		{
			if (!Plugin.connection.connected)
			{
				return;
			}
			ArchipelagoSession session = Plugin.connection.session;
			ReadOnlyCollection<long> allLocationsChecked = session.Locations.AllLocationsChecked;
			foreach (long item in allLocationsChecked)
			{
				if (!GetLocationsChecked().Contains(item))
				{
					AddLocationChecked(item);
				}
				string locationNameFromId = session.Locations.GetLocationNameFromId(item);
				if (locationNameFromId.Contains("Pelly"))
				{
					AddPellyGathered(locationNameFromId);
				}
				if (locationNameFromId.Contains("Valuable"))
				{
					AddValuableGathered(LocationData.ValuableIDToName(item));
				}
				if (locationNameFromId.Contains("Soul"))
				{
					AddMonsterSoulGathered(LocationData.MonsterSoulIDToName(item));
				}
			}
		}

		public static void AddLocationChecked(long locToAdd)
		{
			if (Plugin.connection.session != null)
			{
				saveData.locationsChecked.Add(locToAdd);
				ES3.Save<APSaveData>(saveKey, saveData, es3Settings);
			}
		}

		public static List<long> GetLocationsChecked()
		{
			if (Plugin.connection.session == null)
			{
				return null;
			}
			return ES3.Load<APSaveData>(saveKey, es3Settings).locationsChecked;
		}

		public static List<int> GetShopLocationsChecked()
		{
			if (Plugin.connection.session == null)
			{
				return null;
			}
			List<long> locationsChecked = GetLocationsChecked();
			List<int> list = new List<int>();
			foreach (long item in locationsChecked)
			{
				if (LocationData.RemoveBaseId(item) <= 100)
				{
					list.Add((int)LocationData.RemoveBaseId(item));
				}
			}
			return list;
		}

		public static void AddItemReceived(long itemId)
		{
			if (Plugin.connection.session != null)
			{
				if (saveData.itemsReceived.ContainsKey(itemId))
				{
					saveData.itemsReceived[itemId]++;
				}
				else
				{
					saveData.itemsReceived.Add(itemId, 1);
				}
				saveData.itemReceivedIndex++;
				ES3.Save<APSaveData>(saveKey, saveData, es3Settings);
			}
		}

		public static int GetItemReceivedIndex()
		{
			if (Plugin.connection.session == null)
			{
				return 0;
			}
			return ES3.Load<APSaveData>(saveKey, es3Settings).itemReceivedIndex;
		}

		public static void AddStockReceived()
		{
			if (Plugin.connection.session != null)
			{
				if (saveData.itemsReceived.ContainsKey(ItemData.AddBaseId(20L)))
				{
					saveData.shopStockReceived = saveData.itemsReceived[ItemData.AddBaseId(20L)];
				}
				else
				{
					saveData.shopStockReceived = 0;
				}
				ES3.Save<APSaveData>(saveKey, saveData, es3Settings);
			}
		}

		public static void UpdateAvailableItems()
		{
			Plugin.ShopItemsAvailable = new List<int>();
			Plugin.ShopItemsBought = GetShopLocationsChecked();
			for (int i = 1; i <= saveData.shopStockSlotData * (saveData.shopStockReceived + 1); i++)
			{
				if (!Plugin.ShopItemsBought.Contains(i) && Plugin.connection.session.Locations.AllMissingLocations.Contains(ItemData.AddBaseId(i)))
				{
					Plugin.ShopItemsAvailable.Add(i);
				}
			}
		}

		public static Dictionary<long, int> GetItemsReceived()
		{
			if (Plugin.connection.session == null)
			{
				return null;
			}
			return ES3.Load<APSaveData>(saveKey, es3Settings).itemsReceived;
		}

		public static bool IsItemReceived(long id, int count = 1)
		{
			if (!Plugin.connection.connected)
			{
				return false;
			}
			Dictionary<long, int> itemsReceived = ES3.Load<APSaveData>(saveKey, es3Settings).itemsReceived;
			bool result = false;
			if (itemsReceived.ContainsKey(id) && itemsReceived[id] >= count)
			{
				result = true;
			}
			return result;
		}

		public static void AddLevelReceived(string levelName)
		{
			if (Plugin.connection.session != null)
			{
				if (!saveData.levelsUnlocked.ContainsKey(levelName) || !saveData.levelsUnlocked[levelName])
				{
					saveData.levelsUnlocked.Add(levelName, value: true);
				}
				else
				{
					Debug.LogError((object)(levelName + " has already been received!"));
				}
				ES3.Save<APSaveData>(saveKey, saveData, es3Settings);
			}
		}

		public static Dictionary<string, bool> GetLevelsReceived()
		{
			if (Plugin.connection.session == null)
			{
				return null;
			}
			return ES3.Load<APSaveData>(saveKey, es3Settings).levelsUnlocked;
		}

		public static async void ScoutLocations()
		{
			if (Plugin.connection.session == null)
			{
				return;
			}
			Debug.Log((object)"Scouting Locations...");
			int shop_item_count = 100;
			int pelly_count = LocationNames.all_pellys.Count * LocationNames.all_levels.Count;
			int valuable_count = LocationNames.all_valuables.Count;
			int monster_count = LocationNames.all_monster_souls.Count;
			Debug.Log((object)$"Checking {shop_item_count} shop items...");
			Debug.Log((object)$"Checking {pelly_count} pelly statues...");
			Debug.Log((object)$"Checking {valuable_count} valuables...");
			Debug.Log((object)$"Checking {monster_count} monster souls...");
			long[] idsToScout = new long[shop_item_count + pelly_count + valuable_count + monster_count];
			int p = 0;
			for (int i = 1; i <= shop_item_count; i++)
			{
				idsToScout[p++] = LocationData.AddBaseId(i);
			}
			for (int j = 1; j <= pelly_count; j++)
			{
				idsToScout[p++] = LocationData.AddBaseId(100 + j);
			}
			for (int k = 1; k <= valuable_count; k++)
			{
				idsToScout[p++] = LocationData.AddBaseId(200 + k);
			}
			for (int l = 1; l <= monster_count; l++)
			{
				idsToScout[p++] = LocationData.AddBaseId(500 + l);
			}
			try
			{
				Dictionary<long, ScoutedItemInfo> scout = await Plugin.connection.session.Locations.ScoutLocationsAsync(idsToScout);
				saveData.locationsScouted = new Dictionary<long, ItemInfo>();
				foreach (ScoutedItemInfo item in scout.Values)
				{
					saveData.locationsScouted.Add(item.LocationId, item);
				}
			}
			catch (Exception e)
			{
				Debug.LogError((object)e);
			}
			ES3.Save<APSaveData>(saveKey, saveData, es3Settings);
		}

		public static ItemInfo GetScoutedLocation(long id)
		{
			if (Plugin.connection.session != null && saveData.locationsScouted.ContainsKey(id))
			{
				return saveData.locationsScouted[id];
			}
			return null;
		}

		public static ItemInfo GetScoutedShopItem(long id)
		{
			return GetScoutedLocation(id);
		}

		public static void AddPellyGathered(string name)
		{
			if (Plugin.connection.session == null)
			{
				return;
			}
			if (LocationNames.all_levels.Any((string x) => name.Contains(x)))
			{
				string text = LocationNames.all_levels.FirstOrDefault((string x) => name.Contains(x));
				int index = LocationNames.all_levels.IndexOf(text);
				name.Replace(text, LocationNames.all_levels_short[index]);
			}
			name = name.Replace(" ", "").Replace("Valuable", "").Replace("(Clone)", "")
				.ToLower();
			if (!saveData.pellysGathered.Contains(name))
			{
				saveData.pellysGathered.Add(name);
			}
			ES3.Save<APSaveData>(saveKey, saveData, es3Settings);
		}

		public static void AddValuableGathered(string name)
		{
			name = LocationData.GetBaseName(name);
			if (Plugin.connection.session != null)
			{
				if (!saveData.valuablesGathered.Contains(name))
				{
					saveData.valuablesGathered.Add(name);
				}
				ES3.Save<APSaveData>(saveKey, saveData, es3Settings);
			}
		}

		public static void AddMonsterSoulGathered(string name)
		{
			name = LocationData.GetBaseName(name);
			if (Plugin.connection.session != null)
			{
				if (!saveData.monsterSoulsGathered.Contains(name))
				{
					saveData.monsterSoulsGathered.Add(name);
				}
				ES3.Save<APSaveData>(saveKey, saveData, es3Settings);
			}
		}

		public static bool WasValuableGathered(string name)
		{
			name = LocationData.GetBaseName(name);
			return saveData.valuablesGathered.Contains(name);
		}

		public static bool WasMonsterSoulGathered(string name)
		{
			name = LocationData.GetBaseName(name);
			return saveData.monsterSoulsGathered.Contains(name);
		}

		public static bool WasPellyGathered(string pelly, string level)
		{
			return saveData.pellysGathered.Exists((string x) => x.Contains(level) && x.Contains(pelly));
		}

		public static bool IsPellyRequired(string pelly)
		{
			return ((IEnumerable<JToken>)saveData.pellysRequired).Any((JToken x) => pelly.Contains(((object)x).ToString()));
		}

		public static bool CheckCompletion(out string status)
		{
			if (Plugin.connection.session == null)
			{
				status = string.Empty;
				return false;
			}
			ReadOnlyCollection<long> allLocationsChecked = Plugin.connection.session.Locations.AllLocationsChecked;
			ReadOnlyCollection<long> allMissingLocations = Plugin.connection.session.Locations.AllMissingLocations;
			bool flag = true;
			int runStatLevel = StatsManager.instance.GetRunStatLevel();
			status = "";
			Debug.Log((object)"CheckComplete");
			Debug.Log((object)$"Current Level: {runStatLevel}\nQuota: {saveData.levelQuota}");
			if (runStatLevel < saveData.levelQuota)
			{
				Debug.Log((object)"Level Quota not met");
				flag = false;
			}
			status = string.Format("{{truck}} Levels - {0}/{1}{2}", runStatLevel, saveData.levelQuota, (runStatLevel >= saveData.levelQuota) ? " {check}" : " {X}");
			JArray pellysRequired = saveData.pellysRequired;
			int num = ((JContainer)saveData.pellysRequired).Count * LocationNames.all_levels_short.Count;
			int num2 = 0;
			Debug.Log((object)"Pellys Required:");
			foreach (JToken item in saveData.pellysRequired)
			{
				Debug.Log((object)$"-{((object)item).ToString()} {((JContainer)saveData.pellysRequired).Count}");
			}
			Debug.Log((object)"Pellys Gathered:");
			foreach (long item2 in allLocationsChecked)
			{
				string locName = Plugin.connection.session.Locations.GetLocationNameFromId(item2);
				if (!locName.Contains("Pelly"))
				{
					continue;
				}
				Debug.Log((object)("-" + locName));
				foreach (string all_level in LocationNames.all_levels)
				{
					Debug.Log((object)all_level);
					locName = locName.Replace(all_level, "");
				}
				Debug.Log((object)locName);
				if (((IEnumerable<JToken>)saveData.pellysRequired).Any((JToken x) => locName.Contains(((object)x).ToString())))
				{
					num2++;
				}
			}
			if (num2 < num)
			{
				Debug.Log((object)"Pelly hunt not complete.");
				flag = false;
			}
			foreach (long item3 in allMissingLocations)
			{
				string locationNameFromId = Plugin.connection.session.Locations.GetLocationNameFromId(item3);
				if (locationNameFromId.Contains("Pelly"))
				{
					Debug.Log((object)("Missing " + locationNameFromId));
				}
			}
			status += string.Format("<br>{{?}} Pelly - {0}/{1}{2}", num2, num, (num2 == num) ? " {check}" : " {X}");
			if (saveData.monsterHunt)
			{
				num = LocationNames.all_monster_souls.Count;
				num2 = 0;
				Debug.Log((object)"Monster Hunt");
				foreach (string all_monster_soul in LocationNames.all_monster_souls)
				{
					if (!saveData.monsterSoulsGathered.Contains(all_monster_soul))
					{
						Debug.Log((object)(all_monster_soul + " has not been extracted"));
						flag = false;
					}
					else
					{
						Debug.Log((object)(all_monster_soul + " hunted"));
						num2++;
					}
				}
				status += string.Format("<br>{{ghost}} Souls - {0}/{1}{2}", num2, num, (num2 == num) ? " {check}" : " {X}");
			}
			if (saveData.valuableHunt)
			{
				num = LocationNames.all_valuables.Count;
				num2 = 0;
				Debug.Log((object)"Valuable Hunt");
				foreach (string all_valuable in LocationNames.all_valuables)
				{
					if (!saveData.valuablesGathered.Contains(all_valuable))
					{
						Debug.Log((object)(all_valuable + " has not been extracted"));
						flag = false;
					}
					else
					{
						Debug.Log((object)(all_valuable + " extracted"));
						num2++;
					}
				}
				status += string.Format("<br>{{$$$}} Valuables - {0}/{1}{2}", num2, num, (num2 == num) ? " {check}" : " {X}");
			}
			if (flag)
			{
				Debug.Log((object)"All Goals Complete.");
			}
			return flag;
		}
	}
	internal class APConnectionData
	{
		private string address = "archipelago.gg";

		private string port = "";

		private string password = "";

		private string slot = "";
	}
	public class ArchipelagoConnection
	{
		private struct messageData
		{
			public string message { get; }

			public Color flashCol { get; }

			public Color mainCol { get; }

			public float time { get; }

			public messageData(string m, Color fc, Color mc, float t)
			{
				//IL_0009: 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_0010: 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)
				message = m;
				flashCol = fc;
				mainCol = mc;
				time = t;
			}
		}

		public REPOPopupPage connectingPage;

		public ArchipelagoSession session;

		public IEnumerator<bool> incomingItemHandler;

		public IEnumerator<bool> outgoingItemHandler;

		public IEnumerator<bool> checkItemsReceived;

		public IEnumerator<bool> messageHandler;

		private float messageDelay = 0f;

		public bool sentCompletion = false;

		public bool sentRelease = false;

		public bool sentCollect = false;

		public Dictionary<string, object> slotData;

		public DeathLinkService deathLinkService;

		public int ItemIndex = 0;

		private ConcurrentQueue<(ItemInfo NetworkItem, int index)> incomingItems;

		private ConcurrentQueue<ItemInfo> outgoingItems;

		private ConcurrentQueue<messageData> messageItems;

		public bool connected => session != null && session.Socket.Connected;

		public async Task TryConnect(string adress, int port, string pass, string player)
		{
			Debug.Log((object)"TryConnect");
			if (connected)
			{
				Debug.Log((object)"Returning");
				return;
			}
			TryDisconnect();
			if (session == null)
			{
				try
				{
					session = ArchipelagoSessionFactory.CreateSession(adress, port);
					Debug.Log((object)("Session at " + session.ToString()));
					session.MessageLog.OnMessageReceived += MessageLog_OnMessageReceived;
				}
				catch
				{
					Debug.Log((object)"Failed to create archipelago session!");
				}
			}
			incomingItemHandler = IncomingItemHandler();
			outgoingItemHandler = OutgoingItemHandler();
			checkItemsReceived = CheckItemsReceived();
			messageHandler = MessageHandler();
			incomingItems = new ConcurrentQueue<(ItemInfo, int)>();
			outgoingItems = new ConcurrentQueue<ItemInfo>();
			messageItems = new ConcurrentQueue<messageData>();
			LoginResult result;
			try
			{
				await session.ConnectAsync();
				result = await session.LoginAsync("R.E.P.O", player, ItemsHandlingFlags.AllItems, null, null, null, pass);
			}
			catch (Exception e)
			{
				result = new LoginFailure(e.GetBaseException().Message);
			}
			if (result is LoginSuccessful LoginSuccess)
			{
				slotData = LoginSuccess.SlotData;
				Debug.Log((object)"Successfully connected to Archipelago Multiworld server!");
				APSave.Init();
				APSave.ScoutLocations();
				if (!SemiFunc.MenuLevel())
				{
					messageData md = new messageData("Successfully Connected!", Color.white, Color.green, 3f);
					messageItems.Enqueue(md);
				}
				deathLinkService = session.CreateDeathLinkService();
			}
			else
			{
				LoginFailure loginFailure = (LoginFailure)result;
				Debug.Log((object)"Error connecting to Archipelago:");
				string[] errors = loginFailure.Errors;
				foreach (string Error in errors)
				{
					Debug.Log((object)Error);
				}
				ConnectionRefusedError[] errorCodes = loginFailure.ErrorCodes;
				for (int j = 0; j < errorCodes.Length; j++)
				{
					ConnectionRefusedError Error2 = errorCodes[j];
					Debug.Log((object)Error2.ToString());
				}
				TryDisconnect();
			}
			if (SemiFunc.MenuLevel())
			{
				connectingPage.ClosePage(false);
				MenuBuilder.BuildPopup();
			}
		}

		private string RGBtoHtmlStr(Color col)
		{
			byte[] array = new byte[3] { col.R, col.G, col.B };
			return BitConverter.ToString(array).Replace("-", string.Empty);
		}

		private void MessageLog_OnMessageReceived(LogMessage message)
		{
			string text = string.Empty;
			MessagePart[] parts = message.Parts;
			foreach (MessagePart messagePart in parts)
			{
				string empty = string.Empty;
				string empty2 = string.Empty;
				empty2 = RGBtoHtmlStr(messagePart.Color);
				text = ((!(empty2 != string.Empty)) ? (text + messagePart.Text) : (text + "<color=#" + empty2 + "><b>" + messagePart.Text + "</b></color>"));
			}
			HandleAPTruckScreenMessages.TruckScreenChatPatch.AddMessage("AP", text);
		}

		private void OnItemReceived(ReceivedItemsHelper helper)
		{
			ItemInfo itemInfo = helper.DequeueItem();
			Debug.Log((object)("OnItemReceived: " + itemInfo.ToString()));
		}

		public void TryDisconnect()
		{
			try
			{
				if (session != null)
				{
					session.Socket.DisconnectAsync();
					session = null;
				}
				incomingItems = new ConcurrentQueue<(ItemInfo, int)>();
				outgoingItems = new ConcurrentQueue<ItemInfo>();
				deathLinkService = null;
				slotData = null;
				ItemIndex = 0;
				Debug.Log((object)"Disconnected from Archipelago");
			}
			catch
			{
				Debug.Log((object)"Encountered an error disconnecting from Archipelago!");
			}
		}

		public async Task ClientDisconnected()
		{
			try
			{
				messageData md = new messageData("Client Disconnected! Trying to Reconnect...", Color.white, Color.red, 4f);
				messageItems.Enqueue(md);
				await TryConnect(Plugin.apAdress, int.Parse(Plugin.apPort), Plugin.apPassword, Plugin.apSlot);
			}
			catch (Exception ex)
			{
				Exception e = ex;
				Debug.Log((object)("Failure in reconnecting: " + e.Message));
			}
		}

		public void ActivateCheck(long locationID)
		{
			if (APSave.saveData.locationsChecked.Contains(locationID))
			{
				return;
			}
			Debug.Log((object)("Checked Location " + locationID));
			session.Locations.CompleteLocationChecksAsync(locationID);
			APSave.AddLocationChecked(locationID);
			if (APSave.saveData.locationsScouted.ContainsKey(locationID))
			{
				outgoingItems.Enqueue(APSave.saveData.locationsScouted[locationID]);
				return;
			}
			session.Locations.ScoutLocationsAsync(locationID).ContinueWith(delegate(Task<Dictionary<long, ScoutedItemInfo>> locationInfoPacket)
			{
				foreach (ScoutedItemInfo value in locationInfoPacket.Result.Values)
				{
					outgoingItems.Enqueue(value);
				}
			});
		}

		public void SyncLocations()
		{
			int count = session.Locations.AllLocationsChecked.Count;
			Dictionary<string, int> dictionary = StatsManager.instance.dictionaryOfDictionaries["archipelago items sent to other players"];
			if (count != dictionary.Count)
			{
				Debug.Log((object)"Locations Unsynced, resyncing...");
				Dictionary<string, int> dictionary2 = StatsManager.instance.dictionaryOfDictionaries["Locations Obtained"];
				Debug.Log((object)("Server: " + count + "\nClient Count: " + dictionary?.ToString() + "\nClient Raw: " + dictionary2.Count));
			}
		}

		public string GetLocationName(long id)
		{
			return session.Locations.GetLocationNameFromId(id);
		}

		public long GetLocationID(string name)
		{
			return session.Locations.GetLocationIdFromName("Another Crabs Treasure", name);
		}

		public string GetItemName(long id)
		{
			return session.Items.GetItemName(id) ?? $"Item: {id}";
		}

		private IEnumerator<bool> CheckItemsReceived()
		{
			while (connected)
			{
				if (session.Items.AllItemsReceived.Count > ItemIndex)
				{
					ItemInfo Item = session.Items.AllItemsReceived[ItemIndex];
					string ItemReceivedName = Item.ItemName;
					Debug.Log((object)("Placing item " + ItemReceivedName + " with index " + ItemIndex + " in queue."));
					incomingItems.Enqueue((Item, ItemIndex));
					ItemIndex++;
					yield return true;
				}
				else
				{
					yield return true;
				}
			}
		}

		private IEnumerator<bool> MessageHandler()
		{
			while (!SemiFunc.MenuLevel())
			{
				messageDelay -= Time.deltaTime;
				if (messageDelay > 0f)
				{
					yield return true;
					continue;
				}
				if (!messageItems.TryDequeue(out var messageData))
				{
					yield return true;
					continue;
				}
				messageDelay = 3.5f;
				Plugin.customRPCManager.CallFocusTextRPC(messageData.message, messageData.mainCol, messageData.flashCol, messageData.time, Plugin.customRPCManagerObject);
				yield return true;
				messageData = default(messageData);
			}
		}

		private IEnumerator<bool> OutgoingItemHandler()
		{
			while (connected)
			{
				if (!outgoingItems.TryDequeue(out var networkItem))
				{
					yield return true;
					continue;
				}
				string itemName = networkItem.ItemName;
				string location = networkItem.LocationName;
				_ = networkItem.LocationId;
				string receiver = session.Players.GetPlayerName(networkItem.Player);
				Debug.Log((object)("Sent " + itemName + " at " + location + " for " + receiver));
				if ((int)networkItem.Player != session.ConnectionInfo.Slot)
				{
				}
				yield return true;
				networkItem = null;
			}
		}

		private IEnumerator<bool> IncomingItemHandler()
		{
			while (connected)
			{
				if (!incomingItems.TryPeek(out var pendingItem))
				{
					yield return true;
					continue;
				}
				ItemInfo networkItem = pendingItem.NetworkItem;
				string itemName = networkItem.ItemName;
				_ = itemName + " (" + networkItem.ItemName + ") at index " + pendingItem.index;
				(ItemInfo, int) result;
				if (APSave.GetItemReceivedIndex() > pendingItem.index)
				{
					incomingItems.TryDequeue(out result);
					Debug.Log((object)("Skipping item " + itemName + " at index " + pendingItem.index + " as it has already been processed."));
					yield return true;
					continue;
				}
				Debug.Log((object)("ItemHandler " + networkItem.ItemId));
				APSave.AddItemReceived(networkItem.ItemId);
				List<Level> nonGameLevels = new List<Level>
				{
					RunManager.instance.levelMainMenu,
					RunManager.instance.levelLobby,
					RunManager.instance.levelLobbyMenu
				};
				if (!nonGameLevels.Contains(RunManager.instance.levelCurrent))
				{
					ItemData.AddItemToInventory(networkItem.ItemId, repeatedAdditions: false);
					messageData md = new messageData("Received " + itemName, Color.green, Color.white, 3f);
					messageItems.Enqueue(md);
				}
				incomingItems.TryDequeue(out result);
				yield return true;
				pendingItem = default((ItemInfo, int));
			}
		}

		public void SendCompletion()
		{
			StatusUpdatePacket statusUpdatePacket = new StatusUpdatePacket();
			statusUpdatePacket.Status = ArchipelagoClientState.ClientGoal;
			session.Socket.SendPacket(statusUpdatePacket);
		}

		public void Release()
		{
			if (connected && sentCompletion && !sentRelease)
			{
				session.Socket.SendPacket(new SayPacket
				{
					Text = "!release"
				});
				sentRelease = true;
				Debug.Log((object)"Released remaining checks.");
			}
		}

		public void Collect()
		{
			if (connected && sentCompletion && !sentCollect)
			{
				session.Socket.SendPacket(new SayPacket
				{
					Text = "!collect"
				});
				sentCollect = true;
				Debug.Log((object)"Collected remaining items.");
			}
		}

		public void SendDeathLink()
		{
			if (connected)
			{
				deathLinkService.SendDeathLink(new DeathLink(session.Players.ActivePlayer.Name));
			}
		}
	}
	[HarmonyPatch(typeof(PlayerController), "Update")]
	internal class CheckForDisconnect
	{
		[HarmonyPostfix]
		private static void CheckDC()
		{
			if (!SemiFunc.MenuLevel() && !Plugin.connection.connected)
			{
				if (Plugin.reconnectTask == null)
				{
					Debug.Log((object)"Disconnected from AP Server");
					Plugin.reconnectTask = Plugin.connection.ClientDisconnected();
				}
				else if (Plugin.reconnectTask.Status == TaskStatus.RanToCompletion)
				{
					Plugin.reconnectTask = null;
				}
			}
		}
	}
	public class CustomRPCs : MonoBehaviour
	{
		public void CallUpdateItemNameRPC(string name, GameObject inst)
		{
			Debug.Log((object)"Calling RPC");
			PhotonView component = inst.GetComponent<PhotonView>();
			object[] array = new object[1] { name };
			component.RPC("UpdateItemNameRPC", (RpcTarget)0, array);
		}

		public void CallFocusTextRPC(string message, Color mainCol, Color flashCol, float lingerTime, GameObject inst)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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)
			if (GameManager.instance.gameMode == 1)
			{
				PhotonView component = inst.GetComponent<PhotonView>();
				object[] array = new object[4] { message, mainCol, flashCol, lingerTime };
				component.RPC("FocusTextRPC", (RpcTarget)0, array);
			}
			else
			{
				FocusTextOffline(message, mainCol, flashCol, lingerTime);
			}
		}

		[PunRPC]
		public void UpdateItemNameRPC(string name, PhotonMessageInfo info)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			Debug.Log((object)"RPC Called");
			ItemAttributes component = ((Component)info.photonView).gameObject.GetComponent<ItemAttributes>();
			FieldInfo fieldInfo = AccessTools.Field(typeof(ItemAttributes), "itemName");
			fieldInfo.SetValue(component, name.Replace("_", " "));
		}

		[PunRPC]
		public void FocusTextRPC(string message, Color mainCol, Color flashCol, float lingerTime)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			SemiFunc.UIFocusText(message, mainCol, flashCol, lingerTime);
		}

		public void FocusTextOffline(string message, Color mainCol, Color flashCol, float lingerTime)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			SemiFunc.UIFocusText(message, mainCol, flashCol, lingerTime);
		}
	}
	[HarmonyPatch(typeof(TruckScreenText), "GotoNextLevel")]
	internal class NextLevelCheckCompletePatch
	{
		[HarmonyPostfix]
		private static void CheckComplete()
		{
			Debug.Log((object)"Truck Go To Next");
			if (APSave.CheckCompletion(out var _))
			{
				Plugin.connection.SendCompletion();
			}
		}
	}
	[BepInPlugin("Automagic.ArchipelagoREPO", "Archipelago Randomizer", "0.2.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public static ArchipelagoConnection connection;

		public static Task reconnectTask = null;

		public static PlayerController _player;

		public static CustomRPCs customRPCManager;

		public static GameObject customRPCManagerObject;

		public static bool showMenu = true;

		public static string apAdress = "archipelago.gg";

		public static string apPort = "";

		public static string apPassword = "";

		public static string apSlot = "";

		public static int LastShopItemChecked = 0;

		public static List<int> ShopItemsBought = new List<int>();

		public static List<int> ShopItemsAvailable = new List<int>();

		private void Awake()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			_player = PlayerController.instance;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin RepoAP is loaded!");
			Harmony val = new Harmony("com.example.patch");
			val.PatchAll();
		}

		private void Start()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			Debug.Log((object)"In Start");
			connection = new ArchipelagoConnection();
			customRPCManagerObject = new GameObject();
			customRPCManager = customRPCManagerObject.AddComponent<CustomRPCs>();
			customRPCManagerObject.AddComponent<PhotonView>();
			Object.DontDestroyOnLoad((Object)(object)customRPCManager);
			ItemData.CreateItemDataTable();
		}

		public static ArchipelagoConnection GetConnection()
		{
			return connection;
		}

		public void CheckLocation(long locID)
		{
			connection.ActivateCheck(locID);
		}

		public void Update()
		{
			if (connection.connected)
			{
				if (connection.checkItemsReceived != null)
				{
					connection.checkItemsReceived.MoveNext();
				}
				if (connection.incomingItemHandler != null)
				{
					connection.incomingItemHandler.MoveNext();
				}
				if (connection.outgoingItemHandler != null)
				{
					connection.outgoingItemHandler.MoveNext();
				}
				if (connection.messageHandler != null)
				{
					connection.messageHandler.MoveNext();
				}
			}
		}

		public static void UpdateAPAddress(string input)
		{
			apAdress = input;
		}
	}
	internal class ItemData
	{
		private const int baseID = 75912022;

		public const int shopStockID = 20;

		public static Dictionary<long, string> itemIDToName;

		public static Dictionary<string, long> itemNameToID;

		public static void CreateItemDataTable()
		{
			itemIDToName = new Dictionary<long, string>();
			itemNameToID = new Dictionary<string, long>();
			List<string> list = new List<string>();
			List<long> list2 = new List<long>();
			list2.Add(0L);
			list.Add(LocationNames.swiftbroom);
			list2.Add(1L);
			list.Add(LocationNames.headman_manor);
			list2.Add(2L);
			list.Add(LocationNames.mcjannek);
			list2.Add(3L);
			list.Add(LocationNames.museum);
			list2.Add(10L);
			list.Add(ItemNames.upgradeHealth);
			list2.Add(11L);
			list.Add(ItemNames.upgradeStrength);
			list2.Add(12L);
			list.Add(ItemNames.upgradeRange);
			list2.Add(13L);
			list.Add(ItemNames.upgradeSprintSpeed);
			list2.Add(14L);
			list.Add(ItemNames.upgradeStamina);
			list2.Add(15L);
			list.Add(ItemNames.upgradePlayerCount);
			list2.Add(16L);
			list.Add(ItemNames.upgradeDoubleJump);
			list2.Add(17L);
			list.Add(ItemNames.upgradeTumbleLaunch);
			list2.Add(18L);
			list.Add(ItemNames.upgradeCrouchRest);
			list2.Add(19L);
			list.Add(ItemNames.upgradeTumbleWings);
			list2.Add(20L);
			list.Add(ItemNames.shopStock);
			list2.Add(21L);
			list.Add(ItemNames.small_health);
			list2.Add(22L);
			list.Add(ItemNames.medium_health);
			list2.Add(23L);
			list.Add(ItemNames.large_health);
			list2.Add(24L);
			list.Add(ItemNames.progressive_health);
			list2.Add(25L);
			list.Add(ItemNames.baseball_bat);
			list2.Add(26L);
			list.Add(ItemNames.frying_pan);
			list2.Add(27L);
			list.Add(ItemNames.sledge_hammer);
			list2.Add(28L);
			list.Add(ItemNames.sword);
			list2.Add(29L);
			list.Add(ItemNames.inflatable_hammer);
			list2.Add(30L);
			list.Add(ItemNames.prodzap);
			list2.Add(31L);
			list.Add(ItemNames.gun);
			list2.Add(32L);
			list.Add(ItemNames.shotgun);
			list2.Add(33L);
			list.Add(ItemNames.tranq_gun);
			list2.Add(34L);
			list.Add(ItemNames.pulse_pistol);
			list2.Add(35L);
			list.Add(ItemNames.photon_blaster);
			list2.Add(36L);
			list.Add(ItemNames.boltzap);
			list2.Add(37L);
			list.Add(ItemNames.cart_cannon);
			list2.Add(38L);
			list.Add(ItemNames.cart_laser);
			list2.Add(39L);
			list.Add(ItemNames.grenade);
			list2.Add(40L);
			list.Add(ItemNames.shock_grenade);
			list2.Add(41L);
			list.Add(ItemNames.stun_grenade);
			list2.Add(42L);
			list.Add(ItemNames.duct_taped_grenade);
			list2.Add(43L);
			list.Add(ItemNames.shockwave_mine);
			list2.Add(44L);
			list.Add(ItemNames.stun_mine);
			list2.Add(45L);
			list.Add(ItemNames.explosive_mine);
			list2.Add(46L);
			list.Add(ItemNames.rubber_duck);
			list2.Add(47L);
			list.Add(ItemNames.recharge_drone);
			list2.Add(48L);
			list.Add(ItemNames.indestructible_drone);
			list2.Add(49L);
			list.Add(ItemNames.roll_drone);
			list2.Add(50L);
			list.Add(ItemNames.feather_drone);
			list2.Add(51L);
			list.Add(ItemNames.zero_grav_drone);
			list2.Add(52L);
			list.Add(ItemNames.pocket_cart);
			list2.Add(53L);
			list.Add(ItemNames.cart);
			list2.Add(54L);
			list.Add(ItemNames.valuable_detector);
			list2.Add(55L);
			list.Add(ItemNames.extraction_detector);
			list2.Add(56L);
			list.Add(ItemNames.energy_crystal);
			list2.Add(57L);
			list.Add(ItemNames.zero_grav_orb);
			list2.Add(58L);
			list.Add(ItemNames.duck_bucket);
			list2.Add(59L);
			list.Add(ItemNames.phase_bridge);
			list2.Add(60L);
			list.Add(ItemNames.human_grenade);
			for (int i = 0; i < list2.Count; i++)
			{
				itemIDToName.Add(list2[i], list[i]);
				itemNameToID.Add(list[i], list2[i]);
			}
		}

		public static void AddItemToInventory(long itemId, bool repeatedAdditions)
		{
			string text = IdToItemName(RemoveBaseId(itemId));
			Debug.Log((object)("Adding Item To Inventory: " + RemoveBaseId(itemId) + " : " + text));
			if (LocationNames.all_levels.Contains(text))
			{
				APSave.AddLevelReceived(text);
			}
			else if (text == ItemNames.shopStock)
			{
				APSave.AddStockReceived();
				APSave.UpdateAvailableItems();
			}
			else if (text.Contains("Upgrade"))
			{
				StatsManager.instance.itemsPurchased[text]++;
			}
		}

		public static string IdToItemName(long itemId)
		{
			return itemIDToName[itemId];
		}

		public static long RemoveBaseId(long id)
		{
			return id - 75912022;
		}

		public static long AddBaseId(long id)
		{
			return id + 75912022;
		}
	}
	public static class ItemNames
	{
		public static string upgradePlayerCount = "Item Upgrade Map Player Count";

		public static string upgradeCrouchRest = "Item Upgrade Player Crouch Rest";

		public static string upgradeStamina = "Item Upgrade Player Energy";

		public static string upgradeDoubleJump = "Item Upgrade Player Extra Jump";

		public static string upgradeRange = "Item Upgrade Player Grab Range";

		public static string upgradeStrength = "Item Upgrade Player Grab Strength";

		public static string upgradeHealth = "Item Upgrade Player Health";

		public static string upgradeSprintSpeed = "Item Upgrade Player Sprint Speed";

		public static string upgradeTumbleLaunch = "Item Upgrade Player Tumble Launch";

		public static string upgradeTumbleWings = "Item Upgrade Player Tumble Wings";

		public static string valuableTracker = "Item Valuable Tracker";

		public static string apItem = "Item Upgrade AP Item";

		public static string shopStock = "Progressive Shop Stock";

		public static string progressive_health = "Progressive Health Pack Unlock";

		public static string small_health = "Small Health Pack";

		public static string medium_health = "Medium Health Pack";

		public static string large_health = "Large Health Pack";

		public static string baseball_bat = "Baseball Bat Unlock";

		public static string frying_pan = "Frying Pan Unlock";

		public static string sledge_hammer = "Sledge Hammer Unlock";

		public static string sword = "Sword Unlock";

		public static string inflatable_hammer = "Inflatable Hammer Unlock";

		public static string prodzap = "Prodzap Unlock";

		public static string gun = "Gun Unlock";

		public static string shotgun = "Shotgun Unlock";

		public static string tranq_gun = "Tranq Gun Unlock";

		public static string pulse_pistol = "Pulse Pistol Unlock";

		public static string photon_blaster = "Photon Blaster Unlock";

		public static string boltzap = "Boltzap Unlock";

		public static string cart_cannon = "C.A.R.T. Cannon Unlock";

		public static string cart_laser = "C.A.R.T. Laser Unlock";

		public static string grenade = "Grenade Unlock";

		public static string shock_grenade = "Shock Grenade Unlock";

		public static string stun_grenade = "Stun Grenade Unlock";

		public static string human_grenade = "Human Grenade Unlock";

		public static string duct_taped_grenade = "Duct Taped Grenade Unlock";

		public static string shockwave_mine = "Shockwave Mine Unlock";

		public static string stun_mine = "Stun Mine Unlock";

		public static string explosive_mine = "Explosive Mine Unlock";

		public static string rubber_duck = "Rubber Duck Unlock";

		public static string recharge_drone = "Recharge Drone Unlock";

		public static string indestructible_drone = "Indestructible Drone Unlock";

		public static string roll_drone = "Roll Drone Unlock";

		public static string feather_drone = "Feather Drone Unlock";

		public static string zero_grav_drone = "Zero Gravity Drone Unlock";

		public static string pocket_cart = "Pocket C.A.R.T. Unlock";

		public static string cart = "C.A.R.T. Unlock";

		public static string valuable_detector = "Valuable Detector Unlock";

		public static string extraction_detector = "Extraction Detector Unlock";

		public static string energy_crystal = "Energy Crystal Unlock";

		public static string zero_grav_orb = "Zero Gravity Orb Unlock";

		public static string duck_bucket = "Duck Bucket Unlock";

		public static string phase_bridge = "Phase Bridge Unlock";
	}
	[HarmonyPatch(typeof(RunManager), "SetRunLevel")]
	internal class LevelLockPatch
	{
		internal static int levelIndex = -1;

		[HarmonyPostfix]
		private static void SetRunLevelPre(RunManager __instance)
		{
			if (APSave.GetLevelsReceived().Count == 0 || Plugin.connection.session == null)
			{
				Debug.LogError((object)"No Levels found in Save!");
				return;
			}
			Dictionary<string, bool> levelsReceived = APSave.GetLevelsReceived();
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, bool> item in levelsReceived)
			{
				Debug.Log((object)("Player has " + item.Key));
				list.Add(item.Key);
			}
			if (levelIndex < 0)
			{
				levelIndex = Random.RandomRangeInt(0, list.Count);
			}
			else
			{
				levelIndex = (levelIndex + 1) % list.Count;
			}
			string text = list[levelIndex];
			Level levelCurrent = null;
			Debug.Log((object)("Setting level to " + text));
			foreach (Level level in __instance.levels)
			{
				if (text.Contains(level.NarrativeName))
				{
					levelCurrent = level;
				}
				else
				{
					Debug.Log((object)(level.NarrativeName + " != " + text));
				}
			}
			__instance.levelCurrent = levelCurrent;
			Debug.Log((object)("Returning " + ((Object)__instance.levelCurrent).name));
		}
	}
	[HarmonyPatch(typeof(PunManager), "Start")]
	internal class DisplayCompletionStatusPatch
	{
		private static void Postfix()
		{
			if (!((Object)RunManager.instance.levelCurrent).name.Contains("Menu"))
			{
				string status;
				bool flag = APSave.CheckCompletion(out status);
				HandleAPTruckScreenMessages.TruckScreenChatPatch.AddMessage("AP", status);
			}
		}
	}
	[HarmonyPatch(typeof(EnemyParent))]
	internal class EnemyDespawnPatch
	{
		[HarmonyPatch("Despawn")]
		[HarmonyPostfix]
		private static void OrbNaming(ref string ___enemyName, ref Enemy ___Enemy)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			FieldInfo fieldInfo = AccessTools.Field(typeof(Enemy), "HasHealth");
			bool flag = (bool)fieldInfo.GetValue(___Enemy);
			FieldInfo fieldInfo2 = AccessTools.Field(typeof(Enemy), "Health");
			EnemyHealth val = (EnemyHealth)fieldInfo2.GetValue(___Enemy);
			FieldInfo fieldInfo3 = AccessTools.Field(typeof(EnemyHealth), "healthCurrent");
			int num = (int)fieldInfo3.GetValue(val);
			if (!flag || !val.spawnValuable || num > 0)
			{
				return;
			}
			EnemyValuable[] array = (EnemyValuable[])(object)Object.FindObjectsByType(typeof(EnemyValuable), (FindObjectsSortMode)0);
			EnemyValuable[] array2 = array;
			foreach (EnemyValuable val2 in array2)
			{
				if (((Object)val2).name.Contains("Enemy Valuable"))
				{
					((Object)val2).name = ___enemyName + " Soul";
				}
			}
		}
	}
	internal class ExtractSendCheck
	{
		private static void CheckValuable(GameObject valuableObject)
		{
			Debug.Log((object)("Extracting " + ((Object)valuableObject).name));
			if (!Object.op_Implicit((Object)(object)valuableObject) || !Object.op_Implicit((Object)(object)valuableObject.GetComponent<PhysGrabObject>()))
			{
				return;
			}
			if (((Object)valuableObject).name.Contains("Pelly"))
			{
				Plugin.connection.ActivateCheck(LocationData.PellyNameToID(((Object)valuableObject).name + ((Object)RunManager.instance.levelCurrent).name));
				APSave.AddPellyGathered(((Object)RunManager.instance.levelCurrent).name + ((Object)valuableObject).name);
			}
			else if (((Object)valuableObject).name.Contains("Soul"))
			{
				long num = LocationData.MonsterSoulNameToID(((Object)valuableObject).name);
				if (LocationData.RemoveBaseId(num) != 0)
				{
					Plugin.connection.ActivateCheck(num);
					APSave.AddMonsterSoulGathered(((Object)valuableObject).name);
				}
			}
			else if (((Object)valuableObject).name.Contains("Valuable"))
			{
				long num2 = LocationData.ValuableNameToID(((Object)valuableObject).name);
				if (LocationData.RemoveBaseId(num2) != 0)
				{
					Plugin.connection.ActivateCheck(num2);
					APSave.AddValuableGathered(((Object)valuableObject).name);
				}
			}
		}

		public static void Send(FieldInfo totalHaulField)
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer() || RoundDirector.instance.dollarHaulList.Count <= 0)
			{
				return;
			}
			foreach (GameObject dollarHaul in RoundDirector.instance.dollarHaulList)
			{
				CheckValuable(dollarHaul);
			}
		}

		public static void SendFirst(FieldInfo totalHaulField)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer() && RoundDirector.instance.dollarHaulList.Count > 0)
			{
				CheckValuable(RoundDirector.instance.dollarHaulList[0]);
			}
		}
	}
	[HarmonyPatch(typeof(ExtractionPoint))]
	internal class ExtractionSendCheckPatch
	{
		private static FieldInfo field = AccessTools.Field(typeof(RoundDirector), "totalHaul");

		private static int totalHaul;

		[HarmonyPrefix]
		[HarmonyPatch("DestroyAllPhysObjectsInHaulList")]
		private static void ExtractAllPatch()
		{
			if (Plugin.connection != null)
			{
				ExtractSendCheck.Send(field);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("DestroyTheFirstPhysObjectsInHaulList")]
		private static void ExtractFirstPatch()
		{
			if (Plugin.connection != null)
			{
				ExtractSendCheck.SendFirst(field);
			}
		}
	}
	internal static class LocationData
	{
		private const int baseID = 75912022;

		public const int pellyOffset = 100;

		public const int valuableOffset = 200;

		public const int monsterOffset = 500;

		private static Dictionary<long, string> idToName;

		private static Dictionary<string, long> nameToId;

		private static long[] ids;

		private static long[] names;

		public static void CreateLocationTables()
		{
			for (int i = 0; i < 100; i++)
			{
			}
		}

		public static string GetBaseName(string name)
		{
			name = name.Replace("Valuable ", "").Replace("(Clone)", "");
			foreach (string item in LocationNames.all_levels_short)
			{
				name = name.Replace(item + " ", "");
			}
			return name;
		}

		public static long MonsterSoulNameToID(string name)
		{
			long num = 0L;
			name = GetBaseName(name);
			num = LocationNames.all_monster_souls.IndexOf(name);
			if (num == -1)
			{
				Debug.Log((object)(name + "'s id not found"));
				num = 0L;
			}
			else
			{
				num += 500;
			}
			return 75912022 + num;
		}

		public static string MonsterSoulIDToName(long id)
		{
			id -= 75912022;
			id -= 500;
			return LocationNames.all_monster_souls[(int)id];
		}

		public static long ValuableNameToID(string name)
		{
			long num = 0L;
			name = GetBaseName(name);
			num = LocationNames.all_valuables.IndexOf(name);
			if (num == -1)
			{
				Debug.Log((object)(name + "'s id not found"));
				num = 0L;
			}
			else
			{
				num += 200;
			}
			return 75912022 + num;
		}

		public static string ValuableIDToName(long id)
		{
			id -= 75912022;
			id -= 200;
			return LocationNames.all_valuables[(int)id];
		}

		public static long PellyNameToID(string name)
		{
			int num = 100;
			int num2 = 1;
			foreach (string item in LocationNames.all_levels_short)
			{
				if (name.Contains(item))
				{
					num += num2;
					break;
				}
				num2 += 3;
			}
			num2 = 0;
			foreach (string all_pelly in LocationNames.all_pellys)
			{
				if (name.Contains(all_pelly))
				{
					num += num2;
					break;
				}
				num2++;
			}
			return 75912022 + num;
		}

		public static long ShopItemToID(string name)
		{
			if (name.Any(char.IsDigit))
			{
				name = new string(name.Where((char x) => char.IsDigit(x)).ToArray());
				int num = int.Parse(name);
				return 75912022 + num;
			}
			return 0L;
		}

		public static long RemoveBaseId(long id)
		{
			return id - 75912022;
		}

		public static long AddBaseId(long id)
		{
			return id + 75912022;
		}
	}
	internal class LocationNames
	{
		public static string standard_pelly = "Standard";

		public static string glass_pelly = "Glass";

		public static string gold_pelly = "Gold";

		public static string upgrade_pur = "Upgrade Purchase";

		public static string swiftbroom = "Swiftbroom Academy ";

		public static string headman_manor = "Headman Manor ";

		public static string mcjannek = "McJannek Station ";

		public static string museum = "Museum of Human Art ";

		public const string diamond = "Diamond";

		public const string ring = "Emerald Bracelet";

		public const string goblet = "Goblet";

		public const string ocarina = "Ocarina";

		public const string pocket_watch = "Pocket Watch";

		public const string uranium_mug = "Uranium Mug";

		public const string crown = "Crown";

		public const string doll = "Doll";

		public const string frog_toy = "Frog";

		public const string gem_box = "Gem Box";

		public const string globe = "Globe";

		public const string money = "Money";

		public const string monkey = "Toy Monkey";

		public const string uranium_plate = "Uranium Plate";

		public const string small_vase = "Vase Small";

		public const string champagne = "Bottle";

		public const string clown_doll = "Clown";

		public const string radio = "Radio";

		public const string ship_in_a_bottle = "Ship in a bottle";

		public const string trophy = "Trophy";

		public const string vase = "Vase";

		public const string tv = "Television";

		public const string large_vase = "Vase Big";

		public const string animal_crate = "Animal Crate";

		public const string bonsai = "Bonsai";

		public const string music_box = "Music Box";

		public const string gramophone = "Gramophone";

		public const string rhino = "Diamond Display";

		public const string scream_doll = "Scream Doll";

		public const string grand_piano = "Piano";

		public const string harp = "Harp";

		public const string painting = "Painting";

		public const string grandfather_clock = "Grandfather Clock";

		public const string dinosaur_skeleton = "Dinosaur";

		public const string golden_statue = "Golden Statue";

		public const string desktop_computer = "Computer";

		public const string fan = "Fan";

		public const string explosive_barrel = "Barrel";

		public const string sample = "Sample";

		public const string big_sample = "Big Sample";

		public const string flamethrower = "Flamethrower";

		public const string science_station = "Science Station";

		public const string server = "Server Rack";

		public const string printer = "3D Printer";

		public const string hdd = "HDD";

		public const string ice_saw = "Ice Saw";

		public const string laptop = "Laptop";

		public const string propane = "Propane Tank";

		public const string sample_pack = "Sample Six Pack";

		public const string guitar = "Guitar";

		public const string sample_cooler = "Sample Cooler";

		public const string leg_ice = "Creature Leg";

		public const string skeleton_ice = "Ice Block";

		public const string chomp_book = "Chomp Book";

		public const string love_potion = "Love Potion";

		public const string cube_of_knowledge = "Cube of Knowledge";

		public const string staff = "Dumgolfs Staff";

		public const string large_sword = "Sword";

		public const string broom = "Broom";

		public const string hourglass = "Time Glass";

		public const string master_potion = "Master Potion";

		public const string goblin_head = "Goblin Head";

		public const string griffin = "Griffin Statue";

		public const string power_crystal = "Power Crystal";

		public const string egg = "Egg";

		public const string car = "Car";

		public const string banana_bow = "Banana Bow";

		public const string boombox = "Boombox";

		public const string cool_brain = "Cool brain";

		public const string cubic_tower = "Cubic Tower";

		public const string fish = "Fish";

		public const string silverfish = "SilverFish";

		public const string goldfish = "GoldFish";

		public const string golden_swirl = "Golden Swirl";

		public const string pacifier = "Pacifier";

		public const string baby_head = "Baby Head";

		public const string monkeybox = "MonkeyBox";

		public const string flesh_blob = "Flesh Blob";

		public const string tooth = "Tooth";

		public const string goldtooth = "GoldTooth";

		public const string toast = "Toast";

		public const string horse = "Horse";

		public const string blender = "Blender";

		public const string mug_deluxe = "Uranium Mug Deluxe";

		public const string gumball = "Gumball";

		public const string traffic_light = "Traffic Light";

		public const string milk = "Milk";

		public const string handface = "Handface";

		public const string gem_burger = "Gem Burger";

		public const string wire_figure = "Wire Figure";

		public const string rubendoll = "RubenDoll";

		public const string duck_man = "duck man";

		public const string cocktail = "Cocktail";

		public const string cube_ball = "Cube ball";

		public const string ladybug = "ladybug";

		public const string cubic_sculpture = "Cubic Sculpture";

		public const string pimpleguy = "PimpleGuy";

		public const string plane = "Plane";

		public const string teeth_bot = "Teeth Bot";

		public const string worm = "Worm";

		public const string vinyl = "Vinyl";

		public const string tray = "Tray";

		public const string tall_guy = "Tall Guy";

		public static readonly ReadOnlyCollection<string> all_pellys = new ReadOnlyCollection<string>(new List<string> { standard_pelly, glass_pelly, gold_pelly });

		public static readonly ReadOnlyCollection<string> all_levels_short = new ReadOnlyCollection<string>(new List<string> { "Wizard", "Manor", "Arctic", "Museum" });

		public static readonly ReadOnlyCollection<string> all_levels = new ReadOnlyCollection<string>(new List<string> { swiftbroom, headman_manor, mcjannek, museum });

		public static readonly ReadOnlyCollection<string> all_valuables = new ReadOnlyCollection<string>(new List<string>
		{
			"Diamond", "Emerald Bracelet", "Goblet", "Ocarina", "Pocket Watch", "Uranium Mug", "Crown", "Doll", "Frog", "Gem Box",
			"Globe", "Money", "Toy Monkey", "Uranium Plate", "Vase Small", "Bottle", "Clown", "Trophy", "Vase", "Vase Big",
			"Animal Crate", "Bonsai", "Music Box", "Gramophone", "Diamond Display", "Scream Doll", "Piano", "Harp", "Painting", "Grandfather Clock",
			"Dinosaur", "Golden Statue", "Television", "Radio", "Ship in a bottle", "Computer", "Fan", "Barrel", "Sample", "Big Sample",
			"Flamethrower", "Science Station", "Server Rack", "3D Printer", "HDD", "Ice Saw", "Laptop", "Propane Tank", "Sample Six Pack", "Guitar",
			"Sample Cooler", "Creature Leg", "Ice Block", "Chomp Book", "Love Potion", "Cube of Knowledge", "Dumgolfs Staff", "Sword", "Broom", "Time Glass",
			"Master Potion", "Goblin Head", "Griffin Statue", "Power Crystal", "Egg", "Car", "Banana Bow", "Boombox", "Cool brain", "Cubic Tower",
			"Fish", "SilverFish", "GoldFish", "Golden Swirl", "Pacifier", "Baby Head", "MonkeyBox", "Flesh Blob", "Tooth", "GoldTooth",
			"Toast", "Horse", "Blender", "Uranium Mug Deluxe", "Gumball", "Traffic Light", "Milk", "Handface", "Gem Burger", "Wire Figure",
			"RubenDoll", "duck man", "Cocktail", "Cube ball", "ladybug", "Cubic Sculpture", "PimpleGuy", "Plane", "Teeth Bot", "Worm",
			"Vinyl", "Tray", "Tall Guy"
		});

		public const string animal_soul = "Animal Soul";

		public const string duck_soul = "Apex Predator Soul";

		public const string bowtie_soul = "Bowtie Soul";

		public const string chef_soul = "Chef Soul";

		public const string clown_soul = "Clown Soul";

		public const string headman_soul = "Headman Soul";

		public const string hidden_soul = "Hidden Soul";

		public const string huntsman_soul = "Huntsman Soul";

		public const string mentalist_soul = "Mentalist Soul";

		public const string reaper_soul = "Reaper Soul";

		public const string robe_soul = "Robe Soul";

		public const string rugrat_soul = "Rugrat Soul";

		public const string shadow_child_soul = "Shadow Child Soul";

		public const string spewer_soul = "Spewer Soul";

		public const string trudge_soul = "Trudge Soul";

		public const string upscream_soul = "Upscream Soul";

		public static readonly ReadOnlyCollection<string> all_monster_souls = new ReadOnlyCollection<string>(new List<string>
		{
			"Animal Soul", "Apex Predator Soul", "Bowtie Soul", "Chef Soul", "Clown Soul", "Headman Soul", "Hidden Soul", "Huntsman Soul", "Mentalist Soul", "Reaper Soul",
			"Robe Soul", "Rugrat Soul", "Shadow Child Soul", "Spewer Soul", "Trudge Soul", "Upscream Soul"
		});
	}
	[HarmonyPatch(typeof(ValuableDirector), "Start")]
	internal class PellySpawingPatch
	{
		[HarmonyPrefix]
		private static void RemovePellysFromList(ValuableDirector __instance)
		{
			if (Plugin.connection.session == null || APSave.saveData.pellySpawning)
			{
				return;
			}
			Debug.Log((object)"InValuableDirector");
			FieldInfo fieldInfo = AccessTools.Field(typeof(ValuableDirector), "mediumValuables");
			List<GameObject> list = (List<GameObject>)fieldInfo.GetValue(__instance);
			foreach (LevelValuables valuablePreset in LevelGenerator.Instance.Level.ValuablePresets)
			{
				foreach (GameObject pelly in valuablePreset.medium.Where((GameObject x) => ((Object)x).name.Contains("Pelly")).ToList())
				{
					Debug.Log((object)("Pelly Found: " + ((Object)pelly).name));
					if (((IEnumerable<JToken>)APSave.saveData.pellysRequired).All((JToken x) => !((Object)pelly).name.Contains(((object)x).ToString())))
					{
						Debug.Log((object)("Removing: " + ((Object)pelly).name));
						valuablePreset.medium.Remove(pelly);
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabObject))]
	internal class PhysGrabObjectPatch
	{
		[HarmonyPatch("GrabStarted")]
		[HarmonyPostfix]
		private static void OrbInfoTextEnabler(PhysGrabObject __instance)
		{
			string name = ((Object)((Component)__instance).gameObject).name;
			bool flag = name.Contains("Soul");
			bool flag2 = name.Contains("Valuable");
			bool flag3 = name.Contains("Pelly");
			bool flag4 = name.Contains("Surplus");
			bool flag5 = name.Contains("Peeper");
			if (flag4 || !(flag || flag2 || flag3))
			{
				return;
			}
			string text = "";
			if (Plugin.connection.session != null)
			{
				long id = -1L;
				bool flag6 = false;
				bool flag7 = false;
				if (!flag5 && flag)
				{
					id = LocationData.MonsterSoulNameToID(name);
					flag6 = APSave.WasMonsterSoulGathered(name);
					flag7 = APSave.saveData.monsterHunt;
				}
				else if (flag3)
				{
					id = LocationData.PellyNameToID(name);
					flag6 = APSave.WasPellyGathered(name, ((Object)RunManager.instance.levelCurrent).name);
					flag7 = APSave.IsPellyRequired(name);
				}
				else if (flag2)
				{
					id = LocationData.ValuableNameToID(name);
					flag6 = APSave.WasValuableGathered(name);
					flag7 = APSave.saveData.valuableHunt;
				}
				ItemInfo itemInfo = (flag5 ? null : APSave.GetScoutedLocation(id));
				if (flag7 && flag6)
				{
					text = "<br><color=#67a9cf>extracted";
				}
				else if (flag7 && itemInfo == null)
				{
					text = "<br><color=#ef8a62>not extracted";
				}
				else if (!flag6 && itemInfo != null)
				{
					try
					{
						text = string.Format("<br><color={0}>{1}'s {2}", "#ef8a62", itemInfo.Player, itemInfo.ItemName);
					}
					catch (Exception ex)
					{
						Debug.Log((object)("OrbInfoTextEnabler: " + ex.Message));
					}
				}
			}
			name = LocationData.GetBaseName(name);
			SemiFunc.UIItemInfoText((ItemAttributes)null, name + text);
		}
	}
	[HarmonyPatch(typeof(ExtractionPoint), "DestroyAllPhysObjectsInShoppingList")]
	internal class ShopSendCheckPatch
	{
		private static FieldInfo field = AccessTools.Field(typeof(ShopManager), "shoppingList");

		private static List<ItemAttributes> shoppingList;

		private static FieldInfo field2 = AccessTools.Field(typeof(ItemAttributes), "value");

		private static int value;

		[HarmonyPrefix]
		private static bool ShopCheckPatch(ExtractionPoint __instance)
		{
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Invalid comparison between Unknown and I4
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Invalid comparison between Unknown and I4
			shoppingList = (List<ItemAttributes>)field.GetValue(ShopManager.instance);
			Debug.Log((object)"Connected in shop check");
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				if (Plugin.connection == null)
				{
					Debug.Log((object)"Connection Null");
					return true;
				}
				foreach (PlayerAvatar player in GameDirector.instance.PlayerList)
				{
					player.playerDeathHead.Revive();
				}
				List<ItemAttributes> list = new List<ItemAttributes>();
				foreach (ItemAttributes shopping in shoppingList)
				{
					value = (int)field2.GetValue(shopping);
					if (!Object.op_Implicit((Object)(object)shopping) || !Object.op_Implicit((Object)(object)((Component)shopping).GetComponent<PhysGrabObject>()) || SemiFunc.StatGetRunCurrency() - value < 0)
					{
						continue;
					}
					SemiFunc.StatSetRunCurrency(SemiFunc.StatGetRunCurrency() - value);
					if (shopping.item.itemAssetName == ItemNames.apItem)
					{
						Debug.Log((object)("AP ITEM PURCHASED " + ((Object)shopping).name));
						long num = LocationData.ShopItemToID(((Object)shopping).name);
						if (num != 0)
						{
							Plugin.connection.ActivateCheck(num);
						}
					}
					else
					{
						Debug.Log((object)("Not AP Item\n" + shopping.item.itemAssetName + " != " + ItemNames.apItem));
						StatsManager.instance.ItemPurchase(shopping.item.itemAssetName);
					}
					if ((int)shopping.item.itemType == 3 && shopping.item.itemAssetName != ItemNames.apItem)
					{
						StatsManager.instance.AddItemsUpgradesPurchased(shopping.item.itemAssetName);
					}
					if ((int)shopping.item.itemType == 5)
					{
						StatsManager.instance.runStats["chargingStationChargeTotal"] += 17;
						if (StatsManager.instance.runStats["chargingStationChargeTotal"] > 100)
						{
							StatsManager.instance.runStats["chargingStationChargeTotal"] = 100;
						}
					}
					((Component)shopping).GetComponent<PhysGrabObject>().DestroyPhysGrabObject();
					list.Add(shopping);
				}
				foreach (ItemAttributes item in list)
				{
					List<ItemAttributes> list2 = (List<ItemAttributes>)field.GetValue(ShopManager.instance);
					list2.Remove(item);
					field.SetValue(ShopManager.instance, list2);
				}
				SemiFunc.ShopUpdateCost();
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(PunManager), "Start")]
	internal class ItemNumberTracker
	{
		[HarmonyPostfix]
		private static void SetNumber()
		{
			if (!((Object)RunManager.instance.levelCurrent).name.Contains("Menu"))
			{
				Plugin.LastShopItemChecked = 0;
				APSave.UpdateAvailableItems();
			}
		}
	}
	[HarmonyPatch(typeof(PunManager), "SpawnShopItem")]
	internal class SpawnShopItemPatch
	{
		[HarmonyPrefix]
		private static bool ReplaceItemPatch(ref bool __result, ref ItemVolume itemVolume, ref List<Item> itemList, ref int spawnCount, bool isSecret = false)
		{
			//IL_1051: Unknown result type (might be due to invalid IL or missing references)
			//IL_1058: Unknown result type (might be due to invalid IL or missing references)
			//IL_1095: Unknown result type (might be due to invalid IL or missing references)
			//IL_10af: Unknown result type (might be due to invalid IL or missing references)
			//IL_10b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_1182: Unknown result type (might be due to invalid IL or missing references)
			//IL_1187: Unknown result type (might be due to invalid IL or missing references)
			//IL_1101: Unknown result type (might be due to invalid IL or missing references)
			//IL_1106: Unknown result type (might be due to invalid IL or missing references)
			FieldInfo fieldInfo = AccessTools.Field(typeof(ItemAttributes), "itemName");
			int num = itemList.Count - 1;
			while (num >= 0)
			{
				Item val;
				if (itemList[num].itemName.Contains("Upgrade") && !((Object)itemList[num]).name.Contains("Counted") && Plugin.ShopItemsAvailable.Count > 0)
				{
					Debug.Log((object)("Replacing  " + itemList[num].itemName));
					val = StatsManager.instance.itemDictionary[ItemNames.apItem];
					if (val.itemVolume == itemVolume.itemVolume)
					{
						((Component)ShopManager.instance.itemRotateHelper).transform.parent = ((Component)itemVolume).transform;
						((Component)ShopManager.instance.itemRotateHelper).transform.localRotation = val.spawnRotationOffset;
						Quaternion rotation = ((Component)ShopManager.instance.itemRotateHelper).transform.rotation;
						((Component)ShopManager.instance.itemRotateHelper).transform.parent = ((Component)ShopManager.instance).transform;
						string text = "Items/" + ((Object)val.prefab).name;
						if (SemiFunc.IsMultiplayer())
						{
							GameObject val2 = PhotonNetwork.InstantiateRoomObject(text, ((Component)itemVolume).transform.position, rotation, (byte)0, (object[])null);
							Plugin.LastShopItemChecked++;
							Random random = new Random();
							int index = random.Next(Plugin.ShopItemsAvailable.Count);
							int num2 = Plugin.ShopItemsAvailable[index];
							((Object)val2).name = ((Object)val2).name + "_Counted_" + num2;
							Plugin.ShopItemsAvailable.RemoveAt(index);
						}
						else
						{
							GameObject val3 = Object.Instantiate<GameObject>(val.prefab, ((Component)itemVolume).transform.position, rotation);
							Plugin.LastShopItemChecked++;
							Random random2 = new Random();
							int index2 = random2.Next(Plugin.ShopItemsAvailable.Count);
							int num3 = Plugin.ShopItemsAvailable[index2];
							((Object)val3).name = ((Object)val3).name + "_Counted_" + num3;
							Plugin.ShopItemsAvailable.RemoveAt(index2);
						}
						itemList.RemoveAt(num);
						if (!isSecret)
						{
							spawnCount++;
						}
						__result = true;
						return false;
					}
					num--;
					continue;
				}
				if (((Object)itemList[num]).name.Contains("Item Cart Cannon") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.cart_cannon])))
				{
					Debug.Log((object)(ItemNames.cart_cannon + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Cart Laser") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.cart_laser])))
				{
					Debug.Log((object)(ItemNames.cart_laser + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Cart Medium") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.cart])))
				{
					Debug.Log((object)(ItemNames.cart + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Cart Small") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.pocket_cart])))
				{
					Debug.Log((object)(ItemNames.pocket_cart + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Drone Battery") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.recharge_drone])))
				{
					Debug.Log((object)(ItemNames.recharge_drone + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Drone Feather") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.feather_drone])))
				{
					Debug.Log((object)(ItemNames.feather_drone + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Drone Indestructible") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.indestructible_drone])))
				{
					Debug.Log((object)(ItemNames.indestructible_drone + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Drone Torque") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.roll_drone])))
				{
					Debug.Log((object)(ItemNames.roll_drone + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Drone Zero Gravity") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.zero_grav_drone])))
				{
					Debug.Log((object)(ItemNames.zero_grav_drone + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Duck Bucket") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.duck_bucket])))
				{
					Debug.Log((object)(ItemNames.duck_bucket + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Extraction Tracker") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.extraction_detector])))
				{
					Debug.Log((object)(ItemNames.extraction_detector + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Grenade Duct Taped") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.duct_taped_grenade])))
				{
					Debug.Log((object)(ItemNames.duct_taped_grenade + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Grenade Explosive") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.grenade])))
				{
					Debug.Log((object)(ItemNames.grenade + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Grenade Human") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.human_grenade])))
				{
					Debug.Log((object)(ItemNames.human_grenade + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Grenade Shockwave") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.shock_grenade])))
				{
					Debug.Log((object)(ItemNames.shock_grenade + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Grenade Stun") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.stun_grenade])))
				{
					Debug.Log((object)(ItemNames.stun_grenade + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Gun Handgun") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.gun])))
				{
					Debug.Log((object)(ItemNames.gun + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Gun Laser") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.photon_blaster])))
				{
					Debug.Log((object)(ItemNames.photon_blaster + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Gun Shockwave") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.pulse_pistol])))
				{
					Debug.Log((object)(ItemNames.pulse_pistol + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Gun Shotgun") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.shotgun])))
				{
					Debug.Log((object)(ItemNames.shotgun + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Gun Stun") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.boltzap])))
				{
					Debug.Log((object)(ItemNames.boltzap + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Gun Tranq") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.tranq_gun])))
				{
					Debug.Log((object)(ItemNames.tranq_gun + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Health Pack Large") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.progressive_health]), 3))
				{
					Debug.Log((object)("3 " + ItemNames.progressive_health + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Health Pack Medium") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.progressive_health]), 2))
				{
					Debug.Log((object)("2 " + ItemNames.progressive_health + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Health Pack Small") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.progressive_health])))
				{
					Debug.Log((object)("1 " + ItemNames.progressive_health + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Melee Baseball Bat") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.baseball_bat])))
				{
					Debug.Log((object)(ItemNames.baseball_bat + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Melee Frying Pan") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.frying_pan])))
				{
					Debug.Log((object)(ItemNames.frying_pan + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Melee Inflatable Hammer") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.inflatable_hammer])))
				{
					Debug.Log((object)(ItemNames.inflatable_hammer + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Melee Sledge Hammer") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.sledge_hammer])))
				{
					Debug.Log((object)(ItemNames.sledge_hammer + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Melee Stun Baton") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.prodzap])))
				{
					Debug.Log((object)(ItemNames.prodzap + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Melee Sword") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.sword])))
				{
					Debug.Log((object)(ItemNames.sword + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Mine Explosive") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.explosive_mine])))
				{
					Debug.Log((object)(ItemNames.explosive_mine + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Mine Shockwave") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.shockwave_mine])))
				{
					Debug.Log((object)(ItemNames.shockwave_mine + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Mine Stun") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.stun_mine])))
				{
					Debug.Log((object)(ItemNames.stun_mine + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Orb Zero Gravity") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.zero_grav_orb])))
				{
					Debug.Log((object)(ItemNames.zero_grav_orb + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Phase Bridge") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.phase_bridge])))
				{
					Debug.Log((object)(ItemNames.phase_bridge + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Power Crystal") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.energy_crystal])))
				{
					Debug.Log((object)(ItemNames.energy_crystal + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Rubber Duck") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.rubber_duck])))
				{
					Debug.Log((object)(ItemNames.rubber_duck + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				if (((Object)itemList[num]).name.Contains("Item Valuable Tracker") && !APSave.IsItemReceived(ItemData.AddBaseId(ItemData.itemNameToID[ItemNames.valuable_detector])))
				{
					Debug.Log((object)(ItemNames.valuable_detector + " Not Unlocked"));
					itemList.RemoveAt(num);
					return false;
				}
				val = itemList[num];
				return true;
			}
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(ItemAttributes), "Start")]
	internal class APItemNamePatch
	{
		[HarmonyPostfix]
		private static void NamePatch(ref string ___itemName, ItemAttributes __instance)
		{
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Expected O, but got Unknown
			if (!___itemName.Contains("Archipelago"))
			{
				return;
			}
			((Component)__instance).gameObject.AddComponent<CustomRPCs>();
			if (!SemiFunc.IsMasterClientOrSingleplayer() || !((Object)RunManager.instance.levelCurrent).name.Contains("Shop"))
			{
				return;
			}
			string text = ((Object)__instance).name;
			if (text.Any(char.IsDigit))
			{
				text = new string(text.Where((char x) => char.IsDigit(x)).ToArray());
			}
			___itemName = ___itemName + " " + text;
			ItemInfo scoutedShopItem = APSave.GetScoutedShopItem(LocationData.AddBaseId(long.Parse(text)));
			___itemName = $"{scoutedShopItem.Player}'s {scoutedShopItem.ItemName}";
			if (GameManager.instance.gameMode == 1)
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(ItemUpgrade), "photonView");
				PhotonView val = (PhotonView)fieldInfo.GetValue(((Component)__instance).GetComponent<ItemUpgrade>());
				Plugin.customRPCManager.CallUpdateItemNameRPC(___itemName, ((Component)__instance).gameObject);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerController), "Update")]
	internal class DebugKeys
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			if (Input.GetKeyDown((KeyCode)277))
			{
				Plugin.showMenu = !Plugin.showMenu;
				Debug.Log((object)"Toggle Menu");
			}
			if (Input.GetKeyDown((KeyCode)282))
			{
				Debug.Log((object)"F1 Pressed");
				RunManager.instance.ChangeLevel(true, false, (ChangeLevelType)5);
			}
			if (Input.GetKeyDown((KeyCode)283))
			{
				Debug.Log((object)"F2 Pressed");
				SemiFunc.StatSetRunCurrency(100000);
			}
			if (Input.GetKeyDown((KeyCode)284))
			{
				Debug.Log((object)"F3 Pressed");
				foreach (string key in StatsManager.instance.itemDictionary.Keys)
				{
					Debug.Log((object)(key ?? ""));
				}
			}
			if (Input.GetKeyDown((KeyCode)285))
			{
				Debug.Log((object)"F4 Pressed");
				StatsManager.instance.itemsPurchased[ItemNames.upgradeStrength] = 15;
			}
			if (Input.GetKeyDown((KeyCode)286))
			{
				Debug.Log((object)"Try Connect");
				Plugin.connection.TryConnect(Plugin.apAdress, int.Parse(Plugin.apPort), Plugin.apPassword, Plugin.apSlot);
			}
			if (Input.GetKeyDown((KeyCode)287))
			{
				string text = "-- Completetion Data --";
				text += $"\nLevel Quota: {APSave.saveData.levelQuota}";
				text += "\nPellys Required: ";
				foreach (JToken item in APSave.saveData.pellysRequired)
				{
					text = text + "\n- " + ((object)item).ToString();
				}
				text += "\n\nPellys Gathered: ";
				foreach (string item2 in APSave.saveData.pellysGathered)
				{
					text = text + "\n- " + item2;
				}
				text += "\n\nValuables Gathered: ";
				foreach (string item3 in APSave.saveData.valuablesGathered)
				{
					text = text + "\n- " + item3;
				}
				text += "\n\nValuables Missing: ";
				foreach (string all_valuable in LocationNames.all_valuables)
				{
					if (!APSave.saveData.valuablesGathered.Contains(all_valuable))
					{
						text = text + "\n- Missing " + all_valuable;
					}
				}
				text += "\n\nMonster Souls Missing: ";
				foreach (string all_monster_soul in LocationNames.all_monster_souls)
				{
					if (!APSave.saveData.monsterSoulsGathered.Contains(all_monster_soul))
					{
						text = text + "\n- Missing " + all_monster_soul;
					}
				}
				text += "\n\nMonster Souls Gathered: ";
				foreach (string item4 in APSave.saveData.monsterSoulsGathered)
				{
					text = text + "\n- " + item4;
				}
				Debug.Log((object)text);
			}
			if (Input.GetKeyDown((KeyCode)289))
			{
				Debug.Log((object)((Object)RunManager.instance.levelCurrent).name);
			}
			if (Input.GetKeyDown((KeyCode)290))
			{
				Debug.Log((object)APSave.saveData.shopStockReceived);
			}
			if (Input.GetKeyDown((KeyCode)291))
			{
				string text2 = "--- Valuable Weights ---";
				foreach (LevelValuables valuablePreset in LevelGenerator.Instance.Level.ValuablePresets)
				{
					List<GameObject> tiny = valuablePreset.tiny;
					tiny.AddRange(valuablePreset.small);
					tiny.AddRange(valuablePreset.medium);
					tiny.AddRange(valuablePreset.big);
					tiny.AddRange(valuablePreset.wide);
					tiny.AddRange(valuablePreset.tall);
					tiny.AddRange(valuablePreset.veryTall);
					foreach (GameObject item5 in tiny)
					{
						text2 += $"\n{((Object)item5).name} - {((Object)LevelGenerator.Instance.Level).name}: {item5.GetComponent<ValuableObject>().physAttributePreset}".Replace("PhysAttribute", "").Replace("()", "");
					}
				}
				Debug.Log((object)text2);
			}
			if (!Input.GetKeyDown((KeyCode)292))
			{
				return;
			}
			Dictionary<long, int> itemsReceived = APSave.GetItemsReceived();
			foreach (KeyValuePair<long, int> item6 in itemsReceived)
			{
				Debug.Log((object)ItemData.itemIDToName[ItemData.RemoveBaseId(item6.Key)]);
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "RepoAP";

		public const string PLUGIN_NAME = "Archipelago Randomizer";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace RepoAP.Items
{
	[HarmonyPatch(typeof(StatsManager), "RunStartStats")]
	internal class StartRunWithAPItemsPatch
	{
		[HarmonyPostfix]
		private static void RunStartStatsPatch()
		{
			if (Plugin.connection.session == null)
			{
				return;
			}
			Debug.Log((object)"Start Run With AP Items");
			Dictionary<long, int> itemsReceived = APSave.GetItemsReceived();
			foreach (KeyValuePair<long, int> item in itemsReceived)
			{
				for (int i = 0; i < item.Value; i++)
				{
					ItemData.AddItemToInventory(item.Key, repeatedAdditions: true);
				}
			}
		}
	}
}
namespace RepoAP.Core
{
	public class HandleAPTruckScreenMessages
	{
		[HarmonyPatch(typeof(TruckScreenText), "MessageSendCustomRPC")]
		public class OverridePlayerNameCheckPatch
		{
			private static string nicknameCacheman = "";

			private static string customFormattedNickname = "";

			private static void Prefix(TruckScreenText __instance)
			{
				if (customFormattedNickname != string.Empty)
				{
					FieldInfo fieldInfo = AccessTools.Field(typeof(TruckScreenText), "nicknameTaxman");
					nicknameCacheman = (string)fieldInfo.GetValue(__instance);
					fieldInfo.SetValue(__instance, customFormattedNickname);
				}
			}

			private static void Postfix(TruckScreenText __instance)
			{
				if (nicknameCacheman != string.Empty)
				{
					AccessTools.Field(typeof(TruckScreenText), "nicknameTaxman").SetValue(__instance, nicknameCacheman);
				}
			}

			public static void SetNickname(string nickname, string color)
			{
				customFormattedNickname = "\n\n<color=#" + color + "><b>" + nickname + ":</b></color>\n";
			}

			public static void SetFormattedNickname(string nicknameFormatted)
			{
				customFormattedNickname = "\n\n" + nicknameFormatted + "\n";
			}

			public static void ResetNickname()
			{
				customFormattedNickname = string.Empty;
			}
		}

		[HarmonyPatch(typeof(TruckScreenText), "Update")]
		public class TruckScreenChatPatch
		{
			private struct messageData
			{
				public string message { get; set; }

				public string nickname { get; set; }

				public messageData(string nick, string msg)
				{
					message = msg;
					nickname = nick;
				}
			}

			private const string nickAP = "<b><color=#c97682>AR</color><color=#75c275>CH</color><color=#ca94c2>IP</color><color=#d9a07d>EL</color><color=#767ebd>AG</color><color=#eee391>O:</color></b>";

			private static ConcurrentQueue<messageData> messageQueue = new ConcurrentQueue<messageData>();

			private static void Prefix(TruckScreenText __instance)
			{
				if (Plugin.connection != null)
				{
					int num = (int)AccessTools.Field(typeof(TruckScreenText), "currentLineIndex").GetValue(__instance);
					int index = (int)AccessTools.Field(typeof(TruckScreenText), "currentPageIndex").GetValue(__instance);
					if (num >= __instance.pages[index].textLines.Count && messageQueue.TryDequeue(out var result))
					{
						OverridePlayerNameCheckPatch.SetFormattedNickname(result.nickname);
						__instance.MessageSendCustom(string.Empty, result.message, 0);
						OverridePlayerNameCheckPatch.ResetNickname();
					}
				}
			}

			public static void AddMessage(string preformattedNickname, string message)
			{
				string nick = ((!(preformattedNickname == "AP")) ? ("\n\n" + preformattedNickname + "\n") : "<b><color=#c97682>AR</color><color=#75c275>CH</color><color=#ca94c2>IP</color><color=#d9a07d>EL</color><color=#767ebd>AG</color><color=#eee391>O:</color></b>");
				messageData item = new messageData(nick, message);
				messageQueue.Enqueue(item);
			}

			public static void AddMessage(string nickname, string hexColor, string message)
			{
				string nick = ((!(nickname == "AP")) ? ("\n\n<color=#" + hexColor + "><b>" + nickname + ":</b></color>\n") : "<b><color=#c97682>AR</color><color=#75c275>CH</color><color=#ca94c2>IP</color><color=#d9a07d>EL</color><color=#767ebd>AG</color><color=#eee391>O:</color></b>");
				messageData item = new messageData(nick, message);
				messageQueue.Enqueue(item);
			}
		}
	}
}
internal interface IConcurrentHashSet<T>
{
	bool TryAdd(T item);

	bool Contains(T item);

	void UnionWith(T[] otherSet);

	T[] ToArray();

	ReadOnlyCollection<T> AsToReadOnlyCollection();

	ReadOnlyCollection<T> AsToReadOnlyCollectionExcept(IConcurrentHashSet<T> otherSet);
}
namespace Archipelago.MultiClient.Net
{
	[Serializable]
	public abstract class ArchipelagoPacketBase
	{
		[JsonIgnore]
		internal JObject jobject;

		[JsonProperty("cmd")]
		[JsonConverter(typeof(StringEnumConverter))]
		public abstract ArchipelagoPacketType PacketType { get; }

		public JObject ToJObject()
		{
			return jobject;
		}
	}
	public interface IArchipelagoSession : IArchipelagoSessionActions
	{
		IArchipelagoSocketHelper Socket { get; }

		IReceivedItemsHelper Items { get; }

		ILocationCheckHelper Locations { get; }

		IPlayerHelper Players { get; }

		IDataStorageHelper DataStorage { get; }

		IConnectionInfoProvider ConnectionInfo { get; }

		IRoomStateHelper RoomState { get; }

		IMessageLogHelper MessageLog { get; }

		Task<RoomInfoPacket> ConnectAsync();

		Task<LoginResult> LoginAsync(string game, string name, ItemsHandlingFlags itemsHandlingFlags, Version version = null, string[] tags = null, string uuid = null, string password = null, bool requestSlotData = true);

		LoginResult TryConnectAndLogin(string game, string name, ItemsHandlingFlags itemsHandlingFlags, Version version = null, string[] tags = null, string uuid = null, string password = null, bool requestSlotData = true);
	}
	public class ArchipelagoSession : IArchipelagoSession, IArchipelagoSessionActions
	{
		private const int ArchipelagoConnectionTimeoutInSeconds = 4;

		private ConnectionInfoHelper connectionInfo;

		private TaskCompletionSource<LoginResult> loginResultTask = new TaskCompletionSource<LoginResult>();

		private TaskCompletionSource<RoomInfoPacket> roomInfoPacketTask = new TaskCompletionSource<RoomInfoPacket>();

		public IArchipelagoSocketHelper Socket { get; }

		public IReceivedItemsHelper Items { get; }

		public ILocationCheckHelper Locations { get; }

		public IPlayerHelper Players { get; }

		public IDataStorageHelper DataStorage { get; }

		public IConnectionInfoProvider ConnectionInfo => connectionInfo;

		public IRoomStateHelper RoomState { get; }

		public IMessageLogHelper MessageLog { get; }

		internal ArchipelagoSession(IArchipelagoSocketHelper socket, IReceivedItemsHelper items, ILocationCheckHelper locations, IPlayerHelper players, IRoomStateHelper roomState, ConnectionInfoHelper connectionInfoHelper, IDataStorageHelper dataStorage, IMessageLogHelper messageLog)
		{
			Socket = socket;
			Items = items;
			Locations = locations;
			Players = players;
			RoomState = roomState;
			connectionInfo = connectionInfoHelper;
			DataStorage = dataStorage;
			MessageLog = messageLog;
			socket.PacketReceived += Socket_PacketReceived;
		}

		private void Socket_PacketReceived(ArchipelagoPacketBase packet)
		{
			if (!(packet is ConnectedPacket) && !(packet is ConnectionRefusedPacket))
			{
				if (packet is RoomInfoPacket result)
				{
					roomInfoPacketTask.TrySetResult(result);
				}
				return;
			}
			if (packet is ConnectedPacket && RoomState.Version != null && RoomState.Version >= new Version(0, 3, 8))
			{
				LogUsedVersion();
			}
			loginResultTask.TrySetResult(LoginResult.FromPacket(packet));
		}

		private void LogUsedVersion()
		{
			try
			{
				string fileVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion;
				Socket.SendPacketAsync(new SetPacket
				{
					Key = ".NetUsedVersions",
					DefaultValue = (JToken)(object)JObject.FromObject((object)new Dictionary<string, bool>()),
					Op