Decompiled source of MuckSaveGame v0.9.0

MuckSaveGame.dll

Decompiled 9 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Schema;
using System.Xml.Serialization;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using MuckSaveGame.Dto;
using MuckSaveGame.Legacy;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("MuckSaveGame")]
[assembly: AssemblyConfiguration("RELEASE")]
[assembly: AssemblyDescription("This mod adds saving your game to Muck. It is basically, a fork and update of flarfo's fantastic SaveUtility mod. This can automatically migrate saves from SaveUtility.")]
[assembly: AssemblyFileVersion("0.9.0.0")]
[assembly: AssemblyInformationalVersion("0.9.0+62e86ef28eb5a4c260cba9991f473635bc43bf5d")]
[assembly: AssemblyProduct("MuckSaveGame")]
[assembly: AssemblyTitle("MuckSaveGame")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.9.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BepInEx
{
	public static class Extensions
	{
		public static void LogItemCreated(this ManualLogSource log, InventoryItem item)
		{
			log.LogInfo((object)("Item \"" + item.name + "\" created, ID " + item.id));
		}

		public static ConfigEntry<int> BindMoreThanZero(this ConfigFile config, string section, string key, int defaultValue, string description)
		{
			ConfigEntry<int> val = config.Bind<int>(section, key, defaultValue, description);
			if (val.Value <= 0)
			{
				val.Value = defaultValue;
			}
			return val;
		}

		public static ConfigEntry<float> BindMoreThanZero(this ConfigFile config, string section, string key, float defaultValue, string description)
		{
			ConfigEntry<float> val = config.Bind<float>(section, key, defaultValue, description);
			if (val.Value <= 0f)
			{
				val.Value = defaultValue;
			}
			return val;
		}

		public static ConfigEntry<float> BindNonNegative(this ConfigFile config, string section, string key, float defaultValue, string description)
		{
			ConfigEntry<float> val = config.Bind<float>(section, key, defaultValue, description);
			if (val.Value < 0f)
			{
				val.Value = defaultValue;
			}
			return val;
		}

		public static ConfigEntry<int> BindNonNegative(this ConfigFile config, string section, string key, int defaultValue, string description)
		{
			ConfigEntry<int> val = config.Bind<int>(section, key, defaultValue, description);
			if ((float)val.Value < 0f)
			{
				val.Value = defaultValue;
			}
			return val;
		}

		public static InventoryItem Clone(this InventoryItem i)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			InventoryItem obj = ScriptableObject.CreateInstance<InventoryItem>();
			obj.amount = i.amount;
			obj.armor = i.armor;
			obj.armorComponent = i.armorComponent;
			obj.attackDamage = i.attackDamage;
			obj.attackRange = i.attackRange;
			obj.attackSpeed = i.attackSpeed;
			obj.attackTypes = i.attackTypes;
			obj.bowComponent = i.bowComponent;
			obj.buildRotation = i.buildRotation;
			obj.buildable = i.buildable;
			obj.craftAmount = i.craftAmount;
			obj.craftable = i.craftable;
			obj.description = i.description;
			obj.fuel = i.fuel;
			obj.grid = i.grid;
			obj.heal = i.heal;
			((Object)obj).hideFlags = ((Object)i).hideFlags;
			obj.hunger = i.hunger;
			obj.id = i.id;
			obj.important = i.important;
			obj.material = i.material;
			obj.max = i.max;
			obj.mesh = i.mesh;
			obj.name = i.name;
			obj.positionOffset = i.positionOffset;
			obj.prefab = i.prefab;
			obj.processTime = i.processTime;
			obj.processType = i.processType;
			obj.processable = i.processable;
			obj.processedItem = i.processedItem;
			obj.rarity = i.rarity;
			obj.requirements = i.requirements;
			obj.resourceDamage = i.resourceDamage;
			obj.rotationOffset = i.rotationOffset;
			obj.scale = i.scale;
			obj.sharpness = i.sharpness;
			obj.sprite = i.sprite;
			obj.stackable = i.stackable;
			obj.stamina = i.stamina;
			obj.stationRequirement = i.stationRequirement;
			obj.swingFx = i.swingFx;
			obj.tag = i.tag;
			obj.tier = i.tier;
			obj.type = i.type;
			obj.unlockWithFirstRequirementOnly = i.unlockWithFirstRequirementOnly;
			return obj;
		}
	}
}
namespace Steamworks
{
	public static class Net
	{
		public static void ClientSendTCPData(Packet _packet)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			ClientSend.bytesSent += _packet.Length();
			ClientSend.packetsSent++;
			_packet.WriteLength();
			if ((int)NetworkController.Instance.networkType == 1)
			{
				LocalClient.instance.tcp.SendData(_packet);
			}
			else
			{
				SteamPacketManager.SendPacket(SteamId.op_Implicit(LocalClient.instance.serverHost.Value), _packet, (P2PSend)2, (NetworkChannel)1);
			}
		}

		public static void ServerSendTCPData(int toClient, Packet packet)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Invalid comparison between Unknown and I4
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			Packet val = new Packet();
			val.SetBytes(packet.CloneBytes());
			val.WriteLength();
			if ((int)NetworkController.Instance.networkType == 1)
			{
				Server.clients[toClient].tcp.SendData(val);
			}
			else
			{
				SteamPacketManager.SendPacket(SteamId.op_Implicit(Server.clients[toClient].player.steamId.Value), val, (P2PSend)2, (NetworkChannel)0);
			}
		}
	}
}
namespace MuckSaveGame
{
	public sealed class BaseGameSaveDataManager : ISaveDataManager
	{
		public BaseGameSaveData? Data { get; set; }

		public string Name => "main";

		public int LastBossNightThatSpawnedBoss { get; set; }

		public Dictionary<string, SavedPlayer> Players { get; private set; } = new Dictionary<string, SavedPlayer>();


		public static T GetFieldStruct<T>(Type type, string name, object instance) where T : struct
		{
			return (T)type.GetField(name, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(instance);
		}

		public static T? GetField<T>(Type type, string name, object instance) where T : class
		{
			if (instance == null)
			{
				return null;
			}
			object value = type.GetField(name, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(instance);
			if (value != null)
			{
				return (T)value;
			}
			return null;
		}

		public ISaveData GetSaveData()
		{
			//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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_033c: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f5: Expected I4, but got Unknown
			//IL_05b3: Unknown result type (might be due to invalid IL or missing references)
			Type typeFromHandle = typeof(GameLoop);
			Vector2 fieldStruct = BaseGameSaveDataManager.GetFieldStruct<Vector2>(typeFromHandle, "checkMobUpdateInterval", (object)GameLoop.Instance);
			List<MobType> field = GetField<List<MobType>>(typeFromHandle, "bossRotation", GameLoop.Instance);
			List<int> bossesInRotation;
			if (field == null)
			{
				bossesInRotation = new List<int>();
				Plugin.Log.LogWarning((object)"GameLoop.bossRotation was null; using empty list as boss rotation");
			}
			else
			{
				bossesInRotation = (from x in field
					where x != null
					select x.id).ToList();
			}
			WorldSaveData worldData = new WorldSaveData(GameLoop.Instance.currentDay, World.worldSeed, DayCycle.time, DayCycle.totalTime, fieldStruct.x, fieldStruct.y, LastBossNightThatSpawnedBoss, bossesInRotation);
			PlayerStatus instance = PlayerStatus.Instance;
			int[] field2 = GetField<int[]>(typeof(PowerupInventory), "powerups", PowerupInventory.Instance);
			if (field2 == null)
			{
				throw new Exception("PowerupInventory.powerups was null!");
			}
			InventoryCell[] array = InventoryUI.Instance.armorCells ?? throw new Exception("InventoryUI.armorCells was null!");
			List<int> list = new List<int>(array.Length);
			for (int i = 0; i < array.Length; i++)
			{
				list.Add((array[i]?.currentItem != null && Object.op_Implicit((Object)(object)array[i].currentItem)) ? array[i].currentItem.id : (-1));
			}
			Type typeFromHandle2 = typeof(UiEvents);
			bool[] array2 = GetField<bool[]>(typeFromHandle2, "unlockedSoft", UiEvents.Instance);
			bool[] array3 = GetField<bool[]>(typeFromHandle2, "unlockedHard", UiEvents.Instance);
			bool[] array4 = GetField<bool[]>(typeFromHandle2, "stationsUnlocked", UiEvents.Instance);
			if (array2 == null)
			{
				array2 = new bool[0];
				Plugin.Log.LogWarning((object)"UiEvents.unlockedSoft was null; using empty list as unlockedSoft");
			}
			if (array3 == null)
			{
				array3 = new bool[0];
				Plugin.Log.LogWarning((object)"UiEvents.unlockedHard was null; using empty list as unlockedHard");
			}
			if (array4 == null)
			{
				array4 = new bool[0];
				Plugin.Log.LogWarning((object)"UiEvents.stationsUnlocked was null; using empty list as stationsUnlocked");
			}
			IdAmount arrows = ((InventoryUI.Instance.arrows?.currentItem != null && Object.op_Implicit((Object)(object)InventoryUI.Instance.arrows.currentItem)) ? IdAmount.FromItem(InventoryUI.Instance.arrows.currentItem) : default(IdAmount));
			if (InventoryUI.Instance.cells == null)
			{
				throw new Exception("InventoryUI.cells was null!");
			}
			List<IdAmount> list2 = new List<IdAmount>(InventoryUI.Instance.cells.Count);
			foreach (InventoryCell cell in InventoryUI.Instance.cells)
			{
				if (cell?.currentItem != null && Object.op_Implicit((Object)(object)cell.currentItem))
				{
					list2.Add(IdAmount.FromItem(cell.currentItem));
				}
				else
				{
					list2.Add(default(IdAmount));
				}
			}
			PlayerSaveData playerData = new PlayerSaveData(new SavedPlayer(instance.hp, instance.maxHp, instance.stamina, instance.maxStamina, instance.shield, instance.maxShield, instance.hunger, instance.maxHunger, instance.draculaStacks, Position.FromVec3(((Component)PlayerMovement.Instance).transform.position), field2.ToList(), list, new List<bool>(array2), new List<bool>(array3), new List<bool>(array4), arrows, list2), LoadManager.Players);
			List<SavedContainer> list3 = new List<SavedContainer>();
			List<SavedContainer> list4 = new List<SavedContainer>();
			List<SavedContainer> list5 = new List<SavedContainer>();
			if (ChestManager.Instance.chests == null)
			{
				throw new Exception("ChestManager.chests was null!");
			}
			foreach (Chest value in ChestManager.Instance.chests.Values)
			{
				if (value != null)
				{
					SavedContainer item = SavedContainer.Create(value);
					switch (value.chestSize)
					{
					case 3:
						list4.Add(item);
						break;
					case 6:
						list5.Add(item);
						break;
					case 21:
						list3.Add(item);
						break;
					}
				}
				else
				{
					Plugin.Log.LogWarning((object)"A container is null, skipping");
				}
			}
			ContainerSaveData containerData = new ContainerSaveData(list3, list4, list5);
			List<SavedBuild> builds = World.builds.Values.ToList();
			Component[] array5 = GetField<Component[]>(typeof(Boat), "repairs", Boat.Instance);
			if (array5 == null)
			{
				Plugin.Log.LogWarning((object)"Boat.repairs was null; using empty list as repairs");
				array5 = (Component[])(object)new Component[0];
			}
			List<int> list6 = new List<int>(array5.Length);
			foreach (RepairInteract item2 in array5.Cast<RepairInteract>())
			{
				if (!Object.op_Implicit((Object)(object)item2))
				{
					list6.Add(item2.GetId());
				}
			}
			BoatSaveData boatData = new BoatSaveData(World.isBoatMarked, World.isBoatFound, World.isBoatFinished, World.areGemsMarked, list6);
			List<SavedMob> list7 = new List<SavedMob>();
			if (MobManager.Instance.mobs == null)
			{
				Plugin.Log.LogWarning((object)"MobManager.mobs was null; not saving mobs");
			}
			else
			{
				foreach (Mob value2 in MobManager.Instance.mobs.Values)
				{
					if (value2?.mobType != null)
					{
						if (Plugin.SaveMobNames.Contains(value2.mobType.name))
						{
							Plugin.Log.LogInfo((object)("Saving mob: " + value2.mobType.name));
							Guardian component = ((Component)value2).gameObject.GetComponent<Guardian>();
							int guardianType = ((component == null || !Object.op_Implicit((Object)(object)component)) ? (-1) : ((int)component.type));
							list7.Add(new SavedMob(value2.mobType.id, (int)value2.bossType, guardianType, value2.multiplier, value2.bossMultiplier, Position.FromVec3(((Component)value2).transform.position)));
						}
						else
						{
							Plugin.Log.LogInfo((object)("Mob will not be saved: " + value2.mobType?.name));
						}
					}
				}
			}
			if (ItemManager.Instance.list == null)
			{
				throw new Exception("ItemManager.list was null!");
			}
			List<SavedDroppedItem> list8 = new List<SavedDroppedItem>();
			foreach (GameObject value3 in ItemManager.Instance.list.Values)
			{
				Item component2 = value3.GetComponent<Item>();
				if (component2 != null && Object.op_Implicit((Object)(object)component2) && component2.item != null)
				{
					list8.Add(new SavedDroppedItem(new IdAmount(component2.item.id, component2.item.amount), Position.FromVec3(value3.transform.position)));
				}
			}
			EntitySaveData entityData = new EntitySaveData(builds, list7, list8);
			return new BaseGameSaveData(worldData, boatData, playerData, containerData, entityData);
		}

		public void ApplyLoadedData()
		{
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			if (Data == null)
			{
				return;
			}
			WorldSaveData worldData = Data.WorldData;
			GameManager.instance.currentDay = worldData.CurrentDay;
			GameManager.instance.UpdateDay(worldData.CurrentDay);
			ServerSend.NewDay(worldData.CurrentDay);
			LastBossNightThatSpawnedBoss = worldData.LastBossNightThatSpawnedBoss;
			List<Chest> list = new List<Chest>();
			List<Chest> list2 = new List<Chest>();
			List<Chest> list3 = new List<Chest>();
			LoadContainers(Data.ContainerData.Chests, World.chest, list);
			LoadContainers(Data.ContainerData.Furnaces, World.furnace, list2);
			LoadContainers(Data.ContainerData.Cauldrons, World.cauldron, list3);
			LoadLocalPlayer(Data.PlayerData.LocalPlayer);
			LoadMobs(Data.EntityData.Mobs);
			LoadItems(Data.EntityData.DroppedItems);
			LoadBuilds(Data.EntityData.Builds);
			LoadBoat(Data.BoatData);
			Plugin.Log.LogInfo((object)"Applying loaded data");
			Dictionary<int, MobType> dictionary = new Dictionary<int, MobType>();
			MobType[] allMobs = MobSpawner.Instance.allMobs;
			foreach (MobType val in allMobs)
			{
				dictionary[val.id] = val;
			}
			GameLoop.Instance.currentDay = worldData.CurrentDay;
			Type typeFromHandle = typeof(GameLoop);
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.NonPublic;
			typeFromHandle.GetField("activeMobs", bindingAttr).SetValue(GameLoop.Instance, Data.EntityData.Mobs.Count);
			float num = (float)typeFromHandle.GetMethod("CalculateSpawnWeights", bindingAttr).Invoke(GameLoop.Instance, new object[1] { worldData.CurrentDay });
			typeFromHandle.GetField("totalWeight", bindingAttr).SetValue(GameLoop.Instance, num);
			typeFromHandle.GetMethod("FindMobCap", bindingAttr).Invoke(GameLoop.Instance, null);
			if (worldData.MobUpdateIntervalMin > 0f && worldData.MobUpdateIntervalMax > 0f)
			{
				float num2 = 1f - PowerupInventory.CumulativeDistribution(worldData.CurrentDay, 0.05f, 0.5f);
				Vector2 val2 = new Vector2(worldData.MobUpdateIntervalMin, worldData.MobUpdateIntervalMax) * num2;
				typeFromHandle.GetField("checkMobUpdateInterval", bindingAttr).SetValue(GameLoop.Instance, val2);
			}
			if (worldData.BossesInRotation.Count > 0)
			{
				List<MobType> list4 = (List<MobType>)typeFromHandle.GetField("bossRotation", bindingAttr).GetValue(GameLoop.Instance);
				list4.Clear();
				foreach (int item in worldData.BossesInRotation)
				{
					if (dictionary.TryGetValue(item, out var value))
					{
						list4.Add(value);
					}
				}
			}
			Players = Data.PlayerData.ClientPlayers;
			foreach (Chest item2 in list)
			{
				try
				{
					item2.UpdateCraftables();
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)ex.ToString());
				}
			}
			foreach (Chest item3 in list2)
			{
				try
				{
					item3.UpdateCraftables();
				}
				catch (Exception ex2)
				{
					Plugin.Log.LogError((object)ex2.ToString());
				}
			}
			foreach (Chest item4 in list3)
			{
				try
				{
					item4.UpdateCraftables();
				}
				catch (Exception ex3)
				{
					Plugin.Log.LogError((object)ex3.ToString());
				}
			}
		}

