using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using TMPro;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace PortalLimit.Client;
[BepInPlugin("keith.valheim.portallimit.client", "Portal Limit and Discovery Client", "0.1.4")]
public class PortalLimitClientPlugin : BaseUnityPlugin
{
[HarmonyPatch(typeof(Chat), "InputText")]
private static class ChatInputPatch
{
private static bool Prefix(Chat __instance)
{
string a = (((Object)(object)((Terminal)__instance).m_input != (Object)null) ? ((TMP_InputField)((Terminal)__instance).m_input).text : string.Empty);
if (string.Equals(a, "/portals", StringComparison.OrdinalIgnoreCase))
{
if ((Object)(object)Instance != (Object)null)
{
Instance.RequestCountForChat();
}
if ((Object)(object)((Terminal)__instance).m_input != (Object)null)
{
((TMP_InputField)((Terminal)__instance).m_input).text = string.Empty;
}
__instance.Hide();
return false;
}
if (!string.Equals(a, "/portallimit", StringComparison.OrdinalIgnoreCase))
{
return true;
}
if ((Object)(object)Instance != (Object)null)
{
Instance.ToggleAdminWindow();
}
if ((Object)(object)((Terminal)__instance).m_input != (Object)null)
{
((TMP_InputField)((Terminal)__instance).m_input).text = string.Empty;
}
__instance.Hide();
return false;
}
}
[HarmonyPatch(typeof(Player), "TryPlacePiece")]
private static class PlacePiecePatch
{
private static bool Prefix(Piece piece, ref bool __result)
{
if (!WouldExceedPortalLimit(piece))
{
return true;
}
__result = false;
Instance.ShowMessage("Portal limit reached: " + Instance.maxPortalsPerPlayer + " portal(s) per player.");
Instance.RequestCount();
return false;
}
private static void Postfix(Piece piece, bool __result)
{
if (__result && (Object)(object)Instance != (Object)null && (Object)(object)piece != (Object)null && Instance.IsLimitedPortal(piece))
{
Instance.ReportPortalMetadata(piece, "placed");
Instance.RequestPlacementCountSoon();
}
}
}
[HarmonyPatch(typeof(Piece), "CanBeRemoved")]
private static class PieceCanBeRemovedPatch
{
private static void Postfix(Piece __instance, ref bool __result)
{
if (__result && !((Object)(object)Instance == (Object)null) && !((Object)(object)__instance == (Object)null) && Instance.IsLimitedPortal(__instance))
{
long creator = __instance.GetCreator();
long localPlayerId = GetLocalPlayerId();
if (!Instance.isAdmin && creator != 0 && creator != localPlayerId)
{
__result = false;
Instance.ShowMessage("Only the builder or an admin can remove this portal.");
}
}
}
}
[HarmonyPatch(typeof(TeleportWorld), "Interact")]
private static class TeleportWorldInteractPatch
{
private static bool Prefix(TeleportWorld __instance, Humanoid human, bool hold, ref bool __result)
{
if ((Object)(object)Instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)human != (Object)(object)Player.m_localPlayer)
{
return true;
}
if (Instance.replayingVanillaPortalInteract)
{
return true;
}
if (Instance.isAdmin && Instance.adminHoldEToEdit && !hold)
{
Instance.BeginDelayedPortalInteract(__instance);
__result = false;
return false;
}
if (hold && Instance.isAdmin && Instance.adminHoldEToEdit)
{
Instance.OpenAdminWindowForPortal(__instance);
Instance.ResetHoldInteract();
__result = false;
return false;
}
if (!hold && ShouldBlockPortalUse(__instance))
{
__result = false;
return false;
}
return true;
}
}
[HarmonyPatch(typeof(TeleportWorld), "Teleport")]
private static class TeleportWorldTeleportPatch
{
private static bool Prefix(TeleportWorld __instance, Player player)
{
if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer)
{
return true;
}
bool flag = !ShouldBlockBlankPortalUse(__instance) && !ShouldBlockPortalUse(__instance);
if (flag && (Object)(object)Instance != (Object)null)
{
Instance.ReportPortalMetadata(__instance, "used");
}
return flag;
}
}
[HarmonyPatch(typeof(TeleportWorld), "GetHoverText")]
private static class TeleportWorldHoverTextPatch
{
private static void Postfix(TeleportWorld __instance, ref string __result)
{
if ((Object)(object)Instance == (Object)null)
{
return;
}
if (string.IsNullOrWhiteSpace(GetPortalTag(__instance)) && !string.IsNullOrEmpty(__result))
{
__result = __result.Replace(" [CONNECTED]", string.Empty).Replace("[CONNECTED]", string.Empty);
}
if (Instance.isAdmin)
{
if (Instance.adminHoldEToEdit)
{
__result += "\nHold E: Portal Limit settings";
}
string portalCreatorName = GetPortalCreatorName(__instance);
if (!string.IsNullOrWhiteSpace(portalCreatorName))
{
__result = __result + "\nBuilt by: " + portalCreatorName + "";
}
}
if (!Instance.discoveryEnabled || (!Instance.showDiscoveryHoverText && !Instance.isAdmin))
{
return;
}
int discoveryRole = GetDiscoveryRole(__instance);
if (discoveryRole == 0)
{
return;
}
string discoveryLink = GetDiscoveryLink(__instance);
if (string.IsNullOrWhiteSpace(discoveryLink))
{
return;
}
string text = string.Empty;
if (Instance.IsDiscoveryUnlocked(discoveryLink))
{
text = GetDiscoveryHoverOverride(__instance, "PortalLimit_DiscoveryUnlockedHoverText");
if (string.IsNullOrWhiteSpace(text))
{
text = Instance.discoveryUnlockedHoverText;
}
}
else
{
switch (discoveryRole)
{
case 1:
text = GetDiscoveryHoverOverride(__instance, "PortalLimit_DiscoveryLockedHoverText");
if (string.IsNullOrWhiteSpace(text))
{
text = Instance.discoveryLockedHoverText;
}
break;
case 2:
text = GetDiscoveryHoverOverride(__instance, "PortalLimit_DiscoveryRemoteHoverText");
if (string.IsNullOrWhiteSpace(text))
{
text = Instance.discoveryRemoteHoverText;
}
break;
}
}
if (!string.IsNullOrWhiteSpace(text))
{
__result = __result + "\n" + text + "";
}
}
}
[HarmonyPatch(typeof(TeleportWorld), "TargetFound")]
private static class TeleportWorldTargetFoundPatch
{
private static void Postfix(TeleportWorld __instance, ref bool __result)
{
if ((Object)(object)__instance != (Object)null && string.IsNullOrWhiteSpace(GetPortalTag(__instance)))
{
__result = false;
SetTargetFound(__instance, value: false);
}
}
}
[HarmonyPatch(typeof(TeleportWorld), "HaveTarget")]
private static class TeleportWorldHaveTargetPatch
{
private static void Postfix(TeleportWorld __instance, ref bool __result)
{
if ((Object)(object)__instance != (Object)null && string.IsNullOrWhiteSpace(GetPortalTag(__instance)))
{
__result = false;
}
}
}
[HarmonyPatch(typeof(TeleportWorld), "Update")]
private static class TeleportWorldVisualPatch
{
private static void Postfix(TeleportWorld __instance)
{
if (!((Object)(object)__instance == (Object)null))
{
PortalLimitDiscoveryVisual portalLimitDiscoveryVisual = ((Component)__instance).GetComponent();
if ((Object)(object)portalLimitDiscoveryVisual == (Object)null)
{
portalLimitDiscoveryVisual = ((Component)__instance).gameObject.AddComponent();
}
portalLimitDiscoveryVisual.Refresh(__instance);
}
}
}
private class PortalLimitDiscoveryVisual : MonoBehaviour
{
private GameObject markerRoot;
private TextMesh markerText;
private Renderer[] portalRenderers;
private ParticleSystem[] portalParticles;
private Light[] portalLights;
private readonly Dictionary originalColors = new Dictionary();
private readonly Dictionary originalParticleStates = new Dictionary();
private readonly Dictionary originalLightStates = new Dictionary();
internal void Refresh(TeleportWorld portal)
{
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: 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_0092: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)Instance == (Object)null) && !((Object)(object)portal == (Object)null))
{
bool flag = Instance.ShouldShowDiscoveryWorldMarker(portal);
bool enabled = Instance.ShouldTintDiscoveryPortal(portal);
bool suppress = Instance.ShouldSuppressLockedPortalGlow(portal);
Color discoveryVisualColor = Instance.GetDiscoveryVisualColor(portal);
EnsureMarker();
markerRoot.SetActive(flag);
if (flag)
{
SetMarkerWorldPose(portal);
SetMarkerText(Instance.GetDiscoveryMarkerDisplayText(portal));
SetMarkerColor(discoveryVisualColor);
}
UpdatePortalTint(enabled, discoveryVisualColor);
UpdatePortalEffects(suppress);
}
}
private void EnsureMarker()
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Expected O, but got Unknown
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)markerRoot != (Object)null))
{
markerRoot = new GameObject("PortalLimit_DiscoveryMarker");
markerRoot.transform.SetParent(((Component)this).transform, false);
markerRoot.transform.localPosition = new Vector3(0f, 1.55f, 0f);
markerRoot.transform.localRotation = Quaternion.identity;
markerRoot.transform.localScale = Vector3.one;
markerText = markerRoot.AddComponent();
markerText.text = "UNLOCK ON OTHER SIDE";
markerText.anchor = (TextAnchor)4;
markerText.alignment = (TextAlignment)1;
markerText.fontSize = 96;
markerText.characterSize = 0.01f;
markerText.richText = false;
SetMarkerColor(LockedOrange);
markerRoot.SetActive(false);
}
}
private void SetMarkerText(string text)
{
if (!((Object)(object)markerText == (Object)null))
{
markerText.text = text;
if (string.Equals(text, "X", StringComparison.Ordinal))
{
markerText.fontSize = 128;
markerText.characterSize = 0.03f;
}
else if (string.Equals(text, "LOCKED", StringComparison.Ordinal))
{
markerText.fontSize = 96;
markerText.characterSize = 0.018f;
}
else
{
markerText.fontSize = 96;
markerText.characterSize = 0.01f;
}
}
}
private void SetMarkerColor(Color color)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)markerText != (Object)null)
{
markerText.color = color;
}
}
private void SetMarkerWorldPose(TeleportWorld portal)
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: 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_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)markerRoot == (Object)null || (Object)(object)portal == (Object)null)
{
return;
}
Vector3 val = ((Component)portal).transform.position + Vector3.up * 1.55f;
if ((Object)(object)Camera.main != (Object)null)
{
Vector3 val2 = ((Component)Camera.main).transform.position - val;
if (((Vector3)(ref val2)).sqrMagnitude > 0.001f)
{
markerRoot.transform.position = val + ((Vector3)(ref val2)).normalized * 0.45f;
markerRoot.transform.rotation = Quaternion.LookRotation(-((Vector3)(ref val2)).normalized, Vector3.up);
return;
}
}
markerRoot.transform.position = val;
markerRoot.transform.rotation = ((Component)portal).transform.rotation;
}
private void UpdatePortalTint(bool enabled, Color color)
{
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: 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_00e9: 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)
if (portalRenderers == null)
{
portalRenderers = ((Component)this).GetComponentsInChildren(true);
}
Renderer[] array = portalRenderers;
foreach (Renderer val in array)
{
if (!((Object)(object)val == (Object)null) && !((Component)val).transform.IsChildOf(markerRoot.transform))
{
if (!originalColors.ContainsKey(val))
{
originalColors[val] = (val.material.HasProperty("_Color") ? val.material.color : Color.white);
}
if (val.material.HasProperty("_Color"))
{
val.material.color = (enabled ? Color.Lerp(originalColors[val], color, 0.45f) : originalColors[val]);
}
}
}
}
private void UpdatePortalEffects(bool suppress)
{
ParticleSystem[] array;
if (portalParticles == null)
{
portalParticles = ((Component)this).GetComponentsInChildren(true);
array = portalParticles;
foreach (ParticleSystem val in array)
{
if ((Object)(object)val != (Object)null)
{
originalParticleStates[val] = ((Component)val).gameObject.activeSelf;
}
}
}
Light[] array2;
if (portalLights == null)
{
portalLights = ((Component)this).GetComponentsInChildren(true);
array2 = portalLights;
foreach (Light val2 in array2)
{
if ((Object)(object)val2 != (Object)null)
{
originalLightStates[val2] = ((Behaviour)val2).enabled;
}
}
}
array = portalParticles;
foreach (ParticleSystem val in array)
{
if (!((Object)(object)val == (Object)null) && !((Component)val).transform.IsChildOf(markerRoot.transform))
{
if (!originalParticleStates.TryGetValue(val, out var value))
{
value = true;
}
((Component)val).gameObject.SetActive(!suppress && value);
if (!suppress && value && !val.isPlaying)
{
val.Play(true);
}
}
}
array2 = portalLights;
foreach (Light val2 in array2)
{
if (!((Object)(object)val2 == (Object)null) && !((Component)val2).transform.IsChildOf(markerRoot.transform))
{
if (!originalLightStates.TryGetValue(val2, out var value2))
{
value2 = true;
}
((Behaviour)val2).enabled = !suppress && value2;
}
}
}
}
public const string PluginGuid = "keith.valheim.portallimit.client";
public const string PluginName = "Portal Limit and Discovery Client";
public const string PluginVersion = "0.1.4";
private const string RpcConfigRequest = "keith.valheim.portallimit.config_request";
private const string RpcConfigResponse = "keith.valheim.portallimit.config_response";
private const string RpcConfigUpdate = "keith.valheim.portallimit.config_update";
private const string RpcCountRequest = "keith.valheim.portallimit.count_request";
private const string RpcCountResponse = "keith.valheim.portallimit.count_response";
private const string RpcNotice = "keith.valheim.portallimit.notice";
private const string RpcDiscoveryMarkRequest = "keith.valheim.portallimit.discovery_mark_request";
private const string RpcDiscoveryUnlockRequest = "keith.valheim.portallimit.discovery_unlock_request";
private const string RpcDiscoveryRelockRequest = "keith.valheim.portallimit.discovery_relock_request";
private const string RpcDiscoveryUnlockListRequest = "keith.valheim.portallimit.discovery_unlock_list_request";
private const string RpcDiscoveryUnlockListResponse = "keith.valheim.portallimit.discovery_unlock_list_response";
private const string RpcAdminReportRequest = "keith.valheim.portallimit.admin_report_request";
private const string RpcAdminReportResponse = "keith.valheim.portallimit.admin_report_response";
private const string RpcPortalMetadataUpdate = "keith.valheim.portallimit.portal_metadata_update";
private const string DiscoveryRoleKey = "PortalLimit_DiscoveryRole";
private const string DiscoveryLinkKey = "PortalLimit_DiscoveryLink";
private const string DiscoveryColorKey = "PortalLimit_DiscoveryColor";
private const string DiscoveryMarkerTextKey = "PortalLimit_DiscoveryMarkerText";
private const string DiscoveryShowMarkerKey = "PortalLimit_DiscoveryShowMarker";
private const string DiscoverySuppressGlowKey = "PortalLimit_DiscoverySuppressGlow";
private const string DiscoveryLockedHoverTextKey = "PortalLimit_DiscoveryLockedHoverText";
private const string DiscoveryRemoteHoverTextKey = "PortalLimit_DiscoveryRemoteHoverText";
private const string DiscoveryUnlockedHoverTextKey = "PortalLimit_DiscoveryUnlockedHoverText";
private const string PortalBuiltUtcKey = "PortalLimit_BuiltUtc";
private const int DiscoveryRoleNone = 0;
private const int DiscoveryRoleLocked = 1;
private const int DiscoveryRoleRemote = 2;
internal static PortalLimitClientPlugin Instance;
internal static ManualLogSource Log;
private static readonly FieldInfo AllPiecesField = AccessTools.Field(typeof(Piece), "s_allPieces");
private static readonly FieldInfo TeleportWorldTargetFoundField = AccessTools.Field(typeof(TeleportWorld), "m_target_found");
private static readonly MethodInfo GetPlayerIdMethod = AccessTools.Method(typeof(Player), "GetPlayerID", (Type[])null, (Type[])null);
private static readonly MethodInfo GetPrefabNameMethod = AccessTools.Method(typeof(ZNetView), "GetPrefabName", (Type[])null, (Type[])null);
private static readonly Color LockedOrange = new Color(1f, 0.6235294f, 0.1019608f, 1f);
private static readonly string[] MarkerColorLabels = new string[8] { "RED", "ORANGE", "YELLOW", "GREEN", "BLUE", "PURPLE", "WHITE", "BLACK" };
private static readonly string[] MarkerColorValues = new string[8] { "#ff3030", "#ff9f1a", "#ffd84a", "#42ff68", "#38a6ff", "#b05cff", "#ffffff", "#000000" };
private static readonly string[] PortalRoleChoiceLabels = new string[3] { "NORMAL PORTAL", "LOCKED ENTRANCE", "UNLOCKED ENTRANCE" };
private static readonly string[] MarkerTextLabels = new string[3] { "UNLOCK ON OTHER SIDE", "LOCKED", "X" };
private static readonly string[] MarkerTextValues = new string[3] { "UnlockOnOtherSide", "Locked", "X" };
private Harmony harmony;
private bool rpcRegistered;
private bool configRequested;
private bool showCountMessageOnNextResponse;
private bool showPlacementCountOnNextResponse;
private bool openAdminUiAfterPermissionCheck;
private bool adminStatusKnown;
private bool isAdmin;
private bool adminBypass = true;
private bool enforceOnServer = true;
private int maxPortalsPerPlayer = 10;
private string portalPrefabNames = "portal_wood,portal_stone";
private bool discoveryEnabled = true;
private bool discoveryAdminBypass = true;
private bool adminHoldEToEdit = true;
private bool showDiscoveryHoverText = true;
private string discoveryLockedHoverText = "Locked: find the other end first.";
private string discoveryRemoteHoverText = "Discovery portal: use this side to unlock the route.";
private string discoveryUnlockedHoverText = "Discovery route unlocked.";
private string discoveryLockedMessage = "This portal is locked. Find and enter the other end first.";
private string discoveryUnlockMessage = "Discovery portal unlocked.";
private bool discoveryShowWorldMarker = true;
private bool discoveryTintPortalModel;
private bool discoverySuppressLockedGlow;
private string discoveryLockedColor = "#ff9f1a";
private string discoveryRemoteColor = "#38a6ff";
private string discoveryUnlockedColor = "#42ff68";
private readonly HashSet unlockedDiscoveryLinks = new HashSet(StringComparer.OrdinalIgnoreCase);
private int serverPortalCount;
private Rect adminWindow = new Rect(120f, 60f, 700f, 720f);
private Vector2 adminScroll;
private Vector2 portalInfoThisScroll;
private Vector2 portalInfoWorldScroll;
private bool showAdminWindow;
private int adminTab;
private string openDropdown = string.Empty;
private bool portalInfoShowThis;
private bool portalInfoShowWorld;
private string portalInfoThisText = "Open this tab while editing a portal.";
private string portalInfoWorldText = "Click Refresh to load world portal information.";
private string portalInfoRequestedPortalKey = string.Empty;
private int selectedPortalRole;
private string loadedPortalKey = string.Empty;
private TeleportWorld selectedPortal;
private string maxText = "10";
private string portalNamesText = "portal_wood,portal_stone";
private string discoveryLinkText = string.Empty;
private string selectedPortalColorText = "#ff9f1a";
private int selectedPortalColorIndex;
private string selectedPortalMarkerText = "UNLOCK ON OTHER SIDE";
private bool selectedPortalShowMarker = true;
private bool selectedPortalSuppressGlow;
private string selectedLockedHoverText = string.Empty;
private string selectedRemoteHoverText = string.Empty;
private string selectedUnlockedHoverText = string.Empty;
private string discoveryLockedHoverTextField = "Locked: find the other end first.";
private string discoveryRemoteHoverTextField = "Discovery portal: use this side to unlock the route.";
private string discoveryUnlockedHoverTextField = "Discovery route unlocked.";
private string discoveryLockedMessageField = "This portal is locked. Find and enter the other end first.";
private string discoveryUnlockMessageField = "Discovery portal unlocked.";
private int selectedPortalMarkerTextIndex;
private TeleportWorld holdInteractPortal;
private float holdInteractStartedAt;
private bool holdInteractOpened;
private bool replayingVanillaPortalInteract;
private string discoveryLockedColorField = "#ff9f1a";
private string discoveryRemoteColorField = "#38a6ff";
private string discoveryUnlockedColorField = "#42ff68";
private string statusMessage = "Use /portallimit to load server settings.";
private bool adminStylesReady;
private Texture2D adminWindowTexture;
private Texture2D adminHeaderTexture;
private Texture2D adminSectionTexture;
private Texture2D adminInputTexture;
private Texture2D adminButtonTexture;
private Texture2D adminButtonHoverTexture;
private Texture2D adminTabTexture;
private Texture2D adminTabSelectedTexture;
private GUIStyle adminWindowStyle;
private GUIStyle adminTitleStyle;
private GUIStyle adminLabelStyle;
private GUIStyle adminHelpStyle;
private GUIStyle adminSectionStyle;
private GUIStyle adminButtonStyle;
private GUIStyle adminTabStyle;
private GUIStyle adminTabSelectedStyle;
private GUIStyle adminTextFieldStyle;
private GUIStyle adminBoxStyle;
private ConfigEntry toggleAdminUiKey;
private void Awake()
{
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Expected O, but got Unknown
if (IsDedicatedServerProcess())
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"Portal Limit Client disabled on the dedicated server process.");
((Behaviour)this).enabled = false;
return;
}
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
toggleAdminUiKey = ((BaseUnityPlugin)this).Config.Bind("Input", "ToggleAdminUIKey", (KeyCode)291, "Key used to open the portal limit admin UI.");
harmony = new Harmony("keith.valheim.portallimit.client");
harmony.PatchAll();
RegisterConsoleCommands();
((MonoBehaviour)this).InvokeRepeating("TryRegisterRpcs", 1f, 1f);
}
private void OnDestroy()
{
if (harmony != null)
{
harmony.UnpatchSelf();
}
DestroyAdminTexture(adminWindowTexture);
DestroyAdminTexture(adminHeaderTexture);
DestroyAdminTexture(adminSectionTexture);
DestroyAdminTexture(adminInputTexture);
DestroyAdminTexture(adminButtonTexture);
DestroyAdminTexture(adminButtonHoverTexture);
DestroyAdminTexture(adminTabTexture);
DestroyAdminTexture(adminTabSelectedTexture);
}
private static bool IsDedicatedServerProcess()
{
string processName = Process.GetCurrentProcess().ProcessName;
return processName.StartsWith("valheim_server", StringComparison.OrdinalIgnoreCase);
}
private void TryRegisterRpcs()
{
if (!rpcRegistered && ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.Register("keith.valheim.portallimit.config_response", (Action)OnConfigResponse);
ZRoutedRpc.instance.Register("keith.valheim.portallimit.count_response", (Method)OnCountResponse);
ZRoutedRpc.instance.Register("keith.valheim.portallimit.notice", (Action)OnNotice);
ZRoutedRpc.instance.Register("keith.valheim.portallimit.discovery_unlock_list_response", (Action)OnDiscoveryUnlockListResponse);
ZRoutedRpc.instance.Register("keith.valheim.portallimit.admin_report_response", (Action)OnAdminReportResponse);
rpcRegistered = true;
((MonoBehaviour)this).CancelInvoke("TryRegisterRpcs");
}
}
private static void RegisterConsoleCommands()
{
//IL_0012: 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)
new ConsoleCommand("portallimit", "Portal Limit commands. Use: portallimit, portallimit count, portallimit counts, portallimit portals, portallimit export", new ConsoleEvent(OnConsolePortalLimit), false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
}
private static void OnConsolePortalLimit(ConsoleEventArgs args)
{
if ((Object)(object)Instance == (Object)null)
{
Terminal.Log((object)"Portal Limit client is not ready.");
return;
}
string text = ((args.Length > 1) ? args[1].ToLowerInvariant() : "help");
if (text == "help")
{
Terminal.Log((object)"Portal Limit F5 commands:");
Terminal.Log((object)" portallimit count - show your portal count");
Terminal.Log((object)" portallimit counts - admin: show counts for all players");
Terminal.Log((object)" portallimit portals - admin: list known portals with names and coordinates");
Terminal.Log((object)" portallimit export - admin: rewrite report files on the server");
Terminal.Log((object)"Regular players can also type /portals in normal chat.");
}
else if (text == "count")
{
Instance.showCountMessageOnNextResponse = true;
Instance.RequestCount();
Terminal.Log((object)"Portal Limit: checking your portal count...");
}
else if (text != "counts" && text != "portals" && text != "export")
{
Terminal.Log((object)"Unknown Portal Limit command. Use: portallimit");
}
else if (ZRoutedRpc.instance == null)
{
Terminal.Log((object)"Portal Limit server RPC is not ready yet.");
}
else
{
ZRoutedRpc.instance.InvokeRoutedRPC("keith.valheim.portallimit.admin_report_request", new object[1] { text });
Terminal.Log((object)("Portal Limit: requesting " + text + " report..."));
}
}
private void Update()
{
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
if (rpcRegistered && !((Object)(object)ZNet.instance == (Object)null))
{
if (!configRequested && (Object)(object)Player.m_localPlayer != (Object)null)
{
RequestConfig(openUi: false);
}
if (Input.GetKeyDown(toggleAdminUiKey.Value))
{
ToggleAdminWindow();
}
UpdateHoldInteractAdminOpen();
}
}
private void UpdateHoldInteractAdminOpen()
{
if (!isAdmin || !adminHoldEToEdit || showAdminWindow || (Object)(object)Player.m_localPlayer == (Object)null)
{
ResetHoldInteract();
}
else if ((Object)(object)holdInteractPortal == (Object)null)
{
TeleportWorld hoveredPortal = GetHoveredPortal();
if ((Object)(object)hoveredPortal != (Object)null && Input.GetKey((KeyCode)101))
{
BeginDelayedPortalInteract(hoveredPortal);
}
}
else if (!Input.GetKey((KeyCode)101))
{
TeleportWorld val = holdInteractPortal;
bool flag = !holdInteractOpened && Time.unscaledTime - holdInteractStartedAt < 0.45f;
ResetHoldInteract();
if (flag && (Object)(object)val != (Object)null)
{
ReplayVanillaPortalInteract(val);
}
}
else if (!holdInteractOpened && Time.unscaledTime - holdInteractStartedAt >= 0.45f)
{
holdInteractOpened = true;
OpenAdminWindowForPortal(holdInteractPortal);
}
}
private void BeginDelayedPortalInteract(TeleportWorld portal)
{
holdInteractPortal = portal;
holdInteractStartedAt = Time.unscaledTime;
holdInteractOpened = false;
}
private void ResetHoldInteract()
{
holdInteractPortal = null;
holdInteractStartedAt = 0f;
holdInteractOpened = false;
}
private void ReplayVanillaPortalInteract(TeleportWorld portal)
{
if ((Object)(object)portal == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
{
return;
}
replayingVanillaPortalInteract = true;
try
{
portal.Interact((Humanoid)(object)Player.m_localPlayer, false, false);
}
finally
{
replayingVanillaPortalInteract = false;
}
}
private void OnGUI()
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Expected O, but got Unknown
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
if (showAdminWindow)
{
EnsureAdminStyles();
CenterAdminWindowIfNeeded();
adminWindow = GUI.Window(((Object)this).GetInstanceID(), adminWindow, new WindowFunction(DrawAdminWindow), GUIContent.none, GUIStyle.none);
}
}
private void CenterAdminWindowIfNeeded()
{
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
float num = Mathf.Min(760f, (float)Screen.width - 40f);
float num2 = Mathf.Min(680f, (float)Screen.height - 40f);
if (Math.Abs(((Rect)(ref adminWindow)).width - num) > 0.1f || Math.Abs(((Rect)(ref adminWindow)).height - num2) > 0.1f)
{
adminWindow = new Rect(((float)Screen.width - num) * 0.5f, ((float)Screen.height - num2) * 0.5f, num, num2);
}
}
private void DrawAdminWindow(int id)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
//IL_0162: Unknown result type (might be due to invalid IL or missing references)
//IL_0192: Unknown result type (might be due to invalid IL or missing references)
//IL_0197: Unknown result type (might be due to invalid IL or missing references)
//IL_026d: Unknown result type (might be due to invalid IL or missing references)
EnsureAdminStyles();
GUI.Box(new Rect(0f, 0f, ((Rect)(ref adminWindow)).width, ((Rect)(ref adminWindow)).height), GUIContent.none, adminWindowStyle);
GUI.Box(new Rect(0f, 0f, ((Rect)(ref adminWindow)).width, 42f), GUIContent.none, adminSectionStyle);
GUI.Label(new Rect(18f, 9f, ((Rect)(ref adminWindow)).width - 36f, 28f), "Portal Limit Admin", adminTitleStyle);
if (GUI.Button(new Rect(((Rect)(ref adminWindow)).width - 38f, 8f, 28f, 26f), "X", adminButtonStyle))
{
showAdminWindow = false;
return;
}
GUILayout.BeginArea(new Rect(16f, 48f, ((Rect)(ref adminWindow)).width - 32f, ((Rect)(ref adminWindow)).height - 62f));
GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[0]);
GUILayout.Label(statusMessage, adminHelpStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
if (isAdmin)
{
DrawAdminTabs();
adminScroll = GUILayout.BeginScrollView(adminScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(Math.Max(220f, ((Rect)(ref adminWindow)).height - 145f)) });
if (adminTab == 0)
{
DrawServerSettingsTab();
}
else if (adminTab == 1)
{
DrawPortalSettingsTab();
}
else
{
DrawPortalInformationTab();
}
GUILayout.EndScrollView();
if (adminTab == 2)
{
DrawInformationFooter();
}
else
{
DrawAdminFooter();
}
}
else
{
GUILayout.Label("You need to be on the Valheim admin list to edit this.", adminLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
if (GUILayout.Button("Close", adminButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]))
{
showAdminWindow = false;
}
}
GUILayout.EndVertical();
GUILayout.EndArea();
GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref adminWindow)).width, 42f));
}
private void EnsureAdminStyles()
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: 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_013e: Unknown result type (might be due to invalid IL or missing references)
//IL_0158: Unknown result type (might be due to invalid IL or missing references)
//IL_0162: Expected O, but got Unknown
//IL_0183: Unknown result type (might be due to invalid IL or missing references)
//IL_018d: Expected O, but got Unknown
//IL_019c: Unknown result type (might be due to invalid IL or missing references)
//IL_01a6: Expected O, but got Unknown
//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
//IL_01bc: Expected O, but got Unknown
//IL_0203: Unknown result type (might be due to invalid IL or missing references)
//IL_0219: Unknown result type (might be due to invalid IL or missing references)
//IL_0223: Expected O, but got Unknown
//IL_025d: Unknown result type (might be due to invalid IL or missing references)
//IL_026f: Unknown result type (might be due to invalid IL or missing references)
//IL_0279: Expected O, but got Unknown
//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
//IL_02c6: Expected O, but got Unknown
//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
//IL_02f1: Expected O, but got Unknown
//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0306: Expected O, but got Unknown
//IL_0326: Unknown result type (might be due to invalid IL or missing references)
//IL_0364: Unknown result type (might be due to invalid IL or missing references)
//IL_036e: Expected O, but got Unknown
//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0412: Unknown result type (might be due to invalid IL or missing references)
//IL_0435: Unknown result type (might be due to invalid IL or missing references)
//IL_043f: Expected O, but got Unknown
//IL_044a: Unknown result type (might be due to invalid IL or missing references)
//IL_0454: Expected O, but got Unknown
//IL_045c: Unknown result type (might be due to invalid IL or missing references)
//IL_0466: Expected O, but got Unknown
//IL_0491: Unknown result type (might be due to invalid IL or missing references)
//IL_049b: Expected O, but got Unknown
//IL_04bd: Unknown result type (might be due to invalid IL or missing references)
//IL_04e0: Unknown result type (might be due to invalid IL or missing references)
//IL_04ea: Expected O, but got Unknown
//IL_0539: Unknown result type (might be due to invalid IL or missing references)
//IL_0543: Expected O, but got Unknown
//IL_0563: Unknown result type (might be due to invalid IL or missing references)
//IL_0579: Unknown result type (might be due to invalid IL or missing references)
//IL_059e: Unknown result type (might be due to invalid IL or missing references)
//IL_05a8: Expected O, but got Unknown
//IL_05b4: Unknown result type (might be due to invalid IL or missing references)
//IL_05be: Expected O, but got Unknown
//IL_05ca: Unknown result type (might be due to invalid IL or missing references)
//IL_05d4: Expected O, but got Unknown
//IL_05f5: Unknown result type (might be due to invalid IL or missing references)
//IL_05ff: Expected O, but got Unknown
//IL_060a: Unknown result type (might be due to invalid IL or missing references)
//IL_0614: Expected O, but got Unknown
if (!adminStylesReady)
{
adminWindowTexture = MakeAdminTexture(new Color(0.03f, 0.026f, 0.022f, 0.98f));
adminHeaderTexture = MakeAdminTexture(new Color(0.18f, 0.115f, 0.065f, 0.98f));
adminSectionTexture = MakeAdminTexture(new Color(0.13f, 0.085f, 0.052f, 0.96f));
adminInputTexture = MakeAdminBorderTexture(new Color(0.12f, 0.105f, 0.08f, 1f), new Color(1f, 0.78f, 0.26f, 1f));
adminButtonTexture = MakeAdminTexture(new Color(0.25f, 0.24f, 0.21f, 0.98f));
adminButtonHoverTexture = MakeAdminTexture(new Color(0.36f, 0.31f, 0.23f, 0.98f));
adminTabTexture = MakeAdminTexture(new Color(0.16f, 0.14f, 0.12f, 0.98f));
adminTabSelectedTexture = MakeAdminTexture(new Color(0.45f, 0.31f, 0.14f, 0.98f));
adminWindowStyle = new GUIStyle(GUI.skin.box);
adminWindowStyle.normal.background = adminWindowTexture;
adminWindowStyle.border = new RectOffset(8, 8, 8, 8);
adminWindowStyle.padding = new RectOffset(14, 14, 14, 14);
adminTitleStyle = new GUIStyle(GUI.skin.label);
adminTitleStyle.fontSize = 18;
adminTitleStyle.fontStyle = (FontStyle)1;
adminTitleStyle.alignment = (TextAnchor)4;
adminTitleStyle.normal.textColor = new Color(0.95f, 0.83f, 0.55f, 1f);
adminLabelStyle = new GUIStyle(GUI.skin.label);
adminLabelStyle.fontSize = 14;
adminLabelStyle.wordWrap = true;
adminLabelStyle.normal.textColor = new Color(0.88f, 0.84f, 0.74f, 1f);
adminHelpStyle = new GUIStyle(adminLabelStyle);
adminHelpStyle.fontSize = 13;
adminHelpStyle.normal.textColor = new Color(0.67f, 0.64f, 0.56f, 1f);
adminSectionStyle = new GUIStyle(GUI.skin.box);
adminSectionStyle.normal.background = adminSectionTexture;
adminSectionStyle.border = new RectOffset(4, 4, 4, 4);
adminSectionStyle.padding = new RectOffset(8, 8, 4, 4);
adminSectionStyle.normal.textColor = new Color(0.98f, 0.82f, 0.43f, 1f);
adminSectionStyle.alignment = (TextAnchor)3;
adminSectionStyle.fontStyle = (FontStyle)1;
adminSectionStyle.fontSize = 15;
adminButtonStyle = new GUIStyle(GUI.skin.button);
adminButtonStyle.normal.background = adminButtonTexture;
adminButtonStyle.hover.background = adminButtonHoverTexture;
adminButtonStyle.active.background = adminTabSelectedTexture;
adminButtonStyle.normal.textColor = new Color(0.9f, 0.86f, 0.76f, 1f);
adminButtonStyle.hover.textColor = new Color(1f, 0.9f, 0.58f, 1f);
adminButtonStyle.active.textColor = Color.white;
adminButtonStyle.fontSize = 13;
adminButtonStyle.padding = new RectOffset(8, 8, 5, 5);
adminButtonStyle.margin = new RectOffset(3, 3, 3, 3);
adminTabStyle = new GUIStyle(adminButtonStyle);
adminTabStyle.normal.background = adminTabTexture;
adminTabStyle.fontStyle = (FontStyle)1;
adminTabSelectedStyle = new GUIStyle(adminButtonStyle);
adminTabSelectedStyle.normal.background = adminTabSelectedTexture;
adminTabSelectedStyle.normal.textColor = Color.white;
adminTabSelectedStyle.fontStyle = (FontStyle)1;
adminTextFieldStyle = new GUIStyle(GUI.skin.textField);
adminTextFieldStyle.normal.background = adminInputTexture;
adminTextFieldStyle.focused.background = adminInputTexture;
adminTextFieldStyle.hover.background = adminInputTexture;
adminTextFieldStyle.border = new RectOffset(4, 4, 4, 4);
adminTextFieldStyle.normal.textColor = new Color(1f, 0.98f, 0.86f, 1f);
adminTextFieldStyle.focused.textColor = Color.white;
adminTextFieldStyle.fontSize = 15;
adminTextFieldStyle.padding = new RectOffset(12, 12, 8, 8);
adminTextFieldStyle.margin = new RectOffset(3, 3, 5, 10);
adminBoxStyle = new GUIStyle(GUI.skin.box);
adminBoxStyle.normal.background = adminHeaderTexture;
adminBoxStyle.padding = new RectOffset(6, 6, 6, 6);
adminBoxStyle.margin = new RectOffset(0, 0, 2, 8);
adminStylesReady = true;
}
}
private static Texture2D MakeAdminTexture(Color color)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Expected O, but got Unknown
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false);
val.SetPixel(0, 0, color);
val.Apply();
return val;
}
private static Texture2D MakeAdminBorderTexture(Color fill, Color border)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Expected O, but got Unknown
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
Texture2D val = new Texture2D(16, 16, (TextureFormat)4, false);
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 16; j++)
{
bool flag = j < 2 || i < 2 || j > 13 || i > 13;
val.SetPixel(j, i, flag ? border : fill);
}
}
val.Apply();
return val;
}
private static void DestroyAdminTexture(Texture2D texture)
{
if ((Object)(object)texture != (Object)null)
{
Object.Destroy((Object)(object)texture);
}
}
private void DrawAdminTabs()
{
GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
if (GUILayout.Button("Server Settings", (adminTab == 0) ? adminTabSelectedStyle : adminTabStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]))
{
adminTab = 0;
openDropdown = string.Empty;
}
if (GUILayout.Button("This Portal", (adminTab == 1) ? adminTabSelectedStyle : adminTabStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]))
{
adminTab = 1;
openDropdown = string.Empty;
}
if (GUILayout.Button("Portal Information", (adminTab == 2) ? adminTabSelectedStyle : adminTabStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]))
{
adminTab = 2;
openDropdown = string.Empty;
RequestPortalInformation(showStatus: false);
}
GUILayout.EndHorizontal();
}
private void DrawSectionHeader(string text)
{
GUILayout.Box(text, adminSectionStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
{
GUILayout.ExpandWidth(true),
GUILayout.Height(30f)
});
}
private void DrawServerSettingsTab()
{
GUILayout.Space(8f);
DrawSectionHeader("Portal Limit");
GUILayout.Label("How many counted portals may each non-admin player own? Use 0 for no limit.", adminHelpStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
maxText = GUILayout.TextField(maxText, adminTextFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
adminBypass = DrawBoolDropdown("adminBypass", "Admin portal limit bypass", adminBypass, "Allowed", "Not allowed");
enforceOnServer = DrawBoolDropdown("enforceOnServer", "Server removes extra portals over the limit", enforceOnServer, "Enabled", "Disabled");
GUILayout.Label("Which portal types count toward the limit?", adminLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
GUILayout.Label("Default covers normal wood and stone portals. Empty means every portal-like object.", adminHelpStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
portalNamesText = GUILayout.TextField(portalNamesText, adminTextFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
GUILayout.Label("Your current portal count: " + serverPortalCount + " / " + maxPortalsPerPlayer, adminLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
GUILayout.Space(12f);
DrawSectionHeader("Discovery Portals");
GUILayout.Label("These settings apply to every locked discovery portal pair.", adminHelpStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
discoveryEnabled = DrawBoolDropdown("discoveryEnabled", "Locked discovery portals", discoveryEnabled, "Enabled", "Disabled");
discoveryAdminBypass = DrawBoolDropdown("discoveryAdminBypass", "Admin bypass for locked discovery portals", discoveryAdminBypass, "Allowed", "Not allowed");
adminHoldEToEdit = DrawBoolDropdown("adminHoldEToEdit", "Admin hold E portal editor", adminHoldEToEdit, "Enabled", "Disabled");
GUILayout.Label("When enabled, admins can hold E on a portal to edit that portal. Tap E still opens Valheim's normal Set Tag box.", adminHelpStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
showDiscoveryHoverText = DrawBoolDropdown("showDiscoveryHoverText", "Lock/unlock hover text", showDiscoveryHoverText, "Shown", "Hidden");
GUILayout.Space(12f);
DrawSectionHeader("Default Player-Facing Hover Text");
GUILayout.Label("These are the server defaults. A locked portal can override them on its own This Portal tab.", adminHelpStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
GUILayout.Label("Locked entrance text", adminLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
discoveryLockedHoverTextField = GUILayout.TextField(discoveryLockedHoverTextField, adminTextFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
GUILayout.Label("Unlocked entrance text", adminLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
discoveryRemoteHoverTextField = GUILayout.TextField(discoveryRemoteHoverTextField, adminTextFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
GUILayout.Label("After unlocked text", adminLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
discoveryUnlockedHoverTextField = GUILayout.TextField(discoveryUnlockedHoverTextField, adminTextFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
}
private void DrawPortalSettingsTab()
{
GUILayout.Space(8f);
TeleportWorld val = GetSelectedPortal();
if ((Object)(object)val == (Object)null)
{
DrawSectionHeader("This Portal");
GUILayout.Label("No portal was opened.", adminLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
GUILayout.Label("Look at a portal and hold E to open settings for that exact portal.", adminHelpStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
return;
}
int discoveryRole = GetDiscoveryRole(val);
string portalTagForUi = GetPortalTagForUi(val);
GUILayout.Label("Portal tag", adminLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
GUILayout.Label("Use the same tag on both portals, for example: Bog Witch.", adminHelpStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
if (CanEditPortalTag(val))
{
discoveryLinkText = GUILayout.TextField(discoveryLinkText, adminTextFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
}
else
{
GUILayout.Label(discoveryLinkText, adminTextFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
GUILayout.Label("This portal was built by another player. Admins can edit Portal Limit settings, but the portal tag stays protected.", adminHelpStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
}
GUILayout.Space(8f);
DrawSectionHeader("This portal");
GUILayout.Label("Current: " + GetPortalRoleLabel(discoveryRole).ToUpperInvariant() + " | Tag: " + (string.IsNullOrWhiteSpace(portalTagForUi) ? "(NONE)" : portalTagForUi), adminHelpStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
selectedPortalRole = DrawInlineChoice("selectedPortalRole", selectedPortalRole, PortalRoleChoiceLabels);
int selectedPortalRoleValue = GetSelectedPortalRoleValue();
if (selectedPortalRoleValue != 0)
{
GUILayout.Space(10f);
DrawSectionHeader("Relock Portal Tag");
GUILayout.Label("For this portal tag, make every player discover the unlocked entrance again.", adminHelpStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
bool flag2 = (GUI.enabled = !string.IsNullOrWhiteSpace(discoveryLinkText));
if (GUILayout.Button("Relock this portal tag for players", adminButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]))
{
RelockSelectedDiscoveryPortal();
}
GUI.enabled = true;
if (!flag2)
{
GUILayout.Label("Enter a portal tag before relocking players.", adminHelpStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
}
}
switch (selectedPortalRoleValue)
{
case 1:
{
GUILayout.Space(10f);
DrawSectionHeader("Locked Entrance Options");
selectedPortalShowMarker = DrawBoolInline("Unlock message marker", selectedPortalShowMarker, "SHOWN", "HIDDEN");
selectedPortalSuppressGlow = !DrawBoolInline("Orange glow while locked", !selectedPortalSuppressGlow, "SHOWN", "HIDDEN");
GUILayout.Space(8f);
GUILayout.Label("Marker color", adminLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
int num = selectedPortalColorIndex;
selectedPortalColorIndex = DrawInlineChoice("selectedPortalColor", selectedPortalColorIndex, MarkerColorLabels);
if (num != selectedPortalColorIndex)
{
selectedPortalColorText = MarkerColorValues[Mathf.Clamp(selectedPortalColorIndex, 0, MarkerColorValues.Length - 1)];
}
selectedPortalColorText = GUILayout.TextField(selectedPortalColorText, adminTextFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
GUILayout.Space(8f);
GUILayout.Label("Marker text", adminLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
int num2 = selectedPortalMarkerTextIndex;
selectedPortalMarkerTextIndex = DrawInlineChoice("selectedPortalMarkerText", selectedPortalMarkerTextIndex, MarkerTextLabels);
if (num2 != selectedPortalMarkerTextIndex)
{
selectedPortalMarkerText = MarkerTextLabels[Mathf.Clamp(selectedPortalMarkerTextIndex, 0, MarkerTextLabels.Length - 1)];
}
selectedPortalMarkerText = GUILayout.TextField(selectedPortalMarkerText, adminTextFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
GUILayout.Space(8f);
GUILayout.Label("Player-facing hover text for this portal", adminLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
GUILayout.Label("Leave blank to use the server default.", adminHelpStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
selectedLockedHoverText = GUILayout.TextField(selectedLockedHoverText, adminTextFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
break;
}
case 2:
GUILayout.Space(10f);
DrawSectionHeader("Unlocked Entrance Options");
GUILayout.Label("Player-facing hover text for this portal", adminLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
GUILayout.Label("Leave blank to use the server default.", adminHelpStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
selectedRemoteHoverText = GUILayout.TextField(selectedRemoteHoverText, adminTextFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
break;
}
if (selectedPortalRoleValue != 0)
{
GUILayout.Space(10f);
DrawSectionHeader("Unlocked Message");
GUILayout.Label("Text players see after they have unlocked this portal tag. Leave blank to use the server default.", adminHelpStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
selectedUnlockedHoverText = GUILayout.TextField(selectedUnlockedHoverText, adminTextFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
}
}
private void DrawPortalInformationTab()
{
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: 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_015e: Unknown result type (might be due to invalid IL or missing references)
GUILayout.Space(8f);
TeleportWorld val = GetSelectedPortal();
if ((Object)(object)val == (Object)null)
{
DrawSectionHeader("Portal Information");
GUILayout.Label("No portal was opened.", adminLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
GUILayout.Label("Look at a portal and hold E to open settings for that exact portal.", adminHelpStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
return;
}
if (GUILayout.Button("Refresh portal information", adminButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]))
{
RequestPortalInformation(showStatus: true);
}
portalInfoShowThis = DrawCollapseHeader(portalInfoShowThis, "THIS PORTAL");
if (portalInfoShowThis)
{
portalInfoThisScroll = GUILayout.BeginScrollView(portalInfoThisScroll, adminBoxStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(220f) });
GUILayout.TextArea(portalInfoThisText, adminTextFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinHeight(GetTextAreaHeight(portalInfoThisText, 170f)) });
GUILayout.EndScrollView();
}
portalInfoShowWorld = DrawCollapseHeader(portalInfoShowWorld, "WORLD PORTALS");
if (portalInfoShowWorld)
{
portalInfoWorldScroll = GUILayout.BeginScrollView(portalInfoWorldScroll, adminBoxStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(260f) });
GUILayout.TextArea(portalInfoWorldText, adminTextFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinHeight(GetTextAreaHeight(portalInfoWorldText, 220f)) });
GUILayout.EndScrollView();
}
}
private static float GetTextAreaHeight(string text, float minimum)
{
int num = 1;
if (!string.IsNullOrEmpty(text))
{
num = text.Split(new char[1] { '\n' }).Length;
}
return Math.Max(minimum, 22f + (float)num * 20f);
}
private bool DrawCollapseHeader(bool expanded, string label)
{
GUILayout.Space(8f);
if (GUILayout.Button((expanded ? "v " : "> ") + label, adminTabSelectedStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]))
{
expanded = !expanded;
}
return expanded;
}
private bool DrawBoolInline(string label, bool value, string trueLabel, string falseLabel)
{
GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
GUILayout.Label(label, adminLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) });
if (GUILayout.Button((value ? "> " : string.Empty) + trueLabel, value ? adminTabSelectedStyle : adminButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]))
{
value = true;
}
if (GUILayout.Button(((!value) ? "> " : string.Empty) + falseLabel, (!value) ? adminTabSelectedStyle : adminButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]))
{
value = false;
}
GUILayout.EndHorizontal();
return value;
}
private int DrawInlineChoice(string id, int selected, string[] labels)
{
if (labels == null || labels.Length == 0)
{
return selected;
}
selected = Mathf.Clamp(selected, 0, labels.Length - 1);
GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
for (int i = 0; i < labels.Length; i++)
{
if (GUILayout.Button(((i == selected) ? "> " : string.Empty) + labels[i], (i == selected) ? adminTabSelectedStyle : adminButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]))
{
selected = i;
openDropdown = string.Empty;
}
}
GUILayout.EndHorizontal();
return selected;
}
private bool DrawBoolDropdown(string id, string label, bool value, string trueLabel, string falseLabel)
{
int selected = ((!value) ? 1 : 0);
selected = DrawChoiceDropdown(id, label, selected, new string[2] { trueLabel, falseLabel });
return selected == 0;
}
private int DrawChoiceDropdown(string id, int selected, string[] labels)
{
return DrawChoiceDropdown(id, string.Empty, selected, labels);
}
private int DrawChoiceDropdown(string id, string label, int selected, string[] labels)
{
if (labels == null || labels.Length == 0)
{
return selected;
}
selected = Mathf.Clamp(selected, 0, labels.Length - 1);
GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
if (!string.IsNullOrWhiteSpace(label))
{
GUILayout.Label(label, adminLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(330f) });
}
string text = labels[selected] + " v";
if (GUILayout.Button(text, adminButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(190f) }))
{
openDropdown = ((openDropdown == id) ? string.Empty : id);
}
GUILayout.EndHorizontal();
if (openDropdown == id)
{
GUILayout.BeginVertical(adminBoxStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
for (int i = 0; i < labels.Length; i++)
{
string text2 = ((i == selected) ? "> " : " ");
if (GUILayout.Button(text2 + labels[i], adminButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]))
{
selected = i;
openDropdown = string.Empty;
}
}
GUILayout.EndVertical();
}
return selected;
}
private int DrawChoiceList(string id, int selected, string[] labels)
{
if (labels == null || labels.Length == 0)
{
return selected;
}
selected = Mathf.Clamp(selected, 0, labels.Length - 1);
GUILayout.BeginVertical(adminBoxStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
for (int i = 0; i < labels.Length; i++)
{
string text = ((i == selected) ? "> " : " ");
if (GUILayout.Button(text + labels[i], adminButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]))
{
selected = i;
openDropdown = string.Empty;
}
}
GUILayout.EndVertical();
return selected;
}
private void DrawAdminFooter()
{
GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
if (GUILayout.Button("Apply", adminButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]))
{
ApplyActiveTab(closeAfterApply: false);
}
if (GUILayout.Button("Apply & Close", adminButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]))
{
ApplyActiveTab(closeAfterApply: true);
}
if (GUILayout.Button("Close Without Applying", adminButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]))
{
showAdminWindow = false;
}
GUILayout.EndHorizontal();
}
private void DrawInformationFooter()
{
GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
if (GUILayout.Button("Refresh", adminButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]))
{
RequestPortalInformation(showStatus: true);
}
if (GUILayout.Button("Close", adminButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]))
{
showAdminWindow = false;
}
GUILayout.EndHorizontal();
}
private void ApplyActiveTab(bool closeAfterApply)
{
if (adminTab == 0)
{
SaveConfigFromUi();
}
else
{
MarkSelectedDiscoveryPortal(GetSelectedPortalRoleValue());
}
if (closeAfterApply)
{
showAdminWindow = false;
}
}
private void ToggleAdminWindow()
{
if (!adminStatusKnown)
{
openAdminUiAfterPermissionCheck = true;
RequestConfig(openUi: false);
ShowMessage("Checking portal limit permissions...");
return;
}
if (!isAdmin)
{
showAdminWindow = false;
RequestCountForChat();
return;
}
showAdminWindow = !showAdminWindow;
openDropdown = string.Empty;
if (showAdminWindow)
{
RequestConfig(openUi: true);
RequestCount();
CenterAdminWindowIfNeeded();
}
}
private void OpenAdminWindowForPortal(TeleportWorld portal)
{
SelectPortalForEditing(portal, showStatus: false);
showAdminWindow = true;
openDropdown = string.Empty;
adminTab = 1;
statusMessage = "Portal selected. Choose what this portal should do, then Apply or Apply & Close.";
CenterAdminWindowIfNeeded();
RequestConfig(openUi: true);
RequestCount();
}
private void SaveConfigFromUi()
{
if (!int.TryParse(maxText, out var result))
{
statusMessage = "Max portals must be a whole number.";
return;
}
string text = "max=" + Math.Max(0, result) + "\nadminBypass=" + adminBypass + "\nenforceOnServer=" + enforceOnServer + "\nportalPrefabNames=" + Escape(portalNamesText) + "\ndiscoveryEnabled=" + discoveryEnabled + "\ndiscoveryAdminBypass=" + discoveryAdminBypass + "\nadminHoldEToEdit=" + adminHoldEToEdit + "\nshowDiscoveryHoverText=" + showDiscoveryHoverText + "\ndiscoveryLockedHoverText=" + Escape(discoveryLockedHoverTextField) + "\ndiscoveryRemoteHoverText=" + Escape(discoveryRemoteHoverTextField) + "\ndiscoveryUnlockedHoverText=" + Escape(discoveryUnlockedHoverTextField) + "\ndiscoveryLockedMessage=" + Escape(discoveryLockedMessageField) + "\ndiscoveryUnlockMessage=" + Escape(discoveryUnlockMessageField) + "\ndiscoveryShowWorldMarker=" + discoveryShowWorldMarker + "\ndiscoveryTintPortalModel=" + discoveryTintPortalModel + "\ndiscoverySuppressLockedGlow=" + discoverySuppressLockedGlow + "\ndiscoveryLockedColor=" + Escape(discoveryLockedColorField) + "\ndiscoveryRemoteColor=" + Escape(discoveryRemoteColorField) + "\ndiscoveryUnlockedColor=" + Escape(discoveryUnlockedColorField);
ZRoutedRpc.instance.InvokeRoutedRPC("keith.valheim.portallimit.config_update", new object[1] { text });
statusMessage = "Saving portal limit settings...";
}
private void RequestConfig(bool openUi)
{
configRequested = true;
if (openUi)
{
statusMessage = "Loading portal limit settings...";
}
ZRoutedRpc.instance.InvokeRoutedRPC("keith.valheim.portallimit.config_request", new object[1] { (openUi ? string.Empty : "[silent]") + GetPlayerName() });
RequestUnlockList();
}
private void RequestCount()
{
long localPlayerId = GetLocalPlayerId();
if (localPlayerId != 0)
{
ZRoutedRpc.instance.InvokeRoutedRPC("keith.valheim.portallimit.count_request", new object[1] { localPlayerId });
}
}
private void RequestCountForChat()
{
showCountMessageOnNextResponse = true;
RequestCount();
ShowMessage("Checking portal count...");
}
private void RequestPlacementCountSoon()
{
((MonoBehaviour)this).StartCoroutine(RequestPlacementCountNextFrame());
}
private IEnumerator RequestPlacementCountNextFrame()
{
yield return (object)new WaitForSeconds(0.35f);
long playerId = GetLocalPlayerId();
int count = CountPortals(playerId);
string maxText = ((maxPortalsPerPlayer > 0) ? maxPortalsPerPlayer.ToString() : "unlimited");
serverPortalCount = count;
ShowMessage("Portals placed: " + count + " / " + maxText);
RequestCount();
}
private void RequestUnlockList()
{
long localPlayerId = GetLocalPlayerId();
if (localPlayerId != 0)
{
ZRoutedRpc.instance.InvokeRoutedRPC("keith.valheim.portallimit.discovery_unlock_list_request", new object[1] { localPlayerId });
}
}
private void RequestPortalInformation(bool showStatus)
{
TeleportWorld val = GetSelectedPortal();
if ((Object)(object)val == (Object)null)
{
portalInfoThisText = "No portal was opened.";
portalInfoWorldText = "Open this tab while editing a portal.";
return;
}
ZNetView component = ((Component)val).GetComponent();
ZDO val2 = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
portalInfoRequestedPortalKey = ((val2 != null) ? ((object)(ZDOID)(ref val2.m_uid)).ToString() : GetPortalKey(val));
portalInfoThisText = "Loading authoritative portal information from the server...";
string portalTagForUi = GetPortalTagForUi(val);
if (ZRoutedRpc.instance == null)
{
portalInfoWorldText = "Portal Limit server RPC is not ready yet.";
return;
}
if (showStatus)
{
statusMessage = "Loading portal information...";
}
ZRoutedRpc.instance.InvokeRoutedRPC("keith.valheim.portallimit.admin_report_request", new object[1] { "portalinfo|" + Escape(portalTagForUi) + "|" + Escape(portalInfoRequestedPortalKey) });
}
private static void OnConfigResponse(long sender, string payload)
{
Instance.ApplyConfigPayload(payload);
}
private static void OnCountResponse(long sender, int count, int max, bool limitReached, string payload)
{
Instance.serverPortalCount = count;
Instance.maxPortalsPerPlayer = max;
Instance.ApplyConfigPayload(payload);
if (Instance.showPlacementCountOnNextResponse)
{
Instance.showPlacementCountOnNextResponse = false;
string text = ((max > 0) ? max.ToString() : "unlimited");
Instance.ShowMessage("Portals placed: " + count + " / " + text);
}
else if (Instance.showCountMessageOnNextResponse)
{
Instance.showCountMessageOnNextResponse = false;
string text = ((max > 0) ? max.ToString() : "unlimited");
Instance.ShowMessage("Portals: " + count + " / " + text);
}
}
private static void OnNotice(long sender, string message)
{
Instance.ShowMessage(message);
}
private static void OnDiscoveryUnlockListResponse(long sender, string payload)
{
Instance.ApplyUnlockPayload(payload);
}
private static void OnAdminReportResponse(long sender, string payload)
{
if (string.IsNullOrWhiteSpace(payload))
{
Terminal.Log((object)"Portal Limit: empty report.");
return;
}
if ((Object)(object)Instance != (Object)null && payload.StartsWith("PortalInfoResponse\n", StringComparison.Ordinal))
{
Instance.ApplyPortalInformationPayload(payload);
return;
}
string[] array = payload.Split(new char[1] { '\n' });
foreach (string text in array)
{
Terminal.Log((object)text);
}
if ((Object)(object)Instance != (Object)null)
{
Instance.ShowMessage("Portal Limit report written to F5 console.");
}
}
private void ApplyPortalInformationPayload(string payload)
{
string text = payload.Substring("PortalInfoResponse\n".Length);
string[] array = text.Split(new string[1] { "\n---WORLD---\n" }, StringSplitOptions.None);
if (array.Length > 0 && !string.IsNullOrWhiteSpace(array[0]))
{
portalInfoThisText = array[0].Trim();
}
portalInfoWorldText = ((array.Length > 1) ? array[1].Trim() : text.Trim());
statusMessage = "Portal information loaded.";
}
private void ApplyConfigPayload(string payload)
{
Dictionary dictionary = ParsePayload(payload);
if (dictionary.TryGetValue("isAdmin", out var value) && bool.TryParse(value, out var result))
{
isAdmin = result;
adminStatusKnown = true;
if (!isAdmin)
{
showAdminWindow = false;
}
if (openAdminUiAfterPermissionCheck)
{
openAdminUiAfterPermissionCheck = false;
if (isAdmin)
{
showAdminWindow = true;
openDropdown = string.Empty;
CenterAdminWindowIfNeeded();
RequestConfig(openUi: true);
RequestCount();
}
else
{
RequestCountForChat();
}
}
}
if (dictionary.TryGetValue("max", out value) && int.TryParse(value, out var result2))
{
maxPortalsPerPlayer = result2;
maxText = result2.ToString();
}
if (dictionary.TryGetValue("adminBypass", out value) && bool.TryParse(value, out result))
{
adminBypass = result;
}
if (dictionary.TryGetValue("enforceOnServer", out value) && bool.TryParse(value, out result))
{
enforceOnServer = result;
}
if (dictionary.TryGetValue("portalPrefabNames", out value))
{
portalPrefabNames = value;
portalNamesText = value;
}
if (dictionary.TryGetValue("discoveryEnabled", out value) && bool.TryParse(value, out result))
{
discoveryEnabled = result;
}
if (dictionary.TryGetValue("discoveryAdminBypass", out value) && bool.TryParse(value, out result))
{
discoveryAdminBypass = result;
}
if (dictionary.TryGetValue("adminHoldEToEdit", out value) && bool.TryParse(value, out result))
{
adminHoldEToEdit = result;
}
if (dictionary.TryGetValue("showDiscoveryHoverText", out value) && bool.TryParse(value, out result))
{
showDiscoveryHoverText = result;
}
if (dictionary.TryGetValue("discoveryLockedHoverText", out value))
{
discoveryLockedHoverText = value;
discoveryLockedHoverTextField = value;
}
if (dictionary.TryGetValue("discoveryRemoteHoverText", out value))
{
discoveryRemoteHoverText = value;
discoveryRemoteHoverTextField = value;
}
if (dictionary.TryGetValue("discoveryUnlockedHoverText", out value))
{
discoveryUnlockedHoverText = value;
discoveryUnlockedHoverTextField = value;
}
if (dictionary.TryGetValue("discoveryLockedMessage", out value))
{
discoveryLockedMessage = value;
discoveryLockedMessageField = value;
}
if (dictionary.TryGetValue("discoveryUnlockMessage", out value))
{
discoveryUnlockMessage = value;
discoveryUnlockMessageField = value;
}
if (dictionary.TryGetValue("discoveryShowWorldMarker", out value) && bool.TryParse(value, out result))
{
discoveryShowWorldMarker = result;
}
if (dictionary.TryGetValue("discoveryTintPortalModel", out value) && bool.TryParse(value, out result))
{
discoveryTintPortalModel = result;
}
if (dictionary.TryGetValue("discoverySuppressLockedGlow", out value) && bool.TryParse(value, out result))
{
discoverySuppressLockedGlow = result;
}
if (dictionary.TryGetValue("discoveryLockedColor", out value))
{
discoveryLockedColor = value;
discoveryLockedColorField = value;
}
if (dictionary.TryGetValue("discoveryRemoteColor", out value))
{
discoveryRemoteColor = value;
discoveryRemoteColorField = value;
}
if (dictionary.TryGetValue("discoveryUnlockedColor", out value))
{
discoveryUnlockedColor = value;
discoveryUnlockedColorField = value;
}
if (dictionary.TryGetValue("message", out value) && !string.IsNullOrWhiteSpace(value))
{
statusMessage = value;
ShowMessage(value);
}
}
private void ApplyUnlockPayload(string payload)
{
Dictionary dictionary = ParsePayload(payload);
unlockedDiscoveryLinks.Clear();
if (dictionary.TryGetValue("links", out var value))
{
string[] array = value.Split(new char[1] { ';' });
foreach (string text in array)
{
string text2 = text.Trim();
if (!string.IsNullOrWhiteSpace(text2))
{
unlockedDiscoveryLinks.Add(text2);
}
}
}
if (dictionary.TryGetValue("message", out var value2) && !string.IsNullOrWhiteSpace(value2))
{
ShowMessage(value2);
}
}
private void MarkSelectedDiscoveryPortal(int role)
{
//IL_0222: Unknown result type (might be due to invalid IL or missing references)
//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
TeleportWorld val = GetSelectedPortal();
if ((Object)(object)val == (Object)null)
{
statusMessage = "No portal selected. Look at a portal and click Select first.";
return;
}
ZNetView component = ((Component)val).GetComponent();
if ((Object)(object)component == (Object)null || !component.IsValid())
{
statusMessage = "That portal has no valid network view.";
return;
}
string text = discoveryLinkText.Trim();
bool flag = CanEditPortalTag(val);
if (!flag)
{
text = GetPortalTagForUi(val).Trim();
}
if (role != 0 && string.IsNullOrWhiteSpace(text))
{
statusMessage = "Enter a portal tag first.";
return;
}
discoveryLinkText = text;
if (flag)
{
SetPortalTag(val, text);
}
string text2 = ((role == 0) ? string.Empty : text);
string normalized = string.Empty;
string text3 = string.Empty;
if (role != 0)
{
if (!TryNormalizeHexColor(selectedPortalColorText, out normalized))
{
statusMessage = "Enter a color like #ff3030.";
return;
}
selectedPortalColorText = normalized;
text3 = NormalizeMarkerTextValue(selectedPortalMarkerText);
}
string text4 = "role=" + role + "\nlink=" + Escape(text2) + "\nmarkerColor=" + Escape(normalized) + "\nmarkerText=" + Escape(text3) + "\nshowMarker=" + selectedPortalShowMarker + "\nsuppressGlow=" + selectedPortalSuppressGlow + "\nlockedHoverText=" + Escape(selectedLockedHoverText) + "\nremoteHoverText=" + Escape(selectedRemoteHoverText) + "\nunlockedHoverText=" + Escape(selectedUnlockedHoverText);
ZRoutedRpc.instance.InvokeRoutedRPC("keith.valheim.portallimit.discovery_mark_request", new object[2]
{
component.GetZDO().m_uid,
text4
});
ApplyLocalPortalMarker(val, role, text2, normalized, text3, selectedPortalShowMarker, selectedPortalSuppressGlow, selectedLockedHoverText, selectedRemoteHoverText, selectedUnlockedHoverText);
statusMessage = "Portal settings saved.";
Log.LogInfo((object)("Sent discovery portal marker request role=" + role + " tag='" + text + "' portal=" + component.GetZDO().m_uid));
}
private void RelockSelectedDiscoveryPortal()
{
RelockDiscoveryPortalTag(discoveryLinkText);
}
private void RelockDiscoveryPortalTag(string portalTagText)
{
string text = (portalTagText ?? string.Empty).Trim();
if (string.IsNullOrWhiteSpace(text))
{
statusMessage = "Enter a portal tag first.";
return;
}
ZRoutedRpc.instance.InvokeRoutedRPC("keith.valheim.portallimit.discovery_relock_request", new object[1] { text });
unlockedDiscoveryLinks.Remove(text);
statusMessage = "Relock request sent for portal tag '" + text + "'.";
}
private void ReadSelectedPortalSettings()
{
TeleportWorld val = GetSelectedPortal();
if ((Object)(object)val == (Object)null)
{
statusMessage = "No portal selected. Look at a portal and click Select first.";
}
else
{
LoadPortalSettings(val, showStatus: true);
}
}
private string BuildLocalPortalInformation(TeleportWorld portal)
{
if ((Object)(object)portal == (Object)null)
{
return "THIS PORTAL\nNo portal selected.";
}
ZNetView component = ((Component)portal).GetComponent();
ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
string text = ((val != null) ? val.GetString("PortalLimit_BuiltUtc", string.Empty) : string.Empty);
string text2 = GetPortalCreatorName(portal);
if (string.IsNullOrWhiteSpace(text2))
{
text2 = "unknown";
}
string text3 = GetPortalTagForUi(portal);
if (string.IsNullOrWhiteSpace(text3))
{
text3 = "(none)";
}
string text4 = (string.IsNullOrWhiteSpace(text) ? "unknown for older portals" : text);
return "THIS PORTAL\nPortal Tag: " + text3 + "\nPlayer Who Built the Portal: " + text2 + "\nDate the portal was built: " + text4 + "\nPortal role: " + GetPortalRoleLabel(GetDiscoveryRole(portal)) + "\nPortal id: " + ((val != null) ? ((object)(ZDOID)(ref val.m_uid)).ToString() : "unknown");
}
private void SelectPortalForEditing(TeleportWorld portal, bool showStatus)
{
if ((Object)(object)portal == (Object)null)
{
if (showStatus)
{
statusMessage = "Look directly at a portal first.";
}
}
else
{
selectedPortal = portal;
LoadPortalSettings(portal, showStatus);
}
}
private TeleportWorld GetSelectedPortal()
{
if ((Object)(object)selectedPortal != (Object)null)
{
ZNetView component = ((Component)selectedPortal).GetComponent();
if ((Object)(object)component != (Object)null && component.IsValid())
{
return selectedPortal;
}
}
selectedPortal = null;
loadedPortalKey = string.Empty;
return null;
}
private void LoadPortalSettings(TeleportWorld portal, bool showStatus)
{
selectedPortalRole = GetDiscoveryRole(portal) switch
{
2 => 2,
1 => 1,
_ => 0,
};
string discoveryLink = GetDiscoveryLink(portal);
if (!string.IsNullOrWhiteSpace(discoveryLink))
{
discoveryLinkText = discoveryLink;
}
else
{
string portalTag = GetPortalTag(portal);
if (!string.IsNullOrWhiteSpace(portalTag))
{
discoveryLinkText = portalTag;
}
}
loadedPortalKey = GetPortalKey(portal);
selectedPortalColorText = GetDiscoveryColor(portal);
if (string.IsNullOrWhiteSpace(selectedPortalColorText))
{
selectedPortalColorText = MarkerColorValues[0];
}
selectedPortalColorIndex = GetMarkerColorIndex(selectedPortalColorText);
selectedPortalMarkerText = GetDiscoveryMarkerText(portal);
selectedPortalMarkerTextIndex = GetMarkerTextIndex(selectedPortalMarkerText);
selectedPortalShowMarker = GetDiscoveryShowMarker(portal);
selectedPortalSuppressGlow = GetDiscoverySuppressGlow(portal);
selectedLockedHoverText = GetDiscoveryHoverOverride(portal, "PortalLimit_DiscoveryLockedHoverText");
selectedRemoteHoverText = GetDiscoveryHoverOverride(portal, "PortalLimit_DiscoveryRemoteHoverText");
selectedUnlockedHoverText = GetDiscoveryHoverOverride(portal, "PortalLimit_DiscoveryUnlockedHoverText");
if (showStatus)
{
statusMessage = "Selected portal loaded. Choose what this portal does, then Apply.";
}
}
private static void ApplyLocalPortalMarker(TeleportWorld portal, int role, string link, string markerColor, string markerText, bool showMarker, bool suppressGlow, string lockedHoverText, string remoteHoverText, string unlockedHoverText)
{
ZNetView val = (((Object)(object)portal != (Object)null) ? ((Component)portal).GetComponent() : null);
ZDO val2 = (((Object)(object)val != (Object)null && val.IsValid()) ? val.GetZDO() : null);
if (val2 != null)
{
val2.Set("PortalLimit_DiscoveryRole", role);
val2.Set("PortalLimit_DiscoveryLink", (role == 0) ? string.Empty : link);
val2.Set("PortalLimit_DiscoveryColor", (role == 0) ? string.Empty : markerColor);
val2.Set("PortalLimit_DiscoveryMarkerText", (role == 0) ? string.Empty : NormalizeMarkerTextValue(markerText));
val2.Set("PortalLimit_DiscoveryShowMarker", (role != 0) ? (showMarker ? 1 : 0) : 0);
val2.Set("PortalLimit_DiscoverySuppressGlow", (role != 0) ? (suppressGlow ? 1 : 0) : 0);
val2.Set("PortalLimit_DiscoveryLockedHoverText", (role == 0) ? string.Empty : (lockedHoverText ?? string.Empty).Trim());
val2.Set("PortalLimit_DiscoveryRemoteHoverText", (role == 0) ? string.Empty : (remoteHoverText ?? string.Empty).Trim());
val2.Set("PortalLimit_DiscoveryUnlockedHoverText", (role == 0) ? string.Empty : (unlockedHoverText ?? string.Empty).Trim());
}
}
private int GetSelectedPortalRoleValue()
{
if (selectedPortalRole == 1)
{
return 1;
}
if (selectedPortalRole == 2)
{
return 2;
}
return 0;
}
private static string GetPortalRoleLabel(int role)
{
return role switch
{
1 => "Locked entrance",
2 => "Unlocked entrance",
_ => "Normal portal",
};
}
private static TeleportWorld GetHoveredPortal()
{
if ((Object)(object)Player.m_localPlayer == (Object)null)
{
return null;
}
GameObject hoverObject = ((Humanoid)Player.m_localPlayer).GetHoverObject();
if ((Object)(object)hoverObject == (Object)null)
{
return null;
}
TeleportWorld val = hoverObject.GetComponent();
if ((Object)(object)val == (Object)null)
{
val = hoverObject.GetComponentInParent();
}
return val;
}
private static string GetPortalKey(TeleportWorld portal)
{
ZNetView val = (((Object)(object)portal != (Object)null) ? ((Component)portal).GetComponent() : null);
ZDO val2 = (((Object)(object)val != (Object)null && val.IsValid()) ? val.GetZDO() : null);
return (val2 != null) ? ((object)(ZDOID)(ref val2.m_uid)).ToString() : string.Empty;
}
private static string GetPortalCreatorName(TeleportWorld portal)
{
ZNetView val = (((Object)(object)portal != (Object)null) ? ((Component)portal).GetComponent() : null);
ZDO val2 = (((Object)(object)val != (Object)null && val.IsValid()) ? val.GetZDO() : null);
if (val2 == null)
{
return string.Empty;
}
string @string = val2.GetString(ZDOVars.s_creatorName, string.Empty);
return @string ?? string.Empty;
}
private static bool CanEditPortalTag(TeleportWorld portal)
{
if ((Object)(object)Instance == (Object)null || (Object)(object)portal == (Object)null)
{
return false;
}
Piece val = ((Component)portal).GetComponent();
if ((Object)(object)val == (Object)null)
{
val = ((Component)portal).GetComponentInParent();
}
if ((Object)(object)val == (Object)null)
{
return true;
}
long creator = val.GetCreator();
long localPlayerId = GetLocalPlayerId();
return creator == 0 || creator == localPlayerId;
}
private static string GetPortalTag(TeleportWorld portal)
{
MethodInfo methodInfo = AccessTools.Method(typeof(TeleportWorld), "GetText", (Type[])null, (Type[])null);
if ((Object)(object)portal != (Object)null && methodInfo != null)
{
object obj = methodInfo.Invoke(portal, null);
if (obj != null)
{
return obj.ToString();
}
}
return string.Empty;
}
private static string GetPortalTagForUi(TeleportWorld portal)
{
string discoveryLink = GetDiscoveryLink(portal);
if (!string.IsNullOrWhiteSpace(discoveryLink))
{
return discoveryLink;
}
return GetPortalTag(portal);
}
private static void SetPortalTag(TeleportWorld portal, string tag)
{
if ((Object)(object)portal == (Object)null)
{
return;
}
MethodInfo methodInfo = AccessTools.Method(typeof(TeleportWorld), "SetText", new Type[1] { typeof(string) }, (Type[])null);
if (methodInfo != null)
{
methodInfo.Invoke(portal, new object[1] { tag ?? string.Empty });
return;
}
ZNetView component = ((Component)portal).GetComponent();
ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
if (val != null)
{
val.Set("tag", tag ?? string.Empty);
}
}
private static void SetTargetFound(TeleportWorld portal, bool value)
{
if ((Object)(object)portal != (Object)null && TeleportWorldTargetFoundField != null)
{
TeleportWorldTargetFoundField.SetValue(portal, value);
}
}
private static int GetDiscoveryRole(TeleportWorld portal)
{
ZNetView val = (((Object)(object)portal != (Object)null) ? ((Component)portal).GetComponent() : null);
ZDO val2 = (((Object)(object)val != (Object)null && val.IsValid()) ? val.GetZDO() : null);
return (val2 != null) ? val2.GetInt("PortalLimit_DiscoveryRole", 0) : 0;
}
private static string GetDiscoveryLink(TeleportWorld portal)
{
ZNetView val = (((Object)(object)portal != (Object)null) ? ((Component)portal).GetComponent() : null);
ZDO val2 = (((Object)(object)val != (Object)null && val.IsValid()) ? val.GetZDO() : null);
return (val2 != null) ? val2.GetString("PortalLimit_DiscoveryLink", string.Empty) : string.Empty;
}
private static string GetDiscoveryColor(TeleportWorld portal)
{
ZNetView val = (((Object)(object)portal != (Object)null) ? ((Component)portal).GetComponent() : null);
ZDO val2 = (((Object)(object)val != (Object)null && val.IsValid()) ? val.GetZDO() : null);
return (val2 != null) ? val2.GetString("PortalLimit_DiscoveryColor", string.Empty) : string.Empty;
}
private static string GetDiscoveryMarkerText(TeleportWorld portal)
{
ZNetView val = (((Object)(object)portal != (Object)null) ? ((Component)portal).GetComponent() : null);
ZDO val2 = (((Object)(object)val != (Object)null && val.IsValid()) ? val.GetZDO() : null);
return (val2 != null) ? NormalizeMarkerTextValue(val2.GetString("PortalLimit_DiscoveryMarkerText", string.Empty)) : MarkerTextValues[0];
}
private bool GetDiscoveryShowMarker(TeleportWorld portal)
{
ZNetView val = (((Object)(object)portal != (Object)null) ? ((Component)portal).GetComponent() : null);
ZDO val2 = (((Object)(object)val != (Object)null && val.IsValid()) ? val.GetZDO() : null);
return (val2 != null) ? (val2.GetInt("PortalLimit_DiscoveryShowMarker", discoveryShowWorldMarker ? 1 : 0) != 0) : discoveryShowWorldMarker;
}
private bool GetDiscoverySuppressGlow(TeleportWorld portal)
{
ZNetView val = (((Object)(object)portal != (Object)null) ? ((Component)portal).GetComponent() : null);
ZDO val2 = (((Object)(object)val != (Object)null && val.IsValid()) ? val.GetZDO() : null);
return (val2 != null) ? (val2.GetInt("PortalLimit_DiscoverySuppressGlow", discoverySuppressLockedGlow ? 1 : 0) != 0) : discoverySuppressLockedGlow;
}
private static string GetDiscoveryHoverOverride(TeleportWorld portal, string key)
{
ZNetView val = (((Object)(object)portal != (Object)null) ? ((Component)portal).GetComponent() : null);
ZDO val2 = (((Object)(object)val != (Object)null && val.IsValid()) ? val.GetZDO() : null);
return (val2 != null) ? val2.GetString(key, string.Empty) : string.Empty;
}
private Color GetDiscoveryVisualColor(TeleportWorld portal)
{
//IL_0016: 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_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
string discoveryColor = GetDiscoveryColor(portal);
if (!string.IsNullOrWhiteSpace(discoveryColor))
{
return ParseHexColor(discoveryColor, LockedOrange);
}
int discoveryRole = GetDiscoveryRole(portal);
string discoveryLink = GetDiscoveryLink(portal);
if (discoveryRole != 0 && !string.IsNullOrWhiteSpace(discoveryLink) && IsDiscoveryUnlocked(discoveryLink))
{
return ParseHexColor(discoveryUnlockedColor, Color.green);
}
if (discoveryRole == 2)
{
return ParseHexColor(discoveryRemoteColor, Color.cyan);
}
return ParseHexColor(discoveryLockedColor, LockedOrange);
}
private bool ShouldShowDiscoveryWorldMarker(TeleportWorld portal)
{
return discoveryEnabled && GetDiscoveryShowMarker(portal) && ShouldShowLockedEntranceX(portal);
}
private string GetDiscoveryMarkerDisplayText(TeleportWorld portal)
{
string discoveryMarkerText = GetDiscoveryMarkerText(portal);
if (string.Equals(discoveryMarkerText, "Locked", StringComparison.OrdinalIgnoreCase))
{
return "LOCKED";
}
if (string.Equals(discoveryMarkerText, "X", StringComparison.OrdinalIgnoreCase))
{
return "X";
}
if (string.Equals(discoveryMarkerText, "UnlockOnOtherSide", StringComparison.OrdinalIgnoreCase))
{
return "UNLOCK ON OTHER SIDE";
}
return string.IsNullOrWhiteSpace(discoveryMarkerText) ? "UNLOCK ON OTHER SIDE" : discoveryMarkerText;
}
private bool ShouldShowLockedEntranceX(TeleportWorld portal)
{
if (GetDiscoveryRole(portal) != 1)
{
return false;
}
string discoveryLink = GetDiscoveryLink(portal);
return !string.IsNullOrWhiteSpace(discoveryLink) && !IsDiscoveryUnlocked(discoveryLink);
}
private bool ShouldTintDiscoveryPortal(TeleportWorld portal)
{
return false;
}
private bool ShouldSuppressLockedPortalGlow(TeleportWorld portal)
{
if (!discoveryEnabled || !GetDiscoverySuppressGlow(portal) || GetDiscoveryRole(portal) != 1)
{
return false;
}
string discoveryLink = GetDiscoveryLink(portal);
return !string.IsNullOrWhiteSpace(discoveryLink) && !IsDiscoveryUnlocked(discoveryLink);
}
private static Color ParseHexColor(string text, Color fallback)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
//IL_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)
if (string.IsNullOrWhiteSpace(text))
{
return fallback;
}
string text2 = text.Trim();
if (text2.StartsWith("#", StringComparison.Ordinal))
{
text2 = text2.Substring(1);
}
if (text2.Length == 6 && int.TryParse(text2.Substring(0, 2), NumberStyles.HexNumber, null, out var result) && int.TryParse(text2.Substring(2, 2), NumberStyles.HexNumber, null, out var result2) && int.TryParse(text2.Substring(4, 2), NumberStyles.HexNumber, null, out var result3))
{
return new Color((float)result / 255f, (float)result2 / 255f, (float)result3 / 255f, 1f);
}
return fallback;
}
private static string NormalizeHexColor(string text, string fallback)
{
string text2 = (text ?? string.Empty).Trim();
if (!text2.StartsWith("#", StringComparison.Ordinal))
{
text2 = "#" + text2;
}
Color val = default(Color);
return ColorUtility.TryParseHtmlString(text2, ref val) ? text2 : fallback;
}
private static bool TryNormalizeHexColor(string text, out string normalized)
{
normalized = (text ?? string.Empty).Trim();
if (!normalized.StartsWith("#", StringComparison.Ordinal))
{
normalized = "#" + normalized;
}
Color val = default(Color);
if (normalized.Length == 7 && ColorUtility.TryParseHtmlString(normalized, ref val))
{
return true;
}
normalized = string.Empty;
return false;
}
private static int GetMarkerColorIndex(string color)
{
string a = NormalizeHexColor(color, MarkerColorValues[0]);
for (int i = 0; i < MarkerColorValues.Length; i++)
{
if (string.Equals(a, MarkerColorValues[i], StringComparison.OrdinalIgnoreCase))
{
return i;
}
}
return 0;
}
private static string NormalizeMarkerTextValue(string value)
{
string text = (value ?? string.Empty).Trim();
if (string.IsNullOrWhiteSpace(text))
{
return MarkerTextLabels[0];
}
for (int i = 0; i < MarkerTextValues.Length; i++)
{
if (string.Equals(text, MarkerTextValues[i], StringComparison.OrdinalIgnoreCase) || string.Equals(text, MarkerTextLabels[i], StringComparison.OrdinalIgnoreCase))
{
return MarkerTextLabels[i];
}
}
return text;
}
private static int GetMarkerTextIndex(string value)
{
string a = NormalizeMarkerTextValue(value);
for (int i = 0; i < MarkerTextValues.Length; i++)
{
if (string.Equals(a, MarkerTextValues[i], StringComparison.OrdinalIgnoreCase) || string.Equals(a, MarkerTextLabels[i], StringComparison.OrdinalIgnoreCase))
{
return i;
}
}
return 0;
}
private bool IsDiscoveryUnlocked(string link)
{
if (string.IsNullOrWhiteSpace(link))
{
return false;
}
return unlockedDiscoveryLinks.Contains(link);
}
private void UnlockDiscoveryLink(string link, TeleportWorld portal)
{
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
if (!string.IsNullOrWhiteSpace(link))
{
unlockedDiscoveryLinks.Add(link);
long localPlayerId = GetLocalPlayerId();
if (localPlayerId != 0 && ZRoutedRpc.instance != null)
{
Vector3 val = (((Object)(object)portal != (Object)null) ? ((Component)portal).transform.position : Vector3.zero);
ZNetView val2 = (((Object)(object)portal != (Object)null) ? ((Component)portal).GetComponent() : null);
ZDOID val3 = (((Object)(object)val2 != (Object)null && val2.IsValid()) ? val2.GetZDO().m_uid : ZDOID.None);
string text = "link=" + Escape(link.Trim()) + "\nplayerName=" + Escape(GetPlayerName()) + "\nportalId=" + Escape(((object)(ZDOID)(ref val3)).ToString()) + "\nx=" + val.x.ToString("F1") + "\ny=" + val.y.ToString("F1") + "\nz=" + val.z.ToString("F1");
ZRoutedRpc.instance.InvokeRoutedRPC("keith.valheim.portallimit.discovery_unlock_request", new object[2] { localPlayerId, text });
}
}
}
private static bool ShouldBlockPortalUse(TeleportWorld portal)
{
if ((Object)(object)Instance == (Object)null || !Instance.discoveryEnabled || (Object)(object)Player.m_localPlayer == (Object)null)
{
return false;
}
int discoveryRole = GetDiscoveryRole(portal);
if (discoveryRole == 0)
{
return false;
}
string discoveryLink = GetDiscoveryLink(portal);
if (string.IsNullOrWhiteSpace(discoveryLink))
{
return false;
}
if (Instance.discoveryAdminBypass && Instance.isAdmin)
{
return false;
}
switch (discoveryRole)
{
case 2:
if (!Instance.IsDiscoveryUnlocked(discoveryLink))
{
Instance.UnlockDiscoveryLink(discoveryLink, portal);
Instance.ShowMessage(Instance.discoveryUnlockMessage);
}
return false;
case 1:
if (!Instance.IsDiscoveryUnlocked(discoveryLink))
{
Instance.ShowMessage(Instance.discoveryLockedMessage);
Instance.RequestUnlockList();
return true;
}
break;
}
return false;
}
private static bool ShouldBlockBlankPortalUse(TeleportWorld portal)
{
if ((Object)(object)Instance == (Object)null || (Object)(object)portal == (Object)null)
{
return false;
}
if (string.IsNullOrWhiteSpace(GetPortalTag(portal)))
{
Instance.ShowMessage("Set a portal tag first.");
return true;
}
return false;
}
internal static bool WouldExceedPortalLimit(Piece piece)
{
PortalLimitClientPlugin instance = Instance;
if ((Object)(object)instance == (Object)null || (Object)(object)piece == (Object)null || !instance.IsLimitedPortal(piece))
{
return false;
}
if (instance.maxPortalsPerPlayer <= 0)
{
return false;
}
if (instance.adminBypass && instance.isAdmin)
{
return false;
}
long localPlayerId = GetLocalPlayerId();
int num = instance.CountPortals(localPlayerId);
return num >= instance.maxPortalsPerPlayer;
}
private bool IsLimitedPortal(Piece piece)
{
if ((Object)(object)piece == (Object)null || (Object)(object)((Component)piece).GetComponent() == (Object)null)
{
return false;
}
HashSet portalPrefabNameSet = GetPortalPrefabNameSet();
if (portalPrefabNameSet.Count == 0)
{
return true;
}
ZNetView component = ((Component)piece).GetComponent();
string prefabName = GetPrefabName(component, piece);
return portalPrefabNameSet.Contains(prefabName);
}
private void ReportPortalMetadata(Piece piece, string action)
{
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)piece == (Object)null) && IsLimitedPortal(piece) && ZRoutedRpc.instance != null)
{
ZNetView component = ((Component)piece).GetComponent();
ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
if (val != null)
{
Vector3 position = ((Component)piece).transform.position;
string text = "action=" + Escape(action) + "\nportalId=" + Escape(((object)(ZDOID)(ref val.m_uid)).ToString()) + "\nplayerId=" + GetLocalPlayerId() + "\nplayerName=" + Escape(GetPlayerName()) + "\nx=" + position.x.ToString("F1") + "\ny=" + position.y.ToString("F1") + "\nz=" + position.z.ToString("F1");
ZRoutedRpc.instance.InvokeRoutedRPC("keith.valheim.portallimit.portal_metadata_update", new object[1] { text });
}
}
}
private void ReportPortalMetadata(TeleportWorld portal, string action)
{
if (!((Object)(object)portal == (Object)null))
{
Piece val = ((Component)portal).GetComponent();
if ((Object)(object)val == (Object)null)
{
val = ((Component)portal).GetComponentInParent();
}
ReportPortalMetadata(val, action);
}
}
private static string GetPrefabName(ZNetView nview, Piece piece)
{
if ((Object)(object)nview != (Object)null && GetPrefabNameMethod != null)
{
object obj = GetPrefabNameMethod.Invoke(nview, null);
if (obj != null)
{
return obj.ToString();
}
}
return ((Object)(object)piece != (Object)null) ? ((Object)piece).name.Replace("(Clone)", string.Empty) : string.Empty;
}
private int CountPortals(long creatorId)
{
if (creatorId == 0 || AllPiecesField == null)
{
return serverPortalCount;
}
int num = 0;
if (!(AllPiecesField.GetValue(null) is IEnumerable enumerable))
{
return serverPortalCount;
}
foreach (object item in enumerable)
{
Piece val = (Piece)((item is Piece) ? item : null);
if ((Object)(object)val != (Object)null && val.GetCreator() == creatorId && IsLimitedPortal(val))
{
num++;
}
}
return num;
}
private HashSet GetPortalPrefabNameSet()
{
HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase);
string[] array = portalPrefabNames.Split(new char[1] { ',' });
foreach (string text in array)
{
string text2 = text.Trim();
if (!string.IsNullOrWhiteSpace(text2))
{
hashSet.Add(text2);
}
}
return hashSet;
}
private static long GetLocalPlayerId()
{
try
{
if ((Object)(object)Player.m_localPlayer != (Object)null && GetPlayerIdMethod != null)
{
object obj = GetPlayerIdMethod.Invoke(Player.m_localPlayer, null);
if (obj != null && obj.GetType() == typeof(long))
{
return (long)obj;
}
}
}
catch (Exception ex)
{
Log.LogWarning((object)("Could not read local player ID: " + ex.Message));
}
return 0L;
}
private static string GetPlayerName()
{
return ((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerName() : "unknown-player";
}
internal void ShowMessage(string message)
{
if ((Object)(object)MessageHud.instance != (Object)null)
{
MessageHud.instance.ShowMessage((MessageType)1, message, 0, (Sprite)null, false);
}
else
{
Log.LogMessage((object)message);
}
}
private static Dictionary ParsePayload(string payload)
{
Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase);
if (string.IsNullOrEmpty(payload))
{
return dictionary;
}
string[] array = payload.Split(new char[1] { '\n' });
foreach (string text in array)
{
int num = text.IndexOf('=');
if (num > 0)
{
dictionary[text.Substring(0, num)] = Unescape(text.Substring(num + 1));
}
}
return dictionary;
}
private static string Escape(string value)
{
return (value ?? string.Empty).Replace("\\", "\\\\").Replace("\n", "\\n").Replace("=", "\\e");
}
private static string Unescape(string value)
{
return (value ?? string.Empty).Replace("\\e", "=").Replace("\\n", "\n").Replace("\\\\", "\\");
}
}