Decompiled source of SimpleDevMenu v0.5.0

SimpleDevMenu.dll

Decompiled 3 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("amumu")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.5.0.0")]
[assembly: AssemblyInformationalVersion("0.5.0")]
[assembly: AssemblyProduct("SimpleDevMenu")]
[assembly: AssemblyTitle("SimpleDevMenu")]
[assembly: AssemblyVersion("0.5.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 SimpleDevMenu
{
	[BepInPlugin("amumu.simpledevmenu", "SimpleDevMenu", "0.5.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "amumu.simpledevmenu";

		public const string Name = "SimpleDevMenu";

		public const string Version = "0.5.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<Key> ToggleKey;

		internal static ConfigEntry<bool> ShowHitCounter;

		internal static ConfigEntry<float> HitCounterOffsetX;

		internal static ConfigEntry<float> HitCounterOffsetY;

		private void Awake()
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			//IL_00a7: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ToggleKey = ((BaseUnityPlugin)this).Config.Bind<Key>("General", "ToggleKey", (Key)4, "메뉴 창을 여닫는 키 (기본: ` 백쿼트)");
			ShowHitCounter = ((BaseUnityPlugin)this).Config.Bind<bool>("HitCounter", "Show", true, "HUD 의 무게(kg) 아래에 피격 횟수를 표시");
			HitCounterOffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("HitCounter", "OffsetX", 0f, "피격 카운터 가로 위치 보정 (무게 표시 기준)");
			HitCounterOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("HitCounter", "OffsetY", -22f, "피격 카운터 세로 위치 보정 (무게 표시 기준, 음수 = 아래)");
			Patches.Apply(new Harmony("amumu.simpledevmenu"));
			GameObject val = new GameObject("SimpleDevMenu")
			{
				hideFlags = (HideFlags)61
			};
			Object.DontDestroyOnLoad((Object)val);
			val.AddComponent<DevMenu>();
			Log.LogInfo((object)"SimpleDevMenu 0.5.0 로드 완료");
		}
	}
	internal static class State
	{
		public static bool MenuOpen;

		public static bool GodMode;

		public static bool FreezeTime;

		public static bool HostGodMode;

		public static bool HostFreezeTime;

		public static PlayerControllerB LocalPlayer
		{
			get
			{
				GameNetworkManager instance = GameNetworkManager.Instance;
				if (!((Object)(object)instance != (Object)null))
				{
					return null;
				}
				return instance.localPlayerController;
			}
		}

		public static bool IsHost
		{
			get
			{
				NetworkManager singleton = NetworkManager.Singleton;
				if ((Object)(object)singleton != (Object)null)
				{
					if (!singleton.IsHost)
					{
						return singleton.IsServer;
					}
					return true;
				}
				return false;
			}
		}

		public static bool GodActive
		{
			get
			{
				if (!GodMode)
				{
					if (!IsHost)
					{
						return HostGodMode;
					}
					return false;
				}
				return true;
			}
		}

		public static bool FreezeActive
		{
			get
			{
				if (!IsHost)
				{
					return HostFreezeTime;
				}
				return FreezeTime;
			}
		}

		public static bool IsLocal(PlayerControllerB player)
		{
			if ((Object)(object)player != (Object)null)
			{
				return (Object)(object)player == (Object)(object)LocalPlayer;
			}
			return false;
		}
	}
	internal static class HitCounter
	{
		public static int Count;

		public static string Last = "";

		public static bool Dirty = true;

		private static float _lastTime = -10f;

		private static bool _lastWasKill;

		public static void Reset()
		{
			Count = 0;
			Last = "";
			Dirty = true;
		}

		public static void Register(int damage)
		{
			bool flag = damage < 0;
			float unscaledTime = Time.unscaledTime;
			float num = unscaledTime - _lastTime;
			if (!(num < 0.15f))
			{
				if (flag && num < 1f)
				{
					_lastTime = (_lastWasKill ? unscaledTime : _lastTime);
					return;
				}
				_lastTime = unscaledTime;
				_lastWasKill = flag;
				Count++;
				Last = (flag ? "KILL" : ("-" + damage));
				Dirty = true;
			}
		}
	}
	internal static class Patches
	{
		public static void Apply(Harmony harmony)
		{
			PatchPrefix(harmony, typeof(PlayerControllerB), "DamagePlayer", "OnDamagePlayer");
			PatchPrefix(harmony, typeof(PlayerControllerB), "KillPlayer", "OnKillPlayer");
			PatchPrefix(harmony, typeof(PlayerControllerB), "PlayerLookInput", "BlockIfMenuOpen");
			PatchPrefix(harmony, typeof(PlayerControllerB), "ActivateItem_performed", "BlockIfMenuOpen");
			PatchPrefix(harmony, typeof(PlayerControllerB), "ItemSecondaryUse_performed", "BlockIfMenuOpen");
			PatchPrefix(harmony, typeof(PlayerControllerB), "ItemTertiaryUse_performed", "BlockIfMenuOpen");
			PatchPrefix(harmony, typeof(PlayerControllerB), "Interact_performed", "BlockIfMenuOpen");
		}

		private static void PatchPrefix(Harmony harmony, Type type, string methodName, string prefixName)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			MethodInfo method = typeof(Patches).GetMethod(prefixName, BindingFlags.Static | BindingFlags.NonPublic);
			List<MethodInfo> list = (from m in AccessTools.GetDeclaredMethods(type)
				where m.Name == methodName
				select m).ToList();
			if (list.Count == 0)
			{
				Plugin.Log.LogWarning((object)(type.Name + "." + methodName + " 을(를) 찾지 못했습니다. 관련 기능이 동작하지 않을 수 있습니다."));
				return;
			}
			foreach (MethodInfo item in list)
			{
				try
				{
					harmony.Patch((MethodBase)item, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)(type.Name + "." + methodName + " 패치 실패: " + ex.Message));
				}
			}
		}

		private static bool OnDamagePlayer(PlayerControllerB __instance, object[] __args)
		{
			if (!State.IsLocal(__instance) || __instance.isPlayerDead)
			{
				return true;
			}
			int num = 0;
			if (__args != null && __args.Length != 0 && __args[0] is int)
			{
				num = (int)__args[0];
			}
			if (num < 0)
			{
				num = 0;
			}
			HitCounter.Register(num);
			return !State.GodActive;
		}

		private static bool OnKillPlayer(PlayerControllerB __instance)
		{
			if (!State.IsLocal(__instance) || __instance.isPlayerDead)
			{
				return true;
			}
			HitCounter.Register(-1);
			return !State.GodActive;
		}

		private static bool BlockIfMenuOpen(PlayerControllerB __instance)
		{
			if (State.MenuOpen)
			{
				return !State.IsLocal(__instance);
			}
			return true;
		}
	}
	internal static class Net
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static HandleNamedMessageDelegate <0>__OnReceive;
		}

		private const string MessageName = "amumu.simpledevmenu.state";

		private static CustomMessagingManager _registeredOn;

		private static float _nextSend;

		private static int _lastSent = -1;

		public static void Tick()
		{
			//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_0068: Expected O, but got Unknown
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsListening || singleton.CustomMessagingManager == null)
			{
				_registeredOn = null;
				_lastSent = -1;
				State.HostGodMode = false;
				State.HostFreezeTime = false;
				return;
			}
			CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager;
			if (_registeredOn != customMessagingManager)
			{
				object obj = <>O.<0>__OnReceive;
				if (obj == null)
				{
					HandleNamedMessageDelegate val = OnReceive;
					<>O.<0>__OnReceive = val;
					obj = (object)val;
				}
				customMessagingManager.RegisterNamedMessageHandler("amumu.simpledevmenu.state", (HandleNamedMessageDelegate)obj);
				_registeredOn = customMessagingManager;
				_lastSent = -1;
			}
			if (!singleton.IsHost && !singleton.IsServer)
			{
				return;
			}
			int num = (State.GodMode ? 1 : 0) | (State.FreezeTime ? 2 : 0);
			float unscaledTime = Time.unscaledTime;
			if (num == _lastSent && (num == 0 || unscaledTime < _nextSend))
			{
				return;
			}
			try
			{
				FastBufferWriter val2 = default(FastBufferWriter);
				((FastBufferWriter)(ref val2))..ctor(1, (Allocator)2, -1);
				try
				{
					((FastBufferWriter)(ref val2)).WriteByteSafe((byte)num);
					customMessagingManager.SendNamedMessageToAll("amumu.simpledevmenu.state", val2, (NetworkDelivery)3);
				}
				finally
				{
					((FastBufferWriter)(ref val2)).Dispose();
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("설정 동기화 전송 실패: " + ex.Message));
			}
			_lastSent = num;
			_nextSend = unscaledTime + 2f;
		}

		private static void OnReceive(ulong senderId, FastBufferReader reader)
		{
			if (!State.IsHost && senderId == 0L)
			{
				byte b = default(byte);
				((FastBufferReader)(ref reader)).ReadByteSafe(ref b);
				State.HostGodMode = (b & 1) != 0;
				State.HostFreezeTime = (b & 2) != 0;
			}
		}
	}
	internal static class HitHud
	{
		private static TMP_Text _text;

		public static void Tick()
		{
			bool value = Plugin.ShowHitCounter.Value;
			if ((Object)(object)_text == (Object)null)
			{
				if (!value)
				{
					return;
				}
				TryCreate();
				if ((Object)(object)_text == (Object)null)
				{
					return;
				}
				HitCounter.Dirty = true;
			}
			if (((Component)_text).gameObject.activeSelf != value)
			{
				((Component)_text).gameObject.SetActive(value);
			}
			if (value && HitCounter.Dirty)
			{
				_text.text = ((HitCounter.Count == 0) ? "HITS 0" : ("HITS " + HitCounter.Count + "  (" + HitCounter.Last + ")"));
				HitCounter.Dirty = false;
			}
		}

		private static void TryCreate()
		{
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: 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)
			try
			{
				HUDManager instance = HUDManager.Instance;
				if ((Object)(object)instance == (Object)null || (Object)(object)instance.weightCounter == (Object)null)
				{
					return;
				}
				TextMeshProUGUI weightCounter = instance.weightCounter;
				GameObject val = Object.Instantiate<GameObject>(((Component)weightCounter).gameObject, ((TMP_Text)weightCounter).transform.parent);
				((Object)val).name = "SimpleDevMenu_HitCounter";
				Animator[] componentsInChildren = val.GetComponentsInChildren<Animator>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Object.Destroy((Object)(object)componentsInChildren[i]);
				}
				TMP_Text component = val.GetComponent<TMP_Text>();
				if ((Object)(object)component == (Object)null)
				{
					Object.Destroy((Object)(object)val);
					return;
				}
				component.enableWordWrapping = false;
				component.overflowMode = (TextOverflowModes)0;
				RectTransform component2 = ((Component)weightCounter).GetComponent<RectTransform>();
				RectTransform component3 = val.GetComponent<RectTransform>();
				if ((Object)(object)component2 != (Object)null && (Object)(object)component3 != (Object)null)
				{
					component3.anchoredPosition = component2.anchoredPosition + new Vector2(Plugin.HitCounterOffsetX.Value, Plugin.HitCounterOffsetY.Value);
				}
				_text = component;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("피격 카운터 HUD 생성 실패: " + ex.Message));
			}
		}
	}
	internal class DevMenu : MonoBehaviour
	{
		private class EnemyEntry
		{
			public string Label;

			public EnemyType Type;
		}

		private class ItemEntry
		{
			public string Label;

			public string ItemName;

			public string PrefabHint;

			public Type Component;
		}

		private static readonly HashSet<string> AllowedOutside = new HashSet<string> { "forestgiant", "mouthdog" };

		private static readonly Dictionary<string, string> KoreanNames = new Dictionary<string, string>
		{
			{ "crawler", "덤퍼 (Thumper)" },
			{ "flowerman", "브래컨 (Bracken)" },
			{ "hoarderbug", "비축 벌레 (Hoarding Bug)" },
			{ "hoardingbug", "비축 벌레 (Hoarding Bug)" },
			{ "centipede", "올무 벼룩 (Snare Flea)" },
			{ "bunkerspider", "벙커 거미 (Bunker Spider)" },
			{ "puffer", "포자 도마뱀 (Spore Lizard)" },
			{ "nutcracker", "호두까기 인형 (Nutcracker)" },
			{ "masked", "마스크 (Masked)" },
			{ "butler", "집사 (Butler)" },
			{ "cavedweller", "맨이터 (Maneater)" },
			{ "maneater", "맨이터 (Maneater)" },
			{ "forestgiant", "숲 거인 (Forest Giant)" },
			{ "mouthdog", "눈 없는 개 (Eyeless Dog)" }
		};

		private readonly List<EnemyEntry> _enemies = new List<EnemyEntry>();

		private string _selectedName = "Crawler";

		private Vector2 _dropdownScroll;

		private static readonly ItemEntry[] Items = new ItemEntry[3]
		{
			new ItemEntry
			{
				Label = "삽",
				ItemName = "Shovel",
				PrefabHint = "shovel",
				Component = typeof(Shovel)
			},
			new ItemEntry
			{
				Label = "식칼",
				ItemName = "Kitchen knife",
				PrefabHint = "knife",
				Component = typeof(KnifeItem)
			},
			new ItemEntry
			{
				Label = "제트팩",
				ItemName = "Jetpack",
				PrefabHint = "jetpack",
				Component = typeof(JetpackItem)
			}
		};

		private static readonly int[] CreditAmounts = new int[5] { 10, 50, 100, 500, 1000 };

		private const int WindowId = 6109713;

		private Rect _window = new Rect(40f, 40f, 320f, 0f);

		private int _selectedEnemy;

		private bool _dropdownOpen;

		private bool _timeWasFrozen;

		private string _status = "";

		private Terminal _terminal;

		private static string NameKey(string enemyName)
		{
			return (enemyName ?? "").Replace(" ", "").Replace("-", "").ToLowerInvariant();
		}

		private static string LabelFor(EnemyType type, bool outside)
		{
			if (!KoreanNames.TryGetValue(NameKey(type.enemyName), out var value))
			{
				value = type.enemyName;
			}
			if (!outside)
			{
				return value;
			}
			return value + " [실외]";
		}

		private void RefreshEnemyList()
		{
			_enemies.Clear();
			_selectedEnemy = 0;
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null || instance.levels == null)
			{
				return;
			}
			HashSet<string> hashSet = new HashSet<string>();
			List<EnemyEntry> list = new List<EnemyEntry>();
			List<EnemyEntry> list2 = new List<EnemyEntry>();
			SelectableLevel[] levels = instance.levels;
			foreach (SelectableLevel val in levels)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				if (val.Enemies != null)
				{
					foreach (SpawnableEnemyWithRarity enemy in val.Enemies)
					{
						EnemyType val2 = enemy?.enemyType;
						if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.enemyPrefab == (Object)null) && val2.canDie && hashSet.Add(NameKey(val2.enemyName)))
						{
							list.Add(new EnemyEntry
							{
								Label = LabelFor(val2, outside: false),
								Type = val2
							});
						}
					}
				}
				if (val.OutsideEnemies == null)
				{
					continue;
				}
				foreach (SpawnableEnemyWithRarity outsideEnemy in val.OutsideEnemies)
				{
					EnemyType val3 = outsideEnemy?.enemyType;
					if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.enemyPrefab == (Object)null))
					{
						string item = NameKey(val3.enemyName);
						if (AllowedOutside.Contains(item) && hashSet.Add(item))
						{
							list2.Add(new EnemyEntry
							{
								Label = LabelFor(val3, outside: true),
								Type = val3
							});
						}
					}
				}
			}
			list.Sort((EnemyEntry a, EnemyEntry b) => string.CompareOrdinal(a.Label, b.Label));
			list2.Sort((EnemyEntry a, EnemyEntry b) => string.CompareOrdinal(a.Label, b.Label));
			_enemies.AddRange(list);
			_enemies.AddRange(list2);
			string text = NameKey(_selectedName);
			for (int num = 0; num < _enemies.Count; num++)
			{
				if (NameKey(_enemies[num].Type.enemyName) == text)
				{
					_selectedEnemy = num;
					break;
				}
			}
		}

		private void Update()
		{
			HandleToggleKey();
			Net.Tick();
			ApplyFreezeTime();
			HitHud.Tick();
			if (State.MenuOpen)
			{
				if ((Object)(object)State.LocalPlayer == (Object)null)
				{
					State.MenuOpen = false;
					return;
				}
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
		}

		private void HandleToggleKey()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			Keyboard current = Keyboard.current;
			if (current == null)
			{
				return;
			}
			bool wasPressedThisFrame;
			try
			{
				wasPressedThisFrame = ((ButtonControl)current[Plugin.ToggleKey.Value]).wasPressedThisFrame;
			}
			catch
			{
				return;
			}
			if (!wasPressedThisFrame)
			{
				return;
			}
			PlayerControllerB localPlayer = State.LocalPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			if (!State.MenuOpen)
			{
				if (!localPlayer.isTypingChat && !localPlayer.inTerminalMenu)
				{
					State.MenuOpen = true;
					_dropdownOpen = false;
					RefreshEnemyList();
				}
			}
			else
			{
				CloseMenu(localPlayer);
			}
		}

		private void CloseMenu(PlayerControllerB player)
		{
			State.MenuOpen = false;
			if ((!((Object)(object)player.quickMenuManager != (Object)null) || !player.quickMenuManager.isMenuOpen) && !player.inTerminalMenu)
			{
				Cursor.lockState = (CursorLockMode)1;
				Cursor.visible = false;
			}
		}

		private void ApplyFreezeTime()
		{
			TimeOfDay instance = TimeOfDay.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				if (State.FreezeActive)
				{
					instance.globalTimeSpeedMultiplier = 0f;
					_timeWasFrozen = true;
				}
				else if (_timeWasFrozen)
				{
					instance.globalTimeSpeedMultiplier = 1f;
					_timeWasFrozen = false;
				}
			}
		}

		private void OnGUI()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (State.MenuOpen)
			{
				((Rect)(ref _window)).height = 0f;
				_window = GUILayout.Window(6109713, _window, new WindowFunction(DrawWindow), "Dev Menu  ( ` )", Array.Empty<GUILayoutOption>());
			}
		}

		private void DrawWindow(int id)
		{
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			bool isHost = State.IsHost;
			State.GodMode = GUILayout.Toggle(State.GodMode, isHost ? " 플레이어 무적 - 전원 (God Mode, all players)" : " 플레이어 무적 - 나만 (God Mode, me only)", Array.Empty<GUILayoutOption>());
			if (!isHost && State.HostGodMode)
			{
				GUILayout.Label("    호스트가 무적을 적용 중 (God Mode by host)", Array.Empty<GUILayoutOption>());
			}
			if (isHost)
			{
				State.FreezeTime = GUILayout.Toggle(State.FreezeTime, " 시간 정지 (Freeze Time)", Array.Empty<GUILayoutOption>());
			}
			else
			{
				GUILayout.Label(State.HostFreezeTime ? " 시간 정지: 호스트가 적용 중 (ON by host)" : " 시간 정지: 호스트 전용 (Host only)", Array.Empty<GUILayoutOption>());
			}
			GUILayout.Space(8f);
			GUILayout.Label("장비 소환 (Items)", Array.Empty<GUILayoutOption>());
			GUI.enabled = isHost;
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			ItemEntry[] items = Items;
			foreach (ItemEntry itemEntry in items)
			{
				if (GUILayout.Button(itemEntry.Label, Array.Empty<GUILayoutOption>()))
				{
					SpawnItem(itemEntry);
				}
			}
			GUILayout.EndHorizontal();
			GUI.enabled = true;
			GUILayout.Space(8f);
			Terminal terminal = GetTerminal();
			GUILayout.Label("돈 추가 (Credits)" + (((Object)(object)terminal != (Object)null) ? ("   현재: " + terminal.groupCredits) : ""), Array.Empty<GUILayoutOption>());
			GUI.enabled = (Object)(object)terminal != (Object)null;
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			int[] creditAmounts = CreditAmounts;
			for (int i = 0; i < creditAmounts.Length; i++)
			{
				int amount = creditAmounts[i];
				if (GUILayout.Button("+" + amount, Array.Empty<GUILayoutOption>()))
				{
					AddCredits(amount);
				}
			}
			GUILayout.EndHorizontal();
			GUI.enabled = true;
			GUILayout.Space(8f);
			GUILayout.Label("몬스터 소환 (Spawn)", Array.Empty<GUILayoutOption>());
			bool flag = _enemies.Count > 0;
			if (_selectedEnemy >= _enemies.Count)
			{
				_selectedEnemy = 0;
			}
			if (!flag)
			{
				GUILayout.Label("  목록을 불러오지 못함 (No enemy data)", Array.Empty<GUILayoutOption>());
				_dropdownOpen = false;
			}
			else if (GUILayout.Button(_enemies[_selectedEnemy].Label + (_dropdownOpen ? "  ▲" : "  ▼"), Array.Empty<GUILayoutOption>()))
			{
				_dropdownOpen = !_dropdownOpen;
			}
			if (_dropdownOpen && flag)
			{
				float num = Mathf.Min((float)_enemies.Count * 24f + 6f, 220f);
				_dropdownScroll = GUILayout.BeginScrollView(_dropdownScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(num) });
				for (int j = 0; j < _enemies.Count; j++)
				{
					if (GUILayout.Button(_enemies[j].Label, Array.Empty<GUILayoutOption>()))
					{
						_selectedEnemy = j;
						_selectedName = _enemies[j].Type.enemyName;
						_dropdownOpen = false;
					}
				}
				GUILayout.EndScrollView();
			}
			GUI.enabled = isHost && flag;
			if (GUILayout.Button("소환 (Spawn)", Array.Empty<GUILayoutOption>()))
			{
				SpawnSelectedEnemy();
			}
			GUILayout.Space(8f);
			GUI.enabled = isHost;
			if (GUILayout.Button("몬스터 전부 삭제 (Delete All)", Array.Empty<GUILayoutOption>()))
			{
				DeleteAllEnemies();
			}
			GUI.enabled = true;
			GUILayout.Space(8f);
			bool flag2 = GUILayout.Toggle(Plugin.ShowHitCounter.Value, " 피격 횟수 HUD 표시 (Hit Counter)", Array.Empty<GUILayoutOption>());
			if (flag2 != Plugin.ShowHitCounter.Value)
			{
				Plugin.ShowHitCounter.Value = flag2;
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("피격: " + HitCounter.Count + "회" + ((HitCounter.Last.Length > 0) ? ("  (최근 " + HitCounter.Last + ")") : ""), Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("초기화 (Reset)", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) }))
			{
				HitCounter.Reset();
			}
			GUILayout.EndHorizontal();
			if (!isHost)
			{
				GUILayout.Label("※ 장비/몬스터 소환·삭제는 호스트만 가능 (Host only)", Array.Empty<GUILayoutOption>());
			}
			if (!string.IsNullOrEmpty(_status))
			{
				GUILayout.Label(_status, Array.Empty<GUILayoutOption>());
			}
			GUI.DragWindow();
		}

		private void SpawnSelectedEnemy()
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PlayerControllerB localPlayer = State.LocalPlayer;
				RoundManager instance = RoundManager.Instance;
				if ((Object)(object)localPlayer == (Object)null || (Object)(object)instance == (Object)null || !State.IsHost || _selectedEnemy < 0 || _selectedEnemy >= _enemies.Count)
				{
					return;
				}
				EnemyEntry enemyEntry = _enemies[_selectedEnemy];
				EnemyType type = enemyEntry.Type;
				if ((Object)(object)type == (Object)null || (Object)(object)type.enemyPrefab == (Object)null)
				{
					_status = "몬스터 데이터를 찾지 못함";
					return;
				}
				Vector3 val = ((Component)localPlayer).transform.position + FlatForward(localPlayer) * 4f;
				NavMeshHit val2 = default(NavMeshHit);
				if (NavMesh.SamplePosition(val, ref val2, 8f, -1))
				{
					val = ((NavMeshHit)(ref val2)).position;
				}
				GameObject obj = Object.Instantiate<GameObject>(type.enemyPrefab, val, Quaternion.identity);
				obj.GetComponentInChildren<NetworkObject>().Spawn(true);
				EnemyAI component = obj.GetComponent<EnemyAI>();
				if ((Object)(object)component != (Object)null)
				{
					instance.SpawnedEnemies.Add(component);
				}
				_status = "소환 완료: " + enemyEntry.Label;
			}
			catch (Exception ex)
			{
				_status = "소환 실패 (로그 확인)";
				Plugin.Log.LogError((object)ex);
			}
		}

		private static Vector3 FlatForward(PlayerControllerB player)
		{
			//IL_0026: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = (((Object)(object)player.gameplayCamera != (Object)null) ? ((Component)player.gameplayCamera).transform.forward : ((Component)player).transform.forward);
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
			{
				val = ((Component)player).transform.forward;
			}
			return ((Vector3)(ref val)).normalized;
		}

		private static Item FindItem(List<Item> all, ItemEntry entry)
		{
			List<Item> source = all.Where((Item i) => (Object)(object)i != (Object)null && (Object)(object)i.spawnPrefab != (Object)null).ToList();
			Item val = ((IEnumerable<Item>)source).FirstOrDefault((Func<Item, bool>)((Item i) => string.Equals(i.itemName, entry.ItemName, StringComparison.OrdinalIgnoreCase)));
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			List<Item> source2 = source.Where((Item i) => (Object)(object)i.spawnPrefab.GetComponent(entry.Component) != (Object)null).ToList();
			val = ((IEnumerable<Item>)source2).FirstOrDefault((Func<Item, bool>)((Item i) => ((Object)i.spawnPrefab).name.IndexOf(entry.PrefabHint, StringComparison.OrdinalIgnoreCase) >= 0));
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			return source2.FirstOrDefault();
		}

		private void SpawnItem(ItemEntry entry)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PlayerControllerB localPlayer = State.LocalPlayer;
				StartOfRound instance = StartOfRound.Instance;
				if ((Object)(object)localPlayer == (Object)null || (Object)(object)instance == (Object)null || (Object)(object)instance.allItemsList == (Object)null || !State.IsHost)
				{
					return;
				}
				Item val = FindItem(instance.allItemsList.itemsList, entry);
				if ((Object)(object)val == (Object)null)
				{
					_status = "장비 데이터를 찾지 못함: " + entry.ItemName;
					return;
				}
				Vector3 val2 = ((Component)localPlayer).transform.position + FlatForward(localPlayer) * 1.5f + Vector3.up * 1.2f;
				GameObject obj = Object.Instantiate<GameObject>(val.spawnPrefab, val2, Quaternion.identity, instance.propsContainer);
				GrabbableObject component = obj.GetComponent<GrabbableObject>();
				if ((Object)(object)component != (Object)null)
				{
					component.fallTime = 0f;
				}
				obj.GetComponent<NetworkObject>().Spawn(false);
				_status = "장비 소환 완료: " + entry.Label;
			}
			catch (Exception ex)
			{
				_status = "장비 소환 실패 (로그 확인)";
				Plugin.Log.LogError((object)ex);
			}
		}

		private Terminal GetTerminal()
		{
			if ((Object)(object)_terminal == (Object)null)
			{
				_terminal = Object.FindObjectOfType<Terminal>();
			}
			return _terminal;
		}

		private void AddCredits(int amount)
		{
			try
			{
				Terminal terminal = GetTerminal();
				if ((Object)(object)terminal == (Object)null)
				{
					_status = "터미널을 찾지 못함";
					return;
				}
				terminal.groupCredits = Mathf.Max(0, terminal.groupCredits + amount);
				terminal.SyncGroupCreditsServerRpc(terminal.groupCredits, terminal.numberOfItemsInDropship);
				_status = "돈 +" + amount + "  (현재 " + terminal.groupCredits + ")";
			}
			catch (Exception ex)
			{
				_status = "돈 추가 실패 (로그 확인)";
				Plugin.Log.LogError((object)ex);
			}
		}

		private void DeleteAllEnemies()
		{
			try
			{
				if (!State.IsHost)
				{
					return;
				}
				int num = 0;
				EnemyAI[] array = Object.FindObjectsOfType<EnemyAI>();
				foreach (EnemyAI val in array)
				{
					if (!((Object)(object)val == (Object)null))
					{
						if ((Object)(object)val.enemyType != (Object)null)
						{
							val.enemyType.numberSpawned = 0;
						}
						NetworkObject networkObject = ((NetworkBehaviour)val).NetworkObject;
						if ((Object)(object)networkObject != (Object)null && networkObject.IsSpawned)
						{
							networkObject.Despawn(true);
						}
						else
						{
							Object.Destroy((Object)(object)((Component)val).gameObject);
						}
						num++;
					}
				}
				RoundManager instance = RoundManager.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					instance.SpawnedEnemies.Clear();
				}
				_status = "삭제 완료: " + num + "마리";
			}
			catch (Exception ex)
			{
				_status = "삭제 실패 (로그 확인)";
				Plugin.Log.LogError((object)ex);
			}
		}
	}
}