		public void LoadXml(XElement xml)
		{
			Data = BaseGameSaveData.Load(xml);
		}

		private void LoadContainers(IEnumerable<SavedContainer> containers, int buildId, List<Chest> chests)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			foreach (SavedContainer container in containers)
			{
				int nextId = ChestManager.Instance.GetNextId();
				BuildManager.Instance.BuildItem(0, buildId, nextId, container.Position.ToVec3(), container.Rotation);
				ServerSend.SendBuild(0, buildId, nextId, container.Position.ToVec3(), container.Rotation);
				Chest val = ChestManager.Instance.chests[nextId];
				val.cells = (InventoryItem[])(object)new InventoryItem[container.Size];
				chests.Add(val);
				int num = 0;
				foreach (CellIdAmount item in container.Inventory)
				{
					if (ItemManager.Instance.allItems.TryGetValue(item.ItemId, out var value))
					{
						InventoryItem val2 = ScriptableObject.CreateInstance<InventoryItem>();
						val2.Copy(value, item.Amount);
						if (item.Cell < val.cells.Length)
						{
							val.cells[item.Cell] = val2;
							ServerSend.UpdateChest(0, nextId, item.Cell, item.ItemId, item.Amount);
						}
						else
						{
							Plugin.Log.LogError((object)("Inventory at index " + num + " specified cell " + item.Cell + " but the inventory only has " + val.cells.Length + " cells; index is out of range. Skipping"));
						}
					}
					else
					{
						Plugin.Log.LogError((object)("Could not find item with ID " + item.ItemId + ". Skipping"));
					}
					num++;
				}
			}
		}

