Decompiled source of PeakStageWarp v1.0.1

PeakStageWarp.dll

Decompiled 6 hours ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using Microsoft.CodeAnalysis;
using PEAKLib.ModConfig;
using Photon.Pun;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("AERX")]
[assembly: AssemblyCopyright("Copyright (c) 2026 AERX")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace PeakStageWarp
{
	public static class StageRules
	{
		public static bool TryResolve(int slot, int segmentCount, bool hasPeakSpawn, out int index)
		{
			index = ((slot == 5) ? 4 : slot);
			if (slot >= 0 && slot <= 5 && index < segmentCount)
			{
				return slot != 5 || hasPeakSpawn;
			}
			return false;
		}

		public static string LabelKey(int slot, int biome)
		{
			return slot switch
			{
				5 => "PEAK", 
				4 => biome switch
				{
					3 => "THE KILN", 
					8 => "THE CITADEL", 
					_ => null, 
				}, 
				_ => biome switch
				{
					0 => "SHORE", 
					1 => "TROPICS", 
					2 => "ALPINE", 
					3 => "CALDERA", 
					6 => "MESA", 
					7 => "ROOTS", 
					8 => "GLOOM", 
					_ => null, 
				}, 
			};
		}
	}
	public enum Destination
	{
		海岸,
		第二区域_雨林或森蕈,
		第三区域_雪山或方山,
		第四区域_火山或雾沼,
		第五区域_熔炉或城塞,
		顶峰
	}
	public sealed class WarpWindow : MenuWindow
	{
		private GameObject surface;

		private static readonly MethodInfo OpenMethod = typeof(MenuWindow).GetMethod("Open", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly MethodInfo CloseMethod = typeof(MenuWindow).GetMethod("Close", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		public override bool openOnStart => false;

		public override bool selectOnOpen => false;

		public override bool closeOnPause => true;

		public override bool closeOnUICancel => true;

		public override bool blocksPlayerInput => true;

		public override bool showCursorWhileOpen => true;

		public override GameObject panel => surface;

		private void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			surface = new GameObject("WarpWindowSurface");
			surface.transform.SetParent(((Component)this).transform, false);
			surface.SetActive(false);
		}

		public void OpenPanel()
		{
			if (!((MenuWindow)this).isOpen)
			{
				OpenMethod.Invoke(this, null);
			}
		}

		public void ClosePanel()
		{
			if (((MenuWindow)this).isOpen)
			{
				CloseMethod.Invoke(this, null);
			}
		}
	}
	[BepInPlugin("local.peak.stagewarp", "区域传送", "1.0.0")]
	[BepInDependency("com.github.PEAKModding.PEAKLib.ModConfig", "1.8.2")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private ConfigEntry<bool> enabledOption;

		private ConfigEntry<bool> confirmOption;

		private ConfigEntry<Destination> target;

		private ConfigEntry<KeyCode> panelKey;

		private ConfigEntry<KeyCode> executeKey;

		private readonly ConfigEntry<KeyCode>[] directKeys = new ConfigEntry<KeyCode>[6];

		private WarpWindow window;

		private Font font;

		private GUIStyle heading;

		private GUIStyle label;

		private GUIStyle button;

		private string message = "";

		private float messageUntil;

		private float cooldownUntil;

		private int pendingSlot = -1;

		private MapHandler pendingMap;

		private bool restorePanelAfterSettings;

		private static readonly PropertyInfo CaptureProperty = typeof(ModConfigPlugin).GetProperty("InputBindingCapture", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);

		private void Awake()
		{
			enabledOption = ((BaseUnityPlugin)this).Config.Bind<bool>("1. 功能", "启用区域传送", true, "仅房主可执行。切换当前地图区域并传送全队,不能进入当前地图没有的区域。");
			confirmOption = ((BaseUnityPlugin)this).Config.Bind<bool>("1. 功能", "传送前确认", true, "快捷键或点击区域后显示确认按钮;关闭后立即执行。");
			target = ((BaseUnityPlugin)this).Config.Bind<Destination>("1. 功能", "快捷传送目标", Destination.第二区域_雨林或森蕈, "在这里选区域,再按快捷传送键。F10 面板会显示当前地图的实际区域名称。");
			panelKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("2. 按键", "打开或关闭选区面板", (KeyCode)291, "点击按键项后重新绑定,设置立即生效。支持键盘和鼠标 0–4;None 为不绑定。");
			executeKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("2. 按键", "传送到选定目标", (KeyCode)292, "传送到上面选定的区域。默认需要确认,不会在暂停菜单或改键时触发。");
			string[] array = new string[6] { "海岸", "第二区域", "第三区域", "第四区域", "第五区域", "顶峰" };
			for (int i = 0; i < directKeys.Length; i++)
			{
				directKeys[i] = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("3. 各区快捷键", "传送到" + array[i], (KeyCode)0, "可单独绑定此区域。None 为关闭此快捷键;多人游戏仅房主可用。");
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"区域传送 loaded; settings and key binding integrated with PEAKLib.ModConfig.");
		}

		private void Start()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			GameObject val = new GameObject("PeakStageWarpWindow");
			Object.DontDestroyOnLoad((Object)(object)val);
			window = val.AddComponent<WarpWindow>();
			font = Font.CreateDynamicFontFromOSFont(new string[3] { "Microsoft YaHei", "SimHei", "Arial" }, 18);
		}

		private MapHandler CurrentMap()
		{
			return Singleton<MapHandler>.Instance;
		}

		private bool Ready(out string reason)
		{
			if (!enabledOption.Value)
			{
				reason = "区域传送已关闭,请在模组设置中开启";
				return false;
			}
			Character localCharacter = Character.localCharacter;
			MapHandler val = CurrentMap();
			if ((Object)(object)localCharacter == (Object)null || !localCharacter.IsLocal || (Object)(object)val == (Object)null || val.segments == null || LoadingScreenHandler.loading)
			{
				reason = "请先进入地图,等待角色和区域加载完成";
				return false;
			}
			if (!PhotonNetwork.IsMasterClient)
			{
				reason = "仅房主可以切换区域并传送全队";
				return false;
			}
			if ((Object)(object)localCharacter.data == (Object)null || localCharacter.data.dead || localCharacter.data.fullyPassedOut)
			{
				reason = "角色死亡或昏迷时不能执行传送";
				return false;
			}
			if (localCharacter.warping)
			{
				reason = "正在传送,请稍候";
				return false;
			}
			reason = "";
			return true;
		}

		private bool Available(MapHandler map, int slot)
		{
			if ((Object)(object)map != (Object)null && map.segments != null && StageRules.TryResolve(slot, map.segments.Length, (Object)(object)map.respawnThePeak != (Object)null, out var index) && map.segments[index] != null)
			{
				return (Object)(object)map.segments[index].segmentParent != (Object)null;
			}
			return false;
		}

		private string Label(MapHandler map, int slot)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected I4, but got Unknown
			if (!Available(map, slot))
			{
				return "未加载";
			}
			int num = ((slot == 5) ? 4 : slot);
			int biome = (int)map.segments[(slot == 4) ? 3 : num].biome;
			string text = StageRules.LabelKey(slot, biome);
			if (text == null)
			{
				return ((Object)map.segments[num].segmentParent).name;
			}
			string text2 = LocalizedText.GetText(text, true);
			if (!string.IsNullOrEmpty(text2) && !text2.StartsWith("LOC:"))
			{
				return text2;
			}
			return text;
		}

		private bool SettingsOpen()
		{
			if (GUIManager.InPauseMenu)
			{
				return true;
			}
			object obj = ((CaptureProperty == null) ? null : CaptureProperty.GetValue(null, null));
			if (obj == null)
			{
				return false;
			}
			PropertyInfo property = obj.GetType().GetProperty("IsCapturing", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null)
			{
				return (bool)property.GetValue(obj, null);
			}
			return false;
		}

		private void Update()
		{
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)window == (Object)null)
			{
				return;
			}
			if (SettingsOpen())
			{
				if (((MenuWindow)window).isOpen)
				{
					restorePanelAfterSettings = true;
					window.ClosePanel();
				}
				return;
			}
			if (restorePanelAfterSettings)
			{
				restorePanelAfterSettings = false;
				if (pendingSlot >= 0 && (Object)(object)pendingMap == (Object)(object)CurrentMap())
				{
					window.OpenPanel();
				}
				return;
			}
			if (!enabledOption.Value || (Object)(object)CurrentMap() == (Object)null || (Object)(object)Character.localCharacter == (Object)null || LoadingScreenHandler.loading)
			{
				window.ClosePanel();
				pendingSlot = -1;
				pendingMap = null;
				return;
			}
			if (pendingSlot >= 0 && (Object)(object)pendingMap != (Object)(object)CurrentMap())
			{
				pendingSlot = -1;
				pendingMap = null;
				window.ClosePanel();
			}
			if (Pressed(panelKey.Value))
			{
				if (((MenuWindow)window).isOpen)
				{
					window.ClosePanel();
					pendingSlot = -1;
					pendingMap = null;
				}
				else
				{
					pendingSlot = -1;
					window.OpenPanel();
				}
			}
			else if (((MenuWindow)window).isOpen && Pressed((KeyCode)27))
			{
				window.ClosePanel();
				pendingSlot = -1;
				pendingMap = null;
			}
			else
			{
				if (((MenuWindow)window).isOpen || ((Object)(object)GUIManager.instance != (Object)null && GUIManager.instance.windowBlockingInput))
				{
					return;
				}
				if (Pressed(executeKey.Value))
				{
					Request((int)target.Value);
					return;
				}
				for (int i = 0; i < directKeys.Length; i++)
				{
					if (Pressed(directKeys[i].Value))
					{
						Request(i);
						break;
					}
				}
			}
		}

		private void Request(int slot)
		{
			if (!Ready(out var reason))
			{
				Notify(reason);
				return;
			}
			MapHandler val = CurrentMap();
			if (!Available(val, slot))
			{
				Notify("当前地图没有加载这个区域");
				return;
			}
			if (Time.unscaledTime < cooldownUntil)
			{
				Notify("请稍候再传送");
				return;
			}
			target.Value = (Destination)slot;
			if (!confirmOption.Value)
			{
				Execute(slot, val);
				return;
			}
			pendingSlot = slot;
			pendingMap = val;
			window.OpenPanel();
		}

		private void Execute(int slot, MapHandler expectedMap)
		{
			if (!Ready(out var reason))
			{
				Notify(reason);
				return;
			}
			MapHandler val = CurrentMap();
			if ((Object)(object)val != (Object)(object)expectedMap || !Available(val, slot))
			{
				Notify("地图已经变化,请重新选区");
				pendingSlot = -1;
			}
			else if (!(Time.unscaledTime < cooldownUntil))
			{
				try
				{
					string text = Label(val, slot);
					window.ClosePanel();
					pendingSlot = -1;
					pendingMap = null;
					cooldownUntil = Time.unscaledTime + 3f;
					MapHandler.JumpToSegment((Segment)(byte)slot);
					Notify("已请求全队传送至:" + text);
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)ex);
					Notify("传送未完成,请查看 BepInEx 日志");
				}
			}
		}

		private void Notify(string text)
		{
			message = text;
			messageUntil = Time.unscaledTime + 5f;
		}

		private void OnGUI()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_004a: Expected O, but got Unknown
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Expected O, but got Unknown
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_040c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0433: Unknown result type (might be due to invalid IL or missing references)
			//IL_0356: Unknown result type (might be due to invalid IL or missing references)
			//IL_0393: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)window == (Object)null)
			{
				return;
			}
			if (label == null)
			{
				label = new GUIStyle(GUI.skin.label)
				{
					font = font,
					fontSize = 18,
					wordWrap = true
				};
				label.normal.textColor = Color.white;
				heading = new GUIStyle(label)
				{
					fontSize = 23,
					fontStyle = (FontStyle)1
				};
				button = new GUIStyle(GUI.skin.button)
				{
					font = font,
					fontSize = 18
				};
			}
			if (((MenuWindow)window).isOpen)
			{
				MapHandler val = CurrentMap();
				float num = Mathf.Min(540f, (float)Screen.width - 24f);
				float num2 = Mathf.Min(570f, (float)Screen.height - 24f);
				Rect val2 = default(Rect);
				((Rect)(ref val2))..ctor(((float)Screen.width - num) / 2f, ((float)Screen.height - num2) / 2f, num, num2);
				GUI.Box(val2, "");
				GUILayout.BeginArea(new Rect(((Rect)(ref val2)).x + 18f, ((Rect)(ref val2)).y + 14f, num - 36f, num2 - 28f));
				GUILayout.Label("区域传送", heading, Array.Empty<GUILayoutOption>());
				GUILayout.Label("房主操作 · 全队切换至区域起点", label, Array.Empty<GUILayoutOption>());
				string reason;
				bool flag = Ready(out reason);
				if (!flag)
				{
					GUILayout.Label(reason, label, Array.Empty<GUILayoutOption>());
				}
				bool enabled = GUI.enabled;
				for (int i = 0; i <= 5; i++)
				{
					GUI.enabled = enabled && flag && Available(val, i) && Time.unscaledTime >= cooldownUntil;
					string text = i + 1 + ". " + Label(val, i);
					if (GUI.Button(new Rect(0f, (float)(95 + i * 43), num - 36f, 36f), text, button))
					{
						Request(i);
					}
				}
				GUI.enabled = enabled;
				GUILayout.EndArea();
				float num3 = ((Rect)(ref val2)).y + 95f + 258f + 18f;
				if (pendingSlot >= 0 && (Object)(object)pendingMap == (Object)(object)val)
				{
					GUI.Label(new Rect(((Rect)(ref val2)).x + 18f, num3, num - 36f, 30f), "目标:" + Label(val, pendingSlot), label);
					GUI.enabled = enabled && flag && Time.unscaledTime >= cooldownUntil;
					if (GUI.Button(new Rect(((Rect)(ref val2)).x + 18f, num3 + 34f, num - 36f, 38f), "确认传送全队", button))
					{
						Execute(pendingSlot, pendingMap);
					}
					GUI.enabled = enabled;
				}
				GUI.Label(new Rect(((Rect)(ref val2)).x + 18f, ((Rect)(ref val2)).y + num2 - 90f, num - 36f, 45f), "改键:暂停 → 模组设置 → 区域传送", label);
				if (GUI.Button(new Rect(((Rect)(ref val2)).x + 18f, ((Rect)(ref val2)).y + num2 - 44f, num - 36f, 32f), "关闭(" + ((object)panelKey.Value/*cast due to .constrained prefix*/).ToString() + " / Esc)", button))
				{
					window.ClosePanel();
					pendingSlot = -1;
					pendingMap = null;
				}
			}
			if (Time.unscaledTime < messageUntil)
			{
				GUI.Box(new Rect(16f, (float)(Screen.height - 82), 620f, 64f), "");
				GUI.Label(new Rect(28f, (float)(Screen.height - 74), 596f, 50f), message, label);
			}
		}

		private unsafe static bool Pressed(KeyCode code)
		{
			//IL_0000: 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_0011: Invalid comparison between Unknown and I4
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			//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_0040: Expected I4, but got Unknown
			//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0400: Unknown result type (might be due to invalid IL or missing references)
			if ((int)code == 0)
			{
				return false;
			}
			Mouse current = Mouse.current;
			if ((int)code >= 323 && (int)code <= 327)
			{
				if (current == null)
				{
					return false;
				}
				switch (code - 323)
				{
				case 0:
					return current.leftButton.wasPressedThisFrame;
				case 1:
					return current.rightButton.wasPressedThisFrame;
				case 2:
					return current.middleButton.wasPressedThisFrame;
				case 3:
					return current.backButton.wasPressedThisFrame;
				case 4:
					return current.forwardButton.wasPressedThisFrame;
				}
			}
			Keyboard current2 = Keyboard.current;
			if (current2 == null)
			{
				return false;
			}
			string text = ((object)(*(KeyCode*)(&code))/*cast due to .constrained prefix*/).ToString();
			if (text.StartsWith("Alpha"))
			{
				text = "Digit" + text.Substring(5);
			}
			else if (text.StartsWith("Keypad"))
			{
				text = "Numpad" + text.Substring(6);
			}
			switch (text)
			{
			case "Return":
				text = "Enter";
				break;
			case "LeftControl":
				text = "LeftCtrl";
				break;
			case "RightControl":
				text = "RightCtrl";
				break;
			case "LeftCommand":
			case "LeftWindows":
			case "LeftApple":
				text = "LeftMeta";
				break;
			case "RightCommand":
			case "RightWindows":
			case "RightApple":
				text = "RightMeta";
				break;
			case "NumpadPeriod":
				text = "NumpadPeriod";
				break;
			case "NumpadDivide":
				text = "NumpadDivide";
				break;
			case "NumpadMultiply":
				text = "NumpadMultiply";
				break;
			case "NumpadMinus":
				text = "NumpadMinus";
				break;
			case "NumpadPlus":
				text = "NumpadPlus";
				break;
			case "SysReq":
			case "Print":
				text = "PrintScreen";
				break;
			case "Break":
				text = "Pause";
				break;
			case "Menu":
				text = "ContextMenu";
				break;
			case "AltGr":
				text = "RightAlt";
				break;
			}
			if (Enum.TryParse<Key>(text, ignoreCase: true, out Key result) && (int)result != 0)
			{
				return ((ButtonControl)current2[result]).wasPressedThisFrame;
			}
			return false;
		}

		private void OnDisable()
		{
			if ((Object)(object)window != (Object)null)
			{
				window.ClosePanel();
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)window != (Object)null)
			{
				window.ClosePanel();
				Object.Destroy((Object)(object)((Component)window).gameObject);
			}
			if ((Object)(object)font != (Object)null)
			{
				Object.Destroy((Object)(object)font);
			}
		}
	}
}