Decompiled source of SeidrChest v0.1.13

SeidrChest.dll

Decompiled 3 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.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("SeidrChest")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SeidrChest")]
[assembly: AssemblyCopyright("Copyright ©  2022")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("9f8a1b6e-6d0e-4dab-bbd8-9ed433836544")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace neobotics.ValheimMods;

internal class CustomDataWrapper
{
	private Dictionary<string, string> playerData;

	private CustomDataWrapper instance;

	private Dictionary<string, string> Data { get; set; }

	public CustomDataWrapper(Dictionary<string, string> sourceData, string keyPrefix)
	{
		CustomDataWrapper customDataWrapper = this;
		playerData = sourceData;
		Data = new Dictionary<string, string>();
		sourceData.Keys.ToList().ForEach(delegate(string key)
		{
			if (key.StartsWith(keyPrefix))
			{
				customDataWrapper.Data.Add(key, sourceData[key]);
			}
		});
	}

	public void Add(string key, string value)
	{
		Data.Add(key, value);
		playerData.Add(key, value);
	}

	public bool Remove(string key)
	{
		return Data.Remove(key) & playerData.Remove(key);
	}

	public void Set(string key, string value)
	{
		if (Data.ContainsKey(key))
		{
			Data[key] = value;
		}
		else
		{
			Data.Add(key, value);
		}
		if (playerData.ContainsKey(key))
		{
			playerData[key] = value;
		}
		else
		{
			playerData.Add(key, value);
		}
	}

	public string Get(string key)
	{
		if (Data.ContainsKey(key))
		{
			return Data[key];
		}
		return null;
	}

	public bool ContainsKey(string key)
	{
		return Data.ContainsKey(key);
	}

	public void PreSaveSync()
	{
		foreach (KeyValuePair<string, string> datum in Data)
		{
			if (!playerData.ContainsKey(datum.Key))
			{
				playerData.Add(datum.Key, datum.Value);
			}
		}
	}
}
internal class DebugUtils
{
	public static void ObjectInspector(object o)
	{
		if (o == null)
		{
			Debug.Log((object)"Object is null");
			return;
		}
		BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
		Type type = o.GetType();
		Debug.Log((object)(o.ToString() + " Type " + type.Name));
		PropertyInfo[] properties = type.GetProperties(bindingAttr);
		foreach (PropertyInfo propertyInfo in properties)
		{
			Debug.Log((object)$"{type.Name}.{propertyInfo.Name} = {propertyInfo.GetValue(o)}");
		}
		FieldInfo[] fields = type.GetFields(bindingAttr);
		foreach (FieldInfo field in fields)
		{
			FieldPrinter(o, type, field);
		}
	}

	public static void MethodInspector(object o)
	{
		if (o == null)
		{
			Debug.Log((object)"Object is null");
			return;
		}
		BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
		Type type = o.GetType();
		Debug.Log((object)(o.ToString() + " Type " + type.Name));
		MethodInfo[] methods = type.GetMethods(bindingAttr);
		foreach (MethodInfo methodInfo in methods)
		{
			methodInfo.GetParameters();
			string arg = string.Join(", ", (from x in methodInfo.GetParameters()
				select x.ParameterType?.ToString() + " " + x.Name).ToArray());
			Debug.Log((object)$"{methodInfo.ReturnType} {methodInfo.Name} ({arg})");
		}
	}

	private static void ItemDataInspector(ItemData item)
	{
		ObjectInspector(item);
		ObjectInspector(item.m_shared);
	}

	private static void FieldPrinter(object o, Type t, FieldInfo field)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Expected O, but got Unknown
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Expected O, but got Unknown
		try
		{
			if (field.FieldType == typeof(ItemData))
			{
				ItemData val = (ItemData)field.GetValue(o);
				if (val != null)
				{
					ItemDataInspector(val);
				}
				else
				{
					Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]");
				}
			}
			else if (field.FieldType == typeof(Transform))
			{
				Transform val2 = (Transform)field.GetValue(o);
				if ((Object)(object)val2 != (Object)null)
				{
					Debug.Log((object)("\tTransform.parent = " + ((Object)val2.parent).name));
				}
				else
				{
					Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]");
				}
			}
			else if (field.FieldType == typeof(EffectList))
			{
				EffectList val3 = (EffectList)field.GetValue(o);
				if (val3 != null)
				{
					Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)}:");
					EffectData[] effectPrefabs = val3.m_effectPrefabs;
					foreach (EffectData val4 in effectPrefabs)
					{
						Debug.Log((object)("\tEffectData.m_prefab = " + ((Object)val4.m_prefab).name));
					}
				}
				else
				{
					Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]");
				}
			}
			else
			{
				Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)}");
			}
		}
		catch (Exception)
		{
			Debug.Log((object)("Exception accessing " + t?.Name + "." + field?.Name));
		}
	}

	public static void GameObjectInspector(GameObject go)
	{
		Debug.Log((object)("\n\nInspecting GameObject " + ((Object)go).name));
		ObjectInspector(go);
		Component[] componentsInChildren = go.GetComponentsInChildren<Component>();
		foreach (Component val in componentsInChildren)
		{
			try
			{
				string obj = ((val != null) ? ((Object)val).name : null);
				object obj2;
				if (val == null)
				{
					obj2 = null;
				}
				else
				{
					Transform transform = val.transform;
					if (transform == null)
					{
						obj2 = null;
					}
					else
					{
						Transform parent = transform.parent;
						obj2 = ((parent != null) ? ((Object)parent).name : null);
					}
				}
				Debug.Log((object)("\n\nInspecting Component " + obj + " with parent " + (string?)obj2));
				ObjectInspector(val);
			}
			catch (Exception)
			{
			}
		}
	}

	public static void ComponentInspector(Component c)
	{
		Debug.Log((object)("\n\nInspecting Component " + ((Object)c).name));
		ObjectInspector(c);
	}

	public static void EffectsInspector(EffectList e)
	{
		EffectData[] effectPrefabs = e.m_effectPrefabs;
		Debug.Log((object)$"Effect list has effects {e.HasEffects()} count {effectPrefabs.Length}");
		EffectData[] array = effectPrefabs;
		foreach (EffectData val in array)
		{
			Debug.Log((object)$"Effect Data {val} prefab name {((Object)val.m_prefab).name} prefab GameObject name {((Object)val.m_prefab.gameObject).name}");
		}
	}

	public static void PrintInventory()
	{
		foreach (ItemData allItem in ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems())
		{
			Debug.Log((object)allItem.m_shared.m_name);
		}
	}

	public static void PrintAllObjects()
	{
		ZNetScene.instance.m_prefabs.ForEach(delegate(GameObject x)
		{
			Debug.Log((object)("GameObject " + ((Object)x).name));
		});
	}

	public static void PrintAllCharacters()
	{
		Character.GetAllCharacters().ForEach(delegate(Character x)
		{
			Debug.Log((object)("Character " + ((Object)x).name));
		});
	}
}
public class DelegatedConfigEntry<T> : DelegatedConfigEntryBase
{
	private ConfigEntry<T> _entry;

	private EventHandler rootHandler;

	private Action<object, EventArgs> clientDelegate;

	private Logging Log;

	public ConfigEntry<T> ConfigEntry
	{
		get
		{
			return _entry;
		}
		set
		{
			_entry = value;
			if (_entry != null && rootHandler != null)
			{
				_entry.SettingChanged += rootHandler;
			}
			Name = ((ConfigEntryBase)_entry).Definition.Key;
			Section = ((ConfigEntryBase)_entry).Definition.Section;
			ServerValue = ((ConfigEntryBase)_entry).GetSerializedValue();
			Log.Trace("Set " + Section + " " + Name + " to serialized value " + ServerValue);
		}
	}

