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);
}
}
}
}