		private void LoadItems(IList<SavedDroppedItem> droppedItems)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			foreach (SavedDroppedItem droppedItem in droppedItems)
			{
				int itemId = droppedItem.Item.ItemId;
				if (ItemManager.Instance.allItems.ContainsKey(itemId))
				{
					int amount = droppedItem.Item.Amount;
					int nextId = ItemManager.Instance.GetNextId();
					Vector3 val = droppedItem.Position.ToVec3();
					ItemManager.Instance.DropItemAtPosition(itemId, amount, val, nextId);
					ServerSend.DropItemAtPosition(itemId, amount, nextId, val);
				}
				else
				{
					Plugin.Log.LogError((object)("Error loading dropped item: Could not find item with ID " + itemId + ". Skipping"));
				}
			}
		}

		private void LoadBuilds(IList<SavedBuild> builds)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			foreach (SavedBuild build in builds)
			{
				if (ItemManager.Instance.allItems.ContainsKey(build.ItemId))
				{
					int nextBuildId = BuildManager.Instance.GetNextBuildId();
					BuildManager.Instance.BuildItem(0, build.ItemId, nextBuildId, build.Position.ToVec3(), build.Rotation);
					ServerSend.SendBuild(0, build.ItemId, nextBuildId, build.Position.ToVec3(), build.Rotation);
				}
				else
				{
					Plugin.Log.LogError((object)("Error loading build: Could not find item with ID " + build.ItemId + ". Skipping"));
				}
			}
		}

		private void LoadMobs(IList<SavedMob> mobs)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			Plugin.Log.LogInfo((object)"Spawning Mobs!");
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			int num = 0;
			foreach (SavedMob mob in mobs)
			{
				if (mob.MobType < MobSpawner.Instance.allMobs.Length)
				{
					int nextId = MobManager.Instance.GetNextId();
					MobSpawner.Instance.ServerSpawnNewMob(nextId, mob.MobType, mob.Position.ToVec3(), mob.Multiplier, mob.BossMultiplier, (BossType)mob.BossType, mob.GuardianType);
					num++;
					continue;
				}
				Plugin.Log.LogError((object)("Error loading mob: Mob type is " + mob.MobType + " but the maximum valid mob type is " + MobSpawner.Instance.allMobs.Length + "; index is out of range. Skipping"));
			}
			typeof(MobManager).GetField("mobId", bindingAttr).SetValue(MobManager.Instance, num);
		}

		private void LoadLocalPlayer(SavedPlayer playerData)
		{
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<int, InventoryItem> allItems = ItemManager.Instance.allItems;
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			Type typeFromHandle = typeof(UiEvents);
			bool[] array = (bool[])typeFromHandle.GetField("unlockedSoft", bindingAttr).GetValue(UiEvents.Instance);
			bool[] array2 = (bool[])typeFromHandle.GetField("unlockedHard", bindingAttr).GetValue(UiEvents.Instance);
			bool[] array3 = (bool[])typeFromHandle.GetField("stationsUnlocked", bindingAttr).GetValue(UiEvents.Instance);
			for (int i = 0; i < playerData.SoftUnlocks.Count && i < array.Length; i++)
			{
				array[i] = playerData.SoftUnlocks[i];
			}
			for (int j = 0; j < playerData.HardUnlocks.Count && j < array2.Length; j++)
			{
				array2[j] = playerData.HardUnlocks[j];
			}
			for (int k = 0; k < playerData.StationUnlocks.Count && k < array3.Length; k++)
			{
				array3[k] = playerData.StationUnlocks[k];
			}
			typeof(PowerupInventory).GetField("powerups", bindingAttr).SetValue(PowerupInventory.Instance, playerData.Powerups.ToArray());
			bool flag = false;
			if (playerData.Health <= 0f)
			{
				flag = true;
				PlayerStatus.Instance.hp = playerData.MaxHealth;
			}
			else
			{
				PlayerStatus.Instance.hp = playerData.Health;
			}
			PlayerStatus.Instance.maxHp = playerData.MaxHealth;
			PlayerStatus.Instance.stamina = playerData.Stamina;
			PlayerStatus.Instance.maxStamina = playerData.MaxStamina;
			PlayerStatus.Instance.shield = playerData.Shield;
			PlayerStatus.Instance.maxShield = playerData.MaxShield;
			PlayerStatus.Instance.hunger = playerData.Hunger;
			PlayerStatus.Instance.maxHunger = playerData.MaxHunger;
			PlayerStatus.Instance.draculaStacks = playerData.DraculaStacks;
			Position position = playerData.Position;
			((Component)PlayerMovement.Instance).transform.position = new Vector3(position.X, position.Y + Plugin.VerticalOffset, position.Z);
			for (int l = 0; l < playerData.Powerups.Count; l++)
			{
				for (int m = 0; m < playerData.Powerups[l]; m++)
				{
					if (ItemManager.Instance.allPowerups.ContainsKey(l))
					{
						PowerupUI.Instance.AddPowerup(l);
					}
					else
					{
						Plugin.Log.LogError((object)("Error loading Player powerups: Powerup ID is " + l + " which was not found. Skipping"));
					}
				}
			}
			OtherInput.Instance.ToggleInventory((CraftingState)0);
			for (int n = 0; n < 4; n++)
			{
				int num = playerData.Armor[n];
				if (num != -1)
				{
					if (allItems.TryGetValue(num, out var value))
					{
						InventoryUI.Instance.AddArmor(value);
						PlayerStatus.Instance.UpdateArmor(n, num);
					}
					else
					{
						Plugin.Log.LogError((object)("Error loading Player armor: Item ID is " + num + " which was not found. Skipping"));
					}
				}
			}
			OtherInput.Instance.ToggleInventory((CraftingState)0);
			for (int num2 = 0; num2 < InventoryUI.Instance.cells.Count; num2++)
			{
				IdAmount idAmount = playerData.Inventory[num2];
				if (idAmount.Amount != 0)
				{
					if (allItems.TryGetValue(idAmount.ItemId, out var value2))
					{
						InventoryUI.Instance.cells[num2].ForceAddItem(value2, idAmount.Amount);
					}
					else
					{
						Plugin.Log.LogError((object)("Error loading Player inventory: Item ID is " + idAmount.ItemId + " which was not found. Skipping"));
					}
				}
			}
			if (playerData.Arrows.Amount != 0)
			{
				if (allItems.TryGetValue(playerData.Arrows.ItemId, out var value3))
				{
					InventoryUI.Instance.arrows.ForceAddItem(value3, playerData.Arrows.Amount);
				}
				else
				{
					Plugin.Log.LogError((object)("Error loading arrows: Item ID is " + playerData.Arrows.ItemId + " which was not found. Skipping"));
				}
			}
			typeof(UiEvents).GetMethod("Unlock", bindingAttr).Invoke(UiEvents.Instance, null);
			InventoryUI.Instance.UpdateAllCells();
			Hotbar.Instance.UpdateHotbar();
			PlayerStatus.Instance.UpdateStats();
			if (LocalClient.serverOwner && GameManager.players.Count == 1 && flag)
			{
				PlayerStatus.Instance.DealDamage(playerData.MaxHealth + playerData.MaxShield, 0, true, -1);
			}
		}

		private void LoadClients()
		{
			List<Player> list = new List<Player>();
			Client[] array = Server.clients.Values.ToArray();
			for (int i = 0; i < Server.clients.Values.Count; i++)
			{
				if (array[i].player != null)
				{
					Plugin.Log.LogInfo((object)i);
					list.Add(array[i].player);
				}
			}
			for (int j = 0; j < list.Count; j++)
			{
				if (Players.ContainsKey(((object)(SteamId)(ref list[j].steamId)).ToString()) && j != 0)
				{
					int id = array[j].id;
					SavedPlayer player = Players[((object)(SteamId)(ref list[j].steamId)).ToString()];
					Plugin.Log.LogInfo((object)("Sending Inventory To: " + j));
					Plugin.Log.LogInfo((object)("Steam Id: " + ((object)(SteamId)(ref list[j].steamId)).ToString()));
					ServerMethods.SendPlayer(id, player);
				}
			}
		}

		private void LoadBoat(BoatSaveData boatData)
		{
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			foreach (int repairedObjectId in boatData.RepairedObjectIds)
			{
				Plugin.Log.LogInfo((object)("Interacting with ID " + repairedObjectId));
				ClientSend.Interact(repairedObjectId);
			}
			if (boatData.IsBoatMarked)
			{
				Boat.Instance.MarkShip();
			}
			if (boatData.IsBoatFound)
			{
				Boat.Instance.FindShip();
			}
			if (boatData.AreGemsMarked)
			{
				typeof(Boat).GetMethod("MarkGems", bindingAttr).Invoke(Boat.Instance, null);
			}
			if (boatData.IsBoatFinished)
			{
				Boat.Instance.BoatFinished(ResourceManager.Instance.GetNextId());
			}
		}

		public void Unload()
		{
			Data = null;
			Players.Clear();
		}
	}
	public interface ISaveData
	{
		void SaveXml(XElement xml);
	}
	public interface ISaveDataManager
	{
		string Name { get; }

		ISaveData GetSaveData();

		void LoadXml(XElement xml);

		void ApplyLoadedData();

		void Unload();
	}
	[HarmonyPatch]
	public static class LoadManager
	{
		public static string? selectedSavePath;

		public static bool serverHasSaveLoaded;

		public static bool playersUpdated;

		public static bool isEverybodyDead;

		public static Dictionary<string, SavedPlayer> Players => SaveSystem.BaseGameManager.Players;

		[HarmonyPatch(typeof(MenuUI), "StartGame")]
		[HarmonyPrefix]
		private static void LoadOnStart()
		{
			if (selectedSavePath != null)
			{
				Plugin.Log.LogInfo((object)("This save is loading: " + selectedSavePath));
				try
				{
					SaveSystem.Load(selectedSavePath);
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("Failed to load: " + ex.ToString()));
					return;
				}
				ServerMethods.SendHasSave();
			}
			else
			{
				Plugin.Log.LogInfo((object)"No save has been selected for loading");
			}
		}

		[HarmonyPatch(typeof(GameManager), "SendPlayersIntoGame")]
		[HarmonyPostfix]
		private static void AllPlayersReady()
		{
			Plugin.Log.LogInfo((object)"All Players Ready");
			if (LocalClient.serverOwner && selectedSavePath != null)
			{
				ServerMethods.SendHasSave();
			}
		}

		[HarmonyPatch(typeof(GameLoop), "StartLoop")]
		[HarmonyPostfix]
		private static void Postfix()
		{
			Plugin.Log.LogInfo((object)"SPAWN PLAYERS THING");
			if (playersUpdated)
			{
				return;
			}
			if (LocalClient.serverOwner)
			{
				if (selectedSavePath != null)
				{
					SaveSystem.ApplyLoadedData();
				}
				else
				{
					selectedSavePath = SaveSystem.GetPathForSeed(World.worldSeed);
				}
				World.doSave = true;
			}
			playersUpdated = true;
		}

		[HarmonyPatch(typeof(GameLoop), "StartBoss")]
		[HarmonyPrefix]
		private static bool PreventBossSpawnIfOneHasAlreadySpawnedIn(GameLoop __instance)
		{
			if (LocalClient.serverOwner && selectedSavePath != null && SaveSystem.BaseGameManager.Data != null)
			{
				if (SaveSystem.BaseGameManager.LastBossNightThatSpawnedBoss == __instance.currentDay)
				{
					Plugin.Log.LogInfo((object)("Blocking boss spawn, as the day is " + __instance.currentDay));
					return false;
				}
				Plugin.Log.LogInfo((object)("New boss spawn night, old: " + SaveSystem.BaseGameManager.LastBossNightThatSpawnedBoss + " new: " + __instance.currentDay));
				SaveSystem.BaseGameManager.LastBossNightThatSpawnedBoss = __instance.currentDay;
			}
			return true;
		}

		[HarmonyPatch(typeof(DayCycle), "Awake")]
		[HarmonyPostfix]
		private static void DayPatch(DayCycle __instance)
		{
			if (LocalClient.serverOwner && selectedSavePath != null && SaveSystem.BaseGameManager.Data != null)
			{
				BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
				DayCycle.time = SaveSystem.BaseGameManager.Data.WorldData.Time;
				typeof(DayCycle).GetProperty("totalTime", bindingAttr).SetValue(__instance, SaveSystem.BaseGameManager.Data.WorldData.TotalTime);
			}
		}

		[HarmonyPatch(typeof(SteamLobby), "FindSeed")]
		[HarmonyPostfix]
		private static void GetLoadedSeed(ref int __result)
		{
			if (selectedSavePath != null && SaveSystem.BaseGameManager.Data != null)
			{
				__result = SaveSystem.BaseGameManager.Data.WorldData.Seed;
			}
		}

		[HarmonyPatch(typeof(SpawnChestsInLocations), "SetChests")]
		[HarmonyPrefix]
		private static bool DontSpawnRandomChestsIfSaveHasBeenLoaded()
		{
			if (LocalClient.serverOwner)
			{
				return selectedSavePath == null;
			}
			return !serverHasSaveLoaded;
		}
	}
	[HarmonyPatch]
	internal class ClientMethods
	{
		[HarmonyPatch(typeof(LocalClient), "InitializeClientData")]
		private static void Postfix()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Expected O, but got Unknown
			Plugin.Log.LogInfo((object)"CLIENT DATA INITIALIZED");
			LocalClient.packetHandlers.Add(100, new PacketHandler(ReceiveServerHasSave));
			LocalClient.packetHandlers.Add(101, new PacketHandler(HandleSave));
			LocalClient.packetHandlers.Add(102, new PacketHandler(ReceiveInventory));
			LocalClient.packetHandlers.Add(103, new PacketHandler(ReceivePowerups));
			LocalClient.packetHandlers.Add(104, new PacketHandler(ReceivePosition));
			LocalClient.packetHandlers.Add(105, new PacketHandler(ReceivePlayerStatus));
			LocalClient.packetHandlers.Add(106, new PacketHandler(ReceiveArmor));
			LocalClient.packetHandlers.Add(107, new PacketHandler(ReceiveTime));
		}

		public static void SendInventory()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			Plugin.Log.LogInfo((object)"SENDING INVENTORY");
			Packet val = new Packet(100);
			try
			{
				val.Write(SteamManager.Instance.PlayerSteamIdString);
				foreach (InventoryCell cell in InventoryUI.Instance.cells)
				{
					if (Object.op_Implicit((Object)(object)cell.currentItem))
					{
						int amount = cell.currentItem.amount;
						if (amount > 0)
						{
							val.Write((short)cell.currentItem.id);
							val.Write((short)amount);
						}
					}
					else
					{
						val.Write((short)(-1));
						val.Write((short)0);
					}
				}
				Net.ClientSendTCPData(val);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		public static void SendPowerups()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			Plugin.Log.LogInfo((object)"SENDING POWERUPS");
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			int[] array = (int[])typeof(PowerupInventory).GetField("powerups", bindingAttr).GetValue(PowerupInventory.Instance);
			Packet val = new Packet(101);
			try
			{
				val.Write(SteamManager.Instance.PlayerSteamIdString);
				int[] array2 = array;
				foreach (int num in array2)
				{
					val.Write((short)num);
				}
				Net.ClientSendTCPData(val);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		public static void SendPosition()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			Plugin.Log.LogInfo((object)"SENDING POSITION");
			float x = ((Component)PlayerMovement.Instance).transform.position.x;
			float y = ((Component)PlayerMovement.Instance).transform.position.y;
			float z = ((Component)PlayerMovement.Instance).transform.position.z;
			Packet val = new Packet(102);
			try
			{
				val.Write(SteamManager.Instance.PlayerSteamIdString);
				val.Write(x);
				val.Write(y);
				val.Write(z);
				Net.ClientSendTCPData(val);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		public static void SendPlayerStatus()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			Plugin.Log.LogInfo((object)"SENDING PLAYERSTATUS");
			Packet val = new Packet(103);
			try
			{
				val.Write(SteamManager.Instance.PlayerSteamIdString);
				val.Write(PlayerStatus.Instance.hp);
				val.Write(PlayerStatus.Instance.maxHp);
				val.Write(PlayerStatus.Instance.stamina);
				val.Write(PlayerStatus.Instance.maxStamina);
				val.Write(PlayerStatus.Instance.shield);
				val.Write(PlayerStatus.Instance.maxShield);
				val.Write(PlayerStatus.Instance.hunger);
				val.Write(PlayerStatus.Instance.maxHunger);
				val.Write(PlayerStatus.Instance.draculaStacks);
				Net.ClientSendTCPData(val);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		public static void SendArmor()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			Plugin.Log.LogInfo((object)"SENDING ARMOR");
			Packet val = new Packet(104);
			try
			{
				val.Write(SteamManager.Instance.PlayerSteamIdString);
				for (int i = 0; i < 4; i++)
				{
					if (Object.op_Implicit((Object)(object)InventoryUI.Instance.armorCells[i].currentItem))
					{
						val.Write((short)InventoryUI.Instance.armorCells[i].currentItem.id);
					}
					else
					{
						val.Write((short)(-1));
					}
				}
				if (Object.op_Implicit((Object)(object)InventoryUI.Instance.arrows.currentItem))
				{
					val.Write((short)InventoryUI.Instance.arrows.currentItem.id);
					val.Write(InventoryUI.Instance.arrows.currentItem.amount);
				}
				else
				{
					val.Write((short)(-1));
					val.Write(-1);
				}
				Net.ClientSendTCPData(val);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		public static void SendPlayerReady()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			Packet val = new Packet(105);
			try
			{
				val.Write(SteamManager.Instance.PlayerSteamIdString);
				Net.ClientSendTCPData(val);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		public static void ReceiveServerHasSave(Packet _packet)
		{
			Plugin.Log.LogInfo((object)"Server Has Save Received!");
			LoadManager.serverHasSaveLoaded = _packet.ReadBool(true);
		}

		public static void HandleSave(Packet _packet)
		{
			Plugin.Log.LogInfo((object)"Send Save Received!");
			SendInventory();
			SendPowerups();
			SendPosition();
			SendPlayerStatus();
			SendArmor();
		}

		private static void ReceiveInventory(Packet _packet)
		{
			Plugin.Log.LogInfo((object)"Inventory Received!");
			Dictionary<int, InventoryItem> allItems = ItemManager.Instance.allItems;
			int num = 0;
			while (_packet.UnreadLength() >= 2)
			{
				int num2 = _packet.ReadShort(true);
				int num3 = _packet.ReadShort(true);
				if (num2 != -1 && allItems.TryGetValue(num2, out var value))
				{
					InventoryUI.Instance.cells[num].ForceAddItem(value, num3);
				}
				num++;
			}
			InventoryUI.Instance.UpdateAllCells();
			Hotbar.Instance.UpdateHotbar();
		}

		private static void ReceivePowerups(Packet _packet)
		{
			Plugin.Log.LogInfo((object)"Powerups Received!");
			List<int> list = new List<int>();
			while (_packet.UnreadLength() >= 2)
			{
				int item = _packet.ReadShort(true);
				list.Add(item);
			}
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			typeof(PowerupInventory).GetField("powerups", bindingAttr).SetValue(PowerupInventory.Instance, list.ToArray());
			for (int i = 0; i < list.Count; i++)
			{
				for (int j = 0; j < list[i]; j++)
				{
					PowerupUI.Instance.AddPowerup(i);
				}
			}
		}

		private static void ReceivePosition(Packet _packet)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			Plugin.Log.LogInfo((object)"Position Received!");
			Vector3 position = default(Vector3);
			position.x = _packet.ReadFloat(true);
			position.y = _packet.ReadFloat(true);
			position.z = _packet.ReadFloat(true);
			((Component)PlayerMovement.Instance).transform.position = position;
		}

		private static void ReceivePlayerStatus(Packet _packet)
		{
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			Plugin.Log.LogInfo((object)"Player Status Received!");
			PlayerStatus.Instance.hp = _packet.ReadFloat(true);
			PlayerStatus.Instance.maxHp = _packet.ReadInt(true);
			PlayerStatus.Instance.stamina = _packet.ReadFloat(true);
			PlayerStatus.Instance.maxStamina = _packet.ReadFloat(true);
			PlayerStatus.Instance.shield = _packet.ReadFloat(true);
			PlayerStatus.Instance.maxShield = _packet.ReadInt(true);
			PlayerStatus.Instance.hunger = _packet.ReadFloat(true);
			PlayerStatus.Instance.maxHunger = _packet.ReadFloat(true);
			PlayerStatus.Instance.draculaStacks = _packet.ReadInt(true);
			PlayerStatus.Instance.UpdateStats();
			if (PlayerStatus.Instance.hp <= 0f)
			{
				try
				{
					ClientSend.PlayerHitObject(1, 1, 1, default(Vector3), 1);
					new GameObject("World Timer", new Type[1] { typeof(WorldTimer) }).GetComponent<WorldTimer>().StartPlayerDeath(0.3f);
				}
				catch
				{
					BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
					typeof(PlayerStatus).GetMethod("PlayerDied", bindingAttr).Invoke(PlayerStatus.Instance, new object[2] { 0, -1 });
				}
			}
		}

		private static void ReceiveArmor(Packet _packet)
		{
			Plugin.Log.LogInfo((object)"Armor Received!");
			Dictionary<int, InventoryItem> allItems = ItemManager.Instance.allItems;
			OtherInput.Instance.ToggleInventory((CraftingState)0);
			for (int i = 0; i < 4; i++)
			{
				short num = _packet.ReadShort(true);
				if (num != -1 && allItems.TryGetValue(num, out var value))
				{
					InventoryUI.Instance.AddArmor(value);
					PlayerStatus.Instance.UpdateArmor(i, (int)num);
				}
			}
			OtherInput.Instance.ToggleInventory((CraftingState)0);
			short num2 = _packet.ReadShort(true);
			int num3 = _packet.ReadInt(true);
			if (num2 != -1 && allItems.TryGetValue(num2, out var value2))
			{
				InventoryUI.Instance.arrows.ForceAddItem(value2, num3);
			}
		}

		private static void ReceiveTime(Packet _packet)
		{
			Plugin.Log.LogInfo((object)"Time Receieved!");
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			DayCycle.time = _packet.ReadFloat(true);
			typeof(DayCycle).GetProperty("totalTime", bindingAttr).SetValue(null, _packet.ReadFloat(true));
		}

		[HarmonyPatch(typeof(GameManager), "SpawnPlayer")]
		[HarmonyPostfix]
		private static void PlayerSpawned(int id, string username, Color color, Vector3 position, float orientationY)
		{
			if (LocalClient.serverOwner)
			{
				return;
			}
			Plugin.Log.LogInfo((object)"Not Owner!");
			if (LoadManager.serverHasSaveLoaded)
			{
				Plugin.Log.LogInfo((object)"Has Save!");
				if (id == LocalClient.instance.myId)
				{
					Plugin.Log.LogInfo((object)"Sending Player Ready!");
					SendPlayerReady();
				}
			}
		}
	}
	[HarmonyPatch]
	internal class ServerMethods
	{
		[HarmonyPatch(typeof(Server), "InitializeServerPackets")]
		[HarmonyPostfix]
		private static void InitializeCustomPackets()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			Plugin.Log.LogInfo((object)"SERVER DATA INITIALIZED");
			Server.PacketHandlers.Add(100, new PacketHandler(ReceiveInventory));
			Server.PacketHandlers.Add(101, new PacketHandler(ReceivePowerups));
			Server.PacketHandlers.Add(102, new PacketHandler(ReceivePosition));
			Server.PacketHandlers.Add(103, new PacketHandler(ReceivePlayerStatus));
			Server.PacketHandlers.Add(104, new PacketHandler(ReceiveArmor));
			Server.PacketHandlers.Add(105, new PacketHandler(ReceivePlayerReady));
		}

		private static void SendTCPDataToAll(Packet _packet)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			_packet.WriteLength();
			if ((int)NetworkController.Instance.networkType == 1)
			{
				for (int i = 1; i < Server.MaxPlayers; i++)
				{
					Server.clients[i].tcp.SendData(_packet);
				}
				return;
			}
			foreach (Client value in Server.clients.Values)
			{
				if (value?.player != null)
				{
					Plugin.Log.LogInfo((object)("Sending packet to id: " + value.id));
					FieldInfo field = typeof(ServerSend).GetField("TCPvariant", bindingAttr);
					SteamPacketManager.SendPacket(SteamId.op_Implicit(value.player.steamId.Value), _packet, (P2PSend)field.GetValue("TCPVariant"), (NetworkChannel)0);
				}
			}
		}

		private static void SendTCPDataToAll(int exceptClient, Packet _packet)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			_packet.WriteLength();
			if ((int)NetworkController.Instance.networkType == 1)
			{
				for (int i = 1; i < Server.MaxPlayers; i++)
				{
					if (i != exceptClient)
					{
						Server.clients[i].tcp.SendData(_packet);
					}
				}
				return;
			}
			foreach (Client value in Server.clients.Values)
			{
				if (value?.player != null && SteamLobby.steamIdToClientId[value.player.steamId.Value] != exceptClient)
				{
					FieldInfo field = typeof(ServerSend).GetField("TCPvariant", bindingAttr);
					SteamPacketManager.SendPacket(SteamId.op_Implicit(value.player.steamId.Value), _packet, (P2PSend)field.GetValue("TCPVariant"), (NetworkChannel)0);
				}
			}
		}

		private static void SendTCPData(int toClient, Packet _packet)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Invalid comparison between Unknown and I4
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			FieldInfo field = typeof(ServerSend).GetField("TCPvariant", bindingAttr);
			Packet val = new Packet();
			val.SetBytes(_packet.CloneBytes());
			val.WriteLength();
			if ((int)NetworkController.Instance.networkType == 1)
			{
				Server.clients[toClient].tcp.SendData(val);
			}
			else
			{
				SteamPacketManager.SendPacket(SteamId.op_Implicit(Server.clients[toClient].player.steamId.Value), val, (P2PSend)field.GetValue("TCPVariant"), (NetworkChannel)0);
			}
		}

		public static void SendPlayer(int toClient, SavedPlayer player)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			SendPosition(toClient, player.Position);
			((Component)GameManager.players[toClient]).transform.position = player.Position.ToVec3();
			if (player.Inventory.Count > 0)
			{
				SendInventory(toClient, player.Inventory);
			}
			if (player.Powerups.Count > 0)
			{
				SendPowerups(toClient, player.Powerups);
			}
			SendPlayerStatus(toClient, player.Health, player.MaxHealth, player.Stamina, player.MaxStamina, player.Shield, player.MaxShield, player.Hunger, player.MaxHunger, player.DraculaStacks);
			if (player.Armor.Count > 0)
			{
				SendArmor(toClient, player.Armor, player.Arrows);
			}
		}

		public static void SendHasSave()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			Packet val = new Packet(100);
			try
			{
				val.Write(true);
				SendTCPDataToAll(0, val);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		public static void SendServerSave()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			Packet val = new Packet(101);
			try
			{
				SendTCPDataToAll(0, val);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		public static void SendInventory(int toClient, List<IdAmount> inventory)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			Packet val = new Packet(102);
			try
			{
				foreach (IdAmount item in inventory)
				{
					val.Write((short)item.ItemId);
					val.Write((short)item.Amount);
				}
				SendTCPData(toClient, val);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		public static void SendPowerups(int toClient, List<int> powerups)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			Packet val = new Packet(103);
			try
			{
				foreach (int powerup in powerups)
				{
					val.Write((short)powerup);
				}
				SendTCPData(toClient, val);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		public static void SendPosition(int toClient, Position position)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			Packet val = new Packet(104);
			try
			{
				val.Write(position.X);
				val.Write(position.Y);
				val.Write(position.Z);
				SendTCPData(toClient, val);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		public static void SendPlayerStatus(int toClient, float hp, int maxhp, float stamina, float maxstamina, float shield, int maxshield, float hunger, float maxhunger, int draculastacks)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			Packet val = new Packet(105);
			try
			{
				val.Write(hp);
				val.Write(maxhp);
				val.Write(stamina);
				val.Write(maxstamina);
				val.Write(shield);
				val.Write(maxshield);
				val.Write(hunger);
				val.Write(maxhunger);
				val.Write(draculastacks);
				SendTCPData(toClient, val);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		public static void SendArmor(int toClient, List<int> armor, IdAmount arrows)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			Packet val = new Packet(106);
			try
			{
				val.Write((short)armor[0]);
				val.Write((short)armor[1]);
				val.Write((short)armor[2]);
				val.Write((short)armor[3]);
				val.Write((short)arrows.ItemId);
				val.Write(arrows.Amount);
				SendTCPData(toClient, val);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		public static void SendTime(int toClient, float time, float totalTime)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			Packet val = new Packet(107);
			try
			{
				val.Write(time);
				val.Write(totalTime);
				SendTCPData(toClient, val);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		private static void ReceiveInventory(int fromClient, Packet _packet)
		{
			Plugin.Log.LogInfo((object)"PACKET RECEIVED");
			Plugin.Log.LogInfo((object)("CLIENT: " + fromClient));
			string text = _packet.ReadString(true);
			Plugin.Log.LogInfo((object)("STEAMID: " + text));
			List<IdAmount> list = new List<IdAmount>();
			while (_packet.UnreadLength() >= 2)
			{
				list.Add(new IdAmount(_packet.ReadShort(true), _packet.ReadShort(true)));
			}
			if (!LoadManager.Players.ContainsKey(text))
			{
				LoadManager.Players.Add(text, SavedPlayer.CreateEmpty());
				LoadManager.Players[text].Inventory = list;
			}
			else
			{
				LoadManager.Players[text].Inventory = list;
			}
		}

		private static void ReceivePowerups(int fromClient, Packet _packet)
		{
			Plugin.Log.LogInfo((object)"PACKET RECEIVED");
			Plugin.Log.LogInfo((object)("CLIENT: " + fromClient));
			string text = _packet.ReadString(true);
			Plugin.Log.LogInfo((object)("STEAMID: " + text));
			List<int> list = new List<int>();
			while (_packet.UnreadLength() >= 2)
			{
				list.Add(_packet.ReadShort(true));
			}
			if (!LoadManager.Players.ContainsKey(text))
			{
				LoadManager.Players.Add(text, SavedPlayer.CreateEmpty());
				LoadManager.Players[text].Powerups = list;
			}
			else
			{
				LoadManager.Players[text].Powerups = list;
			}
		}

		private static void ReceivePosition(int fromClient, Packet _packet)
		{
			Plugin.Log.LogInfo((object)"PACKET RECEIVED");
			Plugin.Log.LogInfo((object)("CLIENT: " + fromClient));
			string text = _packet.ReadString(true);
			Plugin.Log.LogInfo((object)("STEAMID: " + text));
			float x = _packet.ReadFloat(true);
			float y = _packet.ReadFloat(true);
			float z = _packet.ReadFloat(true);
			Position position = new Position(x, y, z);
			if (!LoadManager.Players.ContainsKey(text))
			{
				LoadManager.Players.Add(text, SavedPlayer.CreateEmpty());
				LoadManager.Players[text].Position = position;
			}
			else
			{
				LoadManager.Players[text].Position = position;
			}
		}

		private static void ReceivePlayerStatus(int fromClient, Packet _packet)
		{
			Plugin.Log.LogInfo((object)"PACKET RECEIVED");
			Plugin.Log.LogInfo((object)("CLIENT: " + fromClient));
			string text = _packet.ReadString(true);
			Plugin.Log.LogInfo((object)("STEAMID: " + text));
			float health = _packet.ReadFloat(true);
			int maxHealth = _packet.ReadInt(true);
			float stamina = _packet.ReadFloat(true);
			float maxStamina = _packet.ReadFloat(true);
			float shield = _packet.ReadFloat(true);
			int maxShield = _packet.ReadInt(true);
			float hunger = _packet.ReadFloat(true);
			float maxHunger = _packet.ReadFloat(true);
			int draculaStacks = _packet.ReadInt(true);
			if (!LoadManager.Players.ContainsKey(text))
			{
				LoadManager.Players.Add(text, SavedPlayer.CreateEmpty());
				LoadManager.Players[text].Health = health;
				LoadManager.Players[text].MaxHealth = maxHealth;
				LoadManager.Players[text].Stamina = stamina;
				LoadManager.Players[text].MaxStamina = maxStamina;
				LoadManager.Players[text].Shield = shield;
				LoadManager.Players[text].MaxShield = maxShield;
				LoadManager.Players[text].Hunger = hunger;
				LoadManager.Players[text].MaxHunger = maxHunger;
				LoadManager.Players[text].DraculaStacks = draculaStacks;
			}
			else
			{
				LoadManager.Players[text].Health = health;
				LoadManager.Players[text].MaxHealth = maxHealth;
				LoadManager.Players[text].Stamina = stamina;
				LoadManager.Players[text].MaxStamina = maxStamina;
				LoadManager.Players[text].Shield = shield;
				LoadManager.Players[text].MaxShield = maxShield;
				LoadManager.Players[text].Hunger = hunger;
				LoadManager.Players[text].MaxHunger = maxHunger;
				LoadManager.Players[text].DraculaStacks = draculaStacks;
			}
		}

		private static void ReceiveArmor(int fromClient, Packet _packet)
		{
			Plugin.Log.LogInfo((object)"PACKET RECEIVED");
			Plugin.Log.LogInfo((object)("CLIENT: " + fromClient));
			string text = _packet.ReadString(true);
			Plugin.Log.LogInfo((object)("STEAMID: " + text));
			if (!LoadManager.Players.ContainsKey(text))
			{
				LoadManager.Players.Add(text, SavedPlayer.CreateEmpty());
				List<int> armor = new List<int>
				{
					_packet.ReadShort(true),
					_packet.ReadShort(true),
					_packet.ReadShort(true),
					_packet.ReadShort(true)
				};
				LoadManager.Players[text].Armor = armor;
				LoadManager.Players[text].Arrows = new IdAmount(_packet.ReadShort(true), _packet.ReadInt(true));
			}
			else
			{
				List<int> armor2 = new List<int>
				{
					_packet.ReadShort(true),
					_packet.ReadShort(true),
					_packet.ReadShort(true),
					_packet.ReadShort(true)
				};
				LoadManager.Players[text].Armor = armor2;
				LoadManager.Players[text].Arrows = new IdAmount(_packet.ReadShort(true), _packet.ReadInt(true));
			}
		}

		private static void ReceivePlayerReady(int fromClient, Packet _packet)
		{
			Plugin.Log.LogInfo((object)"PACKET RECEIVED");
			Plugin.Log.LogInfo((object)("CLIENT: " + fromClient));
			string text = _packet.ReadString(true);
			Plugin.Log.LogInfo((object)("STEAMID: " + text));
			if (LoadManager.Players.ContainsKey(text))
			{
				SendPlayer(fromClient, LoadManager.Players[text]);
			}
			if (SaveSystem.BaseGameManager.Data != null)
			{
				SendTime(fromClient, SaveSystem.BaseGameManager.Data.WorldData.Time, SaveSystem.BaseGameManager.Data.WorldData.TotalTime);
			}
		}
	}
	[BepInPlugin("MuckSaveGame.MichMcb", "MuckSaveGame", "0.9.0")]
	[BepInIncompatibility("flarfo.saveutility")]
	public class Plugin : BaseUnityPlugin
	{
		public static ManualLogSource Log = null;

		public static XmlWriterSettings XmlWriterSettings = new XmlWriterSettings
		{
			Encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: false),
			IndentChars = "\t",
			NewLineChars = "\n",
			NewLineHandling = NewLineHandling.None,
			Indent = true
		};

		public static TimeSpan SaveCooldown;

		public static HashSet<string> SaveMobNames = new HashSet<string>();

		public static float MultiplayerSaveDelay = 5f;

		public static float VerticalOffset = 0f;

		public void Awake()
		{
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			XmlWriterSettings.Indent = ((BaseUnityPlugin)this).Config.Bind<bool>("Main", "Indent", true, "Whether or not to indent the XML save file elements and use newlines. This doesn't affect saving or loading in any way. Indenting the file takes up slightly more space, but makes it easier to read.").Value;
			SaveCooldown = TimeSpan.FromSeconds(((BaseUnityPlugin)this).Config.Bind<int>("Main", "SaveCooldown", 60, "The number of seconds you must wait until you can save your game again.").Value);
			SaveMobNames = new HashSet<string>(((BaseUnityPlugin)this).Config.Bind<string>("Main", "SaveMobNames", "Big Chunk,Gronk,Guardian,Chief", "The names of the currently spawned mobs that are saved and restored.").Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries));
			MultiplayerSaveDelay = ((BaseUnityPlugin)this).Config.BindMoreThanZero("Main", "MultiplayerSaveDelay", MultiplayerSaveDelay, "The delay, in seconds, between clicking the Save button and the save actually executing when playing multiplayer. This is so the packets from clients have time to be sent over the network to the game host. There's no delay in singleplayer; saving always happens instantly.").Value;
			VerticalOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Main", "VerticalOffset", VerticalOffset, "Offsets the local player by this value on the Y axis when loading data. This can be useful to prevent you from falling through floors on loading a savegame. Doesn't work in multiplayer yet.").Value;
			((BaseUnityPlugin)this).Config.Save();
			Directory.CreateDirectory(SaveSystem.GetSavesBasePath());
			SaveSystem.MigrateOldSaves();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded MuckSaveGame!");
			UIManager.backgroundImage = GetAssetBundleFromResource("MuckSaveGameAssets").LoadAsset<Texture>("Assets/Texture2D/groundCompressed.png");
			new Harmony("MuckSaveGame").PatchAll();
		}

		public static AssetBundle GetAssetBundleFromResource(string fileName)
		{
			string fileName2 = fileName;
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string text = executingAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(fileName2));
			Log.LogInfo((object)("Resource Name: " + text));
			using Stream stream = executingAssembly.GetManifestResourceStream(text);
			return AssetBundle.LoadFromStream(stream);
		}
	}
	public class SaveButton : MonoBehaviour, IPointerClickHandler, IEventSystemHandler
	{
		private void Start()
		{
			UIManager.saveButtons.Add(((TMP_Text)((Component)this).GetComponentInChildren<TextMeshProUGUI>()).text, this);
		}

		public void OnPointerClick(PointerEventData eventData)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Invalid comparison between Unknown and I4
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			if ((int)eventData.button == 0)
			{
				LoadManager.selectedSavePath = SaveSystem.GetPathForFileName(((TMP_Text)((Component)this).GetComponentInChildren<TextMeshProUGUI>()).text);
				GameObject? selectionGUI = UIManager.selectionGUI;
				if (selectionGUI != null)
				{
					selectionGUI.SetActive(false);
				}
			}
			else if ((int)eventData.button == 1)
			{
				if ((Object)(object)UIManager.buttonExtraGUI != (Object)null)
				{
					UIManager.buttonExtraGUI.transform.position = new Vector3(eventData.position.x + 200f, eventData.position.y - 125f);
					UIManager.buttonExtraGUI.SetActive(true);
				}
				UIManager.curEditSave = ((TMP_Text)((Component)this).GetComponentInChildren<TextMeshProUGUI>()).text;
				if ((Object)(object)UIManager.buttonExtraGUI != (Object)null)
				{
					((TMP_Text)UIManager.buttonExtraGUI.GetComponentInChildren<TextMeshProUGUI>()).text = ((UIManager.curEditSave.Length > 12) ? (((TMP_Text)((Component)this).GetComponentInChildren<TextMeshProUGUI>()).text.Substring(0, 12) + "...") : ((TMP_Text)((Component)this).GetComponentInChildren<TextMeshProUGUI>()).text);
				}
			}
		}

		public void UpdateText(string text)
		{
			((TMP_Text)((Component)this).GetComponentInChildren<TextMeshProUGUI>()).text = text;
		}
	}
	public static class SaveSystem
	{
		public static readonly BaseGameSaveDataManager BaseGameManager = new BaseGameSaveDataManager();

		private static readonly Dictionary<string, ISaveDataManager> Registrations = new Dictionary<string, ISaveDataManager> { [BaseGameManager.Name] = BaseGameManager };

		private static readonly List<ISaveDataManager> OrderedRegistrations = new List<ISaveDataManager> { BaseGameManager };

		public static void Register(ISaveDataManager manager)
		{
			Registrations.Add(manager.Name, manager);
			OrderedRegistrations.Add(manager);
		}

		public static string GetSavesBasePath()
		{
			return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Saves");
		}

		public static string GetPathForSeed(int seed)
		{
			return GetPathForFileName(seed + ".mucksave");
		}

		public static string GetPathForFileName(string fileName)
		{
			return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Saves", fileName);
		}

		public static void Save(string path)
		{
			List<(ISaveData, string)> list = new List<(ISaveData, string)>(OrderedRegistrations.Count);
			foreach (ISaveDataManager orderedRegistration in OrderedRegistrations)
			{
				list.Add((orderedRegistration.GetSaveData(), orderedRegistration.Name));
			}
			XDocument xDocument = new XDocument();
			XElement xElement = new XElement("MuckSaveGame");
			xDocument.Add(xElement);
			foreach (var item3 in list)
			{
				ISaveData item = item3.Item1;
				string item2 = item3.Item2;
				XElement xElement2 = xElement.AddElement("Data");
				xElement2.SetAttributeValue("type", item2);
				item.SaveXml(xElement2);
			}
			using FileStream output = new FileStream(path, FileMode.Create, FileAccess.Write);
			using XmlWriter writer = XmlWriter.Create(output, Plugin.XmlWriterSettings);
			xDocument.Save(writer);
		}

		public static void ApplyLoadedData()
		{
			foreach (ISaveDataManager orderedRegistration in OrderedRegistrations)
			{
				orderedRegistration.ApplyLoadedData();
			}
		}

		public static BaseGameSaveData? Load(string path)
		{
			Plugin.Log.LogInfo((object)"Loading");
			if (File.Exists(path))
			{
				XDocument xDocument;
				using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
				{
					xDocument = XDocument.Load(stream);
				}
				if (xDocument != null)
				{
					foreach (XElement item in xDocument.Root.Elements())
					{
						if (Registrations.TryGetValue(item.Attribute("type").Value, out ISaveDataManager value))
						{
							value.LoadXml(item);
						}
					}
					return BaseGameManager.Data;
				}
				Plugin.Log.LogError((object)("Could not load file at " + path));
				return null;
			}
			Plugin.Log.LogError((object)("Save File does not Exist at " + path));
			return null;
		}

		public static void Unload()
		{
			for (int num = OrderedRegistrations.Count - 1; num >= 0; num--)
			{
				OrderedRegistrations[num].Unload();
			}
		}

		public static List<string> GetAllSaves()
		{
			List<string> list = new List<string>();
			foreach (string item in Directory.EnumerateFiles(GetSavesBasePath()))
			{
				if (".mucksave".Equals(Path.GetExtension(item), StringComparison.OrdinalIgnoreCase))
				{
					list.Add(item);
				}
			}
			return list;
		}

		public static void MigrateOldSaves()
		{
			foreach (string item in Directory.EnumerateFiles(GetSavesBasePath()))
			{
				if (!".muck".Equals(Path.GetExtension(item), StringComparison.OrdinalIgnoreCase))
				{
					continue;
				}
				Plugin.Log.LogInfo((object)("Migrating legacy save: " + item));
				bool flag = false;
				try
				{
					WorldSave worldSave;
					using (FileStream stream = new FileStream(item, FileMode.Open, FileAccess.Read))
					{
						worldSave = (WorldSave)new XmlSerializer(typeof(WorldSave)).Deserialize(stream);
					}
					WorldSaveData worldData = new WorldSaveData(worldSave.currentDay, worldSave.worldSeed, worldSave.time, worldSave.totalTime, 0f, 0f, 0, new List<int>());
					bool isBoatMarked = false;
					bool isBoatFound = false;
					bool isBoatFinished = false;
					bool areGemsMarked = false;
					switch (worldSave.boatStatus)
					{
					case 1:
						isBoatFound = true;
						break;
					case 2:
						isBoatFound = true;
						areGemsMarked = true;
						break;
					case 3:
						isBoatFound = true;
						areGemsMarked = true;
						isBoatFinished = true;
						break;
					}
					BoatSaveData boatData = new BoatSaveData(isBoatMarked, isBoatFound, isBoatFinished, areGemsMarked, worldSave.repairs);
					Dictionary<string, SavedPlayer> clientPlayers = new Dictionary<string, SavedPlayer>();
					PlayerSaveData playerData = new PlayerSaveData(new SavedPlayer(worldSave.health, worldSave.maxHealth, worldSave.stamina, worldSave.maxStamina, worldSave.shield, worldSave.maxShield, worldSave.hunger, worldSave.maxHunger, worldSave.draculaHpIncrease, Position.FromFloats(worldSave.position), worldSave.powerups.ToList(), worldSave.armor.ToList(), worldSave.softUnlocks.ToList(), new List<bool>(), new List<bool>(), new IdAmount(worldSave.arrows.Item1, worldSave.arrows.Item2), worldSave.inventory.Select((SerializableTuple<int, int> x) => new IdAmount(x.Item1, x.Item2)).ToList()), clientPlayers);
					ContainerSaveData containerData = new ContainerSaveData(ConvertContainers(worldSave.chests), ConvertContainers(worldSave.furnaces), ConvertContainers(worldSave.cauldrons));
					EntitySaveData entityData = new EntitySaveData(worldSave.builds.Select((BuildWrapper x) => new SavedBuild(x.itemId, Position.FromFloats(x.position), x.rotation)).ToList(), worldSave.mobs.Select((MobWrapper x) => new SavedMob(x.mobType, x.bossType, x.guardianType, x.multiplier, x.bossMultiplier, Position.FromFloats(x.position))).ToList(), worldSave.droppedItems.Select((DroppedItemWrapper x) => new SavedDroppedItem(new IdAmount(x.itemId, x.amount), Position.FromFloats(x.position))).ToList());
					BaseGameSaveData baseGameSaveData = new BaseGameSaveData(worldData, boatData, playerData, containerData, entityData);
					XDocument xDocument = new XDocument();
					XElement xElement = new XElement("MuckSaveGame");
					xDocument.Add(xElement);
					XElement xElement2 = xElement.AddElement("Data");
					xElement2.SetAttributeValue("type", BaseGameManager.Name);
					baseGameSaveData.SaveXml(xElement2);
					using (FileStream output = new FileStream(item + "save", FileMode.Create, FileAccess.Write))
					{
						using XmlWriter writer = XmlWriter.Create(output, Plugin.XmlWriterSettings);
						xDocument.Save(writer);
					}
					Plugin.Log.LogInfo((object)"Legacy save migrated successfully!");
					flag = true;
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("Failed to migrate legacy save: " + ex.ToString()));
				}
				if (flag)
				{
					try
					{
						File.Delete(item);
					}
					catch (Exception ex2)
					{
						Plugin.Log.LogError((object)("Failed to delete legacy save: " + ex2.ToString()));
					}
				}
			}
		}

		private static List<SavedContainer> ConvertContainers(List<ChestWrapper> chests)
		{
			List<SavedContainer> list = new List<SavedContainer>(chests.Count);
			foreach (ChestWrapper chest in chests)
			{
				list.Add(new SavedContainer(chest.chestSize, Position.FromFloats(chest.position), chest.rotation, chest.cells.Select((SerializableTuple<int, int, int> x) => new CellIdAmount(x.Item3, x.Item1, x.Item2)).ToList()));
			}
			return list;
		}
	}
	[HarmonyPatch]
	public class UIManager
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static UnityAction <>9__12_0;

			public static UnityAction <>9__12_1;

			public static UnityAction <>9__12_2;

			public static UnityAction <>9__12_3;

			public static UnityAction <>9__12_5;

			public static UnityAction <>9__12_6;

			public static UnityAction <>9__12_4;

			public static Func<PlayerManager, bool> <>9__13_1;

			public static UnityAction <>9__13_0;

			internal void <Postfix>b__12_0()
			{
				GameObject? verifyDelete = UIManager.verifyDelete;
				if (verifyDelete != null)
				{
					verifyDelete.SetActive(true);
				}
				GameObject? backgroundDarkGUI = UIManager.backgroundDarkGUI;
				if (backgroundDarkGUI != null)
				{
					backgroundDarkGUI.SetActive(true);
				}
			}

			internal void <Postfix>b__12_1()
			{
				buttonExtraGUI.SetActive(false);
			}

			internal void <Postfix>b__12_2()
			{
				if (curEditSave != null)
				{
					string pathForFileName = SaveSystem.GetPathForFileName(curEditSave);
					if (File.Exists(pathForFileName))
					{
						try
						{
							File.Delete(pathForFileName);
						}
						catch (Exception ex)
						{
							Plugin.Log.LogError((object)("Failed to delete save: " + ex.ToString()));
							return;
						}
					}
					Plugin.Log.LogInfo((object)"Save Deleted!");
					if (saveButtons.TryGetValue(curEditSave, out SaveButton value))
					{
						Object.Destroy((Object)(object)((Component)value).gameObject);
						saveButtons.Remove(curEditSave);
					}
					if (LoadManager.selectedSavePath == pathForFileName)
					{
						LoadManager.selectedSavePath = null;
					}
				}
				buttonExtraGUI.SetActive(false);
				backgroundDarkGUI.SetActive(false);
				verifyDelete.SetActive(false);
			}

			internal void <Postfix>b__12_3()
			{
				buttonExtraGUI.SetActive(false);
				backgroundDarkGUI.SetActive(false);
				verifyDelete.SetActive(false);
			}

			internal void <Postfix>b__12_5()
			{
				LoadManager.selectedSavePath = null;
				selectionGUI.SetActive(false);
			}

			internal void <Postfix>b__12_6()
			{
				selectionGUI.SetActive(false);
			}

			internal void <Postfix>b__12_4()
			{
				Plugin.Log.LogInfo((object)"LOAD SAVE BUTTON CLICKED");
				selectionGUI.SetActive(!selectionGUI.activeSelf);
			}

			internal void <UpdatePauseUI>b__13_0()
			{
				Plugin.Log.LogInfo((object)"SAVE BUTTON CLICKED");
				if (GameManager.players.Values.All((PlayerManager x) => x.dead))
				{
					ChatBox.Instance.AppendMessage(-1, string.Concat("<color=#FF0000>Everybody is dead! There's no saving you now."), "");
				}
				else if (DateTime.Now <= canSaveAfter)
				{
					int num = (int)(canSaveAfter - DateTime.Now).TotalSeconds;
					ChatBox.Instance.AppendMessage(-1, "<color=#FF0000>Can't save for another " + num + " seconds", "");
				}
				else
				{
					World.Save();
					canSaveAfter = DateTime.Now + Plugin.SaveCooldown;
				}
			}

			internal bool <UpdatePauseUI>b__13_1(PlayerManager x)
			{
				return x.dead;
			}
		}

		private static bool uiUpdated = false;

		private static bool pauseUIUpdated = false;

		private static bool serverHost = false;

		public static DateTime canSaveAfter = DateTime.MinValue;

		public static Texture? backgroundImage;

		internal static GameObject? selectionGUI;

		internal static GameObject? buttonExtraGUI;

		internal static GameObject? verifyDelete;

		internal static GameObject? backgroundDarkGUI;

		internal static Dictionary<string, SaveButton> saveButtons = new Dictionary<string, SaveButton>();

		internal static string? curEditSave;

		public static bool useAutoSave = false;

		[HarmonyPatch(typeof(MenuUI), "JoinLobby")]
		public static void Postfix(MenuUI __instance)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Expected O, but got Unknown
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Expected O, but got Unknown
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Expected O, but got Unknown
			//IL_0357: Unknown result type (might be due to invalid IL or missing references)
			//IL_0361: Expected O, but got Unknown
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_0328: Expected O, but got Unknown
			//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e1: Expected O, but got Unknown
			//IL_0400: Unknown result type (might be due to invalid IL or missing references)
			//IL_0420: Unknown result type (might be due to invalid IL or missing references)
			//IL_043c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0441: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c4: Expected O, but got Unknown
			//IL_04e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0526: Unknown result type (might be due to invalid IL or missing references)
			//IL_055c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0561: Unknown result type (might be due to invalid IL or missing references)
			//IL_057d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0587: Expected O, but got Unknown
			//IL_05d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_060d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0619: Unknown result type (might be due to invalid IL or missing references)
			//IL_0633: Unknown result type (might be due to invalid IL or missing references)
			//IL_0667: Unknown result type (might be due to invalid IL or missing references)
			//IL_0671: Expected O, but got Unknown
			//IL_037b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0380: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Expected O, but got Unknown
			//IL_06c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_06cf: Expected O, but got Unknown
			//IL_068b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0690: Unknown result type (might be due to invalid IL or missing references)
			//IL_0696: Expected O, but got Unknown
			//IL_0752: Unknown result type (might be due to invalid IL or missing references)
			//IL_0758: Expected O, but got Unknown
			//IL_0773: Unknown result type (might be due to invalid IL or missing references)
			//IL_079d: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e7: Expected O, but got Unknown
			//IL_0802: Unknown result type (might be due to invalid IL or missing references)
			//IL_0828: Unknown result type (might be due to invalid IL or missing references)
			//IL_0878: Unknown result type (might be due to invalid IL or missing references)
			//IL_087e: Expected O, but got Unknown
			//IL_0899: Unknown result type (might be due to invalid IL or missing references)
			//IL_08ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_08ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_08d8: Expected O, but got Unknown
			//IL_06e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f4: Expected O, but got Unknown
			//IL_0a47: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a51: Expected O, but got Unknown
			//IL_0a6a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a6f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a75: Expected O, but got Unknown
			//IL_0ab5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0abf: Expected O, but got Unknown
			//IL_0ad8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0add: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ae3: Expected O, but got Unknown
			//IL_0979: Unknown result type (might be due to invalid IL or missing references)
			//IL_0983: Expected O, but got Unknown
			//IL_0958: Unknown result type (might be due to invalid IL or missing references)
			//IL_09eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_09f5: Expected O, but got Unknown
			//IL_0a0e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a13: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a19: Expected O, but got Unknown
			if (uiUpdated || !serverHost)
			{
				return;
			}
			Vector2 sizeDelta = default(Vector2);
			((Vector2)(ref sizeDelta))..ctor(500f, 750f);
			GameObject.Find("LobbyDetails").GetComponent<RectTransform>().sizeDelta = new Vector2(250f, 408f);
			selectionGUI = new GameObject("selectionGUI", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(RawImage)
			});
			((Transform)selectionGUI.GetComponent<RectTransform>()).position = new Vector3((float)(Screen.width / 2), (float)(Screen.height / 2), 0f);
			selectionGUI.layer = 5;
			selectionGUI.transform.parent = __instance.lobbyUi.transform;
			selectionGUI.GetComponent<RectTransform>().sizeDelta = sizeDelta;
			selectionGUI.GetComponent<RawImage>().texture = backgroundImage;
			((Graphic)selectionGUI.GetComponent<RawImage>()).color = Color32.op_Implicit(new Color32((byte)137, (byte)104, (byte)61, byte.MaxValue));
			buttonExtraGUI = new GameObject("buttonExtraGUI", new Type[4]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(RawImage),
				typeof(VerticalLayoutGroup)
			});
			((Transform)buttonExtraGUI.GetComponent<RectTransform>()).position = new Vector3((float)(Screen.width / 2), (float)(Screen.height / 2), 0f);
			buttonExtraGUI.layer = 5;
			buttonExtraGUI.transform.parent = __instance.lobbyUi.transform;
			buttonExtraGUI.GetComponent<RectTransform>().sizeDelta = new Vector2(400f, 250f);
			buttonExtraGUI.GetComponent<RawImage>().texture = backgroundImage;
			((Graphic)buttonExtraGUI.GetComponent<RawImage>()).color = Color32.op_Implicit(new Color32((byte)137, (byte)104, (byte)61, byte.MaxValue));
			((LayoutGroup)buttonExtraGUI.GetComponent<VerticalLayoutGroup>()).padding = new RectOffset(15, 15, 15, 15);
			((HorizontalOrVerticalLayoutGroup)buttonExtraGUI.GetComponent<VerticalLayoutGroup>()).spacing = 2f;
			((LayoutGroup)buttonExtraGUI.GetComponent<VerticalLayoutGroup>()).childAlignment = (TextAnchor)1;
			((HorizontalOrVerticalLayoutGroup)buttonExtraGUI.GetComponent<VerticalLayoutGroup>()).childControlWidth = true;
			GameObject val = new GameObject("saveText", new Type[1] { typeof(TextMeshProUGUI) });
			val.transform.parent = buttonExtraGUI.transform;
			((TMP_Text)val.GetComponent<TextMeshProUGUI>()).fontSize = 35f;
			((TMP_Text)val.GetComponent<TextMeshProUGUI>()).fontStyle = (FontStyles)1;
			((Graphic)val.GetComponent<TextMeshProUGUI>()).color = new Color(0f, 0f, 0f, 1f);
			((TMP_Text)val.GetComponent<TextMeshProUGUI>()).alignment = (TextAlignmentOptions)514;
			Button component = Object.Instantiate<GameObject>(__instance.startBtn, buttonExtraGUI.transform).GetComponent<Button>();
			component.onClick = new ButtonClickedEvent();
			ButtonClickedEvent onClick = component.onClick;
			object obj = <>c.<>9__12_0;
			if (obj == null)
			{
				UnityAction val2 = delegate
				{
					GameObject? obj8 = verifyDelete;
					if (obj8 != null)
					{
						obj8.SetActive(true);
					}
					GameObject? obj9 = backgroundDarkGUI;
					if (obj9 != null)
					{
						obj9.SetActive(true);
					}
				};
				<>c.<>9__12_0 = val2;
				obj = (object)val2;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
			((TMP_Text)((Component)component).GetComponentInChildren<TextMeshProUGUI>()).text = "Delete";
			Button component2 = Object.Instantiate<GameObject>(__instance.startBtn, buttonExtraGUI.transform).GetComponent<Button>();
			component2.onClick = new ButtonClickedEvent();
			ButtonClickedEvent onClick2 = component2.onClick;
			object obj2 = <>c.<>9__12_1;
			if (obj2 == null)
			{
				UnityAction val3 = delegate
				{
					buttonExtraGUI.SetActive(false);
				};
				<>c.<>9__12_1 = val3;
				obj2 = (object)val3;
			}
			((UnityEvent)onClick2).AddListener((UnityAction)obj2);
			((TMP_Text)((Component)component2).GetComponentInChildren<TextMeshProUGUI>()).text = "Close";
			buttonExtraGUI.SetActive(false);
			backgroundDarkGUI = new GameObject("backgroundDark", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(RawImage)
			});
			((Transform)backgroundDarkGUI.GetComponent<RectTransform>()).position = new Vector3((float)(Screen.width / 2), (float)(Screen.height / 2), 0f);
			backgroundDarkGUI.GetComponent<RectTransform>().sizeDelta = new Vector2((float)Screen.width, (float)Screen.height);
			((Graphic)backgroundDarkGUI.GetComponent<RawImage>()).color = Color32.op_Implicit(new Color32((byte)0, (byte)0, (byte)0, (byte)150));
			backgroundDarkGUI.layer = 5;
			backgroundDarkGUI.transform.parent = __instance.lobbyUi.transform;
			backgroundDarkGUI.SetActive(false);
			verifyDelete = new GameObject("verifyDelete", new Type[4]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(RawImage),
				typeof(VerticalLayoutGroup)
			});
			((Transform)verifyDelete.GetComponent<RectTransform>()).position = new Vector3((float)(Screen.width / 2), (float)(Screen.height / 2), 0f);
			verifyDelete.layer = 5;
			verifyDelete.transform.parent = __instance.lobbyUi.transform;
			verifyDelete.GetComponent<RectTransform>().sizeDelta = new Vector2(400f, 250f);
			verifyDelete.GetComponent<RawImage>().texture = backgroundImage;
			((Graphic)verifyDelete.GetComponent<RawImage>()).color = Color32.op_Implicit(new Color32((byte)137, (byte)104, (byte)61, byte.MaxValue));
			((LayoutGroup)verifyDelete.GetComponent<VerticalLayoutGroup>()).padding = new RectOffset(15, 15, 15, 15);
			((HorizontalOrVerticalLayoutGroup)verifyDelete.GetComponent<VerticalLayoutGroup>()).spacing = 2f;
			((LayoutGroup)verifyDelete.GetComponent<VerticalLayoutGroup>()).childAlignment = (TextAnchor)1;
			((HorizontalOrVerticalLayoutGroup)verifyDelete.GetComponent<VerticalLayoutGroup>()).childControlWidth = true;
			GameObject val4 = new GameObject("deleteText", new Type[1] { typeof(TextMeshProUGUI) });
			val4.transform.parent = verifyDelete.transform;
			((TMP_Text)val4.GetComponent<TextMeshProUGUI>()).text = "Are you sure?";
			((TMP_Text)val4.GetComponent<TextMeshProUGUI>()).fontSize = 35f;
			((TMP_Text)val4.GetComponent<TextMeshProUGUI>()).fontStyle = (FontStyles)1;
			((Graphic)val4.GetComponent<TextMeshProUGUI>()).color = new Color(0f, 0f, 0f, 1f);
			((TMP_Text)val4.GetComponent<TextMeshProUGUI>()).alignment = (TextAlignmentOptions)514;
			Button component3 = Object.Instantiate<GameObject>(__instance.startBtn, verifyDelete.transform).GetComponent<Button>();
			component3.onClick = new ButtonClickedEvent();
			ButtonClickedEvent onClick3 = component3.onClick;
			object obj3 = <>c.<>9__12_2;
			if (obj3 == null)
			{
				UnityAction val5 = delegate
				{
					if (curEditSave != null)
					{
						string pathForFileName = SaveSystem.GetPathForFileName(curEditSave);
						if (File.Exists(pathForFileName))
						{
							try
							{
								File.Delete(pathForFileName);
							}
							catch (Exception ex)
							{
								Plugin.Log.LogError((object)("Failed to delete save: " + ex.ToString()));
								return;
							}
						}
						Plugin.Log.LogInfo((object)"Save Deleted!");
						if (saveButtons.TryGetValue(curEditSave, out SaveButton value))
						{
							Object.Destroy((Object)(object)((Component)value).gameObject);
							saveButtons.Remove(curEditSave);
						}
						if (LoadManager.selectedSavePath == pathForFileName)
						{
							LoadManager.selectedSavePath = null;
						}
					}
					buttonExtraGUI.SetActive(false);
					backgroundDarkGUI.SetActive(false);
					verifyDelete.SetActive(false);
				};
				<>c.<>9__12_2 = val5;
				obj3 = (object)val5;
			}
			((UnityEvent)onClick3).AddListener((UnityAction)obj3);
			((TMP_Text)((Component)component3).GetComponentInChildren<TextMeshProUGUI>()).text = "Yes";
			Button component4 = Object.Instantiate<GameObject>(__instance.startBtn, verifyDelete.transform).GetComponent<Button>();
			component4.onClick = new ButtonClickedEvent();
			ButtonClickedEvent onClick4 = component4.onClick;
			object obj4 = <>c.<>9__12_3;
			if (obj4 == null)
			{
				UnityAction val6 = delegate
				{
					buttonExtraGUI.SetActive(false);
					backgroundDarkGUI.SetActive(false);
					verifyDelete.SetActive(false);
				};
				<>c.<>9__12_3 = val6;
				obj4 = (object)val6;
			}
			((UnityEvent)onClick4).AddListener((UnityAction)obj4);
			((TMP_Text)((Component)component4).GetComponentInChildren<TextMeshProUGUI>()).text = "No";
			verifyDelete.SetActive(false);
			GameObject val7 = new GameObject("maskRect", new Type[4]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(RawImage),
				typeof(Mask)
			});
			((Transform)val7.GetComponent<RectTransform>()).position = new Vector3((float)(Screen.width / 2), (float)(Screen.height / 2), 0f);
			val7.transform.parent = selectionGUI.transform;
			val7.GetComponent<Mask>().rectTransform.sizeDelta = sizeDelta;
			val7.GetComponent<Mask>().showMaskGraphic = false;
			GameObject val8 = new GameObject("scrollGUI", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(ScrollRect)
			});
			((Transform)val8.GetComponent<RectTransform>()).position = new Vector3((float)(Screen.width / 2), (float)(Screen.height / 2), 0f);
			val8.transform.parent = val7.transform;
			((Component)val8.GetComponent<ScrollRect>()).GetComponent<RectTransform>().sizeDelta = sizeDelta;
			val8.GetComponent<ScrollRect>().horizontal = false;
			val8.GetComponent<ScrollRect>().movementType = (MovementType)1;
			GameObject val9 = new GameObject("scrollContent", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(VerticalLayoutGroup)
			});
			((Transform)val9.GetComponent<RectTransform>()).position = new Vector3((float)(Screen.width / 2), (float)(Screen.height / 2), 0f);
			val9.transform.parent = val8.transform;
			val9.GetComponent<RectTransform>().sizeDelta = sizeDelta;
			((LayoutGroup)val9.GetComponent<VerticalLayoutGroup>()).padding = new RectOffset(15, 15, 15, 15);
			((HorizontalOrVerticalLayoutGroup)val9.GetComponent<VerticalLayoutGroup>()).spacing = 2f;
			((LayoutGroup)val9.GetComponent<VerticalLayoutGroup>()).childAlignment = (TextAnchor)1;
			((HorizontalOrVerticalLayoutGroup)val9.GetComponent<VerticalLayoutGroup>()).childControlWidth = true;
			val8.GetComponent<ScrollRect>().content = val9.GetComponent<RectTransform>();
			List<string> allSaves = SaveSystem.GetAllSaves();
			if (allSaves.Count > 0)
			{
				int num = 0;
				foreach (string item in allSaves)
				{
					if (num > 8)
					{
						val9.GetComponent<RectTransform>().sizeDelta = new Vector2(500f, (float)(750 + num * 30));
					}
					Button component5 = Object.Instantiate<GameObject>(__instance.startBtn, val9.transform).GetComponent<Button>();
					component5.onClick = new ButtonClickedEvent();
					((Component)component5).gameObject.AddComponent<SaveButton>();
					((TMP_Text)((Component)component5).GetComponentInChildren<TextMeshProUGUI>()).text = Path.GetFileName(item);
					num++;
				}
				Button component6 = Object.Instantiate<GameObject>(__instance.startBtn, ((Component)val9.transform).transform).GetComponent<Button>();
				((TMP_Text)((Component)component6).GetComponentInChildren<TextMeshProUGUI>()).text = "None";
				component6.onClick = new ButtonClickedEvent();
				ButtonClickedEvent onClick5 = component6.onClick;
				object obj5 = <>c.<>9__12_5;
				if (obj5 == null)
				{
					UnityAction val10 = delegate
					{
						LoadManager.selectedSavePath = null;
						selectionGUI.SetActive(false);
					};
					<>c.<>9__12_5 = val10;
					obj5 = (object)val10;
				}
				((UnityEvent)onClick5).AddListener((UnityAction)obj5);
			}
			else
			{
				Button component7 = Object.Instantiate<GameObject>(__instance.startBtn, val9.transform).GetComponent<Button>();
				((TMP_Text)((Component)component7).GetComponentInChildren<TextMeshProUGUI>()).text = "No Saves :(";
				component7.onClick = new ButtonClickedEvent();
				ButtonClickedEvent onClick6 = component7.onClick;
				object obj6 = <>c.<>9__12_6;
				if (obj6 == null)
				{
					UnityAction val11 = delegate
					{
						selectionGUI.SetActive(false);
					};
					<>c.<>9__12_6 = val11;
					obj6 = (object)val11;
				}
				((UnityEvent)onClick6).AddListener((UnityAction)obj6);
			}
			selectionGUI.SetActive(false);
			Button component8 = Object.Instantiate<GameObject>(__instance.startBtn, GameObject.Find("LobbyDetails").transform).GetComponent<Button>();
			((TMP_Text)((Component)component8).GetComponentInChildren<TextMeshProUGUI>()).text = "Load Save";
			component8.onClick = new ButtonClickedEvent();
			ButtonClickedEvent onClick7 = component8.onClick;
			object obj7 = <>c.<>9__12_4;
			if (obj7 == null)
			{
				UnityAction val12 = delegate
				{
					Plugin.Log.LogInfo((object)"LOAD SAVE BUTTON CLICKED");
					selectionGUI.SetActive(!selectionGUI.activeSelf);
				};
				<>c.<>9__12_4 = val12;
				obj7 = (object)val12;
			}
			((UnityEvent)onClick7).AddListener((UnityAction)obj7);
			uiUpdated = true;
		}

		[HarmonyPatch(typeof(OtherInput), "Pause")]
		[HarmonyPostfix]
		private static void UpdatePauseUI()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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
			if (pauseUIUpdated)
			{
				return;
			}
			Button component = Object.Instantiate<GameObject>(GameObject.Find("ResumeBtn"), GameObject.Find("PauseUI").transform).GetComponent<Button>();
			((Component)component).gameObject.transform.SetSiblingIndex(2);
			((TMP_Text)((Component)component).GetComponentInChildren<TextMeshProUGUI>()).text = "Save";
			component.onClick = new ButtonClickedEvent();
			ButtonClickedEvent onClick = component.onClick;
			object obj = <>c.<>9__13_0;
			if (obj == null)
			{
				UnityAction val = delegate
				{
					Plugin.Log.LogInfo((object)"SAVE BUTTON CLICKED");
					if (GameManager.players.Values.All((PlayerManager x) => x.dead))
					{
						ChatBox.Instance.AppendMessage(-1, string.Concat("<color=#FF0000>Everybody is dead! There's no saving you now."), "");
					}
					else if (DateTime.Now <= canSaveAfter)
					{
						int num = (int)(canSaveAfter - DateTime.Now).TotalSeconds;
						ChatBox.Instance.AppendMessage(-1, "<color=#FF0000>Can't save for another " + num + " seconds", "");
					}
					else
					{
						World.Save();
						canSaveAfter = DateTime.Now + Plugin.SaveCooldown;
					}
				};
				<>c.<>9__13_0 = val;
				obj = (object)val;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
			pauseUIUpdated = true;
		}

		[HarmonyPatch(typeof(MenuUI), "StartLobby")]
		[HarmonyPrefix]
		private static void SetHost()
		{
			serverHost = true;
		}

		[HarmonyPatch(typeof(MenuUI), "Start")]
		private static void Prefix()
		{
			saveButtons.Clear();
			pauseUIUpdated = false;
			uiUpdated = false;
			serverHost = false;
		}

		[HarmonyPatch(typeof(Settings), "Start")]
		[HarmonyPostfix]
		private static void UpdateSettings(Settings __instance)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			if (PlayerPrefs.HasKey("autosave"))
			{
				useAutoSave = Convert.ToBoolean(PlayerPrefs.GetInt("autosave"));
			}
			GameObject autoSave = Object.Instantiate<GameObject>(((Component)__instance.tutorial).gameObject, ((Component)__instance.tutorial).transform.parent);
			((TMP_Text)autoSave.GetComponentInChildren<TextMeshProUGUI>()).text = "Auto Save";
			autoSave.GetComponentInChildren<MyBoolSetting>().SetSetting(useAutoSave);
			autoSave.GetComponentInChildren<Button>().onClick = new ButtonClickedEvent();
			((UnityEvent)autoSave.GetComponentInChildren<Button>().onClick).AddListener((UnityAction)delegate
			{
				useAutoSave = !useAutoSave;
				autoSave.GetComponentInChildren<MyBoolSetting>().SetSetting(useAutoSave);
				PlayerPrefs.SetInt("autosave", Convert.ToInt32(useAutoSave));
			});
		}
	}
	[HarmonyPatch]
	public static class World
	{
		public static bool doSave = false;

		public static int worldSeed;

		internal static Dictionary<int, SavedBuild> builds = new Dictionary<int, SavedBuild>();

		public static bool isBoatMarked = false;

		public static bool isBoatFound = false;

		public static bool isBoatFinished = false;

		public static bool areGemsMarked = false;

		public static bool isLeavingIsland = false;

		public static int chest;

		public static int furnace;

		public static int cauldron;

		[HarmonyPatch(typeof(ItemManager), "InitAllItems")]
		[HarmonyPostfix]
		private static void GetBuildIds()
		{
			chest = ItemManager.Instance.GetItemByName("Chest").id;
			furnace = ItemManager.Instance.GetItemByName("Furnace").id;
			cauldron = ItemManager.Instance.GetItemByName("Cauldron").id;
		}

		[HarmonyPatch(typeof(SteamLobby), "FindSeed")]
		private static void Postfix(ref int __result)
		{
			worldSeed = __result;
		}

		[HarmonyPatch(typeof(GameLoop), "NewDay")]
		private static void Postfix(int day)
		{
			if (UIManager.useAutoSave)
			{
				Plugin.Log.LogInfo((object)("Day " + day));
				if (day == 0 || !doSave)
				{
					Plugin.Log.LogInfo((object)"DO NOT SAVE");
				}
				else
				{
					Save();
				}
			}
		}

		public static void Save()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if (LocalClient.serverOwner && LoadManager.selectedSavePath != "")
			{
				ClientSend.SendChatMessage("<color=#ADD8E6>Saving...");
				ChatBox.Instance.AppendMessage(-1, "<color=#ADD8E6>Saving...", "");
				Plu