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 Stavebound v1.2.1
plugins\Stavebound.dll
Decompiled 3 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Splatform; using Stavebound.Compat; using Stavebound.Config; using Stavebound.Portals; using Stavebound.Staves; using Stavebound.Tiers; using Stavebound.Travel; using Stavebound.UI; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("recognizerHD")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (c) 2026 recognizerHD")] [assembly: AssemblyFileVersion("1.2.1.0")] [assembly: AssemblyInformationalVersion("1.2.1+e2296992736910d3a3f115da5a61f1ce3e934cf4")] [assembly: AssemblyProduct("Stavebound")] [assembly: AssemblyTitle("Stavebound")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/recognizerHD/stave-bound")] [assembly: NeutralResourcesLanguage("en")] [assembly: AssemblyVersion("1.2.1.0")] namespace Stavebound { internal static class BuildInfo { internal const string Guid = "com.recognizerhd.stavebound"; internal const string Name = "Stavebound"; internal const string Version = "1.2.1"; } [BepInPlugin("com.recognizerhd.stavebound", "Stavebound", "1.2.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal sealed class Plugin : BaseUnityPlugin { private Harmony _harmony; internal static Plugin Instance { get; private set; } private void Awake() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown Instance = this; StaveboundConfig.Bind(((BaseUnityPlugin)this).Config); SelectorKeys.Bind(((BaseUnityPlugin)this).Config); Translations.Add(); StavePieces.Register(); PortalRegistry.Register(); _harmony = new Harmony("com.recognizerhd.stavebound"); _harmony.PatchAll(Assembly.GetExecutingAssembly()); Logger.LogInfo((object)"Stavebound 1.2.1 loaded."); } private void Start() { ConflictDetector.WarnAboutKnownConflicts(); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } _harmony = null; Instance = null; } } } namespace Stavebound.UI { internal static class DestinationSelector { private enum SortOrder { Distance, Name } internal sealed class RowView { internal GameObject Root; internal Button Button; internal Text Name; internal Text Chips; internal int Candidate = -1; } private static readonly List<PortalRecord> Candidates = new List<PortalRecord>(); private static readonly List<PinData> Pins = new List<PinData>(); private const int VisibleRows = 9; private static ZDOID _sourceId; private static long _sourcePid; private static Vector3 _sourcePosition; private static string _sourceName; private static SortOrder _order = SortOrder.Distance; private static bool _onlyWhatAcceptsMyCargo; private static int _highlight; private static Clearance _carrying; private static Clearance _sourceMask; private static GameObject _panel; private static Text _title; private static Text _status; private static Dropdown _picker; private static Text _moreAbove; private static Text _moreBelow; private static readonly List<RowView> Rows = new List<RowView>(); private static readonly List<Selectable> NeedsCandidates = new List<Selectable>(); private static bool _pickerStale; private static float _wheel; private static int _wheelFrame = -1; private static float _lastWheelStep; private const float WheelInterval = 0.06f; private static long _homePid = 0L; private static PinData _homePin; private static readonly Color HomeColour = new Color(0.5f, 0.83f, 1f); private const string HomeHex = "#7FD4FF"; private static RowView _hovered; private static bool _previewing; private static bool _updateSeen; private static readonly FieldRef<Dropdown, GameObject> PickerBlocker = AccessTools.FieldRefAccess<Dropdown, GameObject>("m_Blocker"); private const float PanelHeight = 530f; private const float RowHeight = 28f; private const float ChipsWidth = 132f; private const float BaseInner = 400f; private const float PanelPadding = 40f; private const float PerNameCharacter = 3f; private const float MostExtraWidth = 70f; private static float Inner = 400f; private static float PanelWidth = 440f; internal static bool IsOpen { get; private set; } internal static void Open(TeleportWorld portal, Humanoid who) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_008d: 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) ZDO val = PortalTarget.ZdoOf(portal); if (val == null || (Object)(object)Minimap.instance == (Object)null) { return; } if (!ReaimGuard.MayReaim(((Component)portal).transform.position, out var refusal)) { if (who != null) { ((Character)who).Message((MessageType)2, refusal, 0, (Sprite)null, false); } return; } _sourceId = val.m_uid; long pid = PortalTarget.GetPid(val); string text = val.GetString(ZDOVars.s_tag, string.Empty); _sourceName = (string.IsNullOrEmpty(text) ? "this portal" : ("\"" + text + "\"")); _sourcePosition = ((Component)portal).transform.position; _sourcePid = pid; _sourceMask = ClearanceGate.MaskOf(val); _carrying = CarriedTiers((Player)(object)((who is Player) ? who : null)); _homePid = NearestToHome(); _onlyWhatAcceptsMyCargo = false; Rebuild(0L); if (Candidates.Count == 0) { if (who != null) { ((Character)who).Message((MessageType)2, Translations.Get("stave_sel_nowhere"), 0, (Sprite)null, false); } return; } long current = PortalTarget.GetDestination(val); _highlight = Candidates.FindIndex((PortalRecord p) => p.Pid == current); if (_highlight < 0) { _highlight = 0; } AddPins(); BuildPanel(); IsOpen = true; _updateSeen = false; Minimap.instance.SetMapMode((MapMode)2); ShowHighlight(); Logger.LogInfo((object)$"Selector opened for {_sourceName} with {Candidates.Count} destination(s)."); } internal static void Update() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Invalid comparison between Unknown and I4 //IL_00e8: Unknown result type (might be due to invalid IL or missing references) if (!IsOpen) { return; } if (!_updateSeen) { _updateSeen = true; Logger.LogInfo((object)"Selector is receiving frames."); } if ((Object)(object)Minimap.instance == (Object)null || (int)Minimap.instance.m_mode != 2) { Close(); return; } TintPins(); if (PickerIsOpen()) { if (Cancelled()) { _picker.Hide(); } return; } GameObject val = (((Object)(object)EventSystem.current != (Object)null) ? EventSystem.current.currentSelectedGameObject : null); if ((Object)(object)val != (Object)null && (Object)(object)_panel != (Object)null && val.transform.IsChildOf(_panel.transform)) { Unfocus(); } if (_previewing && _hovered == null) { _previewing = false; if (Candidates.Count > 0) { Minimap instance = Minimap.instance; if (instance != null) { instance.ShowPointOnMap(Candidates[_highlight].Position); } } } if (Cancelled()) { Close(); return; } if (Confirmed()) { Commit(); return; } if (SelectorKeys.Pressed("stave_filter")) { ToggleFilter(); return; } if (SelectorKeys.Pressed("stave_sort")) { ToggleSort(); return; } int num = Stepped(); if (num != 0) { Step(num); } else { ScrollFromWheel(); } } internal static bool OwnsWheel() { if (IsOpen && (Object)(object)_panel != (Object)null) { if (!PickerIsOpen()) { if (StaveboundConfig.WheelScrollsList.Value) { return PointerOverPanel(); } return false; } return true; } return false; } internal static void ReceiveWheel(float delta) { _wheel = delta; _wheelFrame = Time.frameCount; } private static void ScrollFromWheel() { if (StaveboundConfig.WheelScrollsList.Value && _wheelFrame == Time.frameCount && _wheel != 0f && Candidates.Count != 0 && !(Time.unscaledTime - _lastWheelStep < 0.06f) && PointerOverPanel()) { _lastWheelStep = Time.unscaledTime; int num = Mathf.Clamp(_highlight + ((!(_wheel > 0f)) ? 1 : (-1)), 0, Candidates.Count - 1); if (num != _highlight) { _highlight = num; ShowHighlight(); } } } private static bool PointerOverPanel() { //IL_0037: 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_0057: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_panel == (Object)null) { return false; } Canvas componentInParent = _panel.GetComponentInParent<Canvas>(); Canvas val = (((Object)(object)componentInParent != (Object)null) ? componentInParent.rootCanvas : null); Camera val2 = (((Object)(object)val == (Object)null || (int)val.renderMode == 0) ? null : val.worldCamera); return RectTransformUtility.RectangleContainsScreenPoint(_panel.GetComponent<RectTransform>(), Vector2.op_Implicit(ZInput.pointerPosition), val2); } internal static void HoverEntered(RowView row) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (IsOpen && StaveboundConfig.HoverPreviewsOnMap.Value && row != null && row.Candidate >= 0 && row.Candidate < Candidates.Count) { _hovered = row; _previewing = true; Minimap instance = Minimap.instance; if (instance != null) { instance.ShowPointOnMap(Candidates[row.Candidate].Position); } } } internal static void HoverLeft(RowView row) { if (_hovered == row) { _hovered = null; } } private static void Step(int step) { if (Candidates.Count != 0) { _highlight = (_highlight + step + Candidates.Count) % Candidates.Count; ShowHighlight(); } } private static void ToggleFilter() { _onlyWhatAcceptsMyCargo = !_onlyWhatAcceptsMyCargo; Rebuild(Held()); AddPins(); ShowHighlight(); } private static void ToggleSort() { _order = ((_order == SortOrder.Distance) ? SortOrder.Name : SortOrder.Distance); Rebuild(Held()); ShowHighlight(); } private static long Held() { if (_highlight < 0 || _highlight >= Candidates.Count) { return 0L; } return Candidates[_highlight].Pid; } private static void Rebuild(long keep) { Candidates.Clear(); Candidates.AddRange(PortalRegistry.All.Where((PortalRecord p) => p.Pid != _sourcePid)); if (_onlyWhatAcceptsMyCargo && _carrying != Clearance.None) { Candidates.RemoveAll((PortalRecord p) => !Accepts(p)); } Sort(); _pickerStale = true; _highlight = ((keep != 0L) ? Candidates.FindIndex((PortalRecord p) => p.Pid == keep) : 0); if (_highlight < 0) { _highlight = 0; } } private static void Sort() { if (_order == SortOrder.Name) { Candidates.Sort((PortalRecord a, PortalRecord b) => string.Compare(Describe(a), Describe(b), StringComparison.CurrentCultureIgnoreCase)); } else { Candidates.Sort((PortalRecord a, PortalRecord b) => Vector3.Distance(_sourcePosition, a.Position).CompareTo(Vector3.Distance(_sourcePosition, b.Position))); } } internal static void SelectNear(Vector3 worldPoint, float radius) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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 (!IsOpen || Candidates.Count == 0) { return; } int num = -1; float num2 = radius * radius; for (int i = 0; i < Candidates.Count; i++) { Vector3 val = Candidates[i].Position - worldPoint; val.y = 0f; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude <= num2) { num2 = sqrMagnitude; num = i; } } if (num >= 0) { _highlight = num; if (StaveboundConfig.MapClickPicksPortal.Value) { Commit(); } else { ShowHighlight(); } } } private static void Commit() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (Candidates.Count == 0) { return; } ZDOMan instance = ZDOMan.instance; ZDO val = ((instance != null) ? instance.GetZDO(_sourceId) : null); if (val == null) { Close(); return; } PortalRecord portal = Candidates[_highlight]; PortalTarget.Set(val, portal.Pid); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, Translations.Format("stave_sel_aimed", _sourceName, Describe(portal)), 0, (Sprite)null, false); } Close(); } internal static void Reset() { Close(); } private static void Close() { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Invalid comparison between Unknown and I4 IsOpen = false; RemovePins(); if ((Object)(object)_panel != (Object)null) { Object.Destroy((Object)(object)_panel); _panel = null; } _title = null; _status = null; _picker = null; _moreAbove = null; _moreBelow = null; Rows.Clear(); NeedsCandidates.Clear(); _hovered = null; _previewing = false; _homePid = 0L; Candidates.Clear(); if ((Object)(object)Minimap.instance != (Object)null && (int)Minimap.instance.m_mode == 2) { Minimap.instance.SetMapMode((MapMode)1); } } private static void AddPins() { //IL_0021: 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_0039: Unknown result type (might be due to invalid IL or missing references) RemovePins(); foreach (PortalRecord candidate in Candidates) { PinData val = Minimap.instance.AddPin(candidate.Position, (PinType)3, Describe(candidate), false, false, 0L, default(PlatformUserID)); Pins.Add(val); if (candidate.Pid == _homePid) { _homePin = val; } } } private static void TintPins() { //IL_0010: 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_004d: 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) bool value = StaveboundConfig.ColourPortalPins.Value; Color valheimOrange = GUIManager.Instance.ValheimOrange; foreach (PinData pin in Pins) { if (!((Object)(object)pin?.m_iconElement == (Object)null)) { if (pin == _homePin) { ((Graphic)pin.m_iconElement).color = HomeColour; } else if (value) { ((Graphic)pin.m_iconElement).color = valheimOrange; } } } } private static void RemovePins() { foreach (PinData pin in Pins) { if (pin != null) { Minimap instance = Minimap.instance; if (instance != null) { instance.RemovePin(pin); } } } Pins.Clear(); _homePin = null; } private static void ShowHighlight() { //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_panel == (Object)null) { return; } RefreshPicker(); bool flag = Candidates.Count > 0; foreach (Selectable needsCandidate in NeedsCandidates) { needsCandidate.interactable = flag; } _title.text = Translations.Format("stave_sel_title", _sourceName); if (!flag) { _status.text = "<color=#E06C4A>" + Translations.Get("stave_sel_empty") + "</color>"; _moreAbove.text = string.Empty; _moreBelow.text = string.Empty; foreach (RowView row in Rows) { row.Root.SetActive(false); row.Candidate = -1; } _hovered = null; return; } PortalRecord destination = Candidates[_highlight]; Minimap instance = Minimap.instance; if (instance != null) { instance.ShowPointOnMap(destination.Position); } string text = Translations.Get((_order == SortOrder.Distance) ? "stave_sel_by_distance" : "stave_sel_by_name"); string text2 = (_onlyWhatAcceptsMyCargo ? Translations.Get("stave_sel_filtered") : string.Empty); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine(text + text2); string text3 = FlowNote(); if (text3 != null) { stringBuilder.AppendLine("<color=#B9A67A>" + text3 + "</color>"); } stringBuilder.Append(Verdict(destination)); _status.text = stringBuilder.ToString(); int num = Mathf.Clamp(_highlight - 4, 0, Mathf.Max(0, Candidates.Count - 9)); int num2 = Mathf.Min(num + 9, Candidates.Count); _moreAbove.text = ((num > 0) ? Translations.Format("stave_sel_more_above", num) : string.Empty); _moreBelow.text = ((num2 < Candidates.Count) ? Translations.Format("stave_sel_more_below", Candidates.Count - num2) : string.Empty); for (int i = 0; i < Rows.Count; i++) { RowView rowView = Rows[i]; int num3 = num + i; if (num3 >= num2) { rowView.Root.SetActive(false); rowView.Candidate = -1; if (_hovered == rowView) { _hovered = null; } continue; } PortalRecord portal = Candidates[num3]; bool flag2 = num3 == _highlight; string text4 = $"{Describe(portal)} <size=12>{Vector3.Distance(_sourcePosition, portal.Position):F0}m</size>"; rowView.Candidate = num3; rowView.Root.SetActive(true); string text5 = ((portal.Pid == _homePid) ? "#7FD4FF" : (flag2 ? "#FFB726" : "#C9C0AC")); rowView.Name.text = (flag2 ? ("<color=#FFB726>» </color><color=" + text5 + ">" + text4 + "</color>") : ("<color=" + text5 + "> " + text4 + "</color>")); rowView.Chips.text = Chips(portal); ((Selectable)rowView.Button).colors = RowColours(flag2); } } private static void RefreshPicker() { //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) if ((Object)(object)_picker == (Object)null) { return; } if (_pickerStale) { _pickerStale = false; _picker.ClearOptions(); List<string> list = new List<string>(Candidates.Count); foreach (PortalRecord candidate in Candidates) { list.Add($"{Describe(candidate)} {Vector3.Distance(_sourcePosition, candidate.Position):F0}m"); } if (list.Count == 0) { list.Add(Translations.Get("stave_sel_empty")); } _picker.AddOptions(list); } _picker.SetValueWithoutNotify((Candidates.Count != 0) ? _highlight : 0); } private static ColorBlock RowColours(bool current) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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_00a0: 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_00af: 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_00d8: Unknown result type (might be due to invalid IL or missing references) Color val = default(Color); ((Color)(ref val))..ctor(1f, 1f, 1f, 0f); Color val2 = default(Color); ((Color)(ref val2))..ctor(1f, 0.72f, 0.15f, 0.16f); ColorBlock result = default(ColorBlock); ((ColorBlock)(ref result)).normalColor = (current ? val2 : val); ((ColorBlock)(ref result)).highlightedColor = (current ? new Color(1f, 0.72f, 0.15f, 0.26f) : new Color(1f, 1f, 1f, 0.08f)); ((ColorBlock)(ref result)).pressedColor = new Color(1f, 0.72f, 0.15f, 0.32f); ((ColorBlock)(ref result)).selectedColor = (current ? val2 : val); ((ColorBlock)(ref result)).disabledColor = val; ((ColorBlock)(ref result)).colorMultiplier = 1f; ((ColorBlock)(ref result)).fadeDuration = 0.08f; return result; } private static bool PickerIsOpen() { if ((Object)(object)_picker != (Object)null) { return (Object)(object)PickerBlocker.Invoke(_picker) != (Object)null; } return false; } private static string Chips(PortalRecord portal) { Clearance clearanceMask = (Clearance)portal.ClearanceMask; StringBuilder stringBuilder = new StringBuilder("<size=12>"); Clearance[] ladder = ClearanceExtensions.Ladder; foreach (Clearance clearance in ladder) { bool num = (clearanceMask & clearance) == clearance; bool flag = (_carrying & clearance) == clearance; if (num) { stringBuilder.Append(clearance.Symbol()); } else if (flag) { stringBuilder.Append("<color=#E06C4A>" + clearance.Symbol() + "</color>"); } else { stringBuilder.Append("··"); } stringBuilder.Append(' '); } return stringBuilder.ToString().TrimEnd(Array.Empty<char>()) + "</size>"; } private static string Verdict(PortalRecord destination) { if (_carrying == Clearance.None) { return "<size=13>" + Translations.Get("stave_sel_carrying_nothing") + "</size>"; } int num = Candidates.Count(Accepts); string text = "<size=13>" + Translations.Format("stave_sel_tally", num, Candidates.Count) + "</size>"; if (!Accepts(destination)) { return "<size=13><color=#E06C4A>" + Translations.Get("stave_sel_refuses") + "</color></size> " + text; } return "<size=13><color=#8FC97A>" + Translations.Get("stave_sel_takes") + "</color></size> " + text; } private static string FlowNote() { return (StaveboundConfig.Flow?.Value ?? MaterialFlow.Both) switch { MaterialFlow.Both => Translations.Get("stave_sel_flow_both"), MaterialFlow.Deliver => Translations.Get("stave_sel_flow_deliver"), _ => null, }; } private static bool Accepts(PortalRecord portal) { return (ClearanceGate.EffectiveMask(_sourceMask, (Clearance)portal.ClearanceMask) & _carrying) == _carrying; } private static Clearance CarriedTiers(Player player) { Clearance clearance = Clearance.None; Inventory val = ((player != null) ? ((Humanoid)player).GetInventory() : null); if (val == null) { return clearance; } foreach (ItemData allItem in val.GetAllItems()) { if (allItem?.m_shared != null && !allItem.m_shared.m_teleportable) { string prefabName = (((Object)(object)allItem.m_dropPrefab != (Object)null) ? ((Object)allItem.m_dropPrefab).name : null); clearance |= TierMap.RequiredFor(prefabName); } } return clearance; } private static string Bound(string button) { return SelectorKeys.KeyLabel(button); } private static long NearestToHome() { //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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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) PlayerProfile val = (((Object)(object)Game.instance != (Object)null) ? Game.instance.GetPlayerProfile() : null); if (!StaveboundConfig.ColourHomePortal.Value || val == null || !val.HaveCustomSpawnPoint()) { return 0L; } Vector3 customSpawnPoint = val.GetCustomSpawnPoint(); long result = 0L; float num = float.MaxValue; foreach (PortalRecord item in PortalRegistry.All) { Vector3 val2 = item.Position - customSpawnPoint; val2.y = 0f; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; result = item.Pid; } } return result; } private static string Describe(PortalRecord portal) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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) if (StaveboundConfig.HidePortalNames.Value) { return Translations.Format("stave_portal_at", portal.Position.x.ToString("F0"), portal.Position.z.ToString("F0")); } if (!string.IsNullOrEmpty(portal.Name)) { return portal.Name; } return Translations.Get("stave_unnamed_portal"); } private static void BuildPanel() { //IL_0084: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_panel != (Object)null) { Object.Destroy((Object)(object)_panel); } Rows.Clear(); NeedsCandidates.Clear(); float num = Mathf.Clamp((float)(StaveboundConfig.PortalNameLength.Value - 10) * 3f, 0f, 70f); Inner = 400f + num; PanelWidth = Inner + 40f; _panel = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(40f + PanelWidth / 2f, -20f), PanelWidth, 530f); float num2 = 18f; _title = AddText(num2, 24f, 16, (TextAnchor)3); num2 += 28f; GameObject obj = GUIManager.Instance.CreateDropDown(_panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), Vector2.zero, 14, Inner, 32f); Place(obj.GetComponent<RectTransform>(), num2, 32f, Inner); _picker = obj.GetComponent<Dropdown>(); Dropdown picker = _picker; Navigation navigation = default(Navigation); ((Navigation)(ref navigation)).mode = (Mode)0; ((Selectable)picker).navigation = navigation; ((UnityEvent<int>)(object)_picker.onValueChanged).AddListener((UnityAction<int>)OnPicked); _pickerStale = true; NeedsCandidates.Add((Selectable)(object)_picker); num2 += 38f; _status = AddText(num2, 56f, 13, (TextAnchor)0); num2 += 58f; _moreAbove = AddText(num2, 18f, 12, (TextAnchor)3); num2 += 18f; for (int i = 0; i < 9; i++) { Rows.Add(AddRow(num2, i)); num2 += 28f; } _moreBelow = AddText(num2, 18f, 12, (TextAnchor)3); num2 += 24f; float num3 = (Inner - 12f) / 4f; float num4 = (0f - Inner) / 2f + num3 / 2f; NeedsCandidates.Add((Selectable)(object)AddButton("[" + Bound("stave_previous") + "]", num2, 30f, num3, num4, delegate { Step(-1); })); NeedsCandidates.Add((Selectable)(object)AddButton("[" + Bound("stave_next") + "]", num2, 30f, num3, num4 + (num3 + 4f), delegate { Step(1); })); AddButton("[" + Bound("stave_sort") + "] " + Translations.Get("stave_sel_sort"), num2, 30f, num3, num4 + 2f * (num3 + 4f), ToggleSort); AddButton("[" + Bound("stave_filter") + "] " + Translations.Get("stave_sel_filter"), num2, 30f, num3, num4 + 3f * (num3 + 4f), ToggleFilter); num2 += 36f; float num5 = (Inner - 6f) / 2f; NeedsCandidates.Add((Selectable)(object)AddButton("[" + Bound("stave_confirm") + "] " + Translations.Get("stave_sel_confirm"), num2, 34f, num5, (0f - num5) / 2f - 3f, Commit)); AddButton("[" + Bound("stave_cancel") + "] " + Translations.Get("stave_sel_cancel"), num2, 34f, num5, num5 / 2f + 3f, Close); } private static void Place(RectTransform rect, float top, float height, float width, float x = 0f) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) rect.anchorMin = new Vector2(0.5f, 1f); rect.anchorMax = new Vector2(0.5f, 1f); rect.pivot = new Vector2(0.5f, 1f); rect.sizeDelta = new Vector2(width, height); rect.anchoredPosition = new Vector2(x, 0f - top); } private static Text AddText(float top, float height, int size, TextAnchor alignment) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) Text obj = CreateLabel(_panel.transform, size, alignment); Place(((Graphic)obj).rectTransform, top, height, Inner); return obj; } private static Text CreateLabel(Transform parent, int size, TextAnchor alignment) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_003e: 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_005f: Unknown result type (might be due to invalid IL or missing references) Text component = GUIManager.Instance.CreateText(string.Empty, parent, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, GUIManager.Instance.AveriaSerifBold, size, GUIManager.Instance.ValheimOrange, true, Color.black, Inner, 28f, false).GetComponent<Text>(); component.alignment = alignment; component.supportRichText = true; ((Graphic)component).raycastTarget = false; return component; } private static RowView AddRow(float top, int slot) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: 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) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Expected O, but got Unknown //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject($"StaveboundRow{slot}", new Type[1] { typeof(RectTransform) }); val.SetActive(false); val.transform.SetParent(_panel.transform, false); Place((RectTransform)val.transform, top, 28f, Inner); Image val2 = val.AddComponent<Image>(); ((Graphic)val2).color = Color.white; RowView view = new RowView { Root = val, Button = val.AddComponent<Button>() }; ((Selectable)view.Button).targetGraphic = (Graphic)(object)val2; ((Selectable)view.Button).transition = (Transition)1; ((Selectable)view.Button).colors = RowColours(current: false); Button button = view.Button; Navigation navigation = default(Navigation); ((Navigation)(ref navigation)).mode = (Mode)0; ((Selectable)button).navigation = navigation; ((UnityEvent)view.Button.onClick).AddListener((UnityAction)delegate { OnRowClicked(view); Unfocus(); }); val.AddComponent<SelectorRowHover>().Row = view; view.Name = CreateLabel(val.transform, 15, (TextAnchor)3); RectTransform rectTransform = ((Graphic)view.Name).rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.pivot = new Vector2(0f, 0.5f); rectTransform.offsetMin = new Vector2(6f, 0f); rectTransform.offsetMax = new Vector2(-140f, 0f); view.Name.horizontalOverflow = (HorizontalWrapMode)0; view.Name.verticalOverflow = (VerticalWrapMode)0; view.Chips = CreateLabel(val.transform, 12, (TextAnchor)5); RectTransform rectTransform2 = ((Graphic)view.Chips).rectTransform; rectTransform2.anchorMin = new Vector2(1f, 0f); rectTransform2.anchorMax = new Vector2(1f, 1f); rectTransform2.pivot = new Vector2(1f, 0.5f); rectTransform2.sizeDelta = new Vector2(132f, 0f); rectTransform2.anchoredPosition = new Vector2(-6f, 0f); return view; } private static Button AddButton(string label, float top, float height, float width, float x, Action action) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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_0087: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown GameObject obj = GUIManager.Instance.CreateButton(label, _panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), Vector2.zero, width, height); Place(obj.GetComponent<RectTransform>(), top, height, width, x); Text componentInChildren = obj.GetComponentInChildren<Text>(); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.resizeTextForBestFit = true; componentInChildren.resizeTextMinSize = 9; componentInChildren.resizeTextMaxSize = 14; } Button component = obj.GetComponent<Button>(); Navigation navigation = default(Navigation); ((Navigation)(ref navigation)).mode = (Mode)0; ((Selectable)component).navigation = navigation; ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { action(); Unfocus(); }); return component; } private static void OnRowClicked(RowView row) { if (row.Candidate >= 0 && row.Candidate < Candidates.Count) { _highlight = row.Candidate; if (StaveboundConfig.ClickPicksPortal.Value) { Commit(); } else { ShowHighlight(); } } } private static void OnPicked(int index) { if (index >= 0 && index < Candidates.Count) { _highlight = index; if (StaveboundConfig.ClickPicksPortal.Value) { Commit(); return; } ShowHighlight(); Unfocus(); } } private static void Unfocus() { if ((Object)(object)EventSystem.current != (Object)null) { EventSystem.current.SetSelectedGameObject((GameObject)null); } } private static int Stepped() { if (SelectorKeys.Pressed("stave_next")) { return 1; } if (!SelectorKeys.Pressed("stave_previous")) { return 0; } return -1; } private static bool Confirmed() { return SelectorKeys.Pressed("stave_confirm"); } private static bool Cancelled() { return SelectorKeys.Pressed("stave_cancel"); } } internal sealed class SelectorRowHover : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler { internal DestinationSelector.RowView Row; public void OnPointerEnter(PointerEventData eventData) { DestinationSelector.HoverEntered(Row); } public void OnPointerExit(PointerEventData eventData) { DestinationSelector.HoverLeft(Row); } } } namespace Stavebound.Travel { internal static class ApproachWarning { private static ZDOID _warnedAbout = ZDOID.None; internal static void Consider(ZDO portal, ZDO destination, Player nearby, bool allowed) { //IL_0037: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) if (portal == null) { return; } if ((Object)(object)nearby == (Object)null || (Object)(object)nearby != (Object)(object)Player.m_localPlayer) { Forget(portal); } else if (allowed || !StaveboundConfig.WarnOnApproach.Value) { Forget(portal); } else if (!(_warnedAbout == portal.m_uid)) { ClearanceGate.Refusal refusal = ClearanceGate.FirstRefusal(((Humanoid)nearby).GetInventory(), ClearanceGate.EffectiveMask(portal, destination)); if (refusal != null) { _warnedAbout = portal.m_uid; ((Character)nearby).Message((MessageType)2, ClearanceGate.Explain(refusal, destination.GetString(ZDOVars.s_tag, string.Empty)), 0, (Sprite)null, false); } } } private static void Forget(ZDO portal) { //IL_0000: 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_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) if (_warnedAbout == portal.m_uid) { _warnedAbout = ZDOID.None; } } internal static void Reset() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) _warnedAbout = ZDOID.None; } } internal static class CargoPreview { internal static bool TryGetNearbyDestination(out Clearance mask, out bool allowsEverything) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) mask = Clearance.None; allowsEverything = false; if (!StaveboundConfig.ShowBlockedCargoOverlay.Value || (Object)(object)Player.m_localPlayer == (Object)null) { return false; } TeleportWorld val = PortalTarget.FindNearest(((Component)Player.m_localPlayer).transform.position, StaveboundConfig.CargoPreviewRange.Value); if ((Object)(object)val == (Object)null) { return false; } if (val.m_allowAllItems) { allowsEverything = true; return true; } ZDO val2 = PortalTarget.ZdoOf(val); if (!ClearanceGate.TryResolveDestination(val2, out var destination, out var _) || destination == null) { return false; } mask = ClearanceGate.EffectiveMask(val2, destination); return true; } internal static bool WouldBeRefused(ItemData item, Clearance destinationMask, bool allowsEverything) { if (item?.m_shared == null || item.m_shared.m_teleportable) { return false; } if (allowsEverything) { return false; } string prefabName = (((Object)(object)item.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : null); return !destinationMask.Permits(TierMap.RequiredFor(prefabName)); } } internal static class ClearanceGate { internal sealed class Refusal { internal string Item; internal Clearance Missing; internal int OtherStacks; } internal static bool TryResolveDestination(ZDO portal, out ZDO destination, out long pendingPid) { //IL_0043: 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_005a: 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) destination = null; pendingPid = 0L; if (portal == null || ZDOMan.instance == null) { return false; } long destination2 = PortalTarget.GetDestination(portal); if (destination2 != 0L) { if (!PortalRegistry.TryGet(destination2, out var record)) { return false; } pendingPid = destination2; destination = ZDOMan.instance.GetZDO(record.Id); return true; } ZDOID connectionZDOID = portal.GetConnectionZDOID((ConnectionType)1); if (((ZDOID)(ref connectionZDOID)).IsNone()) { return false; } destination = ZDOMan.instance.GetZDO(connectionZDOID); return true; } internal static bool Allows(Player player, ZDO source, ZDO destination, bool allowAllItems) { if (allowAllItems) { return true; } if ((Object)(object)player != (Object)null) { return FirstRefusal(((Humanoid)player).GetInventory(), EffectiveMask(source, destination)) == null; } return false; } internal static Refusal FirstRefusal(Inventory inventory, Clearance permitted) { if (inventory == null) { return null; } Refusal refusal = null; int num = 0; foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem?.m_shared == null || allItem.m_shared.m_teleportable) { continue; } string text = (((Object)(object)allItem.m_dropPrefab != (Object)null) ? ((Object)allItem.m_dropPrefab).name : null); Clearance clearance = TierMap.RequiredFor(text); if (!permitted.Permits(clearance)) { if (refusal == null) { refusal = new Refusal { Item = ((Localization.instance != null) ? Localization.instance.Localize(allItem.m_shared.m_name) : text), Missing = clearance }; } else { num++; } } } if (refusal != null) { refusal.OtherStacks = num; } return refusal; } internal static string Explain(Refusal refusal, string destinationName) { string text; if (refusal.Missing == Clearance.Sealed) { text = Translations.Format("stave_refusal_sealed", refusal.Item); } else { string text2 = (string.IsNullOrEmpty(destinationName) ? Translations.Get("stave_that_portal") : ("\"" + destinationName + "\"")); text = Translations.Format("stave_refusal", refusal.Item, text2, refusal.Missing.StaveName()); } if (refusal.OtherStacks > 0) { text += Translations.Format("stave_refusal_more", refusal.OtherStacks); } return text; } internal static Clearance MaskOf(ZDO portal) { if (portal != null) { return (Clearance)portal.GetInt(ZdoKeys.ClearanceMask, 0); } return Clearance.None; } internal static Clearance EffectiveMask(ZDO source, ZDO destination) { return EffectiveMask(MaskOf(source), MaskOf(destination)); } internal static Clearance EffectiveMask(Clearance source, Clearance destination) { MaterialFlow num = StaveboundConfig.Flow?.Value ?? MaterialFlow.Both; Clearance clearance = Clearance.None; if (num != MaterialFlow.Deliver) { clearance |= destination; } if (num != MaterialFlow.Receive) { clearance |= source; } return clearance; } } internal static class SeamlessTransit { private const float VanillaPause = 2f; private static readonly FieldRef<Player, float> TeleportTimer = AccessTools.FieldRefAccess<Player, float>("m_teleportTimer"); internal static bool Enabled => StaveboundConfig.SeamlessTransit.Value; internal static bool DestinationIsLoaded(Vector3 destination) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNetScene.instance != (Object)null) { return ZNetScene.instance.IsAreaReady(destination); } return false; } internal static bool NeedsLoadingScreen(Vector3 destination) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) if (Enabled) { return !DestinationIsLoaded(destination); } return true; } internal static void ShortenPause(Player player, Vector3 destination) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null) && !NeedsLoadingScreen(destination)) { float num = Mathf.Clamp(StaveboundConfig.TransitPause.Value, 0f, 2f); TeleportTimer.Invoke(player) = 2f - num; } } internal static bool ArrivalIsReady(Vector3 destination) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) if (Enabled) { return DestinationIsLoaded(destination); } return false; } } internal static class StaleTravellers { private sealed class Watch { internal uint Revision; internal float Changed; internal float Requested; } private const float SweepSeconds = 2f; private const float AwayMetres = 100f; private const float StaleSeconds = 5f; private const float RequestCooldown = 10f; private static readonly Dictionary<ZDOID, Watch> Watched = new Dictionary<ZDOID, Watch>(); private static readonly List<ZDOID> Forgotten = new List<ZDOID>(); private static Coroutine _sweep; internal static void OnWorldStart() { OnWorldEnd(); if (!((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer()) { _sweep = ((MonoBehaviour)Plugin.Instance).StartCoroutine(Sweep()); } } internal static void OnWorldEnd() { if (_sweep != null) { if ((Object)(object)Plugin.Instance != (Object)null) { ((MonoBehaviour)Plugin.Instance).StopCoroutine(_sweep); } _sweep = null; } Watched.Clear(); } private static IEnumerator Sweep() { WaitForSeconds wait = new WaitForSeconds(2f); while (true) { yield return wait; try { Look(); } catch (Exception arg) { Logger.LogError((object)$"Stale-traveller sweep failed, and has stopped: {arg}"); _sweep = null; break; } } } private static void Look() { //IL_002e: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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_007b: 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_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) if (!StaveboundConfig.ClearLeftBehindBodies.Value || (Object)(object)ZNet.instance == (Object)null || ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null) { return; } ZDOID val = LocalPlayer(); float unscaledTime = Time.unscaledTime; Forgotten.Clear(); Forgotten.AddRange(Watched.Keys); foreach (PlayerInfo player in ZNet.instance.GetPlayerList()) { ZDOID characterID = player.m_characterID; if (((ZDOID)(ref characterID)).IsNone() || ((ZDOID)(ref characterID)).Equals(val)) { continue; } Forgotten.Remove(characterID); ZDO zDO = ZDOMan.instance.GetZDO(characterID); if (zDO == null || (Object)(object)ZNetScene.instance.FindInstance(characterID) == (Object)null) { Watched.Remove(characterID); continue; } if (!Watched.TryGetValue(characterID, out var value)) { value = new Watch { Revision = zDO.DataRevision, Changed = unscaledTime }; Watched[characterID] = value; } else if (value.Revision != zDO.DataRevision) { value.Revision = zDO.DataRevision; value.Changed = unscaledTime; } if (!(unscaledTime - value.Requested < 10f) && Suspect(player, zDO, value, unscaledTime, out var why)) { value.Requested = unscaledTime; ZDOMan.instance.RequestZDO(characterID); SyncLog.Say("[stale] " + player.m_name + " " + why + " - asked the server for a fresh copy. If they have gone, the body they left here goes with it."); } } foreach (ZDOID item in Forgotten) { Watched.Remove(item); } } private static bool Suspect(PlayerInfo info, ZDO zdo, Watch watch, float now, out string why) { //IL_0000: 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_000e: 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) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (info.m_publicPosition) { Vector3 val = zdo.GetPosition() - info.m_position; val.y = 0f; float magnitude = ((Vector3)(ref val)).magnitude; why = $"is drawn {magnitude:F0}m from where the server says they are"; return magnitude > 100f; } why = $"has not changed in {now - watch.Changed:F0}s and hides their position"; return now - watch.Changed > 5f; } private static ZDOID LocalPlayer() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) ZNetView val = (((Object)(object)Player.m_localPlayer != (Object)null) ? ((Component)Player.m_localPlayer).GetComponent<ZNetView>() : null); return (((Object)(object)val != (Object)null) ? val.GetZDO() : null)?.m_uid ?? ZDOID.None; } } } namespace Stavebound.Tiers { internal sealed class BlockedItemsCommand : StaveboundCommand { public override string Name => "stave_items"; public override string Help => "List every item the game refuses to teleport, grouped by the stave that will permit it. Anything unrecognised is listed separately and defaults to the highest tier."; protected override void Execute(string[] args, Terminal context) { if (!TierMap.Built) { StaveboundCommand.Echo(context, "Stavebound: the tier map has not been built yet. Load a world first — the main menu's item database is only a partial one."); return; } StaveboundCommand.Echo(context, $"Stavebound tiers - {TierMap.BlockedCount} blocked item(s):"); Clearance[] array = new Clearance[5] { Clearance.Elder, Clearance.Bonemass, Clearance.Moder, Clearance.Yagluth, Clearance.Ashen }; foreach (Clearance tier in array) { List<string> list = TierMap.AtTier(tier).Select(TierMap.Describe).ToList(); StaveboundCommand.Echo(context, $" {tier.StaveName()} ({list.Count}): " + ((list.Count == 0) ? "nothing" : string.Join(", ", list))); } IReadOnlyList<string> unclassifiedItems = TierMap.UnclassifiedItems; if (unclassifiedItems.Count == 0) { StaveboundCommand.Echo(context, " Every blocked item is classified."); return; } StaveboundCommand.Echo(context, $" UNCLASSIFIED ({unclassifiedItems.Count}), defaulting to " + Clearance.Ashen.StaveName() + ":"); foreach (string item in unclassifiedItems.OrderBy((string n) => n)) { StaveboundCommand.Echo(context, " " + TierMap.Describe(item)); } StaveboundCommand.Echo(context, " Add these to the 2 - Clearance config lists to place them properly."); } } [Flags] internal enum Clearance { None = 0, Elder = 1, Bonemass = 2, Moder = 4, Yagluth = 8, Queen = 0x10, Ashen = 0x20, Sealed = 0x40 } internal static class ClearanceExtensions { internal const Clearance Highest = Clearance.Ashen; internal const Clearance All = Clearance.Elder | Clearance.Bonemass | Clearance.Moder | Clearance.Yagluth | Clearance.Queen | Clearance.Ashen; internal static readonly Clearance[] Ladder = new Clearance[6] { Clearance.Elder, Clearance.Bonemass, Clearance.Moder, Clearance.Yagluth, Clearance.Queen, Clearance.Ashen }; internal static Clearance UpToFirstGap(Clearance mask) { Clearance clearance = Clearance.None; Clearance[] ladder = Ladder; foreach (Clearance clearance2 in ladder) { if ((mask & clearance2) != clearance2) { break; } clearance |= clearance2; } return clearance; } internal static bool Permits(this Clearance mask, Clearance required) { if (required != Clearance.None) { return (mask & required) == required; } return true; } internal static string Symbol(this Clearance tier) { return tier switch { Clearance.Elder => "Cu", Clearance.Bonemass => "Fe", Clearance.Moder => "Ag", Clearance.Yagluth => "Bm", Clearance.Queen => "Dv", Clearance.Ashen => "Fl", _ => "--", }; } internal static string StaveName(this Clearance tier) { return Translations.Get(tier.NameToken()); } internal static string NameToken(this Clearance tier) { return tier switch { Clearance.Elder => "stave_rune_elder", Clearance.Bonemass => "stave_rune_bonemass", Clearance.Moder => "stave_rune_moder", Clearance.Yagluth => "stave_rune_yagluth", Clearance.Queen => "stave_rune_queen", Clearance.Ashen => "stave_rune_ashen", _ => "stave_rune_none", }; } } internal sealed class PrefabInspectCommand : StaveboundCommand { private const int MaxDepth = 4; public override string Name => "stave_inspect"; public override string Help => "stave_inspect <prefab> - show a prefab's child objects, renderers, materials and shader colour properties. Use it to find out what can be lit or tinted separately."; protected override void Execute(string[] args, Terminal context) { string text = string.Join(" ", args).Trim(); if (text.Length == 0) { StaveboundCommand.Echo(context, "Stavebound: name a prefab, e.g. stave_inspect portal_wood"); return; } if ((Object)(object)ZNetScene.instance == (Object)null) { StaveboundCommand.Echo(context, "Stavebound: no world loaded."); return; } GameObject prefab = ZNetScene.instance.GetPrefab(text); if ((Object)(object)prefab == (Object)null) { StaveboundCommand.Echo(context, "Stavebound: no prefab called \"" + text + "\". Try stave_prefabs " + text); return; } StaveboundCommand.Echo(context, "Stavebound inspect - " + ((Object)prefab).name); Describe(context, prefab.transform, 0); } private static void Describe(Terminal context, Transform node, int depth) { string text = new string(' ', (depth + 1) * 2); List<string> list = (from c in ((Component)node).GetComponents<Component>() where (Object)(object)c != (Object)null && !(c is Transform) select ((object)c).GetType().Name).ToList(); StringBuilder stringBuilder = new StringBuilder(text + ((Object)node).name); if (list.Count > 0) { stringBuilder.Append(" [" + string.Join(", ", list) + "]"); } if (!((Component)node).gameObject.activeSelf) { stringBuilder.Append(" (inactive)"); } StaveboundCommand.Echo(context, stringBuilder.ToString()); Renderer component = ((Component)node).GetComponent<Renderer>(); if ((Object)(object)component != (Object)null) { foreach (Material item in component.sharedMaterials.Where((Material m) => (Object)(object)m != (Object)null)) { string[] obj = new string[7] { text, " material '", ((Object)item).name, "' shader '", null, null, null }; Shader shader = item.shader; obj[4] = ((shader != null) ? ((Object)shader).name : null); obj[5] = "'"; obj[6] = DescribeColours(item); StaveboundCommand.Echo(context, string.Concat(obj)); } } if (depth >= 4) { if (node.childCount > 0) { StaveboundCommand.Echo(context, $"{text} ... {node.childCount} more child object(s), deeper than this dump goes"); } } else { for (int num = 0; num < node.childCount; num++) { Describe(context, node.GetChild(num), depth + 1); } } } private static string DescribeColours(Material material) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) List<string> list = new List<string>(); string[] array = new string[4] { "_Color", "_EmissionColor", "_EmissiveColor", "_TintColor" }; foreach (string text in array) { try { if (material.HasProperty(text)) { list.Add($"{text}={material.GetColor(text)}"); } } catch (Exception) { } } if (list.Count != 0) { return " " + string.Join(" ", list); } return string.Empty; } } internal sealed class PrefabPreviewCommand : StaveboundCommand { private static readonly List<GameObject> Previews = new List<GameObject>(); public override string Name => "stave_preview"; public override string Help => "stave_preview <prefab> - place a look-at-only copy in front of you. It is not saved, not networked and vanishes on reload. 'stave_preview clear' removes them. For anything spawnable, use vanilla spawn instead."; protected override void Execute(string[] args, Terminal context) { //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) string text = string.Join(" ", args).Trim(); if (string.Equals(text, "clear", StringComparison.OrdinalIgnoreCase)) { Clear(context); return; } if (text.Length == 0) { StaveboundCommand.Echo(context, "Stavebound: name a prefab, or 'clear' to remove the previews."); return; } if ((Object)(object)ZNetScene.instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null) { StaveboundCommand.Echo(context, "Stavebound: no world loaded."); return; } GameObject prefab = ZNetScene.instance.GetPrefab(text); if ((Object)(object)prefab == (Object)null) { StaveboundCommand.Echo(context, "Stavebound: no prefab called \"" + text + "\". Try stave_prefabs " + text); } else if ((Object)(object)prefab.GetComponent<ZNetView>() != (Object)null) { StaveboundCommand.Echo(context, "Stavebound: " + ((Object)prefab).name + " is a networked object - use 'spawn " + ((Object)prefab).name + "' instead, which places it properly and can be removed with the hammer."); } else { Transform transform = ((Component)Player.m_localPlayer).transform; Vector3 val = transform.position + transform.forward * 3f; GameObject val2 = Object.Instantiate<GameObject>(prefab, val, transform.rotation); ((Object)val2).name = "stave_preview_" + ((Object)prefab).name; Previews.Add(val2); StaveboundCommand.Echo(context, "Stavebound: previewing " + ((Object)prefab).name + " in front of you " + $"({Previews.Count} up). This is scenery only - nothing was added to the world."); } } private static void Clear(Terminal context) { int num = Previews.Count((GameObject p) => (Object)(object)p != (Object)null); foreach (GameObject item in Previews.Where((GameObject p) => (Object)(object)p != (Object)null)) { Object.Destroy((Object)(object)item); } Previews.Clear(); StaveboundCommand.Echo(context, (num == 0) ? "Stavebound: nothing was being previewed." : $"Stavebound: removed {num} preview(s)."); } } internal sealed class PrefabSearchCommand : StaveboundCommand { private const int Limit = 60; public override string Name => "stave_prefabs"; public override string Help => "stave_prefabs <text>[,<text>...] - list loaded prefabs whose name contains each term, marking which are buildable pieces and which are items. Comma-separate to search for several things at once."; protected override void Execute(string[] args, Terminal context) { if ((Object)(object)ZNetScene.instance == (Object)null) { StaveboundCommand.Echo(context, "Stavebound: no world loaded - prefabs only exist once you are in a game."); return; } string[] array = (from t in string.Join(" ", args).Split(new char[1] { ',' }) select t.Trim() into t where t.Length > 0 select t).ToArray(); if (array.Length == 0) { StaveboundCommand.Echo(context, "Stavebound: give me something to search for, e.g. stave_prefabs trophy,sconce,brazier"); return; } string[] array2 = array; foreach (string term in array2) { Search(context, term); } } private static void Search(Terminal context, string term) { List<GameObject> list = (from p in ZNetScene.instance.m_prefabs where (Object)(object)p != (Object)null && ((Object)p).name.IndexOf(term, StringComparison.OrdinalIgnoreCase) >= 0 orderby ((Object)p).name select p).ToList(); if (list.Count == 0) { StaveboundCommand.Echo(context, "\"" + term + "\": nothing."); return; } StaveboundCommand.Echo(context, $"\"{term}\": {list.Count}" + ((list.Count > 60) ? $" (showing {60})" : string.Empty)); foreach (GameObject item in list.Take(60)) { List<string> list2 = new List<string>(); if ((Object)(object)item.GetComponent<Piece>() != (Object)null) { list2.Add("piece"); } ItemDrop component = item.GetComponent<ItemDrop>(); if (component?.m_itemData?.m_shared != null) { list2.Add("item \"" + Localization.instance.Localize(component.m_itemData.m_shared.m_name) + "\""); } StaveboundCommand.Echo(context, " " + ((Object)item).name + ((list2.Count > 0) ? (" [" + string.Join(", ", list2) + "]") : string.Empty)); } } } internal static class TierMap { private static readonly Dictionary<string, Clearance> Required = new Dictionary<string, Clearance>(StringComparer.OrdinalIgnoreCase); private static readonly List<string> Unclassified = new List<string>(); private static readonly Dictionary<string, string> DisplayTokens = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); internal static bool Built { get; private set; } internal static int BlockedCount => Required.Count; internal static IReadOnlyList<string> UnclassifiedItems => Unclassified; internal static Clearance RequiredFor(string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return Clearance.None; } if (!Required.TryGetValue(prefabName, out var value)) { return Clearance.None; } return value; } internal static IEnumerable<string> AtTier(Clearance tier) { return from pair in Required where pair.Value == tier select pair.Key into name orderby name select name; } internal static string Describe(string prefabName) { if (!DisplayTokens.TryGetValue(prefabName, out var value) || string.IsNullOrEmpty(value)) { return prefabName; } string text = ((Localization.instance != null) ? Localization.instance.Localize(value) : value); if (!string.Equals(text, prefabName, StringComparison.OrdinalIgnoreCase)) { return prefabName + " (" + text + ")"; } return prefabName; } internal static void Build() { ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null || instance.m_items == null || instance.m_items.Count == 0) { return; } Required.Clear(); Unclassified.Clear(); DisplayTokens.Clear(); Dictionary<string, Clearance> dictionary = ReadConfiguredTiers(); foreach (GameObject item in instance.m_items) { if ((Object)(object)item == (Object)null) { continue; } ItemDrop component = item.GetComponent<ItemDrop>(); if (!((Object)(object)component == (Object)null) && component.m_itemData?.m_shared != null && !component.m_itemData.m_shared.m_teleportable) { string name = ((Object)item).name; DisplayTokens[name] = component.m_itemData.m_shared.m_name; if (dictionary.TryGetValue(name, out var value)) { Required[name] = value; continue; } Required[name] = Clearance.Ashen; Unclassified.Add(name); } } Built = true; Logger.LogInfo((object)$"Tier map built: {Required.Count} blocked item(s) across {instance.m_items.Count} in ObjectDB."); if (Unclassified.Count > 0) { Logger.LogWarning((object)($"{Unclassified.Count} blocked item(s) are not in the tier config and default to " + $"{Clearance.Ashen} ({Clearance.Ashen.StaveName()}): " + string.Join(", ", Unclassified.OrderBy((string n) => n)) + ". Add them to the 2 - Clearance section to place them properly.")); } } private static Dictionary<string, Clearance> ReadConfiguredTiers() { Dictionary<string, Clearance> dictionary = new Dictionary<string, Clearance>(StringComparer.OrdinalIgnoreCase); foreach (KeyValuePair<Clearance, string> item in StaveboundConfig.TierPrefabs()) { string[] array = item.Value.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length != 0) { if (dictionary.TryGetValue(text, out var value) && value != item.Key) { Logger.LogWarning((object)($"'{text}' is listed under both {value} and {item.Key}. Using {value}; " + "remove one of them.")); } else { dictionary[text] = item.Key; } } } } return dictionary; } } } namespace Stavebound.Staves { internal static class CoreTint { private static readonly string[] ColourProperties = new string[3] { "_EmissionColor", "_Color", "_TintColor" }; internal static void Apply(GameObject prefab, Color tint, string describe) { //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0172: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null) { return; } List<string> list = new List<string>(); Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { Material[] sharedMaterials = val.sharedMaterials; bool flag = false; for (int j = 0; j < sharedMaterials.Length; j++) { Material val2 = sharedMaterials[j]; if ((Object)(object)val2 == (Object)null || !IsEmissive(val2)) { continue; } Material val3 = new Material(val2) { name = ((Object)val2).name + "_" + describe }; string[] colourProperties = ColourProperties; foreach (string text in colourProperties) { if (val3.HasProperty(text)) { val3.SetColor(text, (text == "_EmissionColor") ? AtIntensityOf(tint, val2.GetColor(text)) : tint); } } sharedMaterials[j] = val3; flag = true; } if (flag) { val.sharedMaterials = sharedMaterials; list.Add("material on " + ((Object)val).name); } } Light[] componentsInChildren2 = prefab.GetComponentsInChildren<Light>(true); foreach (Light val4 in componentsInChildren2) { val4.color = tint; list.Add("light on " + ((Object)val4).name); } ParticleSystem[] componentsInChildren3 = prefab.GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem val5 in componentsInChildren3) { MainModule main = val5.main; ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(tint); list.Add("particles on " + ((Object)val5).name); } Logger.LogInfo((object)((list.Count == 0) ? ("Tint " + describe + ": found nothing emissive on " + ((Object)prefab).name + " - the glow is not where this expects it.") : string.Format("Tint {0} on {1}: {2} target(s) - {3}", describe, ((Object)prefab).name, list.Count, string.Join(", ", list.Distinct())))); } private static Color AtIntensityOf(Color tint, Color original) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_003e: 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) float maxColorComponent = ((Color)(ref original)).maxColorComponent; float maxColorComponent2 = ((Color)(ref tint)).maxColorComponent; if (maxColorComponent <= 0f || maxColorComponent2 <= 0f) { return tint; } float num = maxColorComponent / maxColorComponent2; return new Color(tint.r * num, tint.g * num, tint.b * num, tint.a); } private static bool IsEmissive(Material material) { //IL_002f: 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) if (material.IsKeywordEnabled("_EMISSION") || material.IsKeywordEnabled("_EMISSIVE")) { return true; } if (material.HasProperty("_EmissionColor")) { Color color = material.GetColor("_EmissionColor"); return ((Color)(ref color)).maxColorComponent > 0.01f; } return false; } } internal static class PlacementFeedback { private const float SearchInterval = 0.2f; private static readonly Vector3 BeamLift = Vector3.up * 1.2f; private static GameObject _circle; private static CircleProjector _projector; private static GameObject _beam; private static bool _beamUnavailable; private static bool _circleUnavailable; private static float _nextSearch; private static readonly List<TeleportWorld> InRange = new List<TeleportWorld>(); private static string _lastAnswer; internal static void Update(GameObject ghost) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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) if ((Object)(object)ghost == (Object)null || !IsOurs(ghost)) { Hide(); return; } Vector3 position = ghost.transform.position; float value = StaveboundConfig.StaveRadius.Value; Search(position, value); bool num = StaveboundConfig.Binding.Value == PortalBinding.AllInRadius; TeleportWorld val = ((InRange.Count > 0) ? InRange[0] : null); if (!num && (Object)(object)val != (Object)null) { ShowBeam(position + BeamLift, ((Component)val).transform.position + BeamLift); HideCircle(); } else { ShowCircle(position, value); HideBeam(); } Announce(num); } internal static void Reset() { if ((Object)(object)_circle != (Object)null) { Object.Destroy((Object)(object)_circle); } if ((Object)(object)_beam != (Object)null) { Object.Destroy((Object)(object)_beam); } _circle = null; _projector = null; _beam = null; _beamUnavailable = false; _circleUnavailable = false; _lastAnswer = null; _nextSearch = 0f; InRange.Clear(); } private static bool IsOurs(GameObject ghost) { return StavePieces.ClearanceOf(((Object)ghost).name.Replace("(Clone)", string.Empty).Trim()) != Clearance.None; } private static void Search(Vector3 at, float radius) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (!(Time.time < _nextSearch)) { _nextSearch = Time.time + 0.2f; float limit = radius * radius; InRange.Clear(); InRange.AddRange(LoadedPortals.Current().Where(delegate(TeleportWorld p) { //IL_0006: 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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)p).transform.position - at; return ((Vector3)(ref val)).sqrMagnitude <= limit; }).OrderBy(delegate(TeleportWorld p) { //IL_0006: 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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)p).transform.position - at; return ((Vector3)(ref val)).sqrMagnitude; })); } } private static void ShowBeam(Vector3 from, Vector3 to) { //IL_0016: 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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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_0073: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_beam == (Object)null && !BuildBeam(from)) { return; } Vector3 val = to - from; if (!(((Vector3)(ref val)).sqrMagnitude < 0.001f)) { _beam.transform.position = from; _beam.transform.rotation = Quaternion.LookRotation(((Vector3)(ref val)).normalized); _beam.transform.localScale = new Vector3(1f, 1f, ((Vector3)(ref val)).magnitude); if (!_beam.activeSelf) { _beam.SetActive(true); } } } private static bool BuildBeam(Vector3 at) { //IL_0054: 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) if (_beamUnavailable) { return false; } StationExtension val = ((IEnumerable<StationExtension>)Resources.FindObjectsOfTypeAll<StationExtension>()).FirstOrDefault((Func<StationExtension, bool>)((StationExtension e) => (Object)(object)e != (Object)null && (Object)(object)e.m_connectionPrefab != (Object)null)); if ((Object)(object)val == (Object)null) { _beamUnavailable = true; Logger.LogWarning((object)"No station-connection effect to borrow, so stave binding will be shown as a circle instead of a beam."); return false; } _beam = Object.Instantiate<GameObject>(val.m_connectionPrefab, at, Quaternion.identity); ((Object)_beam).name = "stave_binding_beam"; return true; } private static void HideBeam() { if ((Object)(object)_beam != (Object)null && _beam.activeSelf) { _beam.SetActive(false); } } private static void ShowCircle(Vector3 at, float radius) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_projector == (Object)null) || BuildCircle()) { _circle.transform.position = at; _projector.m_radius = radius; if (!_circle.activeSelf) { _circle.SetActive(true); } } } private static bool BuildCircle() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if (_circleUnavailable) { return false; } CircleProjector val = ((IEnumerable<CircleProjector>)Resources.FindObjectsOfTypeAll<CircleProjector>()).FirstOrDefault((Func<CircleProjector, bool>)((CircleProjector c) => (Object)(object)c != (Object)null && (Object)(object)c.m_prefab != (Object)null)); if ((Object)(object)val == (Object)null) { _circleUnavailable = true; Logger.LogWarning((object)"No CircleProjector to borrow, so stave range will not be drawn. The portal it binds to is still named on placement."); return false; } _circle = new GameObject("stave_range"); _projector = _circle.AddComponent<CircleProjector>(); _projector.m_prefab = val.m_prefab; _projector.m_mask = val.m_mask; _projector.m_nrOfSegments = val.m_nrOfSegments; return true; } private static void HideCircle() { if ((Object)(object)_circle != (Object)null && _circle.activeSelf) { _circle.SetActive(false); } } private static void Hide() { HideCircle(); HideBeam(); _lastAnswer = null; } private static void Announce(bool all) { string text = Describe(all); if (!(text == _lastAnswer)) { _lastAnswer = text; Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, text, 0, (Sprite)null, false); } } } private static string Describe(bool all) { if (InRange.Count == 0) { return Translations.Get("stave_place_no_portal"); } if (all) { if (InRange.Count != 1) { return Translations.Format("stave_place_binds_all", InRange.Count); } return Translations.Format("stave_place_binds", Name(InRange[0])); } if (InRange.Count != 1) { return Translations.Format("stave_place_binds_nearest", Name(InRange[0]), InRange.Count); } return Translations.Format("stave_place_binds", Name(InRange[0])); } private static string Name(TeleportWorld portal) { ZDO val = PortalTarget.ZdoOf(portal); string text = ((val != null) ? val.GetString(ZDOVars.s_tag, string.Empty) : string.Empty); if (!string.IsNullOrEmpty(text)) { return "\"" + text + "\""; } return Translations.Get("stave_an_unnamed_portal"); } } internal static class SiteSweep { private const float SweepSeconds = 10f; private static Coroutine _sweep; private static readonly List<ZDO> Found = new List<ZDO>(); private static readonly Dictionary<ZDO, Clearance> PortalMasks = new Dictionary<ZDO, Clearance>(); internal static void Start() { Stop(); if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer()) { _sweep = ((MonoBehaviour)Plugin.Instance).StartCoroutine(Run()); } } internal static void Stop() { if (_sweep != null && (Object)(object)Plugin.Instance != (Object)null) { ((MonoBehaviour)Plugin.Instance).StopCoroutine(_sweep); } _sweep = null; Found.Clear(); PortalMasks.Clear(); } private static IEnumerator Run() { WaitForSeconds wait = new WaitForSeconds(10f); while (true) { yield return Recompute(); yield return wait; } } private static IEnumerator Recompute() { if (ZDOMan.instance == null) { yield break; } PortalMasks.Clear(); float radius = StaveboundConfig.StaveRadius.Value; bool all = StaveboundConfig.Binding.Value == PortalBinding.AllInRadius; foreach (KeyValuePair<string, Clearance> stave in StavePieces.Staves) { yield return Collect(stave.Key, Found); foreach (ZDO item in Found) { Bind(item.GetPosition(), stave.Value, radius, all); } } if (StaveboundConfig.StrictLadder.Value) { foreach (ZDO item2 in new List<ZDO>(PortalMasks.Keys)) { PortalMasks[item2] = ClearanceExtensions.UpToFirstGap(PortalMasks[item2]); } } WriteChangedMasks(); } private static void Bind(Vector3 runePosition, Clearance tier, float radius, bool all) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) ZDOMan instance = ZDOMan.instance; List<ZDO> list = ((instance != null) ? instance.GetPortalList() : null); if (list == null) { return; } float num = radius * radius; ZDO val = null; float num2 = num; foreach (ZDO item in list) { if (item == null || !item.IsValid()) { continue; } Vector3 val2 = item.GetPosition() - runePosition; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (!(sqrMagnitude > num)) { if (all) { Grant(item, tier); } else if (sqrMagnitude <= num2) { num2 = sqrMagnitude; val = item; } } } if (!all && val != null) { Grant(val, tier); } } private static IEnumerator Collect(string prefab, List<ZDO> into) { into.Clear(); int index = 0; bool complete = false; while (!complete) { if (ZDOMan.instance == null) { into.Clear(); break; } complete = ZDOMan.instance.GetAllZDOsWithPrefabIterative(prefab, into, ref index); yield return null; } } private static void Grant(ZDO portal, Clearance tier) { PortalMasks[portal] = (PortalMasks.TryGetValue(portal, out var value) ? (value | tier) : tier); } private static void WriteChangedMasks() { ZDOMan instance = ZDOMan.instance; List<ZDO> list = ((instance != null) ? instance.GetPortalList() : null); if (list == null) { return; } foreach (ZDO item in list) { if (item != null && item.IsValid()) { PortalMasks.TryGetValue(item, out var value); Write(item, value); } } } private static void Write(ZDO portal, Clearance mask) { if (portal.GetInt(ZdoKeys.ClearanceMask, 0) != (int)mask) { PortalTarget.Claim(portal); portal.Set(ZdoKeys.ClearanceMask, (int)mask, false); PortalTarget.Publish(portal); string text = portal.GetString(ZDOVars.s_tag, string.Empty); Logger.LogInfo((object)("[site] Clearance of " + (string.IsNullOrEmpty(text) ? "an unnamed portal" : ("\"" + text + "\"")) + " is now " + Describe(mask) + ".")); } } private static string Describe(Clearance mask) { if (mask == Clearance.None) { return "nothing"; } List<string> list = new List<string>(); Clearance[] ladder = ClearanceExtensions.Ladder; for (int i = 0; i < ladder.Length; i++) { Clearance clearance = ladder[i]; if ((mask & clearance) == clearance) { list.Add(clearance.ToString()); } } return string.Join(" + ", list); } } internal static class StavePieces { private sealed class PieceSpec { internal string Name; internal string Display; internal string Description; internal Color Tint; internal RequirementConfig[] Requirements; } private const string CloneSource = "Pickable_BlackCoreStand"; private const string TrophyElder = "TrophyTheElder"; private const string TrophyBonemass = "TrophyBonemass"; private const string TrophyModer = "TrophyDragonQueen"; private const string TrophyYagluth = "TrophyGoblinKing"; private const string TrophyQueen = "TrophySeekerQueen"; private const string TrophyFader = "TrophyFader"; private static readonly List<PieceSpec> Specs = new List<PieceSpec> { new PieceSpec { Name = "stave_elder", Display = "stave_rune_elder", Description = "stave_desc_elder", Tint = new Color(0.95f, 0.8f, 0.15f), Requirements = (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig { Item = "TrophyTheElder", Amount = 1, Recover = true }, new RequirementConfig { Item = "Copper", Amount = 10, Recover = true }, new RequirementConfig { Item = "Stone", Amount = 20, Recover = true } } }, new PieceSpec { Name = "stave_bonemass", Display = "stave_rune_bonemass", Description = "stave_desc_bonemass", Tint = new Color(0.25f, 0.85f, 0.3f), Requirements = (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig { Item = "TrophyBonemass", Amount = 1, Recover = true }, new RequirementConfig { Item = "Iron", Amount = 10, Recover = true }, new RequirementConfig { Item = "Stone", Amount = 20, Recover = true } } }, new PieceSpec { Name = "stave_moder", Display = "stave_rune_moder", Description = "stave_desc_moder", Tint = new Color(0.75f, 0.85f, 1f), Requirements = (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig { Item = "TrophyDragonQueen", Amount = 1, Recover = true }, new RequirementConfig { Item = "Silver", Amount = 10, Recover = true }, new RequirementConfig { Item = "Stone", Amount = 20, Recover = true } } }, new PieceSpec { Name = "stave_yagluth", Display = "stave_rune_yagluth", Description = "stave_desc_yagluth", Tint = new Color(0.45f, 0.15f, 0.65f), Requirements = (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig { Item = "TrophyGoblinKing", Amount = 1, Recover = true }, new RequirementConfig { Item = "BlackMetal", Amount = 10, Recover = true }, new RequirementConfig { Item = "Stone", Amount = 20, Recover = true } } }, new PieceSpec { Name = "stave_queen", Display = "stave_rune_queen", Description = "stave_desc_queen", Tint = new Color(0.4f, 0.95f, 0.95f), Requirements = (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig { Item = "TrophySeekerQueen", Amount = 1, Recover = true }, new RequirementConfig { Item = "DvergrNeedle", Amount = 3, Recover = true }, new RequirementConfig { Item = "Stone", Amount = 20, Recover = true } } }, new PieceSpec { Name = "stave_ashen", Display = "stave_rune_ashen", Description = "stave_desc_ashen", Tint = new Color(1f, 0.35f, 0.1f), Requirements = (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig { Item = "TrophyFader", Amount = 1, Recover = true }, new RequirementConfig { Item = "FlametalNew", Amount = 10, Recover = true }, new RequirementConfig { Item = "Stone", Amount = 20, Recover = true } } } }; private static readonly Dictionary<string, Clearance> Granted = new Dictionary<string, Clearance> { { "stave_elder", Clearance.Elder }, { "stave_bonemass", Clearance.Bonemass }, { "stave_moder", Clearance.Moder }, { "stave_yagluth", Clearance.Yagluth }, { "stave_queen", Clearance.Queen }, { "stave_ashen", Clearance.Ashen } }; internal static IEnumerable<KeyValuePair<string, Clearance>> Staves => Granted; internal static Clearance ClearanceOf(string prefabName) { if (!Granted.TryGetValue(prefabName, out var value)) { return Clearance.None; } return value; } internal static void Register() { PrefabManager.OnVanillaPrefabsAvailable += Create; PieceManager.OnPiecesRegistered += FileInTheBuildMenu; } private static void FileInTheBuildMenu() { //IL_0044: 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) foreach (string key in Granted.Keys) { GameObject prefab = PrefabManager.Instance.GetPrefab(key); Piece val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Piece>() : null); if (!((Object)(object)val == (Object)null)) { val.m_category = (PieceCategory)0; val.m_usage = (UsageTagFlags)2048; val.m_isUpgrade = true; } } } private static void Create() { PrefabManager.OnVanillaPrefabsAvailable -= Create; if ((Object)(object)PrefabManager.Instance.GetPrefab("Pickable_BlackCoreStand") == (Object)null) { Logger.LogError((object)"'Pickable_BlackCoreStand' is missing, so no staves can be built. A game update may have renamed it — run stave_prefabs corestand to find its new name."); return; } foreach (PieceSpec spec in Specs) { try { CreateOne(spec); } catch (Exception arg) { Logger.LogError((object)$"Could not create {spec.Name}: {arg}"); } } } private static void CheckRequirements(PieceSpec spec) { RequirementConfig[] requirements = spec.Requirements; foreach (RequirementConfig val in requirements) { if ((Object)(object)PrefabManager.Instance.GetPrefab(val.Item) == (Object)null) { Logger.LogError((object)(spec.Name + " needs '" + val.Item + "', which does not exist. That piece will be unbuildable until the name is corrected - try stave_prefabs to find it.")); } } } private static void CreateOne(PieceSpec spec) { //IL_005e: 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_0075: 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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown CheckRequirements(spec); GameObject val = PrefabManager.Instance.CreateClonedPrefab(spec.Name, "Pickable_BlackCoreStand"); if ((Object)(object)val == (Object)null) { Logger.LogError((object)("Could not clone Pickable_BlackCoreStand for " + spec.Name + ".")); return; } Pickable component = val.GetComponent<Pickable>(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } MakeBuildable(val); CoreTint.Apply(val, spec.Tint, spec.Name); CustomPiece val2 = new CustomPiece(val, false, new PieceConfig { Name = "$" + spec.Display, Description = "$" + spec.Description, PieceTable = PieceTables.Hammer, Category = "Misc", Icon = RenderIcon(val, spec.Name), Requirements = spec.Requirements }); if (!val2.IsValid()) { Logger.LogError((object)(spec.Name + " did not come out valid and will not be registered.")); return; } PieceManager.Instance.AddPiece(val2); Logger.LogInfo((object)("Registered piece " + spec.Name + ".")); } private static Sprite RenderIcon(GameObject prefab, string describe) { //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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown try { Sprite obj = RenderManager.Instance.Render(new RenderRequest(prefab) { Rotation = RenderManager.IsometricRotation, Width = 128, Height = 128, UseCache = false }); if ((Object)(object)obj == (Object)null) { Logger.LogWarning((object)("No icon could be rendered for " + describe + ".")); } return obj; } catch (Exception ex) { Logger.LogWarning((object)("Icon render failed for " + describe + ": " + ex.Message)); return null; } } private static void MakeBuildable(GameObject prefab) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) Piece obj = prefab.GetComponent<Piece>() ?? prefab.AddComponent<Piece>(); obj.m_canBeRemoved = true; obj.m_canRotate = true; obj.m_allowedInDungeons = false; obj.m_groundPiece = false; obj.m_groundOnly = false; obj.m_noInWater = true; if (!((Object)(object)prefab.GetComponent<WearNTear>() != (Object)null)) { WearNTear obj2 = prefab.AddComponent<WearNTear>(); obj2.m_health = 500f; obj2.m_burnable = false; obj2.m_noRoofWear = true; obj2.m_noSupportWear = true; obj2.m_materialType = (MaterialType)1; } } } } namespace Stavebound.Portals { internal static class LoadedPortals { private static readonly List<TeleportWorld> Live = new List<TeleportWorld>(); internal static void Remember(TeleportWorld portal) { if (!((Object)(object)portal == (Object)null)) { List<TeleportWorld> list = Current(); if (!list.Contains(portal)) { list.Add(portal); } } } internal static List<TeleportWorld> Current() { for (int num = Live.Count - 1; num >= 0; num--) { if ((Object)(object)Live[num] == (Object)null) { Live.RemoveAt(num); } } return Live; } internal static void Forget() { Live.Clear(); } } internal sealed class PlayerPositionsCommand : StaveboundCommand { private sealed class Sample { internal string Name; internal ZDOID Id; internal bool You; internal bool Public; internal Vector3 Server; internal bool HaveData; internal Vector3 Data; internal uint Revision; internal long Owner; internal bool HaveBody; internal Vector3 Body; } private const float WatchSeconds = 3f; private const float Apart = 30f; public override string Name => "stave_players"; public override string Help => "Diagnose a player's body left at a portal after they went through: where each player is drawn, where this machine's data says, and where the server says. Watches for a few seconds. Run it on the watcher's machine while the body is visible, and on the traveller's."; protected override void Execute(string[] args, Terminal context) { if ((Object)(object)ZNet.instance == (Object)null || ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null) { StaveboundCommand.Echo(context, "Stavebound: no world loaded."); return; } List<Sample> list = Take(); if (list.Count == 0) { StaveboundCommand.Echo(context, "Stavebound: the server has not sent a player list yet."); return; } StaveboundCommand.Echo(context, $"Stavebound players - watching for {3f:F0}s, stay put ..."); ((MonoBehaviour)Plugin.Instance).StartCoroutine(Finish(context, list)); } private static List<Sample> Take() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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_005d: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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) //IL_007e: 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_0086: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missin