Decompiled source of Cross Server Portals v0.3.1

ValheimCrossServerPortals.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.6", FrameworkDisplayName = ".NET Framework 4.6")]
[assembly: AssemblyCompany("ValheimCrossServerPortals")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Cross Server Portals Valheim Mod")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ValheimCrossServerPortals")]
[assembly: AssemblyTitle("ValheimCrossServerPortals")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Lunarbin.Valheim.CrossServerPortals
{
	[BepInPlugin("lunarbin.games.valheim", "Valheim Cross Server Portals", "0.3.0")]
	public class CrossServerPortals : BaseUnityPlugin
	{
		public struct ServerInfo
		{
			public string Address;

			public ushort Port;

			public string SourceTag;

			public string TargetTag;

			public ServerInfo()
			{
				Address = null;
				Port = 0;
				SourceTag = null;
				TargetTag = null;
			}

			public ServerInfo(string sourceTag, string address, ushort port = 0, string targetTag = "")
			{
				Address = address;
				Port = port;
				SourceTag = sourceTag;
				TargetTag = targetTag;
			}

			public ServerInfo(string sourceTag, string address, string targetTag = "")
			{
				Address = address;
				Port = 0;
				TargetTag = targetTag;
				SourceTag = sourceTag;
			}
		}

		private readonly struct SEData
		{
			public int Name { get; }

			public float Ttl { get; }

			public float Time { get; }

			public SEData(int name, float ttl, float time)
			{
				Name = name;
				Ttl = ttl;
				Time = time;
			}
		}

		[HarmonyPatch(typeof(Player), "Load")]
		private static class PatchPlayerLoad
		{
			private static void Postfix(Player __instance)
			{
				if (!preserveStatusEffects.Value || StatusEffects.Count <= 0)
				{
					return;
				}
				foreach (SEData statusEffect2 in StatusEffects)
				{
					((Character)__instance).GetSEMan().AddStatusEffect(statusEffect2.Name, false, 0, 0f);
					StatusEffect statusEffect = ((Character)__instance).GetSEMan().GetStatusEffect(statusEffect2.Name);
					if ((Object)(object)statusEffect != (Object)null)
					{
						statusEffect.m_ttl = statusEffect2.Time;
					}
				}
				StatusEffects.Clear();
			}
		}

		[HarmonyPatch(typeof(TeleportWorld), "Teleport")]
		internal static class PatchTeleport
		{
			private static bool Prefix(TeleportWorld __instance, ref Player player)
			{
				string text = __instance.GetText();
				if (PortalTagIsToServer(text))
				{
					((Character)player).Message((MessageType)2, "Teleporting to " + text, 0, (Sprite)null);
					TeleportToServer(text, __instance);
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(TeleportWorld), "HaveTarget")]
		internal class PatchTeleportWorldHaveTarget
		{
			private static bool Prefix(ref bool __result, TeleportWorld __instance)
			{
				string text = __instance.GetText();
				if (!PortalTagIsToServer(text))
				{
					if (!defaultsSet)
					{
						SetPortalDefaults(__instance);
					}
					if (defaultsSet)
					{
						SetPortalColors(__instance, defaultColors: true);
					}
					return true;
				}
				if (defaultsSet)
				{
					SetPortalColors(__instance, defaultColors: false);
				}
				__result = true;
				return false;
			}
		}

		[HarmonyPatch(typeof(TeleportWorld), "TargetFound")]
		internal class PatchTeleportWorldTargetFound
		{
			private static bool Prefix(ref bool __result, TeleportWorld __instance)
			{
				string text = __instance.GetText();
				if (!PortalTagIsToServer(text))
				{
					if (!defaultsSet)
					{
						SetPortalDefaults(__instance);
					}
					if (defaultsSet)
					{
						SetPortalColors(__instance, defaultColors: true);
					}
					return true;
				}
				if (defaultsSet)
				{
					SetPortalColors(__instance, defaultColors: false);
				}
				__result = true;
				return false;
			}
		}

		[HarmonyPatch(typeof(TeleportWorld), "Interact")]
		internal class PatchTeleportWorldInteract
		{
			private static bool Prefix(ref Humanoid human, ref bool hold, ref bool __result, TeleportWorld __instance)
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				if (hold)
				{
					__result = false;
					return false;
				}
				if (!PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, true, false))
				{
					((Character)human).Message((MessageType)2, "$piece_noaccess", 0, (Sprite)null);
					__result = true;
					return false;
				}
				TextInput.instance.RequestText((TextReceiver)(object)__instance, "$piece_portal_tag", 50);
				__result = true;
				return false;
			}
		}

		[HarmonyPatch(typeof(FejdStartup), "Start")]
		internal static class PatchFejdStartupStart
		{
			private static void Postfix()
			{
				//IL_015a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0164: Expected O, but got Unknown
				//IL_015f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0166: Expected O, but got Unknown
				MonoBehaviour.print((object)"Test");
				if (!ServerToJoin.HasValue || !TeleportingToServer || HasJoinedServer)
				{
					return;
				}
				string text = ServerToJoin?.Address;
				if (text.StartsWith("world:"))
				{
					string text2 = text.Substring(6);
					if (!(text2 != ""))
					{
						return;
					}
					List<World> worldList = SaveSystem.GetWorldList();
					foreach (World item in worldList)
					{
						if (item.m_name == text2)
						{
							PlayerPrefs.SetString("world", text2);
							FejdStartup.instance.OnStartGame();
							FejdStartup.instance.OnWorldStart();
							return;
						}
					}
					MonoBehaviour.print((object)("World does not exist " + text2));
				}
				else
				{
					ServerStatus serverToJoin = new ServerStatus((ServerJoinData)new ServerJoinDataDedicated($"{ServerToJoin?.Address}:{ServerToJoin?.Port}"));
					FejdStartup.instance.SetServerToJoin(serverToJoin);
					FejdStartup.instance.JoinServer();
				}
			}
		}

		[HarmonyPatch(typeof(FejdStartup), "ShowCharacterSelection")]
		internal class PatchFejdStartupShowCharacterSelection
		{
			private static void Postfix()
			{
				if (ServerToJoin.HasValue && TeleportingToServer && !HasJoinedServer)
				{
					HasJoinedServer = true;
					FejdStartup.instance.OnCharacterStart();
				}
			}
		}

		[HarmonyPatch(typeof(Game), "SpawnPlayer")]
		internal class PatchGameSpawnPlayer
		{
			private static void Prefix(ref Vector3 spawnPoint)
			{
				//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
				//IL_0103: Unknown result type (might be due to invalid IL or missing references)
				//IL_0105: Unknown result type (might be due to invalid IL or missing references)
				//IL_0107: Unknown result type (might be due to invalid IL or missing references)
				//IL_010c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0111: Unknown result type (might be due to invalid IL or missing references)
				//IL_0114: Unknown result type (might be due to invalid IL or missing references)
				//IL_0116: Unknown result type (might be due to invalid IL or missing references)
				//IL_011d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0122: Unknown result type (might be due to invalid IL or missing references)
				//IL_0127: Unknown result type (might be due to invalid IL or missing references)
				//IL_012c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0131: Unknown result type (might be due to invalid IL or missing references)
				if (TeleportingToServer && ServerToJoin.HasValue && ServerToJoin?.TargetTag != "")
				{
					List<ZDO> portals = ZDOMan.instance.GetPortals();
					foreach (ZDO item in portals)
					{
						if (item != null)
						{
							string @string = item.GetString(ZDOVars.s_tag, "");
							if (@string == ServerToJoin?.TargetTag || PortalTagToServerInfo(@string)?.SourceTag == ServerToJoin?.TargetTag)
							{
								Vector3 position = item.GetPosition();
								Quaternion rotation = item.GetRotation();
								Vector3 val = rotation * Vector3.forward;
								spawnPoint = position + val * PortalExitDistance + Vector3.up;
								break;
							}
						}
					}
				}
				TeleportingToServer = false;
				ServerToJoin = null;
			}
		}

		[HarmonyPatch(typeof(Game), "Start")]
		internal class PatchGameStart
		{
			private static void Postfix()
			{
				knownPortals.Clear();
				((MonoBehaviour)Game.instance).StartCoroutine(FetchPortals());
			}

			private static IEnumerator FetchPortals()
			{
				while (true)
				{
					List<ZDO> portals = ZDOMan.instance.GetPortals();
					if (ZNet.instance.IsServer())
					{
						foreach (ZDO zdo in portals.Except(knownPortals))
						{
							ZDOMan.instance.ForceSendZDO(zdo.m_uid);
						}
					}
					knownPortals = portals;
					yield return (object)new WaitForSeconds(10f);
				}
			}
		}

		[HarmonyPatch(typeof(ZDOMan), "AddPeer")]
		internal class PatchZDOManAddPeer
		{
			private static void Postfix(ZDOMan __instance, ZNetPeer netPeer)
			{
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				if (!ZNet.instance.IsServer())
				{
					return;
				}
				foreach (ZDO knownPortal in knownPortals)
				{
					__instance.ForceSendZDO(netPeer.m_uid, knownPortal.m_uid);
				}
			}
		}

		private static string PortalTagRegex = "^(?<SourceTag>[A-z0-9]+)\\|(?<Server>(world:)?[A-z0-9\\.]+):?(?<Port>[0-9]+)?\\|?(?<TargetTag>[A-z0-9]+)?$";

		public static ServerInfo? ServerToJoin = null;

		public static bool TeleportingToServer = false;

		public static bool HasJoinedServer = false;

		public static float PortalExitDistance = 0f;

		public static ConfigEntry<bool> preserveStatusEffects;

		public static ConfigEntry<bool> recolorPortalGlyphs;

		public static ConfigEntry<bool> recolorPortalEffects;

		public static ConfigEntry<Color> customPortalGlyphColor;

		public static ConfigEntry<Color> customPortalEffectColor;

		private static List<SEData> StatusEffects = new List<SEData>();

		public static List<ZDO> knownPortals = new List<ZDO>();

		public static readonly ManualLogSource Logger = Logger.CreateLogSource("CrossServerPortals");

		private static Color defaultColor = Color.white;

		private static MinMaxGradient defaultFlameColor1 = default(MinMaxGradient);

		private static MinMaxGradient defaultFlameColor2 = default(MinMaxGradient);

		private static Color defaultParticleColor = Color.white;

		private static Color defaultPortalSuckColor = Color.white;

		private static Color defaultLightColor = Color.white;

		private static bool defaultsSet = false;

		private readonly Harmony harmony = new Harmony("lunarbin.games.valheim");

		private static void SetPortalDefaults(TeleportWorld portal)
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			Transform val = ((Component)portal).transform.Find("_target_found_red");
			if (Object.op_Implicit((Object)(object)val))
			{
				Transform val2 = ((Component)val).transform.Find("Particle System");
				ParticleSystem component = ((Component)((Component)val2).transform.Find("blue flames")).GetComponent<ParticleSystem>();
				ParticleSystem component2 = ((Component)((Component)val2).transform.Find("Black_suck")).GetComponent<ParticleSystem>();
				ParticleSystem component3 = ((Component)((Component)val2).transform.Find("suck particles")).GetComponent<ParticleSystem>();
				Light component4 = ((Component)((Component)val).transform.Find("Point light")).GetComponent<Light>();
				if (defaultColor == Color.white && portal.m_colorTargetfound != customPortalGlyphColor.Value)
				{
					defaultColor = portal.m_colorTargetfound;
				}
				defaultColor = portal.m_colorTargetfound;
				CustomDataModule customData = component.customData;
				defaultFlameColor1 = ((CustomDataModule)(ref customData)).GetColor((ParticleSystemCustomData)0);
				customData = component.customData;
				defaultFlameColor2 = ((CustomDataModule)(ref customData)).GetColor((ParticleSystemCustomData)1);
				defaultPortalSuckColor = component2.startColor;
				defaultParticleColor = component3.startColor;
				defaultLightColor = component4.color;
				defaultsSet = true;
			}
		}

		private static void SetPortalColors(TeleportWorld portal, bool defaultColors)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			Transform val = ((Component)portal).transform.Find("_target_found_red");
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			Transform val2 = ((Component)val).transform.Find("Particle System");
			ParticleSystem component = ((Component)((Component)val2).transform.Find("blue flames")).GetComponent<ParticleSystem>();
			ParticleSystem component2 = ((Component)((Component)val2).transform.Find("Black_suck")).GetComponent<ParticleSystem>();
			ParticleSystem component3 = ((Component)((Component)val2).transform.Find("suck particles")).GetComponent<ParticleSystem>();
			Light component4 = ((Component)((Component)val).transform.Find("Point light")).GetComponent<Light>();
			CustomDataModule customData;
			if (!defaultsSet)
			{
				defaultColor = portal.m_colorTargetfound;
				customData = component.customData;
				defaultFlameColor1 = ((CustomDataModule)(ref customData)).GetColor((ParticleSystemCustomData)0);
				customData = component.customData;
				defaultFlameColor2 = ((CustomDataModule)(ref customData)).GetColor((ParticleSystemCustomData)1);
				defaultPortalSuckColor = component2.startColor;
				defaultParticleColor = component3.startColor;
				defaultLightColor = component4.color;
				defaultsSet = true;
			}
			if (recolorPortalGlyphs.Value && !defaultColors)
			{
				if (((Object)((Component)portal).gameObject).name == "portal_stone(Clone)")
				{
					portal.m_colorTargetfound = customPortalGlyphColor.Value * 12f;
				}
				else
				{
					portal.m_colorTargetfound = customPortalGlyphColor.Value * 4f;
				}
			}
			else
			{
				portal.m_colorTargetfound = defaultColor;
			}
			if (recolorPortalEffects.Value && !defaultColors)
			{
				customData = component.customData;
				((CustomDataModule)(ref customData)).SetColor((ParticleSystemCustomData)0, MinMaxGradient.op_Implicit(customPortalEffectColor.Value));
				customData = component.customData;
				((CustomDataModule)(ref customData)).SetColor((ParticleSystemCustomData)1, MinMaxGradient.op_Implicit(customPortalEffectColor.Value));
				Color value = customPortalEffectColor.Value;
				value *= 0.1f;
				value.a = 0.1f;
				component2.startColor = value;
				component3.startColor = customPortalEffectColor.Value;
				component4.color = customPortalEffectColor.Value;
			}
			else
			{
				customData = component.customData;
				((CustomDataModule)(ref customData)).SetColor((ParticleSystemCustomData)0, defaultFlameColor1);
				customData = component.customData;
				((CustomDataModule)(ref customData)).SetColor((ParticleSystemCustomData)1, defaultFlameColor2);
				component2.startColor = defaultPortalSuckColor;
				component3.startColor = defaultParticleColor;
				component4.color = defaultLightColor;
			}
		}

		private void Awake()
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			harmony.PatchAll();
			preserveStatusEffects = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "PreserveStatusEffects", true, "Preserve Status Effects while switching servers (such as rested, wet, etc.)");
			recolorPortalGlyphs = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RecolorPortalGlyphs", true, "Set to true to change the color of the glyphs for cross-server portals.");
			customPortalGlyphColor = ((BaseUnityPlugin)this).Config.Bind<Color>("General", "CustomPortalGlyphColor", new Color(0f, 1f, 0f, 1f), "Custom color for portal glyphs. (defaults to Green) *Note: Stone portal glyph colors behave strangely and favor red.");
			recolorPortalEffects = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RecolorPortalEffects", true, "Set to true to change the portal effects colors for cross-server portals.");
			customPortalEffectColor = ((BaseUnityPlugin)this).Config.Bind<Color>("General", "CustomPortalEffectColor", new Color(0f, 1f, 0f, 0.5f), "Custom color for portal effects. (defaults to Green)");
		}

		public static void TeleportToServer(string tag, TeleportWorld instance)
		{
			ServerToJoin = PortalTagToServerInfo(tag);
			if (ServerToJoin.HasValue)
			{
				if (preserveStatusEffects.Value)
				{
					foreach (StatusEffect statusEffect in ((Character)Player.m_localPlayer).GetSEMan().GetStatusEffects())
					{
						StatusEffects.Add(new SEData(statusEffect.NameHash(), statusEffect.m_ttl, (statusEffect.m_ttl > 0f) ? statusEffect.GetRemaningTime() : 0f));
					}
				}
				MovePlayerToPortalExit(ref Player.m_localPlayer, ref instance);
				Game.instance.IncrementPlayerStat((PlayerStatType)15, 1f);
				TeleportingToServer = true;
				HasJoinedServer = false;
				Game.instance.Logout(true, true);
			}
			else
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "Invalid portal tag: " + tag, 0, (Sprite)null);
			}
		}

		public static void MovePlayerToPortalExit(ref Player player, ref TeleportWorld portal)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)portal).transform.position;
			Quaternion rotation = ((Component)portal).transform.rotation;
			Vector3 val = rotation * Vector3.forward;
			Vector3 position2 = position + val * portal.m_exitDistance + Vector3.up;
			((Component)player).transform.position = position2;
			((Component)player).transform.rotation = rotation;
			PortalExitDistance = portal.m_exitDistance * 2f;
		}

		public static bool PortalTagIsToServer(string tag)
		{
			return Regex.IsMatch(tag, PortalTagRegex);
		}

		public static ServerInfo? PortalTagToServerInfo(string tag)
		{
			Match match = Regex.Match(tag, PortalTagRegex);
			if (match.Success)
			{
				return new ServerInfo(match.Groups["SourceTag"].Value, match.Groups["Server"].Value, ushort.Parse("0" + match.Groups["Port"].Value), match.Groups["TargetTag"].Value);
			}
			return null;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "ValheimCrossServerPortals";

		public const string PLUGIN_NAME = "ValheimCrossServerPortals";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}