Decompiled source of ServerCharacters v1.4.16

ServerCharacters.dll

Decompiled a year ago
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.Buffers.Text;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Tracing;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Net.Sockets;
using System.Numerics;
using System.Numerics.Hashing;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
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.Threading;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using FxResources.System.Buffers;
using FxResources.System.Collections.Immutable;
using FxResources.System.Memory;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using ProtoBuf;
using ProtoBuf.Compiler;
using ProtoBuf.Extensions;
using ProtoBuf.Internal;
using ProtoBuf.Internal.Serializers;
using ProtoBuf.Meta;
using ProtoBuf.Serializers;
using ProtoBuf.WellKnownTypes;
using ServerSync;
using Splatform;
using Steamworks;
using TMPro;
using UnityEngine;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.BufferedDeserialization;
using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators;
using YamlDotNet.Serialization.Callbacks;
using YamlDotNet.Serialization.Converters;
using YamlDotNet.Serialization.EventEmitters;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.NodeDeserializers;
using YamlDotNet.Serialization.NodeTypeResolvers;
using YamlDotNet.Serialization.ObjectFactories;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;
using YamlDotNet.Serialization.ObjectGraphVisitors;
using YamlDotNet.Serialization.Schemas;
using YamlDotNet.Serialization.TypeInspectors;
using YamlDotNet.Serialization.TypeResolvers;
using YamlDotNet.Serialization.Utilities;
using YamlDotNet.Serialization.ValueDeserializers;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ServerCharacters")]
[assembly: AssemblyDescription("https://valheim.thunderstore.io/package/Smoothbrain/ServerCharacters")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("ServerCharacters")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("B6DC411F-BB68-4745-BA9E-ADFEAF8C7F0E")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyCompany("")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[<b7e2de72-b000-46fb-a762-da1e7ee8ccff>Embedded]
	internal sealed class <b7e2de72-b000-46fb-a762-da1e7ee8ccff>EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[<b7e2de72-b000-46fb-a762-da1e7ee8ccff>Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class <ac6d2775-cef6-4d66-9819-032e899cd913>NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public <ac6d2775-cef6-4d66-9819-032e899cd913>NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public <ac6d2775-cef6-4d66-9819-032e899cd913>NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[<b7e2de72-b000-46fb-a762-da1e7ee8ccff>Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class <17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public <17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace ServerCharacters
{
	public static class ClientSide
	{
		[HarmonyPatch(typeof(Skills), "ResetSkill")]
		public class SaveLastSkillReset
		{
			public static SkillType last = (SkillType)999;

			[UsedImplicitly]
			public static void Finalizer(SkillType skillType)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				last = skillType;
			}
		}

		[HarmonyPatch(typeof(Console), "Print")]
		public class SilenceConsole
		{
			public static bool silence;

			[UsedImplicitly]
			public static bool Prefix()
			{
				return !silence;
			}
		}

		[HarmonyPatch(typeof(Terminal), "InitTerminal")]
		public class AddChatCommands
		{
			[Serializable]
			[CompilerGenerated]
			private sealed class <>c
			{
				public static readonly <>c <>9 = new <>c();

				public static Func<KeyValuePair<SkillType, Skill>, SkillType> <>9__0_3;

				public static Func<KeyValuePair<SkillType, Skill>, Skill> <>9__0_4;

				public static ConsoleEvent <>9__0_0;

				public static ConsoleOptionsFetcher <>9__0_1;

				internal void <Postfix>b__0_0(ConsoleEventArgs args)
				{
					//IL_0067: Unknown result type (might be due to invalid IL or missing references)
					//IL_0071: Invalid comparison between Unknown and I4
					//IL_023a: Unknown result type (might be due to invalid IL or missing references)
					//IL_0244: Invalid comparison between Unknown and I4
					//IL_081e: Unknown result type (might be due to invalid IL or missing references)
					<>c__DisplayClass0_0 <>c__DisplayClass0_ = new <>c__DisplayClass0_0
					{
						args = args
					};
					if (!ServerCharacters.configSync.IsAdmin)
					{
						<>c__DisplayClass0_.args.Context.AddString("You are not an admin on this server.");
					}
					else if (<>c__DisplayClass0_.args.Length >= 3 && <>c__DisplayClass0_.args[1] == "resetskill")
					{
						if ((int)<Postfix>g__GetSkillType|0_2(<>c__DisplayClass0_.args[2]) == 999)
						{
							<>c__DisplayClass0_.args.Context.AddString(<>c__DisplayClass0_.args[2] + " is not a valid skill.");
						}
						else if (<>c__DisplayClass0_.args.Length > 3)
						{
							string text = <>c__DisplayClass0_.args[3];
							int num = 4;
							if (text.StartsWith("\"", StringComparison.Ordinal))
							{
								text = text.Substring(1);
								while (num < <>c__DisplayClass0_.args.Length && !text.EndsWith("\"", StringComparison.Ordinal))
								{
									text = text + " " + <>c__DisplayClass0_.args[num++];
								}
								text = text.Substring(0, text.Length - 1);
							}
							ZNet.instance.GetServerPeer().m_rpc.Invoke("ServerCharacters ResetSkill", new object[3]
							{
								<>c__DisplayClass0_.args[2],
								text,
								(<>c__DisplayClass0_.args.Length > num) ? <>c__DisplayClass0_.args[num] : "0"
							});
							<>c__DisplayClass0_.args.Context.AddString(<>c__DisplayClass0_.args[2] + " has been reset for " + text + ".");
						}
						else
						{
							ZNet.instance.GetServerPeer().m_rpc.Invoke("ServerCharacters ResetSkill", new object[3]
							{
								<>c__DisplayClass0_.args[2],
								"",
								"0"
							});
							<>c__DisplayClass0_.args.Context.AddString(<>c__DisplayClass0_.args[2] + " has been reset for everyone.");
						}
					}
					else if (<>c__DisplayClass0_.args.Length >= 3 && <>c__DisplayClass0_.args[1] == "raiseskill")
					{
						if ((int)<Postfix>g__GetSkillType|0_2(<>c__DisplayClass0_.args[2]) == 999)
						{
							<>c__DisplayClass0_.args.Context.AddString(<>c__DisplayClass0_.args[2] + " is not a valid skill.");
						}
						else if (<>c__DisplayClass0_.args.Length > 4)
						{
							string text2 = <>c__DisplayClass0_.args[4];
							int num2 = 5;
							if (text2.StartsWith("\"", StringComparison.Ordinal))
							{
								text2 = text2.Substring(1);
								while (num2 < <>c__DisplayClass0_.args.Length && !text2.EndsWith("\"", StringComparison.Ordinal))
								{
									text2 = text2 + " " + <>c__DisplayClass0_.args[num2++];
								}
								text2 = text2.Substring(0, text2.Length - 1);
							}
							ZNet.instance.GetServerPeer().m_rpc.Invoke("ServerCharacters RaiseSkill", new object[4]
							{
								<>c__DisplayClass0_.args[2],
								int.Parse(<>c__DisplayClass0_.args[3]),
								text2,
								(<>c__DisplayClass0_.args.Length > num2) ? <>c__DisplayClass0_.args[num2] : "0"
							});
							<>c__DisplayClass0_.args.Context.AddString(<>c__DisplayClass0_.args[2] + " has been raised by " + <>c__DisplayClass0_.args[3] + " for " + text2 + ".");
						}
						else
						{
							ZNet.instance.GetServerPeer().m_rpc.Invoke("ServerCharacters RaiseSkill", new object[4]
							{
								<>c__DisplayClass0_.args[2],
								int.Parse(<>c__DisplayClass0_.args[3]),
								"",
								"0"
							});
							<>c__DisplayClass0_.args.Context.AddString(<>c__DisplayClass0_.args[2] + " has been raised by " + <>c__DisplayClass0_.args[3] + " for everyone.");
						}
					}
					else if (<>c__DisplayClass0_.args.Length >= 3 && <>c__DisplayClass0_.args[1] == "giveitem")
					{
						if (ObjectDB.instance.GetItemPrefab(<>c__DisplayClass0_.args[2]) == null)
						{
							<>c__DisplayClass0_.args.Context.AddString(<>c__DisplayClass0_.args[2] + " is not a valid item.");
						}
						else if (<>c__DisplayClass0_.args.Length > 4)
						{
							string text3 = <>c__DisplayClass0_.args[4];
							int num3 = 5;
							if (text3.StartsWith("\"", StringComparison.Ordinal))
							{
								text3 = text3.Substring(1);
								while (num3 < <>c__DisplayClass0_.args.Length && !text3.EndsWith("\"", StringComparison.Ordinal))
								{
									text3 = text3 + " " + <>c__DisplayClass0_.args[num3++];
								}
								text3 = text3.Substring(0, text3.Length - 1);
							}
							ZNet.instance.GetServerPeer().m_rpc.Invoke("ServerCharacters GiveItem", new object[4]
							{
								<>c__DisplayClass0_.args[2],
								int.Parse(<>c__DisplayClass0_.args[3]),
								text3,
								(<>c__DisplayClass0_.args.Length > num3) ? <>c__DisplayClass0_.args[num3] : "0"
							});
							<>c__DisplayClass0_.args.Context.AddString(<>c__DisplayClass0_.args[3] + "x " + <>c__DisplayClass0_.args[2] + " has been given to " + text3 + ", if their inventory isn't full.");
						}
						else
						{
							<>c__DisplayClass0_.args.Context.AddString("Please specify a target player.");
						}
					}
					else if (<>c__DisplayClass0_.args.Length >= 3 && <>c__DisplayClass0_.args[1] == "teleport")
					{
						string text4 = <>c__DisplayClass0_.args[2];
						int num4 = 3;
						if (text4.StartsWith("\"", StringComparison.Ordinal))
						{
							text4 = text4.Substring(1);
							while (num4 < <>c__DisplayClass0_.args.Length && !text4.EndsWith("\"", StringComparison.Ordinal))
							{
								text4 = text4 + " " + <>c__DisplayClass0_.args[num4++];
							}
							text4 = text4.Substring(0, text4.Length - 1);
						}
						ZNet.instance.GetServerPeer().m_rpc.Invoke("ServerCharacters GetPlayerPos", new object[2]
						{
							text4,
							(<>c__DisplayClass0_.args.Length > num4) ? <>c__DisplayClass0_.args[num4] : "0"
						});
						((MonoBehaviour)ServerCharacters.selfReference).StartCoroutine(<>c__DisplayClass0_.<Postfix>g__AwaitResponse|5());
					}
					else if (<>c__DisplayClass0_.args.Length >= 3 && <>c__DisplayClass0_.args[1] == "summon")
					{
						string text5 = <>c__DisplayClass0_.args[2];
						int num5 = 3;
						if (text5.StartsWith("\"", StringComparison.Ordinal))
						{
							text5 = text5.Substring(1);
							while (num5 < <>c__DisplayClass0_.args.Length && !text5.EndsWith("\"", StringComparison.Ordinal))
							{
								text5 = text5 + " " + <>c__DisplayClass0_.args[num5++];
							}
							text5 = text5.Substring(0, text5.Length - 1);
						}
						ZNet.instance.GetServerPeer().m_rpc.Invoke("ServerCharacters SendOwnPos", new object[3]
						{
							text5,
							(<>c__DisplayClass0_.args.Length > num5) ? <>c__DisplayClass0_.args[num5] : "0",
							((Component)Player.m_localPlayer).transform.position
						});
						((MonoBehaviour)ServerCharacters.selfReference).StartCoroutine(<>c__DisplayClass0_.<Postfix>g__AwaitResponse|7());
					}
					else
					{
						<>c__DisplayClass0_.args.Context.AddString("ServerCharacters console commands - use 'ServerCharacters' followed by one of the following options.");
						<>c__DisplayClass0_.args.Context.AddString("resetskill [skillname] [playername] [id] - resets the skill for the specified player. Steam / Xbox ID is optional and only required, if multiple players have the same name. If no name is provided, the skill is reset for every character on the server, online and offline.");
						<>c__DisplayClass0_.args.Context.AddString("raiseskill [skillname] [level] [playername] [id] - raises the skill for the specified player by the specified level. Steam / Xbox ID is optional and only required, if multiple players have the same name. If no name is provided, the skill is raised for every character on the server, online and offline.");
						<>c__DisplayClass0_.args.Context.AddString("teleport [playername] [steamid] - teleports you to the specified player. Quote names with a space. Steam / Xbox ID is optional and only required, if multiple players have the same name.");
						<>c__DisplayClass0_.args.Context.AddString("summon [playername] [steamid] - teleports the specified player to you. Quote names with a space. Steam / Xbox ID is optional and only required, if multiple players have the same name.");
						<>c__DisplayClass0_.args.Context.AddString("giveitem [itemname] [quantity] [playername] [id] - adds the specified item to the specified players inventory in the specified quantity. Quote names with a space. Steam / Xbox ID is optional and only required, if multiple players have the same name. Will fail, if their inventory is full.");
					}
				}

				internal SkillType <Postfix>b__0_3(KeyValuePair<SkillType, Skill> kv)
				{
					//IL_0002: Unknown result type (might be due to invalid IL or missing references)
					return kv.Key;
				}

				internal Skill <Postfix>b__0_4(KeyValuePair<SkillType, Skill> kv)
				{
					//IL_000c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Unknown result type (might be due to invalid IL or missing references)
					//IL_0023: Unknown result type (might be due to invalid IL or missing references)
					//IL_0036: Expected O, but got Unknown
					return new Skill(kv.Value.m_info)
					{
						m_accumulator = kv.Value.m_accumulator,
						m_level = kv.Value.m_level
					};
				}

				internal List<string> <Postfix>b__0_1()
				{
					return new List<string> { "resetskill", "teleport", "summon", "raiseskill", "giveitem" };
				}
			}

			[CompilerGenerated]
			private sealed class <>c__DisplayClass0_0
			{
				public ConsoleEventArgs args;
			}

			private static void Postfix()
			{
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Expected O, but got Unknown
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				//IL_0047: Unknown result type (might be due to invalid IL or missing references)
				//IL_004d: Expected O, but got Unknown
				object obj = <>c.<>9__0_0;
				if (obj == null)
				{
					ConsoleEvent val = delegate(ConsoleEventArgs args)
					{
						//IL_0067: Unknown result type (might be due to invalid IL or missing references)
						//IL_0071: Invalid comparison between Unknown and I4
						//IL_023a: Unknown result type (might be due to invalid IL or missing references)
						//IL_0244: Invalid comparison between Unknown and I4
						//IL_081e: Unknown result type (might be due to invalid IL or missing references)
						<>c__DisplayClass0_0 CS$<>8__locals0 = new <>c__DisplayClass0_0();
						CS$<>8__locals0.args = args;
						if (!ServerCharacters.configSync.IsAdmin)
						{
							CS$<>8__locals0.args.Context.AddString("You are not an admin on this server.");
						}
						else if (CS$<>8__locals0.args.Length >= 3 && CS$<>8__locals0.args[1] == "resetskill")
						{
							if ((int)GetSkillType(CS$<>8__locals0.args[2]) == 999)
							{
								CS$<>8__locals0.args.Context.AddString(CS$<>8__locals0.args[2] + " is not a valid skill.");
							}
							else if (CS$<>8__locals0.args.Length > 3)
							{
								string text = CS$<>8__locals0.args[3];
								int num = 4;
								if (text.StartsWith("\"", StringComparison.Ordinal))
								{
									text = text.Substring(1);
									while (num < CS$<>8__locals0.args.Length && !text.EndsWith("\"", StringComparison.Ordinal))
									{
										text = text + " " + CS$<>8__locals0.args[num++];
									}
									text = text.Substring(0, text.Length - 1);
								}
								ZNet.instance.GetServerPeer().m_rpc.Invoke("ServerCharacters ResetSkill", new object[3]
								{
									CS$<>8__locals0.args[2],
									text,
									(CS$<>8__locals0.args.Length > num) ? CS$<>8__locals0.args[num] : "0"
								});
								CS$<>8__locals0.args.Context.AddString(CS$<>8__locals0.args[2] + " has been reset for " + text + ".");
							}
							else
							{
								ZNet.instance.GetServerPeer().m_rpc.Invoke("ServerCharacters ResetSkill", new object[3]
								{
									CS$<>8__locals0.args[2],
									"",
									"0"
								});
								CS$<>8__locals0.args.Context.AddString(CS$<>8__locals0.args[2] + " has been reset for everyone.");
							}
						}
						else if (CS$<>8__locals0.args.Length >= 3 && CS$<>8__locals0.args[1] == "raiseskill")
						{
							if ((int)GetSkillType(CS$<>8__locals0.args[2]) == 999)
							{
								CS$<>8__locals0.args.Context.AddString(CS$<>8__locals0.args[2] + " is not a valid skill.");
							}
							else if (CS$<>8__locals0.args.Length > 4)
							{
								string text2 = CS$<>8__locals0.args[4];
								int num2 = 5;
								if (text2.StartsWith("\"", StringComparison.Ordinal))
								{
									text2 = text2.Substring(1);
									while (num2 < CS$<>8__locals0.args.Length && !text2.EndsWith("\"", StringComparison.Ordinal))
									{
										text2 = text2 + " " + CS$<>8__locals0.args[num2++];
									}
									text2 = text2.Substring(0, text2.Length - 1);
								}
								ZNet.instance.GetServerPeer().m_rpc.Invoke("ServerCharacters RaiseSkill", new object[4]
								{
									CS$<>8__locals0.args[2],
									int.Parse(CS$<>8__locals0.args[3]),
									text2,
									(CS$<>8__locals0.args.Length > num2) ? CS$<>8__locals0.args[num2] : "0"
								});
								CS$<>8__locals0.args.Context.AddString(CS$<>8__locals0.args[2] + " has been raised by " + CS$<>8__locals0.args[3] + " for " + text2 + ".");
							}
							else
							{
								ZNet.instance.GetServerPeer().m_rpc.Invoke("ServerCharacters RaiseSkill", new object[4]
								{
									CS$<>8__locals0.args[2],
									int.Parse(CS$<>8__locals0.args[3]),
									"",
									"0"
								});
								CS$<>8__locals0.args.Context.AddString(CS$<>8__locals0.args[2] + " has been raised by " + CS$<>8__locals0.args[3] + " for everyone.");
							}
						}
						else if (CS$<>8__locals0.args.Length >= 3 && CS$<>8__locals0.args[1] == "giveitem")
						{
							if (ObjectDB.instance.GetItemPrefab(CS$<>8__locals0.args[2]) == null)
							{
								CS$<>8__locals0.args.Context.AddString(CS$<>8__locals0.args[2] + " is not a valid item.");
							}
							else if (CS$<>8__locals0.args.Length > 4)
							{
								string text3 = CS$<>8__locals0.args[4];
								int num3 = 5;
								if (text3.StartsWith("\"", StringComparison.Ordinal))
								{
									text3 = text3.Substring(1);
									while (num3 < CS$<>8__locals0.args.Length && !text3.EndsWith("\"", StringComparison.Ordinal))
									{
										text3 = text3 + " " + CS$<>8__locals0.args[num3++];
									}
									text3 = text3.Substring(0, text3.Length - 1);
								}
								ZNet.instance.GetServerPeer().m_rpc.Invoke("ServerCharacters GiveItem", new object[4]
								{
									CS$<>8__locals0.args[2],
									int.Parse(CS$<>8__locals0.args[3]),
									text3,
									(CS$<>8__locals0.args.Length > num3) ? CS$<>8__locals0.args[num3] : "0"
								});
								CS$<>8__locals0.args.Context.AddString(CS$<>8__locals0.args[3] + "x " + CS$<>8__locals0.args[2] + " has been given to " + text3 + ", if their inventory isn't full.");
							}
							else
							{
								CS$<>8__locals0.args.Context.AddString("Please specify a target player.");
							}
						}
						else if (CS$<>8__locals0.args.Length >= 3 && CS$<>8__locals0.args[1] == "teleport")
						{
							string text4 = CS$<>8__locals0.args[2];
							int num4 = 3;
							if (text4.StartsWith("\"", StringComparison.Ordinal))
							{
								text4 = text4.Substring(1);
								while (num4 < CS$<>8__locals0.args.Length && !text4.EndsWith("\"", StringComparison.Ordinal))
								{
									text4 = text4 + " " + CS$<>8__locals0.args[num4++];
								}
								text4 = text4.Substring(0, text4.Length - 1);
							}
							ZNet.instance.GetServerPeer().m_rpc.Invoke("ServerCharacters GetPlayerPos", new object[2]
							{
								text4,
								(CS$<>8__locals0.args.Length > num4) ? CS$<>8__locals0.args[num4] : "0"
							});
							((MonoBehaviour)ServerCharacters.selfReference).StartCoroutine(AwaitResponse());
						}
						else if (CS$<>8__locals0.args.Length >= 3 && CS$<>8__locals0.args[1] == "summon")
						{
							string text5 = CS$<>8__locals0.args[2];
							int num5 = 3;
							if (text5.StartsWith("\"", StringComparison.Ordinal))
							{
								text5 = text5.Substring(1);
								while (num5 < CS$<>8__locals0.args.Length && !text5.EndsWith("\"", StringComparison.Ordinal))
								{
									text5 = text5 + " " + CS$<>8__locals0.args[num5++];
								}
								text5 = text5.Substring(0, text5.Length - 1);
							}
							ZNet.instance.GetServerPeer().m_rpc.Invoke("ServerCharacters SendOwnPos", new object[3]
							{
								text5,
								(CS$<>8__locals0.args.Length > num5) ? CS$<>8__locals0.args[num5] : "0",
								((Component)Player.m_localPlayer).transform.position
							});
							((MonoBehaviour)ServerCharacters.selfReference).StartCoroutine(AwaitResponse());
						}
						else
						{
							CS$<>8__locals0.args.Context.AddString("ServerCharacters console commands - use 'ServerCharacters' followed by one of the following options.");
							CS$<>8__locals0.args.Context.AddString("resetskill [skillname] [playername] [id] - resets the skill for the specified player. Steam / Xbox ID is optional and only required, if multiple players have the same name. If no name is provided, the skill is reset for every character on the server, online and offline.");
							CS$<>8__locals0.args.Context.AddString("raiseskill [skillname] [level] [playername] [id] - raises the skill for the specified player by the specified level. Steam / Xbox ID is optional and only required, if multiple players have the same name. If no name is provided, the skill is raised for every character on the server, online and offline.");
							CS$<>8__locals0.args.Context.AddString("teleport [playername] [steamid] - teleports you to the specified player. Quote names with a space. Steam / Xbox ID is optional and only required, if multiple players have the same name.");
							CS$<>8__locals0.args.Context.AddString("summon [playername] [steamid] - teleports the specified player to you. Quote names with a space. Steam / Xbox ID is optional and only required, if multiple players have the same name.");
							CS$<>8__locals0.args.Context.AddString("giveitem [itemname] [quantity] [playername] [id] - adds the specified item to the specified players inventory in the specified quantity. Quote names with a space. Steam / Xbox ID is optional and only required, if multiple players have the same name. Will fail, if their inventory is full.");
						}
						[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
						[IteratorStateMachine(typeof(<>c__DisplayClass0_0.<<Postfix>g__AwaitResponse|5>d))]
						IEnumerator AwaitResponse()
						{
							//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
							return new <>c__DisplayClass0_0.<<Postfix>g__AwaitResponse|5>d(0)
							{
								<>4__this = CS$<>8__locals0
							};
						}
						[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
						[IteratorStateMachine(typeof(<>c__DisplayClass0_0.<<Postfix>g__AwaitResponse|7>d))]
						IEnumerator AwaitResponse()
						{
							//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
							return new <>c__DisplayClass0_0.<<Postfix>g__AwaitResponse|7>d(0)
							{
								<>4__this = CS$<>8__locals0
							};
						}
					};
					<>c.<>9__0_0 = val;
					obj = (object)val;
				}
				object obj2 = <>c.<>9__0_1;
				if (obj2 == null)
				{
					ConsoleOptionsFetcher val2 = () => new List<string> { "resetskill", "teleport", "summon", "raiseskill", "giveitem" };
					<>c.<>9__0_1 = val2;
					obj2 = (object)val2;
				}
				new ConsoleCommand("ServerCharacters", "Manages the ServerCharacters commands.", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)obj2, false, false, false);
				[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
				static SkillType GetSkillType(string name)
				{
					//IL_005a: Unknown result type (might be due to invalid IL or missing references)
					//IL_0085: Unknown result type (might be due to invalid IL or missing references)
					Dictionary<SkillType, Skill> skillData = ((Character)Player.m_localPlayer).GetSkills().m_skillData;
					Dictionary<SkillType, Skill> src = ((IEnumerable<KeyValuePair<SkillType, Skill>>)skillData).ToDictionary((Func<KeyValuePair<SkillType, Skill>, SkillType>)((KeyValuePair<SkillType, Skill> kv) => kv.Key), (Func<KeyValuePair<SkillType, Skill>, Skill>)((KeyValuePair<SkillType, Skill> kv) => new Skill(kv.Value.m_info)
					{
						m_accumulator = kv.Value.m_accumulator,
						m_level = kv.Value.m_level
					}));
					SaveLastSkillReset.last = (SkillType)999;
					try
					{
						SilenceConsole.silence = true;
						((Character)Player.m_localPlayer).GetSkills().CheatResetSkill(name);
					}
					finally
					{
						SilenceConsole.silence = false;
					}
					Utils.OverwriteDict(src, skillData);
					return SaveLastSkillReset.last;
				}
			}

			[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
			[CompilerGenerated]
			internal static SkillType <Postfix>g__GetSkillType|0_2(string name)
			{
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0085: Unknown result type (might be due to invalid IL or missing references)
				Dictionary<SkillType, Skill> skillData = ((Character)Player.m_localPlayer).GetSkills().m_skillData;
				Dictionary<SkillType, Skill> src = ((IEnumerable<KeyValuePair<SkillType, Skill>>)skillData).ToDictionary((Func<KeyValuePair<SkillType, Skill>, SkillType>)((KeyValuePair<SkillType, Skill> kv) => kv.Key), (Func<KeyValuePair<SkillType, Skill>, Skill>)((KeyValuePair<SkillType, Skill> kv) => new Skill(kv.Value.m_info)
				{
					m_accumulator = kv.Value.m_accumulator,
					m_level = kv.Value.m_level
				}));
				SaveLastSkillReset.last = (SkillType)999;
				try
				{
					SilenceConsole.silence = true;
					((Character)Player.m_localPlayer).GetSkills().CheatResetSkill(name);
				}
				finally
				{
					SilenceConsole.silence = false;
				}
				Utils.OverwriteDict(src, skillData);
				return SaveLastSkillReset.last;
			}
		}

		[HarmonyPatch(typeof(PlayerProfile), "SavePlayerData")]
		private static class PatchPlayerProfilePlayerSave
		{
			[UsedImplicitly]
			private static void Prefix()
			{
				if (serverCharacter && doEmergencyBackup && playerSnapShotLast != null)
				{
					Player localPlayer = Player.m_localPlayer;
					if (localPlayer != null)
					{
						((Humanoid)localPlayer).m_inventory.m_inventory = playerSnapShotLast.inventory;
						Utils.OverwriteDict(playerSnapShotLast.knownStations, localPlayer.m_knownStations);
						Utils.OverwriteDict(playerSnapShotLast.knownTexts, localPlayer.m_knownTexts);
					}
				}
			}
		}

		[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
		[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
		[HarmonyPatch(typeof(PlayerProfile), "SavePlayerToDisk")]
		private static class PatchPlayerProfileSave_Client
		{
			[CompilerGenerated]
			private sealed class <>c__DisplayClass0_0
			{
				[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
				public byte[] packageArray;
			}

			private static readonly MethodInfo ArrayWriter = AccessTools.DeclaredMethod(typeof(BinaryWriter), "Write", new Type[1] { typeof(byte[]) }, (Type[])null);

			private static readonly MethodInfo ServerCharacterSaver = AccessTools.DeclaredMethod(typeof(PatchPlayerProfileSave_Client), "SaveCharacterToServer", (Type[])null, (Type[])null);

			private static byte[] SaveCharacterToServer(byte[] packageArray, PlayerProfile profile)
			{
				<>c__DisplayClass0_0 CS$<>8__locals0 = new <>c__DisplayClass0_0();
				CS$<>8__locals0.packageArray = packageArray;
				if (serverCharacter && doEmergencyBackup && serverEncryptionKey != null)
				{
					string characterSavePath = Utils.CharacterSavePath;
					char directorySeparatorChar = Path.DirectorySeparatorChar;
					File.WriteAllBytes(characterSavePath + directorySeparatorChar + profile.m_filename + ".fch.signature", generateProfileSignature(CS$<>8__locals0.packageArray, serverEncryptionKey));
					string characterSavePath2 = Utils.CharacterSavePath;
					directorySeparatorChar = Path.DirectorySeparatorChar;
					File.WriteAllBytes(characterSavePath2 + directorySeparatorChar + profile.m_filename + ".fch.serverbackup", CS$<>8__locals0.packageArray);
					doEmergencyBackup = false;
				}
				if (serverCharacter && !currentlySaving)
				{
					ZNet instance = ZNet.instance;
					if (instance != null)
					{
						ZNetPeer serverPeer = instance.GetServerPeer();
						if (((serverPeer != null) ? new bool?(serverPeer.IsReady()) : null).GetValueOrDefault())
						{
							if (forceSynchronousSaving)
							{
								foreach (bool item in Shared.sendCompressedDataToPeer(ZNet.instance.GetServerPeer(), (iDied && ServerCharacters.hardcoreMode.GetToggle()) ? "ServerCharacters PlayerDied" : "ServerCharacters PlayerProfile", CS$<>8__locals0.packageArray))
								{
									if (!item)
									{
										Thread.Sleep(10);
									}
								}
							}
							else
							{
								currentlySaving = true;
								((MonoBehaviour)ZNet.instance).StartCoroutine(saveAsync());
							}
							return CS$<>8__locals0.packageArray;
						}
					}
				}
				return CS$<>8__locals0.packageArray;
				[IteratorStateMachine(typeof(<>c__DisplayClass0_0.<<SaveCharacterToServer>g__saveAsync|0>d))]
				IEnumerator saveAsync()
				{
					//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
					return new <>c__DisplayClass0_0.<<SaveCharacterToServer>g__saveAsync|0>d(0)
					{
						<>4__this = CS$<>8__locals0
					};
				}
			}

			[UsedImplicitly]
			private static IEnumerable<CodeInstruction> Transpiler(MethodBase method, IEnumerable<CodeInstruction> instructions)
			{
				//IL_0002: 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_0025: Expected O, but got Unknown
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Expected O, but got Unknown
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Expected O, but got Unknown
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Expected O, but got Unknown
				return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1]
				{
					new CodeMatch(new CodeInstruction(OpCodes.Callvirt, (object)ArrayWriter), (string)null)
				}).Insert((CodeInstruction[])(object)new CodeInstruction[2]
				{
					new CodeInstruction(OpCodes.Ldarg_0, (object)null),
					new CodeInstruction(OpCodes.Call, (object)ServerCharacterSaver)
				}).Instructions();
			}
		}

		[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
		[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
		[HarmonyPatch]
		private class EnableSocketLinger
		{
			[CompilerGenerated]
			private sealed class <Transpiler>d__4 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator
			{
				private int <>1__state;

				private CodeInstruction <>2__current;

				private int <>l__initialThreadId;

				[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(new byte[] { 0, 1 })]
				private IEnumerable<CodeInstruction> codeInstructions;

				[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(new byte[] { 0, 1 })]
				public IEnumerable<CodeInstruction> <>3__codeInstructions;

				[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(new byte[] { 0, 1 })]
				private IEnumerator<CodeInstruction> <>7__wrap1;

				[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
				private CodeInstruction <instruction>5__3;

				CodeInstruction IEnumerator<CodeInstruction>.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				object IEnumerator.Current
				{
					[DebuggerHidden]
					[return: <ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
					get
					{
						return <>2__current;
					}
				}

				[DebuggerHidden]
				public <Transpiler>d__4(int <>1__state)
				{
					this.<>1__state = <>1__state;
					<>l__initialThreadId = Environment.CurrentManagedThreadId;
				}

				[DebuggerHidden]
				void IDisposable.Dispose()
				{
					int num = <>1__state;
					if (num == -3 || (uint)(num - 1) <= 2u)
					{
						try
						{
						}
						finally
						{
							<>m__Finally1();
						}
					}
					<>7__wrap1 = null;
					<instruction>5__3 = null;
					<>1__state = -2;
				}

				private bool MoveNext()
				{
					//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
					//IL_00b8: Expected O, but got Unknown
					//IL_008a: Unknown result type (might be due to invalid IL or missing references)
					//IL_0094: Expected O, but got Unknown
					try
					{
						switch (<>1__state)
						{
						default:
							return false;
						case 0:
							<>1__state = -1;
							<>7__wrap1 = codeInstructions.GetEnumerator();
							<>1__state = -3;
							goto IL_00f1;
						case 1:
							<>1__state = -3;
							<>2__current = new CodeInstruction(OpCodes.Ldc_I4_1, (object)null);
							<>1__state = 2;
							return true;
						case 2:
							<>1__state = -3;
							goto IL_00cb;
						case 3:
							{
								<>1__state = -3;
								<instruction>5__3 = null;
								goto IL_00f1;
							}
							IL_00f1:
							if (<>7__wrap1.MoveNext())
							{
								<instruction>5__3 = <>7__wrap1.Current;
								if (<instruction>5__3.opcode == OpCodes.Call && CodeInstructionExtensions.OperandIs(<instruction>5__3, (MemberInfo)socketClose))
								{
									<>2__current = new CodeInstruction(OpCodes.Pop, (object)null);
									<>1__state = 1;
									return true;
								}
								goto IL_00cb;
							}
							<>m__Finally1();
							<>7__wrap1 = null;
							return false;
							IL_00cb:
							<>2__current = <instruction>5__3;
							<>1__state = 3;
							return true;
						}
					}
					catch
					{
						//try-fault
						((IDisposable)this).Dispose();
						throw;
					}
				}

				bool IEnumerator.MoveNext()
				{
					//ILSpy generated this explicit interface implementation from .override directive in MoveNext
					return this.MoveNext();
				}

				private void <>m__Finally1()
				{
					<>1__state = -1;
					if (<>7__wrap1 != null)
					{
						<>7__wrap1.Dispose();
					}
				}

				[DebuggerHidden]
				void IEnumerator.Reset()
				{
					throw new NotSupportedException();
				}

				[DebuggerHidden]
				[return: <ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
				IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
				{
					<Transpiler>d__4 <Transpiler>d__;
					if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
					{
						<>1__state = 0;
						<Transpiler>d__ = this;
					}
					else
					{
						<Transpiler>d__ = new <Transpiler>d__4(0);
					}
					<Transpiler>d__.codeInstructions = <>3__codeInstructions;
					return <Transpiler>d__;
				}

				[DebuggerHidden]
				[return: <ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
				IEnumerator IEnumerable.GetEnumerator()
				{
					return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
				}
			}

			private static MethodInfo socketClose => AccessTools.Method(typeof(SteamNetworkingSockets), "CloseConnection", (Type[])null, (Type[])null);

			private static void dummy()
			{
			}

			private static MethodInfo TargetMethod()
			{
				Type type = Type.GetType("ZSteamSocket, assembly_valheim");
				if ((object)type == null)
				{
					return AccessTools.DeclaredMethod(typeof(EnableSocketLinger), "dummy", (Type[])null, (Type[])null);
				}
				return AccessTools.DeclaredMethod(type, "Close", (Type[])null, (Type[])null);
			}

			[IteratorStateMachine(typeof(<Transpiler>d__4))]
			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> codeInstructions)
			{
				//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
				return new <Transpiler>d__4(-2)
				{
					<>3__codeInstructions = codeInstructions
				};
			}
		}

		[HarmonyPatch(typeof(Game), "Shutdown")]
		private static class PatchGameShutdown
		{
			[UsedImplicitly]
			private static void Prefix()
			{
				forceSynchronousSaving = true;
			}

			[UsedImplicitly]
			private static void Finalizer()
			{
				serverCharacter = false;
				forceSynchronousSaving = false;
			}
		}

		[HarmonyPatch(typeof(Player), "Save")]
		private static class StorePoisonDebuff
		{
			[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
			private static void Prefix(Player __instance)
			{
				if (ServerCharacters.storePoison.GetToggle())
				{
					StatusEffect statusEffect = ((Character)__instance).m_seman.GetStatusEffect(StringExtensionMethods.GetStableHashCode("Poison"));
					SE_Poison val = (SE_Poison)(object)((statusEffect is SE_Poison) ? statusEffect : null);
					if (val != null && !((Character)__instance).IsDead())
					{
						__instance.m_customData["ServerCharacters PoisonDamage"] = val.m_damageLeft.ToString(CultureInfo.InvariantCulture);
						__instance.m_customData["ServerCharacters PoisonDamageHit"] = val.m_damagePerHit.ToString(CultureInfo.InvariantCulture);
						__instance.m_customData["ServerCharacters PoisonTTL"] = ((StatusEffect)val).m_ttl.ToString(CultureInfo.InvariantCulture);
					}
					else
					{
						__instance.m_customData.Remove("ServerCharacters PoisonDamage");
						__instance.m_customData.Remove("ServerCharacters PoisonDamageHit");
						__instance.m_customData.Remove("ServerCharacters PoisonTTL");
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player), "Load")]
		private static class LoadPoisonDebuff
		{
			[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
			private static void Postfix(Player __instance)
			{
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_0087: Unknown result type (might be due to invalid IL or missing references)
				if (((Character)__instance).m_nview.m_zdo != null && ServerCharacters.storePoison.GetToggle() && __instance.m_customData.TryGetValue("ServerCharacters PoisonDamage", out var value) && value != "")
				{
					SE_Poison val = (SE_Poison)((Character)__instance).m_seman.AddStatusEffect(StringExtensionMethods.GetStableHashCode("Poison"), false, 0, 0f);
					val.m_damageLeft = float.Parse(__instance.m_customData["ServerCharacters PoisonDamage"], CultureInfo.InvariantCulture);
					val.m_damagePerHit = float.Parse(__instance.m_customData["ServerCharacters PoisonDamageHit"], CultureInfo.InvariantCulture);
					((StatusEffect)val).m_ttl = float.Parse(__instance.m_customData["ServerCharacters PoisonTTL"], CultureInfo.InvariantCulture);
				}
			}
		}

		[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
		[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
		[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
		private static class PatchZNetOnNewConnection
		{
			[UsedImplicitly]
			private static void Postfix(ZNet __instance, ZNetPeer peer)
			{
				//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c3: Expected O, but got Unknown
				if (ZNet.instance.IsServer())
				{
					return;
				}
				peer.m_rpc.Register<ZPackage>("ServerCharacters PlayerProfile", Shared.receiveCompressedFromPeer(onReceivedProfile));
				peer.m_rpc.Register<ZPackage>("ServerCharacters KeyExchange", (Action<ZRpc, ZPackage>)receiveEncryptionKeyFromServer);
				peer.m_rpc.Register<string>("ServerCharacters IngameMessage", (Action<ZRpc, string>)onReceivedIngameMessage);
				peer.m_rpc.Register<string>("ServerCharacters KickMessage", (Action<ZRpc, string>)onReceivedKickMessage);
				peer.m_rpc.Register<string>("ServerCharacters ResetSkill", (Action<ZRpc, string>)onReceivedResetSkill);
				peer.m_rpc.Register<string, int>("ServerCharacters RaiseSkill", (Action<ZRpc, string, int>)onReceivedRaiseSkill);
				peer.m_rpc.Register<Vector3>("ServerCharacters GetPlayerPos", (Action<ZRpc, Vector3>)onReceivedPlayerPos);
				peer.m_rpc.Register<string, int>("ServerCharacters GiveItem", (Action<ZRpc, string, int>)onReceivedGiveItem);
				peer.m_rpc.Register<Vector3>("ServerCharacters SendOwnPos", (Action<ZRpc, Vector3>)onReceivedOwnPos);
				peer.m_rpc.Register<Vector3>("ServerCharacters TeleportTo", (Action<ZRpc, Vector3>)onReceivedTeleportTo);
				string characterSavePath = Utils.CharacterSavePath;
				char directorySeparatorChar = Path.DirectorySeparatorChar;
				string path = characterSavePath + directorySeparatorChar + Game.instance.m_playerProfile.m_filename + ".fch.signature";
				string characterSavePath2 = Utils.CharacterSavePath;
				directorySeparatorChar = Path.DirectorySeparatorChar;
				string path2 = characterSavePath2 + directorySeparatorChar + Game.instance.m_playerProfile.m_filename + ".fch.serverbackup";
				if (!File.Exists(path) || !File.Exists(path2))
				{
					return;
				}
				Utils.Log("Found emergency backup and signature for character '" + Game.instance.m_playerProfile.m_filename + "'. Trying to restore the backup.");
				ZPackage val = new ZPackage();
				val.Write(File.ReadAllBytes(path2));
				val.Write(File.ReadAllBytes(path));
				foreach (bool item in Shared.sendCompressedDataToPeer(peer, "ServerCharacters CheckSignature", val.GetArray()))
				{
					if (!item)
					{
						Thread.Sleep(10);
					}
				}
			}

			private static void onReceivedOwnPos(ZRpc peerRpc, Vector3 pos)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				if (awaitingPos != null)
				{
					awaitingPos.SetResult(pos);
					awaitingPos = null;
				}
			}

			private static void onReceivedTeleportTo(ZRpc peerRpc, Vector3 pos)
			{
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				((Character)Player.m_localPlayer).TeleportTo(pos, Quaternion.identity, true);
			}

			private static void onReceivedPlayerPos(ZRpc peerRpc, Vector3 pos)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				if (awaitingPos != null)
				{
					awaitingPos.SetResult(pos);
					awaitingPos = null;
				}
			}

			private static void onReceivedGiveItem(ZRpc peerRpc, string itemName, int itemQuantity)
			{
				string text = (((Humanoid)Player.m_localPlayer).m_inventory.AddItem(ObjectDB.instance.GetItemPrefab(itemName), itemQuantity) ? $"An admin added {itemQuantity}x {itemName} to your inventory." : $"An admin tried to add {itemQuantity}x {itemName} to your inventory, but it is full.");
				((Terminal)Chat.instance).AddString(text);
				Chat.instance.m_hideTimer = 0f;
				MessageHud.instance.ShowMessage((MessageType)2, text, 0, (Sprite)null, false);
			}

			private static void onReceivedResetSkill(ZRpc peerRpc, string skill)
			{
				Player.m_localPlayer.m_skills.CheatResetSkill(skill);
				string text = "An admin reset your skill " + skill;
				((Terminal)Chat.instance).AddString(text);
				Chat.instance.m_hideTimer = 0f;
				MessageHud.instance.ShowMessage((MessageType)2, text, 0, (Sprite)null, false);
			}

			private static void onReceivedRaiseSkill(ZRpc peerRpc, string skill, int level)
			{
				Player.m_localPlayer.m_skills.CheatRaiseSkill(skill, (float)level, true);
				string text = $"An admin raised your skill {skill} by {level}";
				((Terminal)Chat.instance).AddString(text);
				Chat.instance.m_hideTimer = 0f;
				MessageHud.instance.ShowMessage((MessageType)2, text, 0, (Sprite)null, false);
			}

			private static void onReceivedIngameMessage(ZRpc peerRpc, string message)
			{
				((Terminal)Chat.instance).AddString(message);
				Chat.instance.m_hideTimer = 0f;
				MessageHud.instance.ShowMessage((MessageType)2, message, 0, (Sprite)null, false);
			}

			private static void onReceivedKickMessage(ZRpc peerRpc, string message)
			{
				connectionError = message;
			}

			private static void onReceivedProfile(ZRpc peerRpc, byte[] profileData)
			{
				//IL_0054: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: Expected O, but got Unknown
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				if (profileData.Length == 0)
				{
					if (Game.instance.m_playerProfile.m_worldData.Count != 0)
					{
						Game.instance.Logout(true, true);
						ZNet.m_connectionStatus = (ConnectionStatus)5;
						connectionError = "Please create a new character, before connecting to this server, to avoid loss of data.";
					}
					else
					{
						serverCharacter = true;
						acquireCharacterFromTemplate = true;
					}
					return;
				}
				PlayerProfile val = new PlayerProfile(Game.instance.m_playerProfile.m_filename, (FileSource)0);
				if (!val.LoadPlayerProfileFromBytes(profileData) || Shared.CharacterNameIsForbidden(val.m_playerName))
				{
					Game.instance.Logout(true, true);
					ZNet.m_connectionStatus = (ConnectionStatus)5;
					connectionError = "The saved data on the server was corrupt, please contact your server admin or create a new character.";
				}
				else
				{
					serverCharacter = true;
					Game.instance.m_playerProfile = val;
					cleanEmergencyBackup();
				}
			}
		}

		[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
		private static class DetectBackupOnlyMode
		{
			[UsedImplicitly]
			[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
			private static void Postfix(ZNet __instance)
			{
				if (ServerCharacters.backupOnlyMode.GetToggle() && !__instance.IsServer())
				{
					serverCharacter = true;
				}
			}
		}

		[HarmonyPatch(typeof(Game), "SpawnPlayer")]
		private class InitializePlayerFromTemplate
		{
			[UsedImplicitly]
			private static void Postfix()
			{
				//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
				//IL_0232: Unknown result type (might be due to invalid IL or missing references)
				if (ServerCharacters.backupOnlyMode.GetToggle())
				{
					cleanEmergencyBackup();
				}
				bool num;
				if (!ServerCharacters.backupOnlyMode.GetToggle())
				{
					num = !acquireCharacterFromTemplate;
				}
				else
				{
					if (Game.instance.GetPlayerProfile().HaveLogoutPoint())
					{
						return;
					}
					num = Game.instance.GetPlayerProfile().HaveCustomSpawnPoint();
				}
				if (num)
				{
					return;
				}
				acquireCharacterFromTemplate = false;
				((Humanoid)Player.m_localPlayer).m_inventory.RemoveAll();
				Player.m_localPlayer.m_skills.m_skillData.Clear();
				Player.m_localPlayer.m_knownMaterial.Clear();
				Player.m_localPlayer.m_knownRecipes.Clear();
				Player.m_localPlayer.m_knownStations.Clear();
				Player.m_localPlayer.m_knownTexts.Clear();
				Player.m_localPlayer.m_uniques.Clear();
				Player.m_localPlayer.m_trophies.Clear();
				Player.m_localPlayer.m_customData.Clear();
				((Humanoid)Player.m_localPlayer).GiveDefaultItems();
				try
				{
					PlayerTemplate playerTemplate = new DeserializerBuilder().IgnoreFields().Build().Deserialize<PlayerTemplate>(ServerCharacters.playerTemplate.Value);
					if (playerTemplate != null)
					{
						foreach (KeyValuePair<string, float> skill in playerTemplate.skills)
						{
							((Character)Player.m_localPlayer).GetSkills().CheatRaiseSkill(skill.Key, skill.Value, true);
						}
						Inventory inventory = ((Humanoid)Player.m_localPlayer).m_inventory;
						foreach (KeyValuePair<string, int> item in playerTemplate.items)
						{
							inventory.AddItem(item.Key, item.Value, 1, 0, 0L, "", false);
						}
						List<PlayerTemplate.Position> spawn = playerTemplate.spawn;
						if (spawn != null && spawn.Count > 0)
						{
							State state = Random.state;
							Random.InitState(((object)(PlatformUserID)(ref UserInfo.GetLocalUser().UserId)).GetHashCode());
							int index = Random.Range(0, spawn.Count - 1);
							Random.state = state;
							((Component)Player.m_localPlayer).transform.position = new Vector3((float)spawn[index].x, (float)spawn[index].y, (float)spawn[index].z);
						}
					}
				}
				catch (SerializationException)
				{
				}
				Game.instance.SavePlayerProfile(true);
				if (!(ServerCharacters.firstLoginMessage.Value != ""))
				{
					return;
				}
				foreach (Player allPlayer in Player.GetAllPlayers())
				{
					((Character)allPlayer).Message((MessageType)2, ServerCharacters.firstLoginMessage.Value.Replace("{name}", ((Character)Player.m_localPlayer).GetHoverName()), 0, (Sprite)null);
				}
			}
		}

		[HarmonyPatch(typeof(Valkyrie), "Awake")]
		private class ChangeValkyrieTarget
		{
			[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
			private static void Prefix(Valkyrie __instance)
			{
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
				if (!((Component)__instance).GetComponent<ZNetView>().IsOwner())
				{
					return;
				}
				try
				{
					PlayerTemplate playerTemplate = new DeserializerBuilder().IgnoreFields().Build().Deserialize<PlayerTemplate>(ServerCharacters.playerTemplate.Value);
					if (playerTemplate != null)
					{
						List<PlayerTemplate.Position> spawn = playerTemplate.spawn;
						if (spawn != null && spawn.Count > 0)
						{
							State state = Random.state;
							Random.InitState(((object)(PlatformUserID)(ref UserInfo.GetLocalUser().UserId)).GetHashCode());
							int index = Random.Range(0, spawn.Count - 1);
							Random.state = state;
							((Component)Player.m_localPlayer).transform.position = new Vector3((float)spawn[index].x, (float)spawn[index].y, (float)spawn[index].z);
						}
					}
				}
				catch (SerializationException)
				{
				}
			}
		}

		[HarmonyPatch(typeof(Player), "OnSpawned")]
		private static class DisableValkyrieAndIntro
		{
			private static void Postfix(bool spawnValkyrie)
			{
				if (spawnValkyrie)
				{
					switch (ServerCharacters.newCharacterIntro.Value)
					{
					case Intro.Disabled:
						Game.instance.SkipIntro();
						break;
					case Intro.Valkyrie:
						Game.instance.m_inIntro = (Game.instance.m_queuedIntro = false);
						TextViewer.instance.HideIntro();
						break;
					}
				}
			}
		}

		[HarmonyPatch(typeof(Game), "FindSpawnPoint")]
		private class ReplaceSpawnPoint
		{
			private static bool CheckCustomSpawnPoint(out Vector3 pos)
			{
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bb: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					PlayerTemplate playerTemplate = new DeserializerBuilder().IgnoreFields().Build().Deserialize<PlayerTemplate>(ServerCharacters.playerTemplate.Value);
					if (playerTemplate == null)
					{
						pos = Vector3.zero;
						return false;
					}
					List<PlayerTemplate.Position> spawn = playerTemplate.spawn;
					if (spawn != null && spawn.Count > 0)
					{
						State state = Random.state;
						Random.InitState(((object)(PlatformUserID)(ref UserInfo.GetLocalUser().UserId)).GetHashCode());
						int index = Random.Range(0, spawn.Count - 1);
						Random.state = state;
						pos = new Vector3((float)spawn[index].x, (float)spawn[index].y, (float)spawn[index].z);
						return true;
					}
				}
				catch (SerializationException)
				{
				}
				pos = Vector3.zero;
				return false;
			}

			[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> _instructions, ILGenerator ilg)
			{
				//IL_015b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0160: Unknown result type (might be due to invalid IL or missing references)
				//IL_016e: Expected O, but got Unknown
				//IL_0197: Unknown result type (might be due to invalid IL or missing references)
				//IL_019d: Expected O, but got Unknown
				//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b1: Expected O, but got Unknown
				MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(ZoneSystem), "GetLocationIcon", (Type[])null, (Type[])null);
				FieldInfo fieldInfo = AccessTools.DeclaredField(typeof(Game), "m_StartLocation");
				List<CodeInstruction> list = _instructions.ToList();
				for (int i = 0; i < list.Count; i++)
				{
					if (i < list.Count - 4 && list[i].opcode == OpCodes.Callvirt && CodeInstructionExtensions.OperandIs(list[i], (MemberInfo)methodInfo) && list[i - 2].opcode == OpCodes.Ldfld && CodeInstructionExtensions.OperandIs(list[i - 2], (MemberInfo)fieldInfo))
					{
						int num = i;
						MethodInfo methodInfo2 = AccessTools.DeclaredPropertyGetter(typeof(ZoneSystem), "instance");
						while (list[num].opcode != OpCodes.Call || !CodeInstructionExtensions.OperandIs(list[num], (MemberInfo)methodInfo2))
						{
							num--;
						}
						CodeInstruction obj = list.Skip(i).SkipWhile((CodeInstruction instr) => instr.opcode.FlowControl != FlowControl.Cond_Branch).Skip(1)
							.First();
						Label label = ilg.DefineLabel();
						obj.labels.Add(label);
						List<Label> labels = list[num].labels;
						list.InsertRange(num, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[4]
						{
							new CodeInstruction(OpCodes.Nop, (object)null)
							{
								labels = new List<Label>(labels)
							},
							list[i - 1],
							new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(ReplaceSpawnPoint), "CheckCustomSpawnPoint", (Type[])null, (Type[])null)),
							new CodeInstruction(OpCodes.Brtrue, (object)label)
						});
						labels.Clear();
						break;
					}
				}
				return list;
			}
		}

		[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
		[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
		[HarmonyPatch(typeof(Player), "CreateTombStone")]
		private class PreserveItemsOnHardcoreModeDeath
		{
			[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(2)]
			private static ZPackage playerSave;

			[HarmonyPriority(700)]
			private static void Prefix(Player __instance)
			{
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Expected O, but got Unknown
				if (ServerCharacters.hardcoreMode.GetToggle() && iDied)
				{
					playerSave = new ZPackage();
					__instance.Save(playerSave);
					playerSave.SetPos(0);
				}
			}

			[HarmonyPriority(100)]
			private static void Postfix(Player __instance)
			{
				if (playerSave != null && ServerCharacters.hardcoreMode.GetToggle() && iDied)
				{
					__instance.m_knownTexts.Clear();
					__instance.m_knownStations.Clear();
					__instance.Load(playerSave);
					playerSave = null;
				}
			}
		}

		[HarmonyPatch(typeof(Game), "UpdateRespawn")]
		[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
		[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
		private static class ChangeSpawnShoutMessage
		{
			[CompilerGenerated]
			private sealed class <Transpiler>d__1 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator
			{
				private int <>1__state;

				private CodeInstruction <>2__current;

				private int <>l__initialThreadId;

				[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(new byte[] { 0, 1 })]
				private IEnumerable<CodeInstruction> instructions;

				[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(new byte[] { 0, 1 })]
				public IEnumerable<CodeInstruction> <>3__instructions;

				[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
				private ILGenerator ilg;

				[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
				public ILGenerator <>3__ilg;

				[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
				private MethodInfo <sendText>5__2;

				[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(new byte[] { 0, 1 })]
				private IEnumerator<CodeInstruction> <>7__wrap2;

				[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
				private CodeInstruction <instruction>5__4;

				private Label <skipLabel>5__5;

				private Label <endLabel>5__6;

				CodeInstruction IEnumerator<CodeInstruction>.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				object IEnumerator.Current
				{
					[DebuggerHidden]
					[return: <ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
					get
					{
						return <>2__current;
					}
				}

				[DebuggerHidden]
				public <Transpiler>d__1(int <>1__state)
				{
					this.<>1__state = <>1__state;
					<>l__initialThreadId = Environment.CurrentManagedThreadId;
				}

				[DebuggerHidden]
				void IDisposable.Dispose()
				{
					int num = <>1__state;
					if (num == -3 || (uint)(num - 1) <= 11u)
					{
						try
						{
						}
						finally
						{
							<>m__Finally1();
						}
					}
					<sendText>5__2 = null;
					<>7__wrap2 = null;
					<instruction>5__4 = null;
					<>1__state = -2;
				}

				private bool MoveNext()
				{
					//IL_0115: Unknown result type (might be due to invalid IL or missing references)
					//IL_011f: Expected O, but got Unknown
					//IL_0140: Unknown result type (might be due to invalid IL or missing references)
					//IL_014a: Expected O, but got Unknown
					//IL_019b: Unknown result type (might be due to invalid IL or missing references)
					//IL_01a5: Expected O, but got Unknown
					//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
					//IL_01d6: Expected O, but got Unknown
					//IL_021f: Unknown result type (might be due to invalid IL or missing references)
					//IL_0229: Expected O, but got Unknown
					//IL_0246: Unknown result type (might be due to invalid IL or missing references)
					//IL_024b: Unknown result type (might be due to invalid IL or missing references)
					//IL_0267: Expected O, but got Unknown
					//IL_0284: Unknown result type (might be due to invalid IL or missing references)
					//IL_028e: Expected O, but got Unknown
					//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
					//IL_02b6: Expected O, but got Unknown
					//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
					//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
					//IL_02f5: Expected O, but got Unknown
					//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
					//IL_00f8: Expected O, but got Unknown
					try
					{
						switch (<>1__state)
						{
						default:
							return false;
						case 0:
							<>1__state = -1;
							<sendText>5__2 = AccessTools.DeclaredMethod(typeof(Chat), "SendText", (Type[])null, (Type[])null);
							<>7__wrap2 = instructions.GetEnumerator();
							<>1__state = -3;
							break;
						case 1:
							<>1__state = -3;
							<>2__current = new CodeInstruction(OpCodes.Dup, (object)null);
							<>1__state = 2;
							return true;
						case 2:
							<>1__state = -3;
							<>2__current = new CodeInstruction(OpCodes.Ldstr, (object)"");
							<>1__state = 3;
							return true;
						case 3:
							<>1__state = -3;
							<>2__current = new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(string), "Equals", new Type[2]
							{
								typeof(string),
								typeof(string)
							}, (Type[])null));
							<>1__state = 4;
							return true;
						case 4:
							<>1__state = -3;
							<>2__current = new CodeInstruction(OpCodes.Brtrue, (object)<skipLabel>5__5);
							<>1__state = 5;
							return true;
						case 5:
							<>1__state = -3;
							<>2__current = <instruction>5__4;
							<>1__state = 6;
							return true;
						case 6:
							<>1__state = -3;
							<>2__current = new CodeInstruction(OpCodes.Br, (object)<endLabel>5__6);
							<>1__state = 7;
							return true;
						case 7:
							<>1__state = -3;
							<>2__current = new CodeInstruction(OpCodes.Pop, (object)null)
							{
								labels = new List<Label> { <skipLabel>5__5 }
							};
							<>1__state = 8;
							return true;
						case 8:
							<>1__state = -3;
							<>2__current = new CodeInstruction(OpCodes.Pop, (object)null);
							<>1__state = 9;
							return true;
						case 9:
							<>1__state = -3;
							<>2__current = new CodeInstruction(OpCodes.Pop, (object)null);
							<>1__state = 10;
							return true;
						case 10:
							<>1__state = -3;
							<>2__current = new CodeInstruction(OpCodes.Nop, (object)null)
							{
								labels = new List<Label> { <endLabel>5__6 }
							};
							<>1__state = 11;
							return true;
						case 11:
							<>1__state = -3;
							goto IL_032b;
						case 12:
							{
								<>1__state = -3;
								goto IL_032b;
							}
							IL_032b:
							<instruction>5__4 = null;
							break;
						}
						if (<>7__wrap2.MoveNext())
						{
							<instruction>5__4 = <>7__wrap2.Current;
							if (CodeInstructionExtensions.Calls(<instruction>5__4, <sendText>5__2))
							{
								<skipLabel>5__5 = ilg.DefineLabel();
								<endLabel>5__6 = ilg.DefineLabel();
								<>2__current = new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(ChangeSpawnShoutMessage), "ReplaceMessage", (Type[])null, (Type[])null));
								<>1__state = 1;
								return true;
							}
							<>2__current = <instruction>5__4;
							<>1__state = 12;
							return true;
						}
						<>m__Finally1();
						<>7__wrap2 = null;
						return false;
					}
					catch
					{
						//try-fault
						((IDisposable)this).Dispose();
						throw;
					}
				}

				bool IEnumerator.MoveNext()
				{
					//ILSpy generated this explicit interface implementation from .override directive in MoveNext
					return this.MoveNext();
				}

				private void <>m__Finally1()
				{
					<>1__state = -1;
					if (<>7__wrap2 != null)
					{
						<>7__wrap2.Dispose();
					}
				}

				[DebuggerHidden]
				void IEnumerator.Reset()
				{
					throw new NotSupportedException();
				}

				[DebuggerHidden]
				[return: <ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
				IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
				{
					<Transpiler>d__1 <Transpiler>d__;
					if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
					{
						<>1__state = 0;
						<Transpiler>d__ = this;
					}
					else
					{
						<Transpiler>d__ = new <Transpiler>d__1(0);
					}
					<Transpiler>d__.instructions = <>3__instructions;
					<Transpiler>d__.ilg = <>3__ilg;
					return <Transpiler>d__;
				}

				[DebuggerHidden]
				[return: <ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
				IEnumerator IEnumerable.GetEnumerator()
				{
					return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
				}
			}

			private static string ReplaceMessage(string original)
			{
				if (!(ServerCharacters.loginMessage.Value == "I have arrived!"))
				{
					return ServerCharacters.loginMessage.Value;
				}
				return original;
			}

			[IteratorStateMachine(typeof(<Transpiler>d__1))]
			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator ilg)
			{
				//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
				return new <Transpiler>d__1(-2)
				{
					<>3__instructions = instructions,
					<>3__ilg = ilg
				};
			}
		}

		[HarmonyPatch(typeof(FejdStartup), "ShowConnectError")]
		private class ShowConnectionError
		{
			[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
			private static void Postfix(FejdStartup __instance)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Invalid comparison between Unknown and I4
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Invalid comparison between Unknown and I4
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Invalid comparison between Unknown and I4
				if ((int)ZNet.GetConnectionStatus() == 987345987)
				{
					__instance.m_connectionFailedError.text = "Server is undergoing maintenance. Please try again later.";
				}
				if ((int)ZNet.GetConnectionStatus() == 498209834)
				{
					__instance.m_connectionFailedError.text = "Your character name contains illegal characters. Please choose a different name.";
				}
				if ((int)ZNet.GetConnectionStatus() == 845979243)
				{
					__instance.m_connectionFailedError.text = "You are not allowed to create more than one character on this server.";
				}
				if (__instance.m_connectionFailedPanel.activeSelf && connectionError != null)
				{
					TMP_Text connectionFailedError = __instance.m_connectionFailedError;
					connectionFailedError.text = connectionFailedError.text + "\n" + connectionError;
					connectionError = null;
				}
				if (iDied && ServerCharacters.hardcoreMode.GetToggle())
				{
					__instance.m_connectionFailedError.text = "You died on a hardcore server. You can continue to use your character in singleplayer, but will have to create a new one to connect to the server.";
					__instance.m_connectionFailedPanel.SetActive(true);
					iDied = false;
				}
			}
		}

		[HarmonyPatch(typeof(ZNet), "RPC_Disconnect")]
		private class PatchZNetRPC_Disconnect
		{
			[UsedImplicitly]
			[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
			private static void Prefix(ZNet __instance)
			{
				if (!__instance.IsServer() && serverCharacter)
				{
					forceSynchronousSaving = true;
					Game.instance.SavePlayerProfile(true);
					forceSynchronousSaving = false;
				}
			}
		}

		[HarmonyPatch(typeof(Game), "OnApplicationQuit")]
		private class PatchGameOnApplicationQuit
		{
			[UsedImplicitly]
			private static void Prefix()
			{
				forceSynchronousSaving = true;
			}
		}

		[HarmonyPatch(typeof(Menu), "QuitGame")]
		private static class ForceSaveOnQuit
		{
			private static void Prefix()
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Invalid comparison between Unknown and I4
				if ((int)ZNet.m_onlineBackend == 1)
				{
					ZNet.instance.m_haveStoped = false;
					forceSynchronousSaving = false;
					Game.instance.SavePlayerProfile(true);
				}
			}
		}

		[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
		[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
		[HarmonyPatch(typeof(Game), "SavePlayerProfile")]
		private class ForceSavingPosition
		{
			private static bool originalValue;

			[UsedImplicitly]
			private static void Prefix(Game __instance, ref bool setLogoutPoint, out bool __state)
			{
				__state = ZNet.instance.m_haveStoped;
				if (__instance.m_shuttingDown)
				{
					ZNet.instance.m_haveStoped = true;
				}
				if (ZNet.m_world == null || __instance.m_playerProfile.HaveLogoutPoint())
				{
					originalValue = true;
					return;
				}
				originalValue = setLogoutPoint;
				setLogoutPoint = true;
			}

			[UsedImplicitly]
			private static void Postfix(Game __instance)
			{
				if (!originalValue)
				{
					__instance.m_playerProfile.ClearLoguoutPoint();
				}
			}

			[UsedImplicitly]
			private static void Finalizer(bool __state)
			{
				ZNet.instance.m_haveStoped = __state;
			}
		}

		[HarmonyPatch(typeof(Game), "Logout")]
		private class PatchGameLogout
		{
			[UsedImplicitly]
			private static void Prefix()
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Invalid comparison between Unknown and I4
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Invalid comparison between Unknown and I4
				doEmergencyBackup = (int)ZNet.GetConnectionStatus() != 1 && (int)ZNet.GetConnectionStatus() != 2 && !Game.instance.IsShuttingDown();
				if (doEmergencyBackup)
				{
					Utils.Log("Lost connection to the server. Preparing for emergency backup of profile data.");
				}
			}
		}

		[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
		[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
		private class PlayerSnapshot
		{
			public List<ItemData> inventory;

			public Dictionary<string, int> knownStations;

			public Dictionary<string, string> knownTexts;
		}

		[HarmonyPatch(typeof(Inventory), "Changed")]
		private class PatchInventoryChanged
		{
			[CompilerGenerated]
			private sealed class <>c__DisplayClass1_0
			{
				public Inventory __instance;

				public ZNetPeer serverPeer;
			}

			public static bool queuedThisFrame;

			[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
			private static void Prefix(Inventory __instance)
			{
				<>c__DisplayClass1_0 CS$<>8__locals0 = new <>c__DisplayClass1_0();
				CS$<>8__locals0.__instance = __instance;
				if (!queuedThisFrame && CS$<>8__locals0.__instance == ((Humanoid)(Player.m_localPlayer?)).m_inventory)
				{
					CS$<>8__locals0.serverPeer = ZNet.instance.GetServerPeer();
					if (CS$<>8__locals0.serverPeer != null)
					{
						queuedThisFrame = true;
						((MonoBehaviour)ZNet.instance).StartCoroutine(saveAsync());
					}
				}
				[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
				[IteratorStateMachine(typeof(<>c__DisplayClass1_0.<<Prefix>g__saveAsync|0>d))]
				IEnumerator saveAsync()
				{
					//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
					return new <>c__DisplayClass1_0.<<Prefix>g__saveAsync|0>d(0)
					{
						<>4__this = CS$<>8__locals0
					};
				}
			}
		}

		[HarmonyPatch(typeof(Player), "OnDeath")]
		private class KickPlayerOnDeath
		{
			private static void Prefix()
			{
				if (ServerCharacters.hardcoreMode.GetToggle())
				{
					iDied = true;
					((MonoBehaviour)Game.instance).Invoke("Logout", 1f);
				}
			}
		}

		[HarmonyPatch]
		private static class MonitorPlayerActivityCheck
		{
			[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
			private static IEnumerable<MethodInfo> TargetMethods()
			{
				return new MethodInfo[2]
				{
					AccessTools.DeclaredMethod(typeof(ZInput), "GetButton", (Type[])null, (Type[])null),
					AccessTools.DeclaredMethod(typeof(ZInput), "GetButtonDown", (Type[])null, (Type[])null)
				};
			}

			private static void Postfix(ref bool __result)
			{
				if (__result)
				{
					MonitorPlayerActivity.counter = 0;
				}
			}
		}

		[HarmonyPatch(typeof(Player), "SetLocalPlayer")]
		[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
		[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
		private static class MonitorPlayerActivity
		{
			[CompilerGenerated]
			private sealed class <MeasureActivity>d__1 : IEnumerator<object>, IDisposable, IEnumerator
			{
				private int <>1__state;

				[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
				private object <>2__current;

				object IEnumerator<object>.Current
				{
					[DebuggerHidden]
					[return: <ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
					get
					{
						return <>2__current;
					}
				}

				object IEnumerator.Current
				{
					[DebuggerHidden]
					[return: <ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
					get
					{
						return <>2__current;
					}
				}

				[DebuggerHidden]
				public <MeasureActivity>d__1(int <>1__state)
				{
					this.<>1__state = <>1__state;
				}

				[DebuggerHidden]
				void IDisposable.Dispose()
				{
					<>1__state = -2;
				}

				private bool MoveNext()
				{
					//IL_0087: Unknown result type (might be due to invalid IL or missing references)
					//IL_0091: Expected O, but got Unknown
					//IL_006c: Unknown result type (might be due to invalid IL or missing references)
					int num = <>1__state;
					if (num != 0)
					{
						if (num != 1)
						{
							return false;
						}
						<>1__state = -1;
					}
					else
					{
						<>1__state = -1;
					}
					if (++counter >= ServerCharacters.afkKickTimer.Value && ServerCharacters.afkKickTimer.Value > 0 && !ZNet.m_isServer && (!ServerCharacters.configSync.IsAdmin || ServerCharacters.excludeAdminsFromAfkCheck.Value == Toggle.Off))
					{
						Game.instance.Logout(true, true);
						ZNet.m_connectionStatus = (ConnectionStatus)4;
						connectionError = "You have been logged out due to inactivity.";
						counter = 0;
					}
					<>2__current = (object)new WaitForSeconds(60f);
					<>1__state = 1;
					return true;
				}

				bool IEnumerator.MoveNext()
				{
					//ILSpy generated this explicit interface implementation from .override directive in MoveNext
					return this.MoveNext();
				}

				[DebuggerHidden]
				void IEnumerator.Reset()
				{
					throw new NotSupportedException();
				}
			}

			public static int counter;

			[IteratorStateMachine(typeof(<MeasureActivity>d__1))]
			private static IEnumerator MeasureActivity()
			{
				//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
				return new <MeasureActivity>d__1(0);
			}

			private static void Postfix(Player __instance)
			{
				PatchInventoryChanged.queuedThisFrame = false;
				((MonoBehaviour)__instance).StartCoroutine(MeasureActivity());
			}
		}

		[HarmonyPatch(typeof(Minimap), "Awake")]
		private static class DisplayMaintenanceCountdown
		{
			[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
			private static void Postfix(Minimap __instance)
			{
				//IL_0072: Unknown result type (might be due to invalid IL or missing references)
				//IL_0087: Unknown result type (might be due to invalid IL or missing references)
				//IL_009c: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ad: 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)
				maintenanceCountdown = ((Component)Object.Instantiate<Transform>(__instance.m_smallRoot.transform.Find("small_biome"), __instance.m_smallRoot.transform)).GetComponent<TextMeshProUGUI>();
				((Object)maintenanceCountdown).name = "ServerCharacters Maintenance Timer";
				((TMP_Text)maintenanceCountdown).text = "";
				((TMP_Text)maintenanceCountdown).alignment = (TextAlignmentOptions)513;
				RectTransform component = ((Component)maintenanceCountdown).GetComponent<RectTransform>();
				component.anchorMin = new Vector2(0f, 1f);
				component.anchorMax = new Vector2(1f, 1f);
				component.pivot = new Vector2(0f, 0.5f);
				component.anchoredPosition = new Vector2(5f, 0f - component.anchoredPosition.y);
			}
		}

		public static bool serverCharacter;

		private static bool currentlySaving;

		private static bool forceSynchronousSaving;

		private static bool acquireCharacterFromTemplate;

		private static bool doEmergencyBackup;

		private static bool iDied;

		[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(1)]
		public static TextMeshProUGUI maintenanceCountdown;

		[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(2)]
		private static PlayerSnapshot playerSnapShotLast;

		[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(2)]
		private static PlayerSnapshot playerSnapShotNew;

		[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(2)]
		private static byte[] serverEncryptionKey;

		private static long serverEncryptionTime;

		[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(2)]
		private static string connectionError;

		[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(2)]
		private static TaskCompletionSource<Vector3> awaitingPos;

		private static void cleanEmergencyBackup()
		{
			string characterSavePath = Utils.CharacterSavePath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			string path = characterSavePath + directorySeparatorChar + Game.instance.m_playerProfile.m_filename + ".fch.signature";
			string characterSavePath2 = Utils.CharacterSavePath;
			directorySeparatorChar = Path.DirectorySeparatorChar;
			string text = characterSavePath2 + directorySeparatorChar + Game.instance.m_playerProfile.m_filename + ".fch.serverbackup";
			if (File.Exists(text) && File.Exists(path))
			{
				File.Delete(path);
				File.Delete(text);
				Utils.Log("Deleted emergency backup from " + text);
			}
		}

		[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
		private static byte[] generateProfileSignature(byte[] profileData, byte[] key)
		{
			//IL_0042: 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_0053: 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)
			byte[] array = SHA512.Create().ComputeHash(profileData);
			Aes aes = Aes.Create();
			aes.Key = key;
			MemoryStream memoryStream = new MemoryStream();
			CryptoStream cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write);
			cryptoStream.Write(array, 0, array.Length);
			cryptoStream.FlushFinalBlock();
			cryptoStream.Close();
			ZPackage val = new ZPackage();
			val.Write(memoryStream.ToArray());
			val.Write(aes.IV);
			val.Write(serverEncryptionTime);
			return val.GetArray();
		}

		[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
		private static void receiveEncryptionKeyFromServer(ZRpc peerRpc, ZPackage keyPackage)
		{
			serverEncryptionKey = keyPackage.ReadByteArray();
			serverEncryptionTime = keyPackage.ReadLong();
		}

		public static void snapShotProfile()
		{
			ZNet instance = ZNet.instance;
			if (instance != null && !instance.IsServer() && (Object)(object)Player.m_localPlayer != (Object)null)
			{
				if (ZNet.instance.GetServerPing() < 1.5f)
				{
					playerSnapShotLast = playerSnapShotNew;
				}
				playerSnapShotNew = new PlayerSnapshot
				{
					inventory = ((Humanoid)Player.m_localPlayer).GetInventory().m_inventory.Select((ItemData d) => d.Clone()).ToList(),
					knownStations = Player.m_localPlayer.m_knownStations.ToDictionary((KeyValuePair<string, int> t) => t.Key, (KeyValuePair<string, int> t) => t.Value),
					knownTexts = Player.m_localPlayer.m_knownTexts.ToDictionary((KeyValuePair<string, string> t) => t.Key, (KeyValuePair<string, string> t) => t.Value)
				};
			}
		}
	}
	public enum Toggle
	{
		On = 1,
		Off = 0
	}
	public enum Intro
	{
		Disabled,
		Valkyrie,
		ValkyrieAndIntro
	}
	[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
	[PublicAPI]
	[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
	public class PlayerTemplate
	{
		[PublicAPI]
		[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(0)]
		public class Position
		{
			public int x { get; set; }

			public int y { get; set; }

			public int z { get; set; }
		}

		public Dictionary<string, float> skills { get; set; } = new Dictionary<string, float>();


		public Dictionary<string, int> items { get; set; } = new Dictionary<string, int>();


		public List<Position> spawn { get; set; } = new List<Position>();

	}
	[BepInIncompatibility("org.bepinex.plugins.valheim_plus")]
	[BepInPlugin("org.bepinex.plugins.servercharacters", "Server Characters", "1.4.16")]
	[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(0)]
	[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(1)]
	public class ServerCharacters : BaseUnityPlugin
	{
		[<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(0)]
		private class ConfigurationManagerAttributes
		{
			[UsedImplicitly]
			public bool? Browsable = false;
		}

		private const string ModName = "Server Characters";

		private const string ModVersion = "1.4.16";

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

		public static ServerCharacters selfReference = null;

		private static readonly Harmony harmony = new Harmony("org.bepinex.plugins.servercharacters");

		private float fixedUpdateCount;

		public int tickCount = int.MaxValue;

		public static int monotonicCounter = 0;

		public const int MaintenanceDisconnectMagic = 987345987;

		public const int CharacterNameDisconnectMagic = 498209834;

		public const int SingleCharacterModeDisconnectMagic = 845979243;

		public static readonly ConfigSync configSync = new ConfigSync("org.bepinex.plugins.servercharacters")
		{
			DisplayName = "Server Characters",
			CurrentVersion = "1.4.16",
			MinimumRequiredVersion = "1.4.16"
		};

		private static ConfigEntry<Toggle> serverConfigLocked = null;

		public static ConfigEntry<Toggle> singleCharacterMode = null;

		public static ConfigEntry<Toggle> backupOnlyMode = null;

		public static ConfigEntry<Toggle> hardcoreMode = null;

		public static ConfigEntry<Toggle> maintenanceMode = null;

		private static ConfigEntry<int> maintenanceTimer = null;

		public static ConfigEntry<int> backupsToKeep = null;

		public static ConfigEntry<int> autoSaveInterval = null;

		public static ConfigEntry<int> afkKickTimer = null;

		public static ConfigEntry<Toggle> excludeAdminsFromAfkCheck = null;

		public static ConfigEntry<string> webhookURL = null;

		private static ConfigEntry<string> webhookUsernameMaintenance = null;

		private static ConfigEntry<string> maintenanceEnabledText = null;

		private static ConfigEntry<string> maintenanceFinishedText = null;

		private static ConfigEntry<string> maintenanceAbortedText = null;

		private static ConfigEntry<string> maintenanceStartedText = null;

		public static ConfigEntry<string> loginMessage = null;

		public static ConfigEntry<string> firstLoginMessage = null;

		public static ConfigEntry<Toggle> postFirstLoginToWebhook = null;

		public static ConfigEntry<string> webhookUsernameOther = null;

		public static ConfigEntry<string> serverKey = null;

		public static ConfigEntry<string> serverListenAddress = null;

		public static ConfigEntry<Intro> newCharacterIntro = null;

		public static ConfigEntry<Toggle> storePoison = null;

		public static readonly CustomSyncedValue<string> playerTemplate = new CustomSyncedValue<string>(configSync, "PlayerTemplate", readCharacterTemplate());

		public static ManualLogSource logger => ((BaseUnityPlugin)selfReference).Logger;

		private static string pluginDir => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

		private ConfigEntry<T> config<[<ac6d2775-cef6-4d66-9819-032e899cd913>Nullable(2)] T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true)
		{
			ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, description);
			configSync.AddConfigEntry<T>(val).SynchronizedConfig = synchronizedSetting;
			return val;
		}

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

		public void Awake()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Expected O, but got Unknown
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Expected O, but got Unknown
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Expected O, but got Unknown
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Expected O, but got Unknown
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Expected O, but got Unknown
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Expected O, but got Unknown
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Expected O, but got Unknown
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Expected O, but got Unknown
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Expected O, but got Unknown
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Expected O, but got Unknown
			//IL_0378: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Expected O, but got Unknown
			//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ae: Expected O, but got Unknown
			//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d5: Expected O, but got Unknown
			//IL_03fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0405: Expected O, but got Unknown
			//IL_042e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0439: Expected O, but got Unknown
			//IL_0462: Unknown result type (might be due to invalid IL or missing references)
			//IL_046d: Expected O, but got Unknown
			//IL_0574: Unknown result type (might be due to invalid IL or missing references)
			//IL_0581: Expected O, but got Unknown
			selfReference = this;
			serverConfigLocked = config("1 - General", "Lock Configuration", Toggle.On, "If on, the configuration is locked and can be changed by server admins only.");
			configSync.AddLockingConfigEntry<Toggle>(serverConfigLocked);
			afkKickTimer = config("1 - General", "AFK Kick Timer", 0, new ConfigDescription("Automatically kicks players, if they haven't moved at all in the configured time. In minutes. 0 is disabled.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 30), Array.Empty<object>()));
			excludeAdminsFromAfkCheck = config("1 - General", "Exclude Admins from AFK check", Toggle.Off, new ConfigDescription("Can be used to exclude admins from the AFK kick timer.", (AcceptableValueBase)null, Array.Empty<object>()));
			webhookURL = config("1 - General", "Discord Webhook URL", "", new ConfigDescription("Discord API endpoint to announce maintenance.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes()
			}), synchronizedSetting: false);
			loginMessage = config("1 - General", "Login Message", "I have arrived!", new ConfigDescription("Message to shout on login. Leave empty to not shout anything.", (AcceptableValueBase)null, Array.Empty<object>()));
			webhookUsernameOther = config("1 - General", "Discord Username Other", "Server Characters", new ConfigDescription("Username to be used for non-maintenance related posts to Discord.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes()
			}), synchronizedSetting: false);
			hardcoreMode = config("2 - Save Files", "Hardcore mode", Toggle.Off, "If set to on, players will be kicked from the server and their save file on the server will be deleted, if they die.");
			singleCharacterMode = config("2 - Save Files", "Single Character Mode", Toggle.Off, "If set to on, each SteamID / Xbox ID can create one character only on this server. Has no effect for admins.");
			backupOnlyMode = config("2 - Save Files", "Backup only mode", Toggle.Off, "Enabling this will not enforce the server profile anymore. DO NOT ENABLE THIS IF YOU DON'T KNOW EXACTLY WHAT YOU ARE DOING!");
			backupsToKeep = config("2 - Save Files", "Number of backups to keep", 25, new ConfigDescription("Sets the number of backups that should be stored for each character.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50), Array.Empty<object>()));
			autoSaveInterval = config("2 - Save Files", "Auto save interval", 30, new ConfigDescription("Minutes between auto saves of characters and the world.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 120), Array.Empty<object>()));
			autoSaveInterval.SettingChanged += [<17692631-e0d9-4bdb-8b7e-e1cff9bf39d5>NullableContext(0)] (object _, EventArgs _) =>
			{
				Game.m_saveInterval = autoSaveInterval.Value * 60;
			};
			storePoison = config("2 - Save Files", "Store poison debuff", Toggle.On, new ConfigDescription("If on, poison debuffs are stored in the save file on logout and applied on login, to prevent users from logging out if they are poisoned, to clear the debuff.", (AcceptableValueBase)null, Array.Empty<object>()));
			maintenanceMode = config("3 - Maintenance", "Maintenance Mode", Toggle.Off, "If set to on, a timer will start. If the timer elapses, all non-admins will be disconnected, the world will be saved and only admins will be able to connect to the server, until maintenance mode is toggled to off.");
			maintenanceMode.SettingChanged += toggleMaintenanceMode;
			maintenanceTimer = config("3 - Maintenance", "Maintenance Timer", 300, new ConfigDescription("Time in seconds that has to pass, before the maintenance mode becomes active.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 1800), Array.Empty<object>()));
			webhookUsernameMaintenance = config("3 - Maintenance", "Discord Username Maintenance", "Maintenance Bot", new ConfigDescription("Username to be used for maintenance related posts to Discord.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes()
			}), synchronizedSetting: false);
			maintenanceEnabledText = config("3 - Maintenance", "Maintenance enabled text", "Maintenance mode enabled. All non-admins will be disconnected in {time}.", new ConfigDescription("Message to be posted to Discord, when the maintenance mode has been toggled to 'On'. Leave empty to not post anything. Use {time} for the time until the maintenance starts.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes()
			}), synchronizedSetting: false);
			maintenanceFinishedText = config("3 - Maintenance", "Maintenance finished text", "Maintenance has been disabled and the server is back online. Have fun!", new ConfigDescription("Message to be posted to Discord, when the maintenance mode has been toggled to 'Off'. Leave empty to not post anything.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes()
			}), synchronizedSetting: false);
			maintenanceAbortedText = config("3 - Maintenance", "Maintenance aborted text", "Maintenance has been aborted.", new ConfigDescription("Message to be posted to Discord, when the maintenance has been aborted. Leave empty to not post anything.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes()
			}), synchronizedSetting: false);
			maintenanceStartedText = config("3 - Maintenance", "Maintenance started text", "Maintenance has started and players will be unable to connect.", new ConfigDescription("Message to be posted to Discord, when the maintenance has begun. Leave empty to not post anything.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes()
			}), synchronizedSetting: false);
			firstLoginMessage = config("3 - First Login", "First Login Message", "A new player logged in for the first time: {name}", new ConfigDescription("Message to display if a player logs in for the very first time. Leave empty to not display anything.", (AcceptableValueBase)null, Array.Empty<object>()));
			newCharacterIntro = config("3 - First Login", "Intro", Intro.ValkyrieAndIntro, new ConfigDescription("Sets the kind of intro new characters will get.", (AcceptableValueBase)null, Array.Empty<object>()));
			postFirstLoginToWebhook = config("3 - First Login", "First Login Webhook", Toggle.Off, new ConfigDescription("If on, the first login message is posted to the webhook as well.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes()
			}), synchronizedSetting: false);
			serverKey = config("4 - Other", "Server key", "", new ConfigDescription("DO NOT TOUCH THIS! DO NOT SHARE THIS! Encryption key used for emergency profile backups. DO NOT SHARE THIS! DO NOT TOUCH THIS!", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes()
			}), synchronizedSetting: false);
			serverListenAddress = config("4 - Other", "Webinterface listen address", "127.0.0.1:5982", new ConfigDescription("The address the webinterface API should listen on. Clear this value, if you don't use the webinterface.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes()
			}), synchronizedSetting: false);
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			harmony.PatchAll(executingAssembly);
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, "maintenance");
			fileSystemWatcher.Created += maintenanceFileEvent;
			fileSystemWatcher.Deleted += maintenanceFileEvent;
			fileSystemWatcher.IncludeSubdirectories = true;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.EnableRaisingEvents = true;
			FileSystemWatcher fileSystemWatcher2 = new FileSystemWatcher(pluginDir, "CharacterTemplate.yml");
			fileSystemWatcher2.Created += templateFileEvent;
			fileSystemWatcher2.Changed += templateFileEvent;
			fileSystemWatcher2.Renamed += templateFileEvent;
			fileSystemWatcher2.Deleted += templateFileEvent;
			fileSystemWatcher2.IncludeSubdirectories = true;
			fileSystemWatcher2.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher2.EnableRaisingEvents = true;
			ServerSide.generateServerKey();
			harmony.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ServerCharacters), "Initialize", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		public static void Initialize()
		{
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Expected O, but got Unknown
			harmony.Unpatch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Awake", (Type[])null, (Type[])null), (HarmonyPatchType)2, harmony.Id);
			if (!Utility.IsNullOrWhiteSpace(serverListenAddress.Value))
			{
				WebInterfaceAPI.StartServer();
			}
			Directory.CreateDirectory(Utils.CharacterSavePath);
			string characterFolderPath = PlayerProfile.GetCharacterFolderPath((FileSource)3);
			string[] files;
			if (Directory.Exists(characterFolderPath))
			{
				files = Directory.GetFiles(characterFolderPath);
				for (int i = 0; i < files.Length; i++)
				{
					FileInfo fileInfo = new FileInfo(files[i]);
					if (Utils.IsServerCharactersFilePattern(fileInfo.Name) || fileInfo.Name == "backups")
					{
						string fullName = fileInfo.FullName;
						string characterSavePath = Utils.CharacterSavePath;
						char directorySeparatorChar = Path.DirectorySeparatorChar;
						Directory.Move(fullName, characterSavePath + directorySeparatorChar + fileInfo.Name);
					}
				}
			}
			files = Directory.GetFiles(Utils.CharacterSavePath);
			for (int i = 0; i < files.Length; i++)
			{
				FileInfo fileInfo2 = new FileInfo(files[i]);
				if (fileInfo2.Name.EndsWith(".fch", StringComparison.Ordinal) && Regex.IsMatch(fileInfo2.Name.Split(new char[1] { '_' })[0], "^\\d+$"))
				{
					string? directoryName = fileInfo2.DirectoryName;
					char directorySeparatorChar = Path.DirectorySeparatorChar;
					string destFileName = directoryName + directorySeparatorChar + "Steam_" + fileInfo2.Name;
					fileInfo2.MoveTo(destFileName);
				}
			}
			files = Directory.GetFiles(Utils.CharacterSavePath);
			for (int i = 0; i < files.Length; i++)
			{
				FileInfo fileInfo3 = new FileInfo(files[i]);
				if (Utils.IsServerCharactersFilePattern(fileInfo3.Name))
				{
					Utils.ProfileName key = default(Utils.ProfileName);
					string[] array = fileInfo3.Name.Split(new char[1] { '_' });
					key.id = array[0] + "_" + array[1];
					key.name = array[2].Split(new char[1] { '.' })[0];
					PlayerProfile val = new PlayerProfile(fileInfo3.Name.Replace(".fch", ""), (FileSource)1);
					val.Load();
					Utils.Cache.profiles[key] = val;
				}
			}
		}

		private static void maintenanceFileEvent(object s, EventArgs e)
		{
			string configPath = Paths.ConfigPath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			Toggle toggle = (File.Exists(configPath + directorySeparatorChar + "maintenance") ? Toggle.On : Toggle.Off);
			SyncedConfigEntry<Toggle> syncedConfigEntry = ConfigSync.ConfigData<Toggle>(maintenanceMode);
			if (syncedConfigEntry.LocalBaseValue == null)
			{
				maintenanceMode.Value = toggle;
			}
			else
			{
				syncedConfigEntry.LocalBaseValue = toggle;
			}
		}

		private static void templateFileEvent(object s, EventArgs e)
		{
			playerTemplate.AssignLocalValue(readCharacterTemplate());
		}

		private static string readCharacterTemplate()
		{
			string text = pluginDir;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			string path = text + directorySeparatorChar + "CharacterTemplate.yml";
			if (!File.Exists(path))
			{
				return "";
			}
			return File.ReadAllText(path);
		}

		private void toggleMaintenanceMode(object s, EventArgs e)
		{
			if (maintenanceMode.GetToggle())
			{
				string text = maintenanceEnabledText.Value.Replace("{time}", Utils.getHumanFriendlyTime(maintenanceTimer.Value));
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Character)localPlayer).Message((MessageType)2, text, 0, (Sprite)null);
				}
				Utils.Log(text);
				tickCount = maintenanceTimer.Value;
				WebInterfaceAPI.SendMaintenanceMessage(new Maintenance
				{
					startTime = DateTimeOffset.Now.ToUnixTimeSeconds() + tickCount,
					maintenanceActive = false
				});
				if (configSync.IsSourceOfTruth)
				{
					string configPath = Paths.ConfigPath;
					char directorySeparatorChar = Path.DirectorySeparatorChar;
					File.Create(configPath + directorySeparatorChar + "maintenance");
					Utils.PostToDiscord(text, webhookUsernameMaintenance.Value);
				}
				return;
			}
			if (configSync.IsSourceOfTruth)
			{
				string configPath2 = Paths.ConfigPath;
				char directorySeparatorChar = Path.DirectorySeparatorChar;
				File.Delete(configPath2 + directorySeparatorChar + "maintenance");
				Utils.PostToDiscord((tickCount <= maintenanceTimer.Value) ? maintenanceAbortedText.Value : maintenanceFinishedText.Value, webhookUsernameMaintenance.Value);
				WebInterfaceAPI.SendMaintenanceMessage(new Maintenance
				{
					startTime = 0L,
					maintenanceActive = false
				});
			}
			if (tickCount <= maintenanceTimer.Value)
			{
				Player localPlayer2 = Player.m_localPlayer;
				if (localPlayer2 != null)
				{
					((Character)localPlayer2).Message((MessageType)2, "Maintenance aborted", 0, (Sprite)null);
				}
				Utils.Log("Maintenance aborted");
				tickCount = int.MaxValue;
			}
		}

		private void FixedUpdate()
		{
			fixedUpdateCount += Time.fixedDeltaTime;
			if ((double)fixedUpdateCount < 1.0)
			{
				return;
			}
			ZNet instance = ZN