Decompiled source of PerspexModpack v1.1.64

BepInEx/plugins/Hearthstone.dll

Decompiled 9 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Valheim HearthStone Mod")]
[assembly: AssemblyDescription("Adds a ConsumableItem that will bring you home")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HearthStone")]
[assembly: AssemblyCopyright("Copyright ©  2022")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("97d58a4d-8886-44f9-ba81-73da0e389949")]
[assembly: AssemblyFileVersion("1.0.5.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.5.0")]
[module: UnverifiableCode]
namespace Hearthstone;

[BepInPlugin("twentyoneZ.mods.Hearthstone_Revolution", "Hearthstone Revolution by TwentyOneZ", "1.0.4")]
[BepInDependency("com.jotunn.jotunn", "2.9.0")]
public class Hearthstone : BaseUnityPlugin
{
	public const string sharedName = "Hearthstone";

	public const string PluginGUID = "twentyoneZ.mods.Hearthstone_Revolution";

	private Harmony harmony = new Harmony("twentyoneZ.mods.Hearthstone_Revolution");

	public static ConfigEntry<string> item1;

	public static ConfigEntry<string> item2;

	public static ConfigEntry<string> item3;

	public static ConfigEntry<int> itemCost1;

	public static ConfigEntry<int> itemCost2;

	public static ConfigEntry<int> itemCost3;

	public static ConfigEntry<bool> allowTeleportWithoutRestriction;

	public static ConfigEntry<bool> allowTeleportWhileTargeted;

	public static ConfigEntry<bool> allowTeleportWhileEncumbered;

	public static ConfigEntry<bool> allowTeleportWhileInWater;

	public static ConfigEntry<bool> needsToBeResting;

	public static ConfigEntry<bool> writeDebugOutput;

	private static CustomItem m_hearthStoneItem;

	private static string m_lastPositionString;

	public static bool IsOwner { get; set; }

	private static string PositionFile
	{
		get
		{
			string customItemDataFolder = Paths.CustomItemDataFolder;
			if (!Directory.Exists(customItemDataFolder))
			{
				Directory.CreateDirectory(customItemDataFolder);
			}
			string text = Path.Combine(customItemDataFolder, "HSPosition.txt");
			Debug("using Position File: " + text);
			return text;
		}
	}

	public static void Debug(string value)
	{
		if (writeDebugOutput.Value)
		{
			Logger.LogMessage((object)value);
		}
	}

	private void Awake()
	{
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Expected O, but got Unknown
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Expected O, but got Unknown
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Expected O, but got Unknown
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Expected O, but got Unknown
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Expected O, but got Unknown
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Expected O, but got Unknown
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Expected O, but got Unknown
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Expected O, but got Unknown
		//IL_013b: 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
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Expected O, but got Unknown
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Expected O, but got Unknown
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Expected O, but got Unknown
		//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Expected O, but got Unknown
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Expected O, but got Unknown
		//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: Expected O, but got Unknown
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0203: Expected O, but got Unknown
		//IL_0227: Unknown result type (might be due to invalid IL or missing references)
		//IL_022c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0234: Expected O, but got Unknown
		//IL_0234: Unknown result type (might be due to invalid IL or missing references)
		//IL_023e: Expected O, but got Unknown
		//IL_0262: Unknown result type (might be due to invalid IL or missing references)
		//IL_0267: Unknown result type (might be due to invalid IL or missing references)
		//IL_026f: Expected O, but got Unknown
		//IL_026f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0279: Expected O, but got Unknown
		//IL_029d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02aa: Expected O, but got Unknown
		//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b4: Expected O, but got Unknown
		//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e5: Expected O, but got Unknown
		//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ef: Expected O, but got Unknown
		((BaseUnityPlugin)this).Config.SaveOnConfigSet = true;
		((BaseUnityPlugin)this).Config.SettingChanged += delegate
		{
			GenerateRecipe();
		};
		item1 = ((BaseUnityPlugin)this).Config.Bind<string>("General", "RecipeItem1", "Stone", new ConfigDescription("Recipe item 1 - leave blank for none", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		} }));
		itemCost1 = ((BaseUnityPlugin)this).Config.Bind<int>("General", "itemCost1", 2, new ConfigDescription("Amount of item 1 required to craft the Hearthstone", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		} }));
		item2 = ((BaseUnityPlugin)this).Config.Bind<string>("General", "RecipeItem2", "Coins", new ConfigDescription("Recipe item 2 - leave blank for none", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		} }));
		itemCost2 = ((BaseUnityPlugin)this).Config.Bind<int>("General", "itemCost2", 10, new ConfigDescription("Amount of item 2 required to craft the Hearthstone", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		} }));
		item3 = ((BaseUnityPlugin)this).Config.Bind<string>("General", "RecipeItem3", "Carrot", new ConfigDescription("Recipe item 3 - leave blank for none", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		} }));
		itemCost3 = ((BaseUnityPlugin)this).Config.Bind<int>("General", "itemCost3", 5, new ConfigDescription("Amount of item 3 required to craft the Hearthstone", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		} }));
		writeDebugOutput = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "writeDebugOutput", true, new ConfigDescription("Write debug output?", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		} }));
		allowTeleportWithoutRestriction = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "allowTeleportWithoutRestriction", false, new ConfigDescription("Allow teleport without restriction", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		} }));
		allowTeleportWhileTargeted = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "allowTeleportWhileTargeted", true, new ConfigDescription("Allow teleport while targeted", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		} }));
		allowTeleportWhileEncumbered = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "allowTeleportWhileEncumbered", false, new ConfigDescription("Allow teleport while encumbered", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		} }));
		allowTeleportWhileInWater = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "allowTeleportWhileInWater", false, new ConfigDescription("Allow teleport while in water", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		} }));
		needsToBeResting = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "needsToBeResting", true, new ConfigDescription("Require to be resting to teleport (make a safe campfire and sit around)", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		} }));
		harmony.PatchAll();
		GetHearthStonePositionString();
		PrefabManager.OnVanillaPrefabsAvailable += AddOrUpdateHearthStoneItem;
		ItemManager.OnItemsRegistered += ItemManager_OnItemsRegistered;
		SynchronizationManager.OnConfigurationSynchronized += SynchronizationManager_OnConfigurationSynchronized;
		SynchronizationManager.OnAdminStatusChanged += SynchronizationManager_OnAdminStatusChanged;
	}

	private void SynchronizationManager_OnAdminStatusChanged()
	{
		Debug(SynchronizationManager.Instance.PlayerIsAdmin ? "No Admin anymore" : "You are admin");
	}

	private void SynchronizationManager_OnConfigurationSynchronized(object sender, ConfigurationSynchronizationEventArgs e)
	{
		Debug(e.InitialSynchronization ? "Recieved Initial Config" : "Updated Config");
		GenerateRecipe();
	}

	private void Update()
	{
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			return;
		}
		GameObject hoverObject = ((Humanoid)localPlayer).GetHoverObject();
		if (!((Object)(object)hoverObject == (Object)null))
		{
			Interactable componentInParent = hoverObject.GetComponentInParent<Interactable>();
			if (IsOwner && componentInParent is Bed && Input.GetKeyDown((KeyCode)112))
			{
				SetHearthStonePosition();
				((Character)Player.m_localPlayer).Message((MessageType)2, "You have updated your HearthStone location", 0, (Sprite)null);
			}
		}
	}

	private void ItemManager_OnItemsRegistered()
	{
		ItemManager.OnItemsRegistered -= ItemManager_OnItemsRegistered;
		GenerateRecipe();
	}

	private void GenerateRecipe()
	{
		//IL_0047: 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)
		//IL_0054: Expected O, but got Unknown
		List<Requirement> rqs;
		if (m_hearthStoneItem != null && ObjectDB.instance.m_items.Any())
		{
			if (m_hearthStoneItem.Recipe == null)
			{
				Recipe obj = ScriptableObject.CreateInstance<Recipe>();
				((Object)obj).name = "Recipe_Hearthstone";
				obj.m_item = m_hearthStoneItem.ItemDrop;
				CustomRecipe recipe = new CustomRecipe(obj, true, true)
				{
					FixRequirementReferences = true
				};
				m_hearthStoneItem.Recipe = recipe;
			}
			rqs = new List<Requirement>();
			AddRq(item1, itemCost1);
			AddRq(item2, itemCost2);
			AddRq(item3, itemCost3);
			if (m_hearthStoneItem.Recipe != null && (Object)(object)m_hearthStoneItem.Recipe.Recipe != (Object)null)
			{
				m_hearthStoneItem.Recipe.Recipe.m_resources = rqs.ToArray();
			}
		}
		void AddRq(ConfigEntry<string> item, ConfigEntry<int> amount)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			try
			{
				if (item != null && !string.IsNullOrEmpty(item.Value) && amount.Value > 0)
				{
					ItemDrop component = ObjectDB.instance.GetItemPrefab(item.Value).GetComponent<ItemDrop>();
					if ((Object)(object)component != (Object)null)
					{
						rqs.Add(new Requirement
						{
							m_amount = amount.Value,
							m_resItem = component
						});
					}
				}
			}
			catch (Exception ex)
			{
				Debug(ex.Message);
			}
		}
	}

	private void AddOrUpdateHearthStoneItem()
	{
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: 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_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Expected O, but got Unknown
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Expected O, but got Unknown
		if (m_hearthStoneItem != null)
		{
			return;
		}
		AssetBundle val = AssetUtils.LoadAssetBundleFromResources("hs", typeof(Hearthstone).Assembly);
		if ((Object)(object)val == (Object)null)
		{
			Logger.LogWarning((object)"Bundle could not be loaded!");
			return;
		}
		GameObject val2 = val.LoadAsset<GameObject>("Assets/_Custom/Hearthstone.prefab");
		if ((Object)(object)val2 == (Object)null)
		{
			Logger.LogWarning((object)"Prefab could not be loaded!");
			return;
		}
		SharedData shared = val2.GetComponent<ItemDrop>().m_itemData.m_shared;
		if (shared == null)
		{
			Logger.LogWarning((object)"Shared ItemData could not be loaded!");
			return;
		}
		ItemConfig val3 = new ItemConfig
		{
			Name = shared.m_name,
			Requirements = BuildRequirementConfigs(),
			Icons = shared.m_icons,
			Description = shared.m_description
		};
		m_hearthStoneItem = new CustomItem(val, "Assets/_Custom/Hearthstone.prefab", true, val3);
		ItemManager.Instance.AddItem(m_hearthStoneItem);
		GenerateRecipe();
	}

	private static RequirementConfig[] BuildRequirementConfigs()
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Expected O, but got Unknown
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Expected O, but got Unknown
		//IL_00b7: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Expected O, but got Unknown
		List<RequirementConfig> list = new List<RequirementConfig>();
		if (itemCost1.Value > 0 && !string.IsNullOrEmpty(item1.Value))
		{
			list.Add(new RequirementConfig
			{
				Amount = itemCost1.Value,
				Item = item1.Value
			});
		}
		if (itemCost2.Value > 0 && !string.IsNullOrEmpty(item2.Value))
		{
			list.Add(new RequirementConfig
			{
				Amount = itemCost2.Value,
				Item = item2.Value
			});
		}
		if (itemCost3.Value > 0 && !string.IsNullOrEmpty(item3.Value))
		{
			list.Add(new RequirementConfig
			{
				Amount = itemCost3.Value,
				Item = item3.Value
			});
		}
		return list.ToArray();
	}

	public static Vector3 GetHearthStonePosition()
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: 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)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		CultureInfo provider = new CultureInfo("en-US");
		Vector3 zero = Vector3.zero;
		string hearthStonePositionString = GetHearthStonePositionString();
		if (string.IsNullOrEmpty(hearthStonePositionString))
		{
			return zero;
		}
		string[] array = hearthStonePositionString.Split(new char[1] { '|' });
		try
		{
			return new Vector3(float.Parse(array[0], provider), float.Parse(array[1], provider), float.Parse(array[2], provider));
		}
		catch
		{
			return Vector3.zero;
		}
	}

	private static string GetHearthStonePositionString()
	{
		if (string.IsNullOrEmpty(m_lastPositionString) && File.Exists(PositionFile))
		{
			m_lastPositionString = File.ReadAllText(PositionFile);
		}
		return m_lastPositionString;
	}

	private static void SetHearthStonePosition()
	{
		//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)
		//IL_0045: 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_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		CultureInfo cultureInfo = new CultureInfo("en-US");
		string text = ((Component)Player.m_localPlayer).transform.position.x.ToString(cultureInfo) + "|" + ((Component)Player.m_localPlayer).transform.position.y.ToString(cultureInfo) + "|" + ((Component)Player.m_localPlayer).transform.position.z.ToString(cultureInfo);
		File.WriteAllText(PositionFile, text);
		m_lastPositionString = text;
	}
}
internal class Patches
{
	[HarmonyPatch(typeof(Player), "ConsumeItem")]
	public static class ConsumePatch
	{
		private static bool Prefix(ItemData item)
		{
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: 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_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_03de: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0404: Unknown result type (might be due to invalid IL or missing references)
			//IL_0410: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0431: Unknown result type (might be due to invalid IL or missing references)
			//IL_0433: Unknown result type (might be due to invalid IL or missing references)
			//IL_0438: Unknown result type (might be due to invalid IL or missing references)
			//IL_043d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0444: Unknown result type (might be due to invalid IL or missing references)
			//IL_0450: Unknown result type (might be due to invalid IL or missing references)
			string name = item.m_shared.m_name;
			if (string.IsNullOrEmpty(name))
			{
				return false;
			}
			if (name == "Hearthstone")
			{
				if (!((Humanoid)Player.m_localPlayer).IsTeleportable() && !Hearthstone.allowTeleportWithoutRestriction.Value)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "You can't teleport carrying those items", 0, (Sprite)null);
					return false;
				}
				if (Player.m_localPlayer.IsTargeted() && !Hearthstone.allowTeleportWhileTargeted.Value)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "You can't teleport while spotted by anyone", 0, (Sprite)null);
					return false;
				}
				if (((Character)Player.m_localPlayer).IsEncumbered() && !Hearthstone.allowTeleportWhileEncumbered.Value)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "You can't teleport while encumbered", 0, (Sprite)null);
					return false;
				}
				if (((Character)Player.m_localPlayer).InWater() && !Hearthstone.allowTeleportWhileInWater.Value)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "You can't teleport while in water", 0, (Sprite)null);
					return false;
				}
				if (!((Character)Player.m_localPlayer).GetSEMan().HaveStatusEffect("Resting") && Hearthstone.needsToBeResting.Value)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "You have to be resting to teleport", 0, (Sprite)null);
					return false;
				}
				Vector3 hearthStonePosition = Hearthstone.GetHearthStonePosition();
				if (hearthStonePosition == Vector3.zero)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "You need to set hearthstone spawn point", 0, (Sprite)null);
					return false;
				}
				((Character)Player.m_localPlayer).TeleportTo(hearthStonePosition, ((Component)Player.m_localPlayer).transform.rotation, true);
			}
			if (name == "Marketstone")
			{
				if (!((Humanoid)Player.m_localPlayer).IsTeleportable() && !Hearthstone.allowTeleportWithoutRestriction.Value)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "You can't teleport carrying those items", 0, (Sprite)null);
					return false;
				}
				if (Player.m_localPlayer.IsTargeted() && !Hearthstone.allowTeleportWhileTargeted.Value)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "You can't teleport while spotted by anyone", 0, (Sprite)null);
					return false;
				}
				if (((Character)Player.m_localPlayer).IsEncumbered() && !Hearthstone.allowTeleportWhileEncumbered.Value)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "You can't teleport while encumbered", 0, (Sprite)null);
					return false;
				}
				if (((Character)Player.m_localPlayer).InWater() && !Hearthstone.allowTeleportWhileInWater.Value)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "You can't teleport while in water", 0, (Sprite)null);
					return false;
				}
				if (!((Character)Player.m_localPlayer).GetSEMan().HaveStatusEffect("Resting") && Hearthstone.needsToBeResting.Value)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "You have to be resting to teleport", 0, (Sprite)null);
					return false;
				}
				LocationInstance val = default(LocationInstance);
				if (ZoneSystem.instance.FindClosestLocation("Vendor_BlackForest", Vector3.zero, ref val))
				{
					Vector3 val2 = val.m_position + Vector3.up;
					((Character)Player.m_localPlayer).TeleportTo(val2, ((Component)Player.m_localPlayer).transform.rotation, true);
				}
				else
				{
					Vector3 val3 = default(Vector3);
					if (!ZoneSystem.instance.GetLocationIcon("Vendor_BlackForest", ref val3))
					{
						((Character)Player.m_localPlayer).Message((MessageType)2, "I have to find the market first.", 0, (Sprite)null);
						return false;
					}
					Vector3 val2 = val3 + Vector3.up;
					((Character)Player.m_localPlayer).TeleportTo(val2, ((Component)Player.m_localPlayer).transform.rotation, true);
				}
			}
			if (name == "Deathstone")
			{
				if (!((Humanoid)Player.m_localPlayer).IsTeleportable() && !Hearthstone.allowTeleportWithoutRestriction.Value)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "You can't teleport carrying those items", 0, (Sprite)null);
					return false;
				}
				if (Player.m_localPlayer.IsTargeted() && !Hearthstone.allowTeleportWhileTargeted.Value)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "You can't teleport while spotted by anyone", 0, (Sprite)null);
					return false;
				}
				if (((Character)Player.m_localPlayer).IsEncumbered() && !Hearthstone.allowTeleportWhileEncumbered.Value)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "You can't teleport while encumbered", 0, (Sprite)null);
					return false;
				}
				if (((Character)Player.m_localPlayer).InWater() && !Hearthstone.allowTeleportWhileInWater.Value)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "You can't teleport while in water", 0, (Sprite)null);
					return false;
				}
				if (!((Character)Player.m_localPlayer).GetSEMan().HaveStatusEffect("Resting") && Hearthstone.needsToBeResting.Value)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "You have to be resting to teleport", 0, (Sprite)null);
					return false;
				}
				LocationInstance val4 = default(LocationInstance);
				if (ZoneSystem.instance.FindClosestLocation("Vendor_BlackForest", Vector3.zero, ref val4))
				{
					Vector3 val5 = val4.m_position + Vector3.up;
					((Character)Player.m_localPlayer).TeleportTo(val5, ((Component)Player.m_localPlayer).transform.rotation, true);
				}
				else
				{
					Vector3 val6 = default(Vector3);
					if (!ZoneSystem.instance.GetLocationIcon("Vendor_BlackForest", ref val6))
					{
						((Character)Player.m_localPlayer).Message((MessageType)2, "I have to find the market first.", 0, (Sprite)null);
						return false;
					}
					Vector3 val5 = val6 + Vector3.up;
					((Character)Player.m_localPlayer).TeleportTo(val5, ((Component)Player.m_localPlayer).transform.rotation, true);
				}
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Bed), "GetHoverText")]
	private static class Bed_GetHoverText_Patch
	{
		private static void Postfix(Bed __instance, ref string __result, ZNetView ___m_nview)
		{
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				Hearthstone.IsOwner = false;
			}
			else if (___m_nview.GetZDO().GetLong("owner", 0L) == Player.m_localPlayer.GetPlayerID() || __instance.IsCurrent())
			{
				Hearthstone.IsOwner = true;
				__result += "\n[<color=yellow><b>P</b></color>] Set hearthstone";
			}
			else
			{
				Hearthstone.IsOwner = false;
			}
		}
	}

	[HarmonyPatch(typeof(ItemStand), "CanAttach")]
	public static class AttachPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ItemStand __instance, ItemData item, ref bool __result)
		{
			if (!__result)
			{
				string text = item?.m_shared?.m_name;
				if (!string.IsNullOrEmpty(text))
				{
					__result = text == "Hearthstone";
				}
			}
		}
	}
}

BepInEx/plugins/RepairRequiresCoins.dll

Decompiled 9 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace RepairRequiresMats;

[BepInPlugin("aedenthorn.RepairRequiresMats", "Repair Requires Mats", "0.6.1")]
public class BepInExPlugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(UITooltip), "LateUpdate")]
	private static class UITooltip_LateUpdate_Patch
	{
		private static void Postfix(UITooltip __instance, UITooltip ___m_current, GameObject ___m_tooltip)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (modEnabled.Value && (Object)(object)___m_current == (Object)(object)__instance && (Object)(object)___m_tooltip != (Object)null && ((Object)((Component)___m_current).transform).name == "RepairButton")
			{
				___m_tooltip.transform.position = Input.mousePosition + new Vector3(-200f, -100f);
			}
		}
	}

	[HarmonyPatch(typeof(InventoryGui), "UpdateRepair")]
	private static class InventoryGui_UpdateRepair_Patch
	{
		private static void Postfix(InventoryGui __instance, ref List<ItemData> ___m_tempWornItems)
		{
			//IL_0479: Unknown result type (might be due to invalid IL or missing references)
			//IL_0480: Expected O, but got Unknown
			//IL_049c: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a3: Expected O, but got Unknown
			if (!modEnabled.Value || !___m_tempWornItems.Any())
			{
				return;
			}
			List<RepairItemData> list = new List<RepairItemData>();
			List<RepairItemData> list2 = new List<RepairItemData>();
			List<RepairItemData> list3 = new List<RepairItemData>();
			List<RepairItemData> list4 = new List<RepairItemData>();
			List<string> list5 = new List<string>();
			foreach (ItemData ___m_tempWornItem in ___m_tempWornItems)
			{
				if (!Traverse.Create((object)__instance).Method("CanRepair", new object[1] { ___m_tempWornItem }).GetValue<bool>())
				{
					list4.Add(new RepairItemData(___m_tempWornItem));
					continue;
				}
				List<Requirement> list6 = RepairReqs(___m_tempWornItem);
				if (list6 == null)
				{
					list.Add(new RepairItemData(___m_tempWornItem));
					continue;
				}
				List<string> list7 = new List<string>();
				foreach (Requirement item in list6)
				{
					if (item.m_amount != 0)
					{
						list7.Add($"{item.m_amount}/{((Humanoid)Player.m_localPlayer).GetInventory().CountItems(item.m_resItem.m_itemData.m_shared.m_name, -1, true)} {Localization.instance.Localize(item.m_resItem.m_itemData.m_shared.m_name)}");
					}
				}
				bool flag = true;
				foreach (Requirement item2 in list6)
				{
					if (Object.op_Implicit((Object)(object)item2.m_resItem))
					{
						int amount = item2.m_amount;
						if (((Humanoid)Player.m_localPlayer).GetInventory().CountItems(item2.m_resItem.m_itemData.m_shared.m_name, -1, true) < amount)
						{
							flag = false;
							break;
						}
					}
				}
				if (!flag)
				{
					list3.Add(new RepairItemData(___m_tempWornItem, list7));
				}
				else
				{
					list2.Add(new RepairItemData(___m_tempWornItem, list7));
				}
			}
			orderedWornItems = new List<ItemData>();
			foreach (RepairItemData item3 in list)
			{
				list5.Add("<color=#" + hasEnoughTooltipColor.Value + ">" + Localization.instance.Localize(item3.item.m_shared.m_name) + ": Free</color>");
				orderedWornItems.Add(item3.item);
			}
			foreach (RepairItemData item4 in list2)
			{
				list5.Add("<color=#" + hasEnoughTooltipColor.Value + ">" + Localization.instance.Localize(item4.item.m_shared.m_name) + ": " + string.Join(", ", item4.reqstring) + "</color>");
				orderedWornItems.Add(item4.item);
			}
			foreach (RepairItemData item5 in list3)
			{
				list5.Add("<color=#" + notEnoughTooltipColor.Value + ">" + Localization.instance.Localize(item5.item.m_shared.m_name) + ": " + string.Join(", ", item5.reqstring) + "</color>");
				orderedWornItems.Add(item5.item);
			}
			foreach (RepairItemData item6 in list4)
			{
				orderedWornItems.Add(item6.item);
			}
			___m_tempWornItems = new List<ItemData>(orderedWornItems);
			if (showAllRepairsInToolTip.Value)
			{
				UITooltip val = (UITooltip)typeof(UITooltip).GetField("m_current", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
				GameObject val2 = (GameObject)typeof(UITooltip).GetField("m_tooltip", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
				if (!((Object)(object)val2 == (Object)null) && !(((Object)((Component)val).transform).name != "RepairButton"))
				{
					((Component)Utils.FindChild(val2.transform, "Text", (IterativeSearchType)0)).GetComponent<TMP_Text>().richText = true;
					((Component)Utils.FindChild(val2.transform, "Text", (IterativeSearchType)0)).GetComponent<TMP_Text>().alignment = (TextAlignmentOptions)1026;
					((Component)Utils.FindChild(val2.transform, "Text", (IterativeSearchType)0)).GetComponent<TMP_Text>().text = "<b><color=#" + titleTooltipColor.Value + ">" + Localization.instance.Localize("$inventory_repairbutton") + "</color></b>\r\n" + string.Join("\r\n", list5);
				}
			}
		}
	}

	[HarmonyPatch(typeof(InventoryGui), "CanRepair")]
	private static class InventoryGui_CanRepair_Patch
	{
		private static void Postfix(ItemData item, ref bool __result)
		{
			if (!modEnabled.Value || !modEnabled.Value || !Environment.StackTrace.Contains("RepairOneItem") || Environment.StackTrace.Contains("HaveRepairableItems") || !__result || item?.m_shared == null || !((Object)(object)Player.m_localPlayer != (Object)null) || orderedWornItems.Count <= 0)
			{
				return;
			}
			if (orderedWornItems[0] != item)
			{
				__result = false;
				return;
			}
			List<Requirement> list = RepairReqs(item, log: true);
			if (list == null)
			{
				return;
			}
			List<string> list2 = new List<string>();
			foreach (Requirement item2 in list)
			{
				if (item2?.m_resItem?.m_itemData?.m_shared != null)
				{
					list2.Add($"{item2.m_amount}/{((Humanoid)Player.m_localPlayer).GetInventory().CountItems(item2.m_resItem.m_itemData.m_shared.m_name, -1, true)} {Localization.instance.Localize(item2.m_resItem.m_itemData.m_shared.m_name)}");
				}
			}
			bool flag = true;
			foreach (Requirement item3 in list)
			{
				if (Object.op_Implicit((Object)(object)item3.m_resItem))
				{
					int amount = item3.m_amount;
					if (((Humanoid)Player.m_localPlayer).GetInventory().CountItems(item3.m_resItem.m_itemData.m_shared.m_name, -1, true) < amount)
					{
						flag = false;
						break;
					}
				}
			}
			string text;
			if (flag)
			{
				Player.m_localPlayer.ConsumeResources(list.ToArray(), 1, -1);
				text = "Used " + string.Join(", ", list2) + " to repair " + Localization.instance.Localize(item.m_shared.m_name);
				__result = true;
			}
			else
			{
				text = "Require " + string.Join(", ", list2) + " to repair " + item.m_shared.m_name;
				__result = false;
			}
			((Character)Player.m_localPlayer).Message((MessageType)1, text, 0, (Sprite)null);
			Dbgl(text);
		}
	}

	[HarmonyPatch(typeof(Terminal), "InputText")]
	private static class InputText_Patch
	{
		private static bool Prefix(Terminal __instance)
		{
			if (!modEnabled.Value)
			{
				return true;
			}
			string text = ((TMP_InputField)__instance.m_input).text;
			if (text.ToLower().Equals("repairmod reset"))
			{
				((BaseUnityPlugin)context).Config.Reload();
				((BaseUnityPlugin)context).Config.Save();
				Traverse.Create((object)__instance).Method("AddString", new object[1] { text }).GetValue();
				Traverse.Create((object)__instance).Method("AddString", new object[1] { "Repair Items config reloaded" }).GetValue();
				return false;
			}
			return true;
		}
	}

	private static bool isDebug = true;

	public static ConfigEntry<bool> modEnabled;

	public static ConfigEntry<bool> showAllRepairsInToolTip;

	public static ConfigEntry<float> materialRequirementMult;

	public static ConfigEntry<string> titleTooltipColor;

	public static ConfigEntry<string> hasEnoughTooltipColor;

	public static ConfigEntry<string> notEnoughTooltipColor;

	public static ConfigEntry<int> nexusID;

	private static List<ItemData> orderedWornItems = new List<ItemData>();

	private static BepInExPlugin context;

	private static Assembly epicLootAssembly;

	private static MethodInfo epicLootIsMagic;

	private static MethodInfo epicLootGetRarity;

	private static MethodInfo epicLootGetEnchantCosts;

	public static void Dbgl(string str = "", bool pref = true)
	{
		if (isDebug)
		{
			Debug.Log((object)((pref ? (typeof(BepInExPlugin).Namespace + " ") : "") + str));
		}
	}

	private void Awake()
	{
		context = this;
		modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable this mod");
		nexusID = ((BaseUnityPlugin)this).Config.Bind<int>("General", "NexusID", 215, "Nexus mod ID for updates");
		showAllRepairsInToolTip = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowAllRepairsInToolTip", true, "Show all repairs in tooltip when hovering over repair button.");
		titleTooltipColor = ((BaseUnityPlugin)this).Config.Bind<string>("General", "TitleTooltipColor", "FFFFFFFF", "Color to use in tooltip title.");
		hasEnoughTooltipColor = ((BaseUnityPlugin)this).Config.Bind<string>("General", "HasEnoughTooltipColor", "FFFFFFFF", "Color to use in tooltip for items with enough resources to repair.");
		notEnoughTooltipColor = ((BaseUnityPlugin)this).Config.Bind<string>("General", "NotEnoughTooltipColor", "FF0000FF", "Color to use in tooltip for items with enough resources to repair.");
		materialRequirementMult = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MaterialRequirementMult", 0.5f, "Multiplier for amount of each material required.");
		Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
	}

	private void Start()
	{
		if (Chainloader.PluginInfos.ContainsKey("randyknapp.mods.epicloot"))
		{
			epicLootAssembly = ((object)Chainloader.PluginInfos["randyknapp.mods.epicloot"].Instance).GetType().Assembly;
			epicLootIsMagic = epicLootAssembly.GetType("EpicLoot.ItemDataExtensions").GetMethod("IsMagic", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(ItemData) }, null);
			epicLootGetRarity = epicLootAssembly.GetType("EpicLoot.ItemDataExtensions").GetMethod("GetRarity", BindingFlags.Static | BindingFlags.Public);
			epicLootGetEnchantCosts = epicLootAssembly.GetType("EpicLoot.Crafting.EnchantTabController").GetMethod("GetEnchantCosts", BindingFlags.Static | BindingFlags.Public);
			Dbgl($"Loaded Epic Loot assembly; epicLootIsMagic {epicLootIsMagic != null}, epicLootGetRarity {epicLootGetRarity != null}, epicLootGetEnchantCosts {epicLootGetEnchantCosts != null}");
		}
	}

	private static List<Requirement> RepairReqs(ItemData item, bool log = false)
	{
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: Expected O, but got Unknown
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Expected O, but got Unknown
		float num = (item.GetMaxDurability() - item.m_durability) / item.GetMaxDurability();
		Recipe recipe = ObjectDB.instance.GetRecipe(item);
		if (recipe == null)
		{
			return null;
		}
		List<Requirement> list = new List<Requirement>(recipe.m_resources);
		bool flag = false;
		if (epicLootAssembly != null)
		{
			try
			{
				MethodInfo methodInfo = epicLootIsMagic;
				object[] parameters = (object[])(object)new ItemData[1] { item };
				flag = (bool)methodInfo.Invoke(null, parameters);
			}
			catch
			{
			}
		}
		if (flag)
		{
			try
			{
				MethodInfo methodInfo2 = epicLootGetRarity;
				object[] parameters = (object[])(object)new ItemData[1] { item };
				int num2 = (int)methodInfo2.Invoke(null, parameters);
				foreach (KeyValuePair<ItemDrop, int> item2 in (List<KeyValuePair<ItemDrop, int>>)epicLootGetEnchantCosts.Invoke(null, new object[2] { item, num2 }))
				{
					list.Add(new Requirement
					{
						m_amount = item2.Value,
						m_resItem = item2.Key
					});
				}
			}
			catch
			{
			}
		}
		List<Requirement> list2 = new List<Requirement>();
		for (int i = 0; i < list.Count; i++)
		{
			Requirement val = new Requirement
			{
				m_resItem = list[i].m_resItem,
				m_amount = list[i].m_amount,
				m_amountPerLevel = list[i].m_amountPerLevel,
				m_recover = list[i].m_recover
			};
			int num3 = 0;
			for (int num4 = item.m_quality; num4 > 0; num4--)
			{
				if (val.m_resItem.m_itemData.m_shared.m_name.ToLower().Contains("item_coins"))
				{
					num3 += val.GetAmount(num4);
				}
			}
			int num5 = Mathf.RoundToInt((float)num3 * num * materialRequirementMult.Value);
			if (num5 > 0)
			{
				val.m_amount = num5;
				list2.Add(val);
			}
		}
		if (!list2.Any())
		{
			return null;
		}
		return list2;
	}
}
internal class RepairItemData : ItemData
{
	public List<string> reqstring;

