Decompiled source of ValheimPlus Temporary v1.3.1

ValheimPlus.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Net.Http;
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.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Timers;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using IniParser;
using IniParser.Exceptions;
using IniParser.Model;
using IniParser.Model.Configuration;
using IniParser.Model.Formatting;
using IniParser.Parser;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using PlayFab.MultiplayerModels;
using PlayFab.Party;
using ServerSync;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using Valheim.SettingsGui;
using ValheimPlus.Configurations;
using ValheimPlus.Configurations.Sections;
using ValheimPlus.GameClasses;
using ValheimPlus.Http;
using ValheimPlus.RPC;
using ValheimPlus.Utility;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Valheim Plus (Iceskull Temporary)")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Iceskull")]
[assembly: AssemblyProduct("Valheim Plus (Iceskull Temporary)")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("2a837100-a030-4d0c-bffb-b38356118d9a")]
[assembly: AssemblyFileVersion("1.3.1")]
[assembly: AssemblyInformationalVersion("1.3.1")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.3.1.0")]
[module: UnverifiableCode]
internal sealed class ConfigurationManagerAttributes
{
	public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput);

	public bool? ShowRangeAsPercent;

	public Action<ConfigEntryBase> CustomDrawer;

	public CustomHotkeyDrawerFunc CustomHotkeyDrawer;

	public bool? Browsable;

	public string Category;

	public object DefaultValue;

	public bool? HideDefaultButton;

	public bool? HideSettingName;

	public string Description;

	public string DispName;

	public int? Order;

	public bool? ReadOnly;

	public bool? IsAdvanced;

	public Func<object, string> ObjToStr;

	public Func<string, object> StrToObj;
}
public static class ZNetExtensions
{
	public enum ZNetInstanceType
	{
		Local,
		Client,
		Server
	}

	public static bool IsLocalInstance(this ZNet znet)
	{
		if (znet.IsServer())
		{
			return !znet.IsDedicated();
		}
		return false;
	}

	public static bool IsClientInstance(this ZNet znet)
	{
		if (!znet.IsServer())
		{
			return !znet.IsDedicated();
		}
		return false;
	}

	public static bool IsServerInstance(this ZNet znet)
	{
		if (znet.IsServer())
		{
			return znet.IsDedicated();
		}
		return false;
	}

	public static ZNetInstanceType GetInstanceType(this ZNet znet)
	{
		if (znet.IsLocalInstance())
		{
			return ZNetInstanceType.Local;
		}
		if (znet.IsClientInstance())
		{
			return ZNetInstanceType.Client;
		}
		return ZNetInstanceType.Server;
	}
}
namespace ValheimPlus
{
	internal class ABM
	{
		public static bool isActive;

		private static Player PlayerInstance;

		private static bool controlFlag;

		private static bool shiftFlag;

		private static bool altFlag;

		public static bool exitOnNextIteration;

		private static Piece component;

		private const float BASE_TRANSLATION_DISTANCE = 0.1f;

		private const float BASE_ROTATION_ANGLE_DEGREES = 3f;

		private static float currentModificationSpeed = 1f;

		private const float MIN_MODIFICATION_SPEED = 1f;

		private const float MAX_MODIFICATION_SPEED = 30f;

		private static Quaternion savedRotation;

		public static void Run(ref Player __instance)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			PlayerInstance = __instance;
			if (AEM.isActive)
			{
				if (isActive)
				{
					exitMode();
				}
				return;
			}
			if (Input.GetKeyDown(Configuration.Current.AdvancedBuildingMode.exitAdvancedBuildingMode))
			{
				if (isActive)
				{
					exitMode();
				}
				return;
			}
			if (exitOnNextIteration)
			{
				isActive = false;
				exitOnNextIteration = false;
				component = null;
			}
			if (isActive && (Object)(object)component == (Object)null)
			{
				exitMode();
			}
			else if ((Object)(object)selectedPrefab() == (Object)null || (Object)(object)PlayerInstance.m_placementGhost == (Object)null)
			{
				if (isActive)
				{
					exitMode();
				}
			}
			else if (isInBuildMode() && IsHoeOrTerrainTool(selectedPrefab()))
			{
				if (isActive)
				{
					exitMode();
				}
			}
			else if (isActive)
			{
				if (Vector3.Distance(((Component)PlayerInstance).transform.position, ((Component)component).transform.position) > PlayerInstance.m_maxPlaceDistance)
				{
					exitMode();
				}
				isRunning();
				listenToHotKeysAndDoWork();
			}
			else if (Input.GetKeyDown(Configuration.Current.AdvancedBuildingMode.enterAdvancedBuildingMode))
			{
				startMode();
			}
		}

		private static void listenToHotKeysAndDoWork()
		{
			//IL_008d: 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_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_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: 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_0263: 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_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: 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_01e8: 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_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: 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_0378: Unknown result type (might be due to invalid IL or missing references)
			//IL_037f: Unknown result type (might be due to invalid IL or missing references)
			//IL_035b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: 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_030f: 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_031e: 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_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ad: 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_0418: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			float num2 = 0f;
			float num3 = 0f;
			if (Input.GetKeyDown((KeyCode)306))
			{
				controlFlag = true;
			}
			if (Input.GetKeyUp((KeyCode)306))
			{
				controlFlag = false;
			}
			if (Input.GetKeyDown((KeyCode)304))
			{
				shiftFlag = true;
			}
			if (Input.GetKeyUp((KeyCode)304))
			{
				shiftFlag = false;
			}
			if (Input.GetKeyDown((KeyCode)308))
			{
				altFlag = true;
			}
			if (Input.GetKeyUp((KeyCode)308))
			{
				altFlag = false;
			}
			changeModificationSpeed();
			if (Input.GetKeyUp(Configuration.Current.AdvancedBuildingMode.copyObjectRotation))
			{
				savedRotation = ((Component)component).transform.rotation;
			}
			if (Input.GetKeyUp(Configuration.Current.AdvancedBuildingMode.pasteObjectRotation))
			{
				((Component)component).transform.rotation = savedRotation;
			}
			float num4 = 3f * currentModificationSpeed;
			if (Input.GetAxis("Mouse ScrollWheel") > 0f)
			{
				Quaternion rotation;
				if (controlFlag)
				{
					num += 1f;
					rotation = Quaternion.Euler(((Component)component).transform.eulerAngles.x + num4 * num, ((Component)component).transform.eulerAngles.y, ((Component)component).transform.eulerAngles.z);
				}
				else if (altFlag)
				{
					num2 += 1f;
					rotation = Quaternion.Euler(((Component)component).transform.eulerAngles.x, ((Component)component).transform.eulerAngles.y, ((Component)component).transform.eulerAngles.z + num4 * num2);
				}
				else
				{
					num3 += 1f;
					rotation = Quaternion.Euler(((Component)component).transform.eulerAngles.x, ((Component)component).transform.eulerAngles.y + num4 * num3, ((Component)component).transform.eulerAngles.z);
				}
				((Component)component).transform.rotation = rotation;
			}
			if (Input.GetAxis("Mouse ScrollWheel") < 0f)
			{
				Quaternion rotation2;
				if (controlFlag)
				{
					num -= 1f;
					rotation2 = Quaternion.Euler(((Component)component).transform.eulerAngles.x + num4 * num, ((Component)component).transform.eulerAngles.y, ((Component)component).transform.eulerAngles.z);
				}
				else if (altFlag)
				{
					num2 -= 1f;
					rotation2 = Quaternion.Euler(((Component)component).transform.eulerAngles.x, ((Component)component).transform.eulerAngles.y, ((Component)component).transform.eulerAngles.z + num4 * num2);
				}
				else
				{
					num3 -= 1f;
					rotation2 = Quaternion.Euler(((Component)component).transform.eulerAngles.x, ((Component)component).transform.eulerAngles.y + num4 * num3, ((Component)component).transform.eulerAngles.z);
				}
				((Component)component).transform.rotation = rotation2;
			}
			float num5 = 0.1f * currentModificationSpeed;
			if (Input.GetKeyDown((KeyCode)273))
			{
				if (controlFlag)
				{
					((Component)component).transform.Translate(Vector3.up * num5);
				}
				else
				{
					((Component)component).transform.Translate(Vector3.forward * num5);
				}
			}
			if (Input.GetKeyDown((KeyCode)274))
			{
				if (controlFlag)
				{
					((Component)component).transform.Translate(Vector3.down * num5);
				}
				else
				{
					((Component)component).transform.Translate(Vector3.back * num5);
				}
			}
			if (Input.GetKeyDown((KeyCode)276))
			{
				((Component)component).transform.Translate(Vector3.left * num5);
			}
			if (Input.GetKeyDown((KeyCode)275))
			{
				((Component)component).transform.Translate(Vector3.right * num5);
			}
			try
			{
				isValidPlacement();
			}
			catch
			{
			}
		}