	public T Value
	{
		get
		{
			return _entry.Value;
		}
		set
		{
			_entry.Value = value;
		}
	}

	public DelegatedConfigEntry(bool useServerDelegate = false)
		: this((Action<object, EventArgs>)null, useServerDelegate)
	{
	}

	public DelegatedConfigEntry(Action<object, EventArgs> delegateHandler, bool useServerDelegate = false)
	{
		Log = Logging.GetLogger();
		Log.Trace("DelegatedConfigEntry");
		if (delegateHandler != null)
		{
			clientDelegate = delegateHandler;
		}
		if (useServerDelegate)
		{
			Log.Trace("Configuring server delegate");
			rootHandler = delegate(object s, EventArgs e)
			{
				ServerDelegate(s, e);
			};
			ServerConfiguration.ServerDelegatedEntries.Add(this);
		}
		else if (clientDelegate != null)
		{
			rootHandler = delegate(object s, EventArgs e)
			{
				clientDelegate(s, e);
			};
		}
	}

	private void ServerDelegate(object sender, EventArgs args)
	{
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Expected O, but got Unknown
		Logging.GetLogger().Trace("ServerDelegate");
		_entry.SettingChanged -= rootHandler;
		ZNet instance = ZNet.instance;
		bool? flag = ((instance != null) ? new bool?(instance.IsServer()) : null);
		if (flag.HasValue)
		{
			if (flag == false)
			{
				if (ServerValue != null)
				{
					((ConfigEntryBase)_entry).SetSerializedValue(ServerValue);
				}
			}
			else
			{
				ServerValue = ((ConfigEntryBase)_entry).GetSerializedValue();
				ServerConfiguration.Instance.SendConfigToAllClients(sender, (SettingChangedEventArgs)args);
			}
		}
		if (clientDelegate != null)
		{
			clientDelegate(sender, args);
		}
		_entry.SettingChanged += rootHandler;
	}

	public void EnableHandler(bool setActive)
	{
		if (setActive)
		{
			_entry.SettingChanged += rootHandler;
		}
		else
		{
			_entry.SettingChanged -= rootHandler;
		}
	}

	public bool IsKeyPressed()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		if (ConfigEntry is ConfigEntry<KeyboardShortcut> val)
		{
			KeyboardShortcut value = val.Value;
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!Input.GetKey(modifier))
				{
					return false;
				}
			}
			if (!Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey))
			{
				return false;
			}
			return true;
		}
		Log.Error("Keyboard read attempted on non-KeyboardShortcut config.");
		return false;
	}

	public bool IsKeyDown()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		if (ConfigEntry is ConfigEntry<KeyboardShortcut> val)
		{
			KeyboardShortcut value = val.Value;
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!Input.GetKey(modifier))
				{
					return false;
				}
			}
			if (!Input.GetKey(((KeyboardShortcut)(ref value)).MainKey))
			{
				return false;
			}
			return true;
		}
		Log.Error("Keyboard read attempted on non-KeyboardShortcut config.");
		return false;
	}

	public bool IsKeyReleased()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		if (ConfigEntry is ConfigEntry<KeyboardShortcut> val)
		{
			KeyboardShortcut value = val.Value;
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!Input.GetKeyUp(modifier))
				{
					return false;
				}
			}
			if (!Input.GetKeyUp(((KeyboardShortcut)(ref value)).MainKey))
			{
				return false;
			}
			return true;
		}
		Log.Error("Keyboard read attempted on non-KeyboardShortcut config.");
		return false;
	}
}
public class DelegatedConfigEntryBase
{
	public string Name;

	public string Section;

	public string ServerValue;
}
public class Logging
{
	public enum LogLevels
	{
		Critical,
		Error,
		Warning,
		Info,
		Debug,
		Trace
	}

	private static Logging _logger;

	public LogLevels LogLevel { get; set; }

	public string ModName { get; set; }

	private Logging(LogLevels level, string name)
	{
		LogLevel = level;
		ModName = name;
	}

	public static Logging GetLogger(LogLevels level, string name)
	{
		if (_logger == null)
		{
			_logger = new Logging(level, name);
		}
		return _logger;
	}

	public static Logging GetLogger()
	{
		if (_logger == null)
		{
			throw new NullReferenceException("Logger not initialized");
		}
		return _logger;
	}

	public void Trace(string msg)
	{
		if (LogLevel >= LogLevels.Trace)
		{
			Debug.Log((object)Message(msg));
		}
	}

	public void Debug(string msg)
	{
		if (LogLevel >= LogLevels.Debug)
		{
			Debug.Log((object)Message(msg));
		}
	}

	public void Info(string msg)
	{
		if (LogLevel >= LogLevels.Info)
		{
			Debug.Log((object)Message(msg));
		}
	}

	public void Warning(string msg)
	{
		if (LogLevel >= LogLevels.Warning)
		{
			Debug.LogWarning((object)Message(msg));
		}
	}

	public void Error(string msg)
	{
		if (LogLevel >= LogLevels.Error)
		{
			Debug.LogWarning((object)Message(msg));
		}
	}

	public void Error(Exception e)
	{
		Error(e, stackTrace: false);
	}

	public void Error(Exception e, bool stackTrace)
	{
		if (LogLevel >= LogLevels.Error)
		{
			Warning(Message(e.Message));
			if (stackTrace)
			{
				Warning(e.StackTrace);
			}
		}
	}

	public void Critical(Exception e)
	{
		if (LogLevel >= LogLevels.Critical)
		{
			Debug(Message(e.Message));
			Error(e.StackTrace);
		}
	}

	private string Message(string msg)
	{
		return ModName + ": " + msg;
	}