	public ItemData item;

	public RepairItemData(ItemData item, List<string> reqstring = null)
	{
		this.reqstring = reqstring;
		this.item = item;
	}
}

BepInEx/plugins/VLDamageFix.dll

Decompiled 9 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using EpicMMOSystem;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ValheimLegends")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ValheimLegends")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("f0baf009-4135-4368-9987-850698809493")]
[assembly: AssemblyFileVersion("0.4.9.3")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.4.9.3")]
[module: UnverifiableCode]
namespace ValheimLegends;

public class AnimationClipOverrides : List<KeyValuePair<AnimationClip, AnimationClip>>
{
	public AnimationClip this[string name]
	{
		get
		{
			return Find((KeyValuePair<AnimationClip, AnimationClip> x) => ((Object)x.Key).name == name).Value;
		}
		set
		{
			int num = FindIndex((KeyValuePair<AnimationClip, AnimationClip> x) => ((Object)x.Key).name == name);
			if (num != -1)
			{
				base[num] = new KeyValuePair<AnimationClip, AnimationClip>(base[num].Key, value);
			}
		}
	}

	public AnimationClipOverrides(int capacity)
		: base(capacity)
	{
	}
}
public class Class_Berserker
{
	private static int Script_Layermask = LayerMask.GetMask(new string[7] { "Default", "static_solid", "Default_small", "piece_nonsolid", "vehicle", "viewblock", "piece" });

	private static int Player_Layermask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece_nonsolid", "terrain", "vehicle" });

	private static GameObject GO_CastFX;

	public static void Execute_Dash(Player player, ref float altitude, ref Rigidbody playerBody)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: 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_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_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_0170: 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)
		//IL_019f: Unknown result type (might be due to invalid IL or missing references)
		//IL_054a: Unknown result type (might be due to invalid IL or missing references)
		//IL_055e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0560: Unknown result type (might be due to invalid IL or missing references)
		//IL_051f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0526: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0205: Unknown result type (might be due to invalid IL or missing references)
		//IL_0282: Unknown result type (might be due to invalid IL or missing references)
		//IL_028d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0292: Unknown result type (might be due to invalid IL or missing references)
		//IL_0299: Unknown result type (might be due to invalid IL or missing references)
		//IL_029e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_053c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0235: Unknown result type (might be due to invalid IL or missing references)
		//IL_023c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0215: Unknown result type (might be due to invalid IL or missing references)
		//IL_0229: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0265: Unknown result type (might be due to invalid IL or missing references)
		//IL_026a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0358: Unknown result type (might be due to invalid IL or missing references)
		//IL_035a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0367: Unknown result type (might be due to invalid IL or missing references)
		//IL_036e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0375: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0300: Unknown result type (might be due to invalid IL or missing references)
		//IL_0307: Unknown result type (might be due to invalid IL or missing references)
		//IL_030c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0319: Unknown result type (might be due to invalid IL or missing references)
		//IL_031a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0321: Unknown result type (might be due to invalid IL or missing references)
		//IL_0326: Unknown result type (might be due to invalid IL or missing references)
		//IL_0337: Unknown result type (might be due to invalid IL or missing references)
		//IL_0339: Unknown result type (might be due to invalid IL or missing references)
		//IL_039b: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a2: Expected O, but got Unknown
		//IL_03aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_03af: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_040a: Unknown result type (might be due to invalid IL or missing references)
		//IL_040f: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c9: Unknown result type (might be due to invalid IL or missing references)
		Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("sfx_perfectblock"), ((Component)player).transform.position, Quaternion.identity);
		Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_stonegolem_attack_hit"), ((Component)player).transform.position, Quaternion.identity);
		float num = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.DisciplineSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddPhysicDamage() / 40f + LevelSystem.Instance.getAddAttackSpeed() / 40f, 0f, 0.5f));
		float num2 = 0.6f + num * 0.015f * VL_GlobalConfigs.g_DamageModifer * VL_GlobalConfigs.c_berserkerDash;
		if (((Character)player).GetSEMan().HaveStatusEffect("SE_VL_Berserk") || ((Character)player).GetSEMan().HaveStatusEffect("SE_VL_Execute"))
		{
			SE_Berserk sE_Berserk = (SE_Berserk)(object)((Character)player).GetSEMan().GetStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_Berserk"));
			if ((Object)(object)sE_Berserk != (Object)null)
			{
				num2 *= sE_Berserk.damageModifier;
			}
		}
		Vector3 lookDir = ((Character)player).GetLookDir();
		lookDir.y = 0f;
		((Component)player).transform.rotation = Quaternion.LookRotation(lookDir);
		Vector3 val = default(Vector3);
		Vector3 forward = ((Component)player).transform.forward;
		Vector3 position = ((Component)player).transform.position;
		Vector3 val2 = ((Component)player).transform.position;
		val2.y += 0.1f;
		List<int> list = new List<int>();
		float num3 = 1f;
		int i;
		for (i = 0; i <= 10; i++)
		{
			RaycastHit val3 = default(RaycastHit);
			bool flag = false;
			for (int j = 0; j <= 10; j++)
			{
				Vector3 val4 = Vector3.MoveTowards(((Component)player).transform.position, ((Component)player).transform.position + forward * 100f, (float)i + (float)j * 0.1f);
				val4.y = val2.y;
				if (val4.y < ZoneSystem.instance.GetGroundHeight(val4))
				{
					val2.y = ZoneSystem.instance.GetGroundHeight(val4) + 1f;
					val4.y = val2.y;
				}
				flag = Physics.SphereCast(val4, 0.05f, forward, ref val3, float.PositiveInfinity, Script_Layermask);
				if (flag && Object.op_Implicit((Object)(object)((RaycastHit)(ref val3)).collider))
				{
					val = ((RaycastHit)(ref val3)).point;
					break;
				}
			}
			position = Vector3.MoveTowards(((Component)player).transform.position, ((Component)player).transform.position + forward * 100f, (float)i);
			position.y = ((ZoneSystem.instance.GetSolidHeight(position) - ZoneSystem.instance.GetGroundHeight(position) <= 1f) ? ZoneSystem.instance.GetSolidHeight(position) : ZoneSystem.instance.GetGroundHeight(position));
			if (flag && Vector3.Distance(new Vector3(position.x, val2.y, position.z), val) <= 1f)
			{
				val2 = Vector3.MoveTowards(val, val2, 1f);
				Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_beehive_hit"), val2, Quaternion.identity);
				break;
			}
			Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_beehive_hit"), val2, Quaternion.identity);
			((Vector3)(ref val2))..ctor(position.x, val2.y, position.z);
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				HitData val5 = new HitData();
				val5.m_damage = ((Humanoid)player).GetCurrentWeapon().GetDamage();
				val5.ApplyModifier(Random.Range(0.8f, 1.2f) * num2 / num3);
				val5.m_point = allCharacter.GetCenterPoint();
				val5.m_dir = ((Component)allCharacter).transform.position - position;
				val5.m_skill = ValheimLegends.DisciplineSkill;
				float num4 = Vector3.Distance(((Component)allCharacter).transform.position, position);
				if (!BaseAI.IsEnemy(allCharacter, (Character)(object)player) || !(num4 <= 3f) || list.Contains(((Object)allCharacter).GetInstanceID()))
				{
					continue;
				}
				SE_Execute sE_Execute = (SE_Execute)(object)((Character)player).GetSEMan().GetStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_Execute"));
				if ((Object)(object)sE_Execute != (Object)null)
				{
					val5.ApplyModifier(sE_Execute.damageBonus);
					sE_Execute.hitCount--;
					if (sE_Execute.hitCount <= 0)
					{
						((Character)player).GetSEMan().RemoveStatusEffect((StatusEffect)(object)sE_Execute, false);
					}
				}
				num3 += 0.6f;
				allCharacter.Damage(val5);
				Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_crit"), allCharacter.GetCenterPoint(), Quaternion.identity);
				list.Add(((Object)allCharacter).GetInstanceID());
			}
		}
		list.Clear();
		if (i > 10 && ZoneSystem.instance.GetSolidHeight(val2) - val2.y <= 2f)
		{
			val2.y = ZoneSystem.instance.GetSolidHeight(val2);
		}
		playerBody.position = val2;
		altitude = 0f;
		((Component)player).transform.rotation = Quaternion.LookRotation(forward);
	}

	public static void Process_Input(Player player, ref float altitude)
	{
		//IL_0094: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03de: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02da: Unknown result type (might be due to invalid IL or missing references)
		//IL_050f: Unknown result type (might be due to invalid IL or missing references)
		new Random();
		if (VL_Utility.Ability3_Input_Down)
		{
			if (!((Character)player).GetSEMan().HaveStatusEffect("SE_VL_Ability3_CD"))
			{
				if (player.GetStamina() > VL_Utility.GetDashCost(player))
				{
					StatusEffect val = (StatusEffect)(object)(SE_Ability3_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability3_CD));
					val.m_ttl = VL_Utility.GetDashCooldown(player);
					((Character)player).GetSEMan().AddStatusEffect(val, false, 0, 0f);
					((Character)player).UseStamina(VL_Utility.GetDashCost(player), false);
					((ZSyncAnimation)typeof(Player).GetField("m_zanim", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(player)).SetTrigger("swing_longsword2");
					Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_Potion_stamina_medium"), ((Component)player).transform.position, Quaternion.identity);
					ValheimLegends.isChargingDash = true;
					ValheimLegends.dashCounter = 0;
					((Character)player).RaiseSkill(ValheimLegends.DisciplineSkill, VL_Utility.GetDashSkillGain(player));
				}
				else
				{
					((Character)player).Message((MessageType)1, "Not enough stamina for Dash: (" + player.GetStamina().ToString("#.#") + "/" + VL_Utility.GetDashCost(player) + ")", 0, (Sprite)null);
				}
			}
			else
			{
				((Character)player).Message((MessageType)1, "Ability not ready", 0, (Sprite)null);
			}
		}
		else if (VL_Utility.Ability2_Input_Down)
		{
			if (!((Character)player).GetSEMan().HaveStatusEffect("SE_VL_Ability2_CD"))
			{
				if (player.GetStamina() > VL_Utility.GetBerserkCost(player))
				{
					StatusEffect val2 = (StatusEffect)(object)(SE_Ability2_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability2_CD));
					val2.m_ttl = VL_Utility.GetBerserkCooldown(player);
					((Character)player).GetSEMan().AddStatusEffect(val2, false, 0, 0f);
					((Character)player).UseStamina(VL_Utility.GetBerserkCost(player), false);
					ValheimLegends.shouldUseGuardianPower = false;
					player.StartEmote("challenge", true);
					Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_GP_Stone"), ((Character)player).GetCenterPoint(), Quaternion.identity);
					float num = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.AlterationSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddCriticalChance() / 40f + LevelSystem.Instance.getAddMagicDamage() / 80f, 0f, 0.5f));
					SE_Berserk sE_Berserk = (SE_Berserk)(object)ScriptableObject.CreateInstance(typeof(SE_Berserk));
					((StatusEffect)sE_Berserk).m_ttl = SE_Berserk.m_baseTTL;
					sE_Berserk.speedModifier = 1.2f + 0.006f * num;
					sE_Berserk.damageModifier = 1.2f + 0.006f * num * VL_GlobalConfigs.g_DamageModifer * VL_GlobalConfigs.c_berserkerBerserk;
					sE_Berserk.healthAbsorbPercent = 0.2f + 0.002f * num;
					((Character)player).GetSEMan().AddStatusEffect((StatusEffect)(object)sE_Berserk, false, 0, 0f);
					((Character)player).RaiseSkill(ValheimLegends.AlterationSkill, VL_Utility.GetBerserkSkillGain(player));
				}
				else
				{
					((Character)player).Message((MessageType)1, "Not enough stamina for Berserk: (" + player.GetStamina().ToString("#.#") + "/" + VL_Utility.GetBerserkCost(player) + ")", 0, (Sprite)null);
				}
			}
			else
			{
				((Character)player).Message((MessageType)1, "Ability not ready", 0, (Sprite)null);
			}
		}
		else
		{
			if (!VL_Utility.Ability1_Input_Down)
			{
				return;
			}
			if (!((Character)player).GetSEMan().HaveStatusEffect("SE_VL_Ability1_CD"))
			{
				if (player.GetStamina() > VL_Utility.GetExecuteCost(player))
				{
					StatusEffect val3 = (StatusEffect)(object)(SE_Ability1_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability1_CD));
					val3.m_ttl = VL_Utility.GetExecuteCooldown(player);
					((Character)player).GetSEMan().AddStatusEffect(val3, false, 0, 0f);
					((Character)player).UseStamina(VL_Utility.GetExecuteCost(player), false);
					player.StartEmote("point", true);
					Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_backstab"), ((Character)player).GetCenterPoint(), Quaternion.identity);
					float num2 = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.DisciplineSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddPhysicDamage() / 40f + LevelSystem.Instance.getAddAttackSpeed() / 40f, 0f, 0.5f));
					SE_Execute sE_Execute = (SE_Execute)(object)ScriptableObject.CreateInstance(typeof(SE_Execute));
					sE_Execute.hitCount = Mathf.RoundToInt(3f + 0.04f * num2);
					sE_Execute.damageBonus = 1.4f + 0.005f * num2 * VL_GlobalConfigs.g_DamageModifer * VL_GlobalConfigs.c_berserkerExecute;
					sE_Execute.staggerForce = 1.5f + 0.005f * num2;
					if (((Character)player).GetSEMan().HaveStatusEffect("SE_VL_Execute"))
					{
						StatusEffect statusEffect = ((Character)player).GetSEMan().GetStatusEffect(StringExtensionMethods.GetStableHashCode("SE_VL_Execute"));
						((Character)player).GetSEMan().RemoveStatusEffect(statusEffect, false);
					}
					((Character)player).GetSEMan().AddStatusEffect((StatusEffect)(object)sE_Execute, false, 0, 0f);
					((Character)player).RaiseSkill(ValheimLegends.DisciplineSkill, VL_Utility.GetExecuteSkillGain(player));
				}
				else
				{
					((Character)player).Message((MessageType)1, "Not enough stamina for Execute: (" + player.GetStamina().ToString("#.#") + "/" + VL_Utility.GetExecuteCost(player) + ")", 0, (Sprite)null);
				}
			}
			else
			{
				((Character)player).Message((MessageType)1, "Ability not ready", 0, (Sprite)null);
			}
		}
	}
}
public class Class_Druid
{
	private static int Script_Layermask = LayerMask.GetMask(new string[11]
	{
		"Default", "static_solid", "Default_small", "piece_nonsolid", "terrain", "vehicle", "piece", "viewblock", "character", "character_net",
		"character_ghost"
	});

	private static GameObject GO_CastFX;

	private static GameObject GO_Root;

	private static Projectile P_Root;

	private static StatusEffect SE_Root;

	private static GameObject GO_RootDefender;

	private static int rootCount;

	private static int rootTotal;

	private static int rootCountTrigger;

	public static void Process_Input(Player player, float altitude)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_077a: Unknown result type (might be due to invalid IL or missing references)
		//IL_038d: 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_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_07bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_07c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_07cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_07cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_07d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_03df: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0205: Unknown result type (might be due to invalid IL or missing references)
		//IL_020b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0211: Unknown result type (might be due to invalid IL or missing references)
		//IL_0217: Unknown result type (might be due to invalid IL or missing references)
		//IL_021c: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02de: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01af: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0804: Unknown result type (might be due to invalid IL or missing references)
		//IL_0807: Unknown result type (might be due to invalid IL or missing references)
		//IL_0811: Unknown result type (might be due to invalid IL or missing references)
		//IL_0816: Unknown result type (might be due to invalid IL or missing references)
		//IL_081b: Unknown result type (might be due to invalid IL or missing references)
		//IL_081d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0824: Expected O, but got Unknown
		//IL_0853: Unknown result type (might be due to invalid IL or missing references)
		//IL_0858: Unknown result type (might be due to invalid IL or missing references)
		//IL_085f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0864: Unknown result type (might be due to invalid IL or missing references)
		//IL_086c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0878: Unknown result type (might be due to invalid IL or missing references)
		//IL_087d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0887: Unknown result type (might be due to invalid IL or missing references)
		//IL_08ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_07fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0901: Unknown result type (might be due to invalid IL or missing references)
		//IL_0906: Unknown result type (might be due to invalid IL or missing references)
		//IL_091a: Unknown result type (might be due to invalid IL or missing references)
		//IL_091c: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_05f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_05f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_09fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a20: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a25: Unknown result type (might be due to invalid IL or missing references)
		//IL_0621: Unknown result type (might be due to invalid IL or missing references)
		//IL_062c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0636: Unknown result type (might be due to invalid IL or missing references)
		//IL_063b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0641: Unknown result type (might be due to invalid IL or missing references)
		//IL_064b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0650: Unknown result type (might be due to invalid IL or missing references)
		//IL_0655: Unknown result type (might be due to invalid IL or missing references)
		//IL_0657: Unknown result type (might be due to invalid IL or missing references)
		//IL_065c: Unknown result type (might be due to invalid IL or missing references)
		//IL_066c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0672: Unknown result type (might be due to invalid IL or missing references)
		//IL_0678: Unknown result type (might be due to invalid IL or missing references)
		//IL_067e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0683: Unknown result type (might be due to invalid IL or missing references)
		//IL_070a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0725: Unknown result type (might be due to invalid IL or missing references)
		//IL_072a: Unknown result type (might be due to invalid IL or missing references)
		//IL_073e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0748: Unknown result type (might be due to invalid IL or missing references)
		//IL_060d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0614: Unknown result type (might be due to invalid IL or missing references)
		//IL_0619: Unknown result type (might be due to invalid IL or missing references)
		//IL_0488: Unknown result type (might be due to invalid IL or missing references)
		//IL_0494: Unknown result type (might be due to invalid IL or missing references)
		//IL_0499: Unknown result type (might be due to invalid IL or missing references)
		//IL_049c: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a9b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0aa1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0aab: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ab0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0abb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ac5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0aca: Unknown result type (might be due to invalid IL or missing references)
		//IL_0acf: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ad2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ade: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ae4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0aee: Unknown result type (might be due to invalid IL or missing references)
		//IL_0af3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0afe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b08: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b12: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b17: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b1c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b1f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b2b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b31: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b3b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b45: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b4a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b4f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b52: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_04de: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_1322: Unknown result type (might be due to invalid IL or missing references)
		//IL_1327: Unknown result type (might be due to invalid IL or missing references)
		//IL_134b: Unknown result type (might be due to invalid IL or missing references)
		//IL_1350: Unknown result type (might be due to invalid IL or missing references)
		//IL_13de: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f1: Expected O, but got Unknown
		//IL_054c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0551: Unknown result type (might be due to invalid IL or missing references)
		//IL_0558: Unknown result type (might be due to invalid IL or missing references)
		//IL_055d: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b66: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b6b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c7a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c7f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0bfb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c00: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c45: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c4a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c57: Unknown result type (might be due to invalid IL or missing references)
		//IL_0588: Unknown result type (might be due to invalid IL or missing references)
		//IL_0594: Unknown result type (might be due to invalid IL or missing references)
		//IL_0599: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_05ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_149a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d14: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d1f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d29: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d2e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d34: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d60: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d6b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d97: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d9c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0da1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0da6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0da9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0daa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e9f: Unknown result type (might be due to invalid IL or missing references)
		//IL_103a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e7f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e84: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e4a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e4f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e5c: Unknown result type (might be due to invalid IL or missing references)
		//IL_1134: Unknown result type (might be due to invalid IL or missing references)
		//IL_1139: Unknown result type (might be due to invalid IL or missing references)
		//IL_11b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_11ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_11da: Unknown result type (might be due to invalid IL or missing references)
		//IL_11df: Unknown result type (might be due to invalid IL or missing references)
		new Random();
		Vector3 val = default(Vector3);
		if (VL_Utility.Ability3_Input_Down)
		{
			if (!((Character)player).GetSEMan().HaveStatusEffect("SE_VL_Ability3_CD"))
			{
				ValheimLegends.shouldUseGuardianPower = false;
				if (player.GetStamina() >= VL_Utility.GetRootCost && !ValheimLegends.isChanneling)
				{
					ValheimLegends.isChanneling = true;
					StatusEffect val2 = (StatusEffect)(object)(SE_Ability3_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability3_CD));
					val2.m_ttl = VL_Utility.GetRootCooldownTime;
					((Character)player).GetSEMan().AddStatusEffect(val2, false, 0, 0f);
					((Character)player).UseStamina(VL_Utility.GetRootCost, false);
					((ZSyncAnimation)typeof(Player).GetField("m_zanim", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(Player.m_localPlayer)).SetTrigger("gpower");
					((ZSyncAnimation)typeof(Player).GetField("m_zanim", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(Player.m_localPlayer)).SetSpeed(0.3f);
					float num = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.ConjurationSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddStamina() / 200f + LevelSystem.Instance.getAddMagicDamage() / 80f, 0f, 0.5f));
					rootCount = 0;
					rootCountTrigger = 32 - Mathf.RoundToInt(0.12f * num);
					rootTotal = 0;
					Vector3 val3 = ((Component)player).transform.right * 2.5f;
					if (Random.Range(0f, 1f) < 0.5f)
					{
						val3 *= -1f;
					}
					val = ((Component)player).transform.position + ((Component)player).transform.up * 3f + ((Character)player).GetLookDir() * 2f + val3;
					GO_Root = Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("gdking_root_projectile"), new Vector3(val.x, val.y, val.z), Quaternion.identity);
					P_Root = GO_Root.GetComponent<Projectile>();
					((Object)P_Root).name = "Root";
					P_Root.m_respawnItemOnHit = false;
					P_Root.m_spawnOnHit = null;
					P_Root.m_ttl = 35f;
					P_Root.m_gravity = 0f;
					P_Root.m_rayRadius = 0.1f;
					Traverse.Create((object)P_Root).Field("m_skill").SetValue((object)ValheimLegends.ConjurationSkill);
					((Component)P_Root).transform.localRotation = Quaternion.LookRotation(((Character)player).GetLookDir());
					GO_Root.transform.localScale = Vector3.one * 1.5f;
					((Character)player).RaiseSkill(ValheimLegends.ConjurationSkill, VL_Utility.GetRootSkillGain);
				}
				else
				{
					((Character)player).Message((MessageType)1, "Not enough stamina to channel Root: (" + player.GetStamina().ToString("#.#") + "/" + VL_Utility.GetRootCost + ")", 0, (Sprite)null);
				}
			}
			else
			{
				((Character)player).Message((MessageType)1, "Ability not ready", 0, (Sprite)null);
			}
		}
		else if (VL_Utility.Ability3_Input_Pressed && player.GetStamina() > VL_Utility.GetRootCostPerUpdate && ValheimLegends.isChanneling && Mathf.Max(0f, altitude - ((Component)player).transform.position.y) <= 2f)
		{
			rootCount++;
			VL_Utility.SetTimer();
			((Character)player).UseStamina(VL_Utility.GetRootCostPerUpdate * (float)rootTotal, false);
			ValheimLegends.isChanneling = true;
			if (rootCount < rootCountTrigger)
			{
				return;
			}
			((Character)player).RaiseSkill(ValheimLegends.ConjurationSkill, 0.06f);
			float num2 = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.ConjurationSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddStamina() / 200f + LevelSystem.Instance.getAddMagicDamage() / 80f, 0f, 0.5f));
			rootCount = 0;
			if ((Object)(object)GO_Root != (Object)null && (Object)(object)GO_Root.transform != (Object)null)
			{
				RaycastHit val4 = default(RaycastHit);
				Vector3 position = ((Component)player).transform.position;
				Vector3 val5 = ((!Physics.Raycast(((Character)player).GetEyePoint(), ((Character)player).GetLookDir(), ref val4, float.PositiveInfinity, Script_Layermask) || !Object.op_Implicit((Object)(object)((RaycastHit)(ref val4)).collider)) ? (position + ((Character)player).GetLookDir() * 1000f) : ((RaycastHit)(ref val4)).point);
				HitData val6 = new HitData();
				val6.m_damage.m_pierce = Random.Range(10f + 0.6f * num2, 15f + 1.2f * num2) * VL_GlobalConfigs.g_DamageModifer * VL_GlobalConfigs.c_druidVines;
				val6.m_pushForce = 2f;
				rootTotal++;
				Vector3 val7 = Vector3.MoveTowards(GO_Root.transform.position, val5, 1f);
				if ((Object)(object)P_Root != (Object)null && ((Object)P_Root).name == "Root")
				{
					P_Root.Setup((Character)(object)player, (val7 - GO_Root.transform.position) * 75f, -1f, val6, (ItemData)null, (ItemData)null);
					Traverse.Create((object)P_Root).Field("m_skill").SetValue((object)ValheimLegends.ConjurationSkill);
				}
			}
			GO_Root = null;
			Vector3 val8 = ((Component)player).transform.right * 2.5f;
			if (Random.Range(0f, 1f) < 0.5f)
			{
				val8 *= -1f;
			}
			val = ((Component)player).transform.position + ((Component)player).transform.up * 3f + ((Character)player).GetLookDir() * 2f + val8;
			GO_Root = Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("gdking_root_projectile"), new Vector3(val.x, val.y, val.z), Quaternion.identity);
			P_Root = GO_Root.GetComponent<Projectile>();
			((Object)P_Root).name = "Root";
			P_Root.m_respawnItemOnHit = false;
			P_Root.m_spawnOnHit = null;
			P_Root.m_ttl = rootCountTrigger + 1;
			P_Root.m_gravity = 0f;
			P_Root.m_rayRadius = 0.1f;
			Traverse.Create((object)P_Root).Field("m_skill").SetValue((object)ValheimLegends.ConjurationSkill);
			((Component)P_Root).transform.localRotation = Quaternion.LookRotation(((Character)player).GetLookDir());
			GO_Root.transform.localScale = Vector3.one * 1.5f;
		}
		else if (((VL_Utility.Ability3_Input_Up || player.GetStamina() <= VL_Utility.GetRootCostPerUpdate) && ValheimLegends.isChanneling) || Mathf.Max(0f, altitude - ((Component)player).transform.position.y) > 2f)
		{
			if ((Object)(object)GO_Root != (Object)null && (Object)(object)GO_Root.transform != (Object)null)
			{
				RaycastHit val9 = default(RaycastHit);
				Vector3 position2 = ((Component)player).transform.position;
				Vector3 val10 = ((!Physics.Raycast(((Character)player).GetEyePoint(), ((Character)player).GetLookDir(), ref val9, float.PositiveInfinity, Script_Layermask) || !Object.op_Implicit((Object)(object)((RaycastHit)(ref val9)).collider)) ? (position2 + ((Character)player).GetLookDir() * 1000f) : ((RaycastHit)(ref val9)).point);
				HitData val11 = new HitData();
				val11.m_damage.m_pierce = 10f;
				val11.m_pushForce = 10f;
				val11.SetAttacker((Character)(object)player);
				Vector3 val12 = Vector3.MoveTowards(GO_Root.transform.position, val10, 1f);
				P_Root.Setup((Character)(object)player, (val12 - GO_Root.transform.position) * 65f, -1f, val11, (ItemData)null, (ItemData)null);
				Traverse.Create((object)P_Root).Field("m_skill").SetValue((object)ValheimLegends.ConjurationSkill);
			}
			rootTotal = 0;
			GO_Root = null;
			ValheimLegends.isChanneling = false;
		}
		else if (VL_Utility.Ability2_Input_Down)
		{
			if (!((Character)player).GetSEMan().HaveStatusEffect("SE_VL_Ability2_CD"))
			{
				if (player.GetStamina() >= VL_Utility.GetDefenderCost)
				{
					Vector3 lookDir = ((Character)player).GetLookDir();
					lookDir.y = 0f;
					((Component)player).transform.rotation = Quaternion.LookRotation(lookDir);
					ValheimLegends.shouldUseGuardianPower = false;
					StatusEffect val13 = (StatusEffect)(object)(SE_Ability2_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability2_CD));
					val13.m_ttl = VL_Utility.GetDefenderCooldownTime;
					((Character)player).GetSEMan().AddStatusEffect(val13, false, 0, 0f);
					((Character)player).UseStamina(VL_Utility.GetDefenderCost, false);
					float num3 = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.ConjurationSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddStamina() / 200f + LevelSystem.Instance.getAddMagicDamage() / 80f, 0f, 0.5f));
					((ZSyncAnimation)typeof(Player).GetField("m_zanim", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(Player.m_localPlayer)).SetTrigger("gpower");
					Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_WishbonePing"), ((Component)player).transform.position, Quaternion.identity);
					GameObject prefab = ZNetScene.instance.GetPrefab("TentaRoot");
					CharacterTimedDestruction component = prefab.GetComponent<CharacterTimedDestruction>();
					if ((Object)(object)component != (Object)null)
					{
						component.m_timeoutMin = 24f + 0.3f * num3;
						component.m_timeoutMax = component.m_timeoutMin;
						component.m_triggerOnAwake = true;
						((Behaviour)component).enabled = true;
					}
					List<Vector3> list = new List<Vector3>();
					list.Clear();
					val = ((Component)player).transform.position + ((Character)player).GetLookDir() * 5f + ((Component)player).transform.right * 5f;
					list.Add(val);
					val = ((Component)player).transform.position + ((Character)player).GetLookDir() * 5f + ((Component)player).transform.right * 5f * -1f;
					list.Add(val);
					val = ((Component)player).transform.position + ((Character)player).GetLookDir() * 5f * -1f;
					list.Add(val);
					for (int i = 0; i < list.Count; i++)
					{
						GO_RootDefender = Object.Instantiate<GameObject>(prefab, list[i], Quaternion.identity);
						Character component2 = GO_RootDefender.GetComponent<Character>();
						if ((Object)(object)component2 != (Object)null)
						{
							SE_RootsBuff sE_RootsBuff = (SE_RootsBuff)(object)ScriptableObject.CreateInstance(typeof(SE_RootsBuff));
							((StatusEffect)sE_RootsBuff).m_ttl = SE_RootsBuff.m_baseTTL;
							sE_RootsBuff.damageModifier = 0.5f + 0.015f * num3 * VL_GlobalConfigs.g_DamageModifer * VL_GlobalConfigs.c_druidDefenders;
							sE_RootsBuff.staminaRegen = 0.5f + 0.05f * num3;
							sE_RootsBuff.summoner = player;
							sE_RootsBuff.centerPoint = ((Component)player).transform.position;
							component2.GetSEMan().AddStatusEffect((StatusEffect)(object)sE_RootsBuff, false, 0, 0f);
							component2.SetMaxHealth(30f + 6f * num3);
							((Component)component2).transform.localScale = (0.75f + 0.005f * num3) * Vector3.one;
							component2.m_faction = (Faction)0;
							component2.SetTamed(true);
						}
						Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_Potion_stamina_medium"), ((Component)component2).transform.position, Quaternion.identity);
					}
					GameObject prefab2 = ZNetScene.instance.GetPrefab("VL_Deathsquit");
					CharacterTimedDestruction component3 = prefab2.GetComponent<CharacterTimedDestruction>();
					if ((Object)(object)component3 != (Object)null)
					{
						component3.m_timeoutMin = 24f + 0.3f * num3;
						component3.m_timeoutMax = component3.m_timeoutMin;
						component3.m_triggerOnAwake = true;
						((Behaviour)component3).enabled = true;
					}
					int num4 = 2 + Mathf.RoundToInt(0.05f * num3);
					for (int j = 0; j < num4; j++)
					{
						val = ((Component)player).transform.position + ((Component)player).transform.up * 4f + (((Character)player).GetLookDir() * Random.Range(0f - (5f + 0.1f * num3), 5f + 0.1f * num3) + ((Component)player).transform.right * Random.Range(0f - (5f + 0.1f * num3), 5f + 0.1f * num3));
						Character component4 = Object.Instantiate<GameObject>(prefab2, val, Quaternion.identity).GetComponent<Character>();
						component4.m_name = "Drusquito";
						if ((Object)(object)component4 != (Object)null)
						{
							SE_Companion sE_Companion = (SE_Companion)(object)ScriptableObject.CreateInstance(typeof(SE_Companion));
							((StatusEffect)sE_Companion).m_ttl = 60f;
							sE_Companion.damageModifier = 0.05f + 0.0075f * num3 * VL_GlobalConfigs.g_DamageModifer * VL_GlobalConfigs.c_druidDefenders;
							sE_Companion.summoner = player;
							component4.GetSEMan().AddStatusEffect((StatusEffect)(object)sE_Companion, false, 0, 0f);
							((Component)component4).transform.localScale = (0.4f + 0.005f * num3) * Vector3.one;
							component4.m_faction = (Faction)0;
							component4.SetTamed(true);
						}
						Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_float_hitwater"), ((Component)component4).transform.position, Quaternion.identity);
					}
					((Character)player).RaiseSkill(ValheimLegends.ConjurationSkill, VL_Utility.GetDefenderSkillGain);
				}
				else
				{
					((Character)player).Message((MessageType)1, "Not enough stamina to summon root defenders: (" + player.GetStamina().ToString("#.#") + "/" + VL_Utility.GetDefenderCost + ")", 0, (Sprite)null);
				}
			}
			else
			{
				((Character)player).Message((MessageType)1, "Ability not ready", 0, (Sprite)null);
			}
		}
		else if (VL_Utility.Ability1_Input_Down)
		{
			if (!((Character)player).GetSEMan().HaveStatusEffect("SE_VL_Ability1_CD"))
			{
				if (((Character)player).IsBlocking())
				{
					if (((Humanoid)player).GetInventory() == null)
					{
						return;
					}
					ItemData val14 = null;
					ItemData val15 = null;
					ItemDrop val16 = null;
					ItemDrop[] array = Resources.FindObjectsOfTypeAll(typeof(ItemDrop)) as ItemDrop[];
					foreach (ItemDrop val17 in array)
					{
						if (val17.m_itemData.m_shared.m_name.ToLower().Contains("spirit binding vial"))
						{
							val16 = val17;
							break;
						}
					}
					for (int l = 0; l < ((Humanoid)player).GetInventory().GetHeight(); l++)
					{
						if (val15 != null)
						{
							break;
						}
						for (int m = 0; m < ((Humanoid)player).GetInventory().GetWidth(); m++)
						{
							val14 = ((Humanoid)player).GetInventory().GetItemAt(m, l);
							if (val14 != null)
							{
								if (val14.m_shared.m_name == "$item_ancientseed")
								{
									val15 = val14;
								}
								if (val15 != null)
								{
									break;
								}
							}
						}
					}
					if (val15 == null)
					{
						((Character)player).Message((MessageType)1, "You need an Ancient Seed to create a Spirit Binding Vial.", 0, (Sprite)null);
					}
					else if (player.GetStamina() >= VL_Utility.GetRegenerationCost)
					{
						((Character)player).RaiseSkill(ValheimLegends.AlterationSkill, VL_Utility.GetRegenerationSkillGain);
						StatusEffect val18 = (StatusEffect)(object)(SE_Ability1_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability1_CD));
						float num5 = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.AlterationSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddCriticalChance() / 40f + LevelSystem.Instance.getAddMagicDamage() / 80f, 0f, 0.5f));
						val18.m_ttl = VL_Utility.GetHealCooldownTime * 20f / (1f + num5 / 150f);
						((Character)player).GetSEMan().AddStatusEffect(val18, false, 0, 0f);
						((Character)player).UseStamina(VL_Utility.GetRegenerationCost, false);
						Player localPlayer = Player.m_localPlayer;
						if (localPlayer != null)
						{
							((Humanoid)localPlayer).GetInventory().RemoveOneItem(val15);
						}
						ItemDrop.DropItem(val16.m_itemData, 1, ((Component)player).transform.position, Quaternion.identity);
						player.StartEmote("cheer", true);
						((Character)player).Message((MessageType)1, "Consumed 1 " + val15.m_shared.m_name + " to create a " + val16.m_itemData.m_shared.m_name + ".", 0, (Sprite)null);
						Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_Potion_stamina_medium"), ((Component)player).transform.position, Quaternion.identity);
						Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_WishbonePing"), ((Component)player).transform.position, Quaternion.identity);
					}
					else
					{
						((Character)player).Message((MessageType)1, "Not enough stamina to Create Spirit Binding Vial: (" + player.GetStamina().ToString("#.#") + "/" + VL_Utility.GetHealCost.ToString("#.#") + ")", 0, (Sprite)null);
					}
				}
				else if (player.GetStamina() >= VL_Utility.GetRegenerationCost)
				{
					StatusEffect val19 = (StatusEffect)(object)(SE_Ability1_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability1_CD));
					val19.m_ttl = VL_Utility.GetRegenerationCooldownTime;
					((Character)player).GetSEMan().AddStatusEffect(val19, false, 0, 0f);
					((Character)player).UseStamina(VL_Utility.GetRegenerationCost, false);
					float num6 = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.AlterationSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddCriticalChance() / 40f + LevelSystem.Instance.getAddMagicDamage() / 80f, 0f, 0.5f));
					player.StartEmote("cheer", true);
					GO_CastFX = Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_guardstone_permitted_add"), ((Character)player).GetCenterPoint(), Quaternion.identity);
					GO_CastFX = Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_WishbonePing"), ((Component)player).transform.position, Quaternion.identity);
					SE_Regeneration sE_Regeneration = (SE_Regeneration)(object)ScriptableObject.CreateInstance(typeof(SE_Regeneration));
					((StatusEffect)sE_Regeneration).m_ttl = SE_Regeneration.m_baseTTL;
					((StatusEffect)sE_Regeneration).m_icon = ZNetScene.instance.GetPrefab("TrophyGreydwarfShaman").GetComponent<ItemDrop>().m_itemData.GetIcon();
					sE_Regeneration.m_HealAmount = 0.5f + 0.4f * num6 * VL_GlobalConfigs.g_DamageModifer * VL_GlobalConfigs.c_druidRegen;
					sE_Regeneration.doOnce = false;
					List<Character> list2 = new List<Character>();
					list2.Clear();
					Character.GetCharactersInRange(((Character)player).GetCenterPoint(), 30f + 0.2f * num6, list2);
					foreach (Character item in list2)
					{
						if (!BaseAI.IsEnemy((Character)(object)player, item))
						{
							if ((Object)(object)item == (Object)(object)Player.m_localPlayer)
							{
								item.GetSEMan().AddStatusEffect((StatusEffect)(object)sE_Regeneration, true, 0, 0f);
							}
							else if (item.IsPlayer())
							{
								item.GetSEMan().AddStatusEffect(StringExtensionMethods.GetStableHashCode(((Object)sE_Regeneration).name), true, 0, 0f);
							}
							else
							{
								item.GetSEMan().AddStatusEffect((StatusEffect)(object)sE_Regeneration, true, 0, 0f);
							}
						}
					}
					((Character)player).RaiseSkill(ValheimLegends.AlterationSkill, VL_Utility.GetRegenerationSkillGain);
				}
				else
				{
					((Character)player).Message((MessageType)1, "Not enough stamina to for Regeneration: (" + player.GetStamina().ToString("#.#") + "/" + VL_Utility.GetRegenerationCost + ")", 0, (Sprite)null);
				}
			}
			else
			{
				((Character)player).Message((MessageType)1, "Ability not ready", 0, (Sprite)null);
			}
		}
		else
		{
			ValheimLegends.isChanneling = false;
		}
	}
}
public class Class_Duelist
{
	private static int ScriptChar_Layermask = LayerMask.GetMask(new string[11]
	{
		"Default", "static_solid", "Default_small", "piece_nonsolid", "terrain", "vehicle", "piece", "viewblock", "character", "character_net",
		"character_ghost"
	});