		private static void isValidPlacement()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: 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_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			PlayerInstance.m_placementStatus = (PlacementStatus)0;
			if (component.m_groundOnly || component.m_groundPiece || component.m_cultivatedGroundOnly)
			{
				PlayerInstance.m_placementMarkerInstance.SetActive(false);
			}
			StationExtension val = ((Component)component).GetComponent<StationExtension>();
			if ((Object)(object)val != (Object)null)
			{
				CraftingStation val2 = val.FindClosestStationInRange(((Component)component).transform.position);
				if (Object.op_Implicit((Object)(object)val2))
				{
					val.StartConnectionEffect(val2, 1f);
				}
				else
				{
					val.StopConnectionEffect();
					PlayerInstance.m_placementStatus = (PlacementStatus)7;
				}
				if (val.OtherExtensionInRange(component.m_spaceRequirement))
				{
					PlayerInstance.m_placementStatus = (PlacementStatus)5;
				}
			}
			if (component.m_onlyInTeleportArea && !Object.op_Implicit((Object)(object)EffectArea.IsPointInsideArea(((Component)component).transform.position, (Type)16, 0f)))
			{
				PlayerInstance.m_placementStatus = (PlacementStatus)6;
			}
			if (!component.m_allowedInDungeons && ((Component)component).transform.position.y > 3000f)
			{
				PlayerInstance.m_placementStatus = (PlacementStatus)11;
			}
			if (Location.IsInsideNoBuildLocation(PlayerInstance.m_placementGhost.transform.position))
			{
				PlayerInstance.m_placementStatus = (PlacementStatus)3;
			}
			float num = (Object.op_Implicit((Object)(object)((Component)component).GetComponent<PrivateArea>()) ? ((Component)component).GetComponent<PrivateArea>().m_radius : 0f);
			if (!PrivateArea.CheckAccess(PlayerInstance.m_placementGhost.transform.position, num, true, false))
			{
				PlayerInstance.m_placementStatus = (PlacementStatus)4;
			}
			if ((int)PlayerInstance.m_placementStatus != 0)
			{
				component.SetInvalidPlacementHeightlight(true);
			}
			else
			{
				component.SetInvalidPlacementHeightlight(false);
			}
		}

		private static void startMode()
		{
			notifyUser("Starting ABM", (MessageType)1);
			isActive = true;
			component = PlayerInstance.m_placementGhost.GetComponent<Piece>();
		}

		private static void exitMode()
		{
			notifyUser("Exiting ABM", (MessageType)1);
			exitOnNextIteration = true;
			isActive = false;
			component = null;
		}

		private static bool isInBuildMode()
		{
			return ((Character)PlayerInstance).InPlaceMode();
		}

		private static GameObject selectedPrefab()
		{
			if ((Object)(object)PlayerInstance.m_buildPieces != (Object)null)
			{
				try
				{
					return PlayerInstance.m_buildPieces.GetSelectedPrefab();
				}
				catch
				{
					return null;
				}
			}
			return null;
		}

		private static bool IsHoeOrTerrainTool(GameObject selectedPrefab)
		{
			string[] source = new string[4] { "paved_road", "mud_road", "raise", "path" };
			string[] source2 = new string[2] { "cultivate", "replant" };
			if (((Object)selectedPrefab).name.ToLower().Contains("sapling"))
			{
				return true;
			}
			if (source.Contains(((Object)selectedPrefab).name) || source2.Contains(((Object)selectedPrefab).name))
			{
				return true;
			}
			return false;
		}

		private static void notifyUser(string Message, MessageType position = (MessageType)1)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			MessageHud.instance.ShowMessage(position, "ABM: " + Message, 0, (Sprite)null, false, true);
		}

		private static void isRunning()
		{
			if (isActive)
			{
				MessageHud.instance.ShowMessage((MessageType)2, "ABM is active", 0, (Sprite)null, false, true);
			}
		}

		private static void changeModificationSpeed()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			float num = 1f;
			if (shiftFlag)
			{
				num = 10f;
			}
			if (Input.GetKeyDown(Configuration.Current.AdvancedBuildingMode.increaseScrollSpeed))
			{
				currentModificationSpeed = Mathf.Clamp(currentModificationSpeed + num, 1f, 30f);
				notifyUser("Modification Speed: " + currentModificationSpeed, (MessageType)1);
			}
			if (Input.GetKeyDown(Configuration.Current.AdvancedBuildingMode.decreaseScrollSpeed))
			{
				currentModificationSpeed = Mathf.Clamp(currentModificationSpeed - num, 1f, 30f);
				notifyUser("Modification Speed: " + currentModificationSpeed, (MessageType)1);
			}
		}
	}
	internal class AEM
	{
		public static bool isActive;

		public static Player PlayerInstance;

		private static bool controlFlag;

		private static bool shiftFlag;

		private static bool altFlag;

		public static Vector3 HitPoint;

		public static Vector3 HitNormal;

		public static Piece HitPiece;

		public static GameObject HitObject;

		public static Heightmap HitHeightmap;

		private static Quaternion InitialRotation;

		private static Vector3 InitialPosition;

		private static bool isInExistence;

		private const float BASE_TRANSLATION_DISTANCE = 0.1f;

		private const float BASE_ROTATION_ANGLE_DEGREES = 3f;

		private static float currentModificationSpeed = 1f;

		private const float MIN_MODIFICATION_SPEED = 1f;

		private const float MAX_MODIFICATION_SPEED = 30f;

		private static Quaternion savedRotation;

		public static bool forceExitNextIteration;

		public static bool ExecuteRayCast(Player playerInstance)
		{
			//IL_0011: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_00eb: 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)
			int placeRayMask = playerInstance.m_placeRayMask;
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(((Component)GameCamera.instance).transform.position, ((Component)GameCamera.instance).transform.forward, ref val, 50f, placeRayMask) && Object.op_Implicit((Object)(object)((RaycastHit)(ref val)).collider) && !Object.op_Implicit((Object)(object)((RaycastHit)(ref val)).collider.attachedRigidbody) && Vector3.Distance(Helper.getPlayerCharacter(playerInstance).m_eye.position, ((RaycastHit)(ref val)).point) < playerInstance.m_maxPlaceDistance)
			{
				HitPoint = ((RaycastHit)(ref val)).point;
				HitNormal = ((RaycastHit)(ref val)).normal;
				HitPiece = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Piece>();
				HitObject = ((Component)((RaycastHit)(ref val)).collider).gameObject;
				HitHeightmap = ((Component)((RaycastHit)(ref val)).collider).GetComponent<Heightmap>();
				InitialRotation = ((Component)HitPiece).transform.rotation;
				InitialPosition = ((Component)HitPiece).transform.position;
				return isValidRayCastTarget();
			}
			resetObjectInfo();
			return false;
		}

		public static bool checkForObject()
		{
			if ((Object)(object)PlayerInstance == (Object)null)
			{
				return false;
			}
			if (!ExecuteRayCast(PlayerInstance))
			{
				return false;
			}
			return true;
		}

		public static void run()
		{
			//IL_007f: 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)
			if (forceExitNextIteration)
			{
				forceExitNextIteration = false;
				resetObjectInfo();
				isActive = false;
				return;
			}
			if (isInBuildMode())
			{
				if (isActive)
				{
					exitMode();
					resetObjectTransform();
				}
				return;
			}
			if (ABM.isActive)
			{
				if (isActive)
				{
					exitMode();
					resetObjectTransform();
				}
				return;
			}
			if (!isActive && Input.GetKeyDown(Configuration.Current.AdvancedEditingMode.enterAdvancedEditingMode))
			{
				if (checkForObject())
				{
					startMode();
				}
				return;
			}
			if (Input.GetKeyDown(Configuration.Current.AdvancedEditingMode.abortAndExitAdvancedEditingMode))
			{
				exitMode();
				resetObjectTransform();
			}
			if (!isActive)
			{
				return;
			}
			if (hitPieceStillExists())
			{
				try
				{
					if ((Object)(object)((Component)HitPiece).GetComponent<ZNetView>() == (Object)null)
					{
						ValheimPlusPlugin.Logger.LogWarning((object)"AEM: Error, network object empty. Code: 2.");
						exitMode();
						return;
					}
				}
				catch
				{
					ValheimPlusPlugin.Logger.LogWarning((object)"AEM: Error, network object empty. Code: 3.");
					exitMode();
				}
				isRunning();
				listenToHotKeysAndDoWork();
			}
			else
			{
				exitMode();
			}
		}

		private static void listenToHotKeysAndDoWork()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: 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_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_0384: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: 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_03bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: 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_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04af: Unknown result type (might be due to invalid IL or missing references)
			//IL_0430: 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_045c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0466: Unknown result type (might be due to invalid IL or missing references)
			//IL_046b: 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_03f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0407: Unknown result type (might be due to invalid IL or missing references)
			//IL_0415: Unknown result type (might be due to invalid IL or missing references)
			//IL_041a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0477: Unknown result type (might be due to invalid IL or missing references)
			//IL_0537: Unknown result type (might be due to invalid IL or missing references)
			//IL_053e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0510: Unknown result type (might be due to invalid IL or missing references)
			//IL_0517: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fa: 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_0565: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			float num2 = 0f;
			float num3 = 0f;
			if (Input.GetKeyDown(Configuration.Current.AdvancedEditingMode.resetAdvancedEditingMode))
			{
				resetObjectTransform();
			}
			if (Input.GetKeyDown(Configuration.Current.AdvancedEditingMode.confirmPlacementOfAdvancedEditingMode))
			{
				if (isContainer())
				{
					dropContainerContents();
				}
				GameObject val = Object.Instantiate<GameObject>(((Component)HitPiece).gameObject, ((Component)HitPiece).transform.position, ((Component)HitPiece).transform.rotation);
				HitPiece.m_placeEffect.Create(((Component)HitPiece).transform.position, ((Component)HitPiece).transform.rotation, val.transform, 1f, -1, default(ZDOID));
				ZNetView component = ((Component)HitPiece).GetComponent<ZNetView>();
				if ((Object)(object)component == (Object)null)
				{
					ValheimPlusPlugin.Logger.LogWarning((object)"AEM: Error, network object empty.");
					resetObjectTransform();
					exitMode();
				}
				else
				{
					component.ClaimOwnership();
					ZNetScene.instance.Destroy(((Component)HitPiece).gameObject);
					ValheimPlusPlugin.Logger.LogDebug((object)"AEM: Executed.");
					exitMode();
				}
				return;
			}
			if (Input.GetKeyDown((KeyCode)306))
			{
				controlFlag = true;
			}
			if (Input.GetKeyUp((KeyCode)306))
			{
				controlFlag = false;
			}
			if (Input.GetKeyDown((KeyCode)304))
			{
				shiftFlag = true;
			}
			if (Input.GetKeyUp((KeyCode)304))
			{
				shiftFlag = false;
			}
			if (Input.GetKeyDown((KeyCode)308))
			{
				altFlag = true;
			}
			if (Input.GetKeyUp((KeyCode)308))
			{
				altFlag = false;
			}
			changeModificationSpeed();
			if (Input.GetKeyUp(Configuration.Current.AdvancedEditingMode.copyObjectRotation))
			{
				savedRotation = ((Component)HitPiece).transform.rotation;
			}
			if (Input.GetKeyUp(Configuration.Current.AdvancedEditingMode.pasteObjectRotation))
			{
				((Component)HitPiece).transform.rotation = savedRotation;
			}
			if (Vector3.Distance(((Component)PlayerInstance).transform.position, ((Component)HitPiece).transform.position) > PlayerInstance.m_maxPlaceDistance)
			{
				resetObjectTransform();
				exitMode();
			}
			float num4 = 3f * currentModificationSpeed;
			if (Input.GetAxis("Mouse ScrollWheel") > 0f)
			{
				Quaternion rotation;
				if (controlFlag)
				{
					num += 1f;
					rotation = Quaternion.Euler(((Component)HitPiece).transform.eulerAngles.x + num4 * num, ((Component)HitPiece).transform.eulerAngles.y, ((Component)HitPiece).transform.eulerAngles.z);
				}
				else if (altFlag)
				{
					num2 += 1f;
					rotation = Quaternion.Euler(((Component)HitPiece).transform.eulerAngles.x, ((Component)HitPiece).transform.eulerAngles.y, ((Component)HitPiece).transform.eulerAngles.z + num4 * num2);
				}
				else
				{
					num3 += 1f;
					rotation = Quaternion.Euler(((Component)HitPiece).transform.eulerAngles.x, ((Component)HitPiece).transform.eulerAngles.y + num4 * num3, ((Component)HitPiece).transform.eulerAngles.z);
				}
				((Component)HitPiece).transform.rotation = rotation;
			}
			if (Input.GetAxis("Mouse ScrollWheel") < 0f)
			{
				Quaternion rotation2;
				if (controlFlag)
				{
					num -= 1f;
					rotation2 = Quaternion.Euler(((Component)HitPiece).transform.eulerAngles.x + num4 * num, ((Component)HitPiece).transform.eulerAngles.y, ((Component)HitPiece).transform.eulerAngles.z);
				}
				else if (altFlag)
				{
					num2 -= 1f;
					rotation2 = Quaternion.Euler(((Component)HitPiece).transform.eulerAngles.x, ((Component)HitPiece).transform.eulerAngles.y, ((Component)HitPiece).transform.eulerAngles.z + num4 * num2);
				}
				else
				{
					num3 -= 1f;
					rotation2 = Quaternion.Euler(((Component)HitPiece).transform.eulerAngles.x, ((Component)HitPiece).transform.eulerAngles.y + num4 * num3, ((Component)HitPiece).transform.eulerAngles.z);
				}
				((Component)HitPiece).transform.rotation = rotation2;
			}
			float num5 = 0.1f * currentModificationSpeed;
			if (Input.GetKeyDown((KeyCode)273))
			{
				if (controlFlag)
				{
					((Component)HitPiece).transform.Translate(Vector3.up * num5);
				}
				else
				{
					((Component)HitPiece).transform.Translate(Vector3.forward * num5);
				}
			}
			if (Input.GetKeyDown((KeyCode)274))
			{
				if (controlFlag)
				{
					((Component)HitPiece).transform.Translate(Vector3.down * num5);
				}
				else
				{
					((Component)HitPiece).transform.Translate(Vector3.back * num5);
				}
			}
			if (Input.GetKeyDown((KeyCode)276))
			{
				((Component)HitPiece).transform.Translate(Vector3.left * num5);
			}
			if (Input.GetKeyDown((KeyCode)275))
			{
				((Component)HitPiece).transform.Translate(Vector3.right * num5);
			}
		}

		private static bool hitPieceStillExists()
		{
			try
			{
				if (isActive)
				{
					isInExistence = true;
				}
			}
			catch
			{
				isInExistence = false;
			}
			return isInExistence;
		}

		private static bool isValidRayCastTarget()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			bool result = true;
			if (HitPiece.m_onlyInTeleportArea && !Object.op_Implicit((Object)(object)EffectArea.IsPointInsideArea(((Component)HitPiece).transform.position, (Type)16, 0f)))
			{
				result = false;
			}
			if (!HitPiece.m_allowedInDungeons && ((Component)HitPiece).transform.position.y > 3000f)
			{
				result = false;
			}
			if (Location.IsInsideNoBuildLocation(((Component)HitPiece).transform.position))
			{
				result = false;
			}
			float num = (Object.op_Implicit((Object)(object)((Component)HitPiece).GetComponent<PrivateArea>()) ? ((Component)HitPiece).GetComponent<PrivateArea>().m_radius : 0f);
			if (!PrivateArea.CheckAccess(((Component)HitPiece).transform.position, num, true, false))
			{
				result = false;
			}
			return result;
		}

		private static bool isInBuildMode()
		{
			return ((Character)PlayerInstance).InPlaceMode();
		}

		private static void resetObjectTransform()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			notifyUser("Object has been reset to initial position & rotation.", (MessageType)1);
			((Component)HitPiece).transform.position = InitialPosition;
			((Component)HitPiece).transform.rotation = InitialRotation;
		}

		private static void resetObjectInfo()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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)
			HitPoint = Vector3.zero;
			HitNormal = Vector3.zero;
			HitObject = null;
			HitPiece = null;
			HitHeightmap = null;
			InitialRotation = default(Quaternion);
			InitialPosition = default(Vector3);
		}

		private static void startMode()
		{
			notifyUser("Entering AEM", (MessageType)1);
			isActive = true;
		}

		private static void exitMode()
		{
			notifyUser("Exiting AEM", (MessageType)1);
			forceExitNextIteration = true;
		}

		private static void notifyUser(string Message, MessageType position = (MessageType)1)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			MessageHud.instance.ShowMessage(position, "AEM: " + Message, 0, (Sprite)null, false, true);
		}

		private static void isRunning()
		{
			if (isActive)
			{
				MessageHud.instance.ShowMessage((MessageType)2, "AEM is active", 0, (Sprite)null, false, true);
			}
		}

		private static bool isContainer()
		{
			return (Object)(object)((Component)HitPiece).GetComponent<Container>() != (Object)null;
		}

		private static void dropContainerContents()
		{
			((Component)HitPiece).GetComponent<Container>().DropAllItems();
		}

		private static void changeModificationSpeed()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			float num = 1f;
			if (shiftFlag)
			{
				num = 10f;
			}
			if (Input.GetKeyDown(Configuration.Current.AdvancedEditingMode.increaseScrollSpeed))
			{
				currentModificationSpeed = Mathf.Clamp(currentModificationSpeed + num, 1f, 30f);
				notifyUser("Modification Speed: " + currentModificationSpeed, (MessageType)1);
			}
			if (Input.GetKeyDown(Configuration.Current.AdvancedEditingMode.decreaseScrollSpeed))
			{
				currentModificationSpeed = Mathf.Clamp(currentModificationSpeed - num, 1f, 30f);
				notifyUser("Modification Speed: " + currentModificationSpeed, (MessageType)1);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
	public static class Player_UpdatePlacementGhost_Transpile
	{
		private static readonly MethodInfo Method_Quaternion_Euler = AccessTools.Method(typeof(Quaternion), "Euler", new Type[3]
		{
			typeof(float),
			typeof(float),
			typeof(float)
		}, (Type[])null);

		private static readonly MethodInfo Method_GetRotation = AccessTools.Method(typeof(Player_UpdatePlacementGhost_Transpile), "GetRotation", (Type[])null, (Type[])null);

		[UsedImplicitly]
		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			if (!Configuration.Current.FreePlacementRotation.IsEnabled)
			{
				return instructions;
			}
			List<CodeInstruction> list = instructions.ToList();
			try
			{
				return new CodeMatcher((IEnumerable<CodeInstruction>)list, (ILGenerator)null).MatchEndForward((CodeMatch[])(object)new CodeMatch[1]
				{
					new CodeMatch((OpCode?)OpCodes.Call, (object)Method_Quaternion_Euler, (string)null)
				}).ThrowIfNotMatch("Could not find Quaternion.Euler call", Array.Empty<CodeMatch>()).Advance(1)
					.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2]
					{
						new CodeInstruction(OpCodes.Ldarg_0, (object)null),
						new CodeInstruction(OpCodes.Call, (object)Method_GetRotation)
					})
					.InstructionEnumeration();
			}
			catch (Exception exception)
			{
				PatchLog.Failed("Player_UpdatePlacementGhost_Transpile", "Free placement rotation will not work.", exception);
				return list;
			}
		}

		public static Quaternion GetRotation(Quaternion quaternion, Player __instance)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (ABM.isActive)
			{
				return quaternion;
			}
			FreePlacementRotation.PlayerData value;
			return Quaternion.Euler(FreePlacementRotation.PlayersData.TryGetValue(__instance, out value) ? value.PlaceRotation : ((float)__instance.m_placeRotation * 22.5f * Vector3.up));
		}
	}
	public static class FreePlacementRotation
	{
		public class PlayerData
		{
			public Vector3 PlaceRotation = Vector3.zero;

			public bool Opposite;

			public Piece LastPiece;

			public KeyCode LastKeyCode;
		}

		[HarmonyPatch(typeof(Player), "UpdatePlacement")]
		public static class ModifyPUpdatePlacement
		{
			[UsedImplicitly]
			private static void Postfix(Player __instance, bool takeInput, float dt)
			{
				//IL_0056: Unknown result type (might be due to invalid IL or missing references)
				//IL_0063: Unknown result type (might be due to invalid IL or missing references)
				FreePlacementRotationConfiguration freePlacementRotation = Configuration.Current.FreePlacementRotation;
				if (freePlacementRotation.IsEnabled && !ABM.isActive && ((Character)__instance).InPlaceMode() && takeInput && !Hud.IsPieceSelectionVisible())
				{
					if (!PlayersData.ContainsKey(__instance))
					{
						PlayersData[__instance] = new PlayerData();
					}
					RotateWithWheel(__instance);
					SyncRotationWithTargetInFront(__instance, freePlacementRotation.copyRotationParallel, perpendicular: false);
					SyncRotationWithTargetInFront(__instance, freePlacementRotation.copyRotationPerpendicular, perpendicular: true);
				}
			}

			private static void RotateWithWheel(Player __instance)
			{
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0090: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: Unknown result type (might be due to invalid IL or missing references)
				//IL_004f: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: 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_0064: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
				//IL_009e: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_012d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0132: Unknown result type (might be due to invalid IL or missing references)
				//IL_0137: Unknown result type (might be due to invalid IL or missing references)
				//IL_0121: Unknown result type (might be due to invalid IL or missing references)
				//IL_0126: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
				float axis = Input.GetAxis("Mouse ScrollWheel");
				PlayerData playerData = PlayersData[__instance];
				if (!axis.Equals(0f) || ZInput.GetButton("JoyRotate"))
				{
					if (Input.GetKey(Configuration.Current.FreePlacementRotation.rotateY))
					{
						playerData.PlaceRotation += Vector3.up * Mathf.Sign(axis);
						__instance.m_placeRotation = (int)(playerData.PlaceRotation.y / 22.5f);
					}
					else if (Input.GetKey(Configuration.Current.FreePlacementRotation.rotateX))
					{
						playerData.PlaceRotation += Vector3.right * Mathf.Sign(axis);
					}
					else if (Input.GetKey(Configuration.Current.FreePlacementRotation.rotateZ))
					{
						playerData.PlaceRotation += Vector3.forward * Mathf.Sign(axis);
					}
					else
					{
						__instance.m_placeRotation = ClampPlaceRotation(__instance.m_placeRotation);
						playerData.PlaceRotation = new Vector3(0f, (float)__instance.m_placeRotation * 22.5f, 0f);
					}
					playerData.PlaceRotation = ClampAngles(playerData.PlaceRotation);
				}
			}

			private static void SyncRotationWithTargetInFront(Player __instance, KeyCode keyCode, bool perpendicular)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//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_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_0060: Unknown result type (might be due to invalid IL or missing references)
				//IL_0065: Unknown result type (might be due to invalid IL or missing references)
				//IL_006a: Unknown result type (might be due to invalid IL or missing references)
				//IL_008a: Unknown result type (might be due to invalid IL or missing references)
				//IL_008b: 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_00d1: 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_00af: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val = default(Vector3);
				Vector3 val2 = default(Vector3);
				Piece val3 = default(Piece);
				Heightmap val4 = default(Heightmap);
				Collider val5 = default(Collider);
				if (!((Object)(object)__instance.m_placementGhost == (Object)null) && Input.GetKeyUp(keyCode) && __instance.PieceRayTest(ref val, ref val2, ref val3, ref val4, ref val5, false) && !((Object)(object)val3 == (Object)null))
				{
					PlayerData playerData = PlayersData[__instance];
					Quaternion val6 = ((Component)val3).transform.rotation;
					if (perpendicular)
					{
						val6 *= Quaternion.Euler(0f, 90f, 0f);
					}
					if (playerData.LastKeyCode != keyCode || (Object)(object)playerData.LastPiece != (Object)(object)val3)
					{
						playerData.Opposite = false;
					}
					playerData.LastKeyCode = keyCode;
					playerData.LastPiece = val3;
					if (playerData.Opposite)
					{
						val6 *= Quaternion.Euler(0f, 180f, 0f);
					}
					playerData.Opposite = !playerData.Opposite;
					playerData.PlaceRotation = ((Quaternion)(ref val6)).eulerAngles;
				}
			}
		}

		public static readonly Dictionary<Player, PlayerData> PlayersData = new Dictionary<Player, PlayerData>();

		private const int MaxIndex = 16;

		private static Vector3 ClampAngles(Vector3 angles)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(ClampAngle(angles.x), ClampAngle(angles.y), ClampAngle(angles.z));
		}

		private static int ClampPlaceRotation(int index)
		{
			if (index >= 0)
			{
				if (index >= 16)
				{
					return index - 16;
				}
				return index;
			}
			return 16 + index;
		}

		private static float ClampAngle(float angle)
		{
			if (!(angle < 0f))
			{
				if (angle >= 360f)
				{
					return angle - 360f;
				}
				return angle;
			}
			return 360f + angle;
		}
	}
	[HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")]
	public static class CharacterDrop_GenerateDropList_Patch
	{
		private static void Prefix(ref List<Drop> ___m_drops, out List<Drop> __state)
		{
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: 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_019c: 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_01bb: Expected O, but got Unknown
			__state = null;
			LootDropConfiguration lootDrop = Configuration.Current.LootDrop;
			MouldsConfiguration moulds = Configuration.Current.Moulds;
			bool isEnabled = lootDrop.IsEnabled;
			bool isEnabled2 = moulds.IsEnabled;
			if (!isEnabled && !isEnabled2)
			{
				return;
			}
			List<Drop> list = new List<Drop>(___m_drops.Count);
			bool flag = isEnabled;
			ItemDrop val = default(ItemDrop);
			foreach (Drop ___m_drop in ___m_drops)
			{
				if ((Object)(object)___m_drop.m_prefab == (Object)null || !___m_drop.m_prefab.TryGetComponent<ItemDrop>(ref val))
				{
					list.Add(___m_drop);
					continue;
				}
				float num = (isEnabled2 ? GetMouldModifier(((Object)___m_drop.m_prefab).name, moulds) : 0f);
				bool flag2 = num != 0f && !float.IsNaN(num);
				if (!isEnabled && !flag2)
				{
					list.Add(___m_drop);
					continue;
				}
				float num2 = (isEnabled ? Helper.applyModifierValue(___m_drop.m_chance, lootDrop.lootDropChanceMultiplier) : ___m_drop.m_chance);
				if (flag2)
				{
					flag = true;
					num2 = Helper.applyModifierValue(num2, num);
					num2 = Math.Min(1f, num2);
				}
				if (num2 > 0f)
				{
					list.Add(new Drop
					{
						m_prefab = ___m_drop.m_prefab,
						m_amountMin = (isEnabled ? ((int)Helper.applyModifierValue(___m_drop.m_amountMin, lootDrop.lootDropAmountMultiplier)) : ___m_drop.m_amountMin),
						m_amountMax = (isEnabled ? ((int)Helper.applyModifierValue(___m_drop.m_amountMax, lootDrop.lootDropAmountMultiplier)) : ___m_drop.m_amountMax),
						m_chance = num2,
						m_onePerPlayer = ___m_drop.m_onePerPlayer,
						m_levelMultiplier = ___m_drop.m_levelMultiplier,
						m_levelMultiplierNotAmount = ___m_drop.m_levelMultiplierNotAmount,
						m_dontScale = ___m_drop.m_dontScale
					});
				}
			}
			if (flag)
			{
				__state = ___m_drops;
				___m_drops = list;
			}
		}

		private static float GetMouldModifier(string prefabName, MouldsConfiguration config)
		{
			switch (prefabName)
			{
			case "MoldArmorMageChest":
			case "MoldArmorMageHelmet":
			case "MoldArmorMageLegs":
				return config.callerDropChanceMultiplier;
			case "MoldArmorMediumLegs":
			case "MoldArmormediumChest":
			case "MoldArmorMediumHelmet":
				return config.vanguardDropChanceMultiplier;
			case "MoldArmorGoldChest":
			case "MoldArmorGoldHelmet":
			case "MoldArmorGoldLegs":
				return config.protectorDropChanceMultiplier;
			default:
				return 0f;
			}
		}

		private static void Postfix(ref List<Drop> ___m_drops, ref List<Drop> __state)
		{
			RestoreDrops(ref ___m_drops, ref __state);
		}

		private static void Finalizer(ref List<Drop> ___m_drops, ref List<Drop> __state)
		{
			RestoreDrops(ref ___m_drops, ref __state);
		}

		private static void RestoreDrops(ref List<Drop> drops, ref List<Drop> state)
		{
			if (state != null)
			{
				drops = state;
				state = null;
			}
		}
	}
	[HarmonyPatch(typeof(Piece), "DropResources")]
	public static class Piece_DropResources_Transpiler
	{
		private static MethodInfo method_Piece_IsPlacedByPlayer = AccessTools.Method(typeof(Piece), "IsPlacedByPlayer", (Type[])null, (Type[])null);

		private static FieldInfo field_Requirement_m_recover = AccessTools.Field(typeof(Requirement), "m_recover");

		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			if (!Configuration.Current.Building.IsEnabled)
			{
				return instructions;
			}
			List<CodeInstruction> list = instructions.ToList();
			if (Configuration.Current.Building.alwaysDropResources)
			{
				for (int i = 0; i < list.Count; i++)
				{
					if (CodeInstructionExtensions.Calls(list[i], method_Piece_IsPlacedByPlayer))
					{
						list[i] = new CodeInstruction(OpCodes.Ldc_I4_1, (object)null);
						list.RemoveAt(i - 1);
					}
				}
			}
			if (Configuration.Current.Building.alwaysDropExcludedResources)
			{
				for (int j = 0; j < list.Count; j++)
				{
					if (CodeInstructionExtensions.LoadsField(list[j], field_Requirement_m_recover, false))
					{
						list.RemoveRange(j - 1, 3);
					}
				}
			}
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch(typeof(StationExtension), "Awake")]
	public static class StationExtension_Awake_Patch
	{
		[HarmonyPrefix]
		public static void Prefix(ref float ___m_maxStationDistance)
		{
			if (Configuration.Current.Workbench.IsEnabled)
			{
				___m_maxStationDistance = Configuration.Current.Workbench.workbenchAttachmentRange;
			}
		}
	}
	internal static class InventoryAssistant
	{
		private struct ChestPrefab
		{
			public bool IsPublicPieceContainer;

			public bool IsCart;

			public bool IsShip;
		}

		private const float ChestRangeSlack = 2f;

		private static readonly List<ZDO> NearbyZdos = new List<ZDO>();

		private static readonly Dictionary<int, ChestPrefab> ChestPrefabs = new Dictionary<int, ChestPrefab>();

		public static List<Container> GetNearbyChests(GameObject target, float range, bool checkWard = true, bool includeVehicles = true)
		{
			if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				return new List<Container>();
			}
			long playerId = Player.m_localPlayer.GetPlayerID();
			return FindNearbyChests(target, range, includeVehicles, (Container container, Vector3 position) => container.CheckAccess(playerId) && (!checkWard || PrivateArea.CheckAccess(position, 0f, false, true)));
		}

		public static List<Container> GetNearbyChestsForMachine(GameObject machine, float range, bool checkWard = true)
		{
			//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)
			Vector3 machinePosition = machine.transform.position;
			return FindNearbyChests(machine, range, includeVehicles: true, (Container container, Vector3 position) => (int)container.m_privacy == 2 && (!checkWard || SharesWards(machinePosition, position)));
		}

		private static bool SharesWards(Vector3 machine, Vector3 chest)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			foreach (PrivateArea allArea in PrivateArea.m_allAreas)
			{
				if (Object.op_Implicit((Object)(object)allArea) && allArea.IsEnabled() && allArea.IsInside(chest, 0f) && !allArea.IsInside(machine, 0f))
				{
					return false;
				}
			}
			return true;
		}

		public static bool NearbyChestsLoaded(Vector3 position, float range)
		{
			//IL_000f: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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)
			NearbyZdos.Clear();
			ZDOMan.instance.FindSectorObjects(ZoneSystem.GetZone(position), new SimulationDistance(1, 0, false), NearbyZdos, (List<ZDO>)null);
			foreach (ZDO nearbyZdo in NearbyZdos)
			{
				Vector3 position2 = nearbyZdo.GetPosition();
				if (!(Vector3.Distance(position, position2) > range + 2f) && MachineCouldUseChest(nearbyZdo) && SpawnsOnThisPeer(position2))
				{
					ZNetView val = ZNetScene.instance.FindInstance(nearbyZdo);
					if (!Object.op_Implicit((Object)(object)val))
					{
						return false;
					}
					Container componentInChildren = ((Component)val).GetComponentInChildren<Container>();
					if (Object.op_Implicit((Object)(object)componentInChildren) && componentInChildren.m_lastRevision == uint.MaxValue)
					{
						return false;
					}
				}
			}
			return true;
		}

		public static bool SpawnsOnThisPeer(Vector3 position)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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_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_001b: 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_0021: 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_0030: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			SimulationDistance syncedSimulationDistance = ZNet.instance.GetSyncedSimulationDistance();
			Vector2s zone = ZoneSystem.GetZone(ZNet.instance.GetReferencePosition());
			Vector2s zone2 = ZoneSystem.GetZone(position);
			int nearSimulationDistance = ((SimulationDistance)(ref syncedSimulationDistance)).NearSimulationDistance;
			if (Mathf.Abs(zone2.x - zone.x) <= nearSimulationDistance && Mathf.Abs(zone2.y - zone.y) <= nearSimulationDistance)
			{
				if (!((SimulationDistance)(ref syncedSimulationDistance)).IsClassic)
				{
					return ZoneSystem.instance.ZonesWithinRadius(zone, zone2, nearSimulationDistance, false);
				}
				return true;
			}
			return false;
		}

		public static bool MachineCouldUseChest(ZDO zdo)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Invalid comparison between Unknown and I4
			int prefab = zdo.GetPrefab();
			if (!ChestPrefabs.TryGetValue(prefab, out var value))
			{
				GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab);
				Container val = (((Object)(object)prefab2 != (Object)null) ? prefab2.GetComponentInChildren<Container>(true) : null);
				if ((Object)(object)val != (Object)null)
				{
					value.IsPublicPieceContainer = (int)val.m_privacy == 2 && (Object)(object)((Component)val).GetComponentInParent<Piece>(true) != (Object)null;
					value.IsCart = (Object)(object)((Component)val).GetComponentInParent<Vagon>(true) != (Object)null;
					value.IsShip = (Object)(object)((Component)val).GetComponentInParent<Ship>(true) != (Object)null;
				}
				ChestPrefabs[prefab] = value;
			}
			if (!value.IsPublicPieceContainer)
			{
				return false;
			}
			CraftFromChestConfiguration craftFromChest = Configuration.Current.CraftFromChest;
			if (value.IsShip)
			{
				return craftFromChest.allowCraftingFromShips;
			}
			if (value.IsCart && !craftFromChest.allowCraftingFromCarts)
			{
				return false;
			}
			return zdo.GetLong(ZDOVars.s_creator, 0L) != 0;
		}

		public static int RemoveItemInAmountFromChests(List<Container> chests, ItemData needle, int amount)
		{
			int num = 0;
			foreach (Container chest in chests)
			{
				if (amount <= 0)
				{
					break;
				}
				int num2 = RemoveItemFromChest(chest, needle, amount);
				num += num2;
				amount -= num2;
			}
			return num;
		}

		private static List<Container> FindNearbyChests(GameObject target, float range, bool includeVehicles, Func<Container, Vector3, bool> hasAccessAt)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			string[] array = new string[1] { "piece" };
			if (includeVehicles && (Configuration.Current.CraftFromChest.allowCraftingFromCarts || Configuration.Current.CraftFromChest.allowCraftingFromShips))
			{
				array = new string[3] { "piece", "item", "vehicle" };
			}
			IOrderedEnumerable<Collider> orderedEnumerable = from x in Physics.OverlapSphere(target.transform.position, range, LayerMask.GetMask(array))
				orderby Vector3.Distance(((Component)x).gameObject.transform.position, target.transform.position)
				select x;
			List<Container> list = new List<Container>();
			foreach (Collider item in orderedEnumerable)
			{
				try
				{
					Container componentInParent = ((Component)item).GetComponentInParent<Container>();
					if (Object.op_Implicit((Object)(object)componentInParent) && componentInParent.m_lastRevision != uint.MaxValue && !list.Contains(componentInParent))
					{
						bool flag = hasAccessAt(componentInParent, ((Component)item).gameObject.transform.position);
						Piece componentInParent2 = ((Component)componentInParent).GetComponentInParent<Piece>();
						bool flag2 = (Object)(object)((Component)componentInParent).GetComponentInParent<Vagon>() != (Object)null;
						bool flag3 = (Object)(object)((Component)componentInParent).GetComponentInParent<Ship>() != (Object)null;
						if ((Object)(object)componentInParent2 != (Object)null && flag && componentInParent.GetInventory() != null && (!flag2 || (includeVehicles && Configuration.Current.CraftFromChest.allowCraftingFromCarts)) && (!flag3 || (includeVehicles && Configuration.Current.CraftFromChest.allowCraftingFromShips)) && (componentInParent2.IsPlacedByPlayer() || (flag3 && Configuration.Current.CraftFromChest.allowCraftingFromShips)))
						{
							list.Add(componentInParent);
						}
					}
				}
				catch (Exception arg)
				{
					ValheimPlusPlugin.Logger.LogDebug((object)$"GetNearbyChests skipped '{((Object)((Component)item).gameObject).name}': {arg}");
				}
			}
			return list;
		}

		public static List<Container> GetNearbyChestsWithItem(GameObject target, float range, ItemData itemInfo, bool checkWard = true)
		{
			List<Container> nearbyChests = GetNearbyChests(target, range, checkWard);
			List<Container> list = new List<Container>();
			foreach (Container item in nearbyChests)
			{
				if (ChestContainsItem(item, itemInfo))
				{
					list.Add(item);
				}
			}
			return list;
		}

		public static bool ChestContainsItem(Container chest, ItemData needle)
		{
			foreach (ItemData allItem in chest.GetInventory().GetAllItems())
			{
				if (allItem.m_shared.m_name == needle.m_shared.m_name)
				{
					return true;
				}
			}
			return false;
		}

		public static bool ChestContainsItem(Container chest, string needle)
		{
			foreach (ItemData allItem in chest.GetInventory().GetAllItems())
			{
				if (allItem.m_shared.m_name == needle)
				{
					return true;
				}
			}
			return false;
		}

		public static List<ItemData> GetNearbyChestItems(GameObject target, float range = 10f, bool checkWard = true)
		{
			List<ItemData> list = new List<ItemData>();
			foreach (Container nearbyChest in GetNearbyChests(target, range, checkWard))
			{
				foreach (ItemData allItem in nearbyChest.GetInventory().GetAllItems())
				{
					list.Add(allItem);
				}
			}
			return list;
		}

		public static List<ItemData> GetNearbyChestItemsByContainerList(List<Container> nearbyChests)
		{
			List<ItemData> list = new List<ItemData>();
			foreach (Container nearbyChest in nearbyChests)
			{
				foreach (ItemData allItem in nearbyChest.GetInventory().GetAllItems())
				{
					list.Add(allItem);
				}
			}
			return list;
		}

		public static int GetItemAmountInItemList(List<ItemData> itemList, ItemData item, int quality = -1, bool matchWorldLevel = true)
		{
			return itemList.Where((ItemData current) => current.m_shared.m_name == item.m_shared.m_name && (quality < 0 || quality == current.m_quality) && (!matchWorldLevel || current.m_worldLevel >= Game.m_worldLevel)).Sum((ItemData current) => current.m_stack);
		}

		public static int GetItemAmountInItemList(List<ItemData> itemList, string name, int quality = -1, bool matchWorldLevel = true)
		{
			return itemList.Where((ItemData current) => current.m_shared.m_name == name && (quality < 0 || quality == current.m_quality) && (!matchWorldLevel || current.m_worldLevel >= Game.m_worldLevel)).Sum((ItemData current) => current.m_stack);
		}

		public static int RemoveItemInAmountFromAllNearbyChests(GameObject target, float range, ItemData needle, int amount, bool checkWard = true)
		{
			List<Container> nearbyChests = GetNearbyChests(target, range, checkWard);
			GetItemAmountInItemList(GetNearbyChestItemsByContainerList(nearbyChests), needle);
			if (amount == 0)
			{
				return 0;
			}
			int num = 0;
			foreach (Container item in nearbyChests)
			{
				if (num != amount)
				{
					int num2 = RemoveItemFromChest(item, needle, amount);
					num += num2;
					amount -= num2;
				}
			}
			return num;
		}

		public static int RemoveItemInAmountFromAllNearbyChests(GameObject target, float range, string needle, int amount, bool checkWard = true)
		{
			List<Container> nearbyChests = GetNearbyChests(target, range, checkWard);
			GetItemAmountInItemList(GetNearbyChestItemsByContainerList(nearbyChests), needle);
			if (amount == 0)
			{
				return 0;
			}
			int num = 0;
			foreach (Container item in nearbyChests)
			{
				if (num != amount)
				{
					int num2 = RemoveItemFromChest(item, needle, amount);
					num += num2;
					amount -= num2;
				}
			}
			return num;
		}

		public static int RemoveItemFromChest(Container chest, ItemData needle, int amount = 1)
		{
			if (!ChestContainsItem(chest, needle))
			{
				return 0;
			}
			int num = 0;
			List<ItemData> allItems = chest.GetInventory().GetAllItems();
			foreach (ItemData item in allItems)
			{
				if (item.m_shared.m_name == needle.m_shared.m_name)
				{
					int num2 = Mathf.Min(item.m_stack, amount);
					item.m_stack -= num2;
					amount -= num2;
					num += num2;
					if (amount <= 0)
					{
						break;
					}
				}
			}
			if (num == 0)
			{
				return 0;
			}
			allItems.RemoveAll((ItemData x) => x.m_stack <= 0);
			chest.m_inventory.m_inventory = allItems;
			ConveyContainerToNetwork(chest);
			return num;
		}

		public static int RemoveItemFromChest(Container chest, string needle, int amount = 1)
		{
			if (!ChestContainsItem(chest, needle))
			{
				return 0;
			}
			int num = 0;
			List<ItemData> allItems = chest.GetInventory().GetAllItems();
			foreach (ItemData item in allItems)
			{
				if (item.m_shared.m_name == needle)
				{
					int num2 = Mathf.Min(item.m_stack, amount);
					item.m_stack -= num2;
					amount -= num2;
					num += num2;
					if (amount <= 0)
					{
						break;
					}
				}
			}
			if (num == 0)
			{
				return 0;
			}
			allItems.RemoveAll((ItemData x) => x.m_stack <= 0);
			chest.m_inventory.m_inventory = allItems;
			ConveyContainerToNetwork(chest);
			return num;
		}

		public static void ConveyContainerToNetwork(Container c)
		{
			c.Save();
			c.GetInventory().Changed(false, false);
		}
	}
	[BepInPlugin("org.bepinex.plugins.valheim_plus", "Valheim Plus (Iceskull Temporary)", "1.3.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class ValheimPlusPlugin : BaseUnityPlugin
	{
		internal const string ValheimPlusGuid = "org.bepinex.plugins.valheim_plus";

		internal const string ForkName = "Iceskull Temporary";

		internal const string ValheimPlusName = "Valheim Plus (Iceskull Temporary)";

		public const string NumericVersion = "1.3.1";

		private const string VersionExtra = "";

		public const string FullVersion = "1.3.1";

		internal const string DisplayVersion = "ValheimPlus 1.3.1 (Iceskull Temporary)";

		internal const string MinRequiredNumericVersion = "1.3.1";

		private static readonly GameVersion MinSupportedGameVersion = new GameVersion(1, 0, 20);

		private static readonly GameVersion TargetGameVersion = new GameVersion(1, 0, 20);

		private static readonly Dictionary<GameVersion, string> ExcludeGameVersions = new Dictionary<GameVersion, string>();

		public static readonly Timer MapSyncSaveTimer = new Timer(TimeSpan.FromMinutes(5.0).TotalMilliseconds);

		public static readonly string VPlusDataDirectoryPath;

		private static readonly Harmony Harmony;

		private static bool configLoaded;

		public const string Repository = "https://github.com/Iceskull7/ValheimPlus/releases/latest";

		private const string ApiRepository = "https://api.github.com/repos/Iceskull7/ValheimPlus/releases/latest";

		internal static string newestVersion { get; private set; } = "";

		internal static bool isUpToDate { get; private set; }

		public static ManualLogSource Logger { get; private set; }

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			Logger.LogInfo((object)("Valheim Plus dll file location: '" + ((object)this).GetType().Assembly.Location + "'"));
			bool num = IsGameVersionTooOld();
			if (num)
			{
				LogTooOld();
			}
			bool flag = CheckIsGameVersionExcluded();
			if (num || flag)
			{
				Logger.LogFatal((object)"Aborting loading of Valheim Plus due to incompatible version.");
				return;
			}
			try
			{
				BepInExConfig.Load(((BaseUnityPlugin)this).Config);
				configLoaded = true;
				Logger.LogInfo((object)("Configuration loaded successfully from '" + ((BaseUnityPlugin)this).Config.ConfigFilePath + "'."));
				PatchAll();
				isUpToDate = !IsNewVersionAvailable();
				if (!isUpToDate)
				{
					Logger.LogWarning((object)"There is a newer version available of ValheimPlus. Please visit https://github.com/Iceskull7/ValheimPlus/releases/latest.");
				}
				if (!Directory.Exists(VPlusDataDirectoryPath))
				{
					Directory.CreateDirectory(VPlusDataDirectoryPath);
				}
				MapConfiguration map = Configuration.Current.Map;
				if (!ZNet.m_isServer || !map.IsEnabled || (!map.shareMapProgression && !map.syncPins))
				{
					return;
				}
				MapSyncSaveTimer.AutoReset = true;
				if (map.shareMapProgression)
				{
					MapSyncSaveTimer.Elapsed += delegate
					{
						VPlusMapSync.SaveMapDataToDisk();
					};
				}
				if (map.syncPins)
				{
					MapSyncSaveTimer.Elapsed += delegate
					{
						VPlusMapPinSync.SavePinsToDisk();
					};
				}
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"Error while loading the configuration: {arg}");
			}
		}

		private void Start()
		{
			if (configLoaded)
			{
				BepInExConfig.ResolveModConflicts();
			}
		}

		private static bool IsGameVersionTooOld()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return Version.CurrentVersion < MinSupportedGameVersion;
		}

		private static bool IsGameVersionNewerThanTarget()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return Version.CurrentVersion > TargetGameVersion;
		}

		private static bool CheckIsGameVersionExcluded()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			string value;
			bool num = ExcludeGameVersions.TryGetValue(Version.CurrentVersion, out value);
			if (num)
			{
				Logger.LogError((object)value);
			}
			return num;
		}

		private static bool IsNewVersionAvailable()
		{
			try
			{
				string input = HttpHelper.DownloadString("https://api.github.com/repos/Iceskull7/ValheimPlus/releases/latest");
				newestVersion = new Regex("\"tag_name\":\"([^\"]*)?\"").Match(input).Groups[1].Value;
			}
			catch
			{
				Logger.LogWarning((object)"The newest version could not be determined.");
				newestVersion = "Unknown";
			}
			if (Version.TryParse(newestVersion, out Version result))
			{
				if (Version.TryParse("1.3.1", out Version result2))
				{
					if (result2 < result)
					{
						return true;
					}
				}
				else
				{
					Logger.LogWarning((object)"Couldn't parse current version");
				}
			}
			else
			{
				Logger.LogWarning((object)"Couldn't parse newest version, comparing version strings with equality.");
				if (newestVersion != "1.3.1")
				{
					return true;
				}
			}
			return false;
		}

		public static void PatchAll()
		{
			//IL_0114: 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)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			Logger.LogDebug((object)"Applying patches.");
			try
			{
				Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(typeof(ValheimPlusPlugin).Assembly);
				foreach (Type type in typesFromAssembly)
				{
					if (!ConfigSyncGlue.IsServerSyncType(type))
					{
						Harmony.CreateClassProcessor(type).Patch();
					}
				}
				if (AppDomain.CurrentDomain.GetAssemblies().Any((Assembly assembly) => assembly.FullName.Contains("assembly_steamworks")))
				{
					Harmony.Patch((MethodBase)AccessTools.TypeByName("SteamGameServer").GetMethod("SetMaxPlayerCount"), new HarmonyMethod(typeof(ChangeSteamServerVariables).GetMethod("Prefix")), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				ConfigSyncGlue.SetModRequired(Configuration.Current.Server.enforceMod);
				Logger.LogDebug((object)"Patches successfully applied.");
			}
			catch (Exception)
			{
				Logger.LogError((object)"Failed to apply patches.");
				if (IsGameVersionTooOld())
				{
					LogTooOld();
				}
				else if (IsGameVersionNewerThanTarget())
				{
					Logger.LogWarning((object)("This version of Valheim Plus (1.3.1) was compiled with a game version of " + $"\"{TargetGameVersion}\", but this game version is newer at \"{Version.CurrentVersion}\". " + "If you are using the PTB, you likely need to use the non-beta version of the game. Otherwise, the errors seen above likely will require the Valheim Plus mod to be updated. If a game update just came out for Valheim, this may take some time for the mod to be updated. See https://github.com/Iceskull7/ValheimPlus/blob/main/COMPATIBILITY.md for what game versions are compatible with what mod versions."));
				}
				else
				{
					Logger.LogWarning((object)("Valheim Plus failed to apply patches. Please ensure the game version (" + Version.GetVersionString(false) + ") is compatible with the Valheim Plus version (1.3.1) at https://github.com/Iceskull7/ValheimPlus/blob/main/COMPATIBILITY.md. If it already is, please report a bug at https://github.com/Iceskull7/ValheimPlus/issues."));
				}
				throw;
			}
		}

		private static void LogTooOld()
		{
			//IL_000f: 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)
			Logger.LogError((object)("This version of Valheim Plus (1.3.1) expects a minimum game version of " + $"\"{MinSupportedGameVersion}\", but this game version is older at \"{Version.CurrentVersion}\". " + "Please either update the Valheim game, or use an older version of Valheim Plus as per https://github.com/Iceskull7/ValheimPlus/blob/main/COMPATIBILITY.md."));
		}

		public static void UnpatchSelf()
		{
			Logger.LogDebug((object)"Unpatching.");
			try
			{
				Harmony.UnpatchSelf();
				Logger.LogDebug((object)"Successfully unpatched.");
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"Failed to unpatch. Exception: {arg}");
			}
		}

		static ValheimPlusPlugin()
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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_0080: Expected O, but got Unknown
			string bepInExRootPath = Paths.BepInExRootPath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			VPlusDataDirectoryPath = bepInExRootPath + directorySeparatorChar + "vplus-data";
			Harmony = new Harmony("mod.valheim_plus");
		}
	}
	internal static class Helper
	{
		private const BindingFlags FieldBindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		public static Character getPlayerCharacter(Player __instance)
		{
			return (Character)(object)__instance;
		}

		public static Player getPlayerBySenderId(long id)
		{
			//IL_001b: 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_0021: 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)
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				ZDOID zDOID = getPlayerCharacter(allPlayer).GetZDOID();
				if (zDOID != new ZDOID(0L, 0u) && ((ZDOID)(ref zDOID)).UserID == id)
				{
					return allPlayer;
				}
			}
			return null;
		}

		public static bool IsSenderPlayerInRange(long senderId, float range)
		{
			//IL_000b: 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)
			return Vector3.Distance(((Component)getPlayerBySenderId(senderId)).transform.position, ((Component)Player.m_localPlayer).transform.position) <= range;
		}

		public static float tFloat(this float value, int digits)
		{
			double num = Math.Pow(10.0, digits);
			return (float)(Math.Truncate(num * (double)value) / num);
		}

		public static float applyModifierValue(float targetValue, float value)
		{
			if (!(value <= -100f))
			{
				return targetValue + targetValue / 100f * value;
			}
			return 0f;
		}

		public static void applyModifierValueTo(ref float targetValue, float modifier)
		{
			targetValue = ((modifier <= -100f) ? 0f : (targetValue + targetValue / 100f * modifier));
		}

		public static int applyModifierValueWithChance(float targetValue, float value)
		{
			float num = applyModifierValue(targetValue, value);
			if (num == 0f)
			{
				return 0;
			}
			int num2 = (int)Math.Floor(num);
			return num2 + (((double)(num - (float)num2) > 1.0 - new Random().NextDouble()) ? 1 : 0);
		}

		public static string CreateMD5(string input)
		{
			using MD5 mD = MD5.Create();
			byte[] bytes = Encoding.ASCII.GetBytes(input);
			byte[] array = mD.ComputeHash(bytes);
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < array.Length; i++)
			{
				stringBuilder.Append(array[i].ToString("X2"));
			}
			return stringBuilder.ToString();
		}

		public static void ResizeChildEffectArea(MonoBehaviour parent, Type includedTypes, float newRadius)
		{
			//IL_001a: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)parent != (Object)null))
			{
				return;
			}
			EffectArea componentInChildren = ((Component)parent).GetComponentInChildren<EffectArea>();
			if ((Object)(object)componentInChildren != (Object)null && (componentInChildren.m_type & includedTypes) != 0)
			{
				SphereCollider component = ((Component)componentInChildren).GetComponent<SphereCollider>();
				if ((Object)(object)component != (Object)null)
				{
					component.radius = newRadius;
				}
			}
		}

		public static int Clamp(int value, int min, int max)
		{
			return Math.Min(max, Math.Max(min, value));
		}

		public static float Clamp(float value, float min, float max)
		{
			return Math.Min(max, Math.Max(min, value));
		}

		public static bool SetFieldIfFound(object obj, string field, object value)
		{
			FieldInfo field2 = obj.GetType().GetField(field, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field2 == null)
			{
				return false;
			}
			field2.SetValue(obj, value);
			return true;
		}
	}
	public static class VPlusDataObjects
	{
		public class MapRange
		{
			public int StartingX;

			public int EndingX;

			public int Y;
		}
	}
}
namespace ValheimPlus.Http
{
	public static class HttpHelper
	{
		private const string UserAgent = "ValheimPlusClient/1.0";