	public static void ChangeLogging(object s, EventArgs e)
	{
		SettingChangedEventArgs val = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null);
		GetLogger().Debug($"ChangeLog {val.ChangedSetting.Definition.Key} to {val.ChangedSetting.BoxedValue}");
		GetLogger().LogLevel = Cfg.debugLevel.Value;
	}
}
public class ServerConfiguration
{
	[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
	private static class ZNet_OnNewConnection_Patch
	{
		private static void Postfix(ZNet __instance, ZNetPeer peer)
		{
			Log.Debug("ZNet OnNewConnection postfix");
			if (!__instance.IsServer())
			{
				try
				{
					Log.Debug("Client registered RPC_ClientConfigReceiver");
					peer.m_rpc.Register<ZPackage>("ClientConfigReceiver." + GetPluginGuid(), (Action<ZRpc, ZPackage>)RPC_ClientConfigReceiver);
					return;
				}
				catch (Exception)
				{
					Log.Warning("Failed to register RPC");
					return;
				}
			}
			try
			{
				SendConfigToClient(peer);
			}
			catch (Exception)
			{
				Log.Warning("Error sending server configuration to client");
			}
		}
	}

	public static List<DelegatedConfigEntryBase> ServerDelegatedEntries = new List<DelegatedConfigEntryBase>();

	private static ConfigFile LocalConfig;

	private static BaseUnityPlugin Mod;

	private static string ConfigFileName;

	private static ServerConfiguration _instance;

	private static Logging Log;

	public static bool IsSetup = false;

	private const string NOT_CONFIGURED = "ServerConfiguration not initialized. Setup first.";

	public static ServerConfiguration Instance
	{
		get
		{
			if (_instance == null)
			{
				_instance = new ServerConfiguration();
			}
			return _instance;
		}
	}

	private ServerConfiguration()
	{
	}

	public void Setup(ConfigFile config, BaseUnityPlugin modInstance)
	{
		LocalConfig = config;
		Log = Logging.GetLogger();
		Log.Trace("ServerConfiguration Setup");
		Mod = modInstance;
		ConfigFileName = Path.GetFileName(LocalConfig.ConfigFilePath);
		IsSetup = true;
	}

	public void CreateConfigWatcher()
	{
		string configFilePath = LocalConfig.ConfigFilePath;
		string fileName = Path.GetFileName(LocalConfig.ConfigFilePath);
		Log.Trace("Configuration File Watcher Setup");
		FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(configFilePath.Substring(0, configFilePath.Length - fileName.Length), fileName);
		fileSystemWatcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime;
		fileSystemWatcher.Changed += LoadConfig;
		fileSystemWatcher.Created += LoadConfig;
		fileSystemWatcher.IncludeSubdirectories = false;
		fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
		fileSystemWatcher.EnableRaisingEvents = true;
	}

	private void LoadConfig(object sender, FileSystemEventArgs e)
	{
		if (!File.Exists(LocalConfig.ConfigFilePath))
		{
			return;
		}
		try
		{
			Log.Debug($"Loading configuration {e.ChangeType}");
			LocalConfig.Reload();
		}
		catch
		{
			Log.Error("Error loading configuration file " + ConfigFileName);
		}
	}

	public static string GetPluginGuid()
	{
		return Mod.Info.Metadata.GUID;
	}

	public static void RPC_ClientConfigReceiver(ZRpc zrpc, ZPackage package)
	{
		if (!IsSetup)
		{
			Log.Error("ServerConfiguration not initialized. Setup first.");
			return;
		}
		Log.Debug("ClientConfigReceiver");
		string section;
		string name;
		while (package.GetPos() < package.Size())
		{
			section = package.ReadString();
			name = package.ReadString();
			string text = package.ReadString();
			Log.Trace("Reading " + section + " " + name + " value " + text + " from ZPackage");
			DelegatedConfigEntryBase delegatedConfigEntryBase = ServerDelegatedEntries.Find((DelegatedConfigEntryBase e) => e.Name == name && e.Section == section);
			if (delegatedConfigEntryBase != null)
			{
				Log.Trace("Found DCEB on client and setting to server value " + text);
				delegatedConfigEntryBase.ServerValue = text;
			}
			ConfigEntryBase val = LocalConfig[section, name];
			if (val != null)
			{
				Log.Trace("Found local CEB and setting underlying config value " + text);
				val.SetSerializedValue(text);
			}
		}
	}

	internal static void WriteConfigEntries(ZPackage zpkg)
	{
		foreach (DelegatedConfigEntryBase serverDelegatedEntry in ServerDelegatedEntries)
		{
			Log.Trace("Writing " + serverDelegatedEntry.Section + " " + serverDelegatedEntry.Name + " value " + serverDelegatedEntry.ServerValue + " to ZPackage");
			zpkg.Write(serverDelegatedEntry.Section);
			zpkg.Write(serverDelegatedEntry.Name);
			zpkg.Write(serverDelegatedEntry.ServerValue);
		}
	}

	internal static void SendConfigToClient(ZNetPeer peer)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		if (!IsSetup)
		{
			Log.Error("ServerConfiguration not initialized. Setup first.");
			return;
		}
		Log.Debug("ServerSendConfigToClient");
		ZPackage val = new ZPackage();
		WriteConfigEntries(val);
		peer.m_rpc.Invoke("ClientConfigReceiver." + GetPluginGuid(), new object[1] { val });
	}

	public void SendConfigToAllClients(object o, SettingChangedEventArgs e)
	{
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Expected O, but got Unknown
		if (!IsSetup)
		{
			Log.Error("ServerConfiguration not initialized. Setup first.");
		}
		else if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && ZNet.instance.GetPeerConnections() > 0)
		{
			Log.Debug("SendConfigToAllClients");
			ZPackage zpkg = new ZPackage();
			WriteConfigEntries(zpkg);
			((MonoBehaviour)Mod).StartCoroutine(_instance.Co_BroadcastConfig(zpkg));
		}
	}

	private IEnumerator Co_BroadcastConfig(ZPackage zpkg)
	{
		Log.Debug("Co_BroadcastConfig");
		List<ZNetPeer> connectedPeers = ZNet.instance.GetConnectedPeers();
		foreach (ZNetPeer item in connectedPeers)
		{
			if (item != ZNet.instance.GetServerPeer())
			{
				item.m_rpc.Invoke("ClientConfigReceiver." + GetPluginGuid(), new object[1] { zpkg });
			}
			yield return null;
		}
	}
}
internal class Utils
{
	public static TEnum Guardrails<TEnum>(string value, TEnum enumDefault) where TEnum : struct
	{
		if (Enum.TryParse<TEnum>(value, ignoreCase: true, out var result))
		{
			return result;
		}
		return enumDefault;
	}

	public static int Guardrails(int value, int lbound, int ubound)
	{
		if (value < lbound)
		{
			return lbound;
		}
		if (value > ubound)
		{
			return ubound;
		}
		return value;
	}

	public static float Guardrails(float value, float lbound, float ubound)
	{
		if (value < lbound)
		{
			return lbound;
		}
		if (value > ubound)
		{
			return ubound;
		}
		return value;
	}

	public static string UnClonifiedName(string name)
	{
		if (name == null)
		{
			return null;
		}
		int num = name.IndexOf("(Clone)");
		if (num < 1)
		{
			return name;
		}
		return name.Substring(0, num);
	}

	public static void SetTranslator(int id, string idText)
	{
		typeof(Localization).GetMethod("AddWord", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(Localization.instance, new object[2]
		{
			"skill_" + id,
			idText
		});
	}

	public static string GetTranslated(int id)
	{
		Logging.GetLogger().Debug(string.Format("Got translation for id {0} to {1}", id, Localization.instance.Localize("skill_" + id)));
		return Localization.instance.Localize("$skill_" + id);
	}

	public static Sprite GetPrefabIcon(string prefabName)
	{
		Sprite result = null;
		GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefabName);
		ItemDrop val = default(ItemDrop);
		if ((Object)(object)itemPrefab != (Object)null && itemPrefab.TryGetComponent<ItemDrop>(ref val))
		{
			result = val.m_itemData.GetIcon();
		}
		return result;
	}