	private static GameObject GO_CastFX;

	private static GameObject GO_QuickShot;

	private static Projectile P_QuickShot;

	public static ItemDrop coinsItem;

	public static List<int> challengedDeath = new List<int>();

	public static List<int> challengedMastery = new List<int>();

	public static void Execute_Slash(Player player)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//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_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: 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_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_014a: Expected O, but got Unknown
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01af: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0211: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0276: Unknown result type (might be due to invalid IL or missing references)
		//IL_027b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0296: Unknown result type (might be due to invalid IL or missing references)
		//IL_029b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0389: Unknown result type (might be due to invalid IL or missing references)
		//IL_038e: Unknown result type (might be due to invalid IL or missing references)
		Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_VL_BlinkStrike"), ((Character)player).GetCenterPoint() + ((Character)player).GetLookDir() * 3f, Quaternion.LookRotation(((Character)player).GetLookDir()));
		float num = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.DisciplineSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddPhysicDamage() / 40f + LevelSystem.Instance.getAddAttackSpeed() / 40f, 0f, 0.5f));
		float num2 = (1.25f + num / 300f) * VL_GlobalConfigs.g_DamageModifer * VL_GlobalConfigs.c_duelistSeismicSlash;
		Vector3 val = ((Character)player).GetEyePoint() + ((Character)player).GetLookDir() * 6f;
		List<Character> list = new List<Character>();
		list.Clear();
		Character.GetCharactersInRange(val, 6f, list);
		foreach (Character item in list)
		{
			if (!BaseAI.IsEnemy((Character)(object)player, item) || !VL_Utility.LOS_IsValid(item, val, val))
			{
				continue;
			}
			_ = ((Component)item).transform.position - ((Component)player).transform.position;
			HitData val2 = new HitData();
			val2.m_damage = ((Humanoid)player).GetCurrentWeapon().GetDamage();
			val2.ApplyModifier(Random.Range(0.8f, 1.2f) * num2);
			val2.m_pushForce = 25f + 0.1f * num;
			val2.m_point = item.GetEyePoint();
			val2.m_dir = ((Component)player).transform.position - ((Component)item).transform.position;
			val2.m_skill = ValheimLegends.DisciplineSkill;
			item.Damage(val2);
			if (challengedMastery == null || !challengedMastery.Contains(((Object)item).GetInstanceID()))
			{
				continue;
			}
			challengedMastery.Remove(((Object)item).GetInstanceID());
			ItemDrop.DropItem(ValheimLegends.coinsItem.m_itemData, 1, ((Component)player).transform.position, Quaternion.identity);
			int num3 = Mathf.CeilToInt(Mathf.Sqrt(item.GetMaxHealth()) + (1f + LevelSystem.Instance.getAddCriticalChance() / 40f) * Mathf.Sqrt(item.GetMaxHealth()));
			if (num3 < LevelSystem.Instance.getLevel())
			{
				Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("sfx_coins_destroyed"), ((Character)player).GetCenterPoint(), Quaternion.identity);
				Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_coin_stack_destroyed"), ((Character)player).GetCenterPoint(), Quaternion.identity);
			}
			else
			{
				Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("sfx_coins_pile_destroyed"), ((Character)player).GetCenterPoint(), Quaternion.identity);
				Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_coin_pile_destroyed"), ((Character)player).GetCenterPoint(), Quaternion.identity);
			}
			ItemDrop[] array = Resources.FindObjectsOfTypeAll(typeof(ItemDrop)) as ItemDrop[];
			foreach (ItemDrop val3 in array)
			{
				if (val3.m_itemData.m_shared.m_name.ToLower().Contains("$item_wood"))
				{
					break;
				}
			}
			if (((Humanoid)player).GetInventory().CanAddItem(ValheimLegends.coinsItem.m_itemData.m_dropPrefab, num3))
			{
				((Humanoid)player).GetInventory().AddItem(ValheimLegends.coinsItem.m_itemData.m_dropPrefab, num3);
			}
			else
			{
				ItemDrop.DropItem(ValheimLegends.coinsItem.m_itemData, num3, ((Component)player).transform.position, Quaternion.identity);
			}
			((Character)player).Message((MessageType)1, "Spoiled " + num3.ToString("#") + " coins from " + item.GetHoverName() + "!", 0, (Sprite)null);
		}
	}

	public static void Process_Input(Player player, ref Rigidbody playerBody)
	{
		//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_058d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0592: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_05fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Invalid comparison between Unknown and I4
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Invalid comparison between Unknown and I4
		//IL_072a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0736: Unknown result type (might be due to invalid IL or missing references)
		//IL_073d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0748: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Invalid comparison between Unknown and I4
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Invalid comparison between Unknown and I4
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Invalid comparison between Unknown and I4
		//IL_07ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_07f6: Expected O, but got Unknown
		//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0307: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e45: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e69: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e6e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e83: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e8e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e98: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e9d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ea3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ead: Unknown result type (might be due to invalid IL or missing references)
		//IL_0eb2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0eb7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ec9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ece: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ee8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0eeb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ef0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0f0e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0f10: Unknown result type (might be due to invalid IL or missing references)
		//IL_0f9a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0f9c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0fa1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0fc4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0fd0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0fd7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0fdd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0875: Unknown result type (might be due to invalid IL or missing references)
		//IL_0881: Unknown result type (might be due to invalid IL or missing references)
		//IL_100d: Unknown result type (might be due to invalid IL or missing references)
		//IL_1013: Unknown result type (might be due to invalid IL or missing references)
		//IL_101d: Unknown result type (might be due to invalid IL or missing references)
		//IL_1022: Unknown result type (might be due to invalid IL or missing references)
		//IL_1027: Unknown result type (might be due to invalid IL or missing references)
		//IL_1029: Unknown result type (might be due to invalid IL or missing references)
		//IL_1030: Expected O, but got Unknown
		//IL_108f: Unknown result type (might be due to invalid IL or missing references)
		//IL_1094: Unknown result type (might be due to invalid IL or missing references)
		//IL_1099: Unknown result type (might be due to invalid IL or missing references)
		//IL_109b: Unknown result type (might be due to invalid IL or missing references)
		//IL_10a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_10a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_10af: Unknown result type (might be due to invalid IL or missing references)
		//IL_10bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_10c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_10ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_10f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_110e: Unknown result type (might be due to invalid IL or missing references)
		//IL_1005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a61: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a66: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a82: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a87: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a1d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a22: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a3e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a43: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b80: Unknown result type (might be due to invalid IL or missing references)
		new Random();
		if (VL_Utility.Ability3_Input_Down)
		{
			if (challengedDeath == null)
			{
				challengedDeath = new List<int>();
				challengedDeath.Clear();
			}
			if (challengedDeath.Count > 50)
			{
				challengedDeath.Clear();
			}
			if (challengedMastery == null)
			{
				challengedMastery = new List<int>();
				challengedMastery.Clear();
			}
			if (challengedMastery.Count > 50)
			{
				challengedMastery.Clear();
			}
			if (!((Character)player).GetSEMan().HaveStatusEffect("SE_VL_Ability3_CD"))
			{
				if (((Character)player).IsBlocking())
				{
					if (Traverse.Create((object)player).Field("m_leftItem").GetValue<ItemData>() == null && ((Humanoid)player).GetCurrentWeapon() != null && (int)((Humanoid)player).GetCurrentWeapon().m_shared.m_itemType != 14 && ((int)((Humanoid)player).GetCurrentWeapon().m_shared.m_skillType == 1 || (int)((Humanoid)player).GetCurrentWeapon().m_shared.m_skillType == 2 || (int)((Humanoid)player).GetCurrentWeapon().m_shared.m_skillType == 7 || (int)((Humanoid)player).GetCurrentWeapon().m_shared.m_skillType == 5))
					{
						float num = ((Humanoid)player).GetCurrentWeapon().GetMaxDurability() * (1f - ((Humanoid)player).GetCurrentWeapon().GetDurabilityPercentage());
						if (num > 0f)
						{
							float num2 = num * 4f * (1f - LevelSystem.Instance.getStaminaReduction() / 100f);
							float num3 = num;
							if (player.GetStamina() < num2)
							{
								num3 = player.GetStamina() / (4f * (1f - LevelSystem.Instance.getStaminaReduction() / 100f));
							}
							float num4 = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.DisciplineSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddPhysicDamage() / 40f + LevelSystem.Instance.getAddAttackSpeed() / 40f, 0f, 0.5f));
							StatusEffect val = (StatusEffect)(object)(SE_Ability3_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability3_CD));
							val.m_ttl = 60f + num3 * 2f * (1f - LevelSystem.Instance.getAddCriticalChance() / 40f);
							((Character)player).GetSEMan().AddStatusEffect(val, false, 0, 0f);
							((Character)player).UseStamina(num3 * 10f * (1f - LevelSystem.Instance.getAddCriticalChance() / 40f) * (1f - num4 / 300f), false);
							ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon();
							currentWeapon.m_durability += num3;
							Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_VL_BlinkStrike"), ((Character)player).GetCenterPoint() + ((Character)player).GetLookDir() * 3f, Quaternion.LookRotation(((Character)player).GetLookDir()));
							((ZSyncAnimation)typeof(Player).GetField("m_zanim", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(player)).SetTrigger("knife_stab1");
							((Character)player).RaiseSkill(ValheimLegends.DisciplineSkill, VL_Utility.GetBlinkStrikeSkillGain);
						}
						else
						{
							((Character)player).Message((MessageType)1, "You don't need to Sharpen you weapon.", 0, (Sprite)null);
						}
					}
					else
					{
						((Character)player).Message((MessageType)1, "You can only Sharpen an equipped bladed single one-handed weapon (swords, knives, axes or spears).", 0, (Sprite)null);
					}
				}
				else if (player.GetStamina() >= VL_Utility.GetBlinkStrikeCost)
				{
					StatusEffect val2 = (StatusEffect)(object)(SE_Ability3_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability3_CD));
					val2.m_ttl = VL_Utility.GetBlinkStrikeCooldownTime;
					((Character)player).GetSEMan().AddStatusEffect(val2, false, 0, 0f);
					((Character)player).UseStamina(VL_Utility.GetBlinkStrikeCost, false);
					((ZSyncAnimation)typeof(Player).GetField("m_zanim", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(player)).SetTrigger("knife_stab1");
					ValheimLegends.isChanneling = true;
					ValheimLegends.isChargingDash = true;
					ValheimLegends.dashCounter = 0;
					((Character)player).RaiseSkill(ValheimLegends.DisciplineSkill, VL_Utility.GetBlinkStrikeSkillGain);
				}
				else
				{
					((Character)player).Message((MessageType)1, "Not enough stamina for S. Slash : (" + player.GetStamina().ToString("#.#") + "/" + VL_Utility.GetBlinkStrikeCost + ")", 0, (Sprite)null);
				}
			}
			else
			{
				((Character)player).Message((MessageType)1, "Ability not ready", 0, (Sprite)null);
			}
		}
		else if (VL_Utility.Ability2_Input_Down)
		{
			if (challengedDeath == null)
			{
				challengedDeath = new List<int>();
				challengedDeath.Clear();
			}
			if (challengedDeath.Count > 50)
			{
				challengedDeath.Clear();
			}
			if (challengedMastery == null)
			{
				challengedMastery = new List<int>();
				challengedMastery.Clear();
			}
			if (challengedMastery.Count > 50)
			{
				challengedMastery.Clear();
			}
			if (!((Character)player).GetSEMan().HaveStatusEffect("SE_VL_Ability2_CD"))
			{
				if (player.GetStamina() >= VL_Utility.GetRiposteCost)
				{
					StatusEffect val3 = (StatusEffect)(object)(SE_Ability2_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability2_CD));
					val3.m_ttl = VL_Utility.GetRiposteCooldownTime;
					((Character)player).GetSEMan().AddStatusEffect(val3, false, 0, 0f);
					((Character)player).UseStamina(VL_Utility.GetRiposteCost, false);
					_ = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.DisciplineSkillDef)).m_level;
					Mathf.Clamp(LevelSystem.Instance.getAddPhysicDamage() / 40f + LevelSystem.Instance.getAddAttackSpeed() / 40f, 0f, 0.5f);
					GO_CastFX = Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("sfx_perfectblock"), ((Component)player).transform.position, Quaternion.identity);
					GO_CastFX = Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_backstab"), ((Character)player).GetCenterPoint(), Quaternion.identity);
					SE_Riposte sE_Riposte = (SE_Riposte)(object)ScriptableObject.CreateInstance(typeof(SE_Riposte));
					sE_Riposte.playerBody = playerBody;
					((Character)player).GetSEMan().AddStatusEffect((StatusEffect)(object)sE_Riposte, false, 0, 0f);
					((Character)player).RaiseSkill(ValheimLegends.DisciplineSkill, VL_Utility.GetRiposteSkillGain);
				}
				else
				{
					((Character)player).Message((MessageType)1, "Not enough stamina for Riposte: (" + player.GetStamina().ToString("#.#") + "/" + VL_Utility.GetRiposteCost + ")", 0, (Sprite)null);
				}
			}
			else
			{
				((Character)player).Message((MessageType)1, "Ability not ready", 0, (Sprite)null);
			}
		}
		else if (VL_Utility.Ability1_Input_Down)
		{
			if (challengedDeath == null)
			{
				challengedDeath = new List<int>();
				challengedDeath.Clear();
			}
			if (challengedDeath.Count > 50)
			{
				challengedDeath.Clear();
			}
			if (challengedMastery == null)
			{
				challengedMastery = new List<int>();
				challengedMastery.Clear();
			}
			if (challengedMastery.Count > 50)
			{
				challengedMastery.Clear();
			}
			if (!((Character)player).GetSEMan().HaveStatusEffect("SE_VL_Ability1_CD"))
			{
				ValheimLegends.DefineCoins();
				if (!((Object)(object)ValheimLegends.coinsItem != (Object)null))
				{
					return;
				}
				if (((Character)player).IsBlocking())
				{
					if (!((Character)player).GetSEMan().HaveStatusEffect("SE_VL_Ability1_CD"))
					{
						RaycastHit val4 = default(RaycastHit);
						_ = ((Component)player).transform.position;
						Physics.SphereCast(((Character)player).GetEyePoint(), 0.2f, ((Character)player).GetLookDir(), ref val4, 200f, ScriptChar_Layermask);
						VL_Utility.SetTimer();
						if ((Object)(object)((RaycastHit)(ref val4)).collider != (Object)null && (Object)(object)((Component)((RaycastHit)(ref val4)).collider).gameObject != (Object)null)
						{
							Character val5 = null;
							((Component)((RaycastHit)(ref val4)).collider).gameObject.TryGetComponent<Character>(ref val5);
							bool flag = (Object)(object)val5 != (Object)null;
							List<Component> list = new List<Component>();
							list.Clear();
							((Component)((RaycastHit)(ref val4)).collider).gameObject.GetComponents<Component>(list);
							if ((Object)(object)val5 == (Object)null)
							{
								val5 = (Character)((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent(typeof(Character));
								flag = (Object)(object)val5 != (Object)null;
								if ((Object)(object)val5 == (Object)null)
								{
									val5 = ((Component)((RaycastHit)(ref val4)).collider).GetComponentInChildren<Character>();
									flag = (Object)(object)val5 != (Object)null;
								}
							}
							if (flag && !val5.IsPlayer())
							{
								if ((challengedDeath != null && !challengedDeath.Contains(((Object)val5).GetInstanceID())) || (challengedMastery != null && !challengedMastery.Contains(((Object)val5).GetInstanceID())))
								{
									if (Vector3.Distance(((Component)player).transform.position, ((Component)val5).transform.position) <= 70f)
									{
										if (player.GetStamina() >= VL_Utility.GetQuickShotCost)
										{
											int num5 = Mathf.CeilToInt(Mathf.Sqrt(val5.GetMaxHealth()));
											if (((Humanoid)player).GetInventory() != null && ((Humanoid)player).GetInventory().HaveItem(ValheimLegends.coinsItem.m_itemData.m_shared.m_name, true) && ((Humanoid)player).GetInventory().CountItems("$item_coins", -1, true) >= num5)
											{
												ItemData val6 = null;
												ItemData val7 = null;
												for (int i = 0; i < ((Humanoid)player).GetInventory().GetHeight(); i++)
												{
													if (val7 != null)
													{
														break;
													}
													for (int j = 0; j < ((Humanoid)player).GetInventory().GetWidth(); j++)
													{
														val6 = ((Humanoid)player).GetInventory().GetItemAt(j, i);
														if (val6 != null)
														{
															if (val6.m_shared.m_name == "$item_coins" && ((Humanoid)player).GetInventory().GetItemAt(j, i).m_stack >= num5)
															{
																val7 = val6;
															}
															if (val7 != null)
															{
																break;
															}
														}
													}
												}
												for (int k = 0; k < num5; k++)
												{
													Player localPlayer = Player.m_localPlayer;
													if (localPlayer != null)
													{
														((Humanoid)localPlayer).GetInventory().RemoveOneItem(val7);
													}
												}
												StatusEffect val8 = (StatusEffect)(object)(SE_Ability1_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability1_CD));
												val8.m_ttl = VL_Utility.GetQuickShotCooldownTime * 4f;
												((Character)player).GetSEMan().AddStatusEffect(val8, false, 0, 0f);
												((Character)player).UseStamina(VL_Utility.GetQuickShotCost, false);
												if (num5 < LevelSystem.Instance.getLevel())
												{
													Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("sfx_coins_destroyed"), val5.GetCenterPoint(), Quaternion.identity);
													Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_coin_stack_destroyed"), val5.GetCenterPoint(), Quaternion.identity);
												}
												else
												{
													Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("sfx_coins_pile_destroyed"), val5.GetCenterPoint(), Quaternion.identity);
													Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_coin_pile_destroyed"), val5.GetCenterPoint(), Quaternion.identity);
												}
												player.StartEmote("point", true);
												((Character)player).Message((MessageType)1, "Challenged " + val5.GetHoverName() + " to a duel worth of " + num5.ToString("#") + " coins!", 0, (Sprite)null);
												if (val5.IsOwner())
												{
													if (Random.value < 0.33f)
													{
														((Character)player).Message((MessageType)2, "Duel of Mastery!", 1, ValheimLegends.RiposteIcon);
														challengedMastery.Add(((Object)val5).GetInstanceID());
													}
													else
													{
														((Character)player).Message((MessageType)2, "Duel to the Death!", 1, ZNetScene.instance.GetPrefab("TrophySkeleton").GetComponent<ItemDrop>().m_itemData.GetIcon());
														challengedDeath.Add(((Object)val5).GetInstanceID());
													}
												}
												else
												{
													((Character)player).Message((MessageType)2, "Duel of Mastery!", 1, ValheimLegends.RiposteIcon);
													challengedMastery.Add(((Object)val5).GetInstanceID());
												}
												((Character)player).RaiseSkill(ValheimLegends.DisciplineSkill, VL_Utility.GetQuickShotSkillGain);
											}
											else
											{
												((Character)player).Message((MessageType)1, "You need " + num5.ToString("#") + " coins to challenge " + val5.GetHoverName() + ".", 0, (Sprite)null);
											}
										}
										else
										{
											((Character)player).Message((MessageType)1, "Not enough stamina for Challenge: (" + player.GetStamina().ToString("#.#") + "/" + VL_Utility.GetBackstabCost + ")", 0, (Sprite)null);
										}
									}
									else
									{
										((Character)player).Message((MessageType)1, val5.GetHoverName() + " is too far away to challenge!", 0, (Sprite)null);
									}
								}
								else
								{
									((Character)player).Message((MessageType)1, val5.GetHoverName() + " was already challenged!", 0, (Sprite)null);
								}
							}
							else
							{
								((Character)player).Message((MessageType)1, "Invalid target", 0, (Sprite)null);
							}
						}
						else
						{
							((Character)player).Message((MessageType)1, "No target", 0, (Sprite)null);
						}
					}
					else
					{
						((Character)player).Message((MessageType)1, "Ability not ready", 0, (Sprite)null);
					}
				}
				else if (player.GetStamina() >= VL_Utility.GetQuickShotCost)
				{
					if (((Humanoid)player).GetInventory() != null && ((Humanoid)player).GetInventory().HaveItem(ValheimLegends.coinsItem.m_itemData.m_shared.m_name, true))
					{
						ItemData val9 = null;
						ItemData val10 = null;
						for (int l = 0; l < ((Humanoid)player).GetInventory().GetHeight(); l++)
						{
							if (val10 != null)
							{
								break;
							}
							for (int m = 0; m < ((Humanoid)player).GetInventory().GetWidth(); m++)
							{
								val9 = ((Humanoid)player).GetInventory().GetItemAt(m, l);
								if (val9 != null)
								{
									if (val9.m_shared.m_name == "$item_coins" && ((Humanoid)player).GetInventory().GetItemAt(m, l).m_stack >= 0)
									{
										val10 = val9;
									}
									if (val10 != null)
									{
										break;
									}
								}
							}
						}
						Player localPlayer2 = Player.m_localPlayer;
						if (localPlayer2 != null)
						{
							((Humanoid)localPlayer2).GetInventory().RemoveOneItem(val10);
						}
						float num6 = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.DisciplineSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddPhysicDamage() / 40f + LevelSystem.Instance.getAddAttackSpeed() / 40f, 0f, 0.5f));
						StatusEffect val11 = (StatusEffect)(object)(SE_Ability1_CD)(object)ScriptableObject.CreateInstance(typeof(SE_Ability1_CD));
						val11.m_ttl = VL_Utility.GetQuickShotCooldownTime;
						((Character)player).GetSEMan().AddStatusEffect(val11, false, 0, 0f);
						((Character)player).UseStamina(VL_Utility.GetQuickShotCost + 0.5f * num6, false);
						((ZSyncAnimation)typeof(Player).GetField("m_zanim", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(player)).SetTrigger("interact");
						GO_CastFX = Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("sfx_smelter_add"), ((Component)player).transform.position, Quaternion.identity);
						Vector3 val12 = ((Component)player).transform.position + ((Component)player).transform.up * 1.2f + ((Character)player).GetLookDir() * 0.5f;
						Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("sfx_coins_destroyed"), ((Character)player).GetCenterPoint(), Quaternion.identity);
						GO_CastFX = Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_VL_QuickShot"), val12, Quaternion.LookRotation(((Character)player).GetLookDir()));
						GO_QuickShot = Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("Greydwarf_throw_projectile"), val12, Quaternion.identity);
						P_QuickShot = GO_QuickShot.GetComponent<Projectile>();
						((Object)P_QuickShot).name = "QuickShot";
						P_QuickShot.m_respawnItemOnHit = false;
						P_QuickShot.m_spawnOnHit = null;
						P_QuickShot.m_ttl = 10f;
						P_QuickShot.m_gravity = 1.2f;
						P_QuickShot.m_rayRadius = 0.05f;
						P_QuickShot.m_hitNoise = 20f;
						((Component)P_QuickShot).transform.localRotation = Quaternion.LookRotation(((Humanoid)player).GetAimDir(val12));
						GO_QuickShot.transform.localScale = new Vector3(0.6f, 0.6f, 0.6f);
						RaycastHit val13 = default(RaycastHit);
						Vector3 val14 = ((!Physics.Raycast(((Character)player).GetEyePoint(), ((Character)player).GetLookDir(), ref val13, float.PositiveInfinity, ScriptChar_Layermask) || !Object.op_Implicit((Object)(object)((RaycastHit)(ref val13)).collider)) ? (((Character)player).GetEyePoint() + ((Character)player).GetLookDir() * 1000f) : ((RaycastHit)(ref val13)).point);
						HitData val15 = new HitData();
						val15.m_damage.m_pierce = Random.Range(10f + 1f * (num6 + (float)LevelSystem.Instance.getLevel()), 30f + 2f * (num6 + (float)LevelSystem.Instance.getLevel())) * VL_GlobalConfigs.g_DamageModifer * VL_GlobalConfigs.c_duelistHipShot;
						val15.m_pushForce = 1f;
						val15.m_skill = ValheimLegends.DisciplineSkill;
						Vector3 val16 = Vector3.MoveTowards(val12, val14, 1f);
						P_QuickShot.Setup((Character)(object)player, (val16 - GO_QuickShot.transform.position) * 100f, -1f, val15, (ItemData)null, (ItemData)null);
						Traverse.Create((object)P_QuickShot).Field("m_skill").SetValue((object)ValheimLegends.DisciplineSkill);
						GO_QuickShot = null;
						VL_Utility.RotatePlayerToTarget(player);
						((Character)player).RaiseSkill(ValheimLegends.DisciplineSkill, VL_Utility.GetQuickShotSkillGain);
					}
					else
					{
						((Character)player).Message((MessageType)1, "You need one coin to shoot.", 0, (Sprite)null);
					}
				}
				else
				{
					((Character)player).Message((MessageType)1, "Not enough stamina to for Coin Shot: (" + player.GetStamina().ToString("#.#") + "/" + VL_Utility.GetQuickShotCost + ")", 0, (Sprite)null);
				}
			}
			else
			{
				((Character)player).Message((MessageType)1, "Ability not ready", 0, (Sprite)null);
			}
		}
		else
		{
			ValheimLegends.isChanneling = false;
		}
	}
}
public class Class_Enchanter
{
	public enum EnchanterAttackType
	{
		Charm = 10,
		Shock = 8,
		None = 0
	}