		public static string DownloadString(string url, TimeSpan? timeout = null)
		{
			//IL_0078: 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_0085: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			if (string.IsNullOrWhiteSpace(url))
			{
				throw new ArgumentException("url is null or empty", "url");
			}
			if (!Uri.TryCreate(url, UriKind.Absolute, out Uri result) || (result.Scheme != Uri.UriSchemeHttp && result.Scheme != Uri.UriSchemeHttps))
			{
				throw new ArgumentException("Invalid URL scheme: '" + url + "'", "url");
			}
			try
			{
				ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
			}
			catch
			{
			}
			HttpClientHandler val = new HttpClientHandler
			{
				AllowAutoRedirect = true
			};
			try
			{
				HttpClient val2 = new HttpClient((HttpMessageHandler)(object)val);
				try
				{
					val2.Timeout = timeout ?? TimeSpan.FromSeconds(20.0);
					val2.DefaultRequestHeaders.UserAgent.Clear();
					val2.DefaultRequestHeaders.UserAgent.ParseAdd("ValheimPlusClient/1.0");
					val2.DefaultRequestHeaders.Accept.Clear();
					val2.DefaultRequestHeaders.Accept.ParseAdd("*/*");
					HttpResponseMessage result2 = val2.GetAsync(result).GetAwaiter().GetResult();
					result2.EnsureSuccessStatusCode();
					return result2.Content.ReadAsStringAsync().GetAwaiter().GetResult();
				}
				finally
				{
					((IDisposable)val2)?.Dispose();
				}
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}
	}
}
namespace ValheimPlus.Utility
{
	internal static class GameObjectAssistant
	{
		private static readonly ConcurrentDictionary<float, Stopwatch> Stopwatches = new ConcurrentDictionary<float, Stopwatch>();

