Decompiled source of TyrenheimRaven v0.14.7

plugins/TyrenheimRaven.dll

Decompiled 4 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using ServerSync;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ValheimModTest")]
[assembly: AssemblyDescription("")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("ValheimModTest")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("50ba138c-bd32-434f-a5c0-d9e34e49bca4")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyCompany("")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace TyrenheimRaven
{
	public class Assets
	{
		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		public class ZNetScene_Awake_Patch
		{
			public static bool Prefix(ZNetScene __instance)
			{
				LoadAssets();
				foreach (GameObject allPrefab in allPrefabs)
				{
					if ((Object)(object)allPrefab.GetComponent<ZNetView>() != (Object)null)
					{
						__instance.m_prefabs.Add(allPrefab);
					}
				}
				return true;
			}

			public static void Postfix(ZNetScene __instance)
			{
				TyrRaven.SetupAssets();
				PatreonPortal.SetupAssets();
				MobTweaks.ZNS_Init(__instance);
				BuildPieces.Init();
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		public class ObjectDB_Awake_Patch
		{
			public static void Postfix(ObjectDB __instance)
			{
				LoadAssets();
				foreach (GameObject allPrefab in allPrefabs)
				{
					if ((Object)(object)allPrefab.GetComponent<ItemDrop>() != (Object)null)
					{
						__instance.m_items.Add(allPrefab);
						__instance.m_itemByHash.Add(StringExtensionMethods.GetStableHashCode(((Object)allPrefab).name), allPrefab);
					}
				}
				InvStrip.Init();
			}
		}

		[HarmonyPatch(typeof(Player), "OnSpawned")]
		public static class Player_Awake_Patch
		{
			public static void Postfix(Player __instance)
			{
				foreach (GameObject hammerPrefab in hammerPrefabs)
				{
					if ((Object)(object)hammerPrefab != (Object)null)
					{
						AddToHammer(hammerPrefab);
					}
				}
			}
		}

		private static bool assetsLoaded = false;

		public static string portalBundle = "patreonportal";

		public static string askiaBundle = "askia";

		public static string capesBundle = "patreoncapes";

		public static string denariusBundle = "denarius";

		public static List<GameObject> allPrefabs = new List<GameObject>();

		public static List<Material> capeMaterials = new List<Material>();

		public static List<GameObject> hammerPrefabs = new List<GameObject>();

		private static AssetBundle GetAssetBundleFromResources(string filename)
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string name = executingAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(filename));
			return AssetBundle.LoadFromStream(executingAssembly.GetManifestResourceStream(name));
		}

		public static void LoadAssets()
		{
			if (assetsLoaded)
			{
				return;
			}
			AssetBundle assetBundleFromResources = GetAssetBundleFromResources(portalBundle);
			if ((Object)(object)assetBundleFromResources == (Object)null)
			{
				Debug.Log((object)("Failed to load AssetBundle " + portalBundle));
				return;
			}
			GameObject[] array = assetBundleFromResources.LoadAllAssets<GameObject>();
			Debug.Log((object)$"Loaded {array.Length} prefabs from AssetBundle {portalBundle}");
			GameObject[] array2 = array;
			foreach (GameObject item in array2)
			{
				allPrefabs.Add(item);
			}
			assetBundleFromResources.Unload(false);
			AssetBundle assetBundleFromResources2 = GetAssetBundleFromResources(askiaBundle);
			if ((Object)(object)assetBundleFromResources2 == (Object)null)
			{
				Debug.Log((object)("Failed to load AssetBundle " + askiaBundle));
				return;
			}
			GameObject[] array3 = assetBundleFromResources2.LoadAllAssets<GameObject>();
			Debug.Log((object)$"Loaded {array3.Length} prefabs from AssetBundle {askiaBundle}");
			array2 = array3;
			foreach (GameObject item2 in array2)
			{
				allPrefabs.Add(item2);
			}
			assetBundleFromResources2.Unload(false);
			AssetBundle assetBundleFromResources3 = GetAssetBundleFromResources(denariusBundle);
			if ((Object)(object)assetBundleFromResources3 == (Object)null)
			{
				Debug.Log((object)("Failed to load AssetBundle " + denariusBundle));
				return;
			}
			GameObject[] array4 = assetBundleFromResources3.LoadAllAssets<GameObject>();
			Debug.Log((object)$"Loaded {array4.Length} prefabs from AssetBundle {denariusBundle}");
			array2 = array4;
			foreach (GameObject val in array2)
			{
				allPrefabs.Add(val);
				if ((Object)(object)val.GetComponent<Piece>() != (Object)null)
				{
					hammerPrefabs.Add(val);
				}
			}
			assetBundleFromResources3.Unload(false);
			assetsLoaded = true;
		}

		public static void AddToHammer(GameObject prefab)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			PieceTable val = null;
			Object[] array = Resources.FindObjectsOfTypeAll(typeof(PieceTable));
			for (int i = 0; i < array.Length; i++)
			{
				PieceTable val2 = (PieceTable)array[i];
				if (((Object)((Component)val2).gameObject).name.Contains("_HammerPieceTable"))
				{
					val = val2;
					break;
				}
			}
			if (val != null && !val.m_pieces.Contains(prefab))
			{
				prefab.GetComponent<Piece>();
				val.m_pieces.Add(prefab);
			}
		}
	}
	public class BossWorthiness
	{
		public static string worthyVFX = "vfx_offering";

		public static void RegisterRPC()
		{
			ZRoutedRpc.instance.Register<string, Vector3>("MakeWorthy", (Action<long, string, Vector3>)RPC_MakeWorthy);
		}

		public static string WorthyKey(string bossName)
		{
			return "tyr_" + bossName + "_worthy";
		}

		public static bool IsWorthy(Player p, string bossName)
		{
			return p.m_uniques.Contains(WorthyKey(bossName));
		}

		public static void MakeWorthy(Player p, string bossName)
		{
			if (!((Humanoid)p).HaveUniqueKey(WorthyKey(bossName)))
			{
				p.m_uniques.Add(WorthyKey(bossName));
			}
		}

		public static string PowerNameToBossName(string powerName)
		{
			return powerName.Split(new char[1] { '_' })[1];
		}

		public static string BossEventToBossName(string bossEventName)
		{
			return bossEventName.Split(new char[1] { '_' })[1].Replace("goblinking", "yagluth").Replace("gdking", "theelder").Replace("dragon", "moder");
		}

		public static void RPC_MakeWorthy(long sender, string bossName, Vector3 bossPosition)
		{
			//IL_001d: 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)
			float num = 150f;
			if ((Object)(object)Player.m_localPlayer != (Object)null && Vector3.Distance(((Component)Player.m_localPlayer).transform.position, bossPosition) < num)
			{
				MakeWorthy(Player.m_localPlayer, bossName);
			}
		}
	}
	[HarmonyPatch(typeof(Character), "OnDeath")]
	public class Boss_Death_Patch
	{
		public static bool Prefix(Character __instance)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			if (__instance.IsBoss() && !string.IsNullOrEmpty(__instance.m_bossEvent))
			{
				string text = BossWorthiness.BossEventToBossName(__instance.m_bossEvent);
				Vector3 position = ((Component)__instance).transform.position;
				BossWorthiness.RPC_MakeWorthy(0L, text, position);
				ZRoutedRpc.instance.InvokeRoutedRPC(ZNetView.Everybody, "MakeWorthy", new object[2] { text, position });
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(ItemStand), "DelayedPowerActivation")]
	public class PowerActivationPatch
	{
		public static bool Prefix(ItemStand __instance)
		{
			if ((Object)(object)Player.m_localPlayer != (Object)null && !BossWorthiness.IsWorthy(Player.m_localPlayer, BossWorthiness.PowerNameToBossName(__instance.m_guardianPower.m_name)))
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "The spirit of " + __instance.m_guardianPower.m_name + " does not find you worthy", 0, (Sprite)null);
				TyrRaven.Message(Messages.notWorthy);
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")]
	public class CharacterDrop_GenerateDropList_Patch
	{
		public static bool Prefix(CharacterDrop __instance, ref List<KeyValuePair<GameObject, int>> __result)
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			List<KeyValuePair<GameObject, int>> list = new List<KeyValuePair<GameObject, int>>();
			int num = (((Object)(object)__instance.m_character == (Object)null) ? 1 : Mathf.Max(1, (int)Mathf.Pow(2f, (float)(__instance.m_character.GetLevel() - 1))));
			foreach (Drop drop in __instance.m_drops)
			{
				if ((Object)(object)drop.m_prefab == (Object)null)
				{
					continue;
				}
				float num2 = drop.m_chance;
				if (drop.m_levelMultiplier)
				{
					num2 *= (float)num;
				}
				if (Random.value <= num2)
				{
					int num3 = Random.Range(drop.m_amountMin, drop.m_amountMax);
					if (drop.m_levelMultiplier)
					{
						num3 *= num;
					}
					if (drop.m_onePerPlayer)
					{
						num3 = Player.GetPlayersInRangeXZ(__instance.m_character.GetCenterPoint(), 150f);
					}
					if (num3 > 0)
					{
						list.Add(new KeyValuePair<GameObject, int>(drop.m_prefab, num3));
					}
				}
			}
			__result = list;
			return false;
		}
	}
	public class BuildExclusion
	{
		public static ConfigEntry<float> _bossSummonExclusionRadius;

		public static ConfigEntry<float> _bossHookExclusionRadius;

		public static ConfigEntry<float> _dungeonExclusionRadius;

		public static ConfigEntry<float> _JCWorldBossExclusionRadius;

		public static void SetupConfig(Mod instance)
		{
			_bossSummonExclusionRadius = instance.SyncedConfig("BuildExclusion", "Boss Summon Exclusion Radius", 75f, "Build exclusion zone around Boss Summoners (Offering Bowls)");
			_bossHookExclusionRadius = instance.SyncedConfig("BuildExclusion", "Boss Hook Exclusion Radius", 75f, "Build exclusion zone around Boss Trophy Hooks");
			_dungeonExclusionRadius = instance.SyncedConfig("BuildExclusion", "Dungeon Exclusion Radius", 20f, "Build exclusion zone around dungeons (Crypts, Burial Chambers, etc.)");
			_JCWorldBossExclusionRadius = instance.SyncedConfig("BuildExclusion", "JC WorldBoss Exclusion Radius", 30f, "Build exclusion zone around Jewelcrafting WorldBoss events");
		}

		public static void SetupBuildExclusion(GameObject go, float radius)
		{
			Location component = go.GetComponent<Location>();
			if ((Object)(object)component == (Object)null)
			{
				component = go.AddComponent<Location>();
				component.m_exteriorRadius = Math.Max(0f, radius);
				component.m_noBuild = true;
				component.m_clearArea = false;
				component.m_applyRandomDamage = false;
				component.m_hasInterior = false;
			}
			else
			{
				component.m_exteriorRadius = Math.Max(component.m_exteriorRadius, radius);
				component.m_noBuild = true;
			}
		}
	}
	public class BuildPieces
	{
		public static void Init()
		{
			//IL_0123: 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_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Expected O, but got Unknown
			PieceTable hammerPieceTable = GetHammerPieceTable();
			ZNetScene.instance.GetPrefab("turf_roof").GetComponent<Piece>().m_name = "Turf Roof";
			AddToPieceTable(ZNetScene.instance.GetPrefab("turf_roof"), hammerPieceTable);
			ZNetScene.instance.GetPrefab("turf_roof_top").GetComponent<Piece>().m_name = "Turf Roof Top";
			AddToPieceTable(ZNetScene.instance.GetPrefab("turf_roof_top"), hammerPieceTable);
			ZNetScene.instance.GetPrefab("turf_roof_wall").GetComponent<Piece>().m_name = "Turf Roof Wall";
			AddToPieceTable(ZNetScene.instance.GetPrefab("turf_roof_wall"), hammerPieceTable);
			ZNetScene.instance.GetPrefab("ArmorStand_Male").GetComponent<Piece>().m_name = "ArmorStand Male";
			AddToPieceTable(ZNetScene.instance.GetPrefab("ArmorStand_Male"), hammerPieceTable);
			ZNetScene.instance.GetPrefab("ArmorStand_Female").GetComponent<Piece>().m_name = "ArmorStand Female";
			AddToPieceTable(ZNetScene.instance.GetPrefab("ArmorStand_Female"), hammerPieceTable);
			GameObject prefab = ZNetScene.instance.GetPrefab("stone_floor");
			prefab.GetComponent<Piece>().m_resources = (Requirement[])(object)new Requirement[1]
			{
				new Requirement
				{
					m_resItem = GetItemDrop("Stone"),
					m_amount = 12,
					m_recover = true
				}
			};
			AddToPieceTable(prefab, hammerPieceTable);
		}

		private static ItemDrop GetItemDrop(string prefabName)
		{
			GameObject prefab = ZNetScene.instance.GetPrefab(prefabName);
			ItemDrop obj = ((prefab != null) ? prefab.GetComponent<ItemDrop>() : null);
			if ((Object)(object)obj == (Object)null)
			{
				Debug.Log((object)("ERROR: Failed to find ItemDrop for " + prefabName));
			}
			return obj;
		}

		private static PieceTable GetHammerPieceTable()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			Object[] array = Resources.FindObjectsOfTypeAll(typeof(PieceTable));
			for (int i = 0; i < array.Length; i++)
			{
				PieceTable val = (PieceTable)array[i];
				if (((Object)((Component)val).gameObject).name.Contains("_HammerPieceTable"))
				{
					return val;
				}
			}
			return null;
		}

		private static void AddToPieceTable(GameObject prefab, PieceTable table)
		{
			if (!((Object)(object)table == (Object)null) && !((Object)(object)prefab == (Object)null) && !table.m_pieces.Contains(prefab))
			{
				table.m_pieces.Add(prefab);
			}
		}
	}
	public class RuneStone_Receiver : TextReceiver
	{
		public string GetText()
		{
			return "";
		}

		public void SetText(string text)
		{
			RuneStonePatch.SetText(text);
		}
	}
	[HarmonyPatch(typeof(RuneStone), "Interact")]
	public class RuneStonePatch
	{
		public static RuneStone s_queuedStone;

		public static RuneStone_Receiver s_receiver = new RuneStone_Receiver();

		public static void SetText(string text)
		{
			if ((Object)(object)s_queuedStone != (Object)null)
			{
				s_queuedStone.m_label = "";
				s_queuedStone.m_locationName = "";
				s_queuedStone.m_randomTexts.Clear();
				s_queuedStone.m_text = text;
				s_queuedStone = null;
			}
		}

		public static bool Prefix(RuneStone __instance, Humanoid character, bool hold, bool alt)
		{
			if (!((Character)Player.m_localPlayer).InGodMode() || !alt)
			{
				return true;
			}
			s_queuedStone = __instance;
			TextInput.instance.RequestText((TextReceiver)(object)s_receiver, "$piece_portal_tag", 10);
			return false;
		}
	}
	public class Webhook
	{
		public static void SendJSON(string webhookURL, string json)
		{
			if (string.IsNullOrEmpty(webhookURL))
			{
				Debug.Log((object)"Webook request to empty URL");
				return;
			}
			Debug.Log((object)("Sending POST to webhook: " + webhookURL));
			byte[] bytes = Encoding.UTF8.GetBytes(json);
			WebRequest webRequest = WebRequest.Create(webhookURL);
			webRequest.Method = "POST";
			webRequest.ContentType = "application/json";
			webRequest.ContentLength = bytes.Length;
			Stream requestStream = webRequest.GetRequestStream();
			requestStream.Write(bytes, 0, bytes.Length);
			requestStream.Close();
			webRequest.GetResponse().Close();
		}
	}
	public class Graverobbing
	{
		[HarmonyPatch(typeof(Container), "SetInUse")]
		public static class Container_SetInUse_Patch
		{
			public static void Postfix(Container __instance, bool inUse)
			{
				if (!inUse && __instance.GetInventory() == trackedInventory)
				{
					ProduceReport(__instance);
				}
			}
		}

		private const string webhookFilename = "graverobbing_webhook.txt";

		private const string logFilename = "graverobbing.log";

		private static Dictionary<string, int> priorInventory;

		private static Inventory trackedInventory;

		private static string logFilePath
		{
			get
			{
				string bepInExRootPath = Paths.BepInExRootPath;
				char directorySeparatorChar = Path.DirectorySeparatorChar;
				return bepInExRootPath + directorySeparatorChar + "graverobbing.log";
			}
		}

		private static string webhookFilePath
		{
			get
			{
				string configPath = Paths.ConfigPath;
				char directorySeparatorChar = Path.DirectorySeparatorChar;
				return configPath + directorySeparatorChar + "graverobbing_webhook.txt";
			}
		}

		private static string readWebhookURL()
		{
			return File.ReadAllLines(webhookFilePath)[0];
		}

		public static Dictionary<string, int> ContentsOfInventory(Inventory i)
		{
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			foreach (ItemData item in i.m_inventory)
			{
				string name = item.m_shared.m_name;
				dictionary[name] = (dictionary.ContainsKey(name) ? dictionary[name] : 0) + item.m_stack;
			}
			return dictionary;
		}

		public static string StringifyContents(Dictionary<string, int> contents)
		{
			string text = string.Empty;
			foreach (KeyValuePair<string, int> content in contents)
			{
				text += $"{Localization.instance.Localize(content.Key)} x {content.Value}\n";
			}
			return text;
		}

		public static void TombstoneInteract(Player p, TombStone t)
		{
			trackedInventory = ((Component)t).GetComponent<Container>().GetInventory();
			priorInventory = ContentsOfInventory(trackedInventory);
		}

		public static ZPackage SerializeData(string looter, string tombOwner, Vector3 location, Dictionary<string, int> added, Dictionary<string, int> removed)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage();
			val.Write(looter);
			val.Write(tombOwner);
			val.Write(location);
			val.Write(added.Count);
			foreach (KeyValuePair<string, int> item in added)
			{
				val.Write(item.Key);
				val.Write(item.Value);
			}
			val.Write(removed.Count);
			foreach (KeyValuePair<string, int> item2 in removed)
			{
				val.Write(item2.Key);
				val.Write(item2.Value);
			}
			return val;
		}

		public static void DeserializeData(ZPackage data, out string looter, out string tombOwner, out Vector3 location, out Dictionary<string, int> added, out Dictionary<string, int> removed)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			looter = data.ReadString();
			tombOwner = data.ReadString();
			location = data.ReadVector3();
			int num = data.ReadInt();
			added = new Dictionary<string, int>();
			for (int i = 0; i < num; i++)
			{
				string key = data.ReadString();
				int value = data.ReadInt();
				added[key] = value;
			}
			int num2 = data.ReadInt();
			removed = new Dictionary<string, int>();
			for (int j = 0; j < num2; j++)
			{
				string key2 = data.ReadString();
				int value2 = data.ReadInt();
				removed[key2] = value2;
			}
		}

		public static void ProduceReport(Container cont)
		{
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<string, int> dictionary = ContentsOfInventory(trackedInventory);
			Dictionary<string, int> dictionary2 = new Dictionary<string, int>();
			Dictionary<string, int> dictionary3 = new Dictionary<string, int>();
			foreach (KeyValuePair<string, int> item in priorInventory)
			{
				int value;
				int num = (dictionary.TryGetValue(item.Key, out value) ? value : 0);
				if (num < item.Value)
				{
					dictionary2[item.Key] = item.Value - num;
				}
			}
			foreach (KeyValuePair<string, int> item2 in dictionary)
			{
				int value2;
				int num2 = (priorInventory.TryGetValue(item2.Key, out value2) ? value2 : 0);
				if (num2 < item2.Value)
				{
					dictionary3[item2.Key] = item2.Value - num2;
				}
			}
			ZPackage val = SerializeData(Game.instance.GetPlayerProfile().GetName(), cont.m_nview.GetZDO().GetString("ownerName", ""), ((Component)cont).transform.position, dictionary3, dictionary2);
			ZRoutedRpc.instance.InvokeRoutedRPC("InventoryLog", new object[1] { val });
		}

		public static string CreateJsonReport(string looter, string owner, Vector3 location, Dictionary<string, int> added, Dictionary<string, int> removed)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			string text = $"{{ \"content\": null, \"embeds\" : [ {{ \"title\" : \"Graverobber Report\", \"description\" : \"**{looter}** opened tombstone owned by **{owner}**\\n*{DateTime.UtcNow.ToString()}* UTC\\n*Tombstone location: {location}*\"";
			if (added.Count > 0 || removed.Count > 0)
			{
				text += ", \"fields\" : [";
				if (removed.Count > 0)
				{
					text += "{ \"name\" : \"Items Removed\", \"value\" : \"";
					foreach (KeyValuePair<string, int> item in removed)
					{
						text += $"- {Localization.instance.Localize(item.Key)} x {item.Value}\\n";
					}
					text += "\"}";
				}
				if (added.Count > 0)
				{
					if (removed.Count > 0)
					{
						text += ",";
					}
					text += "{ \"name\" : \"Items Added\", \"value\" : \"";
					foreach (KeyValuePair<string, int> item2 in added)
					{
						text += $"- {Localization.instance.Localize(item2.Key)} x {item2.Value}\\n";
					}
					text += "\"}";
				}
				text += "]";
			}
			return text + "} ] }";
		}

		public static string CreateRawReport(string looter, string owner, Vector3 location, Dictionary<string, int> added, Dictionary<string, int> removed)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			return string.Concat(string.Concat(string.Concat(string.Concat(string.Concat("=== [" + looter + "] opened tombstone owned by [" + owner + "] ===\n", "Timestamp (UTC): ", DateTime.UtcNow.ToString(), "\n"), $"Tombstone Location: {location}\n"), "--- Items removed ---\n", StringifyContents(removed)), "--- Items added --- \n", StringifyContents(added)), "===============================================\n");
		}

		public static void RPC_WriteLog(long sender, ZPackage data)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			if (ZNet.instance.IsServer())
			{
				DeserializeData(data, out var looter, out var tombOwner, out var location, out var added, out var removed);
				File.AppendAllText(logFilePath, CreateRawReport(looter, tombOwner, location, added, removed));
				if (File.Exists(webhookFilePath) && (added.Count > 0 || removed.Count > 0))
				{
					Webhook.SendJSON(readWebhookURL(), CreateJsonReport(looter, tombOwner, location, added, removed));
				}
			}
		}

		public static void RegisterRPC()
		{
			ZRoutedRpc.instance.Register<ZPackage>("InventoryLog", (Action<long, ZPackage>)RPC_WriteLog);
		}
	}
	public class FirstSpawnOverride
	{
	}
	public class ObjectTracking
	{
		[HarmonyPatch(typeof(DungeonGenerator), "Awake")]
		private static class DungeonGenerator_Awake_Patch
		{
			private static void Postfix(DungeonGenerator __instance)
			{
				//IL_000d: 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_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0055: Unknown result type (might be due to invalid IL or missing references)
				dungeons.Add(__instance);
				if (((Enum)__instance.m_themes).HasFlag((Enum)(object)(Theme)1) || ((Enum)__instance.m_themes).HasFlag((Enum)(object)(Theme)8) || ((Enum)__instance.m_themes).HasFlag((Enum)(object)(Theme)2) || ((Enum)__instance.m_themes).HasFlag((Enum)(object)(Theme)4))
				{
					BuildExclusion.SetupBuildExclusion(((Component)__instance).gameObject, BuildExclusion._dungeonExclusionRadius.Value);
				}
			}
		}

		[HarmonyPatch(typeof(DungeonGenerator), "Clear")]
		private static class DungeonGenerator_Clear_Patch
		{
			private static void Postfix(DungeonGenerator __instance)
			{
				dungeons.Remove(__instance);
			}
		}

		[HarmonyPatch(typeof(OfferingBowl), "Awake")]
		private static class OfferingBowl_Awake_Patch
		{
			private static void Postfix(OfferingBowl __instance)
			{
				offeringBowls.Add(__instance);
				BuildExclusion.SetupBuildExclusion(((Component)__instance).gameObject, BuildExclusion._bossSummonExclusionRadius.Value);
			}
		}

		[HarmonyPatch(typeof(BossStone), "Start")]
		private static class BossStone_Start_Patch
		{
			private static void Postfix(BossStone __instance)
			{
				bossStones.Add(__instance);
				BuildExclusion.SetupBuildExclusion(((Component)__instance).gameObject, BuildExclusion._bossHookExclusionRadius.Value);
			}
		}

		[HarmonyPatch(typeof(Destructible), "Start")]
		private static class Destructible_Start_Patch
		{
			private static List<int> JCBossPrefabHashes = new List<int>
			{
				StringExtensionMethods.GetStableHashCode("Crystal_Soul_Reaper_Cage"),
				StringExtensionMethods.GetStableHashCode("Crystal_Flame_Reaper_Cage"),
				StringExtensionMethods.GetStableHashCode("Crystal_Frost_Reaper_Cage")
			};

			private static void Postfix(Destructible __instance)
			{
				if (__instance.m_nview.IsValid() && __instance.m_nview.GetZDO() != null)
				{
					int prefab = __instance.m_nview.GetZDO().GetPrefab();
					if (JCBossPrefabHashes.Contains(prefab))
					{
						BuildExclusion.SetupBuildExclusion(((Component)__instance).gameObject, BuildExclusion._JCWorldBossExclusionRadius.Value);
					}
				}
			}
		}

		[HarmonyPatch(typeof(LocationProxy), "Awake")]
		private static class LocationProxy_Awake_Patch
		{
			private static List<int> proxyHashes = new List<int>
			{
				StringExtensionMethods.GetStableHashCode("DrakeNest01"),
				StringExtensionMethods.GetStableHashCode("Mistlands_DvergrBossEntrance1"),
				StringExtensionMethods.GetStableHashCode("Mistlands_DvergrTownEntrance1"),
				StringExtensionMethods.GetStableHashCode("Mistlands_DvergrTownEntrance2"),
				StringExtensionMethods.GetStableHashCode("MountainCave02")
			};

			private static void Postfix(LocationProxy __instance)
			{
				if (!((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsValid() && __instance.m_nview.GetZDO() != null)
				{
					int @int = __instance.m_nview.GetZDO().GetInt(ZDOVars.s_location, 0);
					if (proxyHashes.Contains(@int))
					{
						BuildExclusion.SetupBuildExclusion(((Component)__instance).gameObject, BuildExclusion._dungeonExclusionRadius.Value);
					}
				}
			}
		}

		public static ISet<DungeonGenerator> dungeons = new HashSet<DungeonGenerator>();

		public static ISet<OfferingBowl> offeringBowls = new HashSet<OfferingBowl>();

		public static ISet<BossStone> bossStones = new HashSet<BossStone>();
	}
	[HarmonyPatch(typeof(Valkyrie), "ShowText")]
	public class Valkyrie_ShowText_Patch
	{
		private static float s_textDuration = 27f;

		private static string s_introTopic = "Darkness Stirs...";

		private static string s_introText = "A shudder ripples through the limbs of Yggdrasil itself, against which the tenth realm currently nestles, stirring the oceans, and once again clearing away the mists of time.\r\n\r\nThe cause - the reawakening foes of the Allfather, their strength rebuilding as once again their avatars eagerly seek to breach their exile.\r\n\r\nWhile history turns over anew, something is not as it was. That which was once <color=#00eeee>cold</color>, barren and still, now moves. That which was mere <color=#500505>ash</color> now burns with greater fury. It seems Odin's enemies have found new brethren.\r\n\r\n<color=#eee600>Tyr</color>, the valorous patron of heroes has scoured the spirit world for allies of his own. A great wind wakes you from your deathly slumber, as great wings begin to carry you on your journey.\r\n\r\nAmidst the whispers of new dangers, and darkened skies - you hear the song of your ancestors, and a sense of offerings to be found in the ground beneath.\r\n\r\nHarken PLAYER_NAME! Life, death, destiny and fame await you...\r\n\r\n... in <color=#ff0000>Tyrenheim</color>!";

		public static bool Prefix(Valkyrie __instance)
		{
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			string newValue;
			try
			{
				newValue = "<color=yellow>" + Game.instance.GetPlayerProfile().GetName() + "</color>";
			}
			catch
			{
				newValue = "warrior";
			}
			__instance.m_introTopic = s_introTopic;
			__instance.m_introText = s_introText.Replace("PLAYER_NAME", newValue);
			__instance.m_textDuration = s_textDuration;
			TextViewer.instance.m_introText.fontSizeMin = 6f;
			TextViewer.instance.m_introText.richText = true;
			TMP_Text introText = TextViewer.instance.m_introText;
			introText.maxVisibleLines *= 2;
			TextViewer.instance.m_introText.rectTransform.SetSizeWithCurrentAnchors((Axis)1, 1150f);
			RectTransform rectTransform = TextViewer.instance.m_introText.rectTransform;
			rectTransform.anchoredPosition += new Vector2(0f, -100f);
			Debug.Log((object)$"{TextViewer.instance.m_introText.isTextTruncated} : {TextViewer.instance.m_introText.maxHeight} : {TextViewer.instance.m_introText.maxVisibleLines}");
			return true;
		}
	}
	public class InvStrip
	{
		[HarmonyPatch(typeof(Inventory), "Changed")]
		public class Inventory_Changed_Patch
		{
			public static void Prefix(Inventory __instance)
			{
				RunStrip(__instance);
			}
		}

		private static List<string> s_stripItemPrefabs = new List<string> { "WindBelt" };

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

		public static void Init()
		{
			foreach (string s_stripItemPrefab in s_stripItemPrefabs)
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(s_stripItemPrefab);
				if ((Object)(object)itemPrefab != (Object)null)
				{
					ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
					if ((Object)(object)component != (Object)null)
					{
						s_stripItemNames.Add(component.m_itemData.m_shared.m_name);
					}
				}
			}
		}

		public static void RunStrip(Inventory inv)
		{
			foreach (string itemName in s_stripItemNames)
			{
				inv.m_inventory.RemoveAll((ItemData x) => x.m_shared.m_name == itemName);
			}
		}
	}
	[HarmonyPatch(typeof(Character), "RPC_Damage")]
	public class Character_RPC_Damage_Patch
	{
		public static void Postfix(Character __instance, HitData hit)
		{
			if (__instance.IsPlayer() || !(__instance.GetHealth() <= 0f) || __instance.IsDead())
			{
				return;
			}
			Character attacker = hit.GetAttacker();
			if (((Object)(object)attacker == (Object)null && __instance.GetSEMan().HaveStatusEffect("SE_Burning")) || ((Object)(object)attacker != (Object)null && !attacker.IsPlayer() && !attacker.IsTamed()))
			{
				CharacterDrop[] componentsInChildren = ((Component)__instance).gameObject.GetComponentsInChildren<CharacterDrop>();
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					componentsInChildren[i].SetDropsEnabled(false);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Ragdoll), "Setup")]
	public class Ragdoll_SaveLootList_Patch
	{
		public static void Prefix(Ragdoll __instance, ref CharacterDrop characterDrop)
		{
			if ((Object)(object)characterDrop != (Object)null && (Object)(object)characterDrop.m_character != (Object)null && !characterDrop.m_character.IsPlayer() && !characterDrop.m_dropsEnabled)
			{
				characterDrop = null;
			}
		}
	}
	public static class NetworkDialog_Tweaks
	{
		[HarmonyPatch(typeof(ConnectPanel), "Update")]
		public class ConnectPanel_Patch
		{
			public static void Postfix(ConnectPanel __instance)
			{
				if ((Object)(object)Player.m_localPlayer != (Object)null && ((Character)Player.m_localPlayer).InGodMode())
				{
					return;
				}
				foreach (GameObject playerListElement in __instance.m_playerListElements)
				{
					Text component = ((Component)playerListElement.transform.Find("hostname")).GetComponent<Text>();
					if ((Object)(object)component != (Object)null)
					{
						component.text = "";
					}
				}
			}
		}

		private const string hostnameReplacement = "";
	}
	public static class OrientationFixes
	{
		[HarmonyPatch(typeof(Smelter), "UpdateSmoke")]
		public class Smelter_Patch
		{
			public static void Postfix(Smelter __instance)
			{
				if (!checkTransform(((Component)__instance).gameObject.transform, (float)Math.PI / 4f))
				{
					__instance.m_blockedSmoke = true;
				}
			}
		}

		[HarmonyPatch(typeof(Fireplace), "IsBurning")]
		public class Fireplace_Patch
		{
			public static void Postfix(Fireplace __instance, ref bool __result)
			{
				if (!checkTransform(((Component)__instance).gameObject.transform, (float)Math.PI / 4f))
				{
					__result = false;
				}
			}
		}

		[HarmonyPatch(typeof(CookingStation), "UpdateCooking")]
		public class CookingStation_Patch
		{
			public static bool Prefix(CookingStation __instance)
			{
				if (!__instance.m_nview.IsValid())
				{
					return false;
				}
				if (!checkTransform(((Component)__instance).gameObject.transform, (float)Math.PI / 4f))
				{
					__instance.UpdateVisual(false);
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Bed), "CheckExposure")]
		public class Bed_ExposurePatch
		{
			public static void Postfix(Bed __instance, Player human, ref bool __result)
			{
				if (!checkTransform(((Component)__instance).gameObject.transform, (float)Math.PI / 6f))
				{
					((Character)human).Message((MessageType)2, "Bed is not at a suitable orientation", 0, (Sprite)null);
					__result = false;
				}
			}
		}

		[HarmonyPatch(typeof(Bed), "IsCurrent")]
		public class Bed_CurrentPatch
		{
			public static void Postfix(Bed __instance, ref bool __result)
			{
				if (!checkTransform(((Component)__instance).gameObject.transform, (float)Math.PI / 6f))
				{
					__result = false;
				}
			}
		}

		[HarmonyPatch(typeof(CraftingStation), "CheckUsable")]
		public class CraftingStation_CheckUsablePatch
		{
			public static void Postfix(CraftingStation __instance, Player player, bool showMessage, ref bool __result)
			{
				if (!checkTransform(((Component)__instance).gameObject.transform, (float)Math.PI / 6f))
				{
					if (showMessage)
					{
						((Character)player).Message((MessageType)2, "Crafting station is not at a suitable orientation", 0, (Sprite)null);
					}
					__result = false;
				}
			}
		}

		[HarmonyPatch(typeof(CraftingStation), "HaveBuildStationInRange")]
		public class CraftingStation_BuildStationInRangePatch
		{
			public static bool Prefix(string name, Vector3 point, ref CraftingStation __result)
			{
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: Unknown result type (might be due to invalid IL or missing references)
				//IL_004f: Unknown result type (might be due to invalid IL or missing references)
				__result = null;
				foreach (CraftingStation allStation in CraftingStation.m_allStations)
				{
					if (!(allStation.m_name != name))
					{
						float stationBuildRange = allStation.GetStationBuildRange();
						point.y = ((Component)allStation).transform.position.y;
						if (Vector3.Distance(((Component)allStation).transform.position, point) < stationBuildRange && checkTransform(((Component)allStation).transform, (float)Math.PI / 6f))
						{
							__result = allStation;
						}
					}
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(StationExtension), "FindExtensions")]
		public class StationExtension_FindExtensionsPatch
		{
			public static void Postfix(CraftingStation station, List<StationExtension> extensions)
			{
				extensions.RemoveAll((StationExtension e) => !checkTransform(((Component)e).gameObject.transform, (float)Math.PI / 6f));
			}
		}

		[HarmonyPatch(typeof(Beehive), "UpdateBees")]
		public class Beehive_UpdatePatch
		{
			public static bool Prefix(Beehive __instance)
			{
				if (!checkTransform(((Component)__instance).gameObject.transform, (float)Math.PI / 4f))
				{
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Beehive), "Interact")]
		public class Beehive_InteractPatch
		{
			public static bool Prefix(Beehive __instance, Humanoid character)
			{
				if (!checkTransform(((Component)__instance).gameObject.transform, (float)Math.PI / 4f))
				{
					((Character)character).Message((MessageType)2, "The bees are disoriented", 0, (Sprite)null);
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Beehive), "RPC_Extract")]
		public class Beehive_ExtractPatch
		{
			public static bool Prefix(Beehive __instance)
			{
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: 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_002c: 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_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0040: 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_0060: 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_0066: 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_0075: 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_0080: Unknown result type (might be due to invalid IL or missing references)
				//IL_0085: Unknown result type (might be due to invalid IL or missing references)
				//IL_008d: Unknown result type (might be due to invalid IL or missing references)
				//IL_008f: Unknown result type (might be due to invalid IL or missing references)
				int honeyLevel = __instance.GetHoneyLevel();
				Vector3 val = __instance.m_spawnPoint.position - ((Component)__instance).gameObject.transform.up * 2.4f;
				if (honeyLevel > 0)
				{
					__instance.m_spawnEffect.Create(val, Quaternion.identity, (Transform)null, 1f, -1);
					for (int i = 0; i < honeyLevel; i++)
					{
						Vector2 val2 = Random.insideUnitCircle * 0.5f;
						Vector3 val3 = val + new Vector3(val2.x, -0.25f * (float)i, val2.y);
						ItemDrop component = ((Component)Object.Instantiate<ItemDrop>(__instance.m_honeyItem, val3, Quaternion.identity)).GetComponent<ItemDrop>();
						if (component != null)
						{
							component.SetStack(Game.instance.ScaleDrops(__instance.m_honeyItem.m_itemData, 1));
						}
					}
					__instance.ResetLevel();
				}
				return false;
			}
		}

		private const float maxAngleRadsGeneral = (float)Math.PI / 4f;

		private const float maxAngleRadsCrafting = (float)Math.PI / 6f;

		private const float maxAngleRadsBed = (float)Math.PI / 6f;

		private static bool checkTransform(Transform t, float thresholdRads)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return Mathf.Acos(t.up.y) < thresholdRads;
		}
	}
	public class PatreonPortal : MonoBehaviour
	{
		public static string patreonPortalPrefabName = "PatreonPortal";

		public static string patreonActivateFXName = "vfx_GodExplosion";

		public static Vector3 patreonSkin = new Vector3(0f, 1f, 1f) * 6f;

		public static string patreonKey = "tyrenheim_patreon_skin";

		public static string patreonMessage = "A powerful energy causes your skin to shift and tingle";

		public static GameObject patreonPortalPrefab;

		public static GameObject patreonFXPrefab;

		public static void SetupAssets()
		{
			patreonPortalPrefab = ZNetScene.instance.GetPrefab(patreonPortalPrefabName);
			patreonFXPrefab = ZNetScene.instance.GetPrefab(patreonActivateFXName);
			Transform val = patreonPortalPrefab.transform.Find("trigger");
			if ((Object)(object)val != (Object)null)
			{
				((Component)val).gameObject.AddComponent<PatreonPortal>();
			}
			else
			{
				Debug.Log((object)("Failed to add PatreonPortal component to object " + ((Object)val).name));
			}
		}

		private static void SetPatreon(Player p)
		{
			p.m_uniques.Add(patreonKey);
		}

		private static bool HasPatreonSkin(Player p)
		{
			return p.m_uniques.Contains(patreonKey);
		}

		public void Awake()
		{
		}

		private void OnTriggerEnter(Collider collider)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			Player component = ((Component)collider).GetComponent<Player>();
			if ((Object)(object)component != (Object)null && (Object)(object)Player.m_localPlayer == (Object)(object)component && !HasPatreonSkin(component))
			{
				component.SetSkinColor(patreonSkin);
				SetPatreon(component);
				Object.Instantiate<GameObject>(patreonFXPrefab, ((Component)component).transform.position, ((Component)component).transform.rotation);
				((Character)component).Message((MessageType)2, patreonMessage, 0, (Sprite)null);
			}
		}
	}
	public class PlayerSummon
	{
		[HarmonyPatch(typeof(Terminal), "InitTerminal")]
		public static class Terminal_Patch
		{
			[Serializable]
			[CompilerGenerated]
			private sealed class <>c
			{
				public static readonly <>c <>9 = new <>c();

				public static ConsoleEvent <>9__0_0;

				public static ConsoleEvent <>9__0_1;

				internal void <Postfix>b__0_0(ConsoleEventArgs args)
				{
					SummonCommand(args.Args);
				}

				internal void <Postfix>b__0_1(ConsoleEventArgs args)
				{
					DismissCommand(args.Args);
				}
			}

			public static void Postfix()
			{
				//IL_0032: 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)
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Expected O, but got Unknown
				//IL_006a: 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_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Expected O, but got Unknown
				object obj = <>c.<>9__0_0;
				if (obj == null)
				{
					ConsoleEvent val = delegate(ConsoleEventArgs args)
					{
						SummonCommand(args.Args);
					};
					<>c.<>9__0_0 = val;
					obj = (object)val;
				}
				new ConsoleCommand("summon", "", (ConsoleEvent)obj, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
				object obj2 = <>c.<>9__0_1;
				if (obj2 == null)
				{
					ConsoleEvent val2 = delegate(ConsoleEventArgs args)
					{
						DismissCommand(args.Args);
					};
					<>c.<>9__0_1 = val2;
					obj2 = (object)val2;
				}
				new ConsoleCommand("dismiss", "", (ConsoleEvent)obj2, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			}
		}

		public static Dictionary<string, Vector3> returnLocations = new Dictionary<string, Vector3>();

		public static void RPC_RequestDismiss(long sender, string target)
		{
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			if (!ZNet.instance.IsServer())
			{
				return;
			}
			ZNetPeer peer = ZNet.instance.GetPeer(sender);
			if (ZNet.instance.m_adminList != null && peer != null && peer.m_rpc != null && peer.m_rpc.GetSocket() != null && !ZNet.instance.m_adminList.Contains(peer.m_rpc.GetSocket().GetHostName()))
			{
				ZNet.instance.RemotePrint(peer.m_rpc, "You are not admin");
				return;
			}
			ZNetPeer val = null;
			foreach (ZNetPeer peer2 in ZNet.instance.m_peers)
			{
				if (peer2.IsReady() && peer2.m_playerName.ToLower() == target.ToLower())
				{
					val = peer2;
					break;
				}
			}
			if (val == null)
			{
				ZNet.instance.RemotePrint(peer.m_rpc, "Could not find player: " + target);
				return;
			}
			if (val == peer)
			{
				ZNet.instance.RemotePrint(peer.m_rpc, "Don't be silly, now");
				return;
			}
			if (!returnLocations.ContainsKey(val.m_playerName))
			{
				ZNet.instance.RemotePrint(peer.m_rpc, "No return location found for " + val.m_playerName);
				return;
			}
			ZRoutedRpc.instance.InvokeRoutedRPC(val.m_uid, "BeDismissed", new object[1] { returnLocations[val.m_playerName] });
			returnLocations.Remove(val.m_playerName);
		}

		public static void RPC_RequestSummon(long sender, string target, Vector3 destination)
		{
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			if (!ZNet.instance.IsServer())
			{
				return;
			}
			ZNetPeer peer = ZNet.instance.GetPeer(sender);
			if (ZNet.instance.m_adminList != null && peer != null && peer.m_rpc != null && peer.m_rpc.GetSocket() != null && !ZNet.instance.m_adminList.Contains(peer.m_rpc.GetSocket().GetHostName()))
			{
				ZNet.instance.RemotePrint(peer?.m_rpc, "You are not admin");
				return;
			}
			ZNetPeer val = null;
			foreach (ZNetPeer peer2 in ZNet.instance.m_peers)
			{
				if (peer2.IsReady() && peer2.m_playerName.ToLower() == target.ToLower())
				{
					val = peer2;
					break;
				}
			}
			if (val == null)
			{
				ZNet.instance.RemotePrint(peer?.m_rpc, "Could not find player: " + target);
				return;
			}
			if (val == peer)
			{
				ZNet.instance.RemotePrint(peer.m_rpc, "Ah, you lonely soul");
				return;
			}
			returnLocations[val.m_playerName] = ZDOMan.instance.GetZDO(val.m_characterID).m_position;
			ZNet.instance.RemotePrint(peer?.m_rpc, "Summoning Player: " + val.m_playerName);
			ZRoutedRpc.instance.InvokeRoutedRPC(val.m_uid, "BeSummoned", new object[1] { destination });
		}

		private static IEnumerator DelayedTeleport(Player p, Vector3 pos, float delay, string message)
		{
			//IL_000e: 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)
			MessageHud.instance.ShowBiomeFoundMsg(message, true);
			Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_shaman_protect"), ((Component)p).transform.position, ((Component)p).transform.rotation);
			yield return (object)new WaitForSeconds(delay);
			((Character)p).AttachStop();
			((Character)p).TeleportTo(pos, Quaternion.identity, true);
			((Character)p).m_lastGroundTouch = 0f;
		}

		public static void RPC_BeSummoned(long sender, Vector3 destination)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			Debug.Log((object)$"Player summoned to {destination}");
			((MonoBehaviour)Player.m_localPlayer).StartCoroutine(DelayedTeleport(Player.m_localPlayer, destination, 0f, "You are being summoned by the Gods"));
		}

		public static void RPC_BeDismissed(long sender, Vector3 destination)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			Debug.Log((object)$"Player dismissed to {destination}");
			((MonoBehaviour)Player.m_localPlayer).StartCoroutine(DelayedTeleport(Player.m_localPlayer, destination, 3f, "The Gods dismiss you"));
		}

		public static void DismissCommand(string[] args)
		{
			string text = string.Join(" ", new ArraySegment<string>(args, 1, args.Length - 1));
			ZRoutedRpc.instance.InvokeRoutedRPC("RequestDismiss", new object[1] { text });
		}

		public static void SummonCommand(string[] args)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			string text = string.Join(" ", new ArraySegment<string>(args, 1, args.Length - 1));
			ZRoutedRpc.instance.InvokeRoutedRPC("RequestSummon", new object[2]
			{
				text,
				((Component)Player.m_localPlayer).transform.position
			});
		}

		public static void RegisterRPC()
		{
			ZRoutedRpc.instance.Register<string, Vector3>("RequestSummon", (Action<long, string, Vector3>)RPC_RequestSummon);
			ZRoutedRpc.instance.Register<string>("RequestDismiss", (Action<long, string>)RPC_RequestDismiss);
			ZRoutedRpc.instance.Register<Vector3>("BeSummoned", (Action<long, Vector3>)RPC_BeSummoned);
			ZRoutedRpc.instance.Register<Vector3>("BeDismissed", (Action<long, Vector3>)RPC_BeDismissed);
		}
	}
	[HarmonyPatch(typeof(Game), "FindRandomUnconnectedPortal")]
	public class UnconnectedPortalsPatch
	{
		public static bool Prefix(Game __instance, string tag, ref ZDO __result)
		{
			__result = null;
			return tag != "";
		}
	}
	[HarmonyPatch(typeof(TeleportWorld), "RPC_SetTag")]
	public class TeleportWorldPatch
	{
		public static bool Prefix(TeleportWorld __instance, string tag)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			if (__instance.m_nview.IsValid() && __instance.m_nview.IsOwner() && !(__instance.GetText() == tag))
			{
				__instance.m_nview.GetZDO().Set("target", ZDOID.None);
			}
			return true;
		}
	}
	public static class ProcreationReplacements
	{
		public static int SS_GetNrOfInstancesXZ(GameObject prefab, Vector3 center, float maxRange, bool eventCreaturesOnly = false, bool procreationOnly = false)
		{
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			string text = ((Object)prefab).name + "(Clone)";
			if ((Object)(object)prefab.GetComponent<BaseAI>() != (Object)null)
			{
				List<BaseAI> instances = BaseAI.Instances;
				int num = 0;
				{
					foreach (BaseAI item in instances)
					{
						if (((Object)((Component)item).gameObject).name != text || (maxRange > 0f && Utils.DistanceXZ(center, ((Component)item).transform.position) > maxRange))
						{
							continue;
						}
						if (eventCreaturesOnly)
						{
							MonsterAI val = (MonsterAI)(object)((item is MonsterAI) ? item : null);
							if (Object.op_Implicit((Object)(object)val) && !val.IsEventCreature())
							{
								continue;
							}
						}
						if (procreationOnly)
						{
							Procreation component = ((Component)item).GetComponent<Procreation>();
							if (Object.op_Implicit((Object)(object)component) && !component.ReadyForProcreation())
							{
								continue;
							}
						}
						num++;
					}
					return num;
				}
			}
			GameObject[] array = GameObject.FindGameObjectsWithTag("spawned");
			int num2 = 0;
			GameObject[] array2 = array;
			foreach (GameObject val2 in array2)
			{
				if (((Object)val2).name.StartsWith(text) && (!(maxRange > 0f) || !(Vector3.Distance(center, val2.transform.position) > maxRange)))
				{
					num2++;
				}
			}
			return num2;
		}

		public static void ProcreateReplace(Procreation __instance)
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			if (!__instance.m_nview.IsValid() || !__instance.m_nview.IsOwner() || !__instance.m_character.IsTamed())
			{
				return;
			}
			if ((Object)(object)__instance.m_offspringPrefab == (Object)null)
			{
				string prefabName = Utils.GetPrefabName(__instance.m_offspring);
				__instance.m_offspringPrefab = ZNetScene.instance.GetPrefab(prefabName);
				int prefab = __instance.m_nview.GetZDO().GetPrefab();
				__instance.m_myPrefab = ZNetScene.instance.GetPrefab(prefab);
			}
			if (__instance.IsPregnant())
			{
				if (__instance.IsDue())
				{
					__instance.ResetPregnancy();
					GameObject val = Object.Instantiate<GameObject>(__instance.m_offspringPrefab, ((Component)__instance).transform.position - ((Component)__instance).transform.forward * __instance.m_spawnOffset, Quaternion.LookRotation(-((Component)__instance).transform.forward, Vector3.up));
					Character component = val.GetComponent<Character>();
					if (Object.op_Implicit((Object)(object)component))
					{
						component.SetTamed(__instance.m_character.IsTamed());
						component.SetLevel(Mathf.Max(__instance.m_minOffspringLevel, __instance.m_character.GetLevel()));
					}
					__instance.m_birthEffects.Create(val.transform.position, Quaternion.identity, (Transform)null, 1f, -1);
				}
			}
			else
			{
				if (Random.value <= __instance.m_pregnancyChance || __instance.m_baseAI.IsAlerted() || __instance.m_tameable.IsHungry())
				{
					return;
				}
				int num = SS_GetNrOfInstancesXZ(__instance.m_myPrefab, ((Component)__instance).transform.position, __instance.m_totalCheckRange);
				int num2 = SS_GetNrOfInstancesXZ(__instance.m_offspringPrefab, ((Component)__instance).transform.position, __instance.m_totalCheckRange);
				if (num + num2 < __instance.m_maxCreatures && SpawnSystem.GetNrOfInstances(__instance.m_myPrefab, ((Component)__instance).transform.position, __instance.m_partnerCheckRange, false, true) >= 2)
				{
					__instance.m_loveEffects.Create(((Component)__instance).transform.position, ((Component)__instance).transform.rotation, (Transform)null, 1f, -1);
					int @int = __instance.m_nview.GetZDO().GetInt("lovePoints", 0);
					@int++;
					__instance.m_nview.GetZDO().Set("lovePoints", @int);
					if (@int >= __instance.m_requiredLovePoints)
					{
						__instance.m_nview.GetZDO().Set("lovePoints", 0);
						__instance.MakePregnant();
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(Procreation), "Procreate")]
	public class ProcreationPatch
	{
		public static bool Prefix(Procreation __instance)
		{
			ProcreationReplacements.ProcreateReplace(__instance);
			return false;
		}
	}
	public class Messages
	{
		private static Dictionary<string, TyrRaven.TutorialText> buildPieceTutorials = new Dictionary<string, TyrRaven.TutorialText>();

		public static List<Triggers.LocationBasedMessage> locationBasedMessages = new List<Triggers.LocationBasedMessage>();

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

		public static TyrRaven.TutorialText welcomeText = new TyrRaven.TutorialText("Tyrenheim_Welcome", "Welcome to Tyrenheim", "Hail brave wanderer, and welcome to Tyrenheim!\nThis realm is reborn, washed clean by the great waters and winds - however, once again dark threats stir beyond the veil, and threaten this realm. Mighty Tyr beseeches you to venture forth into this realm to contain his great foes, and turn the land and its fruits to your needs and desires.\n\nI am <color=white>Askia</color>, confidante and herald of the Allfather Odin - tasked with watching and helping to guide your efforts in your onward journey, along with my lesser companion Hugin.");

		public static TyrRaven.TutorialText sacrificialStones = new TyrRaven.TutorialText("Tyrenheim_Sacrificial_Stones", "Forsaken Powers", "The dark magic of the foes you seek can be harnessed by attuning to their sacrificial monoliths. However, Odin has cast these great stones out amidst the world, hidden from all but the bravest of souls.\nBe wary, as one needs to bear witness to the death of one of their incarnations to attain their power.");

		public static TyrRaven.TutorialText nonOwnedTombstone = new TyrRaven.TutorialText("Tyrenheim_Unowned_Tombstone", "Grave Consequences", "Should a fellow Viking fall, you should leave their belongings in place as a tribute to their adventure - unless they have sought your aid.\n\nViolating the body of another will not be tolerated. The Gods are watching.");

		public static TyrRaven.TutorialText notWorthy = new TyrRaven.TutorialText("Tyrenheim_Not_Worthy", "A Worthy Vessel", "The powers of these dark spirits can only be claimed by those who have defeated their incarnation. Seek them out, and rend them from this land.");

		public static TyrRaven.TutorialText wardCryptProximity = new TyrRaven.TutorialText("Tyrenheim_Ward_Crypt", "Undead Interference", "Careful wanderer - a dark force in a nearby crypt is causing undead to rise.\n\nWhatever twisted energies emanate from within are causing nearby wardstones to shatter.");

		public static TyrRaven.TutorialText wardCaveProximity = wardCryptProximity;

		public static TyrRaven.TutorialText wardBossProximity = new TyrRaven.TutorialText("Tyrenheim_Ward_Boss", "Planar Disjunction", "I sense a powerful artifact nearby, capable of channelling one of the great, dark spirits.\n\nThe ethereal fury spilling through the veil is causing nearby wardstones to shatter!");

		public TyrRaven.TutorialText reachTheGods = new TyrRaven.TutorialText("Tyrenheim_Reach_Gods", "Call through the Veil", "");

		public static void loadBuildPieceTutorials()
		{
		}

		public static void loadLocationTutorials()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			locationBasedMessages.Add(new Triggers.LocationBasedMessage(new Vector3(126f, 33f, 1f), 15f, welcomeText));
			locationBasedMessages.Add(new Triggers.LocationBasedMessage(new Vector3(126f, 33f, 1f), 15f, sacrificialStones));
		}

		public static void loadHuginBlocks()
		{
			huginBlockKeys.Add("temple1");
			huginBlockKeys.Add("temple2");
			huginBlockKeys.Add("temple4");
		}
	}
	public static class TyrRaven
	{
		public class TutorialText
		{
			public string m_tutorialKey;

			public string m_topic;

			public string m_text;

			public TutorialText(string key, string topic, string text)
			{
				m_tutorialKey = key;
				m_topic = topic;
				m_text = text;
			}
		}

		public static Raven r = null;

		public static GameObject landOn = null;

		private static List<RavenText> messageQueue = new List<RavenText>();

		public static GameObject s_askiaPrefab;

		public static void SetupAssets()
		{
			foreach (GameObject allPrefab in Assets.allPrefabs)
			{
				if ((Object)(object)allPrefab.GetComponent<Raven>() != (Object)null)
				{
					s_askiaPrefab = allPrefab;
					CreateAskia();
				}
			}
		}

		public static void CreateAskia()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			r = Object.Instantiate<GameObject>(s_askiaPrefab, new Vector3(0f, 0f, 0f), Quaternion.identity).GetComponent<Raven>();
			if ((Object)(object)r != (Object)null)
			{
				SetupRaven(r);
			}
		}

		private static void SetupRaven(Raven raven)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			raven.m_name = "Askia";
			raven.m_spawnDistance = 10f;
			raven.m_textCullDistance = 15f;
			((Component)raven).gameObject.transform.localScale = new Vector3(3f, 2.6f, 3.6f);
			r.m_randomTextsImportant.Clear();
			r.m_randomTextsImportant.Add("Wanderer, I would speak with you!");
			r.m_randomTextsImportant.Add("Wanderer, a moment, please!");
		}

		public static RavenText GetText()
		{
			if (r.m_hasTalked)
			{
				messageQueue.RemoveAll((RavenText txt) => txt == r.m_currentText);
			}
			messageQueue.RemoveAll((RavenText txt) => Player.m_localPlayer.HaveSeenTutorial(txt.m_key));
			if (messageQueue.Count == 0)
			{
				return null;
			}
			return messageQueue[0];
		}

		public static void Message(TutorialText text)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			if (string.IsNullOrEmpty(text.m_tutorialKey) || !messageQueue.Exists((RavenText t) => t.m_key == text.m_tutorialKey))
			{
				RavenText val = new RavenText();
				val.m_static = false;
				val.m_munin = true;
				val.m_key = text.m_tutorialKey;
				val.m_topic = text.m_topic;
				val.m_text = text.m_text;
				messageQueue.Add(val);
			}
		}
	}
	[HarmonyPatch(typeof(Raven), "Awake")]
	internal static class Raven_Awake_Patch
	{
		private static bool Prefix(Raven __instance)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (__instance.m_name == TyrRaven.s_askiaPrefab.GetComponent<Raven>().m_name)
			{
				((Component)__instance).transform.position = new Vector3(0f, 100000f, 0f);
				__instance.m_animator = __instance.m_visual.GetComponentInChildren<Animator>();
				__instance.m_collider = ((Component)__instance).gameObject.GetComponent<Collider>();
				((MonoBehaviour)__instance).InvokeRepeating("IdleEffect", Random.Range(__instance.m_idleEffectIntervalMin, __instance.m_idleEffectIntervalMax), Random.Range(__instance.m_idleEffectIntervalMin, __instance.m_idleEffectIntervalMax));
				((MonoBehaviour)__instance).InvokeRepeating("CheckSpawn", 1f, 1f);
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Raven), "CheckSpawn")]
	internal static class Raven_CheckSpawn_Patch
	{
		private static bool Prefix(Raven __instance)
		{
			if ((Object)(object)__instance == (Object)(object)TyrRaven.r)
			{
				Triggers.CheckLocationTriggers();
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Raven), "GetBestText")]
	internal static class Raven_GetBestText_Patch
	{
		private static bool Prefix(Raven __instance, ref RavenText __result)
		{
			if ((Object)(object)__instance == (Object)(object)TyrRaven.r)
			{
				__result = TyrRaven.GetText();
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Raven), "FindSpawnPoint")]
	internal static class Raven_FindSpawnPoint_Patch
	{
		private static bool Prefix(Raven __instance, ref bool __result, ref Vector3 point, ref GameObject landOn)
		{
			//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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)(object)TyrRaven.r)
			{
				float num = 5000f;
				Vector3 position = ((Component)Player.m_localPlayer).transform.position;
				Vector3 forward = ((Component)Utils.GetMainCamera()).transform.forward;
				forward.y = 0f;
				((Vector3)(ref forward)).Normalize();
				point = new Vector3(0f, -999f, 0f);
				landOn = null;
				bool flag = false;
				float num2 = default(float);
				Vector3 val3 = default(Vector3);
				GameObject val4 = default(GameObject);
				for (int i = 0; i < 20; i++)
				{
					Vector3 val = Quaternion.Euler(0f, (float)Random.Range(-30, 30), 0f) * forward;
					Vector3 val2 = position + val * Random.Range(__instance.m_spawnDistance - 5f, __instance.m_spawnDistance);
					if (ZoneSystem.instance.GetSolidHeight(val2, ref num2, ref val3, ref val4) && num2 > ZoneSystem.instance.m_waterLevel && num2 > point.y && num2 < num && val3.y > 0.5f && Mathf.Abs(num2 - position.y) < 2f)
					{
						val2.y = num2;
						point = val2;
						landOn = val4;
						flag = true;
					}
				}
				__result = flag;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Raven), "RegisterStaticText")]
	internal static class Raven_RegisterStaticText_Patch
	{
		private static bool Prefix(RavenText text)
		{
			if (Messages.huginBlockKeys.Contains(text.m_key))
			{
				return false;
			}
			return true;
		}
	}
	public class ShipMod
	{
		public static ConfigEntry<float> _shipDamageInterval;

		public static ConfigEntry<float> _shipDamage;

		public static ConfigEntry<float> _shipMinDamageForce;

		public static void SetupConfig(Mod instance)
		{
			_shipDamageInterval = instance.SyncedConfig("ShipDamage", "Ship Damage Min Interval (secs)", 2f, "Minimum time interval between ship damage occurrences due to water");
			_shipDamage = instance.SyncedConfig("ShipDamage", "Ship Damage", 10f, "Damage applied to ships from water forces");
			_shipMinDamageForce = instance.SyncedConfig("ShipDamage", "Ship Damage Min Force", 2.5f, "Minimum water force required before damage is applied");
		}
	}
	[HarmonyPatch(typeof(ShipControlls), "RPC_RequestControl")]
	public class ShipControlsPatch
	{
		public static bool Prefix(ShipControlls __instance)
		{
			if ((Object)(object)__instance.m_ship != (Object)null)
			{
				__instance.m_ship.m_minWaterImpactInterval = Math.Max(0.1f, ShipMod._shipDamageInterval.Value);
				__instance.m_ship.m_waterImpactDamage = Math.Max(0f, ShipMod._shipDamage.Value);
				__instance.m_ship.m_minWaterImpactForce = Math.Max(0f, ShipMod._shipMinDamageForce.Value);
			}
			return true;
		}
	}
	public class MobTweaks
	{
		public static void ZNS_Init(ZNetScene instance)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = ZNetScene.instance.GetPrefab("Surtling");
			prefab.GetComponent<Character>().m_tolerateWater = true;
			prefab.GetComponent<BaseAI>().m_avoidWater = false;
			ZNetScene.instance.GetPrefab("BlobTar").GetComponent<Character>().m_faction = (Faction)7;
		}
	}
	public static class Triggers
	{
		public class LocationBasedMessage
		{
			public Vector3 location;

			public float radius;

			public TyrRaven.TutorialText text;

			public LocationBasedMessage(Vector3 loc, float r, TyrRaven.TutorialText txt)
			{
				//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)
				location = loc;
				radius = r;
				text = txt;
			}
		}

		[HarmonyPatch(typeof(TombStone), "Interact")]
		private static class TombStone_Interact_Patch
		{
			private static void Postfix(TombStone __instance, Humanoid character)
			{
				if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && !__instance.IsOwner())
				{
					Graverobbing.TombstoneInteract(Player.m_localPlayer, __instance);
					TyrRaven.Message(Messages.nonOwnedTombstone);
				}
			}
		}

		public static Incinerator incineratorPrefab;

		public static GameObject lightningPrefab;

		public static void CheckLocationTriggers()
		{
			//IL_0026: 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)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			foreach (LocationBasedMessage locationBasedMessage in Messages.locationBasedMessages)
			{
				if (Vector3.Distance(locationBasedMessage.location, ((Component)localPlayer).transform.position) < locationBasedMessage.radius)
				{
					TyrRaven.Message(locationBasedMessage.text);
				}
			}
		}
	}
	[BepInPlugin("tyrenheim.tyrenheimcustom", "Tyrenheim_Raven", "0.14.7")]
	public class Mod : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(ZNet), "Awake")]
		public static class ZNetAwakePatch
		{
			public static void Postfix(ZNet __instance)
			{
				Ravencast.RegisterRPC();
				Graverobbing.RegisterRPC();
				PlayerSummon.RegisterRPC();
				BossWorthiness.RegisterRPC();
			}
		}

		private const string AuthorName = "JoeOsborne";

		private const string ModName = "Tyrenheim_Raven";

		private const string ModVer = "0.14.7";

		private const string ModGuid = "tyrenheim.tyrenheimcustom";

		private readonly ConfigSync configSync = new ConfigSync("Tyrenheim_Raven")
		{
			DisplayName = "Tyrenheim_Raven",
			CurrentVersion = "0.14.7",
			MinimumRequiredVersion = "0.14.7"
		};

		public static ConfigEntry<bool> _configLocked;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			ShipMod.SetupConfig(this);
			BuildExclusion.SetupConfig(this);
			_configLocked = SyncedConfig("General", "Force Server Config", defaultVal: true, "Force Server Config");
			configSync.AddLockingConfigEntry<bool>(_configLocked);
			SetupWatcher();
			_harmony = new Harmony("tyrenheim.tyrenheimcustom");
			_harmony.PatchAll();
			Messages.loadBuildPieceTutorials();
			Messages.loadLocationTutorials();
			Messages.loadHuginBlocks();
		}

		private void SetupWatcher()
		{
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath);
			fileSystemWatcher.Changed += ReadConfigValues;
			fileSystemWatcher.Created += ReadConfigValues;
			fileSystemWatcher.Renamed += ReadConfigValues;
			fileSystemWatcher.IncludeSubdirectories = true;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.EnableRaisingEvents = true;
		}

		private void ReadConfigValues(object sender, FileSystemEventArgs e)
		{
			if (File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath))
			{
				((BaseUnityPlugin)this).Config.Reload();
			}
		}

		public ConfigEntry<T> SyncedConfig<T>(string group, string name, T defaultVal, string desc)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, defaultVal, new ConfigDescription(desc, (AcceptableValueBase)null, Array.Empty<object>()));
			configSync.AddConfigEntry<T>(val).SynchronizedConfig = true;
			return val;
		}
	}
	public static class Ravencast
	{
		[HarmonyPatch(typeof(Terminal), "InitTerminal")]
		public static class Terminal_Patch
		{
			[Serializable]
			[CompilerGenerated]
			private sealed class <>c
			{
				public static readonly <>c <>9 = new <>c();

				public static ConsoleEvent <>9__0_0;

				public static ConsoleEvent <>9__0_1;

				public static ConsoleEvent <>9__0_2;

				internal void <Postfix>b__0_0(ConsoleEventArgs args)
				{
					RavencastAppend(args.Context, args.Args);
				}

				internal void <Postfix>b__0_1(ConsoleEventArgs args)
				{
					RavencastSend(args.Context, args.Args);
				}

				internal void <Postfix>b__0_2(ConsoleEventArgs args)
				{
					RavencastClear();
				}
			}

			public static void Postfix()
			{
				//IL_0032: 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)
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Expected O, but got Unknown
				//IL_006a: 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_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Expected O, but got Unknown
				//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
				//IL_008e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0093: Unknown result type (might be due to invalid IL or missing references)
				//IL_0099: Expected O, but got Unknown
				object obj = <>c.<>9__0_0;
				if (obj == null)
				{
					ConsoleEvent val = delegate(ConsoleEventArgs args)
					{
						RavencastAppend(args.Context, args.Args);
					};
					<>c.<>9__0_0 = val;
					obj = (object)val;
				}
				new ConsoleCommand("ravencast", "", (ConsoleEvent)obj, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
				object obj2 = <>c.<>9__0_1;
				if (obj2 == null)
				{
					ConsoleEvent val2 = delegate(ConsoleEventArgs args)
					{
						RavencastSend(args.Context, args.Args);
					};
					<>c.<>9__0_1 = val2;
					obj2 = (object)val2;
				}
				new ConsoleCommand("ravencast_send", "", (ConsoleEvent)obj2, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
				object obj3 = <>c.<>9__0_2;
				if (obj3 == null)
				{
					ConsoleEvent val3 = delegate
					{
						RavencastClear();
					};
					<>c.<>9__0_2 = val3;
					obj3 = (object)val3;
				}
				new ConsoleCommand("ravencast_clear", "", (ConsoleEvent)obj3, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			}
		}

		private static string messageBuffer;

		public static void RPC_RequestRavencast(long sender, string msg)
		{
			if (ZNet.instance.IsServer())
			{
				Debug.Log((object)("Sending Ravencast: " + msg));
				ZNetPeer peer = ZNet.instance.GetPeer(sender);
				if (ZNet.instance.m_adminList != null && peer != null && peer.m_rpc != null && peer.m_rpc.GetSocket() != null && !ZNet.instance.m_adminList.Contains(peer.m_rpc.GetSocket().GetHostName()))
				{
					ZNet.instance.RemotePrint(peer.m_rpc, "You are not admin");
					return;
				}
				ZRoutedRpc.instance.InvokeRoutedRPC(ZNetView.Everybody, "ReceiveRavencast", new object[1] { msg });
			}
		}

		public static void RPC_ReceiveRavencast(long sender, string msg)
		{
			if (!ZNet.instance.IsServer() || !ZNet.instance.IsDedicated())
			{
				TyrRaven.Message(new TyrRaven.TutorialText("", "Odin's Herald", "Adventurer! I bring information from the Powers That Be:\n\n <color=yellow>" + msg + "</color>"));
			}
		}

		private static void RavencastAppend(Terminal terminal, string[] args)
		{
			string text = string.Join(" ", new ArraySegment<string>(args, 1, args.Length - 1));
			messageBuffer = messageBuffer + " " + text.Replace("\\n", "\n");
			terminal.AddString($">> Ravencast message length is now {messageBuffer.Length} chars.");
		}

		private static void RavencastClear()
		{
			messageBuffer = "";
		}

		private static void RavencastSend(Terminal terminal, string[] args)
		{
			ZRoutedRpc.instance.InvokeRoutedRPC("RequestRavencast", new object[1] { messageBuffer });
			RavencastClear();
		}

		public static void RegisterRPC()
		{
			ZRoutedRpc.instance.Register<string>("RequestRavencast", (Action<long, string>)RPC_RequestRavencast);
			ZRoutedRpc.instance.Register<string>("ReceiveRavencast", (Action<long, string>)RPC_ReceiveRavencast);
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ServerSync
{
	[PublicAPI]
	internal abstract class OwnConfigEntryBase
	{
		public object? LocalBaseValue;

		public bool SynchronizedConfig = true;

		public abstract ConfigEntryBase BaseConfig { get; }
	}
	[PublicAPI]
	internal class SyncedConfigEntry<T> : OwnConfigEntryBase
	{
		public readonly ConfigEntry<T> SourceConfig;

		public override ConfigEntryBase BaseConfig => (ConfigEntryBase)(object)SourceConfig;

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

		public SyncedConfigEntry(ConfigEntry<T> sourceConfig)
		{
			SourceConfig = sourceConfig;
		}

		public void AssignLocalValue(T value)
		{
			if (LocalBaseValue == null)
			{
				Value = value;
			}
			else
			{
				LocalBaseValue = value;
			}
		}
	}
	internal abstract class CustomSyncedValueBase
	{
		public object? LocalBaseValue;

		public readonly string Identifier;

		public readonly Type Type;

		private object? boxedValue;

		protected bool localIsOwner;

		public readonly int Priority;

		public object? BoxedValue
		{
			get
			{
				return boxedValue;
			}
			set
			{
				boxedValue = value;
				this.ValueChanged?.Invoke();
			}
		}

		public event Action? ValueChanged;

		protected CustomSyncedValueBase(ConfigSync configSync, string identifier, Type type, int priority)
		{
			Priority = priority;
			Identifier = identifier;
			Type = type;
			configSync.AddCustomValue(this);
			localIsOwner = configSync.IsSourceOfTruth;
			configSync.SourceOfTruthChanged += delegate(bool truth)
			{
				localIsOwner = truth;
			};
		}
	}
	[PublicAPI]
	internal sealed class CustomSyncedValue<T> : CustomSyncedValueBase
	{
		public T Value
		{
			get
			{
				return (T)base.BoxedValue;
			}
			set
			{
				base.BoxedValue = value;
			}
		}

		public CustomSyncedValue(ConfigSync configSync, string identifier, T value = default(T), int priority = 0)
			: base(configSync, identifier, typeof(T), priority)
		{
			Value = value;
		}

		public void AssignLocalValue(T value)
		{
			if (localIsOwner)
			{
				Value = value;
			}
			else
			{
				LocalBaseValue = value;
			}
		}
	}
	internal class ConfigurationManagerAttributes
	{
		[UsedImplicitly]
		public bool? ReadOnly = false;
	}
	[PublicAPI]
	internal class ConfigSync
	{
		[HarmonyPatch(typeof(ZRpc), "HandlePackage")]
		private static class SnatchCurrentlyHandlingRPC
		{
			public static ZRpc? currentRpc;

			[HarmonyPrefix]
			private static void Prefix(ZRpc __instance)
			{
				currentRpc = __instance;
			}
		}

		[HarmonyPatch(typeof(ZNet), "Awake")]
		internal static class RegisterRPCPatch
		{
			[HarmonyPostfix]
			private static void Postfix(ZNet __instance)
			{
				isServer = __instance.IsServer();
				foreach (ConfigSync configSync2 in configSyncs)
				{
					ZRoutedRpc.instance.Register<ZPackage>(configSync2.Name + " ConfigSync", (Action<long, ZPackage>)configSync2.RPC_FromOtherClientConfigSync);
					if (isServer)
					{
						configSync2.InitialSyncDone = true;
						Debug.Log((object)("Registered '" + configSync2.Name + " ConfigSync' RPC - waiting for incoming connections"));
					}
				}
				if (isServer)
				{
					((MonoBehaviour)__instance).StartCoroutine(WatchAdminListChanges());
				}
				static void SendAdmin(List<ZNetPeer> peers, bool isAdmin)
				{
					ZPackage package = ConfigsToPackage(null, null, new PackageEntry[1]
					{
						new PackageEntry
						{
							section = "Internal",
							key = "lockexempt",
							type = typeof(bool),
							value = isAdmin
						}
					});
					ConfigSync configSync = configSyncs.First();
					if (configSync != null)
					{
						((MonoBehaviour)ZNet.instance).StartCoroutine(configSync.sendZPackage(peers, package));
					}
				}
				static IEnumerator WatchAdminListChanges()
				{
					SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance);
					List<string> CurrentList = new List<string>(adminList.GetList());
					while (true)
					{
						yield return (object)new WaitForSeconds(30f);
						if (!adminList.GetList().SequenceEqual(CurrentList))
						{
							CurrentList = new List<string>(adminList.GetList());
							List<ZNetPeer> adminPeer = (from p in ZNet.instance.GetPeers()
								where adminList.Contains(p.m_rpc.GetSocket().GetHostName())
								select p).ToList();
							List<ZNetPeer> nonAdminPeer = ZNet.instance.GetPeers().Except(adminPeer).ToList();
							SendAdmin(nonAdminPeer, isAdmin: false);
							SendAdmin(adminPeer, isAdmin: true);
						}
					}
				}
			}
		}

		[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
		private static class RegisterClientRPCPatch
		{
			[HarmonyPostfix]
			private static void Postfix(ZNet __instance, ZNetPeer peer)
			{
				if (__instance.IsServer())
				{
					return;
				}
				foreach (ConfigSync configSync in configSyncs)
				{
					peer.m_rpc.Register<ZPackage>(configSync.Name + " ConfigSync", (Action<ZRpc, ZPackage>)configSync.RPC_FromServerConfigSync);
				}
			}
		}

		private class ParsedConfigs
		{
			public readonly Dictionary<OwnConfigEntryBase, object?> configValues = new Dictionary<OwnConfigEntryBase, object>();

			public readonly Dictionary<CustomSyncedValueBase, object?> customValues = new Dictionary<CustomSyncedValueBase, object>();
		}

		[HarmonyPatch(typeof(ZNet), "Shutdown")]
		private class ResetConfigsOnShutdown
		{
			[HarmonyPostfix]
			private static void Postfix()
			{
				ProcessingServerUpdate = true;
				foreach (ConfigSync configSync in configSyncs)
				{
					configSync.resetConfigsFromServer();
					configSync.IsSourceOfTruth = true;
					configSync.InitialSyncDone = false;
				}
				ProcessingServerUpdate = false;
			}
		}

		[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
		private class SendConfigsAfterLogin
		{
			private class BufferingSocket : ISocket
			{
				public volatile bool finished = false;

				public volatile int versionMatchQueued = -1;

				public readonly List<ZPackage> Package = new List<ZPackage>();

				public readonly ISocket Original;

				public BufferingSocket(ISocket original)
				{
					Original = original;
				}

				public bool IsConnected()
				{
					return Original.IsConnected();
				}

				public ZPackage Recv()
				{
					return Original.Recv();
				}

				public int GetSendQueueSize()
				{
					return Original.GetSendQueueSize();
				}

				public int GetCurrentSendRate()
				{
					return Original.GetCurrentSendRate();
				}

				public bool IsHost()
				{
					return Original.IsHost();
				}

				public void Dispose()
				{
					Original.Dispose();
				}

				public bool GotNewData()
				{
					return Original.GotNewData();
				}

				public void Close()
				{
					Original.Close();
				}

				public string GetEndPointString()
				{
					return Original.GetEndPointString();
				}

				public void GetAndResetStats(out int totalSent, out int totalRecv)
				{
					Original.GetAndResetStats(ref totalSent, ref totalRecv);
				}

				public void GetConnectionQuality(out float localQuality, out float remoteQuality, out int ping, out float outByteSec, out float inByteSec)
				{
					Original.GetConnectionQuality(ref localQuality, ref remoteQuality, ref ping, ref outByteSec, ref inByteSec);
				}

				public ISocket Accept()
				{
					return Original.Accept();
				}

				public int GetHostPort()
				{
					return Original.GetHostPort();
				}

				public bool Flush()
				{
					return Original.Flush();
				}

				public string GetHostName()
				{
					return Original.GetHostName();
				}

				public void VersionMatch()
				{
					if (finished)
					{
						Original.VersionMatch();
					}
					else
					{
						versionMatchQueued = Package.Count;
					}
				}

				public void Send(ZPackage pkg)
				{
					//IL_0057: Unknown result type (might be due to invalid IL or missing references)
					//IL_005d: Expected O, but got Unknown
					int pos = pkg.GetPos();
					pkg.SetPos(0);
					int num = pkg.ReadInt();
					if ((num == StringExtensionMethods.GetStableHashCode("PeerInfo") || num == StringExtensionMethods.GetStableHashCode("RoutedRPC") || num == StringExtensionMethods.GetStableHashCode("ZDOData")) && !finished)
					{
						ZPackage val = new ZPackage(pkg.GetArray());
						val.SetPos(pos);
						Package.Add(val);
					}
					else
					{
						pkg.SetPos(pos);
						Original.Send(pkg);
					}
				}
			}

			[HarmonyPrefix]
			[HarmonyPriority(800)]
			private static void Prefix(ref Dictionary<Assembly, BufferingSocket>? __state, ZNet __instance, ZRpc rpc)
			{
				//IL_0078: Unknown result type (might be due to invalid IL or missing references)
				//IL_007e: Invalid comparison between Unknown and I4
				if (__instance.IsServer())
				{
					BufferingSocket value = new BufferingSocket(rpc.GetSocket());
					AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc, value);
					object? obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc });
					ZNetPeer val = (ZNetPeer)((obj is ZNetPeer) ? obj : null);
					if (val != null && (int)ZNet.m_onlineBackend > 0)
					{
						AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val, value);
					}
					if (__state == null)
					{
						__state = new Dictionary<Assembly, BufferingSocket>();
					}
					__state[Assembly.GetExecutingAssembly()] = value;
				}
			}

			[HarmonyPostfix]
			private static void Postfix(Dictionary<Assembly, BufferingSocket> __state, ZNet __instance, ZRpc rpc)
			{
				ZRpc rpc2 = rpc;
				ZNet __instance2 = __instance;
				Dictionary<Assembly, BufferingSocket> __state2 = __state;
				ZNetPeer peer;
				if (__instance2.IsServer())
				{
					object obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 });
					peer = (ZNetPeer)((obj is ZNetPeer) ? obj : null);
					if (peer == null)
					{
						SendBufferedData();
					}
					else
					{
						((MonoBehaviour)__instance2).StartCoroutine(sendAsync());
					}
				}
				void SendBufferedData()
				{
					if (rpc2.GetSocket() is BufferingSocket bufferingSocket)
					{
						AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc2, bufferingSocket.Original);
						object? obj2 = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 });
						ZNetPeer val = (ZNetPeer)((obj2 is ZNetPeer) ? obj2 : null);
						if (val != null)
						{
							AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val, bufferingSocket.Original);
						}
					}
					BufferingSocket bufferingSocket2 = __state2[Assembly.GetExecutingAssembly()];
					bufferingSocket2.finished = true;
					for (int i = 0; i < bufferingSocket2.Package.Count; i++)
					{
						if (i == bufferingSocket2.versionMatchQueued)
						{
							bufferingSocket2.Original.VersionMatch();
						}
						bufferingSocket2.Original.Send(bufferingSocket2.Package[i]);
					}
					if (bufferingSocket2.Package.Count == bufferingSocket2.versionMatchQueued)
					{
						bufferingSocket2.Original.VersionMatch();
					}
				}
				IEnumerator sendAsync()
				{
					foreach (ConfigSync configSync in configSyncs)
					{
						List<PackageEntry> entries = new List<PackageEntry>();
						if (configSync.CurrentVersion != null)
						{
							entries.Add(new PackageEntry
							{
								section = "Internal",
								key = "serverversion",
								type = typeof(string),
								value = configSync.CurrentVersion
							});
						}
						MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null);
						SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance);
						entries.Add(new PackageEntry
						{
							section = "Internal",
							key = "lockexempt",
							type = typeof(bool),
							value = (((object)listContainsId == null) ? ((object)adminList.Contains(rpc2.GetSocket().GetHostName())) : listContainsId.Invoke(ZNet.instance, new object[2]
							{
								adminList,
								rpc2.GetSocket().GetHostName()
							}))
						});
						ZPackage package = ConfigsToPackage(configSync.allConfigs.Select((OwnConfigEntryBase c) => c.BaseConfig), configSync.allCustomValues, entries, partial: false);
						yield return ((MonoBehaviour)__instance2).StartCoroutine(configSync.sendZPackage(new List<ZNetPeer> { peer }, package));
					}
					SendBufferedData();
				}
			}
		}

		private class PackageEntry
		{
			public string section = null;

			public string key = null;

			public Type type = null;

			public object? value;
		}

		[HarmonyPatch(typeof(ConfigEntryBase), "GetSerializedValue")]
		private static class PreventSavingServerInfo
		{
			[HarmonyPrefix]
			private static bool Prefix(ConfigEntryBase __instance, ref string __result)
			{
				OwnConfigEntryBase ownConfigEntryBase = configData(__instance);
				if (ownConfigEntryBase == null || isWritableConfig(ownConfigEntryBase))
				{
					return true;
				}
				__result = TomlTypeConverter.ConvertToString(ownConfigEntryBase.LocalBaseValue, __instance.SettingType);
				return false;
			}
		}

		[HarmonyPatch(typeof(ConfigEntryBase), "SetSerializedValue")]
		private static class PreventConfigRereadChangingValues
		{
			[HarmonyPrefix]
			private static bool Prefix(ConfigEntryBase __instance, string value)
			{
				OwnConfigEntryBase ownConfigEntryBase = configData(__instance);
				if (ownConfigEntryBase == null || ownConfigEntryBase.LocalBaseValue == null)
				{
					return true;
				}
				try
				{
					ownConfigEntryBase.LocalBaseValue = TomlTypeConverter.ConvertToValue(value, __instance.SettingType);
				}
				catch (Exception ex)
				{
					Debug.LogWarning((object)$"Config value of setting \"{__instance.Definition}\" could not be parsed and will be ignored. Reason: {ex.Message}; Value: {value}");
				}
				return false;
			}
		}

		private class InvalidDeserializationTypeException : Exception
		{
			public string expected = null;

			public string received = null;

			public string field = "";
		}

		public static bool ProcessingServerUpdate;

		public readonly string Name;

		public string? DisplayName;

		public string? CurrentVersion;

		public string? MinimumRequiredVersion;

		public bool ModRequired = false;

		private bool? forceConfigLocking;

		private bool isSourceOfTruth = true;

		private static readonly HashSet<ConfigSync> configSyncs;

		private readonly HashSet<OwnConfigEntryBase> allConfigs = new HashSet<OwnConfigEntryBase>();

		private HashSet<CustomSyncedValueBase> allCustomValues = new HashSet<CustomSyncedValueBase>();

		private static bool isServer;

		private static bool lockExempt;

		private OwnConfigEntryBase? lockedConfig = null;

		private const byte PARTIAL_CONFIGS = 1;

		private const byte FRAGMENTED_CONFIG = 2;

		private const byte COMPRESSED_CONFIG = 4;

		private readonly Dictionary<string, SortedDictionary<int, byte[]>> configValueCache = new Dictionary<string, SortedDictionary<int, byte[]>>();

		private readonly List<KeyValuePair<long, string>> cacheExpirations = new List<KeyValuePair<long, string>>();

		private static long packageCounter;

		public bool IsLocked
		{
			get
			{
				bool? flag = forceConfigLocking;
				bool num;
				if (!flag.HasValue)
				{
					if (lockedConfig == null)
					{
						goto IL_0052;
					}
					num = ((IConvertible)lockedConfig.BaseConfig.BoxedValue).ToInt32(CultureInfo.InvariantCulture) != 0;
				}
				else
				{
					num = flag.GetValueOrDefault();
				}
				if (!num)
				{
					goto IL_0052;
				}
				int result = ((!lockExempt) ? 1 : 0);
				goto IL_0053;
				IL_0053:
				return (byte)result != 0;
				IL_0052:
				result = 0;
				goto IL_0053;
			}
			set
			{
				forceConfigLocking = value;
			}
		}

		public bool IsAdmin => lockExempt || isSourceOfTruth;

		public bool IsSourceOfTruth
		{
			get
			{
				return isSourceOfTruth;
			}
			private set
			{
				if (value != isSourceOfTruth)
				{
					isSourceOfTruth = value;
					this.SourceOfTruthChanged?.Invoke(value);
				}
			}
		}

		public bool InitialSyncDone { get; private set; } = false;


		public event Action<bool>? SourceOfTruthChanged;

		private event Action? lockedConfigChanged;

		static ConfigSync()
		{
			ProcessingServerUpdate = false;
			configSyncs = new HashSet<ConfigSync>();
			lockExempt = false;
			packageCounter = 0L;
			RuntimeHelpers.RunClassConstructor(typeof(VersionCheck).TypeHandle);
		}

		public ConfigSync(string name)
		{
			Name = name;
			configSyncs.Add(this);
			new VersionCheck(this);
		}

		public SyncedConfigEntry<T> AddConfigEntry<T>(ConfigEntry<T> configEntry)
		{
			ConfigEntry<T> configEntry2 = configEntry;
			OwnConfigEntryBase ownConfigEntryBase = configData((ConfigEntryBase)(object)configEntry2);
			SyncedConfigEntry<T> syncedEntry = ownConfigEntryBase as SyncedConfigEntry<T>;
			if (syncedEntry == null)
			{
				syncedEntry = new SyncedConfigEntry<T>(configEntry2);
				AccessTools.DeclaredField(typeof(ConfigDescription), "<Tags>k__BackingField").SetValue(((ConfigEntryBase)configEntry2).Description, new object[1]
				{
					new ConfigurationManagerAttributes()
				}.Concat(((ConfigEntryBase)configEntry2).Description.Tags ?? Array.Empty<object>()).Concat(new SyncedConfigEntry<T>[1] { syncedEntry }).ToArray());
				configEntry2.SettingChanged += delegate
				{
					if (!ProcessingServerUpdate && syncedEntry.SynchronizedConfig)
					{
						Broadcast(ZRoutedRpc.Everybody, (ConfigEntryBase)configEntry2);
					}
				};
				allConfigs.Add(syncedEntry);
			}
			return syncedEntry;
		}

		public SyncedConfigEntry<T> AddLockingConfigEntry<T>(ConfigEntry<T> lockingConfig) where T : IConvertible
		{
			if (lockedConfig != null)
			{
				throw new Exception("Cannot initialize locking ConfigEntry twice");
			}
			lockedConfig = AddConfigEntry<T>(lockingConfig);
			lockingConfig.SettingChanged += delegate
			{
				this.lockedConfigChanged?.Invoke();
			};
			return (SyncedConfigEntry<T>)lockedConfig;
		}

		internal void AddCustomValue(CustomSyncedValueBase customValue)
		{
			CustomSyncedValueBase customValue2 = customValue;
			if (allCustomValues.Select((CustomSyncedValueBase v) => v.Identifier).Concat(new string[1] { "serverversion" }).Contains(customValue2.Identifier))
			{
				throw new Exception("Cannot have multiple settings with the same name or with a reserved name (serverversion)");
			}
			allCustomValues.Add(customValue2);
			allCustomValues = new HashSet<CustomSyncedValueBase>(allCustomValues.OrderByDescending((CustomSyncedValueBase v) => v.Priority));
			customValue2.ValueChanged += delegate
			{
				if (!ProcessingServerUpdate)
				{
					Broadcast(ZRoutedRpc.Everybody, customValue2);
				}
			};
		}

		private void RPC_FromServerConfigSync(ZRpc rpc, ZPackage package)
		{
			lockedConfigChanged += serverLockedSettingChanged;
			IsSourceOfTruth = false;
			if (HandleConfigSyncRPC(0L, package, clientUpdate: false))
			{
				InitialSyncDone = true;
			}
		}

		private void RPC_FromOtherClientConfigSync(long sender, ZPackage package)
		{
			HandleConfigSyncRPC(sender, package, clientUpdate: true);
		}

		private bool HandleConfigSyncRPC(long sender, ZPackage package, bool clientUpdate)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Expected O, but got Unknown
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Expected O, but got Unknown
			try
			{
				if (isServer && IsLocked)
				{
					ZRpc? currentRpc = SnatchCurrentlyHandlingRPC.currentRpc;
					object obj;
					if (currentRpc == null)
					{
						obj = null;
					}
					else
					{
						ISocket socket = currentRpc.GetSocket();
						obj = ((socket != null) ? socket.GetHostName() : null);
					}
					string text = (string)obj;
					if (text != null)
					{
						MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null);
						SyncedList val = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance);
						if (!(((object)methodInfo == null) ? val.Contains(text) : ((bool)methodInfo.Invoke(ZNet.instance, new object[2] { val, text }))))
						{
							return false;
						}
					}
				}
				cacheExpirations.RemoveAll(delegate(KeyValuePair<long, string> kv)
				{
					if (kv.Key < DateTimeOffset.Now.Ticks)
					{
						configValueCache.Remove(kv.Value);
						return true;
					}
					return false;
				});
				byte b = package.ReadByte();
				if ((b & 2u) != 0)
				{
					long num = package.ReadLong();
					string text2 = sender.ToString() + num;
					if (!configValueCache.TryGetValue(text2, out SortedDictionary<int, byte[]> value))
					{
						value = new SortedDictionary<int, byte[]>();
						configValueCache[text2] = value;
						cacheExpirations.Add(new KeyValuePair<long, string>(DateTimeOffset.Now.AddSeconds(60.0).Ticks, text2));
					}
					int key = package.ReadInt();
					int num2 = package.ReadInt();
					value.Add(key, package.ReadByteArray());
					if (value.Count < num2)
					{
						return false;
					}
					configValueCache.Remove(text2);
					package = new ZPackage(value.Values.SelectMany((byte[] a) => a).ToArray());
					b = package.ReadByte();
				}
				ProcessingServerUpdate = true;
				if ((b & 4u) != 0)
				{
					byte[] buffer = package.ReadByteArray();
					MemoryStream stream = new MemoryStream(buffer);
					MemoryStream memoryStream = new MemoryStream();
					using (DeflateStream deflateStream = new DeflateStream(stream, CompressionMode.Decompress))
					{
						deflateStream.CopyTo(memoryStream);
					}
					package = new ZPackage(memoryStream.ToArray());
					b = package.ReadByte();
				}
				if ((b & 1) == 0)
				{
					resetConfigsFromServer();
				}
				ParsedConfigs parsedConfigs = ReadConfigsFromPackage(package);
				foreach (KeyValuePair<OwnConfigEntryBase, object> configValue in parsedConfigs.configValues)
				{
					if (!isServer && configValue.Key.LocalBaseValue == null)
					{
						configValue.Key.LocalBaseValue = configValue.Key.BaseConfig.BoxedValue;
					}
					configValue.Key.BaseConfig.BoxedValue = configValue.Value;
				}
				foreach (KeyValuePair<CustomSyncedValueBase, object> customValue in parsedConfigs.customValues)
				{
					if (!isServer)
					{
						CustomSyncedValueBase key2 = customValue.Key;
						if (key2.LocalBaseValue == null)
						{
							key2.LocalBaseValue = customValue.Key.BoxedValue;
						}
					}
					customValue.Key.BoxedValue = customValue.Value;
				}
				Debug.Log((object)string.Format("Received {0} configs and {1} custom values from {2} for mod {3}", parsedConfigs