	private static int Script_Layermask = LayerMask.GetMask(new string[8] { "Default", "static_solid", "Default_small", "piece_nonsolid", "terrain", "vehicle", "piece", "viewblock" });

	private static int ScriptChar_Layermask = LayerMask.GetMask(new string[14]
	{
		"Default", "static_solid", "Default_small", "piece_nonsolid", "piece", "terrain", "vehicle", "viewblock", "character", "character_noenv",
		"character_trigger", "character_net", "character_ghost", "Water"
	});

	private static bool zonechargeCharging = false;

	private static float zonechargeCount;

	private static int zonechargeChargeAmount;

	private static int zonechargeChargeAmountMax;

	private static float zonechargeSkillGain = 0f;

	public static EnchanterAttackType QueuedAttack;

	public static StatusEffect HasZoneBuffTime(Player p)
	{
		foreach (StatusEffect statusEffect in ((Character)p).GetSEMan().GetStatusEffects())
		{
			if (statusEffect.m_name.StartsWith("Biome: "))
			{
				return statusEffect;
			}
		}
		return null;
	}

	public static StatusEffect HasEnchantBuff(Character p)
	{
		foreach (StatusEffect statusEffect in p.GetSEMan().GetStatusEffects())
		{
			if (statusEffect.m_name.StartsWith("Enchant "))
			{
				return statusEffect;
			}
		}
		return null;
	}

	public static StatusEffect HasEnchantWeapon(Character p)
	{
		foreach (StatusEffect statusEffect in p.GetSEMan().GetStatusEffects())
		{
			if (statusEffect.m_name.EndsWith(" Weapon"))
			{
				return statusEffect;
			}
		}
		return null;
	}

	public static StatusEffect HasEnchantArmor(Character p)
	{
		foreach (StatusEffect statusEffect in p.GetSEMan().GetStatusEffects())
		{
			if (statusEffect.m_name.EndsWith(" Armor"))
			{
				return statusEffect;
			}
		}
		return null;
	}

	public static void Execute_Attack(Player player, ref Rigidbody playerBody, ref float altitude)
	{
		//IL_0079: 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_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: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_0170: Unknown result type (might be due to invalid IL or missing references)
		//IL_017c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: 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_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_027d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0283: Unknown result type (might be due to invalid IL or missing references)
		//IL_028d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0292: Unknown result type (might be due to invalid IL or missing references)
		//IL_029d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0330: Unknown result type (might be due to invalid IL or missing references)
		//IL_0336: Unknown result type (might be due to invalid IL or missing references)
		//IL_0340: Unknown result type (might be due to invalid IL or missing references)
		//IL_0345: Unknown result type (might be due to invalid IL or missing references)
		//IL_034a: Unknown result type (might be due to invalid IL or missing references)
		//IL_035a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e0: Expected O, but got Unknown
		//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0203: Unknown result type (might be due to invalid IL or missing references)
		//IL_0207: Unknown result type (might be due to invalid IL or missing references)
		//IL_020f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0214: Unknown result type (might be due to invalid IL or missing references)
		//IL_021e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0240: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_038e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0390: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c1: Expected O, but got Unknown
		//IL_0412: Unknown result type (might be due to invalid IL or missing references)
		//IL_0417: Unknown result type (might be due to invalid IL or missing references)
		//IL_041e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0420: Unknown result type (might be due to invalid IL or missing references)
		//IL_0427: Unknown result type (might be due to invalid IL or missing references)
		//IL_042c: Unknown result type (might be due to invalid IL or missing references)
		//IL_043e: Unknown result type (might be due to invalid IL or missing references)
		if (QueuedAttack == EnchanterAttackType.Charm)
		{
			float num = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.IllusionSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddAttackSpeed() / 40f + LevelSystem.Instance.getAddMagicDamage() / 80f, 0f, 0.5f));
			Vector3 val = ((Character)player).GetEyePoint() + ((Component)player).transform.up * 0.1f + ((Character)player).GetLookDir() * 0.5f + ((Component)player).transform.right * 0.25f;
			GameObject val2 = Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("VL_Charm"), val, Quaternion.identity);
			Projectile component = val2.GetComponent<Projectile>();
			((Object)component).name = "VL_Charm";
			component.m_respawnItemOnHit = false;
			component.m_spawnOnHit = null;
			component.m_ttl = 30f * VL_GlobalConfigs.c_enchanterCharm;
			component.m_gravity = 0f;
			component.m_rayRadius = 0.01f;
			component.m_aoe = 1f + (float)LevelSystem.Instance.getLevel() * (1f + Mathf.Sqrt(num)) / 600f;
			((Component)component).transform.localRotation = Quaternion.LookRotation(((Humanoid)player).GetAimDir(val));
			val2.transform.localScale = Vector3.zero;
			RaycastHit val3 = default(RaycastHit);
			Vector3 position = ((Component)player).transform.position;
			Vector3 val4 = ((!Physics.Raycast(val, ((Character)player).GetLookDir(), ref val3, 1000f, ScriptChar_Layermask) || !Object.op_Implicit((Object)(object)((RaycastHit)(ref val3)).collider)) ? (position + ((Character)player).GetLookDir() * 1000f) : ((RaycastHit)(ref val3)).point);
			HitData val5 = new HitData();
			val5.m_skill = ValheimLegends.IllusionSkill;
			Vector3 val6 = Vector3.MoveTowards(val2.transform.position, val4, 1f);
			component.Setup((Character)(object)player, (val6 - val2.transform.position) * 40f, -1f, val5, (ItemData)null, (ItemData)null);
			Traverse.Create((object)component).Field("m_skill").SetValue((object)ValheimLegends.IllusionSkill);
		}
		else
		{
			if (QueuedAttack != EnchanterAttackType.Shock)
			{
				return;
			}
			StatusEffect val7 = HasZoneBuffTime(player);
			if (!((Object)(object)val7 != (Object)null))
			{
				return;
			}
			Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("fx_VL_Shock"), ((Character)player).GetEyePoint() + ((Character)player).GetLookDir() * 2.5f + ((Component)player).transform.right * 0.25f, Quaternion.LookRotation(((Character)player).GetLookDir()));
			float num2 = ((IEnumerable<Skill>)((Character)player).GetSkills().GetSkillList()).FirstOrDefault((Func<Skill, bool>)((Skill x) => x.m_info == ValheimLegends.AlterationSkillDef)).m_level * (1f + Mathf.Clamp(LevelSystem.Instance.getAddCriticalChance() / 40f + LevelSystem.Instance.getAddMagicDamage() / 80f, 0f, 0.5f));
			Vector3 val8 = ((Character)player).GetEyePoint() + ((Character)player).GetLookDir() * 4f;
			List<Character> list = new List<Character>();
			list.Clear();
			Character.GetCharactersInRange(val8, 4f, list);
			foreach (Character item in list)
			{
				if (BaseAI.IsEnemy((Character)(object)player, item) && VL_Utility.LOS_IsValid(item, val8, val8))
				{
					Vector3 dir = ((Component)item).transform.position - ((Component)player).transform.position;
					HitData val9 = new HitData();
					val9.m_damage.m_lightning = 15f + num2 + val7.m_ttl * Random.Range(0.03f, 0.06f) * (1f + 0.1f * num2) * VL_GlobalConfigs.c_enchanterBiomeShock;
					val9.m_pushForce = 0f;
					val9.m_point = item.GetEyePoint();
					val9.m_dir = dir;
					val9.m_skill = ValheimLegends.AlterationSkill;
					item.Damage(val9);
					item.Stagger(val9.m_dir);
				}
			}
			if (((Object)val7).name == "SE_VL_BiomeAsh")
			{
				SE_BiomeAsh sE_BiomeAsh = val7 as SE_BiomeAsh;
				if ((Object)(object)sE_BiomeAsh.biomeLight != (Object)null)
				{
					Object.Destroy((Object)(object)sE_BiomeAsh.biomeLight);
				}
			}
			((Character)player).GetSEMan().RemoveStatusEffect(val7, false);
		}
	}

	public static void Process_Input(Player player, ref float altitude)
	{
		//IL_028a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0361: Unknown result type (might be due to invalid IL or missing references)
		//IL_0411: Unknown result type (might be due to invalid IL or missing references)
		//IL_0416: Unknown result type (might be due to invalid IL or missing references)
		//IL_0435: Unknown result type (might be due to invalid IL or missing references)
		//IL_0490: Unknown result type (might be due to invalid IL or missing references)
		//IL_0496: Invalid comparison between Unknown and I4
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b6: Invalid comparison between Unknown and I4
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_1144: Unknown result type (might be due to invalid IL or missing references)
		//IL_115a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e9f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ea4: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d6: Invalid comparison between Unknown and I4
		//IL_0312: Unknown result type (might be due to invalid IL or missing references)
		//IL_0317: Unknown result type (might be due to invalid IL or missing references)
		//IL_12a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_12c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_12c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0f5d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0f62: Unknown result type (might be due to invalid IL or missing references)
		//IL_07f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_07f6: Invalid comparison between Unknown and I4
		//IL_165d: Unknown result type (might be due to invalid IL or missing references)
		//IL_166e: Unknown result type (might be due to invalid IL or missing references)
		//IL_167a: Unknown result type (might be due to invalid IL or missing references)
		//IL_167f: Unknown r

BepInEx/plugins/UsefulTrophiesXP.dll

Decompiled 9 months ago
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using EpicMMOSystem;
using HarmonyLib;
using UnityEngine;
using ValheimLegends;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ClassLibrary1")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ClassLibrary1")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("fba93479-93ac-43d9-8ef2-cfb83bdb7b6d")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.1.1.0")]
namespace UsefulTrophiesXP
{
	[HarmonyPatch(typeof(Humanoid), "UseItem")]
	internal class UseItemPatch
	{
		public static bool Prefix(Player __instance, [HarmonyArgument(0)] Inventory inventory, [HarmonyArgument(1)] ItemData item, [HarmonyArgument(2)] bool fromInventoryGui, Inventory ___m_inventory, ZSyncAnimation ___m_zanim)
		{
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			string name = item.m_shared.m_name;
			if (name.Contains("$item_trophy_"))
			{
				string text = name.Substring(13);
				if (inventory == null)
				{
					inventory = ___m_inventory;
				}
				if (!inventory.ContainsItem(item))
				{
					return false;
				}
				GameObject hoverObject = ((Humanoid)__instance).GetHoverObject();
				if (!((Object)(object)hoverObject == (Object)null) && !fromInventoryGui)
				{
					Interactable componentInParent = hoverObject.GetComponentInParent<Interactable>();
					if (componentInParent is ItemStand || componentInParent is OfferingBowl)
					{
						return true;
					}
				}
				float num = 10f;
				if (UsefulTrophiesXP.TrophyXPDict.TryGetValue(text, out var value))
				{
					num = value * UsefulTrophiesXP.ExperienceModifier;
				}
				else
				{
					Debug.Log((object)("Unknown trophy for " + text + "!"));
				}
				inventory.RemoveOneItem(item);
				Player.m_localPlayer.m_skillLevelupEffects.Create(((Character)Player.m_localPlayer).GetHeadPoint(), Quaternion.identity, (Transform)null, 1f, -1);
				ValheimLegends.shouldUseGuardianPower = false;
				((ZSyncAnimation)typeof(Player).GetField("m_zanim", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(Player.m_localPlayer)).SetSpeed(2f);
				((ZSyncAnimation)typeof(Player).GetField("m_zanim", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(Player.m_localPlayer)).SetTrigger("gpower");
				LevelSystem.Instance.AddExp((int)num, false);
				((Character)__instance).Message((MessageType)1, $"Experience received: {num}", 0, (Sprite)null);
				return false;
			}
			return true;
		}
	}
	[BepInPlugin("gg.khairex.usefultrophies.twentyonez.EpicMMOPatch", "Useful Trophies Mod by Khairex, EpicMMO XP Patch by TwentyOneZ", "2.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInProcess("valheim.exe")]
	public class UsefulTrophiesXP : BaseUnityPlugin
	{
		public const string Id = "gg.khairex.usefultrophies.twentyonez.EpicMMOPatch";

		public static bool EnableSellingTrophies = true;

		public static float ExperienceModifier = 1f;

		public static Dictionary<string, float> TrophyXPDict = new Dictionary<string, float>
		{
			{ "deer", 40f },
			{ "boar", 133f },
			{ "neck", 400f },
			{ "greydwarf", 1200f },
			{ "greydwarfbrute", 1500f },
			{ "greydwarfshaman", 1200f },
			{ "skeleton", 800f },
			{ "skeletonpoison", 1500f },
			{ "troll", 1000f },
			{ "surtling", 2600f },
			{ "leech", 1800f },
			{ "draugr", 1500f },
			{ "draugrelite", 5000f },
			{ "blob", 1800f },
			{ "wraith", 5000f },
			{ "abomination", 200f },
			{ "wolf", 3500f },
			{ "fenring", 4000f },
			{ "hatchling", 3000f },
			{ "sgolem", 14000f },
			{ "ulv", 4000f },
			{ "cultist", 4000f },
			{ "goblin", 4500f },
			{ "goblinbrute", 13000f },
			{ "goblinshaman", 4000f },
			{ "lox", 7000f },
			{ "growth", 6000f },
			{ "deathsquito", 6000f },
			{ "serpent", 1500f },
			{ "hare", 400f },
			{ "gjall", 3600f },
			{ "tick", 4800f },
			{ "dvergr", 6000f },
			{ "seeker", 18000f },
			{ "seekerbrute", 25000f },
			{ "eikthyr", 200f },
			{ "elder", 500f },
			{ "bonemass", 900f },
			{ "dragonqueen", 1400f },
			{ "goblinking", 3000f },
			{ "seekerqueen", 4500f }
		};

		public static Dictionary<string, int> TrophyGoldValueDict = new Dictionary<string, int>
		{
			{ "deer", 15 },
			{ "boar", 10 },
			{ "neck", 10 },
			{ "greydwarf", 10 },
			{ "greydwarfbrute", 15 },
			{ "greydwarfshaman", 15 },
			{ "skeleton", 10 },
			{ "skeletonpoison", 15 },
			{ "troll", 50 },
			{ "surtling", 15 },
			{ "leech", 15 },
			{ "draugr", 15 },
			{ "draugrelite", 30 },
			{ "blob", 20 },
			{ "wraith", 30 },
			{ "abomination", 100 },
			{ "wolf", 25 },
			{ "fenring", 30 },
			{ "hatchling", 35 },
			{ "sgolem", 100 },
			{ "ulv", 50 },
			{ "cultist", 50 },
			{ "goblin", 35 },
			{ "goblinbrute", 50 },
			{ "goblinshaman", 50 },
			{ "lox", 150 },
			{ "growth", 50 },
			{ "deathsquito", 25 },
			{ "serpent", 250 },
			{ "hare", 40 },
			{ "gjall", 150 },
			{ "tick", 50 },
			{ "dvergr", 30 },
			{ "seeker", 50 },
			{ "seekerbrute", 100 },
			{ "eikthyr", 50 },
			{ "elder", 100 },
			{ "bonemass", 150 },
			{ "dragonqueen", 200 },
			{ "goblinking", 250 },
			{ "seekerqueen", 300 }
		};

		public Harmony Harmony { get; } = new Harmony("gg.khairex.usefultrophies.twentyonez.EpicMMOPatch");


		private void Awake()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Expected O, but got Unknown
			ConfigDefinition val = new ConfigDefinition("GoldValue", "EnableSellingTrophies");
			EnableSellingTrophies = ((BaseUnityPlugin)this).Config.Bind<bool>(val, true, (ConfigDescription)null).Value;
			ConfigDefinition val2 = new ConfigDefinition("XPModifier", "ExperienceModifier");
			ExperienceModifier = ((BaseUnityPlugin)this).Config.Bind<float>(val2, 1f, (ConfigDescription)null).Value;
			List<ConfigDefinition> list = new List<ConfigDefinition>();
			foreach (string key in TrophyXPDict.Keys)
			{
				list.Add(new ConfigDefinition("ExpScaling", key));
			}
			foreach (ConfigDefinition item in list)
			{
				TrophyXPDict[item.Key] = ((BaseUnityPlugin)this).Config.Bind<float>(item, TrophyXPDict[item.Key], (ConfigDescription)null).Value;
			}
			List<ConfigDefinition> list2 = new List<ConfigDefinition>();
			foreach (string key2 in TrophyGoldValueDict.Keys)
			{
				list2.Add(new ConfigDefinition("GoldValue", key2));
			}
			foreach (ConfigDefinition item2 in list2)
			{
				TrophyGoldValueDict[item2.Key] = ((BaseUnityPlugin)this).Config.Bind<int>(item2, TrophyGoldValueDict[item2.Key], (ConfigDescription)null).Value;
			}
			Harmony.PatchAll();
		}
	}
}
namespace UsefulTrophiesXP.Properties
{
	[CompilerGenerated]
	[GeneratedCode("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.2.0.0")]
	internal sealed class Settings : ApplicationSettingsBase
	{
		private static Settings defaultInstance = (Settings)(object)SettingsBase.Synchronized((SettingsBase)(object)new Settings());

		public static Settings Default => defaultInstance;
	}
}

BepInEx/plugins/BuildingDemolish.dll

Decompiled 9 months ago
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
public class AedenthornUtils
{
	public static bool IgnoreKeyPresses(bool extra = false)
	{
		if (!extra)
		{
			int result;
			if (!((Object)(object)ZNetScene.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && !Minimap.IsOpen() && !Console.IsVisible() && !TextInput.IsVisible() && !ZNet.instance.InPasswordDialog())
			{
				Chat instance = Chat.instance;
				result = ((instance != null && instance.HasFocus()) ? 1 : 0);
			}
			else
			{
				result = 1;
			}
			return (byte)result != 0;
		}
		int result2;
		if (!((Object)(object)ZNetScene.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && !Minimap.IsOpen() && !Console.IsVisible() && !TextInput.IsVisible() && !ZNet.instance.InPasswordDialog())
		{
			Chat instance2 = Chat.instance;
			if ((instance2 == null || !instance2.HasFocus()) && !StoreGui.IsVisible() && !InventoryGui.IsVisible() && !Menu.IsVisible())
			{
				TextViewer instance3 = TextViewer.instance;
				result2 = ((instance3 != null && instance3.IsVisible()) ? 1 : 0);
				goto IL_00d2;
			}
		}
		result2 = 1;
		goto IL_00d2;
		IL_00d2:
		return (byte)result2 != 0;
	}

	public static bool CheckKeyDown(string value)
	{
		try
		{
			return Input.GetKeyDown(value.ToLower());
		}
		catch
		{
			return false;
		}
	}

	public static bool CheckKeyHeld(string value, bool req = true)
	{
		try
		{
			return Input.GetKey(value.ToLower());
		}
		catch
		{
			return !req;
		}
	}
}
namespace BuildingDemolish;

[BepInPlugin("aedenthorn.BuildingDemolish", "Building Demolish", "0.6.0")]
public class BepInExPlugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(Terminal), "InputText")]
	private static class InputText_Patch
	{
		private static bool Prefix(Terminal __instance)
		{
			if (!modEnabled.Value)
			{
				return true;
			}
			string text = ((TMP_InputField)__instance.m_input).text;
			if (text.ToLower().Equals(typeof(BepInExPlugin).Namespace.ToLower() + " reset"))
			{
				((BaseUnityPlugin)context).Config.Reload();
				((BaseUnityPlugin)context).Config.Save();
				__instance.AddString(text);
				__instance.AddString(((BaseUnityPlugin)context).Info.Metadata.Name + " config reloaded");
				return false;
			}
			if (text.ToLower().Equals(typeof(BepInExPlugin).Namespace.ToLower() + " demolish"))
			{
				__instance.AddString(text);
				int num = DemolishPieces(destroyRadius.Value);
				__instance.AddString($"{((BaseUnityPlugin)context).Info.Metadata.Name} demolished {num} pieces");
				return false;
			}
			if (text.ToLower().StartsWith(typeof(BepInExPlugin).Namespace.ToLower() + " demolish "))
			{
				__instance.AddString(text);
				if (int.TryParse(text.Split(new char[1] { ' ' })[2], out var result))
				{
					int num2 = DemolishPieces(result);
					__instance.AddString($"{((BaseUnityPlugin)context).Info.Metadata.Name} demolished {num2} pieces");
				}
				else
				{
					__instance.AddString(((BaseUnityPlugin)context).Info.Metadata.Name + " syntax error");
				}
				return false;
			}
			return true;
		}
	}

	private static readonly bool isDebug = true;

	private static BepInExPlugin context;

	public static ConfigEntry<bool> modEnabled;

	public static ConfigEntry<int> nexusID;

	public static ConfigEntry<bool> allowDestroyUncreated;

	public static ConfigEntry<bool> requireCraftingStation;

	public static ConfigEntry<float> destroyRadius;

	public static ConfigEntry<string> hotKey;

	public static int destroyMask = LayerMask.GetMask(new string[7] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain", "vehicle" });

	public static void Dbgl(string str = "", bool pref = true)
	{
		if (isDebug)
		{
			Debug.Log((object)((pref ? (typeof(BepInExPlugin).Namespace + " ") : "") + str));
		}
	}

	private void Awake()
	{
		context = this;
		modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable this mod");
		nexusID = ((BaseUnityPlugin)this).Config.Bind<int>("General", "NexusID", 516, "Nexus mod ID for updates");
		destroyRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "DestroyRadius", 20f, "Radius of destruction");
		allowDestroyUncreated = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AllowDestroyUncreated", false, "Allow destroying buildings not created by any player");
		requireCraftingStation = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RequireCraftingStation", true, "Require a nearby crafting station to destroy corresponding pieces (this is a vanilla requirement)");
		hotKey = ((BaseUnityPlugin)this).Config.Bind<string>("General", "HotKey", ";", "Hotkey to initiate destruction");
		if (modEnabled.Value)
		{
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
		}
	}

	private void Update()
	{
		if (!AedenthornUtils.IgnoreKeyPresses(extra: true) && AedenthornUtils.CheckKeyDown(hotKey.Value))
		{
			int num = DemolishPieces(destroyRadius.Value);
			Dbgl($"Demolished {num} pieces.");
		}
	}

	private static int DemolishPieces(float radius)
	{
		//IL_0024: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_019b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		if (!Object.op_Implicit((Object)(object)localPlayer))
		{
			return 0;
		}
		int num = 0;
		Collider[] array = Physics.OverlapSphere(((Component)localPlayer).transform.position, radius, destroyMask);
		for (int i = 0; i < array.Length; i++)
		{
			Piece componentInParent = ((Component)array[i]).GetComponentInParent<Piece>();
			if (!Object.op_Implicit((Object)(object)componentInParent) || (!componentInParent.IsCreator() && (componentInParent.GetCreator() != 0L || !allowDestroyUncreated.Value)) || !componentInParent.m_canBeRemoved || Location.IsInsideNoBuildLocation(((Component)componentInParent).transform.position) || !PrivateArea.CheckAccess(((Component)componentInParent).transform.position, 0f, true, false) || (requireCraftingStation.Value && !Traverse.Create((object)localPlayer).Method("CheckCanRemovePiece", new object[1] { componentInParent }).GetValue<bool>()))
			{
				continue;
			}
			ZNetView component = ((Component)componentInParent).GetComponent<ZNetView>();
			if (!((Object)(object)component == (Object)null) && componentInParent.CanBeRemoved())
			{
				num++;
				WearNTear component2 = ((Component)componentInParent).GetComponent<WearNTear>();
				if (Object.op_Implicit((Object)(object)component2))
				{
					component2.Remove();
					continue;
				}
				component.ClaimOwnership();
				componentInParent.DropResources();
				componentInParent.m_placeEffect.Create(((Component)componentInParent).transform.position, ((Component)componentInParent).transform.rotation, ((Component)componentInParent).gameObject.transform, 1f, -1);
				localPlayer.m_removeEffects.Create(((Component)componentInParent).transform.position, Quaternion.identity, (Transform)null, 1f, -1);
				ZNetScene.instance.Destroy(((Component)componentInParent).gameObject);
			}
		}
		return num;
	}
}

BepInEx/plugins/Building.dll

Decompiled 9 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.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.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using ServerSync;
using SkillManager;
using TMPro;
using UnityEngine;

[assembly: Guid("9BF5432D-9518-4D36-A6C2-A8C62D36B921")]
[assembly: ComVisible(false)]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyProduct("Building")]
[assembly: AssemblyCompany("")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyDescription("https://valheim.thunderstore.io/package/Smoothbrain/Building")]
[assembly: AssemblyTitle("Building")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyConfiguration("")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[<187735d1-a65e-42ae-bbcc-fc54343001cf>Embedded]
	internal sealed class <187735d1-a65e-42ae-bbcc-fc54343001cf>EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[<187735d1-a65e-42ae-bbcc-fc54343001cf>Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class <cd125ad8-3368-4672-9eaf-57b424100665>NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public <cd125ad8-3368-4672-9eaf-57b424100665>NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public <cd125ad8-3368-4672-9eaf-57b424100665>NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[<187735d1-a65e-42ae-bbcc-fc54343001cf>Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class <856f47ca-b3fa-4627-b5fb-589eb438cc28>NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public <856f47ca-b3fa-4627-b5fb-589eb438cc28>NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace Building
{
	[BepInPlugin("org.bepinex.plugins.building", "Building", "1.2.5")]
	[<cd125ad8-3368-4672-9eaf-57b424100665>Nullable(0)]
	[BepInIncompatibility("org.bepinex.plugins.valheim_plus")]
	[<856f47ca-b3fa-4627-b5fb-589eb438cc28>NullableContext(1)]
	public class Building : BaseUnityPlugin
	{
		[<856f47ca-b3fa-4627-b5fb-589eb438cc28>NullableContext(0)]
		private enum Toggle
		{
			On = 1,
			Off = 0
		}

		[<856f47ca-b3fa-4627-b5fb-589eb438cc28>NullableContext(0)]
		private class ConfigurationManagerAttributes
		{
			[UsedImplicitly]
			public bool? ShowRangeAsPercent;
		}

		[<856f47ca-b3fa-4627-b5fb-589eb438cc28>NullableContext(0)]
		[HarmonyPatch(typeof(Player), "UpdatePlacement")]
		private static class ChangeStaminaUsage
		{
			private static float stamina;

			[<856f47ca-b3fa-4627-b5fb-589eb438cc28>NullableContext(1)]
			private static void Prefix(Player __instance, [<cd125ad8-3368-4672-9eaf-57b424100665>Nullable(2)] out ItemData __state)
			{
				__state = ((Humanoid)__instance).GetRightItem();
				if (__state?.m_shared.m_name == "$item_hammer")
				{
					stamina = __state.m_shared.m_attack.m_attackStamina;
					Attack attack = __state.m_shared.m_attack;
					attack.m_attackStamina *= Mathf.Max(0f, 1f - ((Character)(object)__instance).GetSkillFactor("Building") * (float)staminaReductionPerLevel.Value);
				}
			}

			[<856f47ca-b3fa-4627-b5fb-589eb438cc28>NullableContext(2)]
			private static void Finalizer(ItemData __state)
			{
				if (__state?.m_shared.m_name == "$item_hammer")
				{
					__state.m_shared.m_attack.m_attackStamina = stamina;
				}
			}
		}

		[<856f47ca-b3fa-4627-b5fb-589eb438cc28>NullableContext(0)]
		[HarmonyPatch(typeof(WearNTear), "OnPlaced")]
		public class AddZDO
		{
			public static bool forFree;

			[UsedImplicitly]
			[<856f47ca-b3fa-4627-b5fb-589eb438cc28>NullableContext(1)]
			private static void Postfix(WearNTear __instance)
			{
				((Component)__instance).GetComponent<ZNetView>().GetZDO().Set("BuildingSkill Level", ((Character)(object)Player.m_localPlayer).GetSkillFactor("Building"));
				__instance.m_health *= 1f + ((Component)__instance).GetComponent<ZNetView>().GetZDO().GetFloat("BuildingSkill Level", 0f) * (healthFactor.Value - 1f);
				if (freeBuildLevelRequirement.Value > 0)
				{
					forFree = Random.Range((float)freeBuildLevelRequirement.Value / 100f, 5.5f) <= ((Character)(object)Player.m_localPlayer).GetSkillFactor("Building");
				}
				((Component)__instance).GetComponent<ZNetView>().GetZDO().Set("BuildingSkill FreeBuild", forFree);
				if (((Humanoid)Player.m_localPlayer).GetRightItem() != null && ((Humanoid)Player.m_localPlayer).GetRightItem().m_shared.m_name.ToLower().Contains("hammer"))
				{
					((Character)(object)Player.m_localPlayer).RaiseSkill("Building");
				}
			}
		}

		[HarmonyPatch(typeof(WearNTear), "Awake")]
		[<856f47ca-b3fa-4627-b5fb-589eb438cc28>NullableContext(0)]
		private class IncreaseHealth
		{
			[<856f47ca-b3fa-4627-b5fb-589eb438cc28>NullableContext(1)]
			[UsedImplicitly]
			private static void Prefix(WearNTear __instance)
			{
				float health = __instance.m_health;
				float num = 1f;
				ZDO zDO = ((Component)__instance).GetComponent<ZNetView>().GetZDO();
				__instance.m_health = health * ((num + ((zDO != null) ? new float?(zDO.GetFloat("BuildingSkill Level", 0f)) : null) * (healthFactor.Value - 1f)) ?? 1f);
			}
		}

		[HarmonyPatch(typeof(WearNTear), "GetMaterialProperties")]
		[<856f47ca-b3fa-4627-b5fb-589eb438cc28>NullableContext(0)]
		private class BuildHigher
		{
			[UsedImplicitly]
			[<856f47ca-b3fa-4627-b5fb-589eb438cc28>NullableContext(1)]
			private static void Postfix(WearNTear __instance, ref float maxSupport, ref float minSupport, ref float horizontalLoss, ref float verticalLoss)
			{
				ZNetView nview = __instance.m_nview;
				float? obj;
				if (nview == null)
				{
					obj = null;
				}
				else
				{
					ZDO zDO = nview.GetZDO();
					obj = ((zDO != null) ? new float?(zDO.GetFloat("BuildingSkill Level", 0f)) : null);
				}
				float num = obj ?? ((Character)(object)Player.m_localPlayer)?.GetSkillFactor("Building") ?? 0f;
				maxSupport *= 1f + num * (maximumSupportFactor.Value - 1f);
				horizontalLoss *= 1f - num * (1f - supportLossFactor.Value);
				verticalLoss *= 1f - num * (1f - supportLossFactor.Value);
			}
		}

		[<856f47ca-b3fa-4627-b5fb-589eb438cc28>NullableContext(0)]
		[HarmonyPatch(typeof(Player), "UpdatePlacement")]
		private class ResetFlag
		{
			private static void Finalizer()
			{
				AddZDO.forFree = false;
			}
		}

		[<856f47ca-b3fa-4627-b5fb-589eb438cc28>NullableContext(0)]
		[HarmonyPatch(typeof(Player), "ConsumeResources")]
		private class BuildingIsFree
		{
			private class SkipConsumeResourcesException : Exception
			{
			}

			[HarmonyPriority(800)]
			private static void Prefix()
			{
				if (AddZDO.forFree)
				{
					throw new SkipConsumeResourcesException();
				}
			}

			[<856f47ca-b3fa-4627-b5fb-589eb438cc28>NullableContext(1)]
			[return: <cd125ad8-3368-4672-9eaf-57b424100665>Nullable(2)]
			private static Exception Finalizer(Exception __exception)
			{
				if (!(__exception is SkipConsumeResourcesException))
				{
					return __exception;
				}
				return null;
			}
		}

		[HarmonyPatch(typeof(Piece), "DropResources")]
		[<856f47ca-b3fa-4627-b5fb-589eb438cc28>NullableContext(0)]
		private class RecoverResources
		{
			[<856f47ca-b3fa-4627-b5fb-589eb438cc28>NullableContext(1)]
			private static bool Prefix(Piece __instance)
			{
				return !((Component)__instance).GetComponent<ZNetView>().GetZDO().GetBool("BuildingSkill FreeBuild", false);
			}
		}

		[<cd125ad8-3368-4672-9eaf-57b424100665>Nullable(0)]
		[HarmonyPatch(typeof(Player), "UpdatePlacement")]
		private static class ReduceHammerDurabilityLoss
		{
			private static bool reduced;

			private static void Prefix(Player __instance)
			{
				reduced = false;
				if (durabilityUsageLevelRequirement.Value > 0 && (float)durabilityUsageLevelRequirement.Value <= ((Character)(object)__instance).GetSkillFactor("Building") * 100f)
				{
					ItemData rightItem = ((Humanoid)__instance).GetRightItem();
					if (rightItem != null)
					{
						SharedData shared = rightItem.m_shared;
						shared.m_useDurabilityDrain *= 0.7f;
						reduced = true;
					}
				}
			}

			private static void Finalizer(Player __instance)
			{
				ItemData rightItem = ((Humanoid)__instance).GetRightItem();
				if (rightItem != null && reduced)
				{
					SharedData shared = rightItem.m_shared;
					shared.m_useDurabilityDrain /= 0.7f;
				}
			}
		}

		private const string ModName = "Building";

		private const string ModVersion = "1.2.5";

		private const string ModGUID = "org.bepinex.plugins.building";

		private static readonly ConfigSync configSync = new ConfigSync("org.bepinex.plugins.building")
		{
			DisplayName = "Building",
			CurrentVersion = "1.2.5",
			MinimumRequiredVersion = "1.2.5"
		};

		private static ConfigEntry<Toggle> serverConfigLocked = null;

		private static ConfigEntry<float> maximumSupportFactor = null;

		private static ConfigEntry<float> supportLossFactor = null;

		private static ConfigEntry<float> healthFactor = null;

		private static ConfigEntry<int> freeBuildLevelRequirement = null;

		private static ConfigEntry<int> durabilityUsageLevelRequirement = null;

		private static ConfigEntry<float> experienceGainedFactor = null;

		private static ConfigEntry<int> experienceLoss = null;

		private static ConfigEntry<int> staminaReductionPerLevel = null;

		private static Skill building = null;

		private ConfigEntry<T> config<[<cd125ad8-3368-4672-9eaf-57b424100665>Nullable(2)] T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true)
		{
			ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, description);
			configSync.AddConfigEntry<T>(val).SynchronizedConfig = synchronizedSetting;
			return val;
		}

		private ConfigEntry<T> config<[<cd125ad8-3368-4672-9eaf-57b424100665>Nullable(2)] T>(string group, string name, T value, string description, bool synchronizedSetting = true)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting);
		}

		public void Awake()
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Expected O, but got Unknown
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Expected O, but got Unknown
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Expected O, but got Unknown
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Expected O, but got Unknown
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Expected O, but got Unknown
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Expected O, but got Unknown
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Expected O, but got Unknown
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			building = new Skill("Building", "building-icon.png");
			building.Description.English("Increases the health of pieces built by you and you can build higher.");
			building.Name.German("Bauen");
			building.Description.German("Erhöht die Lebenspunkte von Bauten, die von dir errichtet wurden und du kannst höher bauen.");
			building.Configurable = false;
			serverConfigLocked = config("1 - General", "Lock Configuration", Toggle.On, "If on, the configuration is locked and can be changed by server admins only.");
			configSync.AddLockingConfigEntry<Toggle>(serverConfigLocked);
			maximumSupportFactor = config("2 - Building", "Maximum Support Factor", 1.5f, new ConfigDescription("Maximum support factor for building pieces at skill level 100.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>()));
			supportLossFactor = config("2 - Building", "Support Loss Factor", 0.75f, new ConfigDescription("Support loss factor for vertical and horizontal building at skill level 100.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1f), Array.Empty<object>()));
			healthFactor = config("2 - Building", "Health Factor", 3f, new ConfigDescription("Health factor for building pieces at skill level 100.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
			freeBuildLevelRequirement = config("2 - Building", "Free Build Level Requirement", 50, new ConfigDescription("Minimum required skill level to be able to receive free building pieces. 0 is disabled.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					ShowRangeAsPercent = false
				}
			}));
			durabilityUsageLevelRequirement = config("2 - Building", "Durability Increase Level Requirement", 30, new ConfigDescription("Minimum required skill level to reduce the durability usage of hammers by 30%. 0 is disabled.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					ShowRangeAsPercent = false
				}
			}));
			staminaReductionPerLevel = config("2 - Building", "Stamina Reduction per Level", 1, new ConfigDescription("Reduces the stamina usage while building. Percentage stamina reduction per level. 0 is disabled.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			experienceGainedFactor = config("3 - Other", "Skill Experience Gain Factor", 1f, new ConfigDescription("Factor for experience gained for the building skill.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 5f), Array.Empty<object>()));
			experienceGainedFactor.SettingChanged += [<856f47ca-b3fa-4627-b5fb-589eb438cc28>NullableContext(0)] (object _, EventArgs _) =>
			{
				building.SkillGainFactor = experienceGainedFactor.Value;
			};
			building.SkillGainFactor = experienceGainedFactor.Value;
			experienceLoss = config("3 - Other", "Skill Experience Loss", 0, new ConfigDescription("How much experience to lose in the building skill on death.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			experienceLoss.SettingChanged += [<856f47ca-b3fa-4627-b5fb-589eb438cc28>NullableContext(0)] (object _, EventArgs _) =>
			{
				building.SkillLoss = experienceLoss.Value;
			};
			building.SkillLoss = experienceLoss.Value;
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			new Harmony("org.bepinex.plugins.building").PatchAll(executingAssembly);
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[<eeda3cba-b437-4975-ae4f-66faefb344fa>Embedded]
	[CompilerGenerated]
	internal sealed class <eeda3cba-b437-4975-ae4f-66faefb344fa>EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	[CompilerGenerated]
	[<eeda3cba-b437-4975-ae4f-66faefb344fa>Embedded]
	internal sealed class <93311208-800b-4489-ada2-c66b7c500ebc>NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public <93311208-800b-4489-ada2-c66b7c500ebc>NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public <93311208-800b-4489-ada2-c66b7c500ebc>NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[<eeda3cba-b437-4975-ae4f-66faefb344fa>Embedded]
	[CompilerGenerated]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class <6bbb7c97-c1a9-4081-86de-eee169dfb3d5>NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public <6bbb7c97-c1a9-4081-86de-eee169dfb3d5>NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace SkillManager
{
	[<6bbb7c97-c1a9-4081-86de-eee169dfb3d5>NullableContext(1)]
	[PublicAPI]
	[<93311208-800b-4489-ada2-c66b7c500ebc>Nullable(0)]
	internal class Skill
	{
		[<93311208-800b-4489-ada2-c66b7c500ebc>Nullable(0)]
		public static class LocalizationCache
		{
			private static readonly Dictionary<string, Localization> localizations = new Dictionary<string, Localization>();

			internal static void LocalizationPostfix(Localization __instance, string language)
			{
				string key = localizations.FirstOrDefault([<6bbb7c97-c1a9-4081-86de-eee169dfb3d5>NullableContext(0)] (KeyValuePair<string, Localization> l) => l.Value == __instance).Key;
				if (key != null)
				{
					localizations.Remove(key);
				}
				if (!localizations.ContainsKey(language))
				{
					localizations.Add(language, __instance);
				}
			}

			public static Localization ForLanguage([<93311208-800b-4489-ada2-c66b7c500ebc>Nullable(2)] string language = null)
			{
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: Expected O, but got Unknown
				if (localizations.TryGetValue(language ?? PlayerPrefs.GetString("language", "English"), out var value))
				{
					return value;
				}
				value = new Localization();
				if (language != null)
				{
					value.SetupLanguage(language);
				}
				return value;
			}
		}

		[<93311208-800b-4489-ada2-c66b7c500ebc>Nullable(0)]
		[PublicAPI]
		public class LocalizeKey
		{
			private static readonly List<LocalizeKey> keys = new List<LocalizeKey>();

			public readonly string Key;

			public readonly Dictionary<string, string> Localizations = new Dictionary<string, string>();

			public LocalizeKey(string key)
			{
				Key = key.Replace("$", "");
			}

			public void Alias(string alias)
			{
				Localizations.Clear();
				if (!alias.Contains("$"))
				{
					alias = "$" + alias;
				}
				Localizations["alias"] = alias;
				Localization.instance.AddWord(Key, Localization.instance.Localize(alias));
			}

			public LocalizeKey English(string key)
			{
				return addForLang("English", key);
			}

			public LocalizeKey Swedish(string key)
			{
				return addForLang("Swedish", key);
			}

			public LocalizeKey French(string key)
			{
				return addForLang("French", key);
			}

			public LocalizeKey Italian(string key)
			{
				return addForLang("Italian", key);
			}

			public LocalizeKey German(string key)
			{
				return addForLang("German", key);
			}

			public LocalizeKey Spanish(string key)
			{
				return addForLang("Spanish", key);
			}

			public LocalizeKey Russian(string key)
			{
				return addForLang("Russian", key);
			}

			public LocalizeKey Romanian(string key)
			{
				return addForLang("Romanian", key);
			}

			public LocalizeKey Bulgarian(string key)
			{
				return addForLang("Bulgarian", key);
			}

			public LocalizeKey Macedonian(string key)
			{
				return addForLang("Macedonian", key);
			}

			public LocalizeKey Finnish(string key)
			{
				return addForLang("Finnish", key);
			}

			public LocalizeKey Danish(string key)
			{
				return addForLang("Danish", key);
			}

			public LocalizeKey Norwegian(string key)
			{
				return addForLang("Norwegian", key);
			}

			public LocalizeKey Icelandic(string key)
			{
				return addForLang("Icelandic", key);
			}

			public LocalizeKey Turkish(string key)
			{
				return addForLang("Turkish", key);
			}

			public LocalizeKey Lithuanian(string key)
			{
				return addForLang("Lithuanian", key);
			}

			public LocalizeKey Czech(string key)
			{
				return addForLang("Czech", key);
			}

			public LocalizeKey Hungarian(string key)
			{
				return addForLang("Hungarian", key);
			}

			public LocalizeKey Slovak(string key)
			{
				return addForLang("Slovak", key);
			}

			public LocalizeKey Polish(string key)
			{
				return addForLang("Polish", key);
			}

			public LocalizeKey Dutch(string key)
			{
				return addForLang("Dutch", key);
			}

			public LocalizeKey Portuguese_European(string key)
			{
				return addForLang("Portuguese_European", key);
			}

			public LocalizeKey Portuguese_Brazilian(string key)
			{
				return addForLang("Portuguese_Brazilian", key);
			}

			public LocalizeKey Chinese(string key)
			{
				return addForLang("Chinese", key);
			}

			public LocalizeKey Japanese(string key)
			{
				return addForLang("Japanese", key);
			}

			public LocalizeKey Korean(string key)
			{
				return addForLang("Korean", key);
			}

			public LocalizeKey Hindi(string key)
			{
				return addForLang("Hindi", key);
			}

			public LocalizeKey Thai(string key)
			{
				return addForLang("Thai", key);
			}

			public LocalizeKey Abenaki(string key)
			{
				return addForLang("Abenaki", key);
			}

			public LocalizeKey Croatian(string key)
			{
				return addForLang("Croatian", key);
			}

			public LocalizeKey Georgian(string key)
			{
				return addForLang("Georgian", key);
			}

			public LocalizeKey Greek(string key)
			{
				return addForLang("Greek", key);
			}

			public LocalizeKey Serbian(string key)
			{
				return addForLang("Serbian", key);
			}

			public LocalizeKey Ukrainian(string key)
			{
				return addForLang("Ukrainian", key);
			}

			private LocalizeKey addForLang(string lang, string value)
			{
				Localizations[lang] = value;
				if (Localization.instance.GetSelectedLanguage() == lang)
				{
					Localization.instance.AddWord(Key, value);
				}
				else if (lang == "English" && !Localization.instance.m_translations.ContainsKey(Key))
				{
					Localization.instance.AddWord(Key, value);
				}
				return this;
			}

			[HarmonyPriority(300)]
			internal static void AddLocalizedKeys(Localization __instance, string language)
			{
				foreach (LocalizeKey key in keys)
				{
					string value2;
					if (key.Localizations.TryGetValue(language, out var value) || key.Localizations.TryGetValue("English", out value))
					{
						__instance.AddWord(key.Key, value);
					}
					else if (key.Localizations.TryGetValue("alias", out value2))
					{
						Localization.instance.AddWord(key.Key, Localization.instance.Localize(value2));
					}
				}
			}
		}

		[<6bbb7c97-c1a9-4081-86de-eee169dfb3d5>NullableContext(0)]
		private class ConfigurationManagerAttributes
		{
			[<93311208-800b-4489-ada2-c66b7c500ebc>Nullable(2)]
			[UsedImplicitly]
			public string Category;
		}

		[<6bbb7c97-c1a9-4081-86de-eee169dfb3d5>NullableContext(0)]
		[HarmonyPatch(typeof(Skills), "IsSkillValid")]
		private static class Patch_Skills_IsSkillValid
		{
			private static void Postfix(SkillType type, ref bool __result)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				if (!__result && skills.ContainsKey(type))
				{
					__result = true;
				}
			}
		}

		private static readonly Dictionary<SkillType, Skill> skills;

		internal static readonly Dictionary<string, Skill> skillByName;

		private readonly string skillName;

		private readonly string internalSkillName;

		private readonly SkillDef skillDef;

		public readonly LocalizeKey Name;

		public readonly LocalizeKey Description;

		private float skillEffectFactor = 1f;

		private int skillLoss = 5;

		public bool Configurable;

		private static bool InitializedTerminal;

		[<93311208-800b-4489-ada2-c66b7c500ebc>Nullable(2)]
		private static Localization _english;

		[<93311208-800b-4489-ada2-c66b7c500ebc>Nullable(2)]
		private static BaseUnityPlugin _plugin;

		private static bool hasConfigSync;

		[<93311208-800b-4489-ada2-c66b7c500ebc>Nullable(2)]
		private static object _configSync;

		public float SkillGainFactor
		{
			get
			{
				return skillDef.m_increseStep;
			}
			set
			{
				skillDef.m_increseStep = value;
				this.SkillGainFactorChanged?.Invoke(value);
			}
		}

		public float SkillEffectFactor
		{
			get
			{
				return skillEffectFactor;
			}
			set
			{
				skillEffectFactor = value;
				this.SkillEffectFactorChanged?.Invoke(value);
			}
		}

		public int SkillLoss
		{
			get
			{
				return skillLoss;
			}
			set
			{
				skillLoss = value;
				this.SkillLossChanged?.Invoke(value);
			}
		}

		private static Localization english => _english ?? (_english = LocalizationCache.ForLanguage("English"));

		private static BaseUnityPlugin plugin
		{
			get
			{
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: Expected O, but got Unknown
				object obj = _plugin;
				if (obj == null)
				{
					BaseUnityPlugin val = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)Assembly.GetExecutingAssembly().DefinedTypes.First([<6bbb7c97-c1a9-4081-86de-eee169dfb3d5>NullableContext(0)] (TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
					_plugin = val;
					obj = (object)val;
				}
				return (BaseUnityPlugin)obj;
			}
		}

		[<93311208-800b-4489-ada2-c66b7c500ebc>Nullable(2)]
		private static object configSync
		{
			[<6bbb7c97-c1a9-4081-86de-eee169dfb3d5>NullableContext(2)]
			get
			{
				if (_configSync == null && hasConfigSync)
				{
					Type type = Assembly.GetExecutingAssembly().GetType("ServerSync.ConfigSync");
					if ((object)type != null)
					{
						_configSync = Activator.CreateInstance(type, plugin.Info.Metadata.GUID + " SkillManager");
						type.GetField("CurrentVersion").SetValue(_configSync, plugin.Info.Metadata.Version.ToString());
						type.GetProperty("IsLocked").SetValue(_configSync, true);
					}
					else
					{
						hasConfigSync = false;
					}
				}
				return _configSync;
			}
		}

		[<93311208-800b-4489-ada2-c66b7c500ebc>Nullable(2)]
		[method: <6bbb7c97-c1a9-4081-86de-eee169dfb3d5>NullableContext(2)]
		[field: <93311208-800b-4489-ada2-c66b7c500ebc>Nullable(2)]
		public event Action<float> SkillGainFactorChanged;

		[<93311208-800b-4489-ada2-c66b7c500ebc>Nullable(2)]
		[method: <6bbb7c97-c1a9-4081-86de-eee169dfb3d5>NullableContext(2)]
		[field: <93311208-800b-4489-ada2-c66b7c500ebc>Nullable(2)]
		public event Action<float> SkillEffectFactorChanged;

		[<93311208-800b-4489-ada2-c66b7c500ebc>Nullable(2)]
		[method: <6bbb7c97-c1a9-4081-86de-eee169dfb3d5>NullableContext(2)]
		[field: <93311208-800b-4489-ada2-c66b7c500ebc>Nullable(2)]
		public event Action<float> SkillLossChanged;

		public Skill(string englishName, string icon)
			: this(englishName, loadSprite(icon, 64, 64))
		{
		}

		public Skill(string englishName, Sprite icon)
		{
			//IL_0019: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			SkillType val = fromName(englishName);
			string text = new Regex("[^a-zA-Z]").Replace(englishName, "_");
			skills[val] = this;
			skillByName[englishName] = this;
			skillDef = new SkillDef
			{
				m_description = "$skilldesc_" + text,
				m_icon = icon,
				m_increseStep = 1f,
				m_skill = val
			};
			internalSkillName = text;
			skillName = englishName;
			Name = new LocalizeKey("skill_" + ((object)(SkillType)(ref val)).ToString()).English(englishName);
			Description = new LocalizeKey("skilldesc_" + text);
		}

		public static SkillType fromName(string englishName)
		{
			return (SkillType)Math.Abs(StringExtensionMethods.GetStableHashCode(englishName));
		}

		static Skill()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			//IL_00a2: 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)
			//IL_00dd: Expected O, but got Unknown
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Expected O, but got Unknown
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Expected O, but got Unknown
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Expected O, but got Unknown
			//IL_01ab: Expected O, but got Unknown
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Expected O, but got Unknown
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Expected O, but got Unknown
			//IL_023c: Expected O, but got Unknown
			skills = new Dictionary<SkillType, Skill>();
			skillByName = new Dictionary<string, Skill>();
			InitializedTerminal = false;
			hasConfigSync = true;
			Harmony val = new Harmony("org.bepinex.helpers.skillmanager");
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_FejdStartup", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Skills), "GetSkillDef", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Skills_GetSkillDef", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Skills), "CheatRaiseSkill", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Skills_CheatRaiseskill", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Skills), "CheatResetSkill", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Skills_CheatResetSkill", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "LoadCSV", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(LocalizeKey), "AddLocalizedKeys", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Terminal), "InitTerminal", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Terminal_InitTerminal_Prefix", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Terminal_InitTerminal", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(LocalizationCache), "LocalizationPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Skills), "OnDeath", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Skills_OnDeath_Prefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Skills_OnDeath_Finalizer", (Type[])null, (Type[])null)), (HarmonyMethod)null);
		}

