Decompiled source of DefendYourBase v0.2.6

DefendYourBase.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Networking;
using neobotics.ModSdk;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("DefendYourBase")]
[assembly: AssemblyConfiguration("Deploy")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+8f12218228e04526ba7be2e4e0f5dfddcf5e3a69")]
[assembly: AssemblyProduct("DefendYourBase")]
[assembly: AssemblyTitle("DefendYourBase")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
public sealed class ConfigurationManagerAttributes
{
	public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput);

	public bool? ShowRangeAsPercent;

	public Action<ConfigEntryBase> CustomDrawer;

	public CustomHotkeyDrawerFunc CustomHotkeyDrawer;

	public bool? Browsable;

	public string Category;

	public object DefaultValue;

	public bool? HideDefaultButton;

	public bool? HideSettingName;

	public string Description;

	public string DispName;

	public int? Order;

	public bool? ReadOnly;

	public bool? IsAdvanced;

	public Func<object, string> ObjToStr;

	public Func<string, object> StrToObj;
}
namespace neobotics.ModSdk
{
	public class AudioHelper : MonoBehaviour
	{
		private readonly Dictionary<string, AudioClip> audioClips = new Dictionary<string, AudioClip>();

		private Logging logger;

		public void Awake()
		{
			logger = Logging.GetLogger();
			logger.Debug("AudidHelper.Awake");
		}

		public void Start()
		{
			logger.Debug("AudioHelper.Start");
			ZRoutedRpc.instance.Register<Vector3, string>("NeoPlayClip", (Action<long, Vector3, string>)RPC_NeoPlayClip);
		}

		public void RPC_NeoPlayClip(long sender, Vector3 sourcePoint, string clipName)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (ZNet.instance.IsDedicated())
			{
				return;
			}
			try
			{
				NeoPlayClip(sourcePoint, clipName);
			}
			catch (Exception e)
			{
				logger.Error(e, stackTrace: false);
			}
		}

		public void Play(Vector3 sourcePoint, string clipName)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "NeoPlayClip", new object[2] { sourcePoint, clipName });
		}

		public void NeoPlayClip(Vector3 sourcePoint, string clipName)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)Player.m_localPlayer).transform.position;
			NeoPlayClip(sourcePoint, position, clipName);
		}

		public void NeoPlayClip(Vector3 sourcePoint, Vector3 targetPoint, string clipName)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			if (!audioClips.TryGetValue(clipName.ToLower(), out var value))
			{
				logger.Warning("Couldn't find audio clip for " + clipName);
				return;
			}
			Vector3 val = sourcePoint - targetPoint;
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			float num = (Vector3.Distance(sourcePoint, targetPoint) + 1f) / 10f;
			AudioSource.PlayClipAtPoint(value, targetPoint + normalized * num, 1f);
		}

		public float GetClipDuration(string clipName)
		{
			if (!audioClips.TryGetValue(clipName.ToLower(), out var value))
			{
				return -1f;
			}
			return value.length;
		}

		internal void LoadAudioResources(string resourceFolder)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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)
			audioClips.Clear();
			logger.Debug("LoadAudioResources");
			string[] files = Directory.GetFiles(resourceFolder, "*.*", SearchOption.TopDirectoryOnly);
			foreach (string text in files)
			{
				string text2 = Path.GetExtension(text).ToLowerInvariant();
				AudioType val = (AudioType)0;
				if (!(text2 == ".wav"))
				{
					if (text2 == ".mp3")
					{
						val = (AudioType)13;
					}
				}
				else
				{
					val = (AudioType)20;
				}
				if ((int)val != 0)
				{
					((MonoBehaviour)this).StartCoroutine(LoadExternalClip(text, val));
				}
			}
		}

		private IEnumerator LoadExternalClip(string filePath, AudioType type)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			string uri = new Uri(filePath).AbsoluteUri;
			string clipName = Path.GetFileName(filePath).ToLowerInvariant();
			UnityWebRequest req = UnityWebRequestMultimedia.GetAudioClip(uri, type);
			yield return req.SendWebRequest();
			if ((int)req.result == 1)
			{
				AudioClip content = DownloadHandlerAudioClip.GetContent(req);
				audioClips[clipName] = content;
				logger.Debug("Loaded external audio: " + clipName);
			}
			else
			{
				logger.Warning("Failed to load external audio: " + uri);
			}
		}
	}
	internal class CircularList<T>
	{
		private List<T> circle;

		private int index;

		public int Index => index;

		public CircularList(List<T> source, T startingElement)
		{
			circle = new List<T>(source);
			index = circle.FindIndex((T x) => x.Equals(startingElement));
		}

		public T Next()
		{
			index = ((index < circle.Count - 1) ? (index + 1) : 0);
			return circle[index];
		}

		public T Previous()
		{
			index = ((index > 0) ? (index - 1) : (circle.Count - 1));
			return circle[index];
		}
	}
	public static class ConfigFolderHelper
	{
		private const string ROOT = "Neobotics";

		public static string GetOrCreateModConfigFolder(string modName)
		{
			string text = Path.Combine(Paths.ConfigPath, "Neobotics", modName);
			Directory.CreateDirectory(text);
			return text;
		}
	}
	public class ConfigMock
	{
		public bool Value { get; set; }
	}
	public class CrossPlatformRandom : Random
	{
		private const int LCG_MULTIPLIER = 134775813;

		private const int LCG_INCREMENT = 1;

		private int _seed;

		public float value => (float)NextDouble();

		public CrossPlatformRandom()
		{
			Random random = new Random();
			_seed = random.Next();
		}

		public CrossPlatformRandom(int seed)
		{
			_seed = seed;
		}

		public float Range(int min, int max)
		{
			return Next(min, max);
		}

		public float Range(float min, float max)
		{
			return Mathf.Lerp(min, max, (float)NextDouble());
		}

		private int GetNext()
		{
			_seed = _seed * 134775813 + 1;
			return _seed;
		}

		public override int Next()
		{
			return Next(int.MaxValue);
		}

		public override int Next(int maxValue)
		{
			if (maxValue < 0)
			{
				throw new ArgumentOutOfRangeException("maxValue is less than zero.");
			}
			return (int)((long)(uint)GetNext() * (long)(uint)maxValue >>> 32);
		}

		public override int Next(int minValue, int maxValue)
		{
			if (minValue > maxValue)
			{
				throw new ArgumentOutOfRangeException("minValue is greater than maxValue.");
			}
			return minValue + Next(maxValue - minValue);
		}

		public override double NextDouble()
		{
			return Sample();
		}

		protected override double Sample()
		{
			return (double)Next() / 2147483647.0;
		}
	}
	internal class CustomDataWrapper
	{
		private Dictionary<string, string> playerData;

		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
	{
		internal 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)("Object: " + o.ToString() + " Type " + type.Name));
			PropertyInfo[] properties = type.GetProperties(bindingAttr);
			foreach (PropertyInfo propertyInfo in properties)
			{
				if (propertyInfo.CanRead)
				{
					Debug.Log((object)$"Property: {type.Name}.{propertyInfo.Name} = {propertyInfo.GetValue(o)}");
					continue;
				}
				Debug.Log((object)("Property: " + type.Name + "." + propertyInfo.Name + " is write-only"));
			}
			FieldInfo[] fields = type.GetFields(bindingAttr);
			foreach (FieldInfo field in fields)
			{
				FieldPrinter(o, type, field);
			}
		}

		internal 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)("Method: " + 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));
			}
		}

		internal static void GameObjectInspector(GameObject go)
		{
			if ((Object)(object)go == (Object)null)
			{
				Debug.Log((object)"\n\nGame Object is null");
				return;
			}
			Debug.Log((object)("\n\nInspecting GameObject " + ((Object)go).name));
			ObjectInspector(go);
			Component[] componentsInChildren = go.GetComponentsInChildren<Component>();
			if (componentsInChildren.Length == 0)
			{
				return;
			}
			Component[] array = componentsInChildren;
			foreach (Component c in array)
			{
				try
				{
					ComponentInspector(c);
				}
				catch (Exception)
				{
				}
			}
		}

		internal static void PrintList<T>(List<T> l)
		{
			foreach (T item in l)
			{
				Debug.Log((object)item.ToString());
			}
		}

		internal static void ComponentInspector(Component c)
		{
			string obj = ((c != null) ? ((Object)c).name : null);
			object obj2;
			if (c == null)
			{
				obj2 = null;
			}
			else
			{
				Transform transform = c.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(c);
		}

		internal 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}");
			}
		}

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

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

		internal static void PrintAllCharacters()
		{
			Character.GetAllCharacters().ForEach(delegate(Character x)
			{
				Debug.Log((object)("Character " + ((Object)x).name));
			});
		}

		internal static void PrintAllLayers()
		{
			string[] array = (from index in Enumerable.Range(0, 31)
				select LayerMask.LayerToName(index) into l
				where !string.IsNullOrEmpty(l)
				select l).ToArray();
			foreach (string text in array)
			{
				Debug.Log((object)("Layer " + text + " " + Convert.ToString(LayerMask.NameToLayer(text), 2).PadLeft(32, '0')));
			}
		}
	}
	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_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			Logging.GetLogger().Trace("ServerDelegate");
			_entry.SettingChanged -= rootHandler;
			ZNet instance = ZNet.instance;
			bool? flag = ((instance != null) ? new bool?(instance.IsServer()) : ((bool?)null));
			if (flag.HasValue)
			{
				if (flag == false && ServerConfiguration.Instance.ReceivedServerValues)
				{
					if (ServerValue != null)
					{
						((ConfigEntryBase)_entry).SetSerializedValue(ServerValue);
						Log.Debug("Setting " + Name + " to server value " + ServerValue);
					}
				}
				else if (flag == true)
				{
					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)
			if (ConfigEntry is ConfigEntry<KeyboardShortcut> val)
			{
				return InputEvaluator.IsPressed(val.Value);
			}
			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)
			if (ConfigEntry is ConfigEntry<KeyboardShortcut> val)
			{
				return InputEvaluator.IsDown(val.Value);
			}
			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)
			if (ConfigEntry is ConfigEntry<KeyboardShortcut> val)
			{
				return InputEvaluator.IsReleased(val.Value);
			}
			Log.Error("Keyboard read attempted on non-KeyboardShortcut config.");
			return false;
		}
	}
	public class DelegatedConfigEntryBase
	{
		public string Name;

		public string Section;

		public string ServerValue;
	}
	internal class HarmonyHelper
	{
		public enum PatchType
		{
			Prefix,
			Postfix,
			Transpiler,
			Finalizer
		}

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

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

		public static IReadOnlyDictionary<string, string> DetectionSet => detectionSet;

		public static void GetDetectionSet(Dictionary<string, string> harmonyIds)
		{
			Logging logger = Logging.GetLogger();
			foreach (KeyValuePair<string, string> harmonyId in harmonyIds)
			{
				if (Harmony.HasAnyPatches(harmonyId.Key))
				{
					logger.Debug("Detected " + harmonyId.Value + " from Harmony");
					if (!detectionSet.ContainsKey(harmonyId.Key))
					{
						detectionSet.Add(harmonyId.Key, harmonyId.Value);
					}
				}
				else if (Chainloader.PluginInfos.ContainsKey(harmonyId.Key))
				{
					logger.Debug("Detected " + harmonyId.Value + " from BepInEx");
					if (!detectionSet.ContainsKey(harmonyId.Key))
					{
						detectionSet.Add(harmonyId.Key, harmonyId.Value);
					}
				}
			}
		}

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

		public static void UnpatchMods(Harmony harmony)
		{
			Logging logger = Logging.GetLogger();
			foreach (KeyValuePair<string, string> unpatchMod in unpatchMods)
			{
				logger.Warning("Not compatible with " + unpatchMod.Value);
				Harmony.UnpatchID(unpatchMod.Key);
				detectionSet.Remove(unpatchMod.Key);
				logger.Warning("Disabled " + unpatchMod.Value);
			}
		}

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

		public static bool IsModNameDetected(string value)
		{
			return detectionSet.ContainsValue(value);
		}

		public static bool TryGetDetectedModName(string key, out string mod)
		{
			return detectionSet.TryGetValue(key, out mod);
		}

		public static bool TryGetDetectedModKey(string value, out string key)
		{
			key = null;
			foreach (string key2 in detectionSet.Keys)
			{
				if (detectionSet[key2] == value)
				{
					key = key2;
					return true;
				}
			}
			return false;
		}

		public static string AddAnonymousPatch(string baseMethodName, PatchType patchType, string modName, string patchMethodName = null)
		{
			string text = null;
			int num = 0;
			Logging logger = Logging.GetLogger();
			foreach (MethodBase item in Harmony.GetAllPatchedMethods().ToList())
			{
				MethodBaseExtensions.HasMethodBody(item);
				Patches patchInfo = Harmony.GetPatchInfo(item);
				ReadOnlyCollection<Patch> readOnlyCollection = patchInfo.Prefixes;
				switch (patchType)
				{
				case PatchType.Postfix:
					readOnlyCollection = patchInfo.Postfixes;
					break;
				case PatchType.Prefix:
					readOnlyCollection = patchInfo.Prefixes;
					break;
				case PatchType.Transpiler:
					readOnlyCollection = patchInfo.Transpilers;
					break;
				case PatchType.Finalizer:
					readOnlyCollection = patchInfo.Finalizers;
					break;
				}
				foreach (Patch item2 in readOnlyCollection)
				{
					if (!item2.owner.StartsWith("harmony-auto") || !(item.Name == baseMethodName))
					{
						continue;
					}
					if (patchMethodName != null)
					{
						if (item2.PatchMethod.Name == patchMethodName)
						{
							num++;
							text = item2.owner;
						}
					}
					else
					{
						num++;
						text = item2.owner;
					}
				}
				if (num == 1)
				{
					detectionSet.Add(text, modName);
					logger.Info($"Added unique anonymous {baseMethodName} {patchType}: {text} as {modName}");
				}
				else if (num > 1)
				{
					text = null;
					logger.Warning($"Found multiple anonymous {baseMethodName} {patchType} entries. Can't identify correct patch to remove or modify.");
				}
			}
			if (num == 0)
			{
				logger.Info("No patch found for " + modName);
			}
			return text;
		}
	}
	public class ImageHelper
	{
		private readonly string externalFolder;

		private readonly Logging logger;

		public ImageHelper(string externalFolder)
		{
			this.externalFolder = externalFolder;
			logger = Logging.GetLogger();
		}

		public Sprite LoadSprite(string name, int width, int height, bool linear = false, float pixelsPerUnit = 100f)
		{
			logger.Debug("Reading image and creating sprite " + name);
			if (TryLoadImage(name, width, height, linear, out var image))
			{
				return LoadSprite(image, pixelsPerUnit);
			}
			return null;
		}

		public Sprite LoadSprite(Texture2D texture, float pixelsPerUnit = 100f)
		{
			return LoadSprite(texture, ((Object)texture).name, ((Texture)texture).width, ((Texture)texture).height, pixelsPerUnit);
		}

		public Sprite LoadSprite(Texture2D texture, string name, float width, float height, float pixelsPerUnit = 100f)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)texture == (Object)null)
			{
				return null;
			}
			if (string.IsNullOrWhiteSpace(name))
			{
				name = ((Object)texture).name;
			}
			logger.Debug("Creating sprite " + name + " from existing texture");
			Sprite obj = Sprite.Create(texture, new Rect(0f, 0f, width, height), Vector2.zero, pixelsPerUnit);
			if ((Object)(object)obj == (Object)null)
			{
				throw new ApplicationException("Can't create sprite " + name);
			}
			((Object)obj).name = name;
			return obj;
		}

		public bool TryLoadImage(string name, int width, int height, bool linear, out Texture2D image)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			image = null;
			string text = Path.Combine(externalFolder, name);
			logger.Debug("Reading external file " + text);
			if (!File.Exists(text))
			{
				throw new FileNotFoundException("Cannot find image " + name);
			}
			byte[] array = File.ReadAllBytes(text);
			Texture2D val = new Texture2D(width, height, (TextureFormat)4, true, linear);
			if (!ImageConversion.LoadImage(val, array, false))
			{
				throw new FileLoadException("Can't load image " + name);
			}
			image = val;
			return true;
		}
	}
	internal class InputCycler
	{
		private static InputCycler _instance;

		private bool useMouseWheel;

		private DelegatedConfigEntry<KeyboardShortcut> keyAdvance;

		private DelegatedConfigEntry<KeyboardShortcut> keyReferse;

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

		private InputCycler()
		{
		}

		public void Init(bool useMouseWheel, DelegatedConfigEntry<KeyboardShortcut> keyAdvance, DelegatedConfigEntry<KeyboardShortcut> keyReverse = null)
		{
			this.useMouseWheel = useMouseWheel;
			this.keyAdvance = keyAdvance;
			keyReferse = keyReverse;
		}
	}
	internal static class InputEvaluator
	{
		public unsafe static bool IsPressed(KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			object obj = KeyboardShortcut.Empty;
			if (((object)(*(KeyboardShortcut*)(&shortcut))/*cast due to .constrained prefix*/).Equals(obj))
			{
				return false;
			}
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
			{
				if ((int)modifier != 0 && !Input.GetKey(modifier))
				{
					return false;
				}
			}
			return Input.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey);
		}

		public unsafe static bool IsDown(KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			object obj = KeyboardShortcut.Empty;
			if (((object)(*(KeyboardShortcut*)(&shortcut))/*cast due to .constrained prefix*/).Equals(obj))
			{
				return false;
			}
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
			{
				if ((int)modifier != 0 && !Input.GetKey(modifier))
				{
					return false;
				}
			}
			return Input.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey);
		}

		public unsafe static bool IsReleased(KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			object obj = KeyboardShortcut.Empty;
			if (((object)(*(KeyboardShortcut*)(&shortcut))/*cast due to .constrained prefix*/).Equals(obj))
			{
				return false;
			}
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
			{
				if ((int)modifier != 0 && !Input.GetKeyUp(modifier))
				{
					return false;
				}
			}
			return Input.GetKeyUp(((KeyboardShortcut)(ref shortcut)).MainKey);
		}
	}
	public class IterativeStopwatch : Stopwatch
	{
		private double startMillis;

		private Logging Log = Logging.GetLogger();

		public long Iterations { get; private set; }

		public double IterationMicroseconds { get; private set; }

		public double TotalElapsedMicroseconds { get; private set; }

		public double IterationMilliseconds { get; private set; }

		public double TotalElapsedMilliseconds { get; private set; }

		public double AverageMicroseconds { get; private set; }

		public double AverageMilliseconds { get; private set; }

		public IterativeStopwatch()
		{
			Iterations = 0L;
		}

		public new void Start()
		{
			startMillis = base.Elapsed.TotalMilliseconds;
			base.Start();
		}

		public new void Stop()
		{
			if (base.IsRunning)
			{
				base.Stop();
				Iterations++;
				IterationMilliseconds = base.Elapsed.TotalMilliseconds - startMillis;
				IterationMicroseconds = IterationMilliseconds * 1000.0;
				TotalElapsedMilliseconds = base.Elapsed.TotalMilliseconds;
				TotalElapsedMicroseconds = base.Elapsed.TotalMilliseconds * 1000.0;
				AverageMilliseconds = TotalElapsedMilliseconds / (double)Iterations;
				AverageMicroseconds = TotalElapsedMicroseconds / (double)Iterations;
			}
		}

		public new void Reset()
		{
			startMillis = 0.0;
			Iterations = 0L;
			base.Reset();
		}

		public new void Restart()
		{
			startMillis = 0.0;
			Iterations = 0L;
			base.Restart();
		}
	}
	public static class JsonHelper
	{
		[Serializable]
		private class JsonWrapper<T>
		{
			public T[] Items;
		}

		public static T[] FromJson<T>(string json)
		{
			return JsonUtility.FromJson<JsonWrapper<T>>(json).Items;
		}

		public static string ToJson<T>(T[] array)
		{
			return JsonUtility.ToJson((object)new JsonWrapper<T>
			{
				Items = array
			});
		}

		public static string ToJson<T>(T[] array, bool prettyPrint)
		{
			return JsonUtility.ToJson((object)new JsonWrapper<T>
			{
				Items = array
			}, prettyPrint);
		}
	}
	public class Logging
	{
		internal enum LogLevels
		{
			Critical,
			Error,
			Warning,
			Info,
			Debug,
			Trace
		}

		private static Logging _instance;

		public static Logging Instance
		{
			get
			{
				if (_instance == null)
				{
					throw new InvalidOperationException("Logging.Instance was accessed before initialization. Call Logging.Initialize() in your mod's startup code first.");
				}
				return _instance;
			}
			private set
			{
				_instance = value;
			}
		}

		internal LogLevels LogLevel { get; set; }

		internal string ModName { get; private set; }

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

		internal static Logging Initialize(LogLevels level, string name)
		{
			if (_instance != null)
			{
				Instance.Warning("Logger is already initialized. Using existing logger");
				return _instance;
			}
			Instance = new Logging(level, name);
			return _instance;
		}

		internal static Logging GetLogger(LogLevels level, string name)
		{
			if (_instance == null)
			{
				Initialize(level, name);
			}
			return Instance;
		}

		internal static Logging GetLogger()
		{
			return Instance;
		}

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

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

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

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

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

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

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

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

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

		internal bool Testing()
		{
			return Instance.LogLevel >= LogLevels.Debug;
		}

		internal static void ChangeLogging(object s, EventArgs e)
		{
			ConfigEntry<LogLevels> val = s as ConfigEntry<LogLevels>;
			if (_instance != null)
			{
				Instance.LogLevel = val.Value;
				Instance.Info($"Change {((ConfigEntryBase)val).Definition.Key} to {val.Value}");
			}
		}
	}
	public static class ModResourceBootstrap
	{
		public static string InitializeModResources(Type pluginType, string modName)
		{
			string orCreateModConfigFolder = ConfigFolderHelper.GetOrCreateModConfigFolder(modName);
			Logging.Instance.Debug("Mod config folder: " + orCreateModConfigFolder);
			string prefix = modName + ".Resources.";
			Logging.Instance.Debug("Mod resources: " + orCreateModConfigFolder);
			ExtractResources(pluginType.Assembly, prefix, orCreateModConfigFolder);
			return orCreateModConfigFolder;
		}

		private static void ExtractResources(Assembly asm, string prefix, string targetFolder)
		{
			Logging.Instance.Debug("Checking resources for " + prefix);
			string[] manifestResourceNames = asm.GetManifestResourceNames();
			foreach (string text in manifestResourceNames)
			{
				Logging.Instance.Debug("Resource " + text);
				if (!text.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
				{
					continue;
				}
				string text2 = text.Substring(prefix.Length);
				string text3 = Path.Combine(targetFolder, text2);
				Logging.Instance.Debug("Extracting " + text2 + " to " + text3);
				if (File.Exists(text3))
				{
					continue;
				}
				using Stream stream = asm.GetManifestResourceStream(text);
				using FileStream destination = File.Create(text3);
				stream.CopyTo(destination);
			}
		}
	}
	public class ServerConfiguration
	{
		[HarmonyPatch(typeof(ZNet), "StopAll")]
		private static class ZNet_Shutdown_Patch
		{
			[HarmonyPrefix]
			private static void ZNet_StopAll_Prefix(ZNet __instance)
			{
				if (_instance != null)
				{
					Log.Debug("ZNet_StopAll_Patch_Prefix");
					_instance.ReceivedServerValues = false;
				}
			}
		}

		[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
					{
						peer.m_rpc.Register<ZPackage>("ClientConfigReceiver." + GetPluginGuid(), (Action<ZRpc, ZPackage>)Instance.RPC_ClientConfigReceiver);
						Log.Debug("Player registered RPC_ClientConfigReceiver");
						return;
					}
					catch (Exception)
					{
						Log.Warning("Failed to register RPC");
						return;
					}
				}
				try
				{
					Instance.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 bool IsSetup;

		public bool ReceivedServerValues;

		public FileSystemWatcher ConfigWatcher;

		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()
		{
			ConfigWatcher = Utils.CreateFileWatcher(LocalConfig.ConfigFilePath, LoadConfig);
		}

		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 void RPC_ClientConfigReceiver(ZRpc zrpc, ZPackage package)
		{
			if (!Instance.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);
				}
			}
			ReceivedServerValues = true;
		}

		internal 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 void SendConfigToClient(ZNetPeer peer)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			if (!Instance.IsSetup)
			{
				Log.Error("ServerConfiguration not initialized. Setup first.");
				return;
			}
			Log.Debug("SendConfigToClient");
			ZPackage val = new ZPackage();
			WriteConfigEntries(val);
			peer.m_rpc.Invoke("ClientConfigReceiver." + GetPluginGuid(), new object[1] { val });
			Log.Trace("Invoked ClientConfigReceiver on peer");
		}

		public void SendConfigToAllClients(object o, SettingChangedEventArgs e)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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 });
					Log.Trace("Invoked ClientConfigReceiver on peer");
				}
				yield return null;
			}
		}
	}
	public 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 string Truncate(string value, int maxChars)
		{
			if (value == null)
			{
				return null;
			}
			if (value.Length <= maxChars)
			{
				return value;
			}
			return value.Substring(0, maxChars);
		}

		public static void GetCharactersInRangeXZ(Vector3 point, float radius, List<Character> characters)
		{
			//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)
			float num = radius * radius;
			foreach (Character s_character in Character.s_characters)
			{
				if (DistanceSqrXZ(((Component)s_character).transform.position, point) < num)
				{
					characters.Add(s_character);
				}
			}
		}

		public static PinData GetClosestPin(Vector3 pos, float radius, PinType pType)
		{
			//IL_004b: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			PinData result = null;
			float num = float.MaxValue;
			float num2 = radius * radius;
			if ((Object)(object)Minimap.instance != (Object)null)
			{
				foreach (PinData pin in Minimap.instance.m_pins)
				{
					if ((Object)(object)pin.m_uiElement != (Object)null && pin.m_type == pType)
					{
						float num3 = DistanceSqrXZ(pos, pin.m_pos);
						if (Logging.Instance.LogLevel >= Logging.LogLevels.Debug)
						{
							Logging.Instance.Debug($"Testing for pin at {pin.m_pos} within radius {radius} from {pos}");
						}
						if (num3 < num2 && num3 < num)
						{
							Logging.Instance.Debug("Pin is within radius");
							num = num3;
							result = pin;
						}
					}
				}
			}
			return result;
		}

		public static float DistanceSqr(Vector3 v0, Vector3 v1)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = v1 - v0;
			return ((Vector3)(ref val)).sqrMagnitude;
		}

		public static float DistanceSqrXZ(Vector3 v0, Vector3 v1)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			float num = v1.x - v0.x;
			float num2 = v1.z - v0.z;
			return num * num + num2 * num2;
		}

		public static Vector3 ClosestPoint<T>(Vector3 point, IEnumerable<T> collection, Func<T, Vector3> selector)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			Vector3 result = default(Vector3);
			float num = float.MaxValue;
			foreach (T item in collection)
			{
				Vector3 val = selector(item);
				Vector3 val2 = val - point;
				float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
				if (sqrMagnitude < num)
				{
					num = sqrMagnitude;
					result = val;
				}
			}
			return result;
		}

		public static T ClosestObject<T>(Vector3 point, IEnumerable<T> collection, Func<T, Vector3> selector)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			T result = default(T);
			float num = float.MaxValue;
			foreach (T item in collection)
			{
				Vector3 val = selector(item) - point;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				if (sqrMagnitude < num)
				{
					num = sqrMagnitude;
					result = item;
				}
			}
			return result;
		}

		public static Vector3 ClosestPointXZ<T>(Vector3 point, IEnumerable<T> collection, Func<T, Vector3> selector)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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)
			Vector3 result = default(Vector3);
			float num = float.MaxValue;
			foreach (T item in collection)
			{
				Vector3 val = selector(item);
				float num2 = DistanceSqrXZ(val, point);
				if (num2 < num)
				{
					num = num2;
					result = val;
				}
			}
			return result;
		}

		public static T ClosestObjectXZ<T>(Vector3 point, IEnumerable<T> collection, Func<T, Vector3> selector)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			T result = default(T);
			float num = float.MaxValue;
			foreach (T item in collection)
			{
				float num2 = DistanceSqrXZ(selector(item), point);
				if (num2 < num)
				{
					num = num2;
					result = item;
				}
			}
			return result;
		}

		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)
		{
			Localization.instance.AddWord("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 string GetAssemblyPathedFile(string fileName)
		{
			return new FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName.Replace('\\', '/') + "/" + fileName;
		}

		public static Sprite GetPrefabIcon(string prefabName)
		{
			Sprite result = null;
			GameObject prefab = GetPrefab(prefabName);
			ItemDrop val = default(ItemDrop);
			if (Object.op_Implicit((Object)(object)prefab) && prefab.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())
			{
				if (((object)allCharacter.GetZDOID()/*cast due to .constrained prefix*/).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_0018: Unknown result type (might be due to invalid IL or missing references)
			List<GameObject> list = new List<GameObject>();
			Object[] array = Object.FindObjectsByType(t, (FindObjectsSortMode)0);
			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)
			float radiusSq = radius * radius;
			return GetGameObjectsOfType(t).Where(delegate(GameObject x)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val = x.transform.position - point;
				return ((Vector3)(ref val)).sqrMagnitude < radiusSq;
			}).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 bool IsPrefabInScene(string prefabName)
		{
			return IsPrefabInScene(StringExtensionMethods.GetStableHashCode(prefabName));
		}

		public static bool IsPrefabInScene(int prefabHash)
		{
			ZNetScene instance = ZNetScene.instance;
			return (Object)(object)((instance != null) ? instance.GetPrefab(prefabHash) : null) != (Object)null;
		}

		public static bool TryGetPrefab(string prefabName, out GameObject prefab)
		{
			return TryGetPrefab(StringExtensionMethods.GetStableHashCode(prefabName), out prefab);
		}

		public static bool TryGetPrefab(int prefabHash, out GameObject prefab)
		{
			prefab = GetPrefabByHash(prefabHash);
			return (Object)(object)prefab != (Object)null;
		}

		public static GameObject GetPrefabByHash(int prefabHash)
		{
			GameObject val = null;
			Logging logger = Logging.GetLogger();
			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;
			}
			val = ObjectDB.instance.GetItemPrefab(prefabHash);
			if ((Object)(object)val != (Object)null)
			{
				logger.Debug("Found prefab in ObjectDB");
				return val;
			}
			logger.Debug("No prefab found");
			return val;
		}

		public static GameObject GetPrefab(int prefabHash)
		{
			return GetPrefabByHash(prefabHash);
		}

		public static GameObject GetPrefab(string prefabName)
		{
			return GetPrefabByHash(StringExtensionMethods.GetStableHashCode(prefabName));
		}

		public static void LoadPrefabInScene(GameObject prefab)
		{
			int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)prefab).name);
			if ((Object)(object)ZNetScene.instance != (Object)null && !ZNetScene.instance.m_namedPrefabs.ContainsKey(stableHashCode))
			{
				ZNetScene.instance.m_prefabs.Add(prefab);
				ZNetScene.instance.m_namedPrefabs[stableHashCode] = prefab;
			}
		}

		public static GameObject SpawnObject(string prefabName, Vector3 position, Quaternion rotation, bool persist = true)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (TryGetPrefab(prefabName, out var prefab))
			{
				return SpawnObject(prefab, position, rotation, persist);
			}
			return null;
		}

		public static GameObject SpawnObject(GameObject prefab, Vector3 position, Quaternion rotation, bool persist = true)
		{
			//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)
			LoadPrefabInScene(prefab);
			GameObject val = Object.Instantiate<GameObject>(prefab, position, rotation);
			ZNetView val2 = default(ZNetView);
			if (persist && val.TryGetComponent<ZNetView>(ref val2))
			{
				val2.GetZDO().Persistent = true;
			}
			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 FileSystemWatcher CreateFileWatcher(string fullPath, FileSystemEventHandler handler)
		{
			string fileName = Path.GetFileName(fullPath);
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(fullPath.Substring(0, fullPath.Length - fileName.Length), fileName);
			fileSystemWatcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime;
			fileSystemWatcher.Changed += handler;
			fileSystemWatcher.Created += handler;
			fileSystemWatcher.IncludeSubdirectories = false;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.EnableRaisingEvents = true;
			return fileSystemWatcher;
		}

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

		public static float TimeAdjustedRamp(float maxValue, float duration, float elapsedTime, float pctFromStartRise, float pctFromEndFall)
		{
			float num = elapsedTime / duration;
			if (num <= pctFromStartRise)
			{
				return maxValue * (num / pctFromStartRise);
			}
			if (num >= 1f - pctFromEndFall)
			{
				return maxValue * ((1f - num) / pctFromEndFall);
			}
			return maxValue;
		}

		public static Color IntToColor(int rgba)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			float num = (float)((rgba >> 16) & 0xFF) / 255f;
			float num2 = (float)((rgba >> 8) & 0xFF) / 255f;
			float num3 = (float)(rgba & 0xFF) / 255f;
			float num4 = (float)((rgba >> 24) & 0xFF) / 255f;
			return new Color(num, num2, num3, num4);
		}

		public static bool CopyComponentToGameObject(Component original, ref GameObject destination)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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.op_Implicit((Object)(object)val))
			{
				val = destination.AddComponent(type);
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				logger.Debug("Destination component is null");
				return false;
			}
			Component val2 = (Component)Activator.CreateInstance(type);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				logger.Debug("Destination component is null");
				return false;
			}
			if (!Object.op_Implicit((Object)(object)val2))
			{
				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");
				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;
		}
	}
}
namespace neobotics.ValheimMods
{
	internal class Cfg
	{
		public static DelegatedConfigEntry<bool> guardAttacks;

