Decompiled source of StonePortalCrossServer v1.0.1

StonePortalCrossServer.dll

Decompiled 2 years ago
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("StonePortalCrossServer")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("StonePortalCrossServer")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("8a380559-d783-444d-9d7b-e31893a0cc12")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Lunarbin.Valheim.CrossServerPortals;

[BepInPlugin("lunarbin.games.valheim", "Valheim Cross Server Portals", "0.1.0.0")]
public class CrossServerPortals : BaseUnityPlugin
{
	public struct ServerInfo
	{
		public string Address;

		public ushort Port;

		public string SourceTag;

		public string TargetTag;

		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;
		}
	}

	[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 Color defaultColor = Color.white;

		private static bool Prefix(ref bool __result, TeleportWorld __instance)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if (defaultColor == Color.white && __instance.m_colorTargetfound != Color.green)
			{
				defaultColor = __instance.m_colorTargetfound;
			}
			string text = __instance.GetText();
			if (!PortalTagIsToServer(text))
			{
				__instance.m_colorTargetfound = defaultColor;
				return true;
			}
			__instance.m_colorTargetfound = Color.green;
			__result = true;
			return false;
		}
	}

	[HarmonyPatch(typeof(TeleportWorld), "TargetFound")]
	internal class PatchTeleportWorldTargetFound
	{
		private static Color defaultColor = Color.white;

		private static bool Prefix(ref bool __result, TeleportWorld __instance)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if (defaultColor == Color.white && __instance.m_colorTargetfound != Color.green)
			{
				defaultColor = __instance.m_colorTargetfound;
			}
			string text = __instance.GetText();
			if (!PortalTagIsToServer(text))
			{
				__instance.m_colorTargetfound = defaultColor;
				return true;
			}
			__instance.m_colorTargetfound = Color.green;
			__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 class PatchFejdStartupStart
	{
		private static void Postfix()
		{
			if (ServerToJoin.HasValue && TeleportingToServer && !HasJoinedServer)
			{
				ZSteamMatchmaking.instance.QueueServerJoin($"{ServerToJoin?.Address}:{ServerToJoin?.Port}");
			}
		}
	}

	[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_010a: 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_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			if (TeleportingToServer && ServerToJoin.HasValue && ServerToJoin?.TargetTag != "")
			{
				List<ZDO> list = new List<ZDO>();
				int num = 0;
				ZDOMan.instance.GetAllZDOsWithPrefabIterative(portalPrefab, list, ref num);
				foreach (ZDO item in list)
				{
					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 = new List<ZDO>();
				int index = 0;
				while (!ZDOMan.instance.GetAllZDOsWithPrefabIterative(portalPrefab, portals, ref index))
				{
					yield return null;
				}
				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>[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 string portalPrefab = "stone_portal";

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

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

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

	private void Awake()
	{
		harmony.PatchAll();
	}

	public static void TeleportToServer(string tag, TeleportWorld instance)
	{
		ServerToJoin = PortalTagToServerInfo(tag);
		if (ServerToJoin.HasValue)
		{
			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(match.Groups["Port"].Value ?? "0"), match.Groups["TargetTag"].Value);
		}
		return null;
	}
}