		private static void Patch_FejdStartup()
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Expected O, but got Unknown
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Expected O, but got Unknown
			foreach (Skill skill in skills.Values)
			{
				if (skill.Configurable)
				{
					string key = skill.Name.Key;
					string group = new Regex("['[\"\\]]").Replace(english.Localize(key), "").Trim();
					string category = Localization.instance.Localize(key).Trim();
					ConfigEntry<float> skillGain = config(group, "Skill gain factor", skill.SkillGainFactor, new ConfigDescription("The rate at which you gain experience for the skill.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 5f), new object[1]
					{
						new ConfigurationManagerAttributes
						{
							Category = category
						}
					}));
					skill.SkillGainFactor = skillGain.Value;
					skillGain.SettingChanged += [<6bbb7c97-c1a9-4081-86de-eee169dfb3d5>NullableContext(0)] (object _, EventArgs _) =>
					{
						skill.SkillGainFactor = skillGain.Value;
					};
					ConfigEntry<float> skillEffect = config(group, "Skill effect factor", skill.SkillEffectFactor, new ConfigDescription("The power of the skill, based on the default power.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 5f), new object[1]
					{
						new ConfigurationManagerAttributes
						{
							Category = category
						}
					}));
					skill.SkillEffectFactor = skillEffect.Value;
					skillEffect.SettingChanged += [<6bbb7c97-c1a9-4081-86de-eee169dfb3d5>NullableContext(0)] (object _, EventArgs _) =>
					{
						skill.SkillEffectFactor = skillEffect.Value;
					};
					ConfigEntry<int> skillLoss = config(group, "Skill loss", skill.skillLoss, new ConfigDescription("How much experience to lose on death.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), new object[1]
					{
						new ConfigurationManagerAttributes
						{
							Category = category
						}
					}));
					skill.skillLoss = skillLoss.Value;
					skillLoss.SettingChanged += [<6bbb7c97-c1a9-4081-86de-eee169dfb3d5>NullableContext(0)] (object _, EventArgs _) =>
					{
						skill.skillLoss = skillLoss.Value;
					};
				}
			}
		}

		private static void Patch_Skills_GetSkillDef([<93311208-800b-4489-ada2-c66b7c500ebc>Nullable(2)] ref SkillDef __result, List<SkillDef> ___m_skills, SkillType type)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			if (__result == null)
			{
				SkillDef val = GetSkillDef(type);
				if (val != null)
				{
					___m_skills.Add(val);
					__result = val;
				}
			}
		}

		private static bool Patch_Skills_CheatRaiseskill(Skills __instance, string name, float value, Player ___m_player)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			foreach (SkillType key in skills.Keys)
			{
				SkillType current = key;
				Skill skill = skills[current];
				if (string.Equals(skill.internalSkillName, name, StringComparison.CurrentCultureIgnoreCase))
				{
					Skill skill2 = __instance.GetSkill(current);
					skill2.m_level += value;
					skill2.m_level = Mathf.Clamp(skill2.m_level, 0f, 100f);
					((Character)___m_player).Message((MessageType)1, "Skill increased " + Localization.instance.Localize("$skill_" + ((object)(SkillType)(ref current)).ToString()) + ": " + (int)skill2.m_level, 0, skill2.m_info.m_icon);
					Console.instance.Print("Skill " + skill.internalSkillName + " = " + skill2.m_level);
					return false;
				}
			}
			return true;
		}

		private static bool Patch_Skills_CheatResetSkill(Skills __instance, string name)
		{
			//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)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			foreach (SkillType key in skills.Keys)
			{
				Skill skill = skills[key];
				if (string.Equals(skill.internalSkillName, name, StringComparison.CurrentCultureIgnoreCase))
				{
					__instance.ResetSkill(key);
					Console.instance.Print("Skill " + skill.internalSkillName + " reset");
					return false;
				}
			}
			return true;
		}

		private static void Patch_Skills_OnDeath_Prefix(Skills __instance, [<93311208-800b-4489-ada2-c66b7c500ebc>Nullable(new byte[] { 2, 1 })] ref Dictionary<SkillType, Skill> __state)
		{
			//IL_002b: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			if (__state == null)
			{
				__state = new Dictionary<SkillType, Skill>();
			}
			foreach (KeyValuePair<SkillType, Skill> skill in skills)
			{
				if (__instance.m_skillData.TryGetValue(skill.Key, out var value))
				{
					__state[skill.Key] = value;
					if (skill.Value.skillLoss > 0)
					{
						Skill obj = value;
						obj.m_level -= value.m_level * (float)skill.Value.SkillLoss / 100f;
						value.m_accumulator = 0f;
					}
					__instance.m_skillData.Remove(skill.Key);
				}
			}
		}

		private static void Patch_Skills_OnDeath_Finalizer(Skills __instance, [<93311208-800b-4489-ada2-c66b7c500ebc>Nullable(new byte[] { 2, 1 })] ref Dictionary<SkillType, Skill> __state)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (__state == null)
			{
				return;
			}
			foreach (KeyValuePair<SkillType, Skill> item in __state)
			{
				__instance.m_skillData[item.Key] = item.Value;
			}
			__state = null;
		}

		private static void Patch_Terminal_InitTerminal_Prefix()
		{
			InitializedTerminal = Terminal.m_terminalInitialized;
		}

		private static void Patch_Terminal_InitTerminal()
		{
			if (!InitializedTerminal)
			{
				AddSkill(Terminal.commands["raiseskill"]);
				AddSkill(Terminal.commands["resetskill"]);
			}
			static void AddSkill(ConsoleCommand command)
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Expected O, but got Unknown
				ConsoleOptionsFetcher fetcher = command.m_tabOptionsFetcher;
				command.m_tabOptionsFetcher = (ConsoleOptionsFetcher)([<6bbb7c97-c1a9-4081-86de-eee169dfb3d5>NullableContext(0)] () =>
				{
					List<string> list = fetcher.Invoke();
					list.AddRange(skills.Values.Select([<6bbb7c97-c1a9-4081-86de-eee169dfb3d5>NullableContext(0)] (Skill skill) => skill.internalSkillName));
					return list;
				});
			}
		}

		[<6bbb7c97-c1a9-4081-86de-eee169dfb3d5>NullableContext(2)]
		private static SkillDef GetSkillDef(SkillType skillType)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (!skills.ContainsKey(skillType))
			{
				return null;
			}
			return skills[skillType].skillDef;
		}

		private static byte[] ReadEmbeddedFileBytes(string name)
		{
			using MemoryStream memoryStream = new MemoryStream();
			Assembly.GetExecutingAssembly().GetManifestResourceStream(Assembly.GetExecutingAssembly().GetName().Name + "." + name).CopyTo(memoryStream);
			return memoryStream.ToArray();
		}

		private static Texture2D loadTexture(string name)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_001f: Expected O, but got Unknown
			Texture2D val = new Texture2D(0, 0);
			ImageConversion.LoadImage(val, ReadEmbeddedFileBytes("icons." + name));
			return val;
		}

		private static Sprite loadSprite(string name, int width, int height)
		{
			//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)
			return Sprite.Create(loadTexture(name), new Rect(0f, 0f, (float)width, (float)height), Vector2.zero);
		}

		private static ConfigEntry<T> config<[<93311208-800b-4489-ada2-c66b7c500ebc>Nullable(2)] T>(string group, string name, T value, ConfigDescription description)
		{
			ConfigEntry<T> val = plugin.Config.Bind<T>(group, name, value, description);
			configSync?.GetType().GetMethod("AddConfigEntry").MakeGenericMethod(typeof(T))
				.Invoke(configSync, new object[1] { val });
			return val;
		}

		private static ConfigEntry<T> config<[<93311208-800b-4489-ada2-c66b7c500ebc>Nullable(2)] T>(string group, string name, T value, string description)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()));
		}
	}
	[<93311208-800b-4489-ada2-c66b7c500ebc>Nullable(0)]
	[PublicAPI]
	[<6bbb7c97-c1a9-4081-86de-eee169dfb3d5>NullableContext(1)]
	internal static class SkillExtensions
	{
		public static float GetSkillFactor(this Character character, string name)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return character.GetSkillFactor(Skill.fromName(name)) * Skill.skillByName[name].SkillEffectFactor;
		}

		public static float GetSkillFactor(this Skills skills, string name)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return skills.GetSkillFactor(Skill.fromName(name)) * Skill.skillByName[name].SkillEffectFactor;
		}

		public static void RaiseSkill(this Character character, string name, float value = 1f)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			character.RaiseSkill(Skill.fromName(name), value);
		}

		public static void RaiseSkill(this Skills skill, string name, float value = 1f)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			skill.RaiseSkill(Skill.fromName(name), value);
		}

		public static void LowerSkill(this Character character, string name, float factor = 1f)
		{
			character.GetSkills().LowerSkill(name, factor);
		}

		public static void LowerSkill(this Skills skills, string name, float factor)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (factor > 0f && skills.m_skillData.TryGetValue(Skill.fromName(name), out var value))
			{
				Skill obj = value;
				obj.m_level -= value.m_level * factor;
				value.m_accumulator = 0f;
			}
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[Microsoft.CodeAnalysis.Embedded]
	[CompilerGenerated]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	[Microsoft.CodeAnalysis.Embedded]
	[CompilerGenerated]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	[Microsoft.CodeAnalysis.Embedded]
	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.configValues.Count, parsedConfigs.customValues.Count, (isServer || clientUpdate) ? $"client {sender}" : "the server", DisplayName ?? Name));
				if (!isServer)
				{
					serverLockedSettingChanged();
				}
				return true;
			}
			finally
			{
				ProcessingServerUpdate = false;
			}
		}

		private ParsedConfigs ReadConfigsFromPackage(ZPackage package)
		{
			ParsedConfigs parsedConfigs = new ParsedConfigs();
			Dictionary<string, OwnConfigEntryBase> dictionary = allConfigs.Where((OwnConfigEntryBase c) => c.SynchronizedConfig).ToDictionary((OwnConfigEntryBase c) => c.BaseConfig.Definition.Section + "_" + c.BaseConfig.Definition.Key, (OwnConfigEntryBase c) => c);
			Dictionary<string, CustomSyncedValueBase> dictionary2 = allCustomValues.ToDictionary((CustomSyncedValueBase c) => c.Identifier, (CustomSyncedValueBase c) => c);
			int num = package.ReadInt();
			for (int i = 0; i < num; i++)
			{
				string text = package.ReadString();
				string text2 = package.ReadString();
				string text3 = package.ReadString();
				Type type = Type.GetType(text3);
				if (text3 == "" || type != null)
				{
					object obj;
					try
					{
						obj = ((text3 == "") ? null : ReadValueWithTypeFromZPackage(package, type));
					}
					catch (InvalidDeserializationTypeException ex)
					{
						Debug.LogWarning((object)("Got unexpected struct internal type " + ex.received + " for field " + ex.field + " struct " + text3 + " for " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ", expecting " + ex.expected));
						continue;
					}
					OwnConfigEntryBase value2;
					if (text == "Internal")
					{
						CustomSyncedValueBase value;
						if (text2 == "serverversion")
						{
							if (obj?.ToString() != CurrentVersion)
							{
								Debug.LogWarning((object)("Received server version is not equal: server version = " + (obj?.ToString() ?? "null") + "; local version = " + (CurrentVersion ?? "unknown")));
							}
						}
						else if (text2 == "lockexempt")
						{
							if (obj is bool flag)
							{
								lockExempt = flag;
							}
						}
						else if (dictionary2.TryGetValue(text2, out value))
						{
							if ((text3 == "" && (!value.Type.IsValueType || Nullable.GetUnderlyingType(value.Type) != null)) || GetZPackageTypeString(value.Type) == text3)
							{
								parsedConfigs.customValues[value] = obj;
								continue;
							}
							Debug.LogWarning((object)("Got unexpected type " + text3 + " for internal value " + text2 + " for mod " + (DisplayName ?? Name) + ", expecting " + value.Type.AssemblyQualifiedName));
						}
					}
					else if (dictionary.TryGetValue(text + "_" + text2, out value2))
					{
						Type type2 = configType(value2.BaseConfig);
						if ((text3 == "" && (!type2.IsValueType || Nullable.GetUnderlyingType(type2) != null)) || GetZPackageTypeString(type2) == text3)
						{
							parsedConfigs.configValues[value2] = obj;
							continue;
						}
						Debug.LogWarning((object)("Got unexpected type " + text3 + " for " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ", expecting " + type2.AssemblyQualifiedName));
					}
					else
					{
						Debug.LogWarning((object)("Received unknown config entry " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ". This may happen if client and server versions of the mod do not match."));
					}
					continue;
				}
				Debug.LogWarning((object)("Got invalid type " + text3 + ", abort reading of received configs"));
				return new ParsedConfigs();
			}
			return parsedConfigs;
		}

		private static bool isWritableConfig(OwnConfigEntryBase config)
		{
			OwnConfigEntryBase config2 = config;
			ConfigSync configSync = configSyncs.FirstOrDefault((ConfigSync cs) => cs.allConfigs.Contains(config2));
			if (configSync == null)
			{
				return true;
			}
			return configSync.IsSourceOfTruth || !config2.SynchronizedConfig || config2.LocalBaseValue == null || (!configSync.IsLocked && (config2 != configSync.lockedConfig || lockExempt));
		}

		private void serverLockedSettingChanged()
		{
			foreach (OwnConfigEntryBase allConfig in allConfigs)
			{
				configAttribute<ConfigurationManagerAttributes>(allConfig.BaseConfig).ReadOnly = !isWritableConfig(allConfig);
			}
		}

		private void resetConfigsFromServer()
		{
			foreach (OwnConfigEntryBase item in allConfigs.Where((OwnConfigEntryBase config) => config.LocalBaseValue != null))
			{
				item.BaseConfig.BoxedValue = item.LocalBaseValue;
				item.LocalBaseValue = null;
			}
			foreach (CustomSyncedValueBase item2 in allCustomValues.Where((CustomSyncedValueBase config) => config.LocalBaseValue != null))
			{
				item2.BoxedValue = item2.LocalBaseValue;
				item2.LocalBaseValue = null;
			}
			lockedConfigChanged -= serverLockedSettingChanged;
			serverLockedSettingChanged();
		}

		private IEnumerator<bool> distributeConfigToPeers(ZNetPeer peer, ZPackage package)
		{
			ZNetPeer peer2 = peer;
			ZRoutedRpc rpc = ZRoutedRpc.instance;
			if (rpc == null)
			{
				yield break;
			}
			byte[] data = package.GetArray();
			if (data != null && data.LongLength > 250000)
			{
				int fragments = (int)(1 + (data.LongLength - 1) / 250000);
				long packageIdentifier = ++packageCounter;
				int fragment = 0;
				while (fragment < fragments)
				{
					foreach (bool item in waitForQueue())
					{
						yield return item;
					}
					if (peer2.m_socket.IsConnected())
					{
						ZPackage fragmentedPackage = new ZPackage();
						fragmentedPackage.Write((byte)2);
						fragmentedPackage.Write(packageIdentifier);
						fragmentedPackage.Write(fragment);
						fragmentedPackage.Write(fragments);
						fragmentedPackage.Write(data.Skip(250000 * fragment).Take(250000).ToArray());
						SendPackage(fragmentedPackage);
						if (fragment != fragments - 1)
						{
							yield return true;
						}
						int num = fragment + 1;
						fragment = num;
						continue;
					}
					break;
				}
				yield break;
			}
			foreach (bool item2 in waitForQueue())
			{
				yield return item2;
			}
			SendPackage(package);
			void SendPackage(ZPackage pkg)
			{
				string text = Name + " ConfigSync";
				if (isServer)
				{
					peer2.m_rpc.Invoke(text, new object[1] { pkg });
				}
				else
				{
					rpc.InvokeRoutedRPC(peer2.m_server ? 0 : peer2.m_uid, text, new object[1] { pkg });
				}
			}
			IEnumerable<bool> waitForQueue()
			{
				float timeout = Time.time + 30f;
				while (peer2.m_socket.GetSendQueueSize() > 20000)
				{
					if (Time.time > timeout)
					{
						Debug.Log((object)$"Disconnecting {peer2.m_uid} after 30 seconds config sending timeout");
						peer2.m_rpc.Invoke("Error", new object[1] { (object)(ConnectionStatus)5 });
						ZNet.instance.Disconnect(peer2);
						break;
					}
					yield return false;
				}
			}
		}

		private IEnumerator sendZPackage(long target, ZPackage package)
		{
			if (!Object.op_Implicit((Object)(object)ZNet.instance))
			{
				return Enumerable.Empty<object>().GetEnumerator();
			}
			List<ZNetPeer> list = (List<ZNetPeer>)AccessTools.DeclaredField(typeof(ZRoutedRpc), "m_peers").GetValue(ZRoutedRpc.instance);
			if (target != ZRoutedRpc.Everybody)
			{
				list = list.Where((ZNetPeer p) => p.m_uid == target).ToList();
			}
			return sendZPackage(list, package);
		}

		private IEnumerator sendZPackage(List<ZNetPeer> peers, ZPackage package)
		{
			ZPackage package2 = package;
			if (!Object.op_Implicit((Object)(object)ZNet.instance))
			{
				yield break;
			}
			byte[] rawData = package2.GetArray();
			if (rawData != null && rawData.LongLength > 10000)
			{
				ZPackage compressedPackage = new ZPackage();
				compressedPackage.Write((byte)4);
				MemoryStream output = new MemoryStream();
				using (DeflateStream deflateStream = new DeflateStream(output, CompressionLevel.Optimal))
				{
					deflateStream.Write(rawData, 0, rawData.Length);
				}
				compressedPackage.Write(output.ToArray());
				package2 = compressedPackage;
			}
			List<IEnumerator<bool>> writers = (from peer in peers
				where peer.IsReady()
				select peer into p
				select distributeConfigToPeers(p, package2)).ToList();
			writers.RemoveAll((IEnumerator<bool> writer) => !writer.MoveNext());
			while (writers.Count > 0)
			{
				yield return null;
				writers.RemoveAll((IEnumerator<bool> writer) => !writer.MoveNext());
			}
		}

		private void Broadcast(long target, params ConfigEntryBase[] configs)
		{
			if (!IsLocked || isServer)
			{
				ZPackage package = ConfigsToPackage(configs);
				ZNet instance = ZNet.instance;
				if (instance != null)
				{
					((MonoBehaviour)instance).StartCoroutine(sendZPackage(target, package));
				}
			}
		}

		private void Broadcast(long target, params CustomSyncedValueBase[] customValues)
		{
			if (!IsLocked || isServer)
			{
				ZPackage package = ConfigsToPackage(null, customValues);
				ZNet instance = ZNet.instance;
				if (instance != null)
				{
					((MonoBehaviour)instance).StartCoroutine(sendZPackage(target, package));
				}
			}
		}

		private static OwnConfigEntryBase? configData(ConfigEntryBase config)
		{
			return config.Description.Tags?.OfType<OwnConfigEntryBase>().SingleOrDefault();
		}

		public static SyncedConfigEntry<T>? ConfigData<T>(ConfigEntry<T> config)
		{
			return ((ConfigEntryBase)config).Description.Tags?.OfType<SyncedConfigEntry<T>>().SingleOrDefault();
		}

		private static T configAttribute<T>(ConfigEntryBase config)
		{
			return config.Description.Tags.OfType<T>().First();
		}

		private static Type configType(ConfigEntryBase config)
		{
			return configType(config.SettingType);
		}

		private static Type configType(Type type)
		{
			return type.IsEnum ? Enum.GetUnderlyingType(type) : type;
		}

		private static ZPackage ConfigsToPackage(IEnumerable<ConfigEntryBase>? configs = null, IEnumerable<CustomSyncedValueBase>? customValues = null, IEnumerable<PackageEntry>? packageEntries = null, bool partial = true)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			List<ConfigEntryBase> list = configs?.Where((ConfigEntryBase config) => configData(config).SynchronizedConfig).ToList() ?? new List<ConfigEntryBase>();
			List<CustomSyncedValueBase> list2 = customValues?.ToList() ?? new List<CustomSyncedValueBase>();
			ZPackage val = new ZPackage();
			val.Write((byte)(partial ? 1 : 0));
			val.Write(list.Count + list2.Count + (packageEntries?.Count() ?? 0));
			foreach (PackageEntry item in packageEntries ?? Array.Empty<PackageEntry>())
			{
				AddEntryToPackage(val, item);
			}
			foreach (CustomSyncedValueBase item2 in list2)
			{
				AddEntryToPackage(val, new PackageEntry
				{
					section = "Internal",
					key = item2.Identifier,
					type = item2.Type,
					value = item2.BoxedValue
				});
			}
			foreach (ConfigEntryBase item3 in list)
			{
				AddEntryToPackage(val, new PackageEntry
				{
					section = item3.Definition.Section,
					key = item3.Definition.Key,
					type = configType(item3),
					value = item3.BoxedValue
				});
			}
			return val;
		}

		private static void AddEntryToPackage(ZPackage package, PackageEntry entry)
		{
			package.Write(entry.section);
			package.Write(entry.key);
			package.Write((entry.value == null) ? "" : GetZPackageTypeString(entry.type));
			AddValueToZPackage(package, entry.value);
		}

		private static string GetZPackageTypeString(Type type)
		{
			return type.AssemblyQualifiedName;
		}

		private static void AddValueToZPackage(ZPackage package, object? value)
		{
			Type type = value?.GetType();
			if (value is Enum)
			{
				value = ((IConvertible)value).ToType(Enum.GetUnderlyingType(value.GetType()), CultureInfo.InvariantCulture);
			}
			else
			{
				if (value is ICollection collection)
				{
					package.Write(collection.Count);
					{
						foreach (object item in collection)
						{
							AddValueToZPackage(package, item);
						}
						return;
					}
				}
				if ((object)type != null && type.IsValueType && !type.IsPrimitive)
				{
					FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					package.Write(fields.Length);
					FieldInfo[] array = fields;
					foreach (FieldInfo fieldInfo in array)
					{
						package.Write(GetZPackageTypeString(fieldInfo.FieldType));
						AddValueToZPackage(package, fieldInfo.GetValue(value));
					}
					return;
				}
			}
			ZRpc.Serialize(new object[1] { value }, ref package);
		}

		private static object ReadValueWithTypeFromZPackage(ZPackage package, Type type)
		{
			if ((object)type != null && type.IsValueType && !type.IsPrimitive && !type.IsEnum)
			{
				FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				int num = package.ReadInt();
				if (num != fields.Length)
				{
					throw new InvalidDeserializationTypeException
					{
						received = $"(field count: {num})",
						expected = $"(field count: {fields.Length})"
					};
				}
				object uninitializedObject = FormatterServices.GetUninitializedObject(type);
				FieldInfo[] array = fields;
				foreach (FieldInfo fieldInfo in array)
				{
					string text = package.ReadString();
					if (text != GetZPackageTypeString(fieldInfo.FieldType))
					{
						throw new InvalidDeserializationTypeException
						{
							received = text,
							expected = GetZPackageTypeString(fieldInfo.FieldType),
							field = fieldInfo.Name
						};
					}
					fieldInfo.SetValue(uninitializedObject, ReadValueWithTypeFromZPackage(package, fieldInfo.FieldType));
				}
				return uninitializedObject;
			}
			if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<, >))
			{
				int num2 = package.ReadInt();
				IDictionary dictionary = (IDictionary)Activator.CreateInstance(type);
				Type type2 = typeof(KeyValuePair<, >).MakeGenericType(type.GenericTypeArguments);
				FieldInfo field = type2.GetField("key", BindingFlags.Instance | BindingFlags.NonPublic);
				FieldInfo field2 = type2.GetField("value", BindingFlags.Instance | BindingFlags.NonPublic);
				for (int j = 0; j < num2; j++)
				{
					object obj = ReadValueWithTypeFromZPackage(package, type2);
					dictionary.Add(field.GetValue(obj), field2.GetValue(obj));
				}
				return dictionary;
			}
			if (type != typeof(List<string>) && type.IsGenericType)
			{
				Type type3 = typeof(ICollection<>).MakeGenericType(type.GenericTypeArguments[0]);
				if ((object)type3 != null && type3.IsAssignableFrom(type))
				{
					int num3 = package.ReadInt();
					object obj2 = Activator.CreateInstance(type);
					MethodInfo method = type3.GetMethod("Add");
					for (int k = 0; k < num3; k++)
					{
						method.Invoke(obj2, new object[1] { ReadValueWithTypeFromZPackage(package, type.GenericTypeArguments[0]) });
					}
					return obj2;
				}
			}
			ParameterInfo parameterInfo = (ParameterInfo)FormatterServices.GetUninitializedObject(typeof(ParameterInfo));
			AccessTools.DeclaredField(typeof(ParameterInfo), "ClassImpl").SetValue(parameterInfo, type);
			List<object> source = new List<object>();
			ZRpc.Deserialize(new ParameterInfo[2] { null, parameterInfo }, package, ref source);
			return source.First();
		}
	}
	[HarmonyPatch]
	[PublicAPI]
	internal class VersionCheck
	{
		private static readonly HashSet<VersionCheck> versionChecks;

		private static readonly Dictionary<string, string> notProcessedNames;

		public string Name;

		private string? displayName;

		private string? currentVersion;

		private string? minimumRequiredVersion;

		public bool ModRequired = true;

		private string? ReceivedCurrentVersion;

		private string? ReceivedMinimumRequiredVersion;

		private readonly List<ZRpc> ValidatedClients = new List<ZRpc>();

		private ConfigSync? ConfigSync;

		public string DisplayName
		{
			get
			{
				return displayName ?? Name;
			}
			set
			{
				displayName = value;
			}
		}

		public string CurrentVersion
		{
			get
			{
				return currentVersion ?? "0.0.0";
			}
			set
			{
				currentVersion = value;
			}
		}

		public string MinimumRequiredVersion
		{
			get
			{
				return minimumRequiredVersion ?? (ModRequired ? CurrentVersion : "0.0.0");
			}
			set
			{
				minimumRequiredVersion = value;
			}
		}

		private static void PatchServerSync()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			Patches patchInfo = PatchProcessor.GetPatchInfo((MethodBase)AccessTools.DeclaredMethod(typeof(ZNet), "Awake", (Type[])null, (Type[])null));
			if (patchInfo != null && patchInfo.Postfixes.Count((Patch p) => p.PatchMethod.DeclaringType == typeof(ConfigSync.RegisterRPCPatch)) > 0)
			{
				return;
			}
			Harmony val = new Harmony("org.bepinex.helpers.ServerSync");
			foreach (Type item in from t in typeof(ConfigSync).GetNestedTypes(BindingFlags.NonPublic).Concat(new Type[1] { typeof(VersionCheck) })
				where t.IsClass
				select t)
			{
				val.PatchAll(item);
			}
		}

		static VersionCheck()
		{
			versionChecks = new HashSet<VersionCheck>();
			notProcessedNames = new Dictionary<string, string>();
			typeof(ThreadingHelper).GetMethod("StartSyncInvoke").Invoke(ThreadingHelper.Instance, new object[1]
			{
				new Action(PatchServerSync)
			});
		}

		public VersionCheck(string name)
		{
			Name = name;
			ModRequired = true;
			versionChecks.Add(this);
		}

		public VersionCheck(ConfigSync configSync)
		{
			ConfigSync = configSync;
			Name = ConfigSync.Name;
			versionChecks.Add(this);
		}

		public void Initialize()
		{
			ReceivedCurrentVersion = null;
			ReceivedMinimumRequiredVersion = null;
			if (ConfigSync != null)
			{
				Name = ConfigSync.Name;
				DisplayName = ConfigSync.DisplayName;
				CurrentVersion = ConfigSync.CurrentVersion;
				MinimumRequiredVersion = ConfigSync.MinimumRequiredVersion;
				ModRequired = ConfigSync.ModRequired;
			}
		}

		private bool IsVersionOk()
		{
			if (ReceivedMinimumRequiredVersion == null || ReceivedCurrentVersion == null)
			{
				return !ModRequired;
			}
			bool flag = new Version(CurrentVersion) >= new Version(ReceivedMinimumRequiredVersion);
			bool flag2 = new Version(ReceivedCurrentVersion) >= new Version(MinimumRequiredVersion);
			return flag && flag2;
		}

		private string ErrorClient()
		{
			if (ReceivedMinimumRequiredVersion == null)
			{
				return "Mod " + DisplayName + " must not be installed.";
			}
			return (new Version(CurrentVersion) >= new Version(ReceivedMinimumRequiredVersion)) ? ("Mod " + DisplayName + " requires maximum " + ReceivedCurrentVersion + ". Installed is version " + CurrentVersion + ".") : ("Mod " + DisplayName + " requires minimum " + ReceivedMinimumRequiredVersion + ". Installed is version " + CurrentVersion + ".");
		}

		private string ErrorServer(ZRpc rpc)
		{
			return "Disconnect: The client (" + rpc.GetSocket().GetHostName() + ") doesn't have the correct " + DisplayName + " version " + MinimumRequiredVersion;
		}

		private string Error(ZRpc? rpc = null)
		{
			return (rpc == null) ? ErrorClient() : ErrorServer(rpc);
		}

		private static VersionCheck[] GetFailedClient()
		{
			return versionChecks.Where((VersionCheck check) => !check.IsVersionOk()).ToArray();
		}

		private static VersionCheck[] GetFailedServer(ZRpc rpc)
		{
			ZRpc rpc2 = rpc;
			return versionChecks.Where((VersionCheck check) => check.ModRequired && !check.ValidatedClients.Contains(rpc2)).ToArray();
		}

		private static void Logout()
		{
			Game.instance.Logout(true, true);
			AccessTools.DeclaredField(typeof(ZNet), "m_connectionStatus").SetValue(null, (object)(ConnectionStatus)3);
		}

		private static void DisconnectClient(ZRpc rpc)
		{
			rpc.Invoke("Error", new object[1] { 3 });
		}

		private static void CheckVersion(ZRpc rpc, ZPackage pkg)
		{
			CheckVersion(rpc, pkg, null);
		}

		private static void CheckVersion(ZRpc rpc, ZPackage pkg, Action<ZRpc, ZPackage>? original)
		{
			string text = pkg.ReadString();
			string text2 = pkg.ReadString();
			string text3 = pkg.ReadString();
			bool flag = false;
			foreach (VersionCheck versionCheck in versionChecks)
			{
				if (!(text != versionCheck.Name))
				{
					Debug.Log((object)("Received " + versionCheck.DisplayName + " version " + text3 + " and minimum version " + text2 + " from the " + (ZNet.instance.IsServer() ? "client" : "server") + "."));
					versionCheck.ReceivedMinimumRequiredVersion = text2;
					versionCheck.ReceivedCurrentVersion = text3;
					if (ZNet.instance.IsServer() && versionCheck.IsVersionOk())
					{
						versionCheck.ValidatedClients.Add(rpc);
					}
					flag = true;
				}
			}
			if (flag)
			{
				return;
			}
			pkg.SetPos(0);
			if (original != null)
			{
				original(rpc, pkg);
				if (pkg.GetPos() == 0)
				{
					notProcessedNames.Add(text, text3);
				}
			}
		}

		[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
		[HarmonyPrefix]
		private static bool RPC_PeerInfo(ZRpc rpc, ZNet __instance)
		{
			VersionCheck[] array = (__instance.IsServer() ? GetFailedServer(rpc) : GetFailedClient());
			if (array.Length == 0)
			{
				return true;
			}
			VersionCheck[] array2 = array;
			foreach (VersionCheck versionCheck in array2)
			{
				Debug.LogWarning((object)versionCheck.Error(rpc));
			}
			if (__instance.IsServer())
			{
				DisconnectClient(rpc);
			}
			else
			{
				Logout();
			}
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
		private static void RegisterAndCheckVersion(ZNetPeer peer, ZNet __instance)
		{
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Expected O, but got Unknown
			notProcessedNames.Clear();
			IDictionary dictionary = (IDictionary)typeof(ZRpc).GetField("m_functions", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(peer.m_rpc);
			if (dictionary.Contains(StringExtensionMethods.GetStableHashCode("ServerSync VersionCheck")))
			{
				object obj = dictionary[StringExtensionMethods.GetStableHashCode("ServerSync VersionCheck")];
				Action<ZRpc, ZPackage> action = (Action<ZRpc, ZPackage>)obj.GetType().GetField("m_action", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj);
				peer.m_rpc.Register<ZPackage>("ServerSync VersionCheck", (Action<ZRpc, ZPackage>)delegate(ZRpc rpc, ZPackage pkg)
				{
					CheckVersion(rpc, pkg, action);
				});
			}
			else
			{
				peer.m_rpc.Register<ZPackage>("ServerSync VersionCheck", (Action<ZRpc, ZPackage>)CheckVersion);
			}
			foreach (VersionCheck versionCheck in versionChecks)
			{
				versionCheck.Initialize();
				if (versionCheck.ModRequired || __instance.IsServer())
				{
					Debug.Log((object)("Sending " + versionCheck.DisplayName + " version " + versionCheck.CurrentVersion + " and minimum version " + versionCheck.MinimumRequiredVersion + " to the " + (__instance.IsServer() ? "client" : "server") + "."));
					ZPackage val = new ZPackage();
					val.Write(versionCheck.Name);
					val.Write(versionCheck.MinimumRequiredVersion);
					val.Write(versionCheck.CurrentVersion);
					peer.m_rpc.Invoke("ServerSync VersionCheck", new object[1] { val });
				}
			}
		}

		[HarmonyPatch(typeof(ZNet), "Disconnect")]
		[HarmonyPrefix]
		private static void RemoveDisconnected(ZNetPeer peer, ZNet __instance)
		{
			if (!__instance.IsServer())
			{
				return;
			}
			foreach (VersionCheck versionCheck in versionChecks)
			{
				versionCheck.ValidatedClients.Remove(peer.m_rpc);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(FejdStartup), "ShowConnectError")]
		private static void ShowConnectionError(FejdStartup __instance)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			if (!__instance.m_connectionFailedPanel.activeSelf || (int)ZNet.GetConnectionStatus() != 3)
			{
				return;
			}
			VersionCheck[] failedClient = GetFailedClient();
			if (failedClient.Length != 0)
			{
				string text = string.Join("\n", failedClient.Select((VersionCheck check) => check.Error()));
				TMP_Text connectionFailedError = __instance.m_connectionFailedError;
				connectionFailedError.text = connectionFailedError.text + "\n" + text;
			}
			foreach (KeyValuePair<string, string> item in notProcessedNames.OrderBy<KeyValuePair<string, string>, string>((KeyValuePair<string, string> kv) => kv.Key))
			{
				if (!__instance.m_connectionFailedError.text.Contains(item.Key))
				{
					TMP_Text connectionFailedError2 = __instance.m_connectionFailedError;
					connectionFailedError2.text = connectionFailedError2.text + "\n" + item.Key + " (Version: " + item.Value + ")";
				}
			}
		}
	}
}

BepInEx/plugins/Professions.dll

Decompiled 9 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using Professions;
using ServerSync;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: Guid("6A561CBA-69AC-46B3-9095-15E99C3121EC")]
[assembly: ComVisible(false)]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCopyright("Copyright ©  2022")]
[assembly: AssemblyProduct("Professions")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyDescription("https://valheim.thunderstore.io/package/Smoothbrain/Professions")]
[assembly: AssemblyTitle("Professions")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[<2a278b7f-9d60-4fb7-af10-0d8334a40073>Embedded]
	internal sealed class <2a278b7f-9d60-4fb7-af10-0d8334a40073>EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[<2a278b7f-9d60-4fb7-af10-0d8334a40073>Embedded]
	[CompilerGenerated]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class <0f599e97-3333-4107-b0b5-ba674f05d9ec>NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public <0f599e97-3333-4107-b0b5-ba674f05d9ec>NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public <0f599e97-3333-4107-b0b5-ba674f05d9ec>NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[<2a278b7f-9d60-4fb7-af10-0d8334a40073>Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class <a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public <a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
[<0f599e97-3333-4107-b0b5-ba674f05d9ec>Nullable(0)]
public class ProfessionPanel : MonoBehaviour
{
	[Header("Stuff To replace")]
	public Image SelectionBKG;

	public Image ContentBkg;

	public Text header;

	public Image linebreak;

	public Text description;

	[Header("Skill Element")]
	public GameObject SkillElementGO;

	public Skill_Element skill_element;

	public RectTransform panelToInstantiateIn;

	public GameObject InstantiateSkill(Sprite icon, string title, string desc, string buttontext)
	{
		GameObject obj = Object.Instantiate<GameObject>(SkillElementGO, (Transform)(object)panelToInstantiateIn);
		Skill_Element component = obj.GetComponent<Skill_Element>();
		component.m_icon.sprite = icon;
		component.m_desc.text = desc;
		component.m_Title.text = title;
		component.buttontxt.text = buttontext;
		return obj;
	}

	public void Awake()
	{
		GameObject gameObject = ((Component)((Component)this).transform.parent).gameObject;
		Image component = ((Component)gameObject.transform.Find("Menu/MenuRoot/Menu/ornament")).gameObject.GetComponent<Image>();
		Image component2 = ((Component)gameObject.transform.Find("Inventory_screen/root/Player/Bkg")).gameObject.GetComponent<Image>();
		TMP_FontAsset font = ((TMP_Text)((Component)gameObject.transform.Find("Inventory_screen/root/Player/Armor/ac_text")).gameObject.GetComponent<TextMeshProUGUI>()).font;
		description.font = font.sourceFontFile;
		header.font = font.sourceFontFile;
		header.text = "Select Profession";
		linebreak.sprite = component.sprite;
		ContentBkg.sprite = component2.sprite;
		((Graphic)ContentBkg).material = ((Graphic)component2).material;
		((Graphic)SelectionBKG).material = ((Graphic)component2).material;
		SelectionBKG.sprite = component2.sprite;
	}
}
[<0f599e97-3333-4107-b0b5-ba674f05d9ec>Nullable(0)]
[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
public class Skill_Element : MonoBehaviour
{
	[Header("Stuff To replace")]
	public Image m_icon;

	public Text m_Title;

	public Text m_desc;

	public Button Select;

	public Text buttontxt;

	public Image[] configOptions;

	public static Sprite blockUsage;

	public static Sprite blockExperience;

	public static GameObject tooltipPrefab;

	public void Awake()
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		Button component = ((Component)((Component)Menu.instance).transform.Find("MenuRoot/ExitConfirm/dialog/Button_yes")).GetComponent<Button>();
		((Selectable)Select).spriteState = ((Selectable)component).spriteState;
		((Selectable)Select).transition = (Transition)2;
		((Component)Select).GetComponent<Image>().sprite = ((Component)component).GetComponent<Image>().sprite;
		Image[] array = configOptions;
		for (int i = 0; i < array.Length; i++)
		{
			((Component)array[i]).GetComponent<UITooltip>().m_tooltipPrefab = tooltipPrefab;
		}
	}

	public void UpdateImageDisplay(global::Professions.Professions.ProfessionToggle toggle)
	{
		int num = 0;
		switch (toggle)
		{
		case global::Professions.Professions.ProfessionToggle.BlockUsage:
		{
			UITooltip component2 = ((Component)configOptions[num]).GetComponent<UITooltip>();
			component2.m_text = "If you do not pick this profession, you will not be able to perform these actions.";
			component2.m_topic = "Usage blocked";
			configOptions[num++].sprite = blockUsage;
			break;
		}
		case global::Professions.Professions.ProfessionToggle.BlockExperience:
		{
			UITooltip component = ((Component)configOptions[num]).GetComponent<UITooltip>();
			component.m_text = "If you do not pick this profession, you will still be able to perform these actions, but will not gain experience.";
			component.m_topic = "Experience blocked";
			configOptions[num++].sprite = blockExperience;
			break;
		}
		}
		for (int i = 0; i < configOptions.Length; i++)
		{
			((Component)configOptions[i]).gameObject.SetActive(i < num);
		}
	}

	public void Toggle(bool selected, bool maxProfessionsReached)
	{
		((Selectable)Select).interactable = global::Professions.Professions.allowUnselect.Value == global::Professions.Professions.Toggle.On;
		if (selected)
		{
			buttontxt.text = ((global::Professions.Professions.allowUnselect.Value == global::Professions.Professions.Toggle.On) ? "Unlearn" : "Selected");
		}
		else if (!maxProfessionsReached)
		{
			buttontxt.text = "Select";
		}
		else
		{
			buttontxt.text = "Unlock";
		}
	}
}
namespace Professions
{
	public static class Blockers
	{
		[<0f599e97-3333-4107-b0b5-ba674f05d9ec>Nullable(0)]
		[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
		[HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")]
		private class BlockBlacksmithing
		{
			private static bool CheckBlacksmithingItem(SharedData item)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Invalid comparison between Unknown and I4
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: Invalid comparison between Unknown and I4
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Invalid comparison between Unknown and I4
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Invalid comparison between Unknown and I4
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Invalid comparison between Unknown and I4
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Invalid comparison between Unknown and I4
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Invalid comparison between Unknown and I4
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Invalid comparison between Unknown and I4
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Invalid comparison between Unknown and I4
				ItemType itemType = item.m_itemType;
				if ((int)itemType != 4 && (int)itemType != 7 && (int)itemType != 12 && (int)itemType != 6 && (int)itemType != 11 && (int)itemType != 5 && (int)itemType != 17 && (int)itemType != 14)
				{
					if ((int)item.m_itemType == 3)
					{
						return !item.m_attack.m_consumeItem;
					}
					return false;
				}
				return true;
			}

			[HarmonyPriority(0)]
			private static void Postfix(InventoryGui __instance)
			{
				if (__instance.InCraftTab() || __instance.InUpradeTab())
				{
					ItemDrop val = __instance.m_selectedRecipe.Key?.m_item;
					if (val != null && CheckBlacksmithingItem(val.m_itemData.m_shared) && !isAllowed(Professions.Profession.Blacksmithing))
					{
						((Selectable)__instance.m_craftButton).interactable = false;
						((Component)__instance.m_craftButton).GetComponentInChildren<Text>().text = "You cannot perform this action, because you are not a blacksmith.";
					}
				}
			}
		}

		[<0f599e97-3333-4107-b0b5-ba674f05d9ec>Nullable(0)]
		[HarmonyPatch]
		[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
		public static class BlockBlacksmithingSmelter
		{
			private static IEnumerable<MethodInfo> TargetMethods()
			{
				return new MethodInfo[2]
				{
					AccessTools.DeclaredMethod(typeof(Smelter), "OnAddOre", (Type[])null, (Type[])null),
					AccessTools.DeclaredMethod(typeof(Smelter), "OnAddFuel", (Type[])null, (Type[])null)
				};
			}

			private static bool Prefix(Smelter __instance, ref bool __result)
			{
				switch (((Component)__instance).GetComponent<Piece>().m_name)
				{
				case "$piece_smelter":
				case "$piece_blastfurnace":
					if (isAllowed(Professions.Profession.Blacksmithing))
					{
						return true;
					}
					__result = false;
					((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a blacksmith.", 0, (Sprite)null);
					return false;
				case "$piece_windmill":
					if (isAllowed(Professions.Profession.Farming))
					{
						return true;
					}
					__result = false;
					((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a farmer.", 0, (Sprite)null);
					return false;
				default:
					return true;
				}
			}
		}

		[HarmonyPatch(typeof(PieceTable), "SetCategory")]
		private class BlockBuilding
		{
			private static bool Prefix(int index)
			{
				if (index != 2 || isAllowed(Professions.Profession.Building))
				{
					return true;
				}
				((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a builder.", 0, (Sprite)null);
				return false;
			}
		}

		[HarmonyPatch(typeof(PieceTable), "PrevCategory")]
		private class BlockBuildingHotkeyPrev
		{
			[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
			private static void Postfix(PieceTable __instance)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Invalid comparison between Unknown and I4
				if ((int)__instance.m_selectedCategory == 2 && !isAllowed(Professions.Profession.Building))
				{
					__instance.PrevCategory();
				}
			}
		}

		[HarmonyPatch(typeof(PieceTable), "NextCategory")]
		private class BlockBuildingHotkeyNext
		{
			[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
			private static void Postfix(PieceTable __instance)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Invalid comparison between Unknown and I4
				if ((int)__instance.m_selectedCategory == 2 && !isAllowed(Professions.Profession.Building))
				{
					__instance.NextCategory();
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")]
		private class BlockCookingCrafting
		{
			[HarmonyPriority(0)]
			[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
			private static void Postfix(InventoryGui __instance)
			{
				ItemDrop val = __instance.m_selectedRecipe.Key?.m_item;
				if (val != null && val.m_itemData.m_shared.m_food > 0f && val.m_itemData.m_shared.m_foodStamina > 0f && !isAllowed(Professions.Profession.Cooking))
				{
					((Selectable)__instance.m_craftButton).interactable = false;
					((Component)__instance.m_craftButton).GetComponentInChildren<Text>().text = "You cannot perform this action, because you are not a cook.";
				}
			}
		}

		[HarmonyPatch(typeof(CookingStation), "Interact")]
		private class BlockCookingStation
		{
			private static bool Prefix()
			{
				if (isAllowed(Professions.Profession.Cooking))
				{
					return true;
				}
				((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a cook.", 0, (Sprite)null);
				return false;
			}
		}

		[HarmonyPatch(typeof(ItemData), "IsEquipable")]
		private class BlockFarmingCultivator
		{
			[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
			private static void Postfix(ItemData __instance, ref bool __result)
			{
				if (__instance.m_shared.m_name == "$item_cultivator" && !isAllowed(Professions.Profession.Farming))
				{
					__result = false;
				}
			}
		}

		[HarmonyPatch(typeof(Pickable), "Interact")]
		private class BlockFarmingPickingPlants
		{
			[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
			private static bool Prefix(Pickable __instance)
			{
				if (!__instance.m_nview.GetZDO().GetBool("Farming Custom Grown", false) || isAllowed(Professions.Profession.Farming))
				{
					return true;
				}
				((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a farmer.", 0, (Sprite)null);
				return false;
			}
		}

		[<0f599e97-3333-4107-b0b5-ba674f05d9ec>Nullable(0)]
		[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
		[HarmonyPatch(typeof(Plant), "Grow")]
		private class SaveCustomGrownPlantState
		{
			private static GameObject TransferInfo(GameObject pickable)
			{
				pickable.GetComponent<ZNetView>().GetZDO().Set("Farming Custom Grown", true);
				return pickable;
			}

			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				MethodInfo transferInfo = AccessTools.DeclaredMethod(typeof(SaveCustomGrownPlantState), "TransferInfo", (Type[])null, (Type[])null);
				MethodInfo instantiator = typeof(Object).GetMethods().First([<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(0)] (MethodInfo m) => m.Name == "Instantiate" && m.IsGenericMethodDefinition && (from p in m.GetParameters().Skip(1)
					select p.ParameterType).SequenceEqual(new Type[2]
				{
					typeof(Vector3),
					typeof(Quaternion)
				})).MakeGenericMethod(typeof(GameObject));
				foreach (CodeInstruction instruction in instructions)
				{
					yield return instruction;
					if (instruction.opcode == OpCodes.Call && CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)instantiator))
					{
						yield return new CodeInstruction(OpCodes.Call, (object)transferInfo);
					}
				}
			}
		}

		[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
		[<0f599e97-3333-4107-b0b5-ba674f05d9ec>Nullable(0)]
		[HarmonyPatch]
		public static class BlockLumberjacking
		{
			private static IEnumerable<MethodInfo> TargetMethods()
			{
				return new MethodInfo[3]
				{
					AccessTools.DeclaredMethod(typeof(TreeLog), "Damage", (Type[])null, (Type[])null),
					AccessTools.DeclaredMethod(typeof(TreeBase), "Damage", (Type[])null, (Type[])null),
					AccessTools.DeclaredMethod(typeof(Destructible), "Damage", (Type[])null, (Type[])null)
				};
			}

			private static void Prefix(object __instance, HitData hit)
			{
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Invalid comparison between Unknown and I4
				if (isAllowed(Professions.Profession.Lumberjacking) || !((Object)(object)hit.GetAttacker() == (Object)(object)Player.m_localPlayer))
				{
					return;
				}
				Destructible val = (Destructible)((__instance is Destructible) ? __instance : null);
				if (val == null || (int)val.m_destructibleType == 2)
				{
					if (!(__instance is TreeLog) && !(__instance is TreeBase))
					{
						hit.m_damage.m_slash = 0f;
					}
					((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a lumberjack.", 0, (Sprite)null);
					hit.m_damage.m_chop = 0f;
				}
			}
		}

		[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
		[<0f599e97-3333-4107-b0b5-ba674f05d9ec>Nullable(0)]
		[HarmonyPatch]
		public static class BlockMining
		{
			private static IEnumerable<MethodInfo> TargetMethods()
			{
				return new MethodInfo[3]
				{
					AccessTools.DeclaredMethod(typeof(MineRock), "Damage", (Type[])null, (Type[])null),
					AccessTools.DeclaredMethod(typeof(MineRock5), "Damage", (Type[])null, (Type[])null),
					AccessTools.DeclaredMethod(typeof(Destructible), "Damage", (Type[])null, (Type[])null)
				};
			}

			private static void Prefix(object __instance, HitData hit)
			{
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: 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_0032: Invalid comparison between Unknown and I4
				//IL_0034: 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_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0043: Invalid comparison between Unknown and I4
				if (isAllowed(Professions.Profession.Mining) || !((Object)(object)hit.GetAttacker() == (Object)(object)Player.m_localPlayer))
				{
					return;
				}
				Destructible val = (Destructible)((__instance is Destructible) ? __instance : null);
				if (val != null)
				{
					DamageModifiers damages = val.m_damages;
					if ((int)damages.m_pickaxe <= 0 || (int)damages.m_chop != 0 || (int)val.m_destructibleType == 2)
					{
						return;
					}
				}
				((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a miner.", 0, (Sprite)null);
				hit.m_damage.m_pickaxe = 0f;
			}
		}

		[HarmonyPatch(typeof(Character), "Damage")]
		private class BlockRanching
		{
			[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
			private static bool Prefix(Character __instance, HitData hit)
			{
				if (!__instance.IsTamed() || isAllowed(Professions.Profession.Ranching) || (Object)(object)hit.GetAttacker() != (Object)(object)Player.m_localPlayer)
				{
					return true;
				}
				((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a rancher.", 0, (Sprite)null);
				return false;
			}
		}

		[HarmonyPatch(typeof(ShipControlls), "Interact")]
		private class BlockSailing
		{
			private static bool Prefix()
			{
				if (isAllowed(Professions.Profession.Sailing))
				{
					return true;
				}
				((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a sailor.", 0, (Sprite)null);
				return false;
			}
		}

		[HarmonyPatch(typeof(CraftingStation), "Interact")]
		private class BlockAlchemyStation
		{
			[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
			private static bool Prefix(CraftingStation __instance)
			{
				if (!((Object)__instance).name.StartsWith("opalchemy", StringComparison.Ordinal) || isAllowed(Professions.Profession.Alchemy))
				{
					return true;
				}
				((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not an alchemist.", 0, (Sprite)null);
				return false;
			}
		}

		[HarmonyPatch(typeof(Incinerator), "OnIncinerate")]
		private class BlockAlchemyIncinerator
		{
			[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
			private static bool Prefix(Incinerator __instance)
			{
				if (!((Object)__instance).name.StartsWith("opcauldron", StringComparison.Ordinal) || isAllowed(Professions.Profession.Alchemy))
				{
					return true;
				}
				((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not an alchemist.", 0, (Sprite)null);
				return false;
			}
		}

		[HarmonyPatch(typeof(CraftingStation), "Interact")]
		private class BlockGemcuttersTable
		{
			[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
			private static bool Prefix(CraftingStation __instance)
			{
				if (!((Object)__instance).name.StartsWith("op_transmution_table", StringComparison.Ordinal) || isAllowed(Professions.Profession.Jewelcrafting))
				{
					return true;
				}
				((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a jeweler.", 0, (Sprite)null);
				return false;
			}
		}

		[HarmonyPatch(typeof(Pickable), "Interact")]
		private class BlockForaging
		{
			private class SkipForagingException : Exception
			{
			}

			[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
			[HarmonyPriority(800)]
			private static void Prefix(Pickable __instance)
			{
				if (__instance.m_respawnTimeMinutes == 0 || ((Object)__instance.m_itemPrefab).name == "Wood" || isAllowed(Professions.Profession.Foraging))
				{
					return;
				}
				((Character)Player.m_localPlayer).Message((MessageType)2, "You cannot perform this action, because you are not a forager.", 0, (Sprite)null);
				throw new SkipForagingException();
			}

			[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
			[return: <0f599e97-3333-4107-b0b5-ba674f05d9ec>Nullable(2)]
			private static Exception Finalizer(Exception __exception)
			{
				if (!(__exception is SkipForagingException))
				{
					return __exception;
				}
				return null;
			}
		}

		[HarmonyPatch(typeof(Minimap), "Explore", new Type[]
		{
			typeof(Vector3),
			typeof(float)
		})]
		private class BlockExploration
		{
			[HarmonyPriority(800)]
			private static bool Prefix()
			{
				return isAllowed(Professions.Profession.Exploration);
			}
		}

		private static bool isAllowed(Professions.Profession profession)
		{
			if (Professions.blockOtherProfessions[profession].Value == Professions.ProfessionToggle.BlockUsage)
			{
				return Professions.selectedProfessions(Player.m_localPlayer).Contains(profession);
			}
			return true;
		}
	}
	[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
	[<0f599e97-3333-4107-b0b5-ba674f05d9ec>Nullable(0)]
	public static class Helper
	{
		private static byte[] ReadEmbeddedFileBytes(string name)
		{
			using MemoryStream memoryStream = new MemoryStream();
			Assembly.GetExecutingAssembly().GetManifestResourceStream("Professions." + name)?.CopyTo(memoryStream);
			return memoryStream.ToArray();
		}

		private static Texture2D loadTexture(string name)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_001f: Expected O, but got Unknown
			Texture2D val = new Texture2D(0, 0);
			ImageConversion.LoadImage(val, ReadEmbeddedFileBytes("icons." + name));
			return val;
		}

		public static Sprite loadSprite(string name, int width, int height)
		{
			//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)
			return Sprite.Create(loadTexture(name), new Rect(0f, 0f, (float)width, (float)height), Vector2.zero);
		}

		public static string getHumanFriendlyTime(int seconds)
		{
			TimeSpan timeSpan = TimeSpan.FromSeconds(seconds);
			if (timeSpan.TotalSeconds < 60.0)
			{
				return "less than 1 minute";
			}
			string text = "";
			if (timeSpan.TotalDays >= 1.0)
			{
				text = text + $"{(int)timeSpan.TotalDays} day" + ((timeSpan.TotalDays >= 2.0) ? "s" : "");
			}
			if (timeSpan.Hours >= 1)
			{
				if (timeSpan.TotalDays >= 1.0)
				{
					text += " and ";
				}
				text = text + $"{timeSpan.Hours} hour" + ((timeSpan.Hours >= 2) ? "s" : "");
			}
			if (timeSpan.Minutes >= 1)
			{
				if (timeSpan.TotalDays >= 1.0 || timeSpan.Hours >= 1)
				{
					text += " and ";
				}
				text = text + $"{timeSpan.Minutes} minute" + ((timeSpan.Minutes >= 2) ? "s" : "");
			}
			return text;
		}
	}
	[BepInPlugin("org.bepinex.plugins.professions", "Professions", "1.4.1")]
	[<0f599e97-3333-4107-b0b5-ba674f05d9ec>Nullable(0)]
	[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
	[BepInIncompatibility("org.bepinex.plugins.valheim_plus")]
	public class Professions : BaseUnityPlugin
	{
		[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(0)]
		public enum Toggle
		{
			On = 1,
			Off = 0
		}

		[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(0)]
		public enum ProfessionToggle
		{
			Ignored,
			[Description("Block Experience")]
			BlockExperience,
			[Description("Block Usage")]
			BlockUsage
		}

		[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(0)]
		public enum Profession
		{
			Blacksmithing,
			Building,
			Cooking,
			Farming,
			Lumberjacking,
			Mining,
			Ranching,
			Sailing,
			Alchemy,
			Jewelcrafting,
			Foraging,
			Exploration
		}

		[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(0)]
		private class ConfigurationManagerAttributes
		{
			[UsedImplicitly]
			public bool? Browsable;

			[UsedImplicitly]
			public int? Order;
		}

		[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(0)]
		[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
		private static class AddRPCs
		{
			[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
			private static void Postfix(ZNet __instance, ZNetPeer peer)
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Expected O, but got Unknown
				if (__instance.IsServer())
				{
					peer.m_rpc.Register("Professions GetServerTime", new Method(onServerTimeRequest));
				}
				else
				{
					peer.m_rpc.Register<long>("Professions GetServerTime", (Action<ZRpc, long>)onServerTimeReceived);
				}
			}
		}

		[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(0)]
		[HarmonyPatch(typeof(Menu), "Update")]
		private class PreventMainMenu
		{
			public static bool AllowMainMenu = true;

			private static bool Prefix()
			{
				if (!professionPanelInstance.activeSelf)
				{
					return AllowMainMenu;
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(Hud), "Awake")]
		[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(0)]
		public static class InstantiateSelectPanel
		{
			[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
			private static void Prefix(Hud __instance)
			{
				Transform transform = ((Component)((Component)__instance).gameObject.GetComponentInParent<Localize>()).gameObject.transform;
				professionPanelInstance = Object.Instantiate<GameObject>(professionPanel, transform, false);
				professionPanelInstance.SetActive(false);
				professionPanelInstance.transform.SetSiblingIndex(((Component)MessageHud.instance).transform.GetSiblingIndex());
				Skill_Element.tooltipPrefab = InventoryGui.instance.m_playerGrid.m_elementPrefab.GetComponent<UITooltip>().m_tooltipPrefab;
			}
		}

		[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(0)]
		[HarmonyPatch(typeof(Skills), "Awake")]
		public static class PopulateSelectPanel
		{
			[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
			private static void Postfix(Skills __instance)
			{
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_0076: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cd: Expected I4, but got Unknown
				//IL_0143: Unknown result type (might be due to invalid IL or missing references)
				//IL_014d: Expected O, but got Unknown
				//IL_0099: Unknown result type (might be due to invalid IL or missing references)
				if (!Object.op_Implicit((Object)(object)Professions.professionPanelInstance))
				{
					return;
				}
				GameObject professionPanelInstance = Professions.professionPanelInstance;
				ProfessionPanel professionPanel = ((professionPanelInstance != null) ? professionPanelInstance.GetComponent<ProfessionPanel>() : null);
				if (professionPanel == null || ((Transform)professionPanel.panelToInstantiateIn).childCount != 0)
				{
					return;
				}
				professionPanelElements.Clear();
				Profession[] array = (Profession[])Enum.GetValues(typeof(Profession));
				foreach (Profession profession in array)
				{
					SkillType skillType = fromProfession(profession);
					Skill skill = __instance.GetSkill(skillType);
					if (skill.m_info == null)
					{
						__instance.m_skillData.Remove(skillType);
						continue;
					}
					GameObject val = professionPanel.InstantiateSkill(skill.m_info.m_icon, Localization.instance.Localize("$skill_" + (int)fromProfession(profession)), professionDescriptions[profession], "Select");
					professionPanelElements[profession] = val;
					val.SetActive(blockOtherProfessions[profession].Value != ProfessionToggle.Ignored);
					((UnityEvent)val.GetComponent<Skill_Element>().Select.onClick).AddListener((UnityAction)delegate
					{
						//IL_00af: Unknown result type (might be due to invalid IL or missing references)
						//IL_0314: Unknown result type (might be due to invalid IL or missing references)
						//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
						//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
						//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
						//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
						if (selectedProfessions(Player.m_localPlayer).Contains(profession))
						{
							if (allowUnselect.Value == Toggle.On && professionChangeCooldown.Value > 0f && Player.m_localPlayer.m_knownStations.TryGetValue("Professions LastProfessionChange", out var value))
							{
								int num = value + (int)(professionChangeCooldown.Value * 3600f) - (int)((DateTimeOffset)serverTime).ToUnixTimeSeconds();
								if (num > 0)
								{
									((Character)Player.m_localPlayer).Message((MessageType)2, "You can change your profession in " + Helper.getHumanFriendlyTime(num) + ".", 0, (Sprite)null);
									return;
								}
							}
							Player.m_localPlayer.m_skills.m_skillData.Remove(skillType);
							Player.m_localPlayer.m_knownStations["Professions LastProfessionChange"] = (int)((DateTimeOffset)serverTime).ToUnixTimeSeconds();
						}
						else
						{
							if (!Player.m_localPlayer.m_knownStations.TryGetValue("Professions extraProfessionsSlots", out var value2))
							{
								Player.m_localPlayer.m_knownStations["Professions extraProfessionsSlots"] = 0;
								value2 = 0;
							}
							if (selectedProfessions(Player.m_localPlayer).Count >= maximumAllowedProfessions.Value + value2)
							{
								if (((Humanoid)Player.m_localPlayer).GetInventory() != null)
								{
									ItemData val2 = null;
									ItemData val3 = null;
									int num2 = Mathf.CeilToInt(Mathf.Pow(1.6f, (float)(maximumAllowedProfessions.Value + value2)));
									for (int j = 0; j < ((Humanoid)Player.m_localPlayer).GetInventory().GetHeight(); j++)
									{
										if (val3 != null)
										{
											break;
										}
										for (int k = 0; k < ((Humanoid)Player.m_localPlayer).GetInventory().GetWidth(); k++)
										{
											val2 = ((Humanoid)Player.m_localPlayer).GetInventory().GetItemAt(k, j);
											if (val2 != null)
											{
												if (val2.m_shared.m_name.ToLower() == "craftsman trophy" && ((Humanoid)Player.m_localPlayer).GetInventory().GetItemAt(k, j).m_stack >= num2)
												{
													val3 = val2;
												}
												if (val3 != null)
												{
													break;
												}
											}
										}
									}
									if (val3 == null)
									{
										((Character)Player.m_localPlayer).Message((MessageType)2, "You need Craftsman Trophy x " + num2.ToString("#") + ".", 0, (Sprite)null);
									}
									else
									{
										for (int l = 0; l < num2; l++)
										{
											Player localPlayer = Player.m_localPlayer;
											if (localPlayer != null)
											{
												((Humanoid)localPlayer).GetInventory().RemoveOneItem(val3);
											}
										}
										Player.m_localPlayer.StartEmote("cheer", true);
										((Character)Player.m_localPlayer).Message((MessageType)2, "Consumed Craftsman Trophy x " + num2.ToString("#") + ".", 0, (Sprite)null);
										Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_Potion_stamina_medium"), ((Component)Player.m_localPlayer).transform.position, Quaternion.identity);
										Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("vfx_WishbonePing"), ((Component)Player.m_localPlayer).transform.position, Quaternion.identity);
										Player.m_localPlayer.m_knownStations["Professions extraProfessionsSlots"] = value2 + 1;
									}
								}
							}
							else
							{
								Player.m_localPlayer.m_skills.GetSkill(skillType).m_level = 1f;
							}
						}
						UpdateSelectPanelSelections();
					});
				}
			}
		}

		[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(0)]
		[HarmonyPatch(typeof(Skills), "RaiseSkill")]
		private class PreventExperience
		{
			[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
			private static bool Prefix(Skills __instance, SkillType skillType)
			{
				//IL_0000: 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)
				Profession? profession = fromSkill(skillType);
				if (profession.HasValue)
				{
					Profession valueOrDefault = profession.GetValueOrDefault();
					if (!(__instance.GetSkillFactor(skillType) > 0f))
					{
						return blockOtherProfessions[valueOrDefault].Value == ProfessionToggle.Ignored;
					}
				}
				return true;
			}
		}

		[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(0)]
		[HarmonyPatch]
		private class DisablePlayerInputInProfessionMenu
		{
			[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(1)]
			private static IEnumerable<MethodInfo> TargetMethods()
			{
				return new MethodInfo[2]
				{
					AccessTools.DeclaredMethod(typeof(StoreGui), "IsVisible", (Type[])null, (Type[])null),
					AccessTools.DeclaredMethod(typeof(TextInput), "IsVisible", (Type[])null, (Type[])null)
				};
			}

			private static void Postfix(ref bool __result)
			{
				GameObject professionPanelInstance = Professions.professionPanelInstance;
				if (professionPanelInstance != null && professionPanelInstance.activeSelf)
				{
					__result = true;
				}
			}
		}

		private const string ModName = "Professions";

		private const string ModVersion = "1.4.1";

		private const string ModGUID = "org.bepinex.plugins.professions";

		private static readonly ConfigSync configSync = new ConfigSync("org.bepinex.plugins.professions")
		{
			DisplayName = "Professions",
			CurrentVersion = "1.4.1",
			MinimumRequiredVersion = "1.4.1"
		};

		private static ConfigEntry<Toggle> serverConfigLocked = null;

		private static ConfigEntry<KeyboardShortcut> professionPanelHotkey = null;

		private static ConfigEntry<int> maximumAllowedProfessions = null;

		public static ConfigEntry<Toggle> allowUnselect = null;

		private static ConfigEntry<float> professionChangeCooldown = null;

		public static readonly Dictionary<Profession, ConfigEntry<ProfessionToggle>> blockOtherProfessions = new Dictionary<Profession, ConfigEntry<ProfessionToggle>>();

		private static DateTime serverTime = DateTime.Now;

		private int configOrder;

		private static readonly Dictionary<Profession, string> professionDescriptions = new Dictionary<Profession, string>
		{
			{
				Profession.Blacksmithing,
				"A blacksmith uses the smelter and forge to smelt ore and craft armor and weapons."
			},
			{
				Profession.Building,
				"A builder uses the hammer to construct floors, walls and roofs for shelter."
			},
			{
				Profession.Cooking,
				"A cook creates lavish meals."
			},
			{
				Profession.Farming,
				"A farmer uses the cultivator to cultivate land to plant crops and harvest them."
			},
			{
				Profession.Lumberjacking,
				"A lumberjack uses an axe to cut trees to collect all kind of woods."
			},
			{
				Profession.Mining,
				"A miner uses a pickaxe to mine stone and ore."
			},
			{
				Profession.Ranching,
				"A rancher can tame certain animals and breed them for their meat."
			},
			{
				Profession.Sailing,
				"A sailor uses ships to explore the vast ocean and discover new islands."
			},
			{
				Profession.Alchemy,
				"An alchemist creates powerful potions, flasks and elixirs."
			},
			{
				Profession.Jewelcrafting,
				"A jeweler cuts powerful magic gems and adds sockets to equipment."
			},
			{
				Profession.Foraging,
				"A forager collects berries and mushrooms."
			},
			{
				Profession.Exploration,
				"An explorer explores the world and searches treasure chests."
			}
		};

		private static GameObject professionPanel = null;

		[<0f599e97-3333-4107-b0b5-ba674f05d9ec>Nullable(2)]
		private static GameObject professionPanelInstance;

		private static readonly Dictionary<Profession, GameObject> professionPanelElements = new Dictionary<Profession, GameObject>();

		[<0f599e97-3333-4107-b0b5-ba674f05d9ec>Nullable(2)]
		private readonly Assembly bepinexConfigManager = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault([<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(0)] (Assembly a) => a.GetName().Name == "ConfigurationManager");

		private ConfigEntry<T> config<[<0f599e97-3333-4107-b0b5-ba674f05d9ec>Nullable(2)] T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			description = new ConfigDescription(description.Description, description.AcceptableValues, CollectionExtensions.AddItem<object>((IEnumerable<object>)description.Tags, (object)new ConfigurationManagerAttributes
			{
				Order = configOrder--
			}).ToArray());
			ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, description);
			configSync.AddConfigEntry<T>(val).SynchronizedConfig = synchronizedSetting;
			return val;
		}

		private ConfigEntry<T> config<[<0f599e97-3333-4107-b0b5-ba674f05d9ec>Nullable(2)] T>(string group, string name, T value, string description, bool synchronizedSetting = true)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting);
		}

		private static SkillType fromProfession(Profession profession)
		{
			return (SkillType)Math.Abs(StringExtensionMethods.GetStableHashCode(profession.ToString()));
		}

		private static Profession? fromSkill(SkillType skill)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			return ((IEnumerable<Profession>)(Profession[])Enum.GetValues(typeof(Profession))).Select((Func<Profession, Profession?>)((Profession p) => p)).FirstOrDefault((Profession? p) => skill == fromProfession(p.Value));
		}

		public void Awake()
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Expected O, but got Unknown
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Type configManagerType = bepinexConfigManager?.GetType("ConfigurationManager.ConfigurationManager");
				object configManager = ((configManagerType == null) ? null : Chainloader.ManagerObject.GetComponent(configManagerType));
				serverConfigLocked = config("1 - General", "Lock Configuration", Toggle.On, "If on, the configuration is locked and can be changed by server admins only.");
				configSync.AddLockingConfigEntry<Toggle>(serverConfigLocked);
				maximumAllowedProfessions = config("1 - General", "Maximum Number of Professions", 1, new ConfigDescription("Sets the maximum number of professions a player is allowed to have at the same time.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 5), Array.Empty<object>()));
				allowUnselect = config("1 - General", "Allow Profession Change", Toggle.Off, "If on, players can unselect professions and select new ones.");
				ConfigurationManagerAttributes changeCooldownAttributes = new ConfigurationManagerAttributes
				{
					Browsable = (allowUnselect.Value == Toggle.On)
				};
				allowUnselect.SettingChanged += [<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(0)] (object _, EventArgs _) =>
				{
					changeCooldownAttributes.Browsable = allowUnselect.Value == Toggle.On;
					reloadConfigDisplay();
				};
				professionChangeCooldown = config("1 - General", "Profession Change Cooldown", 0f, new ConfigDescription("Time between profession changes. Uses real time hours. Use 0 to disable this.", (AcceptableValueBase)null, new object[1] { changeCooldownAttributes }));
				professionPanelHotkey = config<KeyboardShortcut>("1 - General", "Profession Panel Hotkey", new KeyboardShortcut((KeyCode)112, Array.Empty<KeyCode>()), "Key or key combination to open the profession panel.", synchronizedSetting: false);
				Profession[] array = (Profession[])Enum.GetValues(typeof(Profession));
				foreach (Profession profession in array)
				{
					blockOtherProfessions[profession] = config("2 - Professions", $"{profession} behaviour", ProfessionToggle.BlockExperience, "Ignored: The skill is not considered a profession and can be used by everyone.\nBlock Experience: If you did not pick the skills profession, you will not get any experience for this skill.\nBlock Usage: If you did not pick the skills profession, you will not be able to perform the action that would grant you experience for the skill.");
					blockOtherProfessions[profession].SettingChanged += [<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(0)] (object _, EventArgs _) =>
					{
						if (professionPanelElements.TryGetValue(profession, out var value))
						{
							value.SetActive(blockOtherProfessions[profession].Value != ProfessionToggle.Ignored);
						}
					};
				}
				Assembly executingAssembly = Assembly.GetExecutingAssembly();
				new Harmony("org.bepinex.plugins.professions").PatchAll(executingAssembly);
				professionPanel = LoadAssetBundle("professionSelect").LoadAsset<GameObject>("ProfessionPanel");
				Skill_Element.blockExperience = Helper.loadSprite("blockxp.png", 20, 20);
				Skill_Element.blockUsage = Helper.loadSprite("blockusage.png", 20, 20);
				void reloadConfigDisplay()
				{
					configManagerType?.GetMethod("BuildSettingList").Invoke(configManager, Array.Empty<object>());
				}
			}
			catch (Exception arg)
			{
				Debug.LogError((object)$"Professions Awake failed. Shutting down, to prevent further issues with the professions. Exception:\n{arg}");
				Application.Quit();
			}
		}

		[<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(2)]
		private static void onServerTimeReceived(ZRpc rpc, long time)
		{
			serverTime = new DateTime(time);
		}

		private static void onServerTimeRequest(ZRpc rpc)
		{
			rpc.Invoke("Professions GetServerTime", new object[1] { DateTime.Now.Ticks });
		}

		private static void requestServerTime()
		{
			if (ZNet.instance.IsServer())
			{
				onServerTimeReceived(null, DateTime.Now.Ticks);
			}
			else
			{
				ZNet.instance.GetServerPeer().m_rpc.Invoke("Professions GetServerTime", Array.Empty<object>());
			}
		}

		private void Update()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			PreventMainMenu.AllowMainMenu = true;
			if (Player.m_localPlayer == null)
			{
				return;
			}
			KeyboardShortcut value = professionPanelHotkey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown() && (professionPanelInstance.activeSelf || ((Character)Player.m_localPlayer).TakeInput()))
			{
				professionPanelInstance.SetActive(!professionPanelInstance.activeSelf);
				if (professionPanelInstance.activeSelf)
				{
					UpdateSelectPanelSelections();
					requestServerTime();
				}
			}
			if (professionPanelInstance.activeSelf && Input.GetKey((KeyCode)27))
			{
				professionPanelInstance.SetActive(false);
				PreventMainMenu.AllowMainMenu = false;
			}
		}

		private static void UpdateSelectPanelSelections()
		{
			List<Profession> list = selectedProfessions(Player.m_localPlayer);
			if (!Player.m_localPlayer.m_knownStations.TryGetValue("Professions extraProfessionsSlots", out var value))
			{
				Player.m_localPlayer.m_knownStations["Professions extraProfessionsSlots"] = 0;
				value = 0;
			}
			foreach (KeyValuePair<Profession, GameObject> professionPanelElement in professionPanelElements)
			{
				Skill_Element component = professionPanelElement.Value.GetComponent<Skill_Element>();
				component.Toggle(list.Contains(professionPanelElement.Key), list.Count >= maximumAllowedProfessions.Value + value);
				component.UpdateImageDisplay(blockOtherProfessions[professionPanelElement.Key].Value);
			}
			int num = Mathf.CeilToInt(Mathf.Pow(1.6f, (float)(maximumAllowedProfessions.Value + value)));
			professionPanelInstance.GetComponent<ProfessionPanel>().description.text = string.Format("You have {0} / {1} professions selected.\nYou need Craftsman Trophy x {2} to unlock another profession.\nYou are{3} allowed to change your professions{4}.", list.Count, maximumAllowedProfessions.Value + value, num, (allowUnselect.Value == Toggle.Off) ? " not" : "", (professionChangeCooldown.Value > 0f && allowUnselect.Value == Toggle.On) ? (" every " + Helper.getHumanFriendlyTime((int)(professionChangeCooldown.Value * 3600f))) : "");
		}

		private static AssetBundle LoadAssetBundle(string bundleName)
		{
			string name = typeof(Professions).Assembly.GetManifestResourceNames().Single([<a759d5d3-f43a-4d2a-8046-86fb09ec6a69>NullableContext(0)] (string s) => s.EndsWith(bundleName));
			return AssetBundle.LoadFromStream(typeof(Professions).Assembly.GetManifestResourceStream(name));
		}

		public static List<Profession> selectedProfessions(Player player)
		{
			return selectedProfessions(player.m_skills);
		}

		private static List<Profession> selectedProfessions(Skills skills)
		{
			Skill value;
			return ((Profession[])Enum.GetValues(typeof(Profession))).Where((Profession profession) => blockOtherProfessions[profession].Value != 0 && skills.m_skillData.TryGetValue(fromProfession(profession), out value) && value.m_level > 0f).ToList();
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[Microsoft.CodeAnalysis.Embedded]
	[CompilerGenerated]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	[Microsoft.CodeAnalysis.Embedded]
	[CompilerGenerated]
	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.configValues.Count, parsedConfigs.customValues.Count, (isServer || clientUpdate) ? $"client {sender}" : "the server", DisplayName ?? Name));
				if (!isServer)
				{
					serverLockedSettingChanged();
				}
				return true;
			}
			finally
			{
				ProcessingServerUpdate = false;
			}
		}

		private ParsedConfigs ReadConfigsFromPackage(ZPackage package)
		{
			ParsedConfigs parsedConfigs = new ParsedConfigs();
			Dictionary<string, OwnConfigEntryBase> dictionary = allConfigs.Where((OwnConfigEntryBase c) => c.SynchronizedConfig).ToDictionary((OwnConfigEntryBase c) => c.BaseConfig.Definition.Section + "_" + c.BaseConfig.Definition.Key, (OwnConfigEntryBase c) => c);
			Dictionary<string, CustomSyncedValueBase> dictionary2 = allCustomValues.ToDictionary((CustomSyncedValueBase c) => c.Identifier, (CustomSyncedValueBase c) => c);
			int num = package.ReadInt();
			for (int i = 0; i < num; i++)
			{
				string text = package.ReadString();
				string text2 = package.ReadString();
				string text3 = package.ReadString();
				Type type = Type.GetType(text3);
				if (text3 == "" || type != null)
				{
					object obj;
					try
					{
						obj = ((text3 == "") ? null : ReadValueWithTypeFromZPackage(package, type));
					}
					catch (InvalidDeserializationTypeException ex)
					{
						Debug.LogWarning((object)("Got unexpected struct internal type " + ex.received + " for field " + ex.field + " struct " + text3 + " for " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ", expecting " + ex.expected));
						continue;
					}
					OwnConfigEntryBase value2;
					if (text == "Internal")
					{
						CustomSyncedValueBase value;
						if (text2 == "serverversion")
						{
							if (obj?.ToString() != CurrentVersion)
							{
								Debug.LogWarning((object)("Received server version is not equal: server version = " + (obj?.ToString() ?? "null") + "; local version = " + (CurrentVersion ?? "unknown")));
							}
						}
						else if (text2 == "lockexempt")
						{
							if (obj is bool flag)
							{
								lockExempt = flag;
							}
						}
						else if (dictionary2.TryGetValue(text2, out value))
						{
							if ((text3 == "" && (!value.Type.IsValueType || Nullable.GetUnderlyingType(value.Type) != null)) || GetZPackageTypeString(value.Type) == text3)
							{
								parsedConfigs.customValues[value] = obj;
								continue;
							}
							Debug.LogWarning((object)("Got unexpected type " + text3 + " for internal value " + text2 + " for mod " + (DisplayName ?? Name) + ", expecting " + value.Type.AssemblyQualifiedName));
						}
					}
					else if (dictionary.TryGetValue(text + "_" + text2, out value2))
					{
						Type type2 = configType(value2.BaseConfig);
						if ((text3 == "" && (!type2.IsValueType || Nullable.GetUnderlyingType(type2) != null)) || GetZPackageTypeString(type2) == text3)
						{
							parsedConfigs.configValues[value2] = obj;
							continue;
						}
						Debug.LogWarning((object)("Got unexpected type " + text3 + " for " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ", expecting " + type2.AssemblyQualifiedName));
					}
					else
					{
						Debug.LogWarning((object)("Received unknown config entry " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ". This may happen if client and server versions of the mod do not match."));
					}
					continue;
				}
				Debug.LogWarning((object)("Got invalid type " + text3 + ", abort reading of received configs"));
				return new ParsedConfigs();
			}
			return parsedConfigs;
		}

		private static bool isWritableConfig(OwnConfigEntryBase config)
		{
			OwnConfigEntryBase config2 = config;
			ConfigSync configSync = configSyncs.FirstOrDefault((ConfigSync cs) => cs.allConfigs.Contains(config2));
			if (configSync == null)
			{
				return true;
			}
			return configSync.IsSourceOfTruth || !config2.SynchronizedConfig || config2.LocalBaseValue == null || (!configSync.IsLocked && (config2 != configSync.lockedConfig || lockExempt));
		}

		private void serverLockedSettingChanged()
		{
			foreach (OwnConfigEntryBase allConfig in allConfigs)
			{
				configAttribute<ConfigurationManagerAttributes>(allConfig.BaseConfig).ReadOnly = !isWritableConfig(allConfig);
			}
		}

		private void resetConfigsFromServer()
		{
			foreach (OwnConfigEntryBase item in allConfigs.Where((OwnConfigEntryBase config) => config.LocalBaseValue != null))
			{
				item.BaseConfig.BoxedValue = item.LocalBaseValue;
				item.LocalBaseValue = null;
			}
			foreach (CustomSyncedValueBase item2 in allCustomValues.Where((CustomSyncedValueBase config) => config.LocalBaseValue != null))
			{
				item2.BoxedValue = item2.LocalBaseValue;
				item2.LocalBaseValue = null;
			}
			lockedConfigChanged -= serverLockedSettingChanged;
			serverLockedSettingChanged();
		}

		private IEnumerator<bool> distributeConfigToPeers(ZNetPeer peer, ZPackage package)
		{
			ZNetPeer peer2 = peer;
			ZRoutedRpc rpc = ZRoutedRpc.instance;
			if (rpc == null)
			{
				yield break;
			}
			byte[] data = package.GetArray();
			if (data != null && data.LongLength > 250000)
			{
				int fragments = (int)(1 + (data.LongLength - 1) / 250000);
				long packageIdentifier = ++packageCounter;
				int fragment = 0;
				while (fragment < fragments)
				{
					foreach (bool item in waitForQueue())
					{
						yield return item;
					}
					if (peer2.m_socket.IsConnected())
					{
						ZPackage fragmentedPackage = new ZPackage();
						fragmentedPackage.Write((byte)2);
						fragmentedPackage.Write(packageIdentifier);
						fragmentedPackage.Write(fragment);
						fragmentedPackage.Write(fragments);
						fragmentedPackage.Write(data.Skip(250000 * fragment).Take(250000).ToArray());
						SendPackage(fragmentedPackage);
						if (fragment != fragments - 1)
						{
							yield return true;
						}
						int num = fragment + 1;
						fragment = num;
						continue;
					}
					break;
				}
				yield break;
			}
			foreach (bool item2 in waitForQueue())
			{
				yield return item2;
			}
			SendPackage(package);
			void SendPackage(ZPackage pkg)
			{
				string text = Name + " ConfigSync";
				if (isServer)
				{
					peer2.m_rpc.Invoke(text, new object[1] { pkg });
				}
				else
				{
					rpc.InvokeRoutedRPC(peer2.m_server ? 0 : peer2.m_uid, text, new object[1] { pkg });
				}
			}
			IEnumerable<bool> waitForQueue()
			{
				float timeout = Time.time + 30f;
				while (peer2.m_socket.GetSendQueueSize() > 20000)
				{
					if (Time.time > timeout)
					{
						Debug.Log((object)$"Disconnecting {peer2.m_uid} after 30 seconds config sending timeout");
						peer2.m_rpc.Invoke("Error", new object[1] { (object)(ConnectionStatus)5 });
						ZNet.instance.Disconnect(peer2);
						break;
					}
					yield return false;
				}
			}
		}

		private IEnumerator sendZPackage(long target, ZPackage package)
		{
			if (!Object.op_Implicit((Object)(object)ZNet.instance))
			{
				return Enumerable.Empty<object>().GetEnumerator();
			}
			List<ZNetPeer> list = (List<ZNetPeer>)AccessTools.DeclaredField(typeof(ZRoutedRpc), "m_peers").GetValue(ZRoutedRpc.instance);
			if (target != ZRoutedRpc.Everybody)
			{
				list = list.Where((ZNetPeer p) => p.m_uid == target).ToList();
			}
			return sendZPackage(list, package);
		}

		private IEnumerator sendZPackage(List<ZNetPeer> peers, ZPackage package)
		{
			ZPackage package2 = package;
			if (!Object.op_Implicit((Object)(object)ZNet.instance))
			{
				yield break;
			}
			byte[] rawData = package2.GetArray();
			if (rawData != null && rawData.LongLength > 10000)
			{
				ZPackage compressedPackage = new ZPackage();
				compressedPackage.Write((byte)4);
				MemoryStream output = new MemoryStream();
				using (DeflateStream deflateStream = new DeflateStream(output, CompressionLevel.Optimal))
				{
					deflateStream.Write(rawData, 0, rawData.Length);
				}
				compressedPackage.Write(output.ToArray());
				package2 = compressedPackage;
			}
			List<IEnumerator<bool>> writers = (from peer in peers
				where peer.IsReady()
				select peer into p
				select distributeConfigToPeers(p, package2)).ToList();
			writers.RemoveAll((IEnumerator<bool> writer) => !writer.MoveNext());
			while (writers.Count > 0)
			{
				yield return null;
				writers.RemoveAll((IEnumerator<bool> writer) => !writer.MoveNext());
			}
		}

		private void Broadcast(long target, params ConfigEntryBase[] configs)
		{
			if (!IsLocked || isServer)
			{
				ZPackage package = ConfigsToPackage(configs);
				ZNet instance = ZNet.instance;
				if (instance != null)
				{
					((MonoBehaviour)instance).StartCoroutine(sendZPackage(target, package));
				}
			}
		}

		private void Broadcast(long target, params CustomSyncedValueBase[] customValues)
		{
			if (!IsLocked || isServer)
			{
				ZPackage package = ConfigsToPackage(null, customValues);
				ZNet instance = ZNet.instance;
				if (instance != null)
				{
					((MonoBehaviour)instance).StartCoroutine(sendZPackage(target, package));
				}
			}
		}

		private static OwnConfigEntryBase? configData(ConfigEntryBase config)
		{
			return config.Description.Tags?.OfType<OwnConfigEntryBase>().SingleOrDefault();
		}

		public static SyncedConfigEntry<T>? ConfigData<T>(ConfigEntry<T> config)
		{
			return ((ConfigEntryBase)config).Description.Tags?.OfType<SyncedConfigEntry<T>>().SingleOrDefault();
		}

		private static T configAttribute<T>(ConfigEntryBase config)
		{
			return config.Description.Tags.OfType<T>().First();
		}

		private static Type configType(ConfigEntryBase config)
		{
			return configType(config.SettingType);
		}

		private static Type configType(Type type)
		{
			return type.IsEnum ? Enum.GetUnderlyingType(type) : type;
		}

		private static ZPackage ConfigsToPackage(IEnumerable<ConfigEntryBase>? configs = null, IEnumerable<CustomSyncedValueBase>? customValues = null, IEnumerable<PackageEntry>? packageEntries = null, bool partial = true)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			List<ConfigEntryBase> list = configs?.Where((ConfigEntryBase config) => configData(config).SynchronizedConfig).ToList() ?? new List<ConfigEntryBase>();
			List<CustomSyncedValueBase> list2 = customValues?.ToList() ?? new List<CustomSyncedValueBase>();
			ZPackage val = new ZPackage();
			val.Write((byte)(partial ? 1 : 0));
			val.Write(list.Count + list2.Count + (packageEntries?.Count() ?? 0));
			foreach (PackageEntry item in packageEntries ?? Array.Empty<PackageEntry>())
			{
				AddEntryToPackage(val, item);
			}
			foreach (CustomSyncedValueBase item2 in list2)
			{
				AddEntryToPackage(val, new PackageEntry
				{
					section = "Internal",
					key = item2.Identifier,
					type = item2.Type,
					value = item2.BoxedValue
				});
			}
			foreach (ConfigEntryBase item3 in list)
			{
				AddEntryToPackage(val, new PackageEntry
				{
					section = item3.Definition.Section,
					key = item3.Definition.Key,
					type = configType(item3),
					value = item3.BoxedValue
				});
			}
			return val;
		}

		private static void AddEntryToPackage(ZPackage package, PackageEntry entry)
		{
			package.Write(entry.section);
			package.Write(entry.key);
			package.Write((entry.value == null) ? "" : GetZPackageTypeString(entry.type));
			AddValueToZPackage(package, entry.value);
		}

		private static string GetZPackageTypeString(Type type)
		{
			return type.AssemblyQualifiedName;
		}

		private static void AddValueToZPackage(ZPackage package, object? value)
		{
			Type type = value?.GetType();
			if (value is Enum)
			{
				value = ((IConvertible)value).ToType(Enum.GetUnderlyingType(value.GetType()), CultureInfo.InvariantCulture);
			}
			else
			{
				if (value is ICollection collection)
				{
					package.Write(collection.Count);
					{
						foreach (object item in collection)
						{
							AddValueToZPackage(package, item);
						}
						return;
					}
				}
				if ((object)type != null && type.IsValueType && !type.IsPrimitive)
				{
					FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					package.Write(fields.Length);
					FieldInfo[] array = fields;
					foreach (FieldInfo fieldInfo in array)
					{
						package.Write(GetZPackageTypeString(fieldInfo.FieldType));
						AddValueToZPackage(package, fieldInfo.GetValue(value));
					}
					return;
				}
			}
			ZRpc.Serialize(new object[1] { value }, ref package);
		}

		private static object ReadValueWithTypeFromZPackage(ZPackage package, Type type)
		{
			if ((object)type != null && type.IsValueType && !type.IsPrimitive && !type.IsEnum)
			{
				FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				int num = package.ReadInt();
				if (num != fields.Length)
				{
					throw new InvalidDeserializationTypeException
					{
						received = $"(field count: {num})",
						expected = $"(field count: {fields.Length})"
					};
				}
				object uninitializedObject = FormatterServices.GetUninitializedObject(type);
				FieldInfo[] array = fields;
				foreach (FieldInfo fieldInfo in array)
				{
					string text = package.ReadString();
					if (text != GetZPackageTypeString(fieldInfo.FieldType))
					{
						throw new InvalidDeserializationTypeException
						{
							received = text,
							expected = GetZPackageTypeString(fieldInfo.FieldType),
							field = fieldInfo.Name
						};
					}
					fieldInfo.SetValue(uninitializedObject, ReadValueWithTypeFromZPackage(package, fieldInfo.FieldType));
				}
				return uninitializedObject;
			}
			if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<, >))
			{
				int num2 = package.ReadInt();
				IDictionary dictionary = (IDictionary)Activator.CreateInstance(type);
				Type type2 = typeof(KeyValuePair<, >).MakeGenericType(type.GenericTypeArguments);
				FieldInfo field = type2.GetField("key", BindingFlags.Instance | BindingFlags.NonPublic);
				FieldInfo field2 = type2.GetField("value", BindingFlags.Instance | BindingFlags.NonPublic);
				for (int j = 0; j < num2; j++)
				{
					object obj = ReadValueWithTypeFromZPackage(package, type2);
					dictionary.Add(field.GetValue(obj), field2.GetValue(obj));
				}
				return dictionary;
			}
			if (type != typeof(List<string>) && type.IsGenericType)
			{
				Type type3 = typeof(ICollection<>).MakeGenericType(type.GenericTypeArguments[0]);
				if ((object)type3 != null && type3.IsAssignableFrom(type))
				{
					int num3 = package.ReadInt();
					object obj2 = Activator.CreateInstance(type);
					MethodInfo method = type3.GetMethod("Add");
					for (int k = 0; k < num3; k++)
					{
						method.Invoke(obj2, new object[1] { ReadValueWithTypeFromZPackage(package, type.GenericTypeArguments[0]) });
					}
					return obj2;
				}
			}
			ParameterInfo parameterInfo = (ParameterInfo)FormatterServices.GetUninitializedObject(typeof(ParameterInfo));
			AccessTools.DeclaredField(typeof(ParameterInfo), "ClassImpl").SetValue(parameterInfo, type);
			List<object> source = new List<object>();
			ZRpc.Deserialize(new ParameterInfo[2] { null, parameterInfo }, package, ref source);
			return source.First();
		}
	}
	[PublicAPI]
	[HarmonyPatch]
	internal class VersionCheck
	{
		private static readonly HashSet<VersionCheck> versionChecks;

		private static readonly Dictionary<string, string> notProcessedNames;

		public string Name;

		private string? displayName;

		private string? currentVersion;

		private string? minimumRequiredVersion;

		public bool ModRequired = true;

		private string? ReceivedCurrentVersion;

		private string? ReceivedMinimumRequiredVersion;

		private readonly List<ZRpc> ValidatedClients = new List<ZRpc>();

		private ConfigSync? ConfigSync;

		public string DisplayName
		{
			get
			{
				return displayName ?? Name;
			}
			set
			{
				displayName = value;
			}
		}

		public string CurrentVersion
		{
			get
			{
				return currentVersion ?? "0.0.0";
			}
			set
			{
				currentVersion = value;
			}
		}

		public string MinimumRequiredVersion
		{
			get
			{
				return minimumRequiredVersion ?? (ModRequired ? CurrentVersion : "0.0.0");
			}
			set
			{
				minimumRequiredVersion = value;
			}
		}

		private static void PatchServerSync()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			Patches patchInfo = PatchProcessor.GetPatchInfo((MethodBase)AccessTools.DeclaredMethod(typeof(ZNet), "Awake", (Type[])null, (Type[])null));
			if (patchInfo != null && patchInfo.Postfixes.Count((Patch p) => p.PatchMethod.DeclaringType == typeof(ConfigSync.RegisterRPCPatch)) > 0)
			{
				return;
			}
			Harmony val = new Harmony("org.bepinex.helpers.ServerSync");
			foreach (Type item in from t in typeof(ConfigSync).GetNestedTypes(BindingFlags.NonPublic).Concat(new Type[1] { typeof(VersionCheck) })
				where t.IsClass
				select t)
			{
				val.PatchAll(item);
			}
		}

		static VersionCheck()
		{
			versionChecks = new HashSet<VersionCheck>();
			notProcessedNames = new Dictionary<string, string>();
			typeof(ThreadingHelper).GetMethod("StartSyncInvoke").Invoke(ThreadingHelper.Instance, new object[1]
			{
				new Action(PatchServerSync)
			});
		}

		public VersionCheck(string name)
		{
			Name = name;
			ModRequired = true;
			versionChecks.Add(this);
		}

		public VersionCheck(ConfigSync configSync)
		{
			ConfigSync = configSync;
			Name = ConfigSync.Name;
			versionChecks.Add(this);
		}

		public void Initialize()
		{
			ReceivedCurrentVersion = null;
			ReceivedMinimumRequiredVersion = null;
			if (ConfigSync != null)
			{
				Name = ConfigSync.Name;
				DisplayName = ConfigSync.DisplayName;
				CurrentVersion = ConfigSync.CurrentVersion;
				MinimumRequiredVersion = ConfigSync.MinimumRequiredVersion;
				ModRequired = ConfigSync.ModRequired;
			}
		}

		private bool IsVersionOk()
		{
			if (ReceivedMinimumRequiredVersion == null || ReceivedCurrentVersion == null)
			{
				return !ModRequired;
			}
			bool flag = new Version(CurrentVersion) >= new Version(ReceivedMinimumRequiredVersion);
			bool flag2 = new Version(ReceivedCurrentVersion) >= new Version(MinimumRequiredVersion);
			return flag && flag2;
		}

		private string ErrorClient()
		{
			if (ReceivedMinimumRequiredVersion == null)
			{
				return "Mod " + DisplayName + " must not be installed.";
			}
			return (new Version(CurrentVersion) >= new Version(ReceivedMinimumRequiredVersion)) ? ("Mod " + DisplayName + " requires maximum " + ReceivedCurrentVersion + ". Installed is version " + CurrentVersion + ".") : ("Mod " + DisplayName + " requires minimum " + ReceivedMinimumRequiredVersion + ". Installed is version " + CurrentVersion + ".");
		}

		private string ErrorServer(ZRpc rpc)
		{
			return "Disconnect: The client (" + rpc.GetSocket().GetHostName() + ") doesn't have the correct " + DisplayName + " version " + MinimumRequiredVersion;
		}

		private string Error(ZRpc? rpc = null)
		{
			return (rpc == null) ? ErrorClient() : ErrorServer(rpc);
		}

		private static VersionCheck[] GetFailedClient()
		{
			return versionChecks.Where((VersionCheck check) => !check.IsVersionOk()).ToArray();
		}

		private static VersionCheck[] GetFailedServer(ZRpc rpc)
		{
			ZRpc rpc2 = rpc;
			return versionChecks.Where((VersionCheck check) => check.ModRequired && !check.ValidatedClients.Contains(rpc2)).ToArray();
		}

		private static void Logout()
		{
			Game.instance.Logout(true, true);
			AccessTools.DeclaredField(typeof(ZNet), "m_connectionStatus").SetValue(null, (object)(ConnectionStatus)3);
		}

		private static void DisconnectClient(ZRpc rpc)
		{
			rpc.Invoke("Error", new object[1] { 3 });
		}

		private static void CheckVersion(ZRpc rpc, ZPackage pkg)
		{
			CheckVersion(rpc, pkg, null);
		}

		private static void CheckVersion(ZRpc rpc, ZPackage pkg, Action<ZRpc, ZPackage>? original)
		{
			string text = pkg.ReadString();
			string text2 = pkg.ReadString();
			string text3 = pkg.ReadString();
			bool flag = false;
			foreach (VersionCheck versionCheck in versionChecks)
			{
				if (!(text != versionCheck.Name))
				{
					Debug.Log((object)("Received " + versionCheck.DisplayName + " version " + text3 + " and minimum version " + text2 + " from the " + (ZNet.instance.IsServer() ? "client" : "server") + "."));
					versionCheck.ReceivedMinimumRequiredVersion = text2;
					versionCheck.ReceivedCurrentVersion = text3;
					if (ZNet.instance.IsServer() && versionCheck.IsVersionOk())
					{
						versionCheck.ValidatedClients.Add(rpc);
					}
					flag = true;
				}
			}
			if (flag)
			{
				return;
			}
			pkg.SetPos(0);
			if (original != null)
			{
				original(rpc, pkg);
				if (pkg.GetPos() == 0)
				{
					notProcessedNames.Add(text, text3);
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
		private static bool RPC_PeerInfo(ZRpc rpc, ZNet __instance)
		{
			VersionCheck[] array = (__instance.IsServer() ? GetFailedServer(rpc) : GetFailedClient());
			if (array.Length == 0)
			{
				return true;
			}
			VersionCheck[] array2 = array;
			foreach (VersionCheck versionCheck in array2)
			{
				Debug.LogWarning((object)versionCheck.Error(rpc));
			}
			if (__instance.IsServer())
			{
				DisconnectClient(rpc);
			}
			else
			{
				Logout();
			}
			return false;
		}

		[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
		[HarmonyPrefix]
		private static void RegisterAndCheckVersion(ZNetPeer peer, ZNet __instance)
		{
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Expected O, but got Unknown
			notProcessedNames.Clear();
			IDictionary dictionary = (IDictionary)typeof(ZRpc).GetField("m_functions", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(peer.m_rpc);
			if (dictionary.Contains(StringExtensionMethods.GetStableHashCode("ServerSync VersionCheck")))
			{
				object obj = dictionary[StringExtensionMethods.GetStableHashCode("ServerSync VersionCheck")];
				Action<ZRpc, ZPackage> action = (Action<ZRpc, ZPackage>)obj.GetType().GetField("m_action", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj);
				peer.m_rpc.Register<ZPackage>("ServerSync VersionCheck", (Action<ZRpc, ZPackage>)delegate(ZRpc rpc, ZPackage pkg)
				{
					CheckVersion(rpc, pkg, action);
				});
			}
			else
			{
				peer.m_rpc.Register<ZPackage>("ServerSync VersionCheck", (Action<ZRpc, ZPackage>)CheckVersion);
			}
			foreach (VersionCheck versionCheck in versionChecks)
			{
				versionCheck.Initialize();
				if (versionCheck.ModRequired || __instance.IsServer())
				{
					Debug.Log((object)("Sending " + versionCheck.DisplayName + " version " + versionCheck.CurrentVersion + " and minimum version " + versionCheck.MinimumRequiredVersion + " to the " + (__instance.IsServer() ? "client" : "server") + "."));
					ZPackage val = new ZPackage();
					val.Write(versionCheck.Name);
					val.Write(versionCheck.MinimumRequiredVersion);
					val.Write(versionCheck.CurrentVersion);
					peer.m_rpc.Invoke("ServerSync VersionCheck", new object[1] { val });
				}
			}
		}

		[HarmonyPatch(typeof(ZNet), "Disconnect")]
		[HarmonyPrefix]
		private static void RemoveDisconnected(ZNetPeer peer, ZNet __instance)
		{
			if (!__instance.IsServer())
			{
				return;
			}
			foreach (VersionCheck versionCheck in versionChecks)
			{
				versionCheck.ValidatedClients.Remove(peer.m_rpc);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(FejdStartup), "ShowConnectError")]
		private static void ShowConnectionError(FejdStartup __instance)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			if (!__instance.m_connectionFailedPanel.activeSelf || (int)ZNet.GetConnectionStatus() != 3)
			{
				return;
			}
			VersionCheck[] failedClient = GetFailedClient();
			if (failedClient.Length != 0)
			{
				string text = string.Join("\n", failedClient.Select((VersionCheck check) => check.Error()));
				TMP_Text connectionFailedError = __instance.m_connectionFailedError;
				connectionFailedError.text = connectionFailedError.text + "\n" + text;
			}
			foreach (KeyValuePair<string, string> item in notProcessedNames.OrderBy<KeyValuePair<string, string>, string>((KeyValuePair<string, string> kv) => kv.Key))
			{
				if (!__instance.m_connectionFailedError.text.Contains(item.Key))
				{
					TMP_Text connectionFailedError2 = __instance.m_connectionFailedError;
					connectionFailedError2.text = connectionFailedError2.text + "\n" + item.Key + " (Version: " + item.Value + ")";
				}
			}
		}
	}
}