Decompiled source of KASSEN TeamBattle v1.0.4

TeamBattle.dll

Decompiled 4 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Mirror;
using MoveClasses;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("TeamBattle")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TeamBattle")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("30871c5a-f70c-4492-ba06-01b2a3b215d2")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace GladioMoriKassenTeamBattle;

public enum Language
{
	English,
	Japanese
}
[BepInPlugin("jp.jyoki_tsubame.gladiomori.kassen", "-KASSEN- Team Battle", "1.0.4")]
public class GladioMoriKassenTeamBattlePlugin : BaseUnityPlugin
{
	public enum GameResultType
	{
		Win,
		Draw
	}

	public struct GameDecision
	{
		public GameResultType Result;

		public string WinningTeam;
	}

	public static class GameDecisionEvaluator
	{
		public static GameDecision EvaluateStandardGameResult(Dictionary<string, List<PlayerGameStateInfo>> teams, List<PlayerGameStateInfo> alivePlayers)
		{
			GameDecision result = default(GameDecision);
			if (alivePlayers.Count > 0 && teams.Count == 1)
			{
				result.Result = GameResultType.Win;
				string text = teams.First().Key;
				if (string.IsNullOrEmpty(text))
				{
					text = TeamHelper.ExtractTeamColor(teams.First().Value.First().player.playerName);
				}
				result.WinningTeam = text;
				LogInstance.LogInfo((object)("EvaluateStandardGameResult: Winning Team = " + text));
			}
			else
			{
				result.Result = GameResultType.Draw;
				result.WinningTeam = "";
				LogInstance.LogInfo((object)"EvaluateStandardGameResult: Draw");
			}
			return result;
		}

		public static GameDecision EvaluateCaptainGameResult(Dictionary<string, List<PlayerGameStateInfo>> teams, List<PlayerGameStateInfo> alivePlayers)
		{
			GameDecision result = default(GameDecision);
			Dictionary<string, bool> dictionary = new Dictionary<string, bool>();
			foreach (KeyValuePair<string, List<PlayerGameStateInfo>> team in teams)
			{
				string key = team.Key;
				bool flag2 = (dictionary[key] = team.Value.Any(delegate(PlayerGameStateInfo p)
				{
					string playerName = p.player.playerName;
					return (string.IsNullOrEmpty(playerName) ? "" : Regex.Replace(playerName, "<[^>]+>", "")).StartsWith("[CAP]");
				}));
				LogInstance.LogInfo((object)$"EvaluateCaptainGameResult: Team '{key}' hasCaptain = {flag2}");
			}
			List<string> list = (from kvp in dictionary
				where kvp.Value
				select kvp.Key).ToList();
			if (list.Count == 1)
			{
				result.Result = GameResultType.Win;
				result.WinningTeam = list[0];
				LogInstance.LogInfo((object)("EvaluateCaptainGameResult: Winning Team = " + list[0]));
			}
			else
			{
				result.Result = GameResultType.Draw;
				result.WinningTeam = "";
				LogInstance.LogInfo((object)"EvaluateCaptainGameResult: Draw (multiple or no teams with captain alive)");
			}
			return result;
		}
	}

	public static bool modEnabled = false;

	public static bool gameOverModEnabled = false;

	public static bool spawnPositioningEnabled = false;

	public static bool logEnabled = false;

	public static bool captainModeEnabled = false;

	public static bool autoTeamAssignmentEnabled = true;

	public static Dictionary<int, int> playerColorSelections = new Dictionary<int, int>();

	public static Dictionary<int, bool> playerDropdownOpen = new Dictionary<int, bool>();

	public static Dictionary<int, bool> captainFlags = new Dictionary<int, bool>();

	private List<MultiplayerRoomPlayer> previousPlayers = new List<MultiplayerRoomPlayer>();

	public static Dictionary<int, string> originalPlayerNames = new Dictionary<int, string>();

	public static int CurrentTeamCount = 0;

	public static string[] CurrentAutoTeamColors = null;

	private bool uiOpen;

	private Rect windowRect = new Rect(100f, 100f, 500f, 1200f);

	private KeyCode toggleKey = (KeyCode)288;

	private string teamCountInput = "2";

	private string autoTeamColorsInput = "red, blue, orange, yellow, cyan, purple, brown";

	public static Dictionary<int, HashSet<Vector3>> usedStaticSpawnPositions = new Dictionary<int, HashSet<Vector3>>();

	public static Language currentLanguage = Language.English;

	private static readonly Dictionary<string, string> englishText = new Dictionary<string, string>
	{
		{ "ModEnabled", "Team color function Enabled" },
		{ "TeamGameOverEnabled", "Team GameOver Enabled" },
		{ "SpawnPositioningEnabled", "Spawn Positioning Enabled" },
		{ "ChatBroadcastTeamAssignment", "Team Assignment Announcement" },
		{ "PromptTeamCheck", "Prompt Team Check Announcement" },
		{ "RestartAnnoucement", "Restart Announcement" },
		{ "TeamChangeAnnouncement", "Team Changing Announcement" },
		{ "RuleAnnouncement", "Rule Announcement" },
		{ "RuleAnnouncementForJP", "Rule Announcement for JP User" },
		{ "NameSelection", "Select Color for each player's name:" },
		{ "UpdateAllPlayers", "Update All Players" },
		{ "AutoTeamAssignmentSettings", "Auto Team Assignment Settings" },
		{ "TeamCount", "Team Count:" },
		{ "AutoTeamColors", "Auto Team Colors (comma separated):" },
		{ "AutoAssignTeams", "Auto Assign Teams" },
		{ "Language", "Language:" },
		{ "LogEanbled", "Log Enabled:" },
		{ "CaptainModeEnabled", "Captain Mode Enabled" },
		{ "NewPlayerAutoAssignment", "Auto team assignment on new player entry enabled" },
		{ "Captain", "Captain" },
		{ "SelectCaptain", "Selection of a captain" }
	};

	private static readonly Dictionary<string, string> japaneseText = new Dictionary<string, string>
	{
		{ "ModEnabled", "チームカラー機能有効" },
		{ "TeamGameOverEnabled", "チーム勝敗機能有効" },
		{ "SpawnPositioningEnabled", "スポーン位置調整機能有効" },
		{ "ChatBroadcastTeamAssignment", "チーム割り振り発表アナウンス" },
		{ "PromptTeamCheck", "チーム確認を促すアナウンス" },
		{ "RestartAnnoucement", "ゲーム再開アナウンス" },
		{ "TeamChangeAnnouncement", "チーム変更中アナウンス" },
		{ "RuleAnnouncement", "ルール説明アナウンス" },
		{ "RuleAnnouncementForJP", "ルール説明アナウンス(ローマ字)" },
		{ "NameSelection", "各プレイヤーの名前に付与する色:" },
		{ "UpdateAllPlayers", "全プレイヤー更新" },
		{ "AutoTeamAssignmentSettings", "自動チーム分け設定" },
		{ "TeamCount", "チーム数:" },
		{ "AutoTeamColors", "自動割り当て色(カンマ区切り):" },
		{ "AutoAssignTeams", "自動チーム分け" },
		{ "Language", "言語:" },
		{ "LogEanbled", "ログ有効:" },
		{ "CaptainModeEnabled", "大将戦有効" },
		{ "NewPlayerAutoAssignment", "新規入室時の自動チーム割り当て有効" },
		{ "Captain", "大将" },
		{ "SelectCaptain", "大将をランダムに選出" }
	};

	public static GladioMoriKassenTeamBattlePlugin Instance { get; private set; }

	public static ManualLogSource LogInstance { get; private set; }

	public static string[] colorOptions
	{
		get
		{
			if ((Object)(object)Instance == (Object)null)
			{
				return new string[23]
				{
					"nothing", "aqua", "black", "blue", "brown", "cyan", "darkblue", "fuchsia", "green", "grey",
					"lightblue", "lime", "magenta", "maroon", "navy", "olive", "orange", "purple", "red", "silver",
					"teal", "white", "yellow"
				};
			}
			List<string> list = (from s in Instance.autoTeamColorsInput.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries)
				select s.Trim().ToLower()).ToList();
			list.Insert(0, "nothing");
			return list.ToArray();
		}
	}

	public static string Localize(string key)
	{
		if (currentLanguage == Language.Japanese)
		{
			if (!japaneseText.ContainsKey(key))
			{
				return key;
			}
			return japaneseText[key];
		}
		if (!englishText.ContainsKey(key))
		{
			return key;
		}
		return englishText[key];
	}

	private void Awake()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		Instance = this;
		LogInstance = ((BaseUnityPlugin)this).Logger;
		new Harmony("jp.jyoki_tsubame.gladiomori.kassen").PatchAll();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"GladioMoriKassenTeamBattle: Loaded");
	}

	private IEnumerator OnPlayerListChangedCoroutine(List<MultiplayerRoomPlayer> currentPlayers)
	{
		yield return (object)new WaitForSeconds(1f);
		if (!autoTeamAssignmentEnabled)
		{
			yield break;
		}
		Dictionary<int, int> dictionary = new Dictionary<int, int>();
		foreach (MultiplayerRoomPlayer currentPlayer in currentPlayers)
		{
			int key = ((((NetworkBehaviour)currentPlayer).connectionToClient != null) ? ((NetworkConnection)((NetworkBehaviour)currentPlayer).connectionToClient).connectionId : ((Object)currentPlayer).GetInstanceID());
			if (!playerColorSelections.TryGetValue(key, out var value) || value == 0)
			{
				continue;
			}
			int teamIndex = TeamHelper.GetTeamIndex(currentPlayer);
			if (teamIndex >= 0)
			{
				if (!dictionary.ContainsKey(teamIndex))
				{
					dictionary[teamIndex] = 0;
				}
				dictionary[teamIndex]++;
			}
		}
		foreach (MultiplayerRoomPlayer currentPlayer2 in currentPlayers)
		{
			int num = ((((NetworkBehaviour)currentPlayer2).connectionToClient != null) ? ((NetworkConnection)((NetworkBehaviour)currentPlayer2).connectionToClient).connectionId : ((Object)currentPlayer2).GetInstanceID());
			if (playerColorSelections.TryGetValue(num, out var value2) && value2 != 0)
			{
				continue;
			}
			int num2 = 0;
			if (dictionary.Count > 0)
			{
				num2 = dictionary.OrderBy((KeyValuePair<int, int> kvp) => kvp.Value).First().Key;
			}
			string text = CurrentAutoTeamColors[num2];
			int num3 = Array.IndexOf(colorOptions, text);
			if (num3 < 0)
			{
				LogInstance.LogWarning((object)("自動割り当て: 指定色 '" + text + "' が colorOptions に存在しません。"));
				continue;
			}
			playerColorSelections[num] = num3;
			LogInstance.LogInfo((object)$"自動割り当て: プレイヤー {currentPlayer2.playerName} (ID:{num}) をチーム '{text}' に割り当て");
			ForceUpdatePlayerName(currentPlayer2);
			if (dictionary.ContainsKey(num2))
			{
				dictionary[num2]++;
			}
			else
			{
				dictionary[num2] = 1;
			}
		}
	}

	private void Update()
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		if (Input.GetKeyDown(toggleKey))
		{
			uiOpen = !uiOpen;
			LogInfo("管理ウィンドウ表示状態: " + uiOpen);
		}
		MonitorPlayerList();
	}

	private void MonitorPlayerList()
	{
		List<MultiplayerRoomPlayer> list = Object.FindObjectsOfType<MultiplayerRoomPlayer>().ToList();
		if (list.Count != previousPlayers.Count || !list.Select((MultiplayerRoomPlayer p) => ((Object)p).GetInstanceID()).SequenceEqual(previousPlayers.Select((MultiplayerRoomPlayer p) => ((Object)p).GetInstanceID())))
		{
			((MonoBehaviour)this).StartCoroutine(OnPlayerListChangedCoroutine(list));
			LogInfo($"[PlayerMonitor] Player list changed: {previousPlayers.Count} -> {list.Count}");
			previousPlayers = list;
		}
	}

	private void OnGUI()
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Expected O, but got Unknown
		//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)
		if (uiOpen)
		{
			windowRect = GUI.Window(123456, windowRect, new WindowFunction(DrawWindow), "-KASSEN- Team Battle v1.0.4");
		}
	}

	private void DrawWindow(int windowID)
	{
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b48: Unknown result type (might be due to invalid IL or missing references)
		GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
		if (GUILayout.Button(Localize("Language") + " : " + currentLanguage, Array.Empty<GUILayoutOption>()))
		{
			currentLanguage = ((currentLanguage == Language.English) ? Language.Japanese : Language.English);
			LogInfo("Language switched to " + currentLanguage);
		}
		bool flag = GUILayout.Toggle(modEnabled, Localize("ModEnabled"), Array.Empty<GUILayoutOption>());
		if (flag != modEnabled)
		{
			modEnabled = flag;
			if (!modEnabled)
			{
				gameOverModEnabled = false;
				spawnPositioningEnabled = false;
				captainModeEnabled = false;
				autoTeamAssignmentEnabled = false;
				MultiplayerRoomPlayer[] array = Object.FindObjectsOfType<MultiplayerRoomPlayer>();
				foreach (MultiplayerRoomPlayer val in array)
				{
					int key = ((((NetworkBehaviour)val).connectionToClient != null) ? ((NetworkConnection)((NetworkBehaviour)val).connectionToClient).connectionId : ((Object)val).GetInstanceID());
					playerColorSelections[key] = 0;
					captainFlags[key] = false;
					ForceUpdatePlayerName(val);
				}
			}
		}
		GUI.enabled = modEnabled;
		bool enabled = GUI.enabled;
		GUI.enabled = true;
		GUI.DragWindow(new Rect(0f, 0f, 10000f, 20f));
		GUI.enabled = enabled;
		gameOverModEnabled = GUILayout.Toggle(gameOverModEnabled, Localize("TeamGameOverEnabled"), Array.Empty<GUILayoutOption>());
		spawnPositioningEnabled = GUILayout.Toggle(spawnPositioningEnabled, Localize("SpawnPositioningEnabled"), Array.Empty<GUILayoutOption>());
		bool flag2 = GUILayout.Toggle(captainModeEnabled, Localize("CaptainModeEnabled"), Array.Empty<GUILayoutOption>());
		if (flag2 != captainModeEnabled)
		{
			captainModeEnabled = flag2;
			LogInfo("Captain mode switched to " + captainModeEnabled);
			if (!captainModeEnabled)
			{
				MultiplayerRoomPlayer[] array = Object.FindObjectsOfType<MultiplayerRoomPlayer>();
				foreach (MultiplayerRoomPlayer val2 in array)
				{
					int num = ((((NetworkBehaviour)val2).connectionToClient != null) ? ((NetworkConnection)((NetworkBehaviour)val2).connectionToClient).connectionId : ((Object)val2).GetInstanceID());
					captainFlags[num] = false;
					ForceUpdatePlayerName(val2);
					LogInfo($"Captain mode off: Reset captain flag for player {val2.playerName} (ID: {num})");
				}
			}
		}
		if (GUILayout.Button(Localize("SelectCaptain"), Array.Empty<GUILayoutOption>()))
		{
			List<MultiplayerRoomPlayer> list = Object.FindObjectsOfType<MultiplayerRoomPlayer>().ToList();
			if (list.Count == 0)
			{
				LogInstance.LogWarning((object)"Set Random Captain: No players found.");
			}
			else
			{
				foreach (KeyValuePair<int, List<MultiplayerRoomPlayer>> item in (from p in list
					group p by TeamHelper.GetTeamIndex(p) into g
					where g.Key >= 0
					select g).ToDictionary((IGrouping<int, MultiplayerRoomPlayer> g) => g.Key, (IGrouping<int, MultiplayerRoomPlayer> g) => g.ToList()))
				{
					int key2 = item.Key;
					List<MultiplayerRoomPlayer> value = item.Value;
					foreach (MultiplayerRoomPlayer item2 in value)
					{
						int key3 = ((((NetworkBehaviour)item2).connectionToClient != null) ? ((NetworkConnection)((NetworkBehaviour)item2).connectionToClient).connectionId : ((Object)item2).GetInstanceID());
						captainFlags[key3] = false;
						ForceUpdatePlayerName(item2);
					}
					MultiplayerRoomPlayer val3 = value.OrderBy((MultiplayerRoomPlayer x) => Random.value).First();
					int key4 = ((((NetworkBehaviour)val3).connectionToClient != null) ? ((NetworkConnection)((NetworkBehaviour)val3).connectionToClient).connectionId : ((Object)val3).GetInstanceID());
					captainFlags[key4] = true;
					ForceUpdatePlayerName(val3);
					LogInfo($"Set Random Captain: For Team {key2}, assigned Captain = {val3.playerName}");
				}
			}
		}
		autoTeamAssignmentEnabled = GUILayout.Toggle(autoTeamAssignmentEnabled, Localize("NewPlayerAutoAssignment"), Array.Empty<GUILayoutOption>());
		GUILayout.Space(10f);
		if (GUILayout.Button(Localize("ChatBroadcastTeamAssignment"), Array.Empty<GUILayoutOption>()))
		{
			foreach (MultiplayerRoomPlayer item3 in Object.FindObjectsOfType<MultiplayerRoomPlayer>().ToList())
			{
				string cleanName = TeamHelper.GetCleanName(item3.NetworkplayerName);
				string text = TeamHelper.ExtractTeamColor(item3.NetworkplayerName);
				ChatHelper.BroadcastChatMessage(cleanName + ": " + text, "TeamBattleMod");
			}
		}
		if (GUILayout.Button(Localize("PromptTeamCheck"), Array.Empty<GUILayoutOption>()))
		{
			ChatHelper.BroadcastChatMessage("Press ESC to check your team", "TeamBattleMod");
		}
		if (GUILayout.Button(Localize("RestartAnnoucement"), Array.Empty<GUILayoutOption>()))
		{
			ChatHelper.BroadcastChatMessage("Get ready!", "TeamBattleMod");
		}
		if (GUILayout.Button(Localize("TeamChangeAnnouncement"), Array.Empty<GUILayoutOption>()))
		{
			ChatHelper.BroadcastChatMessage("Now, team assignments are changing...", "TeamBattleMod");
		}
		if (GUILayout.Button(Localize("RuleAnnouncement"), Array.Empty<GUILayoutOption>()))
		{
			ChatHelper.BroadcastChatMessage("Your team is your name color. Same color = friend.", "TeamBattleMod");
			ChatHelper.BroadcastChatMessage("Same color = friend, different color = enemy.", "TeamBattleMod");
			ChatHelper.BroadcastChatMessage("Kill other color Players!", "TeamBattleMod");
		}
		if (GUILayout.Button(Localize("RuleAnnouncementForJP"), Array.Empty<GUILayoutOption>()))
		{
			ChatHelper.BroadcastChatMessage("namae no iro ga team wo arawasi masu", "TeamBattleMod");
			ChatHelper.BroadcastChatMessage("player no namae no iroga onazi nara mikata, kotonaru nara teki desu ", "TeamBattleMod");
			ChatHelper.BroadcastChatMessage("namae no iro ga tigau player wo taosi masyou!", "TeamBattleMod");
		}
		GUILayout.Space(10f);
		GUILayout.Label(Localize("NameSelection"), Array.Empty<GUILayoutOption>());
		GUILayout.Space(10f);
		List<MultiplayerRoomPlayer> list2 = Object.FindObjectsOfType<MultiplayerRoomPlayer>().ToList();
		GUILayout.Label("Total: " + list2.Count, Array.Empty<GUILayoutOption>());
		Dictionary<int, int> dictionary = new Dictionary<int, int>();
		foreach (MultiplayerRoomPlayer item4 in list2)
		{
			int teamIndex = TeamHelper.GetTeamIndex(item4);
			if (!dictionary.ContainsKey(teamIndex))
			{
				dictionary[teamIndex] = 0;
			}
			dictionary[teamIndex]++;
		}
		foreach (KeyValuePair<int, int> item5 in dictionary.OrderBy((KeyValuePair<int, int> x) => x.Key))
		{
			string text2 = ((item5.Key >= 0 && CurrentAutoTeamColors != null && CurrentAutoTeamColors.Length > item5.Key) ? CurrentAutoTeamColors[item5.Key] : ((item5.Key < 0) ? "nothing" : colorOptions[item5.Key]));
			string arg = ((!(text2 != "nothing")) ? text2 : ("<color=\"" + text2 + "\">" + text2 + "</color>"));
			GUILayout.Label($"{arg}: {item5.Value}", Array.Empty<GUILayoutOption>());
		}
		GUILayout.Space(10f);
		foreach (MultiplayerRoomPlayer item6 in list2)
		{
			int num2 = ((((NetworkBehaviour)item6).connectionToClient != null) ? ((NetworkConnection)((NetworkBehaviour)item6).connectionToClient).connectionId : ((Object)item6).GetInstanceID());
			int value2 = 0;
			if (!playerColorSelections.TryGetValue(num2, out value2))
			{
				value2 = 0;
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Player: " + item6.playerName, Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Color: " + colorOptions[value2], (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }))
			{
				bool value3 = false;
				playerDropdownOpen.TryGetValue(num2, out value3);
				playerDropdownOpen[num2] = !value3;
				LogInfo($"プレイヤーID:{num2} ドロップダウン展開: {playerDropdownOpen[num2]}");
			}
			bool value4 = false;
			if (!captainFlags.TryGetValue(num2, out value4))
			{
				captainFlags[num2] = false;
				value4 = false;
			}
			bool flag3 = GUILayout.Toggle(value4, Localize("Captain"), Array.Empty<GUILayoutOption>());
			if (flag3 != value4)
			{
				captainFlags[num2] = flag3;
				ForceUpdatePlayerName(item6);
			}
			GUILayout.EndHorizontal();
			if (!(playerDropdownOpen.TryGetValue(num2, out var value5) && value5))
			{
				continue;
			}
			GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), Array.Empty<GUILayoutOption>());
			for (int j = 0; j < colorOptions.Length; j++)
			{
				if (GUILayout.Button(colorOptions[j], Array.Empty<GUILayoutOption>()))
				{
					playerColorSelections[num2] = j;
					playerDropdownOpen[num2] = false;
					LogInfo($"プレイヤーID:{num2} 色選択: {colorOptions[j]} (Index:{j})");
					ForceUpdatePlayerName(item6);
				}
			}
			GUILayout.EndVertical();
		}
		GUILayout.Space(20f);
		GUILayout.Label(Localize("AutoTeamAssignmentSettings"), Array.Empty<GUILayoutOption>());
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		GUILayout.Label(Localize("TeamCount"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) });
		teamCountInput = GUILayout.TextField(teamCountInput, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
		GUILayout.EndHorizontal();
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		GUILayout.Label(Localize("AutoTeamColors"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(180f) });
		autoTeamColorsInput = GUILayout.TextField(autoTeamColorsInput, Array.Empty<GUILayoutOption>());
		GUILayout.EndHorizontal();
		if (GUILayout.Button(Localize("AutoAssignTeams"), Array.Empty<GUILayoutOption>()))
		{
			if (int.TryParse(teamCountInput, out var result) && result > 0)
			{
				CurrentAutoTeamColors = (from s in autoTeamColorsInput.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries)
					select s.Trim().ToLower()).ToArray();
				CurrentTeamCount = result;
				AutoAssignTeams(result, CurrentAutoTeamColors);
				LogInfo($"自動チーム分け: チーム数 {result} に分割");
			}
			else
			{
				LogInstance.LogWarning((object)"自動チーム分け: 無効なチーム数入力");
			}
		}
		logEnabled = GUILayout.Toggle(logEnabled, Localize("LogEnabled"), Array.Empty<GUILayoutOption>());
		GUILayout.Space(10f);
		GUILayout.EndVertical();
		GUI.DragWindow(new Rect(0f, 0f, 10000f, 20f));
	}

	public static string RemoveAllTags(string input)
	{
		if (string.IsNullOrEmpty(input))
		{
			return "Player";
		}
		string text = Regex.Replace(input, "<.*?>", "");
		if (string.IsNullOrWhiteSpace(text))
		{
			return "Player";
		}
		return text;
	}

	public static void ForceUpdatePlayerName(MultiplayerRoomPlayer player)
	{
		int num = ((((NetworkBehaviour)player).connectionToClient != null) ? ((NetworkConnection)((NetworkBehaviour)player).connectionToClient).connectionId : ((Object)player).GetInstanceID());
		if (!originalPlayerNames.ContainsKey(num))
		{
			originalPlayerNames[num] = player.playerName;
		}
		int value = 0;
		if (!playerColorSelections.TryGetValue(num, out value))
		{
			value = 0;
		}
		string text = colorOptions[value];
		string text2 = RemoveAllTags(originalPlayerNames[num]);
		if (string.IsNullOrEmpty(text2))
		{
			text2 = "Player";
		}
		string text3 = text2;
		bool value2 = false;
		if (!captainFlags.TryGetValue(num, out value2))
		{
			value2 = false;
		}
		if (value2)
		{
			text3 = "<b><size=20>[CAP]" + text3 + "</size></b>";
		}
		if (value != 0)
		{
			text3 = "<color=\"" + text + "\">" + text3 + "</color>";
		}
		LogInfo($"ForceUpdatePlayerName: ConnId={num}, OriginalName={text2}, SelectedIndex={value}, SelectedColor={text}, NewName={text3}");
		player.NetworkplayerName = text3;
	}

	public static void AutoAssignTeams(int teamCount, string[] autoTeamColors)
	{
		if (teamCount > autoTeamColors.Length)
		{
			LogInstance.LogWarning((object)$"チーム数 {teamCount} は自動割り当て可能な色数 {autoTeamColors.Length} を超えています。最大 {autoTeamColors.Length} に設定します。");
			teamCount = autoTeamColors.Length;
		}
		List<MultiplayerRoomPlayer> list = Object.FindObjectsOfType<MultiplayerRoomPlayer>().ToList();
		if (list.Count == 0)
		{
			LogInstance.LogWarning((object)"自動チーム分け: プレイヤーが見つかりません");
			return;
		}
		list = list.OrderBy((MultiplayerRoomPlayer p) => Random.value).ToList();
		for (int i = 0; i < list.Count; i++)
		{
			int num = i % teamCount;
			int num2 = ((((NetworkBehaviour)list[i]).connectionToClient != null) ? ((NetworkConnection)((NetworkBehaviour)list[i]).connectionToClient).connectionId : ((Object)list[i]).GetInstanceID());
			string text = autoTeamColors[num];
			int num3 = Array.IndexOf(colorOptions, text);
			if (num3 < 0)
			{
				LogInstance.LogWarning((object)("自動チーム分け: 指定色 '" + text + "' が利用できません。"));
				num3 = 0;
			}
			playerColorSelections[num2] = num3;
			LogInfo($"自動チーム分け: プレイヤー {list[i].playerName} (ID: {num2}) をチーム {text} に割り当て");
			ForceUpdatePlayerName(list[i]);
		}
	}

	public static GameObject GetPlayerCharacter(PlayerMultiplayerInputManager manager)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Expected O, but got Unknown
		FieldInfo fieldInfo = AccessTools.Field(typeof(PlayerMultiplayerInputManager), "playerCharacter");
		if (!(fieldInfo != null))
		{
			return null;
		}
		return (GameObject)fieldInfo.GetValue(manager);
	}

	public static void LogInfo(string log)
	{
		if (logEnabled)
		{
			LogInstance.LogInfo((object)log);
		}
	}

	public static void LogWarning(string log)
	{
		LogInstance.LogWarning((object)log);
	}
}
public struct ChatMessage : NetworkMessage
{
	public string message;

	public string sender;
}
public static class ChatHelper
{
	public static void BroadcastChatMessage(string message, string sender)
	{
		if ((Object)(object)MultiplayerChat.singleton != (Object)null)
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(MultiplayerChat), "RpcHandleMessage", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				methodInfo.Invoke(MultiplayerChat.singleton, new object[2] { message, sender });
				GladioMoriKassenTeamBattlePlugin.LogInfo("ChatHelper: Broadcasted message '" + message + "' from '" + sender + "' via RpcHandleMessage");
			}
			else
			{
				GladioMoriKassenTeamBattlePlugin.LogWarning("ChatHelper: RpcHandleMessage メソッドが見つかりません");
			}
		}
		else
		{
			GladioMoriKassenTeamBattlePlugin.LogWarning("ChatHelper: MultiplayerChat.singleton が null です");
		}
	}
}
public static class SpawnHelperStatic
{
	private static readonly Vector3[] team0Spawns_T2 = (Vector3[])(object)new Vector3[8]
	{
		new Vector3(0f, 1.45f, -12f),
		new Vector3(3f, 1.45f, 0f),
		new Vector3(0f, 1.45f, -3f),
		new Vector3(7f, 6f, 7f),
		new Vector3(12f, 1.45f, 0f),
		new Vector3(8f, 1.45f, 9f),
		new Vector3(7f, 6f, -7f),
		new Vector3(8f, 1.45f, -9f)
	};

	private static readonly Vector3[] team1Spawns_T2 = (Vector3[])(object)new Vector3[8]
	{
		new Vector3(-12f, 1.45f, 0f),
		new Vector3(-8f, 1.45f, 9f),
		new Vector3(-7f, 6f, 7f),
		new Vector3(-3f, 1.45f, 0f),
		new Vector3(-7f, 6f, -7f),
		new Vector3(0f, 1.45f, 12f),
		new Vector3(-8f, 1.45f, -9f),
		new Vector3(0f, 1.45f, 3f)
	};

	private static readonly Vector3[] team0Spawns_T3 = (Vector3[])(object)new Vector3[6]
	{
		new Vector3(7f, 6f, -7f),
		new Vector3(7f, 6f, 7f),
		new Vector3(12f, 1.45f, 0f),
		new Vector3(8f, 1.45f, 9f),
		new Vector3(3f, 1.45f, 0f),
		new Vector3(8f, 1.45f, -9f)
	};

	private static readonly Vector3[] team1Spawns_T3 = (Vector3[])(object)new Vector3[5]
	{
		new Vector3(0f, 1.45f, 12f),
		new Vector3(-7f, 6f, 7f),
		new Vector3(0f, 1.45f, 3f),
		new Vector3(-8f, 1.45f, 9f),
		new Vector3(-3f, 1.45f, 0f)
	};

	private static readonly Vector3[] team2Spawns_T3 = (Vector3[])(object)new Vector3[5]
	{
		new Vector3(-12f, 1.45f, 0f),
		new Vector3(0f, 1.45f, -12f),
		new Vector3(-7f, 6f, -7f),
		new Vector3(0f, 1.45f, -3f),
		new Vector3(-8f, 1.45f, -9f)
	};

	private static readonly Vector3[] team0Spawns_T4 = (Vector3[])(object)new Vector3[4]
	{
		new Vector3(-7f, 6f, 7f),
		new Vector3(-8f, 1.45f, 9f),
		new Vector3(-12f, 1.45f, 0f),
		new Vector3(-3f, 1.45f, 0f)
	};

	private static readonly Vector3[] team1Spawns_T4 = (Vector3[])(object)new Vector3[4]
	{
		new Vector3(0f, 1.45f, 12f),
		new Vector3(7f, 6f, 7f),
		new Vector3(8f, 1.45f, 9f),
		new Vector3(0f, 1.45f, 3f)
	};

	private static readonly Vector3[] team2Spawns_T4 = (Vector3[])(object)new Vector3[4]
	{
		new Vector3(-7f, 6f, -7f),
		new Vector3(0f, 1.45f, -12f),
		new Vector3(0f, 1.45f, -3f),
		new Vector3(-8f, 1.45f, -9f)
	};

	private static readonly Vector3[] team3Spawns_T4 = (Vector3[])(object)new Vector3[4]
	{
		new Vector3(7f, 6f, -7f),
		new Vector3(12f, 1.45f, 0f),
		new Vector3(3f, 1.45f, 0f),
		new Vector3(8f, 1.45f, -9f)
	};

	private static readonly Vector3[] team0Spawns_T5 = (Vector3[])(object)new Vector3[4]
	{
		new Vector3(7f, 6f, -7f),
		new Vector3(8f, 1.45f, -9f),
		new Vector3(0f, 1.45f, -3f),
		new Vector3(0f, 1.45f, -12f)
	};

	private static readonly Vector3[] team1Spawns_T5 = (Vector3[])(object)new Vector3[3]
	{
		new Vector3(8f, 1.45f, 9f),
		new Vector3(0f, 1.45f, 3f),
		new Vector3(0f, 1.45f, 12f)
	};

	private static readonly Vector3[] team2Spawns_T5 = (Vector3[])(object)new Vector3[3]
	{
		new Vector3(-8f, 1.45f, -9f),
		new Vector3(-3f, 1.45f, 0f),
		new Vector3(-7f, 6f, -7f)
	};

	private static readonly Vector3[] team3Spawns_T5 = (Vector3[])(object)new Vector3[3]
	{
		new Vector3(12f, 1.45f, 0f),
		new Vector3(3f, 1.45f, 0f),
		new Vector3(7f, 6f, 7f)
	};

	private static readonly Vector3[] team4Spawns_T5 = (Vector3[])(object)new Vector3[3]
	{
		new Vector3(-12f, 1.45f, 0f),
		new Vector3(-7f, 6f, 7f),
		new Vector3(-8f, 1.45f, 9f)
	};

	private static readonly Vector3[] team0Spawns_T6 = (Vector3[])(object)new Vector3[3]
	{
		new Vector3(-3f, 1.45f, 0f),
		new Vector3(-12f, 1.45f, 0f),
		new Vector3(-7f, 6f, 7f)
	};

	private static readonly Vector3[] team1Spawns_T6 = (Vector3[])(object)new Vector3[3]
	{
		new Vector3(3f, 1.45f, 0f),
		new Vector3(0f, 1.45f, -12f),
		new Vector3(7f, 6f, -7f)
	};

	private static readonly Vector3[] team2Spawns_T6 = (Vector3[])(object)new Vector3[3]
	{
		new Vector3(0f, 1.45f, 3f),
		new Vector3(-8f, 1.45f, 9f),
		new Vector3(0f, 1.45f, 12f)
	};

	private static readonly Vector3[] team3Spawns_T6 = (Vector3[])(object)new Vector3[3]
	{
		new Vector3(-8f, 1.45f, -9f),
		new Vector3(-7f, 6f, -7f),
		new Vector3(0f, 1.45f, -3f)
	};

	private static readonly Vector3[] team4Spawns_T6 = (Vector3[])(object)new Vector3[2]
	{
		new Vector3(8f, 1.45f, 9f),
		new Vector3(7f, 6f, 7f)
	};

	private static readonly Vector3[] team5Spawns_T6 = (Vector3[])(object)new Vector3[2]
	{
		new Vector3(12f, 1.45f, 0f),
		new Vector3(8f, 1.45f, -9f)
	};

	private static Vector3[] GetSpawnArrayForTeam(int teamCount, int teamIndex)
	{
		switch (teamCount)
		{
		case 2:
			if (teamIndex != 0)
			{
				return team1Spawns_T2;
			}
			return team0Spawns_T2;
		case 3:
			return teamIndex switch
			{
				0 => team0Spawns_T3, 
				1 => team1Spawns_T3, 
				2 => team2Spawns_T3, 
				_ => throw new ArgumentOutOfRangeException(), 
			};
		case 4:
			return teamIndex switch
			{
				0 => team0Spawns_T4, 
				1 => team1Spawns_T4, 
				2 => team2Spawns_T4, 
				3 => team3Spawns_T4, 
				_ => throw new ArgumentOutOfRangeException(), 
			};
		case 5:
			return teamIndex switch
			{
				0 => team0Spawns_T5, 
				1 => team1Spawns_T5, 
				2 => team2Spawns_T5, 
				3 => team3Spawns_T5, 
				4 => team4Spawns_T5, 
				_ => throw new ArgumentOutOfRangeException(), 
			};
		case 6:
			return teamIndex switch
			{
				0 => team0Spawns_T6, 
				1 => team1Spawns_T6, 
				2 => team2Spawns_T6, 
				3 => team3Spawns_T6, 
				4 => team4Spawns_T6, 
				5 => team5Spawns_T6, 
				_ => throw new ArgumentOutOfRangeException(), 
			};
		default:
			throw new NotImplementedException("この実装はチーム数が2,3,4,5,6の場合のみ対応しています。");
		}
	}

	public static Vector3 GetUniqueStaticSpawnPointForTeam(int teamIndex, int teamCount)
	{
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: 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)
		Vector3[] spawnArrayForTeam = GetSpawnArrayForTeam(teamCount, teamIndex);
		if (!GladioMoriKassenTeamBattlePlugin.usedStaticSpawnPositions.ContainsKey(teamIndex))
		{
			GladioMoriKassenTeamBattlePlugin.usedStaticSpawnPositions[teamIndex] = new HashSet<Vector3>();
		}
		Vector3[] array = spawnArrayForTeam.OrderByDescending(delegate(Vector3 sp)
		{
			//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_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)
			Vector2 val3 = new Vector2(sp.x, sp.z);
			return ((Vector2)(ref val3)).magnitude;
		}).ToArray();
		Vector3[] array2 = array;
		foreach (Vector3 val in array2)
		{
			if (!GladioMoriKassenTeamBattlePlugin.usedStaticSpawnPositions[teamIndex].Contains(val))
			{
				GladioMoriKassenTeamBattlePlugin.usedStaticSpawnPositions[teamIndex].Add(val);
				return val;
			}
		}
		GladioMoriKassenTeamBattlePlugin.LogInstance.LogWarning((object)$"All static spawn positions for team {teamIndex} are used. Returning a random spawn.");
		Vector3 val2 = array[Random.Range(0, array.Length)];
		GladioMoriKassenTeamBattlePlugin.usedStaticSpawnPositions[teamIndex].Add(val2);
		return val2;
	}

	public static void ClearUsedStaticSpawnPositions()
	{
		foreach (int item in GladioMoriKassenTeamBattlePlugin.usedStaticSpawnPositions.Keys.ToList())
		{
			GladioMoriKassenTeamBattlePlugin.usedStaticSpawnPositions[item].Clear();
		}
	}
}
[HarmonyPatch(typeof(MultiplayerRoomPlayer), "UserCode_CmdChangePlayerName__String")]
public static class NameChangerPatch
{
	private static bool Prefix(MultiplayerRoomPlayer __instance, ref string newPlayerName)
	{
		if (!GladioMoriKassenTeamBattlePlugin.modEnabled)
		{
			return true;
		}
		int num = ((((NetworkBehaviour)__instance).connectionToClient != null) ? ((NetworkConnection)((NetworkBehaviour)__instance).connectionToClient).connectionId : ((Object)__instance).GetInstanceID());
		int value = 0;
		GladioMoriKassenTeamBattlePlugin.playerColorSelections.TryGetValue(num, out value);
		string text = GladioMoriKassenTeamBattlePlugin.colorOptions[value];
		GladioMoriKassenTeamBattlePlugin.LogInfo($"[NameChangerPatch] ConnId={num} : Before Process newPlayerName={newPlayerName}, SelectedIndex={value}, SelectedColor={text}");
		if (newPlayerName.StartsWith("<color=") && newPlayerName.EndsWith("</color>"))
		{
			int num2 = newPlayerName.IndexOf(">") + 1;
			int num3 = newPlayerName.LastIndexOf("</color>");
			if (num2 > 0 && num3 > num2)
			{
				newPlayerName = newPlayerName.Substring(num2, num3 - num2);
			}
		}
		if (value != 0)
		{
			newPlayerName = "<color=\"" + text + "\">" + newPlayerName + "</color>";
		}
		GladioMoriKassenTeamBattlePlugin.LogInfo($"[NameChangerPatch] ConnId={num} : After Process newPlayerName={newPlayerName}");
		return true;
	}
}
[HarmonyPatch(typeof(PlayerMultiplayerInputManager), "CreatePlayer")]
public static class SpawnPatch
{
	private static bool Prefix(PlayerMultiplayerInputManager __instance)
	{
		//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_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_0096: 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_01a7: Unknown result type (might be due to invalid IL or missing references)
		if (!GladioMoriKassenTeamBattlePlugin.spawnPositioningEnabled)
		{
			return true;
		}
		if (!NetworkServer.active)
		{
			Debug.LogWarning((object)"[Server] CreatePlayer called when server was not active");
			return false;
		}
		if ((Object)(object)__instance.multiplayerRoomPlayer == (Object)null)
		{
			GladioMoriKassenTeamBattlePlugin.LogInfo("SpawnPatch: multiplayerRoomPlayer not found");
			return false;
		}
		int teamIndex = TeamHelper.GetTeamIndex(__instance.multiplayerRoomPlayer);
		GladioMoriKassenTeamBattlePlugin.LogInfo($"SpawnPatch: teamIndex = {teamIndex}");
		int currentTeamCount = GladioMoriKassenTeamBattlePlugin.CurrentTeamCount;
		if (teamIndex < 0 || currentTeamCount <= 0)
		{
			GladioMoriKassenTeamBattlePlugin.LogInfo($"SpawnPatch: illegal state teamIndex:{teamIndex} or teamCount:{currentTeamCount}");
			return true;
		}
		Vector3 uniqueStaticSpawnPointForTeam = SpawnHelperStatic.GetUniqueStaticSpawnPointForTeam(teamIndex, currentTeamCount);
		Quaternion identity = Quaternion.identity;
		GameObject val = Object.Instantiate<GameObject>(__instance.playerPrefab, uniqueStaticSpawnPointForTeam, identity);
		AccessTools.Field(typeof(PlayerMultiplayerInputManager), "playerCharacter").SetValue(__instance, val);
		NetworkServer.Spawn(val, (NetworkConnection)null);
		FieldInfo fieldInfo = AccessTools.Field(typeof(PlayerMultiplayerInputManager), "ballMovements");
		List<BallMovement> value = val.GetComponentsInChildren<BallMovement>().ToList();
		fieldInfo.SetValue(__instance, value);
		__instance.rotatePlayer = val.GetComponentsInChildren<RotatePlayer>(true).FirstOrDefault();
		FieldInfo fieldInfo2 = AccessTools.Field(typeof(PlayerMultiplayerInputManager), "playerAnimator");
		PlayerAnimator componentInChildren = val.GetComponentInChildren<PlayerAnimator>();
		fieldInfo2.SetValue(__instance, componentInChildren);
		FieldInfo fieldInfo3 = AccessTools.Field(typeof(PlayerMultiplayerInputManager), "playerHealth");
		PlayerHealth component = val.GetComponent<PlayerHealth>();
		fieldInfo3.SetValue(__instance, component);
		if (__instance.moveSet != null && (Object)(object)componentInChildren != (Object)null)
		{
			componentInChildren.SetMoveSet(__instance.moveSet, false, false);
			__instance.UpdateDefaultMovesetSettings();
		}
		component.SetEquipment(__instance.equippedEquipment, true);
		NetworkIdentity component2 = val.GetComponent<NetworkIdentity>();
		__instance.NetworkplayerHealthIdentity = component2.netId;
		component.OnlyPhysical();
		GladioMoriKassenTeamBattlePlugin.LogInfo($"SpawnPatch: Player {__instance.playerName} instantiated at {uniqueStaticSpawnPointForTeam}");
		return false;
	}
}
public static class TeamHelper
{
	public static int GetTeamIndex(MultiplayerRoomPlayer mrp)
	{
		int key = ((((NetworkBehaviour)mrp).connectionToClient != null) ? ((NetworkConnection)((NetworkBehaviour)mrp).connectionToClient).connectionId : ((Object)mrp).GetInstanceID());
		if (GladioMoriKassenTeamBattlePlugin.playerColorSelections.TryGetValue(key, out var value))
		{
			string value2 = GladioMoriKassenTeamBattlePlugin.colorOptions[value];
			if (GladioMoriKassenTeamBattlePlugin.CurrentAutoTeamColors != null)
			{
				return Array.IndexOf(GladioMoriKassenTeamBattlePlugin.CurrentAutoTeamColors, value2);
			}
			return value;
		}
		return -1;
	}

	public static string GetCleanNameFromNetwork(MultiplayerRoomPlayer mrp)
	{
		string networkplayerName = mrp.NetworkplayerName;
		if (!string.IsNullOrEmpty(networkplayerName) && networkplayerName.StartsWith("<color=\"") && networkplayerName.EndsWith("</color>"))
		{
			int num = networkplayerName.IndexOf(">") + 1;
			int num2 = networkplayerName.LastIndexOf("</color>");
			if (num > 0 && num2 > num)
			{
				return networkplayerName.Substring(num, num2 - num).ToLower();
			}
		}
		return networkplayerName;
	}

	public static string ExtractTeamColor(string coloredName)
	{
		if (!string.IsNullOrEmpty(coloredName) && coloredName.StartsWith("<color=\"") && coloredName.Contains("\">"))
		{
			int length = "<color=\"".Length;
			int num = coloredName.IndexOf("\">", length);
			if (num > length)
			{
				string text = coloredName.Substring(length, num - length).ToLower();
				GladioMoriKassenTeamBattlePlugin.LogInfo("ExtractTeamColor: Raw='" + coloredName + "', Extracted='" + text + "'");
				return text;
			}
		}
		GladioMoriKassenTeamBattlePlugin.LogInstance.LogWarning((object)("ExtractTeamColor: Invalid input. Value = '" + coloredName + "'"));
		return "";
	}

	public static string GetCleanName(string coloredName)
	{
		if (!string.IsNullOrEmpty(coloredName) && coloredName.StartsWith("<color=\"") && coloredName.EndsWith("</color>"))
		{
			int num = coloredName.IndexOf(">") + 1;
			int num2 = coloredName.LastIndexOf("</color>");
			if (num > 0 && num2 > num)
			{
				return coloredName.Substring(num, num2 - num);
			}
		}
		return coloredName;
	}
}
[HarmonyPatch(typeof(GameMaster), "GameOver")]
public static class GameOverPatch
{
	private static bool Prefix(GameMaster __instance, bool forceLoss)
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Expected O, but got Unknown
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: 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_01a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Expected O, but got Unknown
		//IL_0221: Unknown result type (might be due to invalid IL or missing references)
		if (!GladioMoriKassenTeamBattlePlugin.gameOverModEnabled)
		{
			return true;
		}
		if (__instance.gameIsOver || __instance.testScene)
		{
			return false;
		}
		__instance.gameIsOver = true;
		if ((Object)(object)ReplayManager.singleton != (Object)null)
		{
			ReplayManager.singleton.PauseRecording();
		}
		WinScreenInfo val = new WinScreenInfo();
		List<PlayerGameStateInfo> list = __instance.registeredPlayers.Where((PlayerGameStateInfo x) => x.player.alive).ToList();
		GladioMoriKassenTeamBattlePlugin.LogInfo($"GameOverPatch: AlivePlayers Count = {list.Count}");
		Dictionary<string, List<PlayerGameStateInfo>> dictionary = new Dictionary<string, List<PlayerGameStateInfo>>();
		foreach (PlayerGameStateInfo item in list)
		{
			string text = TeamHelper.ExtractTeamColor(item.player.playerName);
			GladioMoriKassenTeamBattlePlugin.LogInfo("GameOverPatch: Player " + item.player.playerName + " チーム = " + text);
			if (!dictionary.ContainsKey(text))
			{
				dictionary[text] = new List<PlayerGameStateInfo>();
			}
			dictionary[text].Add(item);
		}
		if (forceLoss)
		{
			val.gameEndResultType = (GameEndResultType)2;
		}
		else
		{
			GladioMoriKassenTeamBattlePlugin.GameDecision gameDecision = ((!GladioMoriKassenTeamBattlePlugin.captainModeEnabled) ? GladioMoriKassenTeamBattlePlugin.GameDecisionEvaluator.EvaluateStandardGameResult(dictionary, list) : GladioMoriKassenTeamBattlePlugin.GameDecisionEvaluator.EvaluateCaptainGameResult(dictionary, list));
			val.gameEndResultType = (GameEndResultType)((gameDecision.Result != 0) ? 1 : 0);
			val.winningPlayerName = gameDecision.WinningTeam;
		}
		val.playerList = new List<WinScreenPlayerInfo>();
		foreach (PlayerGameStateInfo registeredPlayer in __instance.registeredPlayers)
		{
			val.playerList.Add(new WinScreenPlayerInfo
			{
				deathTime = registeredPlayer.deathTime,
				playerName = registeredPlayer.player.playerName,
				deathReason = registeredPlayer.deathReason
			});
		}
		if ((Object)(object)SingleplayerManager.singleton != (Object)null)
		{
			bool flag = false;
			if (!forceLoss && list.Count > 0 && dictionary.Count == 1 && !dictionary.First().Value.First().player.ai)
			{
				flag = true;
			}
			SingleplayerManager.singleton.HandleFightResult(val.gameEndResultType, flag);
		}
		if ((Object)(object)__instance.multiplayerGameMaster != (Object)null)
		{
			GladioMoriKassenTeamBattlePlugin.LogInfo("GameOverPatch: Calling multiplayerGameMaster.GameOver");
			__instance.multiplayerGameMaster.GameOver(val);
			foreach (int item2 in GladioMoriKassenTeamBattlePlugin.usedStaticSpawnPositions.Keys.ToList())
			{
				GladioMoriKassenTeamBattlePlugin.usedStaticSpawnPositions[item2].Clear();
			}
			GladioMoriKassenTeamBattlePlugin.LogInfo("GameOverPatch: usedSpawnPositions cleared.");
			return false;
		}
		if ((Object)(object)__instance.gameMenu != (Object)null)
		{
			__instance.gameMenu.ShowWinScreenInfo(val);
		}
		foreach (int item3 in GladioMoriKassenTeamBattlePlugin.usedStaticSpawnPositions.Keys.ToList())
		{
			GladioMoriKassenTeamBattlePlugin.usedStaticSpawnPositions[item3].Clear();
		}
		GladioMoriKassenTeamBattlePlugin.LogInfo("GameOverPatch: usedSpawnPositions cleared.");
		return false;
	}
}
[HarmonyPatch(typeof(GameMaster), "InformPlayerDeath")]
public static class InformPlayerDeathPatch
{
	private static void Postfix(GameMaster __instance, PlayerHealth player, DeathReason newDeathReason, PlayerHealth newKiller)
	{
		if (!GladioMoriKassenTeamBattlePlugin.gameOverModEnabled)
		{
			return;
		}
		string playerName = player.playerName;
		string text = (string.IsNullOrEmpty(playerName) ? playerName : Regex.Replace(playerName, "<color=\"[^\"]*\">|</color>", ""));
		if (text.StartsWith("<b><size=20>[CAP]"))
		{
			string text2 = TeamHelper.ExtractTeamColor(playerName);
			string text3 = Regex.Replace(text, "<.*?>", string.Empty);
			string text4 = "Captain " + text3 + " of team " + text2 + " has died!";
			ChatHelper.BroadcastChatMessage(text4, "TeamBattleMod");
			GladioMoriKassenTeamBattlePlugin.LogInfo("InformPlayerDeathPatch: Announced captain death: " + text4);
		}
		List<PlayerGameStateInfo> list = __instance.registeredPlayers.Where((PlayerGameStateInfo x) => !x.player.ai && x.player.alive).ToList();
		Dictionary<string, List<PlayerGameStateInfo>> dictionary = new Dictionary<string, List<PlayerGameStateInfo>>();
		foreach (PlayerGameStateInfo item in list)
		{
			string key = TeamHelper.ExtractTeamColor(item.player.playerName);
			if (!dictionary.ContainsKey(key))
			{
				dictionary[key] = new List<PlayerGameStateInfo>();
			}
			dictionary[key].Add(item);
		}
		List<string> values = dictionary.Keys.ToList();
		GladioMoriKassenTeamBattlePlugin.LogInfo(string.Format("InformPlayerDeathPatch: AliveNonAIMembers={0}, UniqueTeams={1}", list.Count, string.Join(", ", values)));
		GladioMoriKassenTeamBattlePlugin.GameDecision gameDecision = ((!GladioMoriKassenTeamBattlePlugin.captainModeEnabled) ? GladioMoriKassenTeamBattlePlugin.GameDecisionEvaluator.EvaluateStandardGameResult(dictionary, list) : GladioMoriKassenTeamBattlePlugin.GameDecisionEvaluator.EvaluateCaptainGameResult(dictionary, list));
		GladioMoriKassenTeamBattlePlugin.LogInfo($"InformPlayerDeathPatch: Game decision result = {gameDecision.Result}, WinningTeam = {gameDecision.WinningTeam}");
		if (gameDecision.Result == GladioMoriKassenTeamBattlePlugin.GameResultType.Win && !__instance.gameIsOver)
		{
			GladioMoriKassenTeamBattlePlugin.LogInfo("InformPlayerDeathPatch: Game decision reached, starting GameOverTimer");
			MethodInfo methodInfo = AccessTools.Method(typeof(GameMaster), "GameOverTimer", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				IEnumerator enumerator2 = (IEnumerator)methodInfo.Invoke(__instance, null);
				((MonoBehaviour)__instance).StartCoroutine(enumerator2);
			}
			else
			{
				GladioMoriKassenTeamBattlePlugin.LogInstance.LogError((object)"InformPlayerDeathPatch: GameOverTimer method not found");
			}
		}
	}
}
[HarmonyPatch(typeof(GameMenu), "RestartGame")]
public static class RestartGamePatch
{
	private static void Prefix()
	{
		SpawnHelperStatic.ClearUsedStaticSpawnPositions();
		GladioMoriKassenTeamBattlePlugin.LogInfo("RestartGamePatch: usedStaticSpawnPositions cleared.");
	}
}
[HarmonyPatch(typeof(MultiplayerMenuManager), "Start")]
public static class MultiplayerMenuManagerStartPatch
{
	private static void Prefix()
	{
		GladioMoriKassenTeamBattlePlugin.originalPlayerNames.Clear();
	}
}
[HarmonyPatch(typeof(MultiplayerChat), "RpcHandleMessage")]
public static class RpcHandleMessagePatch
{
	private static void Prefix(ref string playerName)
	{
		playerName = Regex.Replace(playerName, "<.*?>", string.Empty);
	}
}