Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of StonePortalCrossServer v1.0.1
StonePortalCrossServer.dll
Decompiled 2 years agousing 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; } }