		public static DelegatedConfigEntry<Logging.LogLevels> debugLevel;

		public static DelegatedConfigEntry<bool> biomeRestriction;

		public static DelegatedConfigEntry<bool> bossProgression;

		public static DelegatedConfigEntry<int> piecesNeeded;

		public static DelegatedConfigEntry<int> proximityCheckRadius;

		public static DelegatedConfigEntry<int> stationsNeeded;

		public static DelegatedConfigEntry<int> bedsNeeded;

		public static DelegatedConfigEntry<string> creatureBiomeMapping;

		public static DelegatedConfigEntry<bool> allowLevels;

		public static void BepInExConfig(BaseUnityPlugin _instance)
		{
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Expected O, but got Unknown
			ServerConfiguration.Instance.Setup(_instance.Config, _instance);
			debugLevel = new DelegatedConfigEntry<Logging.LogLevels>(ChangeLogging);
			debugLevel.ConfigEntry = _instance.Config.Bind<Logging.LogLevels>("Utility", "LogLevel", Logging.LogLevels.Info, "Controls the level of information contained in the log");
			Logging.GetLogger().LogLevel = debugLevel.Value;
			biomeRestriction = new DelegatedConfigEntry<bool>(useServerDelegate: true);
			biomeRestriction.ConfigEntry = _instance.Config.Bind<bool>("Restrictions", "Limit by biome", false, "If enabled, restricts summoned creatures to those that can spawn in the selected ward's biome, or 'higher' biomes, e.g. a Troll can be summoned to a ward in the Plains, but a Seeker cannot.@");
			bossProgression = new DelegatedConfigEntry<bool>(useServerDelegate: true);
			bossProgression.ConfigEntry = _instance.Config.Bind<bool>("Restrictions", "Limit by Progression", false, "If enabled, allows creatures to be summoned in 'lower' biomes once a boss is defeated, e.g. Once Bonemass is defeated, a Draugr can be summoned to a ward in the Meadows, Black Forest and Swamp.@");
			piecesNeeded = new DelegatedConfigEntry<int>(useServerDelegate: true);
			piecesNeeded.ConfigEntry = _instance.Config.Bind<int>("Restrictions", "Minimum Base Pieces", 100, "The minimum number of build pieces that must be in proximity to the ward to be considered a 'base' (based on the Piece Check Radius)@");
			proximityCheckRadius = new DelegatedConfigEntry<int>(useServerDelegate: true);
			proximityCheckRadius.ConfigEntry = _instance.Config.Bind<int>("Restrictions", "Base Check Radius", 50, "The radius from the ward to check for a 'base' that allows the ward to be used for summoning a guard.@");
			stationsNeeded = new DelegatedConfigEntry<int>(useServerDelegate: true);
			stationsNeeded.ConfigEntry = _instance.Config.Bind<int>("Restrictions", "Minimum Base Crafting Stations", 1, "The minimum number of crafting stations that must be in proximity to the ward to be considered a 'base' (based on the Piece Check Radius)@");
			bedsNeeded = new DelegatedConfigEntry<int>(useServerDelegate: true);
			bedsNeeded.ConfigEntry = _instance.Config.Bind<int>("Restrictions", "Minimum Base Beds", 1, "The minmium number of beds that must be in proximity to the ward to be considered a 'base' (based on the Piece Check Radius)@");
			allowLevels = new DelegatedConfigEntry<bool>(useServerDelegate: true);
			allowLevels.ConfigEntry = _instance.Config.Bind<bool>("Restrictions", "Enable Guardian Levels", true, "If enabled, allows trophies from 'starred' creatures to summon guardians of the same level, i.e. a trophy from a 2-star will summon a 2-star guardian.@");
			creatureBiomeMapping = new DelegatedConfigEntry<string>(DefendYourBase.ChangeBiomeMapping, useServerDelegate: true);
			creatureBiomeMapping.ConfigEntry = _instance.Config.Bind<string>("Hidden", "Creature Biome Mapping", DefendYourBase.creatureConfigString, new ConfigDescription("The list of creature-to-biome mappings. Used by server authoritative configs only. Edit the CreatureBiomeMap.txt file to change local mapping.@", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Browsable = false
				}
			}));
			ServerConfiguration.Instance.CreateConfigWatcher();
		}

		public static void ChangeLogging(object s, EventArgs e)
		{
			Logging logger = Logging.GetLogger();
			SettingChangedEventArgs e2 = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null);
			logger.Debug($"ChangeLog {e2.ChangedSetting.Definition.Key} to {e2.ChangedSetting.BoxedValue}");
			logger.LogLevel = debugLevel.Value;
		}
	}
	internal class CreatureInfo
	{
		public string Name { get; }

		public bool Tamed { get; }

		public bool Tapped { get; }

		public bool Boss { get; }

		public int Level { get; }

		public bool DropsEnabled { get; }

		public CreatureInfo(string name, bool tamed, bool tapped, bool boss, int level, bool dropsEnabled)
		{
			Name = name;
			Tamed = tamed;
			Tapped = tapped;
			Boss = boss;
			Level = level;
			DropsEnabled = dropsEnabled;
		}
	}
	[BepInPlugin("neobotics.valheim_mod.defendyourbase", "DefendYourBase", "0.2.6")]
	[BepInProcess("valheim.exe")]
	[BepInProcess("valheim_server.exe")]
	public class DefendYourBase : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(Character), "RaiseSkill")]
		private static class Character_RaiseSkill_Patch
		{
			[HarmonyPrefix]
			private static bool Character_RaiseSkill_Prefix(Character __instance)
			{
				Log.Debug("Character_RaiseSkill_Patch_Prefix");
				Vector3 val = default(Vector3);
				if (__instance.m_nview.GetZDO().GetVec3(GUARD_PATROL_POINT, ref val))
				{
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		private static class ZNetScene_Awake_Patch
		{
			[HarmonyPostfix]
			private static void ZNetScene_Awake_Postfix(ZNetScene __instance)
			{
				Log.Debug("ZNetScene_Awake_Patch_Postfix");
				BuildTrophyCreatureMap();
			}
		}

		[HarmonyPatch(typeof(PrivateArea), "UseItem")]
		private static class PrivateArea_UseItem_Patch
		{
			[HarmonyPostfix]
			private static void PrivateArea_UseItem_Postfix(PrivateArea __instance, Humanoid user, ItemData item, ref bool __result)
			{
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: Invalid comparison between Unknown and I4
				//IL_012f: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
				//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
				//IL_03b1: Unknown result type (might be due to invalid IL or missing references)
				//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
				//IL_03c6: Unknown result type (might be due to invalid IL or missing references)
				//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
				//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_03d4: Unknown result type (might be due to invalid IL or missing references)
				//IL_03d6: 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_0341: Unknown result type (might be due to invalid IL or missing references)
				//IL_0346: Unknown result type (might be due to invalid IL or missing references)
				//IL_04b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_0440: Unknown result type (might be due to invalid IL or missing references)
				//IL_0451: Unknown result type (might be due to invalid IL or missing references)
				//IL_04e1: Unknown result type (might be due to invalid IL or missing references)
				//IL_04e6: Unknown result type (might be due to invalid IL or missing references)
				//IL_050e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0513: Unknown result type (might be due to invalid IL or missing references)
				//IL_04a0: Unknown result type (might be due to invalid IL or missing references)
				Log.Debug("PrivateArea_UseItem_Patch_Postfix");
				if (!((Character)user).IsPlayer())
				{
					return;
				}
				if ((int)item.m_shared.m_itemType != 13)
				{
					Log.Debug(item.m_shared.m_name + " is not a trophy");
					return;
				}
				__result = true;
				int quality = item.m_quality;
				if (!trophyCreatureMap.TryGetValue(item.m_shared.m_name, out var value))
				{
					Log.Debug("Trophy not mapped");
					((Character)Player.m_localPlayer).Message((MessageType)2, "$msg_neobotics_dyb_cant_summon", 0, (Sprite)null);
					return;
				}
				Player val = (Player)(object)((user is Player) ? user : null);
				if (__instance.GetCreatorName() != val.GetPlayerName())
				{
					Log.Debug("Can't summon on someone else's ward");
					((Character)Player.m_localPlayer).Message((MessageType)2, "$msg_neobotics_dyb_others_ward", 0, (Sprite)null);
					return;
				}
				if (__instance.m_nview.GetZDO().GetBool(WARD_FLAG, false))
				{
					Log.Debug("Ward already has a guard");
					((Character)Player.m_localPlayer).Message((MessageType)2, "$msg_neobotics_dyb_has_guard", 0, (Sprite)null);
					return;
				}
				if ((Cfg.piecesNeeded.Value > 0 || Cfg.stationsNeeded.Value > 0) && Cfg.proximityCheckRadius.Value > 0 && !CheckPiecesInRadius(((Component)__instance).transform.position, Cfg.proximityCheckRadius.Value, Cfg.piecesNeeded.Value, Cfg.stationsNeeded.Value, Cfg.bedsNeeded.Value))
				{
					Log.Debug("Ward is not close enough to a large enough base");
					((Character)Player.m_localPlayer).Message((MessageType)2, "$msg_neobotics_dyb_not_close", 0, (Sprite)null);
					return;
				}
				List<ZDO> list = new List<ZDO>();
				if (GetAllGuardedWardZDOs(list))
				{
					foreach (ZDO item2 in list)
					{
						if (Vector3.Distance(item2.m_position, ((Component)__instance).transform.position) < __instance.m_radius)
						{
							Log.Debug("A guarded ward is within selected ward's radius of protection");
							((Character)Player.m_localPlayer).Message((MessageType)2, "$msg_neobotics_dyb_one_guard", 0, (Sprite)null);
							return;
						}
					}
				}
				GameObject prefabByHash = Utils.GetPrefabByHash(value);
				string empty = string.Empty;
				if ((Object)(object)prefabByHash == (Object)null)
				{
					Log.Warning("Can't find creature prefab for trophy.");
					return;
				}
				MonsterAI val2 = default(MonsterAI);
				if (!prefabByHash.TryGetComponent<MonsterAI>(ref val2))
				{
					Log.Debug("Creature has no MonsterAI");
					((Character)Player.m_localPlayer).Message((MessageType)2, "$msg_neobotics_dyb_cant_summon", 0, (Sprite)null);
					return;
				}
				Character val3 = default(Character);
				if (!prefabByHash.TryGetComponent<Character>(ref val3))
				{
					Log.Warning("Creature has no Character");
					((Character)Player.m_localPlayer).Message((MessageType)2, "$msg_neobotics_dyb_cant_summon", 0, (Sprite)null);
					return;
				}
				if (val3.m_boss)
				{
					Log.Debug("Can't summon a boss");
					((Character)Player.m_localPlayer).Message((MessageType)2, "$msg_neobotics_dyb_no_boss", 0, (Sprite)null);
					return;
				}
				bool flag = true;
				bool flag2 = false;
				if (Cfg.bossProgression.Value)
				{
					flag2 = CheckBossLevel(((Component)__instance).transform.position, item.m_shared.m_name);
					flag = false;
				}
				if (Cfg.biomeRestriction.Value)
				{
					flag = CheckGuardBiome(((Component)__instance).transform.position, item.m_shared.m_name);
				}
				if (!(flag || flag2))
				{
					Log.Debug($"Guard not valid for biome {flag} or boss {flag2}");
					string text = ((object)Heightmap.FindBiome(((Component)__instance).transform.position)/*cast due to .constrained prefix*/).ToString().ToLower();
					string arg = Localization.instance.Localize("$biome_" + text);
					string text2 = string.Format(Localization.instance.Localize("$msg_neobotics_dyb_guard_biome"), arg);
					((Character)Player.m_localPlayer).Message((MessageType)2, text2, 0, (Sprite)null);
					return;
				}
				Log.Debug("Summoning Guard");
				Vector3 position = ((Component)__instance).transform.position + ((Component)__instance).transform.forward * 2f;
				GameObject val4 = Utils.SpawnObject(prefabByHash, position, Quaternion.identity);
				Character val5 = default(Character);
				if (!((Object)(object)val4 != (Object)null) || !val4.TryGetComponent<Character>(ref val5))
				{
					return;
				}
				ConsumeItem(user, item);
				empty = val5.m_name;
				ZNetView nview = val5.m_nview;
				if ((Object)(object)nview != (Object)null && nview.IsValid())
				{
					ZDO zDO = nview.GetZDO();
					zDO.Set(GUARD_PATROL_POINT, ((Component)__instance).transform.position);
					ZDOMan.instance.ForceSendZDO(zDO.m_uid);
				}
				if ((Object)(object)__instance.m_nview != (Object)null && __instance.m_nview.IsValid())
				{
					ZDO zDO2 = __instance.m_nview.GetZDO();
					if (zDO2.IsOwner())
					{
						zDO2.Set(WARD_FLAG, true);
						ZDOMan.instance.ForceSendZDO(zDO2.m_uid);
					}
				}
				SetUpGuard(val4, __instance.m_radius, ((Component)__instance).transform.position, quality);
				GameObject prefab = Utils.GetPrefab("vfx_spawn");
				if (Object.op_Implicit((Object)(object)prefab))
				{
					Object.Instantiate<GameObject>(prefab, ((Component)__instance).transform.position, Quaternion.identity);
				}
				GameObject prefab2 = Utils.GetPrefab("sfx_offering");
				if (Object.op_Implicit((Object)(object)prefab2))
				{
					Object.Instantiate<GameObject>(prefab2, ((Component)__instance).transform.position, Quaternion.identity);
				}
				string arg2 = Localization.instance.Localize(empty);
				string text3 = string.Format(Localization.instance.Localize("$msg_neobotics_dyb_summoned"), arg2);
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Character)localPlayer).Message((MessageType)2, text3, 0, (Sprite)null);
				}
			}
		}

		[HarmonyPatch(typeof(Character), "OnDeath")]
		private static class Character_OnDeath_Patch
		{
			[HarmonyPrefix]
			private static void Character_OnDeath_Prefix(Character __instance)
			{
				//IL_0086: Unknown result type (might be due to invalid IL or missing references)
				Log.Debug("Character_OnDeath_Patch_Prefix");
				Vector3 position = default(Vector3);
				if (!__instance.m_nview.GetZDO().GetVec3(GUARD_PATROL_POINT, ref position))
				{
					return;
				}
				Log.Debug("Guardian died");
				List<ZDO> list = new List<ZDO>();
				if (GetAllGuardedWardZDOs(list))
				{
					ZDO val = list.Find((ZDO x) => x.m_position == position);
					if (val != null)
					{
						Log.Debug("Guardian ward found");
						val.Set(WARD_FLAG, false);
						ZDOMan.instance.ForceSendZDO(val.m_uid);
					}
				}
			}
		}

		[HarmonyPatch(typeof(BaseAI), "IsEnemy", new Type[]
		{
			typeof(Character),
			typeof(Character)
		})]
		private static class BaseAI_IsEnemy_Patch
		{
			[HarmonyPostfix]
			private static void BaseAI_IsEnemy_Postfix(BaseAI __instance, Character a, Character b, ref bool __result)
			{
				if (!((Object)(object)__instance == (Object)null) && !((Object)(object)a == (Object)null) && !((Object)(object)b == (Object)null))
				{
					object obj;
					if (a == null)
					{
						obj = null;
					}
					else
					{
						ZNetView nview = a.m_nview;
						obj = ((nview != null) ? nview.GetZDO() : null);
					}
					ZDO val = (ZDO)obj;
					object obj2;
					if (b == null)
					{
						obj2 = null;
					}
					else
					{
						ZNetView nview2 = b.m_nview;
						obj2 = ((nview2 != null) ? nview2.GetZDO() : null);
					}
					ZDO val2 = (ZDO)obj2;
					Vector3 val3 = default(Vector3);
					if (val != null && val2 != null && ((val.GetVec3(WARD_FLAG, ref val3) && !b.m_tamed) || (val2.GetVec3(WARD_FLAG, ref val3) && !a.m_tamed)))
					{
						__result = true;
					}
				}
			}
		}

		[HarmonyPatch(typeof(MonsterAI), "UpdateTarget")]
		private static class MonsterAI_UpdateTarget_Patch
		{
			[HarmonyPostfix]
			private static void MonsterAI_UpdateTarget_Postfix(MonsterAI __instance, Humanoid humanoid, float dt)
			{
				ZDO val = ((BaseAI)(__instance?)).m_nview?.m_zdo;
				Vector3 val2 = default(Vector3);
				if (val != null && val.GetVec3(GUARD_PATROL_POINT, ref val2) && ((BaseAI)__instance).IsAlerted() && (Object)(object)__instance.m_targetCreature == (Object)null && __instance.m_timeSinceSensedTargetCreature > 1f)
				{
					((BaseAI)__instance).SetAlerted(false);
					__instance.m_targetCreature = null;
					__instance.m_targetStatic = null;
					__instance.m_timeSinceAttacking = 0f;
					__instance.m_updateTargetTimer = 0f;
				}
			}
		}

		[HarmonyPatch(typeof(BaseAI), "ResetRandomMovement")]
		private static class BaseAI_ResetRandomMovement_Patch
		{
			[HarmonyPrefix]
			private static void BaseAI_ResetRandomMovement_Prefix(BaseAI __instance)
			{
				Log.Debug("BaseAI_ResetRandomMovement_Patch_Prefix");
			}

			[HarmonyPostfix]
			private static void BaseAI_ResetRandomMovement_Postfix(BaseAI __instance)
			{
				Log.Debug("BaseAI_ResetRandomMovement_Patch_Postfix");
			}
		}

		[HarmonyPatch(typeof(WearNTear), "Destroy")]
		private static class WearNTear_Destroy_Patch
		{
			[HarmonyPrefix]
			private static void WearNTear_Destroy_Prefix(WearNTear __instance)
			{
				//IL_0052: Unknown result type (might be due to invalid IL or missing references)
				//IL_0057: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_007e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0083: Unknown result type (might be due to invalid IL or missing references)
				Log.Debug("WearNTear_Destroy_Patch_Prefix");
				if (!__instance.m_nview.GetZDO().GetBool(WARD_FLAG, false))
				{
					return;
				}
				List<ZDO> list = new List<ZDO>();
				if (!TryGetGuardZDOs(list))
				{
					return;
				}
				foreach (ZDO item in list)
				{
					if (item.GetVec3(GUARD_PATROL_POINT, Vector3.zero) == ((Component)__instance).gameObject.transform.position)
					{
						Object.Instantiate<GameObject>(Utils.GetPrefab("vfx_odin_despawn"), item.m_position, Quaternion.identity);
						ZNetView val = ZNetScene.instance.FindInstance(item);
						if ((Object)(object)val != (Object)null)
						{
							val.Destroy();
						}
						break;
					}
				}
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "CreateObject")]
		private static class ZNetScene_CreateObject_Patch
		{
			[HarmonyPostfix]
			private static void ZNetScene_CreateObject_Postfix(ZNetScene __instance, ZDO zdo, ref GameObject __result)
			{
				//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
				Vector3 patrolPoint = default(Vector3);
				if ((Object)(object)__result == (Object)null || !zdo.GetVec3(GUARD_PATROL_POINT, ref patrolPoint))
				{
					return;
				}
				Log.Debug("Creating tamed Guard");
				if (privateAreaRadius == 0f)
				{
					privateAreaRadius = 32f;
					GameObject prefab = Utils.GetPrefab("guard_stone");
					if ((Object)(object)prefab != (Object)null)
					{
						PrivateArea val = default(PrivateArea);
						if (prefab.TryGetComponent<PrivateArea>(ref val))
						{
							privateAreaRadius = val.m_radius;
							Log.Debug($"Setting Ward radius to {privateAreaRadius}");
						}
						else
						{
							Log.Debug("Can't get Ward PrivateArea");
						}
					}
					else
					{
						Log.Debug("Cant find Ward prefab");
					}
				}
				SetUpGuard(__result, privateAreaRadius, patrolPoint);
			}
		}

		[HarmonyPatch(typeof(CharacterDrop), "OnDeath")]
		private static class CharacterDrop_OnDeath_Patch
		{
			[HarmonyPrefix]
			private static void CharacterDrop_OnDeath_Prefix(CharacterDrop __instance)
			{
				if (Cfg.allowLevels.Value)
				{
					Log.Debug("CharacterDrop_OnDeath_Patch_Prefix");
					Character character = __instance.m_character;
					if ((Object)(object)character != (Object)null && !character.IsPlayer() && character.GetLevel() > 0)
					{
						s_tempCreatureLevel = character.GetLevel();
					}
				}
			}

			[HarmonyPostfix]
			private static void CharacterDrop_OnDeath_Postfix(CharacterDrop __instance, ref CreatureInfo __state)
			{
				if (Cfg.allowLevels.Value)
				{
					Log.Debug("CharacterDrop_OnDeath_Patch_Postfix");
					s_tempCreatureLevel = 0;
				}
			}
		}

		[HarmonyPatch(typeof(CharacterDrop), "DropItems")]
		[HarmonyPriority(0)]
		private static class CharacterDrop_DropItems_Patch
		{
			[HarmonyPrefix]
			private static bool CharacterDrop_DropItems_Prefix(CharacterDrop __instance, List<KeyValuePair<GameObject, int>> drops, Vector3 centerPos, float dropArea, bool ___m_dropsEnabled)
			{
				//IL_0056: Unknown result type (might be due to invalid IL or missing references)
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_005c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_0078: Unknown result type (might be due to invalid IL or missing references)
				//IL_009c: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a3: Invalid comparison between Unknown and I4
				//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
				//IL_0102: 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_0128: Unknown result type (might be due to invalid IL or missing references)
				//IL_012f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0119: Unknown result type (might be due to invalid IL or missing references)
				Log.Debug("CharacterDrop_DropItems_Patch_Prefix");
				if (!Cfg.allowLevels.Value || s_tempCreatureLevel <= 0)
				{
					return true;
				}
				foreach (KeyValuePair<GameObject, int> drop in drops)
				{
					for (int i = 0; i < drop.Value; i++)
					{
						Quaternion val = Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f);
						Vector3 val2 = Random.insideUnitSphere * dropArea;
						GameObject obj = Object.Instantiate<GameObject>(drop.Key, centerPos + val2, val);
						ItemDrop component = obj.GetComponent<ItemDrop>();
						if ((Object)(object)component != (Object)null && (int)component.m_itemData.m_shared.m_itemType == 13)
						{
							Log.Debug("Adding level to trophy");
							component.m_itemData.m_quality = s_tempCreatureLevel;
							component.m_itemData.m_shared.m_maxQuality = s_tempCreatureLevel;
							component.m_itemData.m_worldLevel = (byte)Game.m_worldLevel;
						}
						Rigidbody component2 = obj.GetComponent<Rigidbody>();
						if (Object.op_Implicit((Object)(object)component2))
						{
							Vector3 insideUnitSphere = Random.insideUnitSphere;
							if (insideUnitSphere.y < 0f)
							{
								insideUnitSphere.y = 0f - insideUnitSphere.y;
							}
							component2.AddForce(insideUnitSphere * 5f, (ForceMode)2);
						}
					}
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(Ragdoll), "SaveLootList")]
		private static class Ragdoll_SaveLootList_Patch
		{
			[HarmonyPostfix]
			private static void Ragdoll_SaveLootList_Postfix(Ragdoll __instance, CharacterDrop characterDrop, ZNetView ___m_nview)
			{
				//IL_0086: Unknown result type (might be due to invalid IL or missing references)
				if (!Cfg.allowLevels.Value)
				{
					return;
				}
				Log.Debug("Ragdoll_SaveLootList_Patch_Postfix");
				Character character = characterDrop.m_character;
				if ((Object)(object)character?.m_nview != (Object)null && !character.IsPlayer() && character.GetLevel() > 0)
				{
					ZDO zDO = __instance.m_nview.GetZDO();
					if (zDO != null && zDO.IsValid())
					{
						Log.Debug("Setting character level on Ragdoll zdo");
						zDO.Set(TROPHY_LEVEL, character.GetLevel(), false);
						ZDOMan.instance.ForceSendZDO(zDO.m_uid);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Ragdoll), "SpawnLoot")]
		private static class Ragdoll_SpawnLoot_Patch
		{
			[HarmonyPrefix]
			private static void Ragdoll_SpawnLoot_Prefix(Ragdoll __instance, Vector3 center)
			{
				if (Cfg.allowLevels.Value)
				{
					Log.Debug("Ragdoll_SpawnLoot_Patch_Postfix");
					ZDO zDO = __instance.m_nview.GetZDO();
					if (zDO.IsValid() && zDO.GetInt(TROPHY_LEVEL, 0) > 0)
					{
						s_tempCreatureLevel = zDO.GetInt(TROPHY_LEVEL, 0);
					}
				}
			}

			[HarmonyPostfix]
			private static void Ragdoll_SpawnLoot_Postfix(Ragdoll __instance, Vector3 center, ZNetView ___m_nview)
			{
				if (Cfg.allowLevels.Value)
				{
					Log.Debug("Ragdoll_SpawnLoot_Patch_Postfix");
					s_tempCreatureLevel = 0;
				}
			}
		}

		[HarmonyPatch(typeof(BaseAI), "Flee")]
		private static class BaseAI_Flee_Patch
		{
			[HarmonyPrefix]
			private static bool BaseAI_Flee_Prefix(BaseAI __instance, float dt, Vector3 from)
			{
				ZDO val = __instance?.m_nview?.m_zdo;
				Vector3 val2 = default(Vector3);
				if (val != null && val.GetVec3(GUARD_PATROL_POINT, ref val2))
				{
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(InventoryGrid), "UpdateGui")]
		private static class InventoryGrid_UpdateGui_Patch
		{
			[HarmonyPostfix]
			private static void InventoryGrid_UpdateGui_Postfix(InventoryGrid __instance)
			{
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Invalid comparison between Unknown and I4
				if (!Cfg.allowLevels.Value)
				{
					return;
				}
				foreach (ItemData allItem in __instance.m_inventory.GetAllItems())
				{
					if ((int)allItem.m_shared.m_itemType != 13)
					{
						continue;
					}
					Element element = __instance.GetElement(allItem.m_gridPos.x, allItem.m_gridPos.y, __instance.m_width);
					if (((Behaviour)element.m_icon).enabled)
					{
						int num = allItem.m_quality - 1;
						if (num > 0)
						{
							((Behaviour)element.m_quality).enabled = true;
							element.m_quality.text = num.ToString();
						}
					}
				}
			}
		}

		private static DefendYourBase _modInstance;

		private static string Mod = "DefendYourBase";

		private static string LcMod = Mod.ToLower();

		public static Logging Log;

		public static Faction tamedGuardFaction = (Faction)StringExtensionMethods.GetStableHashCode("TamedGuard");

		private static string s_configPath;

		public static int GUARD_PATROL_POINT = StringExtensionMethods.GetStableHashCode("Tamed_Guard");

		public static int WARD_FLAG = StringExtensionMethods.GetStableHashCode("Guarded_Ward");

		public static string TROPHY_STRING = "DYB_CL_1847_";

		public static int TROPHY_LEVEL = StringExtensionMethods.GetStableHashCode(TROPHY_STRING);

		private const string CANNOT_BE_SUMMONED = "$msg_neobotics_dyb_cant_summon";

		internal static int s_tempCreatureLevel = 0;

		private static List<int> prefabHashes = new List<int>();

		private static float privateAreaRadius = 0f;

		private static FileSystemWatcher mappingWatcher = null;

		private static List<string> hauntNames = new List<string>();

		private static Harmony harmony = null;

		private static IDictionary<string, int> trophyCreatureMap = new Dictionary<string, int>();

		private static Dictionary<Biome, int> biomeValues = new Dictionary<Biome, int>
		{
			{
				(Biome)1,
				1
			},
			{
				(Biome)8,
				2
			},
			{
				(Biome)2,
				3
			},
			{
				(Biome)4,
				4
			},
			{
				(Biome)16,
				5
			},
			{
				(Biome)512,
				6
			},
			{
				(Biome)32,
				7
			},
			{
				(Biome)64,
				8
			},
			{
				(Biome)256,
				3
			}
		};

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

		public static string creatureConfigString = "$item_trophy_greydwarf,1;$item_trophy_greydwarfbrute,1;$item_trophy_greydwarfshaman,1;$item_trophy_boar,1;$item_trophy_neck,1;$item_trophy_skeleton,1;$item_trophy_troll,2;$item_trophy_skeleton_hildir,3;$item_trophy_skeletonpoison,3;$item_trophy_wraith,3;$item_trophy_abomination,3;$item_trophy_blob,3;$item_trophy_draugr,3;$item_trophy_draugrelite,3;$item_trophy_leech,3;$item_trophy_surtling,3;$item_trophy_fenring,4;$item_trophy_cultist,4;$item_trophy_sgolem,4;$item_trophy_cultist_hildir,4;$item_trophy_ulv,4;$item_trophy_wolf,4;$item_trophy_goblin,5;$item_trophy_goblinbrute,5;$item_trophy_brutebro,5;$item_trophy_goblinshaman,5;$item_trophy_shamanbro,5;$item_trophy_deathsquito,5;$item_trophy_growth,5;$item_trophy_lox,5;$item_trophy_gjall,6;$item_trophy_dvergr,6;$item_trophy_seeker,6;$item_trophy_seeker_brute,6;$item_trophy_hatchling,4;$item_trophy_tick,6;$item_trophy_asksvin,7;$item_trophy_bonemaw,7;$item_trophy_charredarcher,7 ;$item_trophy_charredmage,7;$item_trophy_charredmelee,7;$item_trophy_fader,7;$item_trophy_fallenvalkyrie,7;$item_trophy_morgen,7;$item_trophy_volture,7;$item_trophy_serpent,3";

		public static DefendYourBase GetInstance()
		{
			return _modInstance;
		}

		private void Awake()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			_modInstance = this;
			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);
			Cfg.BepInExConfig((BaseUnityPlugin)(object)_modInstance);
			s_configPath = ModResourceBootstrap.InitializeModResources(typeof(DefendYourBase), Mod);
			new Localizer(Mod);
			SetCreatureBiomeMapping();
			BuildTrophyBiomeMap(creatureConfigString);
			if (Cfg.creatureBiomeMapping.Value != creatureConfigString)
			{
				Cfg.creatureBiomeMapping.Value = creatureConfigString;
			}
		}

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

		private static void BuildTrophyBiomeMap(string stringMapping)
		{
			Log.Debug("BuildTrophyBiomeMap");
			trophyBiomeMap.Clear();
			string[] array = stringMapping.Split(';');
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(',');
				if (array2.Length == 2 && int.TryParse(array2[1], out var result))
				{
					string text = array2[0].Trim();
					if (!trophyBiomeMap.ContainsKey(text))
					{
						trophyBiomeMap.Add(text, result);
						Log.Debug($"Added trophy {text} with biome {result}");
					}
				}
			}
		}

		public static void ChangeBiomeMapping(object s, EventArgs e)
		{
			SettingChangedEventArgs e2 = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null);
			Log.Debug("ChangeBiomeMapping " + e2.ChangedSetting.Definition.Key);
			creatureConfigString = Cfg.creatureBiomeMapping.Value;
			BuildTrophyBiomeMap(Cfg.creatureBiomeMapping.Value);
		}

		public static bool SetCreatureBiomeMapping()
		{
			Log.Debug("SetCreatureBiomeMapping");
			try
			{
				string text = Path.Combine(s_configPath, "CreatureBiomeMap.txt");
				Log.Debug("Using config file " + text);
				if (!File.Exists(text))
				{
					Log.Warning("Creature mapping file is missing. Using vanilla assignment.");
					return false;
				}
				string[] value = File.ReadAllLines(text);
				creatureConfigString = string.Join(";", value).Replace(" ", string.Empty);
				if (mappingWatcher == null)
				{
					mappingWatcher = Utils.CreateFileWatcher(text, ReloadMapping);
					Log.Debug("Created mapping file watcher");
				}
			}
			catch (Exception)
			{
				Log.Warning("Can't read external creature mapping file. Using vanilla assignment.");
				return false;
			}
			return true;
		}

		private static void ReloadMapping()
		{
			Log.Debug("ReloadMapping");
			if (SetCreatureBiomeMapping())
			{
				Log.Debug("Reloading creature biome mapping from file");
				if (Cfg.creatureBiomeMapping.Value != creatureConfigString)
				{
					Cfg.creatureBiomeMapping.Value = creatureConfigString;
					Log.Trace(Cfg.creatureBiomeMapping.Value);
				}
			}
		}

		private static void ReloadMapping(object sender, FileSystemEventArgs e)
		{
			ReloadMapping();
		}

		public static void BuildTrophyCreatureMap()
		{
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Invalid comparison between Unknown and I4
			Log.Debug("BuildTrophyCreatureMap");
			CharacterDrop val = default(CharacterDrop);
			ItemDrop val2 = default(ItemDrop);
			foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
			{
				Character component = (Character)(object)prefab.GetComponent<Humanoid>();
				if ((Object)(object)component == (Object)null)
				{
					component = prefab.GetComponent<Character>();
				}
				if (!((Object)(object)component != (Object)null) || !prefab.TryGetComponent<CharacterDrop>(ref val))
				{
					continue;
				}
				foreach (Drop drop in val.m_drops)
				{
					if ((Object)(object)drop.m_prefab != (Object)null && drop.m_prefab.TryGetComponent<ItemDrop>(ref val2) && (int)val2.m_itemData.m_shared.m_itemType == 13 && !trophyCreatureMap.ContainsKey(val2.m_itemData.m_shared.m_name))
					{
						trophyCreatureMap.Add(val2.m_itemData.m_shared.m_name, StringExtensionMethods.GetStableHashCode(((Object)prefab).name));
					}
				}
			}
		}

		public static bool GetAllGuardedWardZDOs(List<ZDO> zdos)
		{
			Log.Debug("GetAllGuardedWardZDOs");
			zdos.Clear();
			foreach (ZDO value in ZDOMan.instance.m_objectsByID.Values)
			{
				if (value.IsValid() && value.GetBool(WARD_FLAG, false) && !zdos.Contains(value))
				{
					zdos.Add(value);
				}
			}
			return zdos.Count > 0;
		}

		public static bool GetAllTamedZDOs(List<ZDO> zdos)
		{
			Log.Debug("GetAllTamedZDOs");
			foreach (ZDO value in ZDOMan.instance.m_objectsByID.Values)
			{
				if (value.IsValid() && value.GetBool(ZDOVars.s_tamed, false))
				{
					zdos.Add(value);
				}
			}
			return zdos.Count > 0;
		}

		public static bool TryGetGuardZDOs(List<ZDO> guards)
		{
			Log.Debug("TryGetGuardZDOs");
			guards.Clear();
			List<ZDO> list = new List<ZDO>();
			Log.Debug("Searching for tamed Guard ZDOs");
			GetAllTamedZDOs(list);
			Vector3 val = default(Vector3);
			foreach (ZDO item in list)
			{
				if (item.GetVec3(GUARD_PATROL_POINT, ref val))
				{
					Log.Debug("Found bound Guard ZDO");
					guards.Add(item);
				}
			}
			return guards.Count > 0;
		}

		private static bool CheckPiecesInRadius(Vector3 point, float dist, int piecesMin, int stationsMin, int bedsMin)
		{
			//IL_003b: 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)
			Log.Debug("CheckPiecesInRadius");
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			List<WearNTear> allInstances = WearNTear.GetAllInstances();
			if (allInstances.Count < piecesMin + stationsMin)
			{
				return false;
			}
			CraftingStation val = default(CraftingStation);
			Bed val2 = default(Bed);
			foreach (WearNTear item in allInstances)
			{
				if (Vector3.Distance(point, ((Component)item).transform.position) < dist)
				{
					num++;
					if (((Component)item).gameObject.TryGetComponent<CraftingStation>(ref val))
					{
						num2++;
					}
					if (((Component)item).gameObject.TryGetComponent<Bed>(ref val2))
					{
						num3++;
					}
				}
				if (num >= piecesMin && num2 >= stationsMin && num3 >= bedsMin)
				{
					return true;
				}
			}
			Log.Debug($"Base check failed: {num} pieces & {num2} stations {num3} beds found within radius {Cfg.proximityCheckRadius.Value}");
			return false;
		}

		private static bool CheckGuardBiome(Vector3 location, string trophyName)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			Log.Debug("CheckGuardBiome");
			if (biomeValues.TryGetValue(Heightmap.FindBiome(location), out var value) && value > 0 && trophyBiomeMap.TryGetValue(trophyName, out var value2) && value2 > 0)
			{
				Log.Debug($"Biome value heightmap {value} guard {value2} ");
				return value2 <= value;
			}
			return false;
		}

		private static int GetMaxBossLevel()
		{
			int num = 0;
			ZoneSystem instance = ZoneSystem.instance;
			if (instance.GetGlobalKey((GlobalKeys)33))
			{
				num++;
			}
			if (instance.GetGlobalKey((GlobalKeys)36))
			{
				num++;
			}
			if (instance.GetGlobalKey((GlobalKeys)37))
			{
				num++;
			}
			if (instance.GetGlobalKey((GlobalKeys)34))
			{
				num++;
			}
			if (instance.GetGlobalKey((GlobalKeys)35))
			{
				num++;
			}
			if (instance.GetGlobalKey("defeated_queen"))
			{
				num++;
			}
			if (instance.GetGlobalKey("defeated_fader"))
			{
				num++;
			}
			return num;
		}

		private static bool CheckBossLevel(Vector3 location, string trophyName)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			Log.Debug("CheckBossLevel");
			if (biomeValues.TryGetValue(Heightmap.FindBiome(l