	public static Player GetPlayerByZDOID(ZDOID zid)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		foreach (Player allPlayer in Player.GetAllPlayers())
		{
			ZDOID zDOID = ((Character)allPlayer).GetZDOID();
			if (((ZDOID)(ref zDOID)).Equals(zid))
			{
				return allPlayer;
			}
		}
		return null;
	}

	public static Character GetCharacterByZDOID(string cid)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			ZDOID zDOID = allCharacter.GetZDOID();
			if (((object)(ZDOID)(ref zDOID)).ToString().Equals(cid))
			{
				return allCharacter;
			}
		}
		return null;
	}

	public static Character GetCharacterByZDOID(ZDOID cid)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			ZDOID zDOID = allCharacter.GetZDOID();
			if (((ZDOID)(ref zDOID)).Equals(cid))
			{
				return allCharacter;
			}
		}
		return null;
	}

	public static ZNetPeer GetPeerByRPC(ZRpc rpc)
	{
		foreach (ZNetPeer peer in ZNet.instance.GetPeers())
		{
			if (peer.m_rpc == rpc)
			{
				return peer;
			}
		}
		return null;
	}

	public static List<GameObject> GetGameObjectsOfType(Type t)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		List<GameObject> list = new List<GameObject>();
		Object[] array = Object.FindObjectsOfType(t);
		foreach (Object val in array)
		{
			list.Add(((Component)val).gameObject);
		}
		return list;
	}

	public static GameObject GetClosestGameObjectOfType(Type t, Vector3 point, float radius)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return GetGameObjectsOfTypeInRangeByDistance(t, point, radius)?[0];
	}

	public static List<GameObject> GetGameObjectsOfTypeInRangeByDistance(Type t, Vector3 point, float radius)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		List<KeyValuePair<GameObject, float>> list = new List<KeyValuePair<GameObject, float>>();
		List<GameObject> gameObjectsOfTypeInRange = GetGameObjectsOfTypeInRange(t, point, radius);
		if (gameObjectsOfTypeInRange.Count > 0)
		{
			foreach (GameObject item in gameObjectsOfTypeInRange)
			{
				list.Add(new KeyValuePair<GameObject, float>(item, Vector3.Distance(item.transform.position, point)));
			}
			list.Sort((KeyValuePair<GameObject, float> pair1, KeyValuePair<GameObject, float> pair2) => pair1.Value.CompareTo(pair2.Value));
			return list.ConvertAll((KeyValuePair<GameObject, float> x) => x.Key);
		}
		return null;
	}

	public static List<GameObject> GetGameObjectsOfTypeInRange(Type t, Vector3 point, float radius)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		return (from x in GetGameObjectsOfType(t)
			where Vector3.Distance(x.transform.position, point) < radius
			select x).ToList();
	}

	public static float GetPointDepth(Vector3 p)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		return ZoneSystem.instance.m_waterLevel - GetSolidHeight(p);
	}

	public static List<string> GetDelimitedStringAsList(string delimitedString, char delimiter)
	{
		List<string> list = new List<string>();
		string[] array = delimitedString.Split(new char[1] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
		foreach (string text in array)
		{
			list.Add(text.Trim());
		}
		return list;
	}

	public static float GetSolidHeight(Vector3 p)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: 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)
		int solidRayMask = ZoneSystem.instance.m_solidRayMask;
		float result = 0f;
		p.y += 1000f;
		RaycastHit val = default(RaycastHit);
		if (Physics.Raycast(p, Vector3.down, ref val, 2000f, solidRayMask) && !Object.op_Implicit((Object)(object)((RaycastHit)(ref val)).collider.attachedRigidbody))
		{
			result = ((RaycastHit)(ref val)).point.y;
		}
		return result;
	}

	public static Transform FindChild(Transform aParent, string aName)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Expected O, but got Unknown
		foreach (Transform item in aParent)
		{
			Transform val = item;
			if (((Object)val).name == aName)
			{
				return val;
			}
			Transform val2 = FindChild(val, aName);
			if ((Object)(object)val2 != (Object)null)
			{
				return val2;
			}
		}
		return null;
	}

	public static Transform FindParent(Transform go)
	{
		while ((Object)(object)go.parent != (Object)null)
		{
			go = go.parent;
		}
		return go;
	}

	public static GameObject GetPrefabByHash(int prefabHash)
	{
		GameObject val = ObjectDB.instance.GetItemPrefab(prefabHash);
		Logging logger = Logging.GetLogger();
		if ((Object)(object)val != (Object)null)
		{
			logger.Debug("Found prefab in ObjectDB");
		}
		else
		{
			ZNetScene instance = ZNetScene.instance;
			val = ((instance != null) ? instance.GetPrefab(prefabHash) : null);
			if ((Object)(object)val != (Object)null)
			{
				logger.Debug("Found prefab in Scene");
			}
		}
		return val;
	}

	public static GameObject GetPrefab(string prefabName)
	{
		GameObject val = ObjectDB.instance.GetItemPrefab(prefabName);
		Logging logger = Logging.GetLogger();
		if ((Object)(object)val != (Object)null)
		{
			logger.Debug("Found " + prefabName + " in ObjectDB");
		}
		else
		{
			ZNetScene instance = ZNetScene.instance;
			val = ((instance != null) ? instance.GetPrefab(prefabName) : null);
			if ((Object)(object)val != (Object)null)
			{
				logger.Debug("Found " + prefabName + " in Scene");
			}
		}
		return val;
	}

	public static string SerializeFromDictionary<K, V>(string delimp, string delimc, IDictionary<K, V> dict)
	{
		if (dict == null)
		{
			return null;
		}
		IEnumerable<string> values = dict.Select(delegate(KeyValuePair<K, V> kvp)
		{
			KeyValuePair<K, V> keyValuePair = kvp;
			string? obj = keyValuePair.Key?.ToString();
			string text = delimc;
			keyValuePair = kvp;
			return obj + text + keyValuePair.Value;
		});
		return string.Join(delimp, values);
	}

	public static void DeserializeToDictionary<K, V>(string serializedString, string delimp, string delimc, ref IDictionary<K, V> dict)
	{
		if (dict == null)
		{
			return;
		}
		dict.Clear();
		string[] separator = new string[1] { delimp };
		string[] separator2 = new string[1] { delimc };
		string[] array = serializedString.Split(separator, StringSplitOptions.RemoveEmptyEntries);
		for (int i = 0; i < array.Length; i++)
		{
			string[] array2 = array[i].Split(separator2, StringSplitOptions.RemoveEmptyEntries);
			if (array2.Length == 2)
			{
				dict.Add(TypedValue<K>(array2[0]), TypedValue<V>(array2[1]));
			}
		}
	}

	public static T TypedValue<T>(object a)
	{
		return (T)Convert.ChangeType(a, typeof(T));
	}

	public static bool CopyComponentToGameObject(Component original, ref GameObject destination)
	{
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Expected O, but got Unknown
		Logging logger = Logging.GetLogger();
		Type type = ((object)original).GetType();
		logger.Debug($"Original Type is {type}");
		GameObject obj = destination;
		logger.Debug("Destination GameObject " + ((obj != null) ? ((Object)obj).name : null));
		Component val = destination.GetComponent(type);
		if ((Object)(object)val == (Object)null)
		{
			val = destination.AddComponent(type);
		}
		if ((Object)(object)val == (Object)null)
		{
			logger.Debug("Destination component is null");
			return false;
		}
		Component val2 = (Component)Activator.CreateInstance(type);
		if ((Object)(object)val2 == (Object)null)
		{
			logger.Debug("Destination component is null");
			return false;
		}
		if ((Object)(object)val2 == (Object)null)
		{
			logger.Debug("Boxed component is null");
			return false;
		}
		FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (FieldInfo fieldInfo in fields)
		{
			fieldInfo.SetValue(val2, fieldInfo.GetValue(original));
		}
		val = val2;
		return true;
	}

	public static bool CopyObject(object original, object target)
	{
		Logging logger = Logging.GetLogger();
		Type type = original.GetType();
		Type type2 = target.GetType();
		if (type == null)
		{
			logger.Warning("Copy Object: Source object is null");
			Activator.CreateInstance(type);
			return false;
		}
		if (type2 == null)
		{
			logger.Warning("Copy Object: Destination object is null");
			return false;
		}
		if (type2 != type)
		{
			logger.Warning("Copy Object: Source and destination components are different types");
			return false;
		}
		FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (FieldInfo fieldInfo in fields)
		{
			fieldInfo.SetValue(target, fieldInfo.GetValue(original));
		}
		return true;
	}
}
internal class Cfg
{
	public static KeyCode[] keyModifiers = (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 };