		private static readonly MethodInfo InvokeRepeatingMethod = AccessTools.Method(typeof(MonoBehaviour), "InvokeRepeating", (Type[])null, (Type[])null);

		private const float ChestPollInterval = 1f;

		private const float MaxChestWait = 10f;

		public static Stopwatch GetStopwatch(GameObject o)
		{
			float gameObjectPositionHash = GetGameObjectPositionHash(o);
			if (Stopwatches.TryGetValue(gameObjectPositionHash, out var value))
			{
				return value;
			}
			value = new Stopwatch();
			Stopwatches.TryAdd(gameObjectPositionHash, value);
			return value;
		}

		public static float GetGameObjectPositionHash(GameObject obj)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = obj.transform.position;
			return 1000f * position.x + position.y + 0.001f * position.z;
		}

		public static IEnumerable<CodeInstruction> ReplaceInvokeRepeating(IEnumerable<CodeInstruction> instructions, string patchName, string methodName, MethodInfo replacement)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			return new CodeMatcher(instructions, (ILGenerator)null).MatchStartForward((CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((OpCode?)OpCodes.Ldstr, (object)methodName, (string)null)
			}).Repeat((Action<CodeMatcher>)delegate(CodeMatcher matcher)
			{
				matcher.SearchForward((Func<CodeInstruction, bool>)((CodeInstruction instruction) => CodeInstructionExtensions.Calls(instruction, InvokeRepeatingMethod))).SetOperandAndAdvance((object)replacement);
			}, (Action<string>)delegate
			{
				PatchLog.Failed(patchName, methodName + " will not wait for nearby chests to load before auto-depositing.");
			}).InstructionEnumeration();
		}

		public static void InvokeRepeatingWhenChestsLoaded(MonoBehaviour machine, string methodName, float delay, float rate, float chestRange)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (chestRange <= 0f || InventoryAssistant.NearbyChestsLoaded(((Component)machine).transform.position, chestRange))
			{
				machine.InvokeRepeating(methodName, delay, rate);
			}
			else
			{
				machine.StartCoroutine(InvokeRepeatingOnceChestsLoaded(machine, methodName, delay, rate, chestRange));
			}
		}

		private static IEnumerator InvokeRepeatingOnceChestsLoaded(MonoBehaviour machine, string methodName, float delay, float rate, float chestRange)
		{
			float waited;
			for (waited = 0f; waited < 10f; waited += 1f)
			{
				if (InventoryAssistant.NearbyChestsLoaded(((Component)machine).transform.position, chestRange))
				{
					break;
				}
				yield return (object)new WaitForSeconds(1f);
			}
			if (waited >= 10f && !InventoryAssistant.NearbyChestsLoaded(((Component)machine).transform.position, chestRange))
			{
				ValheimPlusPlugin.Logger.LogDebug((object)$"{((Object)machine).name} at {((Component)machine).transform.position} gave up waiting {10f}s for nearby chests to load, starting {methodName} anyway.");
			}
			machine.InvokeRepeating(methodName, delay, rate);
		}

		public static T GetChildComponentByName<T>(string name, GameObject objected) where T : Component
		{
			T[] componentsInChildren = objected.GetComponentsInChildren<T>(true);
			foreach (T val in componentsInChildren)
			{
				if (((Object)((Component)val).gameObject).name == name)
				{
					return val;
				}
			}
			return default(T);
		}
	}
	internal static class ChestDeposit
	{
		internal static int Distribute<TChest>(IReadOnlyList<TChest> chests, int amount, Func<TChest, bool> hasItem, Func<TChest, int, int> add, Action<TChest> synchronize)
		{
			for (int i = 0; i < 2; i++)
			{
				if (amount <= 0)
				{
					break;
				}
				foreach (TChest chest in chests)
				{
					if (hasItem(chest) == (i == 0))
					{
						int num = add(chest, amount);
						if (num < amount)
						{
							synchronize(chest);
						}
						amount = num;
						if (amount == 0)
						{
							break;
						}
					}
				}
			}
			return amount;
		}
	}
	public static class ListExtensions
	{
		public static List<List<T>> ChunkBy<T>(this List<T> source, int chunkSize)
		{
			return (from x in source.Select((T x, int i) => new
				{
					Index = i,
					Value = x
				})
				group x by x.Index / chunkSize into x
				select x.Select(v => v.Value).ToList()).ToList();
		}
	}
	public static class PatchLog
	{
		public static void Failed(string patch, string detail = null, Exception exception = null)
		{
			string text = "Failed to apply `" + patch + "`.";
			if (detail != null)
			{
				text = text + " " + detail;
			}
			if (exception != null)
			{
				text += $" Exception is:\n{exception}";
			}
			ValheimPlusPlugin.Logger.LogError((object)text);
		}
	}
	public class RpcData
	{
		public string Name;

		public long Target;

		public object[] Payload;
	}
	public static class RpcQueue
	{
		private static Queue<RpcData> _rpcQueue = new Queue<RpcData>();

		private static bool _ack = true;

		public static void Enqueue(RpcData rpc)
		{
			_rpcQueue.Enqueue(rpc);
		}

		public static bool SendNextRpc()
		{
			if (_rpcQueue.Count == 0 || !_ack)
			{
				return false;
			}
			RpcData rpcData = _rpcQueue.Dequeue();
			if (Utility.IsNullOrWhiteSpace(rpcData.Name) || rpcData.Payload == null)
			{
				return false;
			}
			ZRoutedRpc.instance.InvokeRoutedRPC(rpcData.Target, rpcData.Name, rpcData.Payload);
			_ack = false;
			return true;
		}

		public static void GotAck()
		{
			_ack = true;
		}
	}
	public static class ZPackageExtensions
	{
		public static VPlusDataObjects.MapRange ReadVPlusMapRange(this ZPackage pkg)
		{
			return new VPlusDataObjects.MapRange
			{
				StartingX = pkg.m_reader.ReadInt32(),
				EndingX = pkg.m_reader.ReadInt32(),
				Y = pkg.m_reader.ReadInt32()
			};
		}

		public static void WriteVPlusMapRange(this ZPackage pkg, VPlusDataObjects.MapRange mapRange)
		{
			pkg.m_writer.Write(mapRange.StartingX);
			pkg.m_writer.Write(mapRange.EndingX);
			pkg.m_writer.Write(mapRange.Y);
		}
	}
}
namespace ValheimPlus.UI
{
	[HarmonyPatch(typeof(HotkeyBar), "UpdateIcons")]
	public static class HotkeyBar_UpdateIcons_Patch
	{
		private const string hudObjectNamePrefix = "BowAmmoCounts";

		private const string noAmmoDisplay = "No Ammo";

		private static readonly GameObject[] ammoCounters = (GameObject[])(object)new GameObject[8];

		private static int elementCount = -1;

		private static bool IsEnabled()
		{
			if (Configuration.Current.Hud.IsEnabled)
			{
				return Configuration.Current.Hud.displayBowAmmoCounts > 0;
			}
			return false;
		}

		private static void Prefix(HotkeyBar __instance, Player player)
		{
			if (IsEnabled())
			{
				elementCount = __instance.m_elements.Count;
				if ((Object)(object)player == (Object)null || ((Character)player).IsDead())
				{
					DestroyAllAmmoCounters();
				}
			}
		}

		private static void Postfix(HotkeyBar __instance, Player player)
		{
			if (IsEnabled())
			{
				if (elementCount != __instance.m_elements.Count)
				{
					DestroyAllAmmoCounters();
				}
				if (!((Object)(object)player == (Object)null) && !((Character)player).IsDead())
				{
					DisplayAmmoCountsUnderBowHotbarIcons(__instance, player);
				}
			}
		}

		private static void DisplayAmmoCountsUnderBowHotbarIcons(HotkeyBar __instance, Player player)
		{
			HashSet<int> hashSet = new HashSet<int> { 0, 1, 2, 3, 4, 5, 6, 7 };
			foreach (ItemData item in __instance.m_items)
			{
				if (item != null)
				{
					hashSet.Remove(item.m_gridPos.x);
					DisplayAmmoCountsUnderBowHotbarIcon(__instance, player, item);
				}
			}
			foreach (int item2 in hashSet)
			{
				DestroyAmmoCounter(item2);
			}
		}

		private static void DisplayAmmoCountsUnderBowHotbarIcon(HotkeyBar __instance, Player player, ItemData item)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Invalid comparison between Unknown and I4
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Invalid comparison between Unknown and I4
			int x = item.m_gridPos.x;
			GameObject val = ammoCounters[x];
			if ((int)item.m_shared.m_itemType != 4 || (Configuration.Current.Hud.displayBowAmmoCounts == 1 && !((Humanoid)player).IsItemEquiped(item)) || x >= __instance.m_elements.Count || x < 0)
			{
				DestroyAmmoCounter(x);
				return;
			}
			ElementData val2 = __instance.m_elements[x];
			TMP_Text componentInChildren;
			if ((Object)(object)val == (Object)null)
			{
				GameObject gameObject = ((Component)val2.m_amount).gameObject;
				val = Object.Instantiate<GameObject>(gameObject, gameObject.transform.parent, false);
				((Object)val).name = "BowAmmoCounts" + x;
				val.SetActive(true);
				Vector3 val3 = gameObject.transform.position - ((Component)val2.m_icon).transform.position - new Vector3(0f, 15f);
				val.transform.Translate(val3);
				componentInChildren = val.GetComponentInChildren<TMP_Text>();
				TMP_Text obj = componentInChildren;
				obj.fontSize -= 2f;
				ammoCounters[x] = val;
			}
			else
			{
				componentInChildren = val.GetComponentInChildren<TMP_Text>();
			}
			val.gameObject.transform.SetParent(((Component)val2.m_amount).gameObject.transform.parent, false);
			ItemData ammoItem = ((Humanoid)player).m_ammoItem;
			if (ammoItem == null || ammoItem.m_shared.m_ammoType != item.m_shared.m_ammoType)
			{
				ammoItem = ((Humanoid)player).GetInventory().GetAmmoItem(item.m_shared.m_ammoType, (string)null);
			}
			int num = 0;
			int num2 = 0;
			foreach (ItemData allItem in ((Humanoid)player).GetInventory().GetAllItems())
			{
				if (allItem.m_shared.m_ammoType == item.m_shared.m_ammoType && ((int)allItem.m_shared.m_itemType == 9 || (int)allItem.m_shared.m_itemType == 2))
				{
					num2 += allItem.m_stack;
					if (allItem.m_shared.m_name == ammoItem.m_shared.m_name)
					{
						num += allItem.m_stack;
					}
				}
			}
			if (num2 == 0)
			{
				componentInChildren.text = "No Ammo";
				return;
			}
			componentInChildren.text = ammoItem.m_shared.m_name.Split(new char[1] { '_' }).Last() + "\n" + num + "/" + num2;
		}

		private static void DestroyAllAmmoCounters()
		{
			for (int i = 0; i < 8; i++)
			{
				DestroyAmmoCounter(i);
			}
		}

		private static void DestroyAmmoCounter(int index)
		{
			GameObject val = ammoCounters[index];
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)val);
				ammoCounters[index] = null;
			}
		}
	}
}
namespace ValheimPlus.RPC
{
	public static class VPlusMapPinSync
	{
		private sealed class SharedPin
		{
			public string Id;

			public string Name;

			public Vector3 Pos;

			public PinType Type;

			public long OwnerId;
		}

		public const string AddRpc = "VPlusMapPinAdd";

		public const string RemoveRpc = "VPlusMapPinRemove";

		public const string SnapshotRpc = "VPlusMapPinSnapshot";

		public const string RequestRpc = "VPlusMapPinRequest";

		private static readonly HashSet<PinType> ShareableTypes = new HashSet<PinType>
		{
			(PinType)0,
			(PinType)1,
			(PinType)2,
			(PinType)3,
			(PinType)6,
			(PinType)9,
			(PinType)14,
			(PinType)15,
			(PinType)16,
			(PinType)17
		};

		private static readonly Dictionary<string, SharedPin> serverPins = new Dictionary<string, SharedPin>();

		private static readonly HashSet<string> deletedPinIds = new HashSet<string>();

		private static bool serverPinsLoaded;

		private static bool serverPinsDirty;

		private static readonly object storeLock = new object();

		private static readonly object saveLock = new object();

		private static bool applying;

		private static bool readingMapTable;

		public static bool CreatingNamedPin;

		private static PinData namedPin;

		public static bool ShouldSyncOnSpawn = true;

		private const string FieldSeparator = "\u001f";

		private static bool Enabled
		{
			get
			{
				if (Configuration.Current.Map.IsEnabled)
				{
					return Configuration.Current.Map.syncPins;
				}
				return false;
			}
		}

		private static bool IsServer
		{
			get
			{
				if ((Object)(object)ZNet.instance != (Object)null)
				{
					return ZNet.instance.IsServer();
				}
				return false;
			}
		}

		private static string StorePath
		{
			get
			{
				string vPlusDataDirectoryPath = ValheimPlusPlugin.VPlusDataDirectoryPath;
				char directorySeparatorChar = Path.DirectorySeparatorChar;
				return vPlusDataDirectoryPath + directorySeparatorChar + ZNet.instance.GetWorldName() + "_mapPins.dat";
			}
		}

		private static string DeletedStorePath
		{
			get
			{
				string vPlusDataDirectoryPath = ValheimPlusPlugin.VPlusDataDirectoryPath;
				char directorySeparatorChar = Path.DirectorySeparatorChar;
				return vPlusDataDirectoryPath + directorySeparatorChar + ZNet.instance.GetWorldName() + "_mapPinsDeleted.dat";
			}
		}

		private static bool IsShareable(PinData pin)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			if (pin != null && pin.m_save)
			{
				return ShareableTypes.Contains(pin.m_type);
			}
			return false;
		}

		private static string PinId(PinType type, Vector3 pos, string name)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected I4, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			return string.Format(CultureInfo.InvariantCulture, "{0}|{1:F1}|{2:F1}|{3}", (int)type, pos.x, pos.z, name ?? string.Empty);
		}

		private static string PinId(PinData pin)
		{
			//IL_0001: 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)
			return PinId(pin.m_type, pin.m_pos, pin.m_name);
		}

		public static void RequestSnapshot()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			if (Enabled && ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "VPlusMapPinRequest", new object[1] { (object)new ZPackage() });
			}
		}

		public static void SendAdd(PinData pin)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			if (!Enabled || applying || !IsShareable(pin) || ZRoutedRpc.instance == null || pin.m_ownerID != 0L)
			{
				return;
			}
			if (CreatingNamedPin)
			{
				namedPin = pin;
				return;
			}
			long num = LocalPlayerId();
			if (num != 0L)
			{
				ZPackage package = new ZPackage();
				WritePin(package, PinId(pin), pin.m_name, pin.m_pos, pin.m_type, num);
				Send("VPlusMapPinAdd", package);
			}
		}

		public static void BeginMapTableRead()
		{
			readingMapTable = true;
		}

		public static void EndMapTableRead()
		{
			readingMapTable = false;
			RequestSnapshot();
		}

		public static void FlushNamedPin(Minimap minimap, PinData dialogPin)
		{
			if (namedPin != null && namedPin != dialogPin)
			{
				PinData val = namedPin;
				namedPin = null;
				if (minimap.m_pins.Contains(val))
				{
					SendAdd(val);
				}
			}
		}

		public static void SendRemove(PinData pin)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			if (Enabled && !applying && !readingMapTable && IsShareable(pin) && ZRoutedRpc.instance != null)
			{
				ZPackage val = new ZPackage();
				val.Write(PinId(pin));
				Send("VPlusMapPinRemove", val);
			}
		}

		private static void Send(string rpc, ZPackage package)
		{
			if (IsServer)
			{
				package.SetPos(0);
				if (rpc == "VPlusMapPinAdd")
				{
					HandleAdd(package, broadcast: true);
				}
				else
				{
					HandleRemove(package, broadcast: true);
				}
			}
			else
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), rpc, new object[1] { package });
			}
		}

		private static long LocalPlayerId()
		{
			if (!((Object)(object)Player.m_localPlayer != (Object)null))
			{
				return 0L;
			}
			return Player.m_localPlayer.GetPlayerID();
		}

		private static void ApplyAdd(SharedPin pin)
		{
			//IL_0040: 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_0056: 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)
			if ((Object)(object)Minimap.instance == (Object)null || Find(pin.Id) != null)
			{
				return;
			}
			long num = ((pin.OwnerId == LocalPlayerId()) ? 0 : pin.OwnerId);
			applying = true;
			try
			{