Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of PortalStation v0.3.2
PortalStation.dll
Decompiled 20 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("PortalStation")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Portal Station — craftable portal hub sign board for Valheim.")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+c1859b102a41ac22c17580ef9940316ec102c0c5")] [assembly: AssemblyProduct("PortalStation")] [assembly: AssemblyTitle("PortalStation")] [assembly: AssemblyVersion("0.1.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace PortalStation { public sealed class PortalNameSign : MonoBehaviour, Interactable, Hoverable, TextReceiver { private TeleportWorld _portal; private StationSignVisual _visual; private bool _rpcRegistered; internal void Bind(TeleportWorld portal) { _portal = portal; _visual = ((Component)this).GetComponent<StationSignVisual>(); RegisterRpc(); RefreshFromPortal(); } public string GetHoverName() { return "Sign"; } public string GetHoverText() { string text = PortalTextHelper.StripRichText(GetStoredDisplayText()); if (string.IsNullOrWhiteSpace(text)) { text = "..."; } return Localization.instance.Localize("\"" + text + "\"\n$piece_portal_station_sign\n[<color=yellow><b>$KEY_Use</b></color>] $piece_use"); } public bool Interact(Humanoid user, bool hold, bool alt) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (hold || (Object)(object)_portal == (Object)null) { return false; } if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false)) { return false; } TextInput.instance.RequestText((TextReceiver)(object)this, "$piece_sign_input", PortalTextHelper.DisplayNameMaxLength); return true; } public bool UseItem(Humanoid user, ItemData item) { return false; } public string GetText() { return GetStoredDisplayText(); } public void SetText(string text) { if (!((Object)(object)_portal == (Object)null)) { text = PortalTextHelper.ClampDisplayName(text?.Trim() ?? string.Empty); ZNetView component = ((Component)_portal).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid() && (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { ApplyDisplayText(text); } else if ((Object)(object)component != (Object)null && component.IsValid()) { component.InvokeRPC("portal_station.portal_sign", new object[1] { text }); } } } internal void RefreshFromPortal() { if (!((Object)(object)_portal == (Object)null) && !((Object)(object)_visual == (Object)null)) { string text = GetStoredDisplayText(); if (string.IsNullOrWhiteSpace(PortalTextHelper.StripRichText(text))) { text = "..."; } _visual.SetDisplayText(PortalTextHelper.FormatDisplayForRender(text)); } } internal void SetDisplayText(string displayText) { _visual?.SetDisplayText(displayText); } private string GetStoredDisplayText() { return PortalTagHelper.GetPortalDisplayText(_portal); } private void RegisterRpc() { if (!_rpcRegistered && !((Object)(object)_portal == (Object)null)) { ZNetView component = ((Component)_portal).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null)) { component.Register<string>("portal_station.portal_sign", (Action<long, string>)RPC_ApplyPortalSignText); _rpcRegistered = true; } } } private void ApplyDisplayText(string displayText) { if (!PortalTagHelper.TrySetPortalDisplay(_portal, displayText, out var error)) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, error ?? "Could not update sign.", 0, (Sprite)null); } } else { PortalStationBoard[] array = Object.FindObjectsByType<PortalStationBoard>((FindObjectsSortMode)0); for (int i = 0; i < array.Length; i++) { array[i].RefreshSigns(); } } } private void RPC_ApplyPortalSignText(long sender, string text) { if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && (text == null || text.Length <= PortalTextHelper.DisplayNameMaxLength)) { ApplyDisplayText(text?.Trim() ?? string.Empty); } } } internal sealed class PortalSignInitRunner : MonoBehaviour { private void Start() { PortalDisplaySignSpawner.EnsureDisplaySign(((Component)this).gameObject); Object.Destroy((Object)(object)this); } } public sealed class PortalStationBoard : MonoBehaviour { private ZNetView _nview; private StationHeaderSign _headerSign; private readonly StationDestinationSign[] _destinationSigns = new StationDestinationSign[18]; private bool _initialized; private bool _rpcRegistered; private void Awake() { _nview = ((Component)this).GetComponent<ZNetView>(); _headerSign = ((Component)this).GetComponentInChildren<StationHeaderSign>(true); RegisterDestinationSigns(); if (StationInstanceHelper.IsPlacedInstance(((Component)this).gameObject)) { TryRegisterRpcs(); } } private void Start() { if (StationInstanceHelper.IsPlacedInstance(((Component)this).gameObject)) { TryRegisterRpcs(); Initialize(); StationInteractionColliders.Enable(((Component)this).gameObject); RefreshSigns(); } } public void BindChildSigns(StationHeaderSign header, StationDestinationSign[] destinations) { _headerSign = header; for (int i = 0; i < destinations.Length && i < 18; i++) { _destinationSigns[i] = destinations[i]; } } internal void TryRegisterRpcs() { if (StationInstanceHelper.IsPlacedInstance(((Component)this).gameObject)) { _nview = ((Component)this).GetComponent<ZNetView>(); if (!_rpcRegistered && !((Object)(object)_nview == (Object)null) && _nview.IsValid()) { _nview.Register<string, string, string>("portal_station.apply_config", (Action<long, string, string, string>)RPC_ApplyStationConfig); _nview.Register<int>("portal_station.activate_destination", (Action<long, int>)RPC_ActivateDestination); _rpcRegistered = true; } } } private void Initialize() { if (!_initialized) { _initialized = true; RegisterDestinationSigns(); _headerSign?.Bind(this); for (int i = 0; i < 18; i++) { _destinationSigns[i]?.Bind(this, i); } } } private void RegisterDestinationSigns() { for (int i = 0; i < 18; i++) { _destinationSigns[i] = null; } StationDestinationSign[] componentsInChildren = ((Component)this).GetComponentsInChildren<StationDestinationSign>(true); foreach (StationDestinationSign stationDestinationSign in componentsInChildren) { int num = stationDestinationSign.ResolveSlotIndex(); if (num >= 0 && num < 18) { _destinationSigns[num] = stationDestinationSign; } } } public string GetStationName() { ZNetView nview = _nview; object obj; if (nview == null) { obj = null; } else { ZDO zDO = nview.GetZDO(); obj = ((zDO != null) ? zDO.GetString("PortalStation_StationName", string.Empty) : null); } if (obj == null) { obj = string.Empty; } return (string)obj; } public string GetSlotPortalName(int index) { if (index < 0 || index >= 18) { return string.Empty; } ZNetView nview = _nview; object obj; if (nview == null) { obj = null; } else { ZDO zDO = nview.GetZDO(); obj = ((zDO != null) ? zDO.GetString(ModConstants.SlotPortalKey(index), string.Empty) : null); } if (obj == null) { obj = string.Empty; } return (string)obj; } public string GetSlotDisplayRaw(int index) { if (index < 0 || index >= 18) { return string.Empty; } ZNetView nview = _nview; object obj; if (nview == null) { obj = null; } else { ZDO zDO = nview.GetZDO(); obj = ((zDO != null) ? zDO.GetString(ModConstants.SlotDisplayKey(index), string.Empty) : null); } if (obj == null) { obj = string.Empty; } return (string)obj; } public string GetSlotBoardText(int index) { string slotDisplayRaw = GetSlotDisplayRaw(index); if (!string.IsNullOrWhiteSpace(PortalTextHelper.StripRichText(slotDisplayRaw))) { return slotDisplayRaw; } return GetSlotPortalName(index); } public string GetSlotDisplayText(int index) { return PortalTextHelper.BuildDisplayText(GetSlotPortalName(index), GetSlotDisplayRaw(index)); } public TeleportWorld GetLinkedPortal() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) ZNetView nview = _nview; object obj; if (nview == null) { obj = null; } else { ZDO zDO = nview.GetZDO(); obj = ((zDO != null) ? zDO.GetString("PortalStation_LinkedPortal", string.Empty) : null); } string value = (string)obj; if (string.IsNullOrEmpty(value) || !TryParseZdoId(value, out var zdoId)) { return null; } ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.FindInstance(zdoId) : null); if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<TeleportWorld>(); } public string GetLinkedPortalTag() { return PortalTagHelper.GetPortalTag(GetLinkedPortal()); } public void ActivateDestination(int slotIndex) { if (!((Object)(object)_nview == (Object)null) && _nview.IsValid()) { if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { ServerActivateDestination(slotIndex); return; } _nview.InvokeRPC("portal_station.activate_destination", new object[1] { slotIndex }); } } public void OpenConfiguration() { StationConfigUI.Instance?.Open(this); } public bool TryApplyConfiguration(string stationName, string[] portalNames, string[] displayNames, out string message) { message = string.Empty; _nview = ((Component)this).GetComponent<ZNetView>(); TryRegisterRpcs(); if ((Object)(object)_nview == (Object)null || !_nview.IsValid()) { message = "Station is not ready yet. Try again in a moment."; return false; } string text = EncodeSlots(portalNames); string text2 = EncodeSlots(displayNames); if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { return ServerApplyConfiguration(stationName, text, text2, out message); } _nview.InvokeRPC("portal_station.apply_config", new object[3] { stationName, text, text2 }); RefreshSigns(); message = "Configuration sent to server."; return true; } public void RefreshSigns() { StationSignVisual obj = (((Object)(object)_headerSign != (Object)null) ? ((Component)_headerSign).GetComponent<StationSignVisual>() : null); string displayText = (string.IsNullOrWhiteSpace(GetStationName()) ? "..." : GetStationName()); obj?.SetDisplayText(PortalTextHelper.FormatDisplayForRender(displayText)); for (int i = 0; i < 18; i++) { _destinationSigns[i]?.RefreshFromStation(); } } private void RPC_ApplyStationConfig(long sender, string stationName, string portalPayload, string displayPayload) { if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer()) { ServerApplyConfiguration(stationName, portalPayload, displayPayload, out var _); } } private void RPC_ActivateDestination(long sender, int slotIndex) { if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer()) { ServerActivateDestination(slotIndex); } } private bool ServerApplyConfiguration(string stationName, string portalPayload, string displayPayload, out string message) { //IL_00ed: Unknown result type (might be due to invalid IL or missing references) message = string.Empty; string[] array = DecodeSlots(portalPayload); string[] array2 = DecodeSlots(displayPayload); for (int i = 0; i < 18; i++) { array[i] = PortalTextHelper.ClampPortalName(array[i]); array2[i] = PortalTextHelper.ClampDisplayName(array2[i]); } List<PortalStationBoard> linkedGroup = StationGroupHelper.GetLinkedGroup(this, stationName); if (!StationGroupHelper.TryCollectPortalNames(linkedGroup, this, array, out var duplicateName)) { message = "Duplicate portal name \"" + duplicateName + "\" across linked stations."; NotifyPlayer(message); return false; } ZDO zDO = _nview.GetZDO(); zDO.Set("PortalStation_StationName", stationName?.Trim() ?? string.Empty); for (int j = 0; j < 18; j++) { zDO.Set(ModConstants.SlotPortalKey(j), array[j] ?? string.Empty); zDO.Set(ModConstants.SlotDisplayKey(j), array2[j] ?? string.Empty); } TeleportWorld val = StationGroupHelper.FindNearestPortal(((Component)this).transform.position, 15f); if ((Object)(object)val != (Object)null) { ZNetView component = ((Component)val).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid()) { zDO.Set("PortalStation_LinkedPortal", ((object)Unsafe.As<ZDOID, ZDOID>(ref component.GetZDO().m_uid)/*cast due to .constrained prefix*/).ToString()); } message = "Station configuration saved and linked to nearby portal."; } else { message = "Names saved. Build a portal within 15 m to enable teleport linking."; } RefreshSigns(); RefreshAllLinkedStations(linkedGroup); NotifyPlayer(message); return true; } private void ServerActivateDestination(int slotIndex) { if (slotIndex < 0 || slotIndex >= 18) { return; } TeleportWorld val = ResolveLinkedPortal(); if ((Object)(object)val == (Object)null) { NotifyPlayer("No linked portal found within 15 m."); return; } string slotPortalName = GetSlotPortalName(slotIndex); if (string.IsNullOrWhiteSpace(PortalTextHelper.StripRichText(slotPortalName))) { if (!PortalTagHelper.TryClearPortal(val, out var error)) { NotifyPlayer(error ?? "Could not clear portal name."); return; } RefreshSigns(); RefreshAllLinkedStations(); NotifyPlayer("Portal name cleared (unnamed pairing)."); return; } string displayText = _nview.GetZDO().GetString(ModConstants.SlotDisplayKey(slotIndex), string.Empty); if (!PortalTagHelper.TrySetPortalTagAndDisplay(val, slotPortalName, displayText, out var error2)) { NotifyPlayer(error2 ?? "Could not update portal."); return; } RefreshSigns(); RefreshAllLinkedStations(); NotifyPlayer("Portal set to \"" + PortalTextHelper.StripRichText(GetSlotDisplayText(slotIndex)) + "\"."); } private TeleportWorld ResolveLinkedPortal() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) TeleportWorld linkedPortal = GetLinkedPortal(); if ((Object)(object)linkedPortal != (Object)null) { return linkedPortal; } linkedPortal = StationGroupHelper.FindNearestPortal(((Component)this).transform.position, 15f); if ((Object)(object)linkedPortal == (Object)null) { return null; } ZNetView component = ((Component)linkedPortal).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid()) { _nview.GetZDO().Set("PortalStation_LinkedPortal", ((object)Unsafe.As<ZDOID, ZDOID>(ref component.GetZDO().m_uid)/*cast due to .constrained prefix*/).ToString()); } return linkedPortal; } private static void RefreshAllLinkedStations(IEnumerable<PortalStationBoard> stations = null) { if (stations != null) { foreach (PortalStationBoard station in stations) { station?.RefreshSigns(); } return; } PortalStationBoard[] array = Object.FindObjectsByType<PortalStationBoard>((FindObjectsSortMode)0); for (int i = 0; i < array.Length; i++) { array[i].RefreshSigns(); } } private static bool TryParseZdoId(string value, out ZDOID zdoId) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) zdoId = ZDOID.None; if (string.IsNullOrEmpty(value)) { return false; } string[] array = value.Split(new char[1] { ':' }); if (array.Length != 2) { return false; } if (!long.TryParse(array[0], out var result)) { return false; } if (!uint.TryParse(array[1], out var result2)) { return false; } zdoId = new ZDOID(result, result2); return true; } private static string EncodeSlots(string[] values) { if (values == null) { return string.Empty; } StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < 18; i++) { if (i > 0) { stringBuilder.Append('\n'); } stringBuilder.Append((values.Length > i) ? (values[i] ?? string.Empty) : string.Empty); } return stringBuilder.ToString(); } private static string[] DecodeSlots(string payload) { string[] array = new string[18]; if (string.IsNullOrEmpty(payload)) { return array; } string[] array2 = payload.Split(new char[1] { '\n' }); for (int i = 0; i < 18 && i < array2.Length; i++) { array[i] = array2[i]; } return array; } private static void NotifyPlayer(string message) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, message, 0, (Sprite)null); } } } public sealed class StationDestinationSign : MonoBehaviour, Hoverable { private const string SlotNamePrefix = "_station_slot_"; private PortalStationBoard _station; [SerializeField] private int _slotIndex = -1; private StationSignVisual _visual; public int SlotIndex => ResolveSlotIndex(); internal void Bind(PortalStationBoard station, int slotIndex) { _station = station; _slotIndex = slotIndex; _visual = ((Component)this).GetComponent<StationSignVisual>(); } internal void SetSlotIndex(int slotIndex) { _slotIndex = slotIndex; } internal int ResolveSlotIndex() { if (_slotIndex >= 0 && _slotIndex < 18) { return _slotIndex; } if (((Object)this).name.StartsWith("_station_slot_") && int.TryParse(((Object)this).name.Substring("_station_slot_".Length), out var result) && result >= 0 && result < 18) { _slotIndex = result; return _slotIndex; } return _slotIndex; } internal void RefreshFromStation() { if (!((Object)(object)_station == (Object)null) && !((Object)(object)_visual == (Object)null)) { int index = ResolveSlotIndex(); string text = _station.GetSlotBoardText(index); if (string.IsNullOrWhiteSpace(PortalTextHelper.StripRichText(text))) { text = "..."; } _visual.SetDisplayText(PortalTextHelper.FormatDisplayForRender(text)); string linkedPortalTag = _station.GetLinkedPortalTag(); string slotPortalName = _station.GetSlotPortalName(index); bool highlighted = (string.IsNullOrWhiteSpace(PortalTextHelper.StripRichText(slotPortalName)) ? string.IsNullOrWhiteSpace(linkedPortalTag) : PortalTextHelper.PortalNamesEqual(slotPortalName, linkedPortalTag)); _visual.SetHighlighted(highlighted); } } public string GetHoverName() { return "$piece_portal_station_destination"; } public string GetHoverText() { int index = ResolveSlotIndex(); if (string.IsNullOrWhiteSpace(PortalTextHelper.StripRichText(((Object)(object)_station != (Object)null) ? _station.GetSlotPortalName(index) : string.Empty))) { return Localization.instance.Localize("$piece_portal_station_destination_empty\n[<color=yellow><b>$KEY_Attack</b></color>] $piece_portal_station_clear"); } string text = PortalTextHelper.StripRichText(_station.GetSlotBoardText(index)); return "\"" + text + "\"\n" + Localization.instance.Localize("$piece_portal_station_destination\n[<color=yellow><b>$KEY_Attack</b></color>] $piece_portal_station_activate"); } internal void TryActivate() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_station == (Object)null) && PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false)) { _station.ActivateDestination(ResolveSlotIndex()); } } } public sealed class StationHeaderSign : MonoBehaviour, Interactable, Hoverable { private PortalStationBoard _station; internal void Bind(PortalStationBoard station) { _station = station; } public string GetHoverName() { return "$piece_portal_station_header"; } public string GetHoverText() { string text = (((Object)(object)_station != (Object)null) ? _station.GetStationName() : string.Empty); if (string.IsNullOrWhiteSpace(text)) { text = "..."; } return "\"" + text + "\"\n" + Localization.instance.Localize("$piece_portal_station_header\n[<color=yellow><b>$KEY_Use</b></color>] $piece_portal_station_configure"); } public bool Interact(Humanoid user, bool hold, bool alt) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (hold || (Object)(object)_station == (Object)null) { return false; } if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false)) { return false; } _station.OpenConfiguration(); return true; } public bool UseItem(Humanoid user, ItemData item) { return false; } } public sealed class StationSignVisual : MonoBehaviour { private TextMeshProUGUI _text; private Color _defaultColor = Color.white; private void Awake() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) _text = ((Component)this).GetComponentInChildren<TextMeshProUGUI>(true); if ((Object)(object)_text != (Object)null) { _defaultColor = ((Graphic)_text).color; ((TMP_Text)_text).richText = true; ((TMP_Text)_text).text = "..."; } } public void SetDisplayText(string text) { if ((Object)(object)_text != (Object)null) { ((TMP_Text)_text).text = text ?? string.Empty; } } public void SetHighlighted(bool highlighted) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_text == (Object)null)) { ((Graphic)_text).color = ((highlighted && PortalTextHelper.TryGetHighlightColor(out var color)) ? color : _defaultColor); } } } public static class ModConfig { public const string DefaultHighlightColorValue = "<#87CEEB>"; public static ConfigEntry<int> DisplayNameMaxLength; public static ConfigEntry<int> CraftCostWood; public static ConfigEntry<int> CraftCostCoal; public static ConfigEntry<string> DefaultPortalDescription; public static ConfigEntry<string> DefaultHighlightColor; public static void Bind(ConfigFile config) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown DisplayNameMaxLength = config.Bind<int>("PortalStation", "DisplayNameMaxLength", 50, new ConfigDescription("DISPLAY TEXT ONLY — does not change the portal tag/name used for pairing (still max 10 plain characters via E on the portal). This limit applies only to sign display descriptions (station slots and E on the portal sign). Very high values will drastically shrink text size on signs.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 200), Array.Empty<object>())); CraftCostWood = config.Bind<int>("PortalStation", "CraftCostWood", 58, new ConfigDescription("Wood required to build a Portal Station.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 999), Array.Empty<object>())); CraftCostCoal = config.Bind<int>("PortalStation", "CraftCostCoal", 19, new ConfigDescription("Coal required to build a Portal Station.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 999), Array.Empty<object>())); DefaultPortalDescription = config.Bind<string>("PortalStation", "DefaultPortalDescription", string.Empty, new ConfigDescription("Default color prefix for sign display text when no color code is set (e.g. <#FFD700>). Leave empty for none. Override per sign by adding a color code before the display name.", (AcceptableValueBase)null, Array.Empty<object>())); DefaultHighlightColor = config.Bind<string>("PortalStation", "DefaultHighlightColor", "<#87CEEB>", new ConfigDescription("Color for the active destination sign on a station (e.g. <#87CEEB> or <color=cyan>).", (AcceptableValueBase)null, Array.Empty<object>())); } } public static class ModConstants { public const string ModName = "Portal Station"; public const string ModVersion = "0.3.2"; public const string ModGuid = "com.portalstation"; public const string BuildLabel = "v0.3.2"; public const string ConfigSection = "PortalStation"; public const string PrefabStation = "portal_station"; public const string LegacyPrefabStation = "runic_portal_station"; public const float StationVisualScale = 0.75f; public const float StationHeaderSignForwardOffset = 0.1f; public const float StationDestinationSignForwardOffset = 0.37f; public const float StationSignFaceEpsilon = 0.02f; public const int DestinationSlotCount = 18; public const int GridColumns = 3; public const int GridRows = 6; public const int PortalNameMaxLength = 10; public const int DefaultDisplayNameMaxLength = 50; public const int DefaultCraftCostWood = 58; public const int DefaultCraftCostCoal = 19; public const float PortalLinkRadius = 15f; public const float StationGroupRadius = 10f; public const string ZdoStationName = "PortalStation_StationName"; public const string ZdoLinkedPortal = "PortalStation_LinkedPortal"; public const string ZdoDisplayText = "PortalStation_DisplayText"; public const string ZdoPortalTag = "tag"; public const string ZdoStationLinked = "PortalStation_StationLinked"; public const string RpcApplyStationConfig = "portal_station.apply_config"; public const string RpcActivateDestination = "portal_station.activate_destination"; public const string RpcPortalSignText = "portal_station.portal_sign"; public static string SlotPortalKey(int index) { return $"PortalStation_Slot{index}_Portal"; } public static string SlotDisplayKey(int index) { return $"PortalStation_Slot{index}_Display"; } } internal static class ModLocalization { private static bool registered; private static readonly FieldRef<Localization, Dictionary<string, string>> TranslationsField = AccessTools.FieldRefAccess<Localization, Dictionary<string, string>>("m_translations"); internal static void Register() { if (!registered && Localization.instance != null) { Dictionary<string, string> dictionary = TranslationsField.Invoke(Localization.instance); if (dictionary != null) { registered = true; dictionary["piece_portal_station"] = "Portal Station"; dictionary["piece_portal_station_desc"] = "A sign board that quickly retargets a nearby portal. Configure station and destination names, then click a sign to switch the linked portal."; dictionary["piece_portal_station_header"] = "Station Nameplate"; dictionary["piece_portal_station_configure"] = "Configure station"; dictionary["piece_portal_station_configure_title"] = "Portal Station Configuration"; dictionary["piece_portal_station_name_label"] = "Station name"; dictionary["piece_portal_station_slots_help"] = "Portal name (max 10, used for pairing) and optional display text (color codes allowed). Linked stations with the same name within 10 m share one destination list."; dictionary["piece_portal_station_cancel"] = "Cancel"; dictionary["piece_portal_station_commit"] = "Commit"; dictionary["piece_portal_station_destination"] = "Destination Sign"; dictionary["piece_portal_station_destination_empty"] = "Empty destination slot"; dictionary["piece_portal_station_activate"] = "Activate destination"; dictionary["piece_portal_station_clear"] = "Clear portal name"; dictionary["piece_portal_station_sign"] = "Sign"; } } } } [HarmonyPatch(typeof(FejdStartup), "SetupGui")] internal static class FejdStartupSetupGuiPatch { private static void Postfix() { ModLocalization.Register(); } } [HarmonyPatch(typeof(WearNTear), "OnPlaced")] internal static class PortalPlacementPatch { private static void Postfix(WearNTear __instance) { if (!((Object)(object)__instance == (Object)null)) { PortalDisplaySignSpawner.EnsureDisplaySign(((Component)__instance).gameObject); } } } [HarmonyPatch(typeof(TeleportWorld), "Awake")] internal static class PortalAwakeSignPatch { private static void Postfix(TeleportWorld __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)((Component)__instance).GetComponent<PortalSignInitRunner>() != (Object)null)) { ((Component)__instance).gameObject.AddComponent<PortalSignInitRunner>(); } } } [HarmonyPatch(typeof(TeleportWorld), "SetText")] internal static class PortalSetTextPatch { private static void Postfix(TeleportWorld __instance) { if (!((Object)(object)__instance == (Object)null)) { PortalTagHelper.RefreshPortalSign(__instance); } } } [HarmonyPatch(typeof(Player), "Update")] internal static class DestinationActivatePatch { private static void Postfix(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !StationConfigUI.IsOpen && ZInput.GetButtonDown("Attack") && !((Character)__instance).InAttack() && !((Character)__instance).InMinorAction() && StationDestinationInputHelper.IsHoveringDestinationSign(__instance)) { GameObject hoverObject = ((Humanoid)__instance).GetHoverObject(); (hoverObject.GetComponent<StationDestinationSign>() ?? hoverObject.GetComponentInParent<StationDestinationSign>())?.TryActivate(); } } } [HarmonyPatch(typeof(Player), "SetControls")] internal static class PlayerSetControlsDestinationPatch { private static void Prefix(ref bool attack, ref bool attackHold, ref bool secondaryAttack, ref bool secondaryAttackHold) { if (StationDestinationInputHelper.IsHoveringDestinationSign(Player.m_localPlayer)) { attack = false; attackHold = false; secondaryAttack = false; secondaryAttackHold = false; } } } [HarmonyPatch(typeof(Player), "PlayerAttackInput")] internal static class PlayerAttackInputDestinationPatch { private static bool Prefix() { return !StationDestinationInputHelper.IsHoveringDestinationSign(Player.m_localPlayer); } } [HarmonyPatch(typeof(Player), "TakeInput")] internal static class PlayerTakeInputStationConfigPatch { private static void Postfix(ref bool __result) { if (StationConfigUI.IsOpen) { __result = false; } } } [HarmonyPatch(typeof(PlayerController), "TakeInput", new Type[] { typeof(bool) })] internal static class PlayerControllerTakeInputStationConfigPatch { private static void Postfix(ref bool __result) { if (StationConfigUI.IsOpen) { __result = false; } } } [HarmonyPatch(typeof(Player), "SetControls")] internal static class PlayerSetControlsStationConfigPatch { private static bool Prefix(ref Vector3 movedir, ref bool attack, ref bool attackHold, ref bool secondaryAttack, ref bool secondaryAttackHold, ref bool block, ref bool blockHold, ref bool jump, ref bool crouch, ref bool run, ref bool autoRun, ref bool dodge) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (!StationConfigUI.IsOpen) { return true; } movedir = Vector3.zero; attack = false; attackHold = false; secondaryAttack = false; secondaryAttackHold = false; block = false; blockHold = false; jump = false; crouch = false; run = false; autoRun = false; dodge = false; return true; } } [HarmonyPatch(typeof(Player), "PlayerAttackInput")] internal static class PlayerAttackInputStationConfigPatch { private static bool Prefix() { return !StationConfigUI.IsOpen; } } [HarmonyPatch(typeof(Minimap), "Update")] internal static class MinimapStationConfigPatch { private static bool Prefix() { return !StationConfigUI.IsOpen; } } [HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")] internal static class GameCameraMouseCaptureStationConfigPatch { private static bool Prefix() { if (!StationConfigUI.IsOpen) { return true; } Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; return false; } } [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] internal static class GameCameraUpdateStationConfigPatch { private static bool Prefix() { return !StationConfigUI.IsOpen; } } [HarmonyPatch] internal static class StationConfigZInputPatch { private static bool Block => StationConfigUI.IsOpen; [HarmonyPrefix] [HarmonyPatch(typeof(ZInput), "GetButtonDown", new Type[] { typeof(string) })] private static bool BlockGetButtonDown(string name, ref bool __result) { if (!Block) { return true; } __result = false; return false; } [HarmonyPrefix] [HarmonyPatch(typeof(ZInput), "GetButton", new Type[] { typeof(string) })] private static bool BlockGetButton(string name, ref bool __result) { if (!Block) { return true; } __result = false; return false; } [HarmonyPrefix] [HarmonyPatch(typeof(ZInput), "GetButtonUp", new Type[] { typeof(string) })] private static bool BlockGetButtonUp(string name, ref bool __result) { if (!Block) { return true; } __result = false; return false; } [HarmonyPrefix] [HarmonyPatch(typeof(ZInput), "GetKeyDown", new Type[] { typeof(KeyCode), typeof(bool) })] private static bool BlockGetKeyDown(KeyCode key, bool logWarning, ref bool __result) { if (!Block) { return true; } __result = false; return false; } [HarmonyPrefix] [HarmonyPatch(typeof(ZInput), "GetKey", new Type[] { typeof(KeyCode), typeof(bool) })] private static bool BlockGetKey(KeyCode key, bool logWarning, ref bool __result) { if (!Block) { return true; } __result = false; return false; } [HarmonyPrefix] [HarmonyPatch(typeof(ZInput), "GetKeyUp", new Type[] { typeof(KeyCode), typeof(bool) })] private static bool BlockGetKeyUp(KeyCode key, bool logWarning, ref bool __result) { if (!Block) { return true; } __result = false; return false; } } [BepInPlugin("com.portalstation", "Portal Station", "0.3.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class PortalStationPlugin : BaseUnityPlugin { internal static ManualLogSource Log; private Harmony harmony; private void Awake() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; harmony = new Harmony("com.portalstation"); try { harmony.PatchAll(typeof(PortalStationPlugin).Assembly); Log.LogInfo((object)$"Harmony applied {harmony.GetPatchedMethods().Count()} patch(es)."); } catch (Exception arg) { Log.LogError((object)$"Harmony PatchAll failed: {arg}"); } ModConfig.Bind(((BaseUnityPlugin)this).Config); StationRegistrar.Init(); if ((Object)(object)((Component)this).GetComponent<StationConfigUI>() == (Object)null) { ((Component)this).gameObject.AddComponent<StationConfigUI>(); } Log.LogInfo((object)"Portal Station 0.3.2 (v0.3.2) loaded."); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } } internal static class NetworkPrefabHelper { internal static void RunWithoutZdoCreation(Action action) { bool forceDisableInit = ZNetView.m_forceDisableInit; ZNetView.m_forceDisableInit = true; try { action(); } finally { ZNetView.m_forceDisableInit = forceDisableInit; } } internal static T RunWithoutZdoCreation<T>(Func<T> factory) { bool forceDisableInit = ZNetView.m_forceDisableInit; ZNetView.m_forceDisableInit = true; try { return factory(); } finally { ZNetView.m_forceDisableInit = forceDisableInit; } } } internal static class PortalDisplaySignSpawner { private const float PortalSignLocalY = 3.1f; private const float PortalSignLocalZ = -0.1f; internal static void EnsureDisplaySign(GameObject portalObject) { //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)portalObject == (Object)null) { return; } TeleportWorld component = portalObject.GetComponent<TeleportWorld>(); if ((Object)(object)component == (Object)null || (Object)(object)portalObject.GetComponentInChildren<PortalNameSign>(true) != (Object)null || (Object)(object)ZNetScene.instance == (Object)null) { return; } GameObject source = StationVisualHelper.TryGetPrefab("sign", "piece_sign"); if (!((Object)(object)source == (Object)null)) { GameObject obj = NetworkPrefabHelper.RunWithoutZdoCreation(() => Object.Instantiate<GameObject>(source)); obj.SetActive(false); ((Object)obj).name = "_portal_display_sign"; StripSign(obj); EnsureInteractionCollider(obj); obj.transform.SetParent(portalObject.transform, false); obj.transform.localPosition = new Vector3(0f, 3.1f, -0.1f); obj.transform.localRotation = Quaternion.identity; obj.transform.localScale = Vector3.one; obj.AddComponent<StationSignVisual>(); PortalNameSign portalNameSign = obj.AddComponent<PortalNameSign>(); obj.SetActive(true); portalNameSign.Bind(component); } } internal static void StripSign(GameObject signObject) { if (!((Object)(object)signObject == (Object)null)) { Sign component = signObject.GetComponent<Sign>(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } ZNetView[] componentsInChildren = signObject.GetComponentsInChildren<ZNetView>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } Piece component2 = signObject.GetComponent<Piece>(); if ((Object)(object)component2 != (Object)null) { Object.DestroyImmediate((Object)(object)component2); } WearNTear component3 = signObject.GetComponent<WearNTear>(); if ((Object)(object)component3 != (Object)null) { Object.DestroyImmediate((Object)(object)component3); } ItemDrop component4 = signObject.GetComponent<ItemDrop>(); if ((Object)(object)component4 != (Object)null) { Object.DestroyImmediate((Object)(object)component4); } } } private static void EnsureInteractionCollider(GameObject signObject) { //IL_0027: 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) BoxCollider val = signObject.GetComponent<BoxCollider>(); if ((Object)(object)val == (Object)null) { val = signObject.AddComponent<BoxCollider>(); val.size = new Vector3(1.8f, 0.9f, 0.15f); val.center = new Vector3(0f, 0f, 0.08f); } ((Collider)val).enabled = true; int num = LayerMask.NameToLayer("piece"); if (num >= 0) { signObject.layer = num; } } } internal static class PrefabBuildHelper { internal static void FinalizeBuildPiece(GameObject prefab) { int num = LayerMask.NameToLayer("piece"); if (num >= 0) { prefab.layer = num; } } } internal static class StationFrameBuilder { private const float XLeft = -1.5f; private const float XRight = 1.5f; private const float ZPlane = 0f; private const float YGround = 0f; private const float YBottomBeam = 1f; private const float YSidePole2m = 1f; private const float YSidePole1m = 3f; private const float YTopBeam = 4f; private const float XQuarterCenter = 1f; internal static void BuildFrame(Transform root) { if (!((Object)(object)root == (Object)null)) { BuildLegs(root); BuildBottomBeams(root); BuildSidePosts(root); BuildTopBeams(root); } } internal static void BuildBoard(Transform root) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)root == (Object)null)) { AddWall(root, "woodwall", new Vector3(-0.5f, 1f, 0f), "piece_wood_wall"); AddWall(root, "wood_wall_half", new Vector3(-0.5f, 3f, 0f)); AddQuarter(root, new Vector3(1f, 1f, 0f)); AddQuarter(root, new Vector3(1f, 2f, 0f)); AddQuarter(root, new Vector3(1f, 3f, 0f)); } } private static void BuildLegs(Transform root) { //IL_0015: 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) AddPole(root, "wood_pole", new Vector3(-1.5f, 0f, 0f)); AddPole(root, "wood_pole", new Vector3(1.5f, 0f, 0f)); } private static void BuildBottomBeams(Transform root) { //IL_0015: 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) AddBeam(root, "wood_beam", new Vector3(-0.5f, 1f, 0f)); AddBeam(root, "wood_beam_1", new Vector3(1f, 1f, 0f)); } private static void BuildSidePosts(Transform root) { //IL_0015: 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) //IL_0053: 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) AddPole(root, "wood_pole2", new Vector3(-1.5f, 1f, 0f)); AddPole(root, "wood_pole2", new Vector3(1.5f, 1f, 0f)); AddPole(root, "wood_pole", new Vector3(-1.5f, 3f, 0f)); AddPole(root, "wood_pole", new Vector3(1.5f, 3f, 0f)); } private static void BuildTopBeams(Transform root) { //IL_0015: 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) AddBeam(root, "wood_beam_1", new Vector3(-1f, 4f, 0f)); AddBeam(root, "wood_beam", new Vector3(0.5f, 4f, 0f)); } private static void AddPole(Transform root, string prefabName, Vector3 localPosition) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) StationVisualHelper.AddVisualChild(root, prefabName, localPosition, Quaternion.identity); } private static void AddBeam(Transform root, string prefabName, Vector3 localPosition) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) StationVisualHelper.AddBeamChild(root, prefabName, localPosition); } private static void AddWall(Transform root, string prefabName, Vector3 localPosition, params string[] fallbackNames) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) StationVisualHelper.AddVisualChild(root, prefabName, localPosition, Quaternion.identity, StationPieceAnchor.BottomFrontCenter, fallbackNames); } private static void AddQuarter(Transform root, Vector3 localPosition) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) StationVisualHelper.AddVisualChild(root, "wood_wall_quarter", localPosition, Quaternion.identity, StationPieceAnchor.BottomFrontCenter); } } internal static class StationHammerIcon { private const string ResourceName = "PortalStation.Assets.Station_Icon.png"; private const string PluginIconFileName = "Station_Icon.png"; private static Sprite _cachedSprite; internal static void Apply(Piece piece) { if (!((Object)(object)piece == (Object)null)) { Sprite sprite = GetSprite(); if ((Object)(object)sprite != (Object)null) { piece.m_icon = sprite; } } } internal static Sprite GetSprite() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0079: 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) if ((Object)(object)_cachedSprite != (Object)null) { return _cachedSprite; } byte[] array = LoadIconBytes(); if (array == null || array.Length == 0) { return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!TryDecodePng(val, array)) { Object.Destroy((Object)(object)val); PortalStationPlugin.Log.LogWarning((object)"Failed to decode station hammer icon texture."); return null; } ((Texture)val).filterMode = (FilterMode)1; ((Texture)val).wrapMode = (TextureWrapMode)1; float num = ResolvePixelsPerUnit(); _cachedSprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), num); return _cachedSprite; } private static byte[] LoadIconBytes() { Assembly executingAssembly = Assembly.GetExecutingAssembly(); using Stream stream = executingAssembly.GetManifestResourceStream("PortalStation.Assets.Station_Icon.png"); if (stream != null) { byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); return array; } string directoryName = Path.GetDirectoryName(executingAssembly.Location); if (string.IsNullOrEmpty(directoryName)) { PortalStationPlugin.Log.LogWarning((object)"Station hammer icon resource not found: PortalStation.Assets.Station_Icon.png"); return null; } string text = Path.Combine(directoryName, "Station_Icon.png"); if (!File.Exists(text)) { PortalStationPlugin.Log.LogWarning((object)("Station hammer icon missing from embedded resource and plugin folder: " + text)); return null; } return File.ReadAllBytes(text); } private static bool TryDecodePng(Texture2D texture, byte[] data) { MethodInfo method = typeof(Texture2D).GetMethod("LoadImage", BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(byte[]) }, null); if (method != null) { return (bool)method.Invoke(texture, new object[1] { data }); } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (assembly.GetName().Name.StartsWith("UnityEngine.ImageConversion", StringComparison.Ordinal)) { MethodInfo methodInfo = assembly.GetType("UnityEngine.ImageConversion")?.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(Texture2D), typeof(byte[]) }, null); if (methodInfo != null) { return (bool)methodInfo.Invoke(null, new object[2] { texture, data }); } } } return false; } private static float ResolvePixelsPerUnit() { GameObject obj = StationVisualHelper.TryGetPrefab("portal", "portal_wood", "piece_portal"); Piece val = ((obj != null) ? obj.GetComponent<Piece>() : null); if (!((Object)(object)val?.m_icon != (Object)null)) { return 100f; } return val.m_icon.pixelsPerUnit; } } internal static class StationInteractionColliders { internal static void Disable(GameObject root) { SetChildColliderState(root, enabled: false); } internal static void Enable(GameObject root) { SetChildColliderState(root, enabled: true); } private static void SetChildColliderState(GameObject root, bool enabled) { if ((Object)(object)root == (Object)null) { return; } int num = LayerMask.NameToLayer("piece"); Collider[] componentsInChildren = root.GetComponentsInChildren<Collider>(true); foreach (Collider val in componentsInChildren) { if (!((Object)(object)((Component)val).gameObject == (Object)(object)root)) { val.enabled = enabled; if (enabled && num >= 0 && IsInteractionTarget(((Component)val).gameObject)) { ((Component)val).gameObject.layer = num; } } } } private static bool IsInteractionTarget(GameObject target) { if (!((Object)(object)target.GetComponent<StationHeaderSign>() != (Object)null)) { return (Object)(object)target.GetComponent<StationDestinationSign>() != (Object)null; } return true; } } internal enum StationPieceAnchor { BottomCenter, BottomLeft, BottomFrontCenter, BottomBackCenter } internal static class StationPiecePlacement { internal static Quaternion GetBeamRotationAlongX(GameObject prefab) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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_0038: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null) { return Quaternion.identity; } float num = MeasureHorizontalWidth(prefab, Quaternion.identity); if (!(MeasureHorizontalWidth(prefab, Quaternion.Euler(0f, 90f, 0f)) >= num)) { return Quaternion.identity; } return Quaternion.Euler(0f, 90f, 0f); } internal static void Place(Transform parent, GameObject piece, Vector3 targetLocalAnchor, Quaternion localRotation, StationPieceAnchor anchor) { //IL_0026: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)parent == (Object)null) && !((Object)(object)piece == (Object)null)) { piece.transform.SetParent(parent, false); piece.transform.localRotation = localRotation; piece.transform.localPosition = Vector3.zero; Vector3 anchorOffsetInParentSpace = GetAnchorOffsetInParentSpace(piece.transform, anchor); piece.transform.localPosition = targetLocalAnchor - anchorOffsetInParentSpace; } } private static float MeasureHorizontalWidth(GameObject prefab, Quaternion rotation) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) GameObject obj = NetworkPrefabHelper.RunWithoutZdoCreation(() => Object.Instantiate<GameObject>(prefab)); obj.SetActive(false); StripMeasurementObject(obj); obj.transform.rotation = rotation; obj.transform.position = Vector3.zero; obj.SetActive(true); Bounds worldBounds = GetWorldBounds(obj); Object.DestroyImmediate((Object)(object)obj); return ((Bounds)(ref worldBounds)).size.x; } private static void StripMeasurementObject(GameObject visual) { PortalDisplaySignSpawner.StripSign(visual); Collider[] componentsInChildren = visual.GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } } private static Vector3 GetAnchorOffsetInParentSpace(Transform piece, StationPieceAnchor anchor) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: 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_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) Bounds worldBounds = GetWorldBounds(((Component)piece).gameObject); Vector3 val = (Vector3)(anchor switch { StationPieceAnchor.BottomLeft => new Vector3(((Bounds)(ref worldBounds)).min.x, ((Bounds)(ref worldBounds)).min.y, ((Bounds)(ref worldBounds)).min.z), StationPieceAnchor.BottomFrontCenter => new Vector3(((Bounds)(ref worldBounds)).center.x, ((Bounds)(ref worldBounds)).min.y, ((Bounds)(ref worldBounds)).max.z), StationPieceAnchor.BottomBackCenter => new Vector3(((Bounds)(ref worldBounds)).center.x, ((Bounds)(ref worldBounds)).min.y, ((Bounds)(ref worldBounds)).min.z), _ => new Vector3(((Bounds)(ref worldBounds)).center.x, ((Bounds)(ref worldBounds)).min.y, ((Bounds)(ref worldBounds)).center.z), }); Transform parent = piece.parent; if ((Object)(object)parent == (Object)null) { return val - piece.position; } return parent.InverseTransformPoint(val); } private static Bounds GetWorldBounds(GameObject root) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true); if (componentsInChildren.Length == 0) { return new Bounds(root.transform.position, Vector3.zero); } Bounds bounds = componentsInChildren[0].bounds; for (int i = 1; i < componentsInChildren.Length; i++) { ((Bounds)(ref bounds)).Encapsulate(componentsInChildren[i].bounds); } return bounds; } } public static class StationPrefabBuilder { private static GameObject _cachedPrefab; private static string _cachedBuildLabel = string.Empty; public static GameObject Build() { //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_cachedPrefab != (Object)null && _cachedBuildLabel == "v0.3.2") { return _cachedPrefab; } _cachedBuildLabel = "v0.3.2"; GameObject val = PrefabManager.Instance.CreateClonedPrefab("portal_station", "piece_wood_wall"); if ((Object)(object)val == (Object)null) { val = PrefabManager.Instance.CreateClonedPrefab("portal_station", "woodwall"); } if ((Object)(object)val == (Object)null) { PortalStationPlugin.Log.LogError((object)"Could not clone piece_wood_wall for Portal Station root."); return null; } StripRootPieceComponents(val); StationVisualHelper.SetRenderersEnabled(val, enabled: false); Collider[] componentsInChildren = val.GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } ConfigurePiece(val); ConfigurePlacementCollider(val); ConfigureZNetView(val); if ((Object)(object)val.GetComponent<PortalStationBoard>() == (Object)null) { val.AddComponent<PortalStationBoard>(); } StationFrameBuilder.BuildFrame(val.transform); StationFrameBuilder.BuildBoard(val.transform); StationHeaderSign header = StationSignGridBuilder.BuildHeaderSign(val.transform); StationDestinationSign[] destinations = StationSignGridBuilder.BuildDestinationSigns(val.transform); val.GetComponent<PortalStationBoard>().BindChildSigns(header, destinations); val.transform.localScale = Vector3.one * 0.75f; StationPrefabSanitizer.StripChildNetworking(val); PrefabBuildHelper.FinalizeBuildPiece(val); StationInteractionColliders.Disable(val); _cachedPrefab = val; return val; } private static void StripRootPieceComponents(GameObject station) { PieceTable component = station.GetComponent<PieceTable>(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } ItemDrop component2 = station.GetComponent<ItemDrop>(); if ((Object)(object)component2 != (Object)null) { Object.DestroyImmediate((Object)(object)component2); } } private static void ConfigurePiece(GameObject station) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) Piece component = station.GetComponent<Piece>(); if (!((Object)(object)component == (Object)null)) { component.m_name = "$piece_portal_station"; component.m_description = "$piece_portal_station_desc"; component.m_category = (PieceCategory)0; component.m_enabled = true; StationHammerIcon.Apply(component); } } private static void ConfigurePlacementCollider(GameObject station) { //IL_0027: 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) BoxCollider val = station.GetComponent<BoxCollider>(); if ((Object)(object)val == (Object)null) { val = station.AddComponent<BoxCollider>(); } val.center = new Vector3(0f, 2.1f, 0f); val.size = new Vector3(3.2f, 4.2f, 0.5f); } private static void ConfigureZNetView(GameObject station) { ZNetView val = station.GetComponent<ZNetView>(); if ((Object)(object)val == (Object)null) { val = station.AddComponent<ZNetView>(); } val.m_persistent = true; val.m_distant = false; } } internal static class StationPrefabSanitizer { internal static void StripChildNetworking(GameObject root) { if ((Object)(object)root == (Object)null) { return; } WearNTear[] componentsInChildren = root.GetComponentsInChildren<WearNTear>(true); foreach (WearNTear val in componentsInChildren) { if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)(object)root) { Object.DestroyImmediate((Object)(object)val); } } ZNetView component = root.GetComponent<ZNetView>(); ZNetView[] componentsInChildren2 = root.GetComponentsInChildren<ZNetView>(true); foreach (ZNetView val2 in componentsInChildren2) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)component)) { Object.DestroyImmediate((Object)(object)val2); } } Piece[] componentsInChildren3 = root.GetComponentsInChildren<Piece>(true); foreach (Piece val3 in componentsInChildren3) { if (!((Object)(object)val3 == (Object)null) && !((Object)(object)((Component)val3).gameObject == (Object)(object)root)) { Object.DestroyImmediate((Object)(object)val3); } } ItemDrop[] componentsInChildren4 = root.GetComponentsInChildren<ItemDrop>(true); foreach (ItemDrop val4 in componentsInChildren4) { if (!((Object)(object)val4 == (Object)null) && !((Object)(object)((Component)val4).gameObject == (Object)(object)root)) { Object.DestroyImmediate((Object)(object)val4); } } } } internal static class StationSignGridBuilder { private const float SignHeight = 0.5f; private const float BoardBottomY = 1f; private const float SignFaceEpsilon = 0.02f; private const float HeaderSignForwardOffset = 0.1f; private const float SignForwardOffset = 0.37f; private static readonly float[] ColumnCenters = new float[3] { 1f, 0f, -1f }; internal static StationHeaderSign BuildHeaderSign(Transform root) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) StationSignOrientation.ResetCache(); float num = ResolveBoardFaceZ(root) + 0.1f; Vector3 targetAnchor = default(Vector3); ((Vector3)(ref targetAnchor))..ctor(0f, 4.3f, num); GameObject obj = CreateSignObject(root, "_station_header", targetAnchor); StationHeaderSign result = obj.AddComponent<StationHeaderSign>(); obj.AddComponent<StationSignVisual>(); return result; } internal static StationDestinationSign[] BuildDestinationSigns(Transform root) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) StationDestinationSign[] array = new StationDestinationSign[18]; Vector3 targetAnchor = default(Vector3); for (int i = 0; i < 6; i++) { int num = 5 - i; float num2 = 1f + (float)num * 0.5f; for (int j = 0; j < 3; j++) { int num3 = i * 3 + j; float num4 = ResolveSignWallFrontZ(root, j, num) + 0.02f + 0.37f; ((Vector3)(ref targetAnchor))..ctor(ColumnCenters[j], num2, num4); GameObject obj = CreateSignObject(root, $"_station_slot_{num3:D2}", targetAnchor); obj.AddComponent<StationSignVisual>(); StationDestinationSign stationDestinationSign = obj.AddComponent<StationDestinationSign>(); stationDestinationSign.SetSlotIndex(num3); array[num3] = stationDestinationSign; } } return array; } private static float ResolveSignWallFrontZ(Transform root, int column, int row) { if (column <= 1) { if (row >= 4) { return ResolveWallPieceFrontZ(root, "wood_wall_half"); } return ResolveWallPieceFrontZ(root, "woodwall"); } return ResolveWallPieceFrontZ(root, "wood_wall_quarter"); } private static float ResolveWallPieceFrontZ(Transform root, string wallPieceName) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0065: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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_0091: Unknown result type (might be due to invalid IL or missing references) float num = float.MinValue; bool flag = false; Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if (!(((Object)val).name != wallPieceName)) { Renderer[] componentsInChildren2 = ((Component)val).GetComponentsInChildren<Renderer>(true); foreach (Renderer val2 in componentsInChildren2) { Bounds bounds = val2.bounds; float x = ((Bounds)(ref bounds)).center.x; bounds = val2.bounds; float y = ((Bounds)(ref bounds)).center.y; bounds = val2.bounds; Vector3 val3 = root.InverseTransformPoint(new Vector3(x, y, ((Bounds)(ref bounds)).max.z)); num = Mathf.Max(num, val3.z); flag = true; } } } if (!flag) { return 0f; } return num; } internal static float ResolveBoardFaceZ(Transform root) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //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_006e: 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) float num = 0f; bool flag = false; Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if (IsBoardWallRenderer(val)) { flag = true; Bounds bounds = val.bounds; float x = ((Bounds)(ref bounds)).center.x; bounds = val.bounds; float y = ((Bounds)(ref bounds)).center.y; bounds = val.bounds; Vector3 val2 = root.InverseTransformPoint(new Vector3(x, y, ((Bounds)(ref bounds)).max.z)); num = Mathf.Max(num, val2.z); } } if (!flag) { num = MeasureWallPlankThickness(); } return num + 0.02f; } private static bool IsBoardWallRenderer(Renderer renderer) { if ((Object)(object)renderer == (Object)null) { return false; } Transform val = ((Component)renderer).transform; while ((Object)(object)val != (Object)null) { switch (((Object)val).name) { case "woodwall": case "wood_wall_half": case "wood_wall_quarter": return true; } if ((Object)(object)val.parent == (Object)null || ((Object)val.parent).name == "portal_station") { break; } val = val.parent; } return false; } private static float MeasureWallPlankThickness() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_009d: 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) GameObject wallPrefab = StationVisualHelper.TryGetPrefab("woodwall", "piece_wood_wall"); if ((Object)(object)wallPrefab == (Object)null) { return 0.26f; } GameObject val = NetworkPrefabHelper.RunWithoutZdoCreation(() => Object.Instantiate<GameObject>(wallPrefab)); val.SetActive(false); StationVisualHelper.StripForVisualChild(val); val.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity); val.SetActive(true); Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true); float result = 0.26f; if (componentsInChildren.Length != 0) { Bounds bounds = componentsInChildren[0].bounds; for (int num = 1; num < componentsInChildren.Length; num++) { ((Bounds)(ref bounds)).Encapsulate(componentsInChildren[num].bounds); } result = ((Bounds)(ref bounds)).size.z; } Object.DestroyImmediate((Object)(object)val); return result; } private static GameObject CreateSignObject(Transform root, string name, Vector3 targetAnchor) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) GameObject source = StationVisualHelper.TryGetPrefab("sign", "piece_sign"); if ((Object)(object)source == (Object)null) { GameObject val = new GameObject(name); val.transform.SetParent(root, false); val.transform.localPosition = targetAnchor; return val; } GameObject val2 = NetworkPrefabHelper.RunWithoutZdoCreation(() => Object.Instantiate<GameObject>(source)); val2.SetActive(false); ((Object)val2).name = name; PortalDisplaySignSpawner.StripSign(val2); val2.SetActive(true); PlaceSignFacingOut(root, val2, targetAnchor); if ((Object)(object)val2.GetComponent<Collider>() == (Object)null) { BoxCollider obj = val2.AddComponent<BoxCollider>(); obj.size = new Vector3(1.8f, 0.9f, 0.15f); obj.center = new Vector3(0f, 0f, 0.08f); ((Collider)obj).enabled = false; } return val2; } private static void PlaceSignFacingOut(Transform root, GameObject signObject, Vector3 targetAnchor) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) Quaternion localRotation = StationSignOrientation.GetBoardMountRotation(root) * Quaternion.Euler(0f, 180f, 0f); StationPieceAnchor placementAnchor = StationSignOrientation.GetPlacementAnchor(); StationPiecePlacement.Place(root, signObject, targetAnchor, localRotation, placementAnchor); } } internal static class StationSignOrientation { private static Quaternion? _cachedLocalRotation; private static StationPieceAnchor _cachedAnchor = StationPieceAnchor.BottomBackCenter; internal static void ResetCache() { _cachedLocalRotation = null; } internal static Quaternion GetBoardMountRotation(Transform boardRoot) { //IL_0011: 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) //IL_0059: 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_0065: 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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: 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) //IL_0095: 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_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) if (_cachedLocalRotation.HasValue) { return _cachedLocalRotation.Value; } GameObject val = StationVisualHelper.TryGetPrefab("sign", "piece_sign"); if ((Object)(object)val == (Object)null || (Object)(object)boardRoot == (Object)null) { _cachedLocalRotation = Quaternion.identity; return _cachedLocalRotation.Value; } Vector3 desiredForward = boardRoot.TransformDirection(Vector3.forward); Quaternion val2 = Quaternion.identity; StationPieceAnchor cachedAnchor = StationPieceAnchor.BottomBackCenter; float num = float.MinValue; Quaternion[] array = BuildRotationCandidates(); foreach (Quaternion val3 in array) { if (TryScoreRotation(val, boardRoot, val3, desiredForward, out var score, out var anchor) && score > num) { num = score; val2 = val3; cachedAnchor = anchor; } } _cachedLocalRotation = val2; _cachedAnchor = cachedAnchor; return val2; } internal static StationPieceAnchor GetPlacementAnchor() { return _cachedAnchor; } private static bool TryScoreRotation(GameObject source, Transform boardRoot, Quaternion localRotation, Vector3 desiredForward, out float score, out StationPieceAnchor anchor) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) score = float.MinValue; anchor = StationPieceAnchor.BottomBackCenter; GameObject val = NetworkPrefabHelper.RunWithoutZdoCreation(() => Object.Instantiate<GameObject>(source)); val.SetActive(false); PortalDisplaySignSpawner.StripSign(val); val.transform.SetParent(boardRoot, false); val.transform.localRotation = localRotation; val.transform.localPosition = Vector3.zero; val.SetActive(true); TextMeshProUGUI componentInChildren = val.GetComponentInChildren<TextMeshProUGUI>(true); if ((Object)(object)componentInChildren == (Object)null) { Object.DestroyImmediate((Object)(object)val); return false; } float num = Vector3.Dot(((TMP_Text)componentInChildren).transform.forward, desiredForward); if (num < 0.85f) { Object.DestroyImmediate((Object)(object)val); return false; } anchor = StationPieceAnchor.BottomBackCenter; float num2 = Vector3.Dot(((TMP_Text)componentInChildren).transform.up, boardRoot.up); score = num * 2f + num2; Object.DestroyImmediate((Object)(object)val); return true; } private static Quaternion[] BuildRotationCandidates() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) Quaternion[] array = (Quaternion[])(object)new Quaternion[24]; int num = 0; for (int i = 0; i < 360; i += 90) { for (int j = -90; j <= 90; j += 90) { array[num++] = Quaternion.Euler((float)j, (float)i, 0f); } } return array; } } internal static class StationVisualHelper { internal static GameObject TryGetPrefab(params string[] prefabNames) { string[] array = prefabNames; foreach (string text in array) { GameObject prefab = PrefabManager.Instance.GetPrefab(text); if ((Object)(object)prefab != (Object)null) { return prefab; } } if ((Object)(object)ZNetScene.instance != (Object)null) { array = prefabNames; foreach (string text2 in array) { GameObject prefab2 = ZNetScene.instance.GetPrefab(text2); if ((Object)(object)prefab2 != (Object)null) { return prefab2; } } } PortalStationPlugin.Log.LogWarning((object)("StationVisualHelper: could not resolve prefab from candidates: " + string.Join(", ", prefabNames))); return null; } internal static GameObject AddVisualChild(Transform parent, string prefabName, Vector3 localPosition, Quaternion localRotation, params string[] prefabNameFallbacks) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) return AddVisualChild(parent, prefabName, localPosition, localRotation, StationPieceAnchor.BottomCenter, prefabNameFallbacks); } internal static GameObject AddVisualChild(Transform parent, string prefabName, Vector3 localPosition, Quaternion localRotation, StationPieceAnchor anchor, params string[] prefabNameFallbacks) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) List<string> list = new List<string> { prefabName }; if (prefabNameFallbacks != null) { list.AddRange(prefabNameFallbacks); } GameObject source = TryGetPrefab(list.ToArray()); if ((Object)(object)source == (Object)null || (Object)(object)parent == (Object)null) { return null; } GameObject val = NetworkPrefabHelper.RunWithoutZdoCreation(() => Object.Instantiate<GameObject>(source)); val.SetActive(false); ((Object)val).name = prefabName; StripForVisualChild(val); val.SetActive(true); StationPiecePlacement.Place(parent, val, localPosition, localRotation, anchor); return val; } internal static GameObject AddBeamChild(Transform parent, string prefabName, Vector3 localPosition, params string[] prefabNameFallbacks) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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) List<string> list = new List<string> { prefabName }; if (prefabNameFallbacks != null) { list.AddRange(prefabNameFallbacks); } GameObject val = TryGetPrefab(list.ToArray()); if ((Object)(object)val == (Object)null || (Object)(object)parent == (Object)null) { return null; } Quaternion beamRotationAlongX = StationPiecePlacement.GetBeamRotationAlongX(val); return AddVisualChild(parent, prefabName, localPosition, beamRotationAlongX, StationPieceAnchor.BottomCenter, prefabNameFallbacks); } internal static void StripForVisualChild(GameObject visual) { PortalDisplaySignSpawner.StripSign(visual); Collider[] componentsInChildren = visual.GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } } internal static void SetRenderersEnabled(GameObject root, bool enabled) { if (!((Object)(object)root == (Object)null)) { Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = enabled; } } } } internal static class StationRegistrar { private static bool _registered; private static string _registeredBuildLabel = string.Empty; internal static void Init() { PrefabManager.OnVanillaPrefabsAvailable += Register; } private static void Register() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Expected O, but got Unknown if (_registered && _registeredBuildLabel == "v0.3.2") { return; } if (_registered) { PrefabManager.Instance.DestroyPrefab("portal_station"); PrefabManager.Instance.DestroyPrefab("runic_portal_station"); _registered = false; } GameObject val = StationPrefabBuilder.Build(); if ((Object)(object)val == (Object)null) { PortalStationPlugin.Log.LogError((object)"Failed to build Portal Station prefab."); return; } PrefabManager.Instance.AddPrefab(val); PieceConfig val2 = new PieceConfig { Name = "$piece_portal_station", Description = "$piece_portal_station_desc", PieceTable = "Hammer", CraftingStation = CraftingStations.Workbench, Category = PieceCategories.Misc, Enabled = true }; val2.AddRequirement("Wood", ModConfig.CraftCostWood.Value, true); val2.AddRequirement("Coal", ModConfig.CraftCostCoal.Value, true); Sprite sprite = StationHammerIcon.GetSprite(); if ((Object)(object)sprite != (Object)null) { val2.Icon = sprite; } PieceManager.Instance.AddPiece(new CustomPiece(val, false, val2)); _registered = true; _registeredBuildLabel = "v0.3.2"; PrefabManager.OnVanillaPrefabsAvailable -= Register; PortalStationPlugin.Log.LogInfo((object)"Portal Station registered with Jotunn (v0.3.2)."); } } public sealed class StationConfigUI : MonoBehaviour { private PortalStationBoard _target; private bool _visible; private string _stationName = string.Empty; private readonly string[] _portalNames = new string[18]; private readonly string[] _displayNames = new string[18]; private Vector2 _scroll; private string _statusMessage = string.Empty; private Rect _windowRect = new Rect(80f, 40f, 760f, 660f); private static Texture2D _solidTexture; private GUIStyle _panelStyle; private GUIStyle _labelStyle; public static StationConfigUI Instance { get; private set; } public static bool IsOpen { get { if ((Object)(object)Instance != (Object)null) { return Instance._visible; } return false; } } private void Awake() { Instance = this; } private void OnDestroy() { if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private void Update() { if (_visible) { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } } public void Open(PortalStationBoard station) { if (!((Object)(object)station == (Object)null)) { _target = station; _stationName = station.GetStationName(); for (int i = 0; i < 18; i++) { _portalNames[i] = station.GetSlotPortalName(i); _displayNames[i] = station.GetSlotDisplayRaw(i); } _statusMessage = string.Empty; _visible = true; Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } } private void Close() { _visible = false; _target = null; _statusMessage = string.Empty; } private void OnGUI() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Invalid comparison between Unknown and I4 if (_visible && !((Object)(object)_target == (Object)null)) { if ((int)Event.current.type == 4 && (int)Event.current.keyCode == 27) { Close(); Event.current.Use(); return; } EnsureStyles(); Color color = GUI.color; GUI.color = new Color(0f, 0f, 0f, 0.65f); GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)_solidTexture); GUI.color = color; _windowRect = GUI.ModalWindow(913427, _windowRect, new WindowFunction(DrawWindow), Localization.instance.Localize("$piece_portal_station_configure_title"), _panelStyle); } } private void DrawWindow(int id) { //IL_0078: 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_0260: Unknown result type (might be due to invalid IL or missing references) GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); GUILayout.Label(Localization.instance.Localize("$piece_portal_station_name_label"), _labelStyle, Array.Empty<GUILayoutOption>()); _stationName = GUILayout.TextField(_stationName, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(680f) }); GUILayout.Space(8f); GUILayout.Label(Localization.instance.Localize("$piece_portal_station_slots_help"), _labelStyle, Array.Empty<GUILayoutOption>()); _scroll = GUILayout.BeginScrollView(_scroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(470f) }); for (int i = 0; i < 6; i++) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); for (int j = 0; j < 3; j++) { int num = i * 3 + j; GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(230f) }); GUILayout.Label($"#{num + 1}", _labelStyle, Array.Empty<GUILayoutOption>()); GUILayout.Label("Portal tag", _labelStyle, Array.Empty<GUILayoutOption>()); string text = GUILayout.TextField(_portalNames[num], (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(210f) }); _portalNames[num] = PortalTextHelper.ClampPortalName(text); GUILayout.Label("Display text", _labelStyle, Array.Empty<GUILayoutOption>()); _displayNames[num] = GUILayout.TextField(_displayNames[num], (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(210f) }); _displayNames[num] = PortalTextHelper.ClampDisplayName(_displayNames[num]); GUILayout.EndVertical(); } GUILayout.EndHorizontal(); GUILayout.Space(4f); } GUILayout.EndScrollView(); if (!string.IsNullOrEmpty(_statusMessage)) { GUILayout.Label(_statusMessage, _labelStyle, Array.Empty<GUILayoutOption>()); } GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button(Localization.instance.Localize("$piece_portal_station_cancel"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(140f) })) { Close(); } if (GUILayout.Button(Localization.instance.Localize("$piece_portal_station_commit"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(140f) })) { Commit(); } GUILayout.EndHorizontal(); GUILayout.EndVertical(); GUI.DragWindow(new Rect(0f, 0f, 10000f, 24f)); } private void Commit() { if (!((Object)(object)_target == (Object)null)) { if (!_target.TryApplyConfiguration(_stationName, _portalNames, _displayNames, out var message)) { _statusMessage = message; return; } _statusMessage = message; Close(); } } private void EnsureStyles() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown //IL_00c1: Expected O, but got Unknown //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown if ((Object)(object)_solidTexture == (Object)null) { _solidTexture = new Texture2D(1, 1, (TextureFormat)4, false); _solidTexture.SetPixel(0, 0, Color.white); _solidTexture.Apply(); } if (_panelStyle == null) { GUIStyle val = new GUIStyle(GUI.skin.window); val.normal.background = MakeTexture(new Color(0.1f, 0.12f, 0.16f, 0.97f)); val.onNormal.background = MakeTexture(new Color(0.1f, 0.12f, 0.16f, 0.97f)); val.fontSize = 16; val.padding = new RectOffset(16, 16, 24, 16); _panelStyle = val; GUIStyle val2 = new GUIStyle(GUI.skin.label) { fontSize = 14 }; val2.normal.textColor = new Color(0.95f, 0.95f, 0.9f, 1f); _labelStyle = val2; } } private static Texture2D MakeTexture(Color color) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_0019: Expected O, but got Unknown Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false); val.SetPixel(0, 0, color); val.Apply(); return val; } } internal static class PortalTagHelper { internal static string GetPortalTag(TeleportWorld portal) { if ((Object)(object)portal == (Object)null) { return string.Empty; } ZNetView component = ((Component)portal).GetComponent<ZNetView>(); ZDO val = ((component != null) ? component.GetZDO() : null); if (val == null) { return string.Empty; } return PortalTextHelper.StripRichText(val.GetString("tag", string.Empty)); } internal static string GetPortalDisplayText(TeleportWorld portal) { object obj; if (portal == null) { obj = null; } else { ZNetView component = ((Component)portal).GetComponent<ZNetView>(); obj = ((component != null) ? component.GetZDO() : null); } return ((obj != null) ? ((ZDO)obj).GetString("PortalStation_DisplayText", string.Empty) : null) ?? string.Empty; } internal static bool TrySetPortalDisplay(TeleportWorld portal, string displayText, out string error) { error = null; if ((Object)(object)portal == (Object)null) { error = "Portal not found."; return false; } displayText = PortalTextHelper.ClampDisplayName(displayText?.Trim() ?? string.Empty); ZNetView component = ((Component)portal).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { error = "Portal is not ready yet."; return false; } component.GetZDO().Set("PortalStation_DisplayText", displayText); RefreshPortalSign(portal); return true; } internal static bool TrySetPortalTagAndDisplay(TeleportWorld portal, string portalName, string displayText, out string error) { error = null; if ((Object)(object)portal == (Object)null) { error = "No linked portal found."; return false; } string text = PortalTextHelper.ClampPortalName(portalName); if (string.IsNullOrWhiteSpace(text)) { error = "Portal name cannot be empty."; return false; } if (text.Length > 10) { error = $"Portal name cannot exceed {10} characters."; return false; } portal.SetText(text); ZNetView component = ((Component)portal).GetComponent<ZNetView>(); string text2 = PortalTextHelper.BuildDisplayText(text, displayText); if ((Object)(object)component != (Object)null && component.IsValid()) { component.GetZDO().Set("PortalStation_DisplayText", text2); component.GetZDO().Set("PortalStation_StationLinked", true); } ((Component)portal).GetComponentInChildren<PortalNameSign>(true)?.SetDisplayText(PortalTextHelper.FormatDisplayForRender(text2)); return true; } internal static bool TryClearPortal(TeleportWorld portal, out string error) { error = null; if ((Object)(object)portal == (Object)null) { error = "No linked portal found."; return false; } portal.SetText(string.Empty); ZNetView component = ((Component)portal).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid()) { component.GetZDO().Set("PortalStation_DisplayText", string.Empty); component.GetZDO().Set("PortalStation_StationLinked", false); } RefreshPortalSign(portal); return true; } internal static void RefreshPortalSign(TeleportWorld portal) { ((portal != null) ? ((Component)portal).GetComponentInChildren<PortalNameSign>(true) : null)?.RefreshFromPortal(); } } internal static class PortalTextHelper { private static readonly Regex HexColorTagRegex = new Regex("<#[0-9a-fA-F]{6,8}>", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex NamedColorTagRegex = new Regex("<color=[^>]+>", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex HexValueRegex = new Regex("#?[0-9a-fA-F]{6,8}", RegexOptions.IgnoreCase | RegexOptions.Compiled); internal static int DisplayNameMaxLength => ModConfig.DisplayNameMaxLength?.Value ?? 50; internal static string StripRichText(string text) { if (string.IsNullOrEmpty(text)) { return string.Empty; } return StringExtensionMethods.RemoveRichTextTags(text).Trim(); } internal static string ClampPortalName(string text) { string text2 = StripRichText(text); if (text2.Length <= 10) { return text2; } return text2.Substring(0, 10); } internal static string ClampDisplayName(string text) { if (string.IsNullOrEmpty(text)) { return string.Empty; } int displayNameMaxLength = DisplayNameMaxLength; if (text.Length <= displayNameMaxLength) { return text; } return text.Substring(0, displayNameMaxLength); } internal static string BuildDisplayText(string portalName, string displayText) { if (!string.IsNullOrWhiteSpace(displayText)) { return displayText.Trim(); } return portalName ?? string.Empty; } internal static string FormatDisplayForRender(string displayText) { if (string.IsNullOrWhiteSpace(displayText) || displayText == "...") { return displayText ?? string.Empty; } string text = displayText.Trim(); if (HasExplicitColor(text)) { return text; } string text2 = ModConfig.DefaultPortalDescription?.Value?.Trim(); if (string.IsNullOrEmpty(text2)) { return text; } return NormalizeColorTag(text2) + text; } internal static bool PortalNamesEqual(string left, string right) { return string.Equals(StripRichText(left), StripRichText(right), StringComparison.OrdinalIgnoreCase); } internal static bool TryGetHighlightColor(out Color color) { string text = ModConfig.DefaultHighlightColor?.Value?.Trim(); if (string.IsNullOrEmpty(text)) { text = "<#87CEEB>"; } return TryParseColorTag(text, out color); } internal static bool HasExplicitColor(string text) { if (string.IsNullOrEmpty(text)) { return false; } if (!HexColorTagRegex.IsMatch(text)) { return NamedColorTagRegex.IsMatch(text); } return true; } private static string NormalizeColorTag(string colorTag) { if (string.IsNullOrWhiteSpace(colorTag)) { return string.Empty; } string text = colorTag.Trim(); if (text.StartsWith("<", StringComparison.Ordinal)) { return text; } if (text.StartsWith("#", StringComparison.Ordinal)) { return "<" + text + ">"; } return "<color=" + text + ">"; } private static bool TryParseCol