	public static KeyboardShortcut chestBindKeyDefault = new KeyboardShortcut((KeyCode)106, keyModifiers);

	public static DelegatedConfigEntry<Logging.LogLevels> debugLevel = null;

	public static DelegatedConfigEntry<KeyboardShortcut> chestBindKey = null;

	public static KeyboardShortcut chestOpenKeyDefault = new KeyboardShortcut((KeyCode)104, Array.Empty<KeyCode>());

	public static DelegatedConfigEntry<KeyboardShortcut> chestOpenKey = null;

	public static DelegatedConfigEntry<bool> useStrictCost = null;

	public static DelegatedConfigEntry<bool> teleportRestriction = null;

	public static DelegatedConfigEntry<int> bindCost = null;

	public static DelegatedConfigEntry<int> openCost = null;

	public static DelegatedConfigEntry<SeidrChest.ChestModes> chestMode = null;

	public static DelegatedConfigEntry<SeidrChest.CostModes> costMode = null;

	public static DelegatedConfigEntry<bool> invertEnderKey = null;

	public static void BepInExConfig(BaseUnityPlugin _instance)
	{
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_01df: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e9: Expected O, but got Unknown
		//IL_0225: Unknown result type (might be due to invalid IL or missing references)
		//IL_022f: Expected O, but got Unknown
		debugLevel = new DelegatedConfigEntry<Logging.LogLevels>(Logging.ChangeLogging);
		debugLevel.ConfigEntry = _instance.Config.Bind<Logging.LogLevels>("Utility", "LogLevel", Logging.LogLevels.Info, "Controls the level of information contained in the log. Default is 'Info'");
		SeidrChest.Log.LogLevel = debugLevel.Value;
		chestMode = new DelegatedConfigEntry<SeidrChest.ChestModes>(useServerDelegate: true);
		chestMode.ConfigEntry = _instance.Config.Bind<SeidrChest.ChestModes>("General", "ChestMode", SeidrChest.ChestModes.SeidrChest, "Seidr mode allows accessing the Seidr chest anyhwere. Ender mode links all personal chests to the same Seidr chest; you must open them to access the common toInventory.");
		costMode = new DelegatedConfigEntry<SeidrChest.CostModes>(useServerDelegate: true);
		costMode.ConfigEntry = _instance.Config.Bind<SeidrChest.CostModes>("Cost", "CostType", SeidrChest.CostModes.EitrThenStamina, "Set the type of energy used to bind and open Seidr chests. Can be exclusivley Eitr or Stamina, or Eitr first, followed by Stamina.");
		chestBindKey = new DelegatedConfigEntry<KeyboardShortcut>();
		chestBindKey.ConfigEntry = _instance.Config.Bind<KeyboardShortcut>("General", "BindSeidrChest", chestBindKeyDefault, "Press this key to seidr bind a Personal Chest to a Seidr Chest.");
		chestOpenKey = new DelegatedConfigEntry<KeyboardShortcut>();
		chestOpenKey.ConfigEntry = _instance.Config.Bind<KeyboardShortcut>("General", "OpenSeidrChest", chestOpenKeyDefault, "Press this key to open your Seidr Chest. In EnderChest mode, hold this key down when opening a Personal chest to access the actual chest contents.");
		useStrictCost = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		useStrictCost.ConfigEntry = _instance.Config.Bind<bool>("Cost", "StrictCost", false, "Require cost to be met before binding or opening. If Eitr and/or Stamina is less than this cost (depending on CostType setting), chest cannot be bound or open.");
		invertEnderKey = new DelegatedConfigEntry<bool>();
		invertEnderKey.ConfigEntry = _instance.Config.Bind<bool>("General", "InvertEnderOpenKey", false, "Set True to invert Ender mode open action, i.e., open Personal Chest as default, open SeidrChest while holding the OpenSeidrChest key.");
		teleportRestriction = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		teleportRestriction.ConfigEntry = _instance.Config.Bind<bool>("General", "RestrictNonTeleportable", false, "Set to true to prevent non-teleportable items in the Seidr chest.");
		bindCost = new DelegatedConfigEntry<int>(useServerDelegate: true);
		bindCost.ConfigEntry = _instance.Config.Bind<int>("Cost", "CostToBind", 50, new ConfigDescription("Sets the amount of eitr and/or stamina consumed to bind a Seidr chest.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 300), Array.Empty<object>()));
		openCost = new DelegatedConfigEntry<int>(useServerDelegate: true);
		openCost.ConfigEntry = _instance.Config.Bind<int>("Cost", "CostToOpen", 10, new ConfigDescription("Sets the amount of eitr and/or stamina consumed to use a Seidr chest.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 300), Array.Empty<object>()));
	}
}
[BepInPlugin("neobotics.valheim_mod.seidrchest", "SeidrChest", "0.1.13")]
[BepInProcess("valheim.exe")]
[BepInProcess("valheim_server.exe")]
public class SeidrChest : BaseUnityPlugin
{
	public enum ChestModes
	{
		SeidrChest,
		EnderChest
	}

	public enum CostModes
	{
		EitrThenStamina,
		EitrOnly,
		StaminaOnly
	}

	[HarmonyPatch(typeof(InventoryGui), "Hide")]
	private static class InventoryGui_Hide_Patch
	{
		[HarmonyPostfix]
		private static void InventoryGui_Hide_Postfix(InventoryGui __instance)
		{
			Log.Debug("InventoryGui_Hide_Patch_Postfix");
			if (originalAutocloseDistance >= 0f)
			{
				__instance.m_autoCloseDistance = originalAutocloseDistance;
			}
		}
	}

	[HarmonyPatch(typeof(InventoryGui), "CloseContainer")]
	private static class InventoryGui_CloseContainer_Patch
	{
		[HarmonyPostfix]
		private static void InventoryGui_CloseContainer_Postfix(InventoryGui __instance)
		{
			Log.Debug("InventoryGui_CloseContainer_Patch_Postfix");
			if (originalAutocloseDistance >= 0f)
			{
				__instance.m_autoCloseDistance = originalAutocloseDistance;
			}
		}
	}

	[HarmonyPatch(typeof(ZDOMan), "FindSectorObjects")]
	public static class ZDOMan_FindSectorObjects1_Patch
	{
		private static void Prefix(ZDOMan __instance, Vector2i sector, int area, List<ZDO> sectorObjects)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			AddSectorObject(__instance, sector, area, sectorObjects);
		}
	}

	[HarmonyPatch(typeof(InventoryGui), "Show")]
	public static class InventoryGui_Show_Patch
	{
		private static bool Prefix(InventoryGui __instance, ref Container container, out Container __state)
		{
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			__state = null;
			if (originalAutocloseDistance == -1f)
			{
				originalAutocloseDistance = __instance.m_autoCloseDistance;
			}
			if ((Object)(object)container != (Object)null)
			{
				Log.Trace("Showing container name " + container.m_name);
				if (container.m_name == "$piece_chestprivate" && Cfg.chestMode.Value == ChestModes.EnderChest && ((!Cfg.chestOpenKey.IsKeyDown() && !Cfg.invertEnderKey.Value) || (Cfg.chestOpenKey.IsKeyDown() && Cfg.invertEnderKey.Value)))
				{
					if (!SetupSeidrChest())
					{
						Log.Info("No Seidr chest is bound");
						return true;
					}
					Container val = default(Container);
					if ((Object)(object)voidChest != (Object)null && voidChest.TryGetComponent<Container>(ref val))
					{
						Log.Debug("Switching to Sedir chest");
						container = val;
					}
				}
				if ((Object)(object)voidChest != (Object)null && (Object)(object)voidChest.GetComponent<Container>() == (Object)(object)container)
				{
					Log.Debug("Showing Seidr chest");
					if (!HasSeidrCost(Player.m_localPlayer, Cfg.openCost.Value, binding: false))
					{
						return false;
					}
					ApplySeidrCost(Player.m_localPlayer, Cfg.openCost.Value);
					container.GetInventory().m_name = "Seiðr chest";
					if (Vector3.Distance(((Component)Player.m_localPlayer).transform.position, voidChest.transform.position) > 5f)
					{
						__instance.m_autoCloseDistance = float.MaxValue;
						Log.Debug("Reset autoclose distance");
					}
					else
					{
						__instance.m_autoCloseDistance = originalAutocloseDistance;
					}
				}
			}
			else
			{
				Log.Debug("Not a Container");
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Player), "Save")]
	public static class Player_Save_Patch
	{
		public static void Prefix(Player __instance, ZPackage pkg)
		{
			if (customData != null)
			{
				customData.PreSaveSync();
			}
		}
	}

	[HarmonyPatch(typeof(Player), "OnSpawned")]
	public static class Player_OnSpawned_Patch
	{
		public static void Postfix(Player __instance)
		{
			World world = ZNet.m_world;
			if (world != null)
			{
				worldName = world.m_name;
				worldPlayer = worldName + "_" + __instance.GetPlayerName();
				customData = new CustomDataWrapper(__instance.m_customData, "SeidrChest_1847_");
			}
			voidChest = null;
			voidZdo = null;
			SetupSeidrChest();
		}
	}

	[HarmonyPatch(typeof(Container), "CanBeRemoved")]
	public static class Container_OnDestroyed_Patch
	{
		private static void Postfix(Container __instance, ref bool __result)
		{
			if (__result && (Object)(object)voidChest != (Object)null && (Object)(object)voidChest == (Object)(object)((Component)__instance).gameObject)
			{
				Log.Trace("Setting Seidr chest removal false");
				__result = false;
			}
		}
	}

	[HarmonyPatch(typeof(Container), "GetHoverText")]
	public static class Container_GetHoverText_Patch
	{
		private static void Postfix(Container __instance, ref string __result)
		{
			if ((Object)(object)voidChest != (Object)null && Cfg.chestMode.Value == ChestModes.EnderChest && __instance.m_name == "$piece_chestprivate" && ((!Cfg.chestOpenKey.IsKeyDown() && !Cfg.invertEnderKey.Value) || (Cfg.chestOpenKey.IsKeyDown() && Cfg.invertEnderKey.Value)))
			{
				__result += " (Seiðr chest)";
			}
		}
	}

	[HarmonyPatch(typeof(Player), "Update")]
	public static class Player_Update_Patch
	{
		private static void Prefix(Player __instance)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && OkToKey(__instance))
			{
				if (Cfg.chestBindKey.IsKeyPressed())
				{
					BindChest();
				}
				if (Cfg.chestMode.Value == ChestModes.SeidrChest && Cfg.chestOpenKey.IsKeyPressed())
				{
					HandleChest();
				}
			}
		}
	}

	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
	{
		typeof(ItemData),
		typeof(int),
		typeof(int),
		typeof(int)
	})]
	private static class Inventory_AddItem_ToSlot_Patch
	{
		private static bool Prefix(Inventory __instance, ItemData item, int amount, int x, int y, string ___m_name, out bool __result)
		{
			__result = true;
			Log.Trace("AddItem_ToSlot " + item.m_shared.m_name + " to " + ___m_name);
			if (!IsOkToMove(item, ___m_name))
			{
				__result = false;
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })]
	private static class Inventory_AddItem_Patch
	{
		private static bool Prefix(Inventory __instance, ItemData item, string ___m_name, out bool __result)
		{
			__result = true;
			Log.Trace("AddItem " + item.m_shared.m_name + " to " + ___m_name);
			if (!IsOkToMove(item, ___m_name))
			{
				__result = false;
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Inventory), "MoveItemToThis", new Type[]
	{
		typeof(Inventory),
		typeof(ItemData),
		typeof(int),
		typeof(int),
		typeof(int)
	})]
	private static class Inventory_MoveItemToThis_Slot_Patch
	{
		private static bool Prefix(Inventory __instance, Inventory fromInventory, ItemData item, int amount, int x, int y, string ___m_name)
		{
			Log.Trace("MoveItemToThis_Slot " + item.m_shared.m_name + " to " + ___m_name);
			ItemData itemAt = __instance.GetItemAt(x, y);
			if (itemAt != null && !IsOkToMove(itemAt, fromInventory.GetName()))
			{
				return false;
			}
			if (!IsOkToMove(item, ___m_name))
			{
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Inventory), "MoveItemToThis", new Type[]
	{
		typeof(Inventory),
		typeof(ItemData)
	})]
	private static class Inventory_MoveItemToThis_Patch
	{
		private static bool Prefix(Inventory __instance, Inventory fromInventory, ItemData item, string ___m_name)
		{
			Log.Trace("MoveItemToThis " + item.m_shared.m_name + " to " + ___m_name);
			if (!IsOkToMove(item, ___m_name))
			{
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(InventoryGrid), "DropItem")]
	private static class InventoryGrid_DropItem_Patch
	{
		private static bool Prefix(InventoryGrid __instance, Inventory fromInventory, ItemData item, int amount, Vector2i pos, Inventory ___m_inventory, out bool __result)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			__result = true;
			string name = ___m_inventory.GetName();
			Log.Trace("InventoryGrid_DropItem " + item.m_shared.m_name + " to " + name);
			ItemData itemAt = ___m_inventory.GetItemAt(pos.x, pos.y);
			if (itemAt != null && !IsOkToMove(itemAt, fromInventory.GetName()))
			{
				return false;
			}
			if (!IsOkToMove(item, name))
			{
				__result = false;
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(InventoryGui), "UpdateContainer")]
	private static class InventoryGui_UpdateContainer_Patch
	{
		private static void Prefix(InventoryGui __instance, Container ___m_currentContainer)
		{
			ZNetView val = default(ZNetView);
			if ((Object)(object)___m_currentContainer != (Object)null && !___m_currentContainer.IsOwner() && (Object)(object)voidChest != (Object)null && (Object)(object)((Component)___m_currentContainer).gameObject == (Object)(object)voidChest && ((Component)___m_currentContainer).gameObject.TryGetComponent<ZNetView>(ref val))
			{
				ZDO zDO = val.GetZDO();
				if (zDO != null)
				{
					zDO.SetOwner(((Character)Player.m_localPlayer).GetOwner());
				}
			}
		}
	}

	[HarmonyPatch(typeof(FejdStartup), "Awake")]
	private static class FejidStartup_Awake_Patch
	{
		private static void Postfix(FejdStartup __instance)
		{
			GetDetectionSet(new Dictionary<string, string> { { "yay.spikehimself.xstorage.harmony", "XStorage" } });
		}
	}

	[HarmonyPatch(typeof(Terminal), "TryRunCommand")]
	private static class Try_Run_Command_Patch
	{
		private static void Prefix(ref string text)
		{
			if (text == null)
			{
				return;
			}
			string text2 = text.ToLower();
			if (text2.StartsWith(LcMod))
			{
				string text3 = text2.Substring(LcMod.Length + 1).Trim();
				Log.Debug(Mod + " Configuration command: " + text3);
				if (text3.Equals("config"))
				{
					((BaseUnityPlugin)_modInstance).Config.Reload();
					_modInstance.ConfigureMod();
				}
				text = "";
			}
		}
	}

	private static SeidrChest _modInstance;

	private static string Mod = "SeidrChest";

	private static string LcMod = Mod.ToLower();

	public static Logging Log;

	private const string convertedName = "Seiðr chest";

	private const string personalChestTag = "$piece_chestprivate";

	private Harmony harmony;

	private static string worldPlayer = "";

	private static string worldName = "";

	private static CustomDataWrapper customData = null;

	private static float originalAutocloseDistance = -1f;

	private static GameObject voidChest = null;

	private static ZDO voidZdo = null;

	private static GameObject bindPrefab = null;

	private const string CANTBIND = "You can't bind it";

	public const string SEIDRPREFIX = "SeidrChest_1847_";

	private const string XSTORAGESKIP = "XStorage_SkipMark";

	private const string SEIDERCHEST_TEMP = "SeidrChest_Temp";

	private static Dictionary<string, string> detectionSet = new Dictionary<string, string>();

	private static Dictionary<string, string> unpatchMods = new Dictionary<string, string>();

	public static SeidrChest GetInstance()
	{
		return _modInstance;
	}

	private void Awake()
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Expected O, but got Unknown
		_modInstance = this;
		Log = Logging.GetLogger(Logging.LogLevels.Info, Mod);
		harmony = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
		harmony.PatchAll(Assembly.GetExecutingAssembly());
		ConfigureMod();
		Log.Info("Awake");
	}

	private void ConfigureMod()
	{
		Log = Logging.GetLogger(Logging.LogLevels.Info, Mod);
		ServerConfiguration.Instance.Setup(((BaseUnityPlugin)this).Config, (BaseUnityPlugin)(object)this);
		Cfg.BepInExConfig((BaseUnityPlugin)(object)_modInstance);
	}

	private void OnDestroy()
	{
		harmony.UnpatchSelf();
	}

	private static bool HasSeidrCost(Player aPlayer, float amount, bool binding = true)
	{
		bool flag = true;
		if (Cfg.useStrictCost.Value)
		{
			float eitr = aPlayer.GetEitr();
			float stamina = aPlayer.GetStamina();
			switch (Cfg.costMode.Value)
			{
			case CostModes.EitrOnly:
				if (eitr < amount)
				{
					flag = false;
				}
				break;
			case CostModes.StaminaOnly:
				if (stamina < amount)
				{
					flag = false;
				}
				break;
			default:
				if (eitr + stamina < amount)
				{
					flag = false;
				}
				break;
			}
			if (!flag)
			{
				Log.Info("Not enough energy to " + (binding ? "bind" : "use") + " the Seidr chest");
				((Character)Player.m_localPlayer).Message((MessageType)2, "Not enough energy", 0, (Sprite)null);
			}
		}
		return flag;
	}

	private static void ApplySeidrCost(Player aPlayer, float amount)
	{
		float eitr = aPlayer.GetEitr();
		aPlayer.GetStamina();
		if ((Cfg.costMode.Value == CostModes.EitrOnly || Cfg.costMode.Value == CostModes.EitrThenStamina) && eitr > 0f)
		{
			((Character)aPlayer).UseEitr(amount);
			amount -= eitr;
		}
		if ((Cfg.costMode.Value == CostModes.StaminaOnly || Cfg.costMode.Value == CostModes.EitrThenStamina) && amount > 0f)
		{
			((Character)aPlayer).UseStamina(amount, false);
		}
	}

	private static void RestoreToPersonalChest()
	{
		Container val = default(Container);
		if ((Object)(object)voidChest != (Object)null && voidChest.TryGetComponent<Container>(ref val))
		{
			val.GetInventory().m_name = "$piece_chestprivate";
			val.m_name = "$piece_chestprivate";
		}
	}

	private static bool IsOkToMove(ItemData item, string name)
	{
		if (name == "Seiðr chest" && item?.m_shared != null && Cfg.teleportRestriction.Value && !item.m_shared.m_teleportable)
		{
			Log.Info("Can't store non-teleportable items in the Seidr chest");
			((Character)Player.m_localPlayer).Message((MessageType)1, "Can't store that in the chest", 0, (Sprite)null);
			return false;
		}
		return true;
	}

	private static void UnbindChest()
	{
		Log.Debug("UnbindChest");
		CreateAura(voidChest);
		RestoreToPersonalChest();
		Container val = default(Container);
		ZDO val2 = default(ZDO);
		if ((Object)(object)voidChest != (Object)null && voidChest.TryGetComponent<Container>(ref val) && voidChest.TryGetComponent<ZDO>(ref val2))
		{
			val2.Set(StringExtensionMethods.GetStableHashCode("XStorage_SkipMark"), false);
			val2.RemoveInt("SeidrChest_1847_");
		}
		voidChest = null;
		customData.Remove(GetChestWorldKey());
		Log.Info("Seidr Chest is unbound");
		((Character)Player.m_localPlayer).Message((MessageType)2, "Seiðr chest is unbound", 0, (Sprite)null);
	}

	private static bool HasNonTeleportableItems(Container container)
	{
		if (((container != null) ? container.GetInventory() : null) != null)
		{
			return container.GetInventory().GetAllItems().Find((ItemData x) => !x.m_shared.m_teleportable) != null;
		}
		return false;
	}

	private static void BindChest()
	{
		Player localPlayer = Player.m_localPlayer;
		Log.Debug("BindChest");
		GameObject hoverObject = ((Humanoid)localPlayer).GetHoverObject();
		GameObject val = ((hoverObject != null) ? ((Component)hoverObject.transform.root).gameObject : null);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		if ((Object)(object)val == (Object)(object)voidChest)
		{
			UnbindChest();
			return;
		}
		if (((Object)val).name != "piece_chest_private(Clone)")
		{
			Log.Info("Hovered object is not a personal chest");
			((Character)localPlayer).Message((MessageType)2, "You can't bind it", 0, (Sprite)null);
			return;
		}
		ZNetView val2 = default(ZNetView);
		if (!val.TryGetComponent<ZNetView>(ref val2))
		{
			Log.Warning("Hovering object has no view");
			return;
		}
		ZDO zDO = val2.GetZDO();
		Piece component = val.GetComponent<Piece>();
		Container container = default(Container);
		if (zDO == null || (Object)(object)component == (Object)null)
		{
			Log.Warning("Invalid hover object");
		}
		else if (!component.IsCreator())
		{
			Log.Info("You can only bind your own Personal chest");
			((Character)localPlayer).Message((MessageType)2, "You can't bind it", 0, (Sprite)null);
		}
		else if (Cfg.teleportRestriction.Value && val.TryGetComponent<Container>(ref container) && HasNonTeleportableItems(container))
		{
			Log.Info("You cannot bind a chest with items that can't be teleported");
			((Character)localPlayer).Message((MessageType)2, "You can't bind it", 0, (Sprite)null);
		}
		else if (HasSeidrCost(localPlayer, Cfg.bindCost.Value))
		{
			ApplySeidrCost(localPlayer, Cfg.bindCost.Value);
			RestoreToPersonalChest();
			voidChest = val;
			Log.Debug("Player selected own Personal chest");
			SaveSeidrChestZDO(zDO);
			Object.DontDestroyOnLoad((Object)(object)voidChest);
			CreateAura(voidChest);
			Container val3 = default(Container);
			if (voidChest.TryGetComponent<Container>(ref val3))
			{
				val3.m_name = "Seiðr chest";
				zDO.Set(StringExtensionMethods.GetStableHashCode("XStorage_SkipMark"), true);
			}
			Log.Info("Seidr Chest is bound");
			((Character)localPlayer).Message((MessageType)2, "Seiðr chest is bound", 0, (Sprite)null);
		}
	}

	private static void CreateAura(GameObject go)
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)bindPrefab == (Object)null)
		{
			bindPrefab = ZNetScene.instance.GetPrefab("fx_Immobilize");
		}
		if ((Object)(object)bindPrefab != (Object)null)
		{
			Object.Instantiate<GameObject>(bindPrefab, go.transform.position, Quaternion.identity);
		}
	}

	private static string GetChestWorldKey()
	{
		return "SeidrChest_1847_" + worldName;
	}

	private static ZDO GetSeidrChestZDO()
	{
		Log.Debug("GetSeidrChestZDO");
		Player localPlayer = Player.m_localPlayer;
		string text = customData.Get(GetChestWorldKey());
		int stableHashCode = StringExtensionMethods.GetStableHashCode("piece_chest_private");
		if (text != null)
		{
			if (int.TryParse(text, out var result))
			{
				foreach (ZDO item in ZDOMan.instance.m_objectsBySector[result])
				{
					if (item != null && item.m_prefab == stableHashCode && item.GetString("SeidrChest_1847_", "") == localPlayer.GetPlayerName())
					{
						return item;
					}
				}
			}
			Log.Info("Sector miss");
			foreach (ZDO value in ZDOMan.instance.m_objectsByID.Values)
			{
				if (value != null && value.m_prefab == stableHashCode && value.GetString("SeidrChest_1847_", "") == localPlayer.GetPlayerName())
				{
					return value;
				}
			}
		}
		return null;
	}

	private static void SaveSeidrChestZDO(ZDO zdo)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		Log.Debug("SaveSeidrChestZDO");
		zdo.Set("SeidrChest_1847_", Player.m_localPlayer.GetPlayerName());
		customData.Set(GetChestWorldKey(), ZDOMan.instance.SectorToIndex(zdo.GetSector()).ToString());
	}

	private static bool SetupSeidrChest()
	{
		if ((Object)(object)voidChest == (Object)null)
		{
			Log.Debug("Finding chest");
			ZDO seidrChestZDO = voidZdo;
			if (seidrChestZDO == null)
			{
				Log.Debug("No ZDO. Reading from saved data.");
				seidrChestZDO = GetSeidrChestZDO();
			}
			if (seidrChestZDO == null)
			{
				Log.Debug("No pre-existing chest");
				return false;
			}
			if (seidrChestZDO == null)
			{
				Log.Warning("Bound chest no longer exists!");
				return false;
			}
			if (!ZNetScene.instance.HaveInstance(seidrChestZDO))
			{
				Log.Debug("No chest instance currently in scene... creating.");
				ZNetScene.instance.CreateObject(seidrChestZDO);
			}
			ZNetView val = ZNetScene.instance.FindInstance(seidrChestZDO);
			if ((Object)(object)val != (Object)null)
			{
				Log.Debug("Re-binding existing chest");
				voidChest = ((Component)val).gameObject;
				voidZdo = seidrChestZDO;
				Container val2 = default(Container);
				if (voidChest.TryGetComponent<Container>(ref val2))
				{
					val2.m_name = "Seiðr chest";
				}
				Object.DontDestroyOnLoad((Object)(object)voidChest);
				return true;
			}
			Log.Warning("Couldn't find existing chest");
			return false;
		}
		return true;
	}

	private static bool HandleChest()
	{
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		Log.Debug("HandleChest");
		if (!SetupSeidrChest())
		{
			Log.Info("No Seidr chest is bound");
			return false;
		}
		if (InventoryGui.instance.IsContainerOpen())
		{
			Container currentContainer = InventoryGui.instance.m_currentContainer;
			if ((Object)(object)currentContainer != (Object)null && (Object)(object)((Component)currentContainer).gameObject != (Object)(object)voidChest)
			{
				InventoryGui.instance.Hide();
			}
		}
		ZNetView val = default(ZNetView);
		if (voidChest.TryGetComponent<ZNetView>(ref val))
		{
			if (val.GetZDO() == null)
			{
				Log.Warning("Chest missing ZDO");
				return false;
			}
			Container val2 = default(Container);
			if (voidChest.TryGetComponent<Container>(ref val2))
			{
				if (val2.IsInUse())
				{
					Log.Debug("Closing chest");
					InventoryGui.instance.Hide();
					return true;
				}
				Log.Debug($"Seidr chest is {Vector3.Distance(voidChest.transform.position, ((Component)localPlayer).transform.position)} meters away");
				if (!HasSeidrCost(localPlayer, Cfg.openCost.Value, binding: false))
				{
					return false;
				}
				val2.m_name = "Seiðr chest";
				if (val2.Interact((Humanoid)(object)localPlayer, false, false))
				{
					val2.SetInUse(true);
					return true;
				}
				Log.Warning("Can't interact with chest");
				return false;
			}
			Log.Warning("Chest missing Container");
			return false;
		}
		Log.Warning("Chest missing ZNetView");
		return false;
	}

	private static bool OkToKey(Player player)
	{
		if (!Chat.instance.HasFocus() && !Console.IsVisible() && (Object)(object)TextViewer.instance != (Object)null && !TextViewer.instance.IsVisible() && !GameCamera.InFreeFly() && !Minimap.IsOpen() && !TextInput.IsVisible() && !StoreGui.IsVisible() && !((Character)player).InCutscene() && !((Character)player).InBed() && !((Character)player).IsTeleporting() && !((Character)player).IsDead())
		{
			return !((Character)player).InPlaceMode();
		}
		return false;
	}

	public static void GetDetectionSet(Dictionary<string, string> harmonyIds)
	{
		foreach (KeyValuePair<string, string> harmonyId in harmonyIds)
		{
			if (Harmony.HasAnyPatches(harmonyId.Key))
			{
				Log.Debug("Detected " + harmonyId.Value);
				if (!detectionSet.ContainsKey(harmonyId.Key))
				{
					detectionSet.Add(harmonyId.Key, harmonyId.Value);
				}
			}
		}
	}

	public static void AddExclusion(string key)
	{
		if (detectionSet.ContainsKey(key))
		{
			unpatchMods.Add(key, detectionSet[key]);
		}
	}

	public static void UnpatchMods()
	{
		foreach (KeyValuePair<string, string> unpatchMod in unpatchMods)
		{
			Log.Warning("Not compatible with " + unpatchMod.Value);
			_modInstance.harmony.UnpatchAll(unpatchMod.Key);
			detectionSet.Remove(unpatchMod.Key);
			Log.Warning("Disabled " + unpatchMod.Value);
		}
	}

	public static bool IsDetectedId(string key)
	{
		return detectionSet.ContainsKey(key);
	}

	private static void AddSectorObject(ZDOMan __instance, Vector2i sector, int area, List<ZDO> sectorObjects)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		ZNetView val = default(ZNetView);
		if (!((Object)(object)voidChest != (Object)null) || sectorObjects == null || !(ZoneSystem.instance.GetZone(voidChest.transform.position) != sector) || !voidChest.TryGetComponent<ZNetView>(ref val))
		{
			return;
		}
		ZDO zDO = val.GetZDO();
		if (zDO != null && (Object)(object)Player.m_localPlayer != (Object)null)
		{
			zDO.SetOwner(((Character)Player.m_localPlayer).GetOwner());
			if (!sectorObjects.Contains(zDO))
			{
				sectorObjects.Add(zDO);
			}
		}
	}
}