Decompiled source of DefendYourBase v0.2.5

DefendYourBase.dll

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

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

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

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

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

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

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

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

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

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

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

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

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

	public 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_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Expected O, but got Unknown
		Logging.GetLogger().Trace("ServerDelegate");
		_entry.SettingChanged -= rootHandler;
		ZNet instance = ZNet.instance;
		bool? flag = ((instance != null) ? new bool?(instance.IsServer()) : null);
		if (flag.HasValue)
		{
			if (flag == false && 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)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		if (ConfigEntry is ConfigEntry<KeyboardShortcut> val)
		{
			KeyboardShortcut value = val.Value;
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!Input.GetKey(modifier))
				{
					return false;
				}
			}
			if (!Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey))
			{
				return false;
			}
			return true;
		}
		Log.Error("Keyboard read attempted on non-KeyboardShortcut config.");
		return false;
	}

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

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

	public string Section;

	public string ServerValue;
}
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 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 AddExclusion(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.UnpatchAll(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 Logging
{
	public enum LogLevels
	{
		Critical,
		Error,
		Warning,
		Info,
		Debug,
		Trace
	}

	private static Logging _logger;

	public LogLevels LogLevel { get; set; }

	public string ModName { get; set; }

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

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

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

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

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

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

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

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

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

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

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

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

	public static void ChangeLogging(object s, EventArgs e)
	{
		SettingChangedEventArgs val = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null);
		GetLogger().Debug($"ChangeLog {val.ChangedSetting.Definition.Key} to {val.ChangedSetting.BoxedValue}");
		GetLogger().LogLevel = Cfg.debugLevel.Value;
	}
}
public class ServerConfiguration
{
	[HarmonyPatch(typeof(ZNet), "StopAll")]
	private static class ZNet_Shutdown_Patch
	{
		[HarmonyPrefix]
		private static void ZNet_StopAll_Prefix(ZNet __instance)
		{
			Log.Debug("ZNet_StopAll_Patch_Prefix");
			if (Instance != null)
			{
				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;
		}
	}
}
internal class Utils
{
	public static TEnum Guardrails<TEnum>(string value, TEnum enumDefault) where TEnum : struct
	{
		if (Enum.TryParse<TEnum>(value, ignoreCase: true, out var result))
		{
			return result;
		}
		return enumDefault;
	}

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

	public static 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 float DistanceSqr(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)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		float num = v1.x - v0.x;
		float num2 = v1.y - v0.y;
		float num3 = v1.z - v0.z;
		return num * num + num2 * num2 + num3 * num3;
	}

	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 float DistanceXZ(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 Mathf.Sqrt(num * num + num2 * num2);
	}

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

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

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

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

	public static 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)(object)prefab != (Object)null && 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())
		{
			ZDOID zDOID = allCharacter.GetZDOID();
			if (((object)(ZDOID)(ref zDOID)).ToString().Equals(cid))
			{
				return allCharacter;
			}
		}
		return null;
	}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	public static bool CopyObject(object original, object target)
	{
		Logging logger = Logging.GetLogger();
		Type type = original.GetType();
		Type type2 = target.GetType();
		if (type == null)
		{
			logger.Warning("Copy Object: Source object is null");
			Activator.CreateInstance(type);
			return false;
		}
		if (type2 == null)
		{
			logger.Warning("Copy Object: Destination object is null");
			return false;
		}
		if (type2 != type)
		{
			logger.Warning("Copy Object: Source and destination components are different types");
			return false;
		}
		FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (FieldInfo fieldInfo in fields)
		{
			fieldInfo.SetValue(target, fieldInfo.GetValue(original));
		}
		return true;
	}
}
internal class Cfg
{
	public static 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 val = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null);
		logger.Debug($"ChangeLog {val.ChangedSetting.Definition.Key} to {val.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.5")]
[BepInProcess("valheim.exe")]
[BepInProcess("valheim_server.exe")]
public class DefendYourBase : BaseUnityPlugin
{
	[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_0375: Unknown result type (might be due to invalid IL or missing references)
			//IL_0380: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_038f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0394: Unknown result type (might be due to invalid IL or missing references)
			//IL_0398: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0415: Unknown result type (might be due to invalid IL or missing references)
			//IL_042b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0447: Unknown result type (might be due to invalid IL or missing references)
			//IL_044c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0467: Unknown result type (might be due to invalid IL or missing references)
			//IL_046c: 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, "This creature cannot be summoned as a guard.", 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, "You can't summon a guard on someone else's 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, "This ward already has a 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, "The ward must be close to a large enough base.", 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, "You can only have one ward guarded within a protected area.", 0, (Sprite)null);
						return;
					}
				}
			}
			GameObject prefabByHash = Utils.GetPrefabByHash(value);
			string text = 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, "This creature cannot be summoned as a guard.", 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, "This creature cannot be summoned as a guard.", 0, (Sprite)null);
				return;
			}
			if (val3.m_boss)
			{
				Log.Debug("Can't summon a boss");
				((Character)Player.m_localPlayer).Message((MessageType)2, "You can't summon a boss as a guard.", 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}");
				((Character)Player.m_localPlayer).Message((MessageType)2, $"This guard is not allowed in the {Heightmap.FindBiome(((Component)__instance).transform.position)}.", 0, (Sprite)null);
				return;
			}
			Log.Debug("Summoning Guard");
			Vector3 val4 = ((Component)__instance).transform.position + ((Component)__instance).transform.forward * 2f;
			GameObject obj = Object.Instantiate<GameObject>(prefabByHash, val4, Quaternion.identity);
			ConsumeItem(user, item);
			Character val5 = default(Character);
			if (obj.TryGetComponent<Character>(ref val5))
			{
				text = val5.m_name;
			}
			ZDO zDO = val5.m_nview.GetZDO();
			zDO.Set(GUARD_PATROL_POINT, ((Component)__instance).transform.position);
			ZDOMan.instance.ForceSendZDO(zDO.m_uid);
			ZDO zDO2 = __instance.m_nview.GetZDO();
			zDO2.Set(WARD_FLAG, true);
			ZDOMan.instance.ForceSendZDO(zDO2.m_uid);
			SetUpGuard(obj, __instance.m_radius, ((Component)__instance).transform.position, quality);
			Object.Instantiate<GameObject>(Utils.GetPrefab("vfx_spawn"), ((Component)__instance).transform.position, Quaternion.identity);
			Object.Instantiate<GameObject>(Utils.GetPrefab("sfx_offering"), ((Component)__instance).transform.position, Quaternion.identity);
			((Character)val).Message((MessageType)2, Localization.instance.Localize("Summoned " + text), 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)
		{
			Log.Debug("MonsterAI_UpdateTarget_Patch_Postfix");
			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");

	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 = "This creature cannot be summoned as a guard.";

	internal static int s_tempCreatureLevel = 0;

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

	private static int prefabHash = 0;

	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);
		SetCreatureBiomeMapping();
		BuildTrophyBiomeMap(creatureConfigString);
		Cfg.BepInExConfig((BaseUnityPlugin)(object)_modInstance);
		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(new char[1] { ';' });
		for (int i = 0; i < array.Length; i++)
		{
			string[] array2 = array[i].Split(new char[1] { ',' });
			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 val = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null);
		Log.Debug("ChangeBiomeMapping " + val.ChangedSetting.Definition.Key);
		creatureConfigString = Cfg.creatureBiomeMapping.Value;
		BuildTrophyBiomeMap(Cfg.creatureBiomeMapping.Value);
	}

	public static bool SetCreatureBiomeMapping()
	{
		Log.Debug("SetCreatureBiomeMapping");
		try
		{
			string assemblyPathedFile = Utils.GetAssemblyPathedFile("CreatureBiomeMap.txt");
			if (!File.Exists(assemblyPathedFile))
			{
				Log.Warning("Creature mapping file is missing. Using vanilla assignment.");
				return false;
			}
			string[] value = File.ReadAllLines(assemblyPathedFile);
			creatureConfigString = string.Join(";", value).Replace(" ", string.Empty);
			if (mappingWatcher == null)
			{
				mappingWatcher = Utils.CreateFileWatcher(assemblyPathedFile, 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)32))
		{
			num++;
		}
		if (instance.GetGlobalKey((GlobalKeys)35))
		{
			num++;
		}
		if (instance.GetGlobalKey((GlobalKeys)36))
		{
			num++;
		}
		if (instance.GetGlobalKey((GlobalKeys)33))
		{
			num++;
		}
		if (instance.GetGlobalKey((GlobalKeys)34))
		{
			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(location), out var value) && value > 0 && trophyBiomeMap.TryGetValue(trophyName, out var value2) && value2 > 0)
		{
			int maxBossLevel = GetMaxBossLevel();
			Log.Debug($"Biome value heightmap {value} guard {value2} boss {maxBossLevel} ");
			return value2 <= maxBossLevel;
		}
		return false;
	}

	private static bool SetUpGuard(GameObject guard, float radius, Vector3 patrolPoint, int level = 0)
	{
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		Log.Debug("SetUpGuard");
		if ((Object)(object)guard == (Object)null)
		{
			Log.Warning("Guard is missing in action. Can't setup");
			return false;
		}
		Character component = guard.GetComponent<Character>();
		if ((Object)(object)component == (Object)null)
		{
			Log.Warning("Guard is missing Character component. Can't setup");
			return false;
		}
		MonsterAI component2 = guard.GetComponent<MonsterAI>();
		if ((Object)(object)component2 == (Object)null)
		{
			Log.Warning("Guard is missing useable monster AI component. Can't setup");
			return false;
		}
		component.SetLevel(level);
		component.SetTamed(true);
		((BaseAI)component2).m_patrol = true;
		((BaseAI)component2).SetPatrolPoint(patrolPoint);
		((BaseAI)component2).m_viewAngle = Mathf.Max(120f, ((BaseAI)component2).m_viewAngle);
		((BaseAI)component2).m_viewRange = Mathf.Max(30f, ((BaseAI)component2).m_viewRange);
		component2.m_alertRange = Math.Max(30f, component2.m_alertRange);
		component2.m_maxChaseDistance = 0f;
		component2.m_circleTargetInterval = 0f;
		component2.m_circleTargetDuration = 2f;
		component2.m_circleTargetDistance = 4f;
		component.m_damageModifiers.m_fire = (DamageModifier)3;
		component.m_tolerateSmoke = true;
		if (Cfg.allowLevels.Value && level > 0)
		{
			component.m_level = level;
		}
		CharacterDrop val = default(CharacterDrop);
		if (guard.TryGetComponent<CharacterDrop>(ref val))
		{
			Object.Destroy((Object)(object)val);
		}
		DebugUtils.ObjectInspector(component.m_damageModifiers);
		return true;
	}

	public static bool TryGetGuardInScene(ZDO zdo, out GameObject guard)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		Log.Debug("TryGetGuardInScene");
		guard = null;
		if (ZNetScene.instance.HaveInstance(zdo))
		{
			Log.Debug("Guard has an instance");
			guard = ZNetScene.instance.FindInstance(zdo.m_uid);
			if ((Object)(object)guard != (Object)null)
			{
				Log.Debug("Found Guard instance in scene");
				return true;
			}
		}
		return false;
	}

	private static void SendOneDestroyed(ZDOID zdoid)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		ZPackage val = new ZPackage();
		val.Write(1);
		val.Write(zdoid);
		ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "DestroyZDO", new object[1] { val });
	}

	private static void ConsumeItem(Humanoid user, ItemData item)
	{
		user.GetInventory().RemoveOneItem(item);
	}

	private static void SendAllDestroyed(List<ZDO> zdos)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		ZPackage val = new ZPackage();
		val.Write(zdos.Count);
		foreach (ZDO zdo in zdos)
		{
			val.Write(zdo.m_uid);
		}
		ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "DestroyZDO", new object[1] { val });
	}
}