Decompiled source of Team Mode v0.3.2

Team_Mode.dll

Decompiled 6 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Localization;
using UnityEngine.Localization.Components;
using UnityEngine.Localization.Settings;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("GameAssembly")]
[assembly: IgnoresAccessChecksTo("SharedAssembly")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Team_Mode")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.3.2.0")]
[assembly: AssemblyInformationalVersion("0.3.2")]
[assembly: AssemblyProduct("Team_Mode")]
[assembly: AssemblyTitle("Team_Mode")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.3.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace Team_Mode
{
	[BepInPlugin("Team_Mode", "Team_Mode", "0.3.2")]
	public class Plugin : BaseUnityPlugin
	{
		public static bool EnabledSetting = false;

		public static bool FriendlyFireEnabled = false;

		public static bool RoundsMode = false;

		public static bool EarlyHoleEnd = false;

		public static int TeamCount = 2;

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

		public static readonly Color[] TeamColors = (Color[])(object)new Color[4]
		{
			new Color(0.9f, 0.2f, 0.2f),
			new Color(0.2f, 0.4f, 0.9f),
			new Color(0.2f, 0.8f, 0.2f),
			new Color(0.9f, 0.8f, 0.1f)
		};

		public const string Id = "Team_Mode";

		internal static ManualLogSource Log { get; private set; } = null;

		public static bool Enabled
		{
			get
			{
				if (EnabledSetting)
				{
					return !NativeTeamsMode;
				}
				return false;
			}
			set
			{
				EnabledSetting = value;
			}
		}

		public static bool NativeTeamsMode
		{
			get
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Invalid comparison between Unknown and I4
				try
				{
					return (int)MatchSetupMenu.CurrentGameMode == 1;
				}
				catch
				{
					return false;
				}
			}
		}

		public static string[] TeamNames => new string[4]
		{
			Lang.Get("Rouge", "Red"),
			Lang.Get("Bleu", "Blue"),
			Lang.Get("Vert", "Green"),
			Lang.Get("Jaune", "Yellow")
		};

		public static string Name => "Team_Mode";

		public static string Version => "0.3.2";

		public static int GetTeam(ulong guid)
		{
			if (!PlayerTeams.TryGetValue(guid, out var value))
			{
				return 0;
			}
			return value;
		}

		public static bool SameTeam(ulong a, ulong b)
		{
			if (Enabled && TeamCount > 1)
			{
				return GetTeam(a) == GetTeam(b);
			}
			return false;
		}

		private void Awake()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			TeamSerialization.Register();
			((Component)this).gameObject.AddComponent<TeamModeRuntime>();
			new Harmony("Team_Mode").PatchAll();
			PlayerId.AnyPlayerNameChanged += delegate
			{
				TeamModeUi.RebuildPlayerDropdowns();
			};
			Log.LogInfo((object)("Plugin " + Name + " loaded!"));
		}
	}
	public struct TeamAssignmentMessage : NetworkMessage
	{
		public ulong playerGuid;

		public int teamIndex;
	}
	public struct TeamStateSyncMessage : NetworkMessage
	{
		public ulong[] guids;

		public int[] teams;

		public int teamCount;

		public bool enabled;

		public bool friendlyFireEnabled;

		public bool roundsMode;
	}
	public struct TeamScoreSyncMessage : NetworkMessage
	{
		public ulong[] guids;

		public int[] totals;
	}
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	public struct TeamStateRequestMessage : NetworkMessage
	{
	}
	public static class TeamSerialization
	{
		private const int MaxEntries = 1024;

		public static void Register()
		{
			Writer<TeamAssignmentMessage>.write = delegate(NetworkWriter w, TeamAssignmentMessage m)
			{
				NetworkWriterExtensions.WriteULong(w, m.playerGuid);
				NetworkWriterExtensions.WriteInt(w, m.teamIndex);
			};
			Reader<TeamAssignmentMessage>.read = (NetworkReader r) => new TeamAssignmentMessage
			{
				playerGuid = NetworkReaderExtensions.ReadULong(r),
				teamIndex = NetworkReaderExtensions.ReadInt(r)
			};
			Writer<TeamStateSyncMessage>.write = delegate(NetworkWriter w, TeamStateSyncMessage m)
			{
				WriteEntries(w, m.guids, m.teams);
				NetworkWriterExtensions.WriteInt(w, m.teamCount);
				NetworkWriterExtensions.WriteBool(w, m.enabled);
				NetworkWriterExtensions.WriteBool(w, m.friendlyFireEnabled);
				NetworkWriterExtensions.WriteBool(w, m.roundsMode);
			};
			Reader<TeamStateSyncMessage>.read = delegate(NetworkReader r)
			{
				var (guids, teams) = ReadEntries(r);
				return new TeamStateSyncMessage
				{
					guids = guids,
					teams = teams,
					teamCount = NetworkReaderExtensions.ReadInt(r),
					enabled = NetworkReaderExtensions.ReadBool(r),
					friendlyFireEnabled = NetworkReaderExtensions.ReadBool(r),
					roundsMode = (r.Remaining > 0 && NetworkReaderExtensions.ReadBool(r))
				};
			};
			Writer<TeamScoreSyncMessage>.write = delegate(NetworkWriter w, TeamScoreSyncMessage m)
			{
				WriteEntries(w, m.guids, m.totals);
			};
			Reader<TeamScoreSyncMessage>.read = delegate(NetworkReader r)
			{
				var (guids, totals) = ReadEntries(r);
				return new TeamScoreSyncMessage
				{
					guids = guids,
					totals = totals
				};
			};
			Writer<TeamStateRequestMessage>.write = delegate
			{
			};
			Reader<TeamStateRequestMessage>.read = (NetworkReader r) => default(TeamStateRequestMessage);
		}

		private static void WriteEntries(NetworkWriter w, ulong[]? keys, int[]? values)
		{
			int num = Math.Min((keys != null) ? keys.Length : 0, (values != null) ? values.Length : 0);
			NetworkWriterExtensions.WriteInt(w, num);
			for (int i = 0; i < num; i++)
			{
				NetworkWriterExtensions.WriteULong(w, keys[i]);
				NetworkWriterExtensions.WriteInt(w, values[i]);
			}
		}

		private static (ulong[] keys, int[] values) ReadEntries(NetworkReader r)
		{
			int num = NetworkReaderExtensions.ReadInt(r);
			if (num < 0 || num > 1024)
			{
				throw new InvalidOperationException($"Team_Mode: invalid entry count {num}");
			}
			ulong[] array = new ulong[num];
			int[] array2 = new int[num];
			for (int i = 0; i < num; i++)
			{
				array[i] = NetworkReaderExtensions.ReadULong(r);
				array2[i] = NetworkReaderExtensions.ReadInt(r);
			}
			return (keys: array, values: array2);
		}
	}
	public static class TeamSyncManager
	{
		private static bool _serverEventHooked;

		private static bool _isRemoteClient;

		public static void OnServerStarted()
		{
			NetworkServer.RegisterHandler<TeamStateRequestMessage>((Action<NetworkConnectionToClient, TeamStateRequestMessage>)OnServerReceiveStateRequest, true);
			if (!_serverEventHooked)
			{
				_serverEventHooked = true;
				GameManager.RemotePlayerRegistered += OnRemotePlayerRegistered;
			}
			Plugin.Log.LogInfo((object)"[Sync/Host] Server started — handlers registered");
		}

		public static void OnClientStarted()
		{
			_isRemoteClient = !NetworkServer.active;
			NetworkClient.RegisterHandler<TeamAssignmentMessage>((Action<TeamAssignmentMessage>)OnClientReceiveAssignment, true);
			NetworkClient.RegisterHandler<TeamStateSyncMessage>((Action<TeamStateSyncMessage>)OnClientReceiveStateSync, true);
			NetworkClient.RegisterHandler<TeamScoreSyncMessage>((Action<TeamScoreSyncMessage>)OnClientReceiveScoreSync, true);
			Plugin.Log.LogInfo((object)$"[Sync] Client started (remote={_isRemoteClient}) — handlers registered");
		}

		public static void OnClientStopped()
		{
			if (_isRemoteClient)
			{
				_isRemoteClient = false;
				Plugin.Enabled = false;
				Plugin.FriendlyFireEnabled = false;
				Plugin.TeamCount = 2;
				Plugin.RoundsMode = false;
				Plugin.PlayerTeams.Clear();
				ScoreboardTeamData.TeamRounds.Clear();
				RoundsTracker.NewHole();
				Plugin.Log.LogInfo((object)"[Sync/Client] Disconnected from host — team state reset");
			}
		}

		public static void RequestState()
		{
			if (!NetworkServer.active && NetworkClient.isConnected)
			{
				NetworkClient.Send<TeamStateRequestMessage>(default(TeamStateRequestMessage), 0);
				Plugin.Log.LogInfo((object)"[Sync/Client] Requested full state from host");
			}
		}

		private static void OnRemotePlayerRegistered(PlayerInfo playerInfo)
		{
			if (!NetworkServer.active)
			{
				return;
			}
			try
			{
				NetworkConnectionToClient connectionToClient = ((NetworkBehaviour)playerInfo).connectionToClient;
				if (connectionToClient == null)
				{
					Plugin.Log.LogWarning((object)"[Sync/Host] New player registered but connectionToClient is null — cannot send state");
					return;
				}
				ManualLogSource log = Plugin.Log;
				PlayerId playerId = playerInfo.PlayerId;
				log.LogInfo((object)$"[Sync/Host] New remote player registered: guid={((playerId != null) ? new ulong?(playerId.Guid) : ((ulong?)null))} — sending full state...");
				SendFullStateTo(connectionToClient);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[Sync] OnRemotePlayerRegistered: " + ex.Message));
			}
		}

		private static void OnServerReceiveStateRequest(NetworkConnectionToClient conn, TeamStateRequestMessage msg)
		{
			Plugin.Log.LogInfo((object)$"[Sync/Host] State requested by connId={conn.connectionId}");
			SendFullStateTo(conn);
		}

		public static void SendFullStateTo(NetworkConnectionToClient conn)
		{
			if (!NetworkServer.active)
			{
				return;
			}
			try
			{
				ulong[] array = new ulong[Plugin.PlayerTeams.Count];
				int[] array2 = new int[Plugin.PlayerTeams.Count];
				int num = 0;
				foreach (KeyValuePair<ulong, int> playerTeam in Plugin.PlayerTeams)
				{
					array[num] = playerTeam.Key;
					array2[num] = playerTeam.Value;
					num++;
				}
				TeamStateSyncMessage teamStateSyncMessage = new TeamStateSyncMessage
				{
					guids = array,
					teams = array2,
					teamCount = Plugin.TeamCount,
					enabled = Plugin.EnabledSetting,
					friendlyFireEnabled = Plugin.FriendlyFireEnabled,
					roundsMode = Plugin.RoundsMode
				};
				((NetworkConnection)conn).Send<TeamStateSyncMessage>(teamStateSyncMessage, 0);
				((NetworkConnection)conn).Send<TeamScoreSyncMessage>(BuildScoreMessage(), 0);
				Plugin.Log.LogInfo((object)$"[Sync/Host] Full state sent → connId={conn.connectionId} | {array.Length} assignments | TeamCount={Plugin.TeamCount} | Enabled={Plugin.EnabledSetting} | FF={Plugin.FriendlyFireEnabled} | Rounds={Plugin.RoundsMode}");
				for (int i = 0; i < array.Length; i++)
				{
					Plugin.Log.LogInfo((object)$"[Sync/Host]   guid={array[i]} → team={Plugin.TeamNames[array2[i]]}");
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[Sync] SendFullStateTo: " + ex.Message));
			}
		}

		private static TeamScoreSyncMessage BuildScoreMessage()
		{
			Dictionary<int, int> teamRounds = ScoreboardTeamData.TeamRounds;
			ulong[] array = new ulong[teamRounds.Count];
			int[] array2 = new int[teamRounds.Count];
			int num = 0;
			foreach (KeyValuePair<int, int> item in teamRounds)
			{
				array[num] = (ulong)item.Key;
				array2[num] = item.Value;
				num++;
			}
			return new TeamScoreSyncMessage
			{
				guids = array,
				totals = array2
			};
		}

		public static void BroadcastAssignment(ulong guid, int team)
		{
			if (NetworkServer.active)
			{
				TeamAssignmentMessage teamAssignmentMessage = new TeamAssignmentMessage
				{
					playerGuid = guid,
					teamIndex = team
				};
				NetworkServer.SendToAll<TeamAssignmentMessage>(teamAssignmentMessage, 0, false);
				Plugin.Log.LogInfo((object)$"[Sync/Host] Broadcast assignment → guid={guid} team={Plugin.TeamNames[team]}");
			}
		}

		public static void BroadcastScores()
		{
			if (NetworkServer.active)
			{
				NetworkServer.SendToAll<TeamScoreSyncMessage>(BuildScoreMessage(), 0, false);
			}
		}

		public static void BroadcastFullState()
		{
			if (!NetworkServer.active)
			{
				return;
			}
			foreach (NetworkConnectionToClient value in NetworkServer.connections.Values)
			{
				if ((object)value != NetworkServer.localConnection)
				{
					SendFullStateTo(value);
				}
			}
			Plugin.Log.LogInfo((object)"[Sync/Host] Full state broadcast to all clients");
		}

		private static void OnClientReceiveAssignment(TeamAssignmentMessage msg)
		{
			if (!NetworkServer.active)
			{
				int num = Mathf.Clamp(msg.teamIndex, 0, Plugin.TeamColors.Length - 1);
				Plugin.PlayerTeams[msg.playerGuid] = num;
				Plugin.Log.LogInfo((object)$"[Sync/Client] ✅ Received assignment → guid={msg.playerGuid} team={Plugin.TeamNames[num]}");
				RefreshVisualsForGuid(msg.playerGuid);
				RefreshScoreboards();
			}
		}

		private static void OnClientReceiveStateSync(TeamStateSyncMessage msg)
		{
			if (NetworkServer.active)
			{
				return;
			}
			ManualLogSource log = Plugin.Log;
			object[] array = new object[4];
			ulong[] guids = msg.guids;
			array[0] = ((guids != null) ? guids.Length : 0);
			array[1] = msg.teamCount;
			array[2] = msg.enabled;
			array[3] = msg.friendlyFireEnabled;
			log.LogInfo((object)string.Format("[Sync/Client] ✅ Received full state from host — {0} assignments | TeamCount={1} | Enabled={2} | FF={3}", array));
			Plugin.PlayerTeams.Clear();
			if (msg.guids != null && msg.teams != null)
			{
				for (int i = 0; i < msg.guids.Length && i < msg.teams.Length; i++)
				{
					int num = Mathf.Clamp(msg.teams[i], 0, Plugin.TeamColors.Length - 1);
					Plugin.PlayerTeams[msg.guids[i]] = num;
					Plugin.Log.LogInfo((object)$"[Sync/Client]   guid={msg.guids[i]} → team={Plugin.TeamNames[num]}");
				}
			}
			Plugin.TeamCount = Mathf.Clamp(msg.teamCount, 1, Plugin.TeamColors.Length);
			Plugin.Enabled = msg.enabled;
			Plugin.FriendlyFireEnabled = msg.friendlyFireEnabled;
			Plugin.RoundsMode = msg.roundsMode;
			Plugin.Log.LogInfo((object)"[Sync/Client] State applied — refreshing visuals for all players...");
			RefreshAllVisuals();
			RefreshScoreboards();
			TeamModeUi.RebuildPlayerDropdowns();
			EnhancedMode.Refresh();
		}

		private static void OnClientReceiveScoreSync(TeamScoreSyncMessage msg)
		{
			if (NetworkServer.active)
			{
				return;
			}
			ScoreboardTeamData.TeamRounds.Clear();
			if (msg.guids != null && msg.totals != null)
			{
				for (int i = 0; i < msg.guids.Length && i < msg.totals.Length; i++)
				{
					if (msg.guids[i] < (ulong)Plugin.TeamColors.Length)
					{
						ScoreboardTeamData.TeamRounds[(int)msg.guids[i]] = msg.totals[i];
					}
				}
			}
			Plugin.Log.LogInfo((object)$"[Sync/Client] ✅ Received team rounds from host — {ScoreboardTeamData.TeamRounds.Count} entries");
			RefreshScoreboards();
		}

		private static void RefreshVisualsForGuid(ulong guid)
		{
			try
			{
				PlayerInfo val = null;
				GameManager.TryFindPlayerByGuid(guid, ref val);
				if (!((Object)(object)val == (Object)null))
				{
					PlayerCosmeticsSwitcher componentInChildren = ((Component)val).GetComponentInChildren<PlayerCosmeticsSwitcher>();
					if (!((Object)(object)componentInChildren == (Object)null))
					{
						componentInChildren.SetSkinColor(componentInChildren.CurrentSkinColorIndex);
						Plugin.Log.LogInfo((object)$"[Sync/Client] Refreshed visuals for guid={guid}");
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[Sync] RefreshVisualsForGuid: " + ex.Message));
			}
		}

		public static void RefreshAllVisuals()
		{
			try
			{
				PlayerCosmeticsSwitcher[] array = Object.FindObjectsByType<PlayerCosmeticsSwitcher>((FindObjectsSortMode)0);
				PlayerCosmeticsSwitcher[] array2 = array;
				foreach (PlayerCosmeticsSwitcher val in array2)
				{
					val.SetSkinColor(val.CurrentSkinColorIndex);
				}
				Plugin.Log.LogInfo((object)$"[Sync] Refreshed visuals for {array.Length} player(s)");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[Sync] RefreshAllVisuals: " + ex.Message));
			}
		}

		private static void RefreshScoreboards()
		{
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(Scoreboard), "MarkDirty", (Type[])null, (Type[])null);
				if (!(methodInfo == null))
				{
					Scoreboard[] array = Object.FindObjectsByType<Scoreboard>((FindObjectsSortMode)0);
					foreach (Scoreboard obj in array)
					{
						methodInfo.Invoke(obj, null);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[Sync] RefreshScoreboards: " + ex.Message));
			}
		}
	}
	public static class HittableHelper
	{
		private static readonly BindingFlags Pub = BindingFlags.Instance | BindingFlags.Public;

		public static ulong GetTargetGuid(object hittable)
		{
			try
			{
				object obj = hittable.GetType().GetProperty("AsEntity", Pub)?.GetValue(hittable);
				if (obj == null)
				{
					return 0uL;
				}
				if (!(bool)(obj.GetType().GetProperty("IsPlayer", Pub)?.GetValue(obj) ?? ((object)false)))
				{
					return 0uL;
				}
				object obj2 = obj.GetType().GetProperty("PlayerInfo", Pub)?.GetValue(obj);
				if (obj2 == null)
				{
					return 0uL;
				}
				return GetGuidFromPlayerInfo(obj2);
			}
			catch
			{
				return 0uL;
			}
		}

		public static ulong GetGuidFromPlayerInfo(object playerInfo)
		{
			try
			{
				object obj = playerInfo.GetType().GetProperty("PlayerId", Pub)?.GetValue(playerInfo);
				if (obj == null)
				{
					return 0uL;
				}
				return (ulong)(obj.GetType().GetProperty("Guid", Pub)?.GetValue(obj) ?? ((object)0uL));
			}
			catch
			{
				return 0uL;
			}
		}

		public static ulong GetGuidViaPlayerInfoProp(object obj)
		{
			try
			{
				object obj2 = obj.GetType().GetProperty("PlayerInfo", Pub)?.GetValue(obj);
				if (obj2 == null)
				{
					return 0uL;
				}
				return GetGuidFromPlayerInfo(obj2);
			}
			catch
			{
				return 0uL;
			}
		}

		public static bool CheckAndBlockFriendlyFire(ulong targetGuid, ulong shooterGuid, string source)
		{
			if (targetGuid == 0L || shooterGuid == 0L)
			{
				return false;
			}
			if (targetGuid == shooterGuid)
			{
				return false;
			}
			int team = Plugin.GetTeam(targetGuid);
			int team2 = Plugin.GetTeam(shooterGuid);
			bool flag = Plugin.SameTeam(shooterGuid, targetGuid);
			string text = (flag ? "TEAMMATE" : "ENEMY");
			Plugin.Log.LogInfo((object)$"[FF/{source}] Shooter={shooterGuid}(Team {team2}) → Target={targetGuid}(Team {team}) | Relation={text} | FriendlyFire={Plugin.FriendlyFireEnabled}");
			if (!Plugin.FriendlyFireEnabled && flag)
			{
				Plugin.Log.LogInfo((object)("[FF/" + source + "] \ud83d\udee1\ufe0f BLOCKED — friendly fire is OFF and target is teammate"));
				return true;
			}
			if (flag)
			{
				Plugin.Log.LogInfo((object)("[FF/" + source + "] ✅ ALLOWED — friendly fire is ON"));
			}
			else
			{
				Plugin.Log.LogInfo((object)("[FF/" + source + "] ✅ ALLOWED — target is enemy"));
			}
			return false;
		}
	}
	[HarmonyPatch]
	public class HittableHitWithItemPatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("Hittable"), "HitWithItem", (Type[])null, (Type[])null);
		}

		[HarmonyPrefix]
		private static bool Prefix(object __instance, object itemUser)
		{
			if (!Plugin.Enabled)
			{
				return true;
			}
			try
			{
				ulong targetGuid = HittableHelper.GetTargetGuid(__instance);
				if (targetGuid == 0L)
				{
					return true;
				}
				if (itemUser == null)
				{
					return true;
				}
				ulong guidViaPlayerInfoProp = HittableHelper.GetGuidViaPlayerInfoProp(itemUser);
				return !HittableHelper.CheckAndBlockFriendlyFire(targetGuid, guidViaPlayerInfoProp, "Item");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("HitWithItemPatch: " + ex.Message));
			}
			return true;
		}
	}
	[HarmonyPatch]
	public class HittableGolfSwingPatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("Hittable"), "HitWithGolfSwing", (Type[])null, (Type[])null);
		}

		[HarmonyPrefix]
		private static bool Prefix(object __instance, object hitter)
		{
			if (!Plugin.Enabled)
			{
				return true;
			}
			try
			{
				ulong targetGuid = HittableHelper.GetTargetGuid(__instance);
				if (targetGuid == 0L)
				{
					return true;
				}
				if (hitter == null)
				{
					return true;
				}
				ulong guidViaPlayerInfoProp = HittableHelper.GetGuidViaPlayerInfoProp(hitter);
				return !HittableHelper.CheckAndBlockFriendlyFire(targetGuid, guidViaPlayerInfoProp, "GolfSwing");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("HittableGolfSwingPatch: " + ex.Message));
			}
			return true;
		}
	}
	[HarmonyPatch]
	public class HittableSwingProjectilePatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("Hittable"), "HitWithSwingProjectile", (Type[])null, (Type[])null);
		}

		[HarmonyPrefix]
		private static bool Prefix(object __instance, object responsiblePlayer)
		{
			if (!Plugin.Enabled)
			{
				return true;
			}
			try
			{
				ulong targetGuid = HittableHelper.GetTargetGuid(__instance);
				if (targetGuid == 0L)
				{
					return true;
				}
				if (responsiblePlayer == null)
				{
					return true;
				}
				ulong guidViaPlayerInfoProp = HittableHelper.GetGuidViaPlayerInfoProp(responsiblePlayer);
				return !HittableHelper.CheckAndBlockFriendlyFire(targetGuid, guidViaPlayerInfoProp, "SwingProjectile");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("HittableSwingProjectilePatch: " + ex.Message));
			}
			return true;
		}
	}
	[HarmonyPatch]
	public class HittableDivePatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("Hittable"), "HitWithDive", (Type[])null, (Type[])null);
		}

		[HarmonyPrefix]
		private static bool Prefix(object __instance, object hitter)
		{
			if (!Plugin.Enabled)
			{
				return true;
			}
			try
			{
				ulong targetGuid = HittableHelper.GetTargetGuid(__instance);
				if (targetGuid == 0L)
				{
					return true;
				}
				if (hitter == null)
				{
					return true;
				}
				ulong guidViaPlayerInfoProp = HittableHelper.GetGuidViaPlayerInfoProp(hitter);
				return !HittableHelper.CheckAndBlockFriendlyFire(targetGuid, guidViaPlayerInfoProp, "Dive");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("HittableDivePatch: " + ex.Message));
			}
			return true;
		}
	}
	[HarmonyPatch]
	public class HittableRocketBackBlastPatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("Hittable"), "HitWithRocketLauncherBackBlast", (Type[])null, (Type[])null);
		}

		[HarmonyPrefix]
		private static bool Prefix(object __instance, object rocketLauncherUser)
		{
			if (!Plugin.Enabled)
			{
				return true;
			}
			try
			{
				ulong targetGuid = HittableHelper.GetTargetGuid(__instance);
				if (targetGuid == 0L)
				{
					return true;
				}
				if (rocketLauncherUser == null)
				{
					return true;
				}
				ulong guidViaPlayerInfoProp = HittableHelper.GetGuidViaPlayerInfoProp(rocketLauncherUser);
				return !HittableHelper.CheckAndBlockFriendlyFire(targetGuid, guidViaPlayerInfoProp, "RocketBackBlast");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("HittableRocketBackBlastPatch: " + ex.Message));
			}
			return true;
		}
	}
	[HarmonyPatch]
	public class TeamScorePatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("CourseManager"), "InformPlayerScoredInternal", (Type[])null, (Type[])null);
		}

		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(object playerAsGolfer)
		{
			if (!Plugin.Enabled || !Plugin.RoundsMode || Plugin.TeamCount <= 1)
			{
				return;
			}
			try
			{
				if (NetworkServer.active && !SingletonBehaviour<DrivingRangeManager>.HasInstance)
				{
					ulong guidViaPlayerInfoProp = HittableHelper.GetGuidViaPlayerInfoProp(playerAsGolfer);
					if (guidViaPlayerInfoProp != 0L)
					{
						RoundsTracker.CountFinisher(Plugin.GetTeam(guidViaPlayerInfoProp));
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("TeamScorePatch: " + ex.Message));
			}
		}
	}
	[HarmonyPatch]
	public class RoundsHoleEndPatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("CourseManager"), "OnMatchStateChanged", (Type[])null, (Type[])null);
		}

		[HarmonyPostfix]
		private static void Postfix(MatchState currentState)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			if (!Plugin.Enabled || !Plugin.RoundsMode || Plugin.TeamCount <= 1)
			{
				return;
			}
			try
			{
				if (NetworkServer.active && !SingletonBehaviour<DrivingRangeManager>.HasInstance && (int)currentState == 6)
				{
					RoundsTracker.AwardRound();
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("RoundsHoleEndPatch: " + ex.Message));
			}
		}
	}
	public class PracticeScoreSnapshot
	{
		public int Index;

		public ulong Guid;

		public int CourseScore;

		public int MatchScore;
	}
	[HarmonyPatch]
	public class PracticeNoScorePatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("CourseManager"), "InformPlayerScoredInternal", (Type[])null, (Type[])null);
		}

		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(object playerAsGolfer, out PracticeScoreSnapshot? __state)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			__state = null;
			if (!Plugin.Enabled || !NetworkServer.active || !TeamStandings.InPractice)
			{
				return true;
			}
			try
			{
				ulong guidViaPlayerInfoProp = HittableHelper.GetGuidViaPlayerInfoProp(playerAsGolfer);
				SyncList<PlayerState> playerStates = CourseManager.PlayerStates;
				if (playerStates != null)
				{
					for (int i = 0; i < playerStates.Count; i++)
					{
						if (playerStates[i].playerGuid == guidViaPlayerInfoProp)
						{
							__state = new PracticeScoreSnapshot
							{
								Index = i,
								Guid = guidViaPlayerInfoProp,
								CourseScore = playerStates[i].courseScore,
								MatchScore = playerStates[i].matchScore
							};
							break;
						}
					}
				}
				Plugin.Log.LogInfo((object)$"\ud83c\udfaf Practice goal not counted (Team Mode active, player {guidViaPlayerInfoProp})");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("PracticeNoScorePatch: " + ex.Message));
			}
			return false;
		}

		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(PracticeScoreSnapshot? __state)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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)
			if (__state == null)
			{
				return;
			}
			try
			{
				SyncList<PlayerState> playerStates = CourseManager.PlayerStates;
				if (playerStates != null && __state.Index < playerStates.Count)
				{
					PlayerState val = playerStates[__state.Index];
					if (val.playerGuid == __state.Guid && (val.courseScore != __state.CourseScore || val.matchScore != __state.MatchScore))
					{
						val.courseScore = __state.CourseScore;
						val.matchScore = __state.MatchScore;
						playerStates[__state.Index] = val;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("PracticeNoScorePatch.Postfix: " + ex.Message));
			}
		}
	}
	[HarmonyPatch]
	public class NameTagColorPatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("NameTagUi"), "LateUpdate", (Type[])null, (Type[])null) ?? AccessTools.Method(AccessTools.TypeByName("NameTagUi"), "Update", (Type[])null, (Type[])null);
		}

		[HarmonyPostfix]
		private static void Postfix(object __instance)
		{
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Enabled)
			{
				return;
			}
			try
			{
				BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
				object obj = __instance.GetType().GetField("playerInfo", bindingAttr)?.GetValue(__instance);
				if (obj == null)
				{
					return;
				}
				object obj2 = obj.GetType().GetProperty("PlayerId", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj);
				if (obj2 != null)
				{
					ulong guid = (ulong)(obj2.GetType().GetProperty("Guid", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj2) ?? ((object)0uL));
					object? obj3 = __instance.GetType().GetField("tag", bindingAttr)?.GetValue(__instance);
					TMP_Text val = (TMP_Text)((obj3 is TMP_Text) ? obj3 : null);
					if ((Object)(object)val != (Object)null)
					{
						((Graphic)val).color = Plugin.TeamColors[Plugin.GetTeam(guid)];
					}
				}
			}
			catch
			{
			}
		}
	}
	[HarmonyPatch]
	public class PlayerSkinColorPatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("PlayerCosmeticsSwitcher"), "ApplyCurrentSkinColorToMaterial", (Type[])null, (Type[])null);
		}

		[HarmonyPostfix]
		private static void Postfix(object __instance, Material material)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Enabled)
			{
				return;
			}
			try
			{
				BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
				object obj = __instance.GetType().GetField("playerInfo", bindingAttr)?.GetValue(__instance);
				if (obj != null)
				{
					ulong guidFromPlayerInfo = HittableHelper.GetGuidFromPlayerInfo(obj);
					material.SetColor("_Color", Plugin.TeamColors[Plugin.GetTeam(guidFromPlayerInfo)]);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("SkinColorPatch: " + ex.Message));
			}
		}
	}
	[HarmonyPatch]
	public class RegisterPlayerPatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("GameManager"), "RegisterPlayer", (Type[])null, (Type[])null);
		}

		[HarmonyPostfix]
		private static void Postfix(PlayerInfo playerInfo)
		{
			TeamModeUi.RebuildPlayerDropdowns();
			if ((Object)(object)playerInfo != (Object)null && ((NetworkBehaviour)playerInfo).isLocalPlayer)
			{
				TeamSyncManager.RequestState();
			}
		}
	}
	[HarmonyPatch]
	public class NetworkStartServerPatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("BNetworkManager"), "OnStartServer", (Type[])null, (Type[])null);
		}

		[HarmonyPostfix]
		private static void Postfix()
		{
			TeamSyncManager.OnServerStarted();
		}
	}
	[HarmonyPatch]
	public class NetworkStartClientPatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("BNetworkManager"), "OnStartClient", (Type[])null, (Type[])null);
		}

		[HarmonyPostfix]
		private static void Postfix()
		{
			TeamSyncManager.OnClientStarted();
		}
	}
	[HarmonyPatch]
	public class NetworkStopClientPatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("BNetworkManager"), "OnStopClient", (Type[])null, (Type[])null);
		}

		[HarmonyPostfix]
		private static void Postfix()
		{
			TeamSyncManager.OnClientStopped();
		}
	}
	public static class ScoreboardTeamData
	{
		public static Dictionary<GameObject, ulong> EntryGuids = new Dictionary<GameObject, ulong>();

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

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

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

		public static bool HoleAwarded;
	}
	public static class RoundsTracker
	{
		public static int Cap()
		{
			Dictionary<int, int> dictionary = new Dictionary<int, int>();
			foreach (var connectedPlayer in TeamModeUi.GetConnectedPlayers())
			{
				ulong item = connectedPlayer.guid;
				int team = Plugin.GetTeam(item);
				dictionary[team] = ((!dictionary.TryGetValue(team, out var value)) ? 1 : (value + 1));
			}
			int num = 0;
			foreach (int value2 in dictionary.Values)
			{
				if (num == 0 || value2 < num)
				{
					num = value2;
				}
			}
			if (num <= 1)
			{
				return 1;
			}
			int num2 = (num + 1) / 2;
			if (num % 2 == 0)
			{
				num2++;
			}
			return num2;
		}

		private static int Counted(int team, int cap)
		{
			int value;
			return Math.Min(ScoreboardTeamData.HoleFinishers.TryGetValue(team, out value) ? value : 0, cap);
		}

		public static void NewHole()
		{
			ScoreboardTeamData.HoleFinishers.Clear();
			ScoreboardTeamData.HoleAwarded = false;
		}

		public static void CountFinisher(int team)
		{
			Dictionary<int, int> holeFinishers = ScoreboardTeamData.HoleFinishers;
			holeFinishers[team] = (holeFinishers.TryGetValue(team, out var value) ? value : 0) + 1;
			int num = Cap();
			Plugin.Log.LogInfo((object)$"\ud83c\udfc1 Team {Plugin.TeamNames[team]}: {holeFinishers[team]} finisher(s) this hole (cap {num})");
			if (Plugin.EarlyHoleEnd && Counted(team, num) >= num)
			{
				EndHoleNow();
			}
		}

		private static void EndHoleNow()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			if ((int)CourseManager.MatchState == 4)
			{
				CourseManager instance = SingletonNetworkBehaviour<CourseManager>.Instance;
				FieldInfo fieldInfo = AccessTools.Field(typeof(CourseManager), "countdownRemainingTime");
				if (!((Object)(object)instance == (Object)null) && !(fieldInfo == null))
				{
					fieldInfo.SetValue(instance, 0f);
					Plugin.Log.LogInfo((object)"⏱\ufe0f Majority reached → the hole ends now");
				}
			}
		}

		public static void AwardRound()
		{
			if (ScoreboardTeamData.HoleAwarded)
			{
				return;
			}
			ScoreboardTeamData.HoleAwarded = true;
			int cap = Cap();
			int num = 0;
			foreach (int key in ScoreboardTeamData.HoleFinishers.Keys)
			{
				num = Math.Max(num, Counted(key, cap));
			}
			if (num <= 0)
			{
				Plugin.Log.LogInfo((object)"\ud83c\udfc1 Hole ended with no finisher → no round awarded");
				return;
			}
			Dictionary<int, int> teamRounds = ScoreboardTeamData.TeamRounds;
			foreach (int item in new List<int>(ScoreboardTeamData.HoleFinishers.Keys))
			{
				if (Counted(item, cap) == num)
				{
					teamRounds[item] = (teamRounds.TryGetValue(item, out var value) ? value : 0) + 1;
					Plugin.Log.LogInfo((object)$"\ud83c\udfc6 Round won by team {Plugin.TeamNames[item]} → {teamRounds[item]} round(s)");
				}
			}
			TeamSyncManager.BroadcastScores();
		}
	}
	public class TeamStanding
	{
		public int Team;

		public int Rank;

		public int Points;

		public int Rounds;

		public readonly List<(ulong guid, string name, int score)> Players = new List<(ulong, string, int)>();
	}
	public static class TeamStandings
	{
		public static bool InPractice => SingletonBehaviour<DrivingRangeManager>.HasInstance;

		public static int RoundsOf(int team)
		{
			if (InPractice || !ScoreboardTeamData.TeamRounds.TryGetValue(team, out var value))
			{
				return 0;
			}
			return value;
		}

		public static List<int> Sort(Dictionary<int, int> teamPoints, out Dictionary<int, int> teamRank)
		{
			List<int> list = new List<int>(teamPoints.Keys);
			list.Sort(delegate(int a, int b)
			{
				if (Plugin.RoundsMode)
				{
					int num3 = RoundsOf(b).CompareTo(RoundsOf(a));
					if (num3 != 0)
					{
						return num3;
					}
				}
				int num4 = teamPoints[b].CompareTo(teamPoints[a]);
				return (num4 == 0) ? a.CompareTo(b) : num4;
			});
			Dictionary<int, int> dictionary = new Dictionary<int, int>();
			for (int num = 0; num < list.Count; num++)
			{
				int num2 = list[num];
				dictionary[num2] = ((num > 0 && SameStanding(list[num - 1], num2)) ? dictionary[list[num - 1]] : (num + 1));
			}
			teamRank = dictionary;
			return list;
			bool SameStanding(int x, int y)
			{
				if (teamPoints[x] == teamPoints[y])
				{
					if (Plugin.RoundsMode)
					{
						return RoundsOf(x) == RoundsOf(y);
					}
					return true;
				}
				return false;
			}
		}

		public static List<TeamStanding> Compute()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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)
			Dictionary<int, TeamStanding> dictionary = new Dictionary<int, TeamStanding>();
			SyncList<PlayerState> playerStates = CourseManager.PlayerStates;
			if (playerStates != null)
			{
				Enumerator<PlayerState> enumerator = playerStates.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						PlayerState current = enumerator.Current;
						if (current.isConnected && !current.isInSpectatorMode)
						{
							int team = Plugin.GetTeam(current.playerGuid);
							if (!dictionary.TryGetValue(team, out var value))
							{
								TeamStanding obj = new TeamStanding
								{
									Team = team
								};
								value = obj;
								dictionary[team] = obj;
							}
							value.Points += current.courseScore;
							value.Players.Add((current.playerGuid, CourseManager.GetPlayerName(current.playerGuid), current.courseScore));
						}
					}
				}
				finally
				{
					((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
				}
			}
			Dictionary<int, int> dictionary2 = new Dictionary<int, int>();
			foreach (KeyValuePair<int, TeamStanding> item in dictionary)
			{
				dictionary2[item.Key] = item.Value.Points;
			}
			List<TeamStanding> list = new List<TeamStanding>();
			Dictionary<int, int> teamRank;
			foreach (int item2 in Sort(dictionary2, out teamRank))
			{
				TeamStanding teamStanding = dictionary[item2];
				teamStanding.Rank = teamRank[item2];
				teamStanding.Rounds = RoundsOf(item2);
				teamStanding.Players.Sort(((ulong guid, string name, int score) a, (ulong guid, string name, int score) b) => b.score.CompareTo(a.score));
				list.Add(teamStanding);
			}
			return list;
		}
	}
	public static class TeamPodium
	{
		private static string _lastSummary = "";

		public static bool Visible { get; private set; }

		public static List<TeamStanding> Standings { get; private set; } = new List<TeamStanding>();

		public static void Refresh()
		{
			NextMatchCountdown val = null;
			try
			{
				val = ShouldShow();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("TeamPodium.ShouldShow: " + ex.Message));
			}
			if ((Object)(object)val == (Object)null)
			{
				if (Visible)
				{
					Visible = false;
					Standings = new List<TeamStanding>();
					_lastSummary = "";
					TeamPodiumView.Destroy();
					Plugin.Log.LogInfo((object)"\ud83c\udfc5 PODIUM hidden");
				}
				return;
			}
			try
			{
				int networkdisplayedTime = val.NetworkdisplayedTime;
				if (!Visible || networkdisplayedTime < 0 || networkdisplayedTime > 1)
				{
					Standings = TeamStandings.Compute();
					string text = Describe(Standings);
					if (text != _lastSummary)
					{
						_lastSummary = text;
						Plugin.Log.LogInfo((object)("\ud83c\udfc5 PODIUM: " + text));
						TeamPodiumView.Build(Standings);
					}
				}
				Visible = true;
				TeamPodiumView.Sync();
			}
			catch (Exception ex2)
			{
				Plugin.Log.LogError((object)("TeamPodium.Refresh: " + ex2.Message));
			}
		}

		private static NextMatchCountdown? ShouldShow()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Invalid comparison between Unknown and I4
			if (!Plugin.Enabled || Plugin.TeamCount <= 1)
			{
				return null;
			}
			if (TeamStandings.InPractice)
			{
				return null;
			}
			if (!SingletonNetworkBehaviour<NextMatchCountdown>.HasInstance)
			{
				return null;
			}
			NextMatchCountdown instance = SingletonNetworkBehaviour<NextMatchCountdown>.Instance;
			if (!instance.NetworkisVisible || !instance.NetworkisCourseFinished)
			{
				return null;
			}
			if ((int)CourseManager.MatchState != 6)
			{
				return null;
			}
			return instance;
		}

		private static string Describe(List<TeamStanding> standings)
		{
			List<string> list = new List<string>();
			foreach (TeamStanding standing in standings)
			{
				List<string> list2 = new List<string>();
				foreach (var player in standing.Players)
				{
					string item = player.name;
					int item2 = player.score;
					list2.Add($"{item}:{item2}");
				}
				list.Add(string.Format("#{0} {1} {2}pts {3}rounds [{4}]", standing.Rank, Plugin.TeamNames[standing.Team], standing.Points, standing.Rounds, string.Join(",", list2)));
			}
			return string.Join(" | ", list);
		}
	}
	public static class TeamPodiumView
	{
		internal sealed class GameStyle
		{
			public Sprite? Sprite;

			public Type SpriteType;

			public float SpritePixels = 1f;

			public Color Panel = FallbackPanel;

			public TMP_FontAsset? Font;

			public Color Text = FallbackText;
		}

		private const float DesignW = 1800f;

		private const float DesignH = 880f;

		private static readonly Color FallbackPanel = new Color(0.98f, 0.96f, 0.91f);

		internal static readonly Color FallbackText = new Color(0.17f, 0.15f, 0.13f);

		private static GameObject? _root;

		private static List<TeamStanding> _standings = new List<TeamStanding>();

		private static Rect _builtWindow;

		private static Type? _scoreboardType;

		private static Object? _scoreboard;

		private static Sprite? _circle;

		public static bool Exists => (Object)(object)_root != (Object)null;

		internal static Object? ScoreboardObject
		{
			get
			{
				if (!FindScoreboard())
				{
					return null;
				}
				return _scoreboard;
			}
		}

		public static void Destroy()
		{
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
			}
			_root = null;
		}

		public static void Build(List<TeamStanding> standings)
		{
			Destroy();
			_standings = standings;
			try
			{
				BuildInternal(standings);
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"TeamPodiumView.Build: {arg}");
				Destroy();
			}
		}

		public static void Sync()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			if (Exists)
			{
				Rect val = CurrentWindow();
				if (Mathf.Abs(((Rect)(ref val)).x - ((Rect)(ref _builtWindow)).x) > 1.5f || Mathf.Abs(((Rect)(ref val)).y - ((Rect)(ref _builtWindow)).y) > 1.5f || Mathf.Abs(((Rect)(ref val)).width - ((Rect)(ref _builtWindow)).width) > 1.5f || Mathf.Abs(((Rect)(ref val)).height - ((Rect)(ref _builtWindow)).height) > 1.5f)
				{
					Build(_standings);
				}
			}
		}

		internal static float Luminance(Color c)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			return 0.299f * c.r + 0.587f * c.g + 0.114f * c.b;
		}

		private static bool FindScoreboard()
		{
			if (_scoreboard != (Object)null)
			{
				return true;
			}
			if ((object)_scoreboardType == null)
			{
				_scoreboardType = AccessTools.TypeByName("Scoreboard");
			}
			if (_scoreboardType == null)
			{
				return false;
			}
			_scoreboard = Object.FindAnyObjectByType(_scoreboardType, (FindObjectsInactive)1);
			return _scoreboard != (Object)null;
		}

		private static Rect CurrentWindow()
		{
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (FindScoreboard())
				{
					object? obj = AccessTools.Field(_scoreboardType, "fullBackground")?.GetValue(_scoreboard);
					Image val = (Image)((obj is Image) ? obj : null);
					if ((Object)(object)val != (Object)null && ((Behaviour)val).isActiveAndEnabled)
					{
						Vector3[] array = (Vector3[])(object)new Vector3[4];
						((Graphic)val).rectTransform.GetWorldCorners(array);
						Canvas val2 = (((Object)(object)((Graphic)val).canvas != (Object)null) ? ((Graphic)val).canvas.rootCanvas : null);
						Camera val3 = (((Object)(object)val2 != (Object)null && (int)val2.renderMode != 0) ? val2.worldCamera : null);
						Vector2 val4 = RectTransformUtility.WorldToScreenPoint(val3, array[0]);
						Vector2 val5 = RectTransformUtility.WorldToScreenPoint(val3, array[2]);
						Rect result = Rect.MinMaxRect(Mathf.Min(val4.x, val5.x), Mathf.Min(val4.y, val5.y), Mathf.Max(val4.x, val5.x), Mathf.Max(val4.y, val5.y));
						if (((Rect)(ref result)).width > 200f && ((Rect)(ref result)).height > 200f)
						{
							return result;
						}
					}
				}
			}
			catch
			{
			}
			return Rect.MinMaxRect((float)Screen.width * 0.03f, (float)Screen.height * 0.09f, (float)Screen.width * 0.97f, (float)Screen.height * 0.87f);
		}

		private static float CanvasScale()
		{
			float num = Mathf.Max(1f, (float)Screen.width);
			float num2 = Mathf.Max(1f, (float)Screen.height);
			return Mathf.Pow(2f, Mathf.Lerp(Mathf.Log(num / 1920f, 2f), Mathf.Log(num2 / 1080f, 2f), 0.5f));
		}

		internal static GameStyle ReadGameStyle()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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_007c: 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_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			GameStyle gameStyle = new GameStyle();
			try
			{
				if (!FindScoreboard())
				{
					return gameStyle;
				}
				Type scoreboardType = _scoreboardType;
				Object scoreboard = _scoreboard;
				object? obj = AccessTools.Field(scoreboardType, "fullBackground")?.GetValue(scoreboard);
				Image val = (Image)((obj is Image) ? obj : null);
				if (val != null && (Object)(object)val.sprite != (Object)null)
				{
					gameStyle.Sprite = val.sprite;
					gameStyle.SpriteType = val.type;
					gameStyle.SpritePixels = val.pixelsPerUnitMultiplier;
					Color color = ((Graphic)val).color;
					if (color.a > 0.5f && Luminance(color) > 0.6f)
					{
						gameStyle.Panel = new Color(color.r, color.g, color.b, 1f);
					}
				}
				string[] array = new string[5] { "holeName", "parInfo", "courseProgress", "lobbyNameLabel", "localPlayerScore" };
				foreach (string text in array)
				{
					object? obj2 = AccessTools.Field(scoreboardType, text)?.GetValue(scoreboard);
					TMP_Text val2 = (TMP_Text)((obj2 is TMP_Text) ? obj2 : null);
					if (val2 != null && (Object)(object)val2.font != (Object)null)
					{
						gameStyle.Font = val2.font;
						Color color2 = ((Graphic)val2).color;
						if (color2.a > 0.5f && Luminance(color2) < 0.45f)
						{
							gameStyle.Text = new Color(color2.r, color2.g, color2.b, 1f);
						}
						break;
					}
				}
				ManualLogSource log = Plugin.Log;
				Sprite? sprite = gameStyle.Sprite;
				string text2 = string.Format("\ud83c\udfa8 UI style: sprite={0} type={1} ", ((sprite != null) ? ((Object)sprite).name : null) ?? "none", gameStyle.SpriteType);
				object[] obj3 = new object[4] { gameStyle.SpritePixels, gameStyle.Panel, null, null };
				TMP_FontAsset? font = gameStyle.Font;
				obj3[2] = ((font != null) ? ((Object)font).name : null) ?? "default";
				obj3[3] = gameStyle.Text;
				log.LogInfo((object)(text2 + string.Format("pixels={0} panel={1} font={2} text={3}", obj3)));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("TeamPodiumView.ReadGameStyle: " + ex.Message));
			}
			return gameStyle;
		}

		internal static void Skin(Image image, GameStyle style, Color color, float pixelScale)
		{
			//IL_0001: 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)
			((Graphic)image).color = color;
			((Graphic)image).raycastTarget = false;
			if (!((Object)(object)style.Sprite == (Object)null))
			{
				image.sprite = style.Sprite;
				image.type = style.SpriteType;
				image.pixelsPerUnitMultiplier = style.SpritePixels * pixelScale;
			}
		}

		internal static RectTransform NewRect(string name, Transform parent, float x, float y, float w, float h, out GameObject go)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			go = new GameObject(name, new Type[1] { typeof(RectTransform) });
			RectTransform val = (RectTransform)go.transform;
			((Transform)val).SetParent(parent, false);
			Vector2 anchorMin = (val.anchorMax = Vector2.zero);
			val.anchorMin = anchorMin;
			val.pivot = Vector2.zero;
			val.anchoredPosition = new Vector2(x, y);
			val.sizeDelta = new Vector2(w, h);
			return val;
		}

		internal static Image NewImage(Transform parent, GameStyle style, string name, float x, float y, float w, float h, Color color, float pixelScale, bool rounded = true)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			NewRect(name, parent, x, y, w, h, out GameObject go);
			Image val = go.AddComponent<Image>();
			if (rounded)
			{
				Skin(val, style, color, pixelScale);
			}
			else
			{
				((Graphic)val).color = color;
				((Graphic)val).raycastTarget = false;
			}
			return val;
		}

		private static Sprite Circle()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_circle != (Object)null)
			{
				return _circle;
			}
			Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false)
			{
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1,
				hideFlags = (HideFlags)61
			};
			Color32[] array = (Color32[])(object)new Color32[16384];
			float num = 64f;
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 128; j++)
				{
					float num2 = (float)j + 0.5f - num;
					float num3 = (float)i + 0.5f - num;
					float num4 = Mathf.Clamp01(num - Mathf.Sqrt(num2 * num2 + num3 * num3));
					array[i * 128 + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)(num4 * 255f));
				}
			}
			val.SetPixels32(array);
			val.Apply();
			_circle = Sprite.Create(val, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f), 100f);
			((Object)_circle).hideFlags = (HideFlags)61;
			return _circle;
		}

		private static Image NewCircle(Transform parent, string name, float x, float y, float size, Color color)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			Image val = NewImage(parent, null, name, x, y, size, size, color, 1f, rounded: false);
			val.sprite = Circle();
			return val;
		}

		internal static TextMeshProUGUI NewText(Transform parent, GameStyle style, float x, float y, float w, float h, string text, float size, Color color, TextAlignmentOptions alignment, bool ellipsis = false)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			NewRect("Text", parent, x, y, w, h, out GameObject go);
			TextMeshProUGUI val = go.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)style.Font != (Object)null)
			{
				((TMP_Text)val).font = style.Font;
			}
			((TMP_Text)val).text = text;
			((TMP_Text)val).fontSize = size;
			((Graphic)val).color = color;
			((TMP_Text)val).alignment = alignment;
			((TMP_Text)val).fontStyle = (FontStyles)0;
			((TMP_Text)val).enableAutoSizing = false;
			((TMP_Text)val).enableWordWrapping = false;
			((TMP_Text)val).overflowMode = (TextOverflowModes)(ellipsis ? 1 : 0);
			((Graphic)val).raycastTarget = false;
			return val;
		}

		private static void BuildInternal(List<TeamStanding> standings)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Expected O, but got Unknown
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Expected O, but got Unknown
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03be: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_040f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Unknown result type (might be due to invalid IL or missing references)
			//IL_049a: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0554: Unknown result type (might be due to invalid IL or missing references)
			//IL_0556: Unknown result type (might be due to invalid IL or missing references)
			//IL_0560: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fa: Unknown result type (might be due to invalid IL or missing references)
			List<TeamStanding> list = new List<TeamStanding>();
			foreach (TeamStanding standing in standings)
			{
				if (standing.Rank <= 3)
				{
					list.Add(standing);
				}
			}
			if (list.Count == 0)
			{
				return;
			}
			GameStyle gameStyle = ReadGameStyle();
			_root = new GameObject("TM_Podium", new Type[1] { typeof(RectTransform) });
			Object.DontDestroyOnLoad((Object)(object)_root);
			Canvas val = _root.AddComponent<Canvas>();
			val.renderMode = (RenderMode)0;
			val.sortingOrder = 1000;
			CanvasScaler val2 = _root.AddComponent<CanvasScaler>();
			val2.uiScaleMode = (ScaleMode)1;
			val2.referenceResolution = new Vector2(1920f, 1080f);
			val2.screenMatchMode = (ScreenMatchMode)0;
			val2.matchWidthOrHeight = 0.5f;
			Rect val3 = (_builtWindow = CurrentWindow());
			GameObject val4 = new GameObject("Panel", new Type[1] { typeof(RectTransform) });
			RectTransform val5 = (RectTransform)val4.transform;
			((Transform)val5).SetParent(_root.transform, false);
			val5.anchorMin = new Vector2(((Rect)(ref val3)).xMin / (float)Screen.width, ((Rect)(ref val3)).yMin / (float)Screen.height);
			val5.anchorMax = new Vector2(((Rect)(ref val3)).xMax / (float)Screen.width, ((Rect)(ref val3)).yMax / (float)Screen.height);
			Vector2 offsetMin = (val5.offsetMax = Vector2.zero);
			val5.offsetMin = offsetMin;
			Skin(val4.AddComponent<Image>(), gameStyle, gameStyle.Panel, 1f);
			float num = CanvasScale();
			float num2 = Mathf.Min(((Rect)(ref val3)).width / num / 1800f, ((Rect)(ref val3)).height / num / 880f);
			RectTransform component = new GameObject("Content", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
			((Transform)component).SetParent((Transform)(object)val5, false);
			Vector2 val6 = default(Vector2);
			((Vector2)(ref val6))..ctor(0.5f, 0.5f);
			component.pivot = val6;
			offsetMin = (component.anchorMax = val6);
			component.anchorMin = offsetMin;
			component.anchoredPosition = Vector2.zero;
			component.sizeDelta = new Vector2(1800f, 880f);
			((Transform)component).localScale = new Vector3(num2, num2, 1f);
			NewText((Transform)(object)component, gameStyle, 0f, 750f, 1800f, 110f, Lang.Get("Classement final", "Final standings"), 62f, gameStyle.Text, (TextAlignmentOptions)514);
			int count = list.Count;
			TeamStanding[] array = new TeamStanding[count];
			for (int i = 0; i < count; i++)
			{
				int num3 = count / 2 + ((i != 0) ? ((i + 1) / 2 * ((i % 2 != 1) ? 1 : (-1))) : 0);
				if (num3 >= 0 && num3 < count)
				{
					array[num3] = list[i];
				}
			}
			float num4 = Mathf.Min(560f, 1720f / (float)count);
			float num5 = (1800f - num4 * (float)count) / 2f;
			for (int j = 0; j < count; j++)
			{
				TeamStanding teamStanding = array[j];
				if (teamStanding != null)
				{
					Color val8 = Plugin.TeamColors[teamStanding.Team];
					float w = num4 - 40f;
					float x = num5 + num4 * (float)j + 20f;
					float num6 = ((teamStanding.Rank == 1) ? 240f : ((teamStanding.Rank == 2) ? 170f : 120f));
					Image val9 = NewImage((Transform)(object)component, gameStyle, "Step", x, 44f, w, num6, new Color(val8.r, val8.g, val8.b, 1f), 2f);
					NewText(((Component)val9).transform, gameStyle, 0f, 0f, w, num6, teamStanding.Rank.ToString(), num6 * 0.62f, (Luminance(val8) > 0.6f) ? FallbackText : Color.white, (TextAlignmentOptions)514);
					int count2 = teamStanding.Players.Count;
					float num7 = Mathf.Clamp((320f - 10f * (float)(count2 - 1)) / (float)Mathf.Max(1, count2), 40f, 80f);
					float num8 = num7 * (float)count2 + 10f * (float)Mathf.Max(0, count2 - 1);
					float num9 = 44f + num6 + 16f;
					for (int k = 0; k < count2; k++)
					{
						BuildCard((Transform)(object)component, gameStyle, teamStanding.Players[k], val8, x, num9 + num8 - num7 - (float)k * (num7 + 10f), w, num7);
					}
					Image val10 = NewImage((Transform)(object)component, gameStyle, "Header", x, num9 + num8 + 14f, w, 104f, new Color(val8.r, val8.g, val8.b, 0.3f), 2f);
					NewText(((Component)val10).transform, gameStyle, 0f, 52f, w, 48f, Lang.Get("Équipe", "Team") + " " + Plugin.TeamNames[teamStanding.Team], 38f, Color.Lerp(val8, Color.black, 0.45f), (TextAlignmentOptions)514);
					string text = (Plugin.RoundsMode ? string.Format("{0} {1}", teamStanding.Rounds, Lang.Get((teamStanding.Rounds > 1) ? "manches" : "manche", (teamStanding.Rounds > 1) ? "rounds" : "round")) : $"{teamStanding.Points} pts");
					NewText(((Component)val10).transform, gameStyle, 0f, 4f, w, 52f, text, 46f, gameStyle.Text, (TextAlignmentOptions)514);
				}
			}
		}

		private static void BuildCard(Transform parent, GameStyle style, (ulong guid, string name, int score) player, Color team, float x, float y, float w, float h)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: 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_018b: Unknown result type (might be due to invalid IL or missing references)
			Image val = NewImage(parent, style, "Card", x, y, w, h, new Color(0.91f, 0.89f, 0.83f, 1f), 3f);
			float num = h - 16f;
			Image val2 = NewCircle(((Component)val).transform, "AvatarFrame", 12f, 8f, num, team);
			Image val3 = NewCircle(((Component)val2).transform, "AvatarMask", 3f, 3f, num - 6f, Color.white);
			((Component)val3).gameObject.AddComponent<Mask>().showMaskGraphic = false;
			Sprite val4 = null;
			try
			{
				val4 = PlayerIconManager.GetPlayerIcon(player.guid, (IconSize)1);
			}
			catch
			{
			}
			Image val5 = NewImage(((Component)val3).transform, style, "Avatar", 0f, 0f, num - 6f, num - 6f, (Color)(((Object)(object)val4 != (Object)null) ? Color.white : new Color(0.6f, 0.6f, 0.6f)), 1f, rounded: false);
			if ((Object)(object)val4 != (Object)null)
			{
				val5.sprite = val4;
			}
			float num2 = 12f + num + 14f;
			NewText(((Component)val).transform, style, num2, 0f, w - num2 - 104f, h, player.name, h * 0.42f, style.Text, (TextAlignmentOptions)4097, ellipsis: true);
			NewText(((Component)val).transform, style, w - 104f, 0f, 92f, h, player.score.ToString(), h * 0.46f, style.Text, (TextAlignmentOptions)4100);
		}
	}
	[HarmonyPatch]
	public class DrivingRangeScoreResetPatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("DrivingRangeManager"), "Awake", (Type[])null, (Type[])null);
		}

		[HarmonyPostfix]
		private static void Postfix()
		{
			ScoreboardTeamData.TeamRounds.Clear();
			RoundsTracker.NewHole();
			Plugin.Log.LogInfo((object)"\ud83c\udfaf Terrain d'entraînement → manches d'équipe remises à zéro");
			TeamSyncManager.BroadcastScores();
		}
	}
	[HarmonyPatch]
	public class ScoreboardEntryPatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("ScoreboardEntry"), "PopulateWith", (Type[])null, (Type[])null);
		}

		[HarmonyPostfix]
		private static void Postfix(object __instance, object playerState)
		{
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
				ulong num = (ulong)(playerState.GetType().GetField("playerGuid", BindingFlags.Instance | BindingFlags.Public)?.GetValue(playerState) ?? ((object)0uL));
				object obj = ((__instance is Component) ? __instance : null);
				GameObject val = ((obj != null) ? ((Component)obj).gameObject : null);
				int value = (int)(playerState.GetType().GetField("courseScore", BindingFlags.Instance | BindingFlags.Public)?.GetValue(playerState) ?? ((object)0));
				if ((Object)(object)val != (Object)null)
				{
					ScoreboardTeamData.EntryGuids[val] = num;
					ScoreboardTeamData.EntryScores[val] = value;
				}
				if (Plugin.Enabled)
				{
					int team = Plugin.GetTeam(num);
					object? obj2 = __instance.GetType().GetField("name", bindingAttr)?.GetValue(__instance);
					TMP_Text val2 = (TMP_Text)((obj2 is TMP_Text) ? obj2 : null);
					if (!((Object)(object)val2 == (Object)null))
					{
						Color val3 = Color.Lerp(Plugin.TeamColors[team], Color.black, (team == 3) ? 0.4f : 0.15f);
						val2.text = "<color=#" + ColorUtility.ToHtmlStringRGB(val3) + ">" + val2.text + "</color>";
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("ScoreboardEntryPatch: " + ex.Message));
			}
		}
	}
	[HarmonyPatch]
	public class ScoreboardRefreshPatch
	{
		private static readonly List<GameObject> _teamHeaders = new List<GameObject>();

		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("Scoreboard"), "Refresh", (Type[])null, (Type[])null);
		}

		[HarmonyPostfix]
		private static void Postfix(object __instance)
		{
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_037a: Unknown result type (might be due to invalid IL or missing references)
			foreach (GameObject teamHeader in _teamHeaders)
			{
				if ((Object)(object)teamHeader != (Object)null)
				{
					Object.Destroy((Object)(object)teamHeader);
				}
			}
			_teamHeaders.Clear();
			ModeLabels.UpdateScoreboardTitle((Component?)((__instance is Component) ? __instance : null));
			if (!Plugin.Enabled)
			{
				return;
			}
			try
			{
				BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
				object? obj = __instance.GetType().GetField("entryParent", bindingFlags)?.GetValue(__instance);
				Transform val = (Transform)((obj is Transform) ? obj : null);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				List<GameObject> list = new List<GameObject>();
				foreach (KeyValuePair<GameObject, ulong> entryGuid in ScoreboardTeamData.EntryGuids)
				{
					if ((Object)(object)entryGuid.Key == (Object)null)
					{
						list.Add(entryGuid.Key);
					}
				}
				foreach (GameObject item2 in list)
				{
					ScoreboardTeamData.EntryGuids.Remove(item2);
					ScoreboardTeamData.EntryScores.Remove(item2);
				}
				bool inPractice = TeamStandings.InPractice;
				Dictionary<int, int> dictionary = new Dictionary<int, int>();
				Dictionary<int, List<(GameObject, int)>> dictionary2 = new Dictionary<int, List<(GameObject, int)>>();
				for (int i = 0; i < val.childCount; i++)
				{
					GameObject gameObject = ((Component)val.GetChild(i)).gameObject;
					if (gameObject.activeSelf && ScoreboardTeamData.EntryGuids.TryGetValue(gameObject, out var value))
					{
						int team = Plugin.GetTeam(value);
						int value2;
						int num = (ScoreboardTeamData.EntryScores.TryGetValue(gameObject, out value2) ? value2 : 0);
						dictionary[team] = (dictionary.TryGetValue(team, out var value3) ? value3 : 0) + ((!inPractice) ? num : 0);
						if (!dictionary2.ContainsKey(team))
						{
							dictionary2[team] = new List<(GameObject, int)>();
						}
						dictionary2[team].Add((gameObject, num));
					}
				}
				Dictionary<int, int> teamRank;
				List<int> list2 = TeamStandings.Sort(dictionary, out teamRank);
				int num2 = 0;
				foreach (int item3 in list2)
				{
					if (!dictionary2.ContainsKey(item3) || dictionary2[item3].Count == 0)
					{
						continue;
					}
					List<(GameObject, int)> list3 = dictionary2[item3];
					list3.Sort(((GameObject go, int score) a, (GameObject go, int score) b) => b.score.CompareTo(a.score));
					Color teamColor = Plugin.TeamColors[item3];
					string teamName = Plugin.TeamNames[item3];
					int num3;
					string label;
					if (Plugin.RoundsMode)
					{
						num3 = RoundsOf(item3);
						label = string.Format("{0} {1}", num3, Lang.Get((num3 > 1) ? "manches" : "manche", (num3 > 1) ? "rounds" : "round"));
					}
					else
					{
						num3 = dictionary[item3];
						label = $"{num3} pts";
					}
					GameObject val2 = Object.Instantiate<GameObject>(list3[0].Item1, val);
					((Object)val2).name = $"TM_TeamHeader_{item3}";
					_teamHeaders.Add(val2);
					SetupTeamHeader(val2, teamName, label, num3, teamColor, bindingFlags);
					val2.transform.SetSiblingIndex(num2);
					num2++;
					foreach (var item4 in list3)
					{
						GameObject item = item4.Item1;
						item.transform.SetSiblingIndex(num2);
						TryColorEntryBackground(item, teamColor);
						SetEntryRank(item, teamRank[item3], bindingFlags);
						num2++;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("ScoreboardRefreshPatch: " + ex.Message));
			}
			static int RoundsOf(int t)
			{
				return TeamStandings.RoundsOf(t);
			}
		}

		private static void SetupTeamHeader(GameObject header, string teamName, string label, int totalScore, Color teamColor, BindingFlags flags)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Image[] componentsInChildren = header.GetComponentsInChildren<Image>(true);
				if (componentsInChildren.Length != 0)
				{
					((Graphic)componentsInChildren[0]).color = new Color(teamColor.r, teamColor.g, teamColor.b, 0.35f);
				}
				for (int i = 1; i < componentsInChildren.Length; i++)
				{
					((Graphic)componentsInChildren[i]).color = Color.clear;
				}
				TMP_Text[] componentsInChildren2 = header.GetComponentsInChildren<TMP_Text>(true);
				foreach (TMP_Text val in componentsInChildren2)
				{
					val.text = "";
				}
				Component component = header.GetComponent(AccessTools.TypeByName("ScoreboardEntry"));
				if (!((Object)(object)component == (Object)null))
				{
					object? obj = ((object)component).GetType().GetField("name", flags)?.GetValue(component);
					TMP_Text val2 = (TMP_Text)((obj is TMP_Text) ? obj : null);
					if ((Object)(object)val2 != (Object)null)
					{
						val2.text = "<b><color=#" + ColorUtility.ToHtmlStringRGB(teamColor) + ">" + Lang.Get("Équipe", "Team") + " " + teamName + "  —  " + label + "</color></b>";
						val2.fontSize *= 1.1f;
					}
					object? obj2 = ((object)component).GetType().GetField("matchScore", flags)?.GetValue(component);
					TMP_Text val3 = (TMP_Text)((obj2 is TMP_Text) ? obj2 : null);
					if ((Object)(object)val3 != (Object)null)
					{
						val3.text = totalScore.ToString();
					}
				}
			}
			catch
			{
			}
		}

		private static void SetEntryRank(GameObject go, int rank, BindingFlags flags)
		{
			try
			{
				Component component = go.GetComponent(AccessTools.TypeByName("ScoreboardEntry"));
				object? obj = ((object)component)?.GetType().GetField("ranking", flags)?.GetValue(component);
				TMP_Text val = (TMP_Text)((obj is TMP_Text) ? obj : null);
				if ((Object)(object)val != (Object)null)
				{
					val.text = rank.ToString();
				}
			}
			catch
			{
			}
		}

		private static void TryColorEntryBackground(GameObject go, Color teamColor)
		{
			//IL_000e: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Image[] componentsInChildren = go.GetComponentsInChildren<Image>(true);
				if (componentsInChildren.Length != 0)
				{
					Color val = default(Color);
					((Color)(ref val))..ctor(teamColor.r, teamColor.g, teamColor.b, 0.15f);
					((Graphic)componentsInChildren[0]).color = Color.Lerp(((Graphic)componentsInChildren[0]).color, val, 0.4f);
				}
			}
			catch
			{
			}
		}
	}
	[HarmonyPatch]
	public class TeamModeMenuPatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("MatchSetupRules"), "Initialize", (Type[])null, (Type[])null);
		}

		[HarmonyPostfix]
		private static void Postfix(object __instance)
		{
			RoundsTracker.NewHole();
			Plugin.Log.LogInfo((object)"\ud83d\uddfa\ufe0f New hole → finishers reset");
			try
			{
				BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
				object? obj = __instance.GetType().GetField("countdown", bindingAttr)?.GetValue(__instance);
				Component val = (Component)((obj is Component) ? obj : null);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				Transform parent = val.transform.parent.parent.parent;
				for (int i = 0; i < parent.childCount; i++)
				{
					if (((Object)parent.GetChild(i)).name == "Team Mode Header")
					{
						return;
					}
				}
				GameObject gameObject = ((Component)val.transform.parent.GetChild(0)).gameObject;
				object? obj2 = __instance.GetType().GetField("knockouts", bindingAttr)?.GetValue(__instance);
				Component val2 = (Component)((obj2 is Component) ? obj2 : null);
				Transform val3 = null;
				Transform val4 = null;
				for (int j = 0; j < parent.childCount; j++)
				{
					Transform child = parent.GetChild(j);
					if (((Object)child).name == "Battle")
					{
						val3 = child;
					}
					if (((Object)child).name == "Battle Rules")
					{
						val4 = child;
					}
				}
				if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val4 == (Object)null))
				{
					GameObject val5 = Object.Instantiate<GameObject>(((Component)val3).gameObject, parent);
					((Object)val5).name = "Team Mode Header";
					LocalizeStringEvent[] componentsInChildren = val5.GetComponentsInChildren<LocalizeStringEvent>(true);
					foreach (LocalizeStringEvent val6 in componentsInChildren)
					{
						Object.Destroy((Object)(object)val6);
					}
					TMP_Text componentInChildren = val5.GetComponentInChildren<TMP_Text>(true);
					if ((Object)(object)componentInChildren != (Object)null)
					{
						componentInChildren.text = EnhancedMode.Label;
					}
					GameObject val7 = Object.Instantiate<GameObject>(((Component)val4).gameObject, parent);
					((Object)val7).name = "Team Mode Rules";
					for (int num = val7.transform.childCount - 1; num >= 0; num--)
					{
						Object.Destroy((Object)(object)((Component)val7.transform.GetChild(num)).gameObject);
					}
					TeamModeUi.SetSection(val5, val7);
					TeamModeUi.Build(gameObject, (val2 != null) ? val2.gameObject : null, val7.transform);
					EnhancedMode.Refresh();
					Plugin.Log.LogInfo((object)"✓ Team Mode UI built!");
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("TeamModeMenuPatch: " + ex.Message + "\n" + ex.StackTrace));
			}
		}
	}
	public static class EnhancedMode
	{
		public const int Index = 2;

		public static int Programmatic;

		public static string Label => Lang.Get("Mode Équipes Amélioré", "Improved Team Mode");

		private static MatchSetupMenu? Menu
		{
			get
			{
				if (!SingletonNetworkBehaviour<MatchSetupMenu>.HasInstance)
				{
					return null;
				}
				return SingletonNetworkBehaviour<MatchSetupMenu>.Instance;
			}
		}

		public static TMP_Dropdown? ModeDropdown
		{
			get
			{
				if (!((Object)(object)Menu?.gameModeDropdown != (Object)null))
				{
					return null;
				}
				return Menu.gameModeDropdown.Dropdown;
			}
		}

		public static string DropdownLabel => Lang.Get("Équipes Améliorées", "Improved Teams");

		private static void EnsureOption(TMP_Dropdown dropdown)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			List<OptionData> options = dropdown.options;
			if (options.Count == 2)
			{
				options.Add(new OptionData(DropdownLabel));
				dropdown.options = options;
			}
			else if (options.Count > 2 && options[2].text != DropdownLabel)
			{
				options[2].text = DropdownLabel;
				dropdown.RefreshShownValue();
			}
		}

		public static void Refresh()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected I4, but got Unknown
			try
			{
				MatchSetupMenu menu = Menu;
				TMP_Dropdown modeDropdown = ModeDropdown;
				if (!((Object)(object)menu == (Object)null) && !((Object)(object)modeDropdown == (Object)null))
				{
					EnsureOption(modeDropdown);
					int num = ((Plugin.EnabledSetting && (int)menu.gameMode == 0) ? 2 : ((int)menu.gameMode));
					if (modeDropdown.value != num)
					{
						modeDropdown.SetValueWithoutNotify(num);
					}
					modeDropdown.RefreshShownValue();
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("EnhancedMode.Refresh: " + ex.Message));
			}
		}

		public static bool OnHostPicked(MatchSetupMenu menu, int value)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			bool flag = value == 2;
			bool flag2 = Plugin.EnabledSetting != flag;
			Plugin.EnabledSetting = flag;
			Plugin.Log.LogInfo((object)("[TeamMode] Game mode menu → " + (flag ? "Enhanced teams (Team Mode ON)" : $"game mode {value} (Team Mode OFF)")));
			if (flag && (int)menu.gameMode != 0)
			{
				menu.NetworkgameMode = (GameMode)0;
			}
			if (flag2)
			{
				if (flag)
				{
					TeamModeUi.RebuildPlayerDropdowns();
				}
				if (NetworkServer.active)
				{
					TeamSyncManager.BroadcastFullState();
				}
			}
			TeamModeUi.UpdateSection();
			CustomScoringBridge.Update();
			return !flag;
		}

		public static void OnGameModeChanged(MatchSetupMenu menu, GameMode current)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			if (((NetworkBehaviour)menu).isServer && (int)current == 1 && Plugin.EnabledSetting)
			{
				Plugin.EnabledSetting = false;
				Plugin.Log.LogInfo((object)"[TeamMode] Native Teams mode selected → Team Mode OFF");
				if (NetworkServer.active)
				{
					TeamSyncManager.BroadcastFullState();
				}
				TeamModeUi.UpdateSection();
				CustomScoringBridge.Update();
			}
			Refresh();
		}
	}
	public static class CustomScoringBridge
	{
		private static bool? _savedEnabled;

		private static bool _looked;

		private static Type? _type;

		private static Type? CustomScoringType()
		{
			if (_looked)
			{
				return _type;
			}
			_looked = true;
			try
			{
				foreach (PluginInfo value in Chainloader.PluginInfos.Values)
				{
					Type type = ((object)value.Instance)?.GetType();
					if (type != null && type.FullName == "Custom_Scoring.Plugin")
					{
						_type = type;
						break;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("CustomScoringBridge: plugin list unavailable (" + ex.Message + ")"));
			}
			Plugin.Log.LogInfo((object)((_type != null) ? "[TeamMode] Custom_Scoring found: its menu section is hidden in Rounds mode" : "[TeamMode] Custom_Scoring not installed: nothing to hide"));
			return _type;
		}

		public static void Update()
		{
			Type type = CustomScoringType();
			if (type == null)
			{
				return;
			}
			try
			{
				bool flag = Plugin.EnabledSetting && Plugin.RoundsMode;
				SetSectionVisible(!flag);
				FieldInfo fieldInfo = AccessTools.Field(type, "Enabled");
				if (fieldInfo == null)
				{
					return;
				}
				bool flag2 = (bool)fieldInfo.GetValue(null);
				if (flag)
				{
					bool valueOrDefault = _savedEnabled == true;
					if (!_savedEnabled.HasValue)
					{
						valueOrDefault = flag2;
						_savedEnabled = valueOrDefault;
					}
					if (flag2)
					{
						fieldInfo.SetValue(null, false);
						AccessTools.Method(type, "ApplyPlacement", (Type[])null, (Type[])null)?.Invoke(null, null);
						Plugin.Log.LogInfo((object)"[TeamMode] Rounds mode → Custom Scoring hidden and switched off");
					}
				}
				else if (_savedEnabled.HasValue)
				{
					bool value = _savedEnabled.Value;
					_savedEnabled = null;
					if (flag2 != value)
					{
						fieldInfo.SetValue(null, value);
						AccessTools.Method(type, "ApplyPlacement", (Type[])null, (Type[])null)?.Invoke(null, null);
						Plugin.Log.LogInfo((object)("[TeamMode] Left Rounds mode → Custom Scoring back (" + (value ? "on" : "off") + ")"));
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("CustomScoringBridge: " + ex.Message));
			}
		}

		private static void SetSectionVisible(bool visible)
		{
			Transform rulesContent = TeamModeUi.RulesContent;
			if ((Object)(object)rulesContent == (Object)null)
			{
				return;
			}
			for (int i = 0; i < rulesContent.childCount; i++)
			{
				Transform child = rulesContent.GetChild(i);
				if ((((Object)child).name == "Custom Scoring Header" || ((Object)child).name == "Custom Scoring Rules") && ((Component)child).gameObject.activeSelf != visible)
				{
					((Component)child).gameObject.SetActive(visible);
				}
			}
		}
	}
	public static class ModeLabels
	{
		private static string Ffa => UI.MATCHSETUP_Option_Mode_FFA;

		public static void UpdateScoreboardTitle(Component? scoreboard)
		{
			if ((Object)(object)scoreboard == (Object)null)
			{
				return;
			}
			try
			{
				string ffa = Ffa;
				string label = EnhancedMode.Label;
				string text = (Plugin.Enabled ? label : ffa);
				TMP_Text[] componentsInChildren = scoreboard.GetComponentsInChildren<TMP_Text>(true);
				foreach (TMP_Text val in componentsInChildren)
				{
					if ((val.text == ffa || val.text == label) && val.text != text)
					{
						val.text = text;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("ModeLabels.UpdateScoreboardTitle: " + ex.Message));
			}
		}

		public static void Tick()
		{
			Object? scoreboardObject = TeamPodiumView.ScoreboardObject;
			UpdateScoreboardTitle((Component?)(object)((scoreboardObject is Component) ? scoreboardObject : null));
		}

		public static void UpdatePauseLabel(TMP_Text? label)
		{
			if ((Object)(object)label == (Object)null || !Plugin.Enabled)
			{
				return;
			}
			try
			{
				string ffa = Ffa;
				if (label.text.Contains(ffa))
				{
					label.text = label.text.Replace(ffa, EnhancedMode.Label);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("ModeLabels.UpdatePauseLabel: " + ex.Message));
			}
		}
	}
	[HarmonyPatch]
	public class PauseMenuModeLabelPatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("PauseMenu"), "UpdateGameInfoLabels", (Type[])null, (Type[])null);
		}

		[HarmonyPostfix]
		private static void Postfix(PauseMenu __instance)
		{
			ModeLabels.UpdatePauseLabel(__instance.gamemodeLabel);
		}
	}
	[HarmonyPatch]
	public class GameModeDropdownPatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("DropdownOption"), "OnValueChanged", (Type[])null, (Type[])null);
		}

		[HarmonyPrefix]
		private static bool Prefix(DropdownOption __instance)
		{
			try
			{
				if (EnhancedMode.Programmatic > 0)
				{
					return true;
				}
				if (!SingletonNetworkBehaviour<MatchSetupMenu>.HasInstance)
				{
					return true;
				}
				MatchSetupMenu instance = SingletonNetworkBehaviour<MatchSetupMenu>.Instance;
				if ((Object)(object)instance.gameModeDropdown != (Object)(object)__instance || !((NetworkBehaviour)instance).isServer)
				{
					return true;
				}
				return EnhancedMode.OnHostPicked(instance, __instance.value);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("GameModeDropdownPatch: " + ex.Message));
			}
			return true;
		}
	}
	[HarmonyPatch]
	public class DropdownSetValuePatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("DropdownOption"), "SetValue", (Type[])null, (Type[])null);
		}

		[HarmonyPrefix]
		private static void Prefix()
		{
			EnhancedMode.Programmatic++;
		}

		[HarmonyFinalizer]
		private static void Finalizer()
		{
			EnhancedMode.Programmatic--;
			if (EnhancedMode.Programmatic <= 0)
			{
				EnhancedMode.Programmatic = 0;
				EnhancedMode.Refresh();
			}
		}
	}
	[HarmonyPatch]
	public class GameModeOptionsPatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("LocalizeDropdown"), "RefreshOptions", (Type[])null, (Type[])null);
		}

		[HarmonyPostfix]
		private static void Postfix(LocalizeDropdown __instance)
		{
			TMP_Dropdown modeDropdown = EnhancedMode.ModeDropdown;
			if ((Object)(object)modeDropdown != (Object)null && (Object)(object)((Component)__instance).gameObject == (Object)(object)((Component)modeDropdown).gameObject)
			{
				EnhancedMode.Refresh();
			}
		}
	}
	[HarmonyPatch]
	public class GameModeChangedPatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("MatchSetupMenu"), "OnGameModeChanged", (Type[])null, (Type[])null);
		}

		[HarmonyPostfix]
		private static void Postfix(MatchSetupMenu __instance, GameMode currentMode)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			EnhancedMode.OnGameModeChanged(__instance, currentMode);
		}
	}
	[HarmonyPatch]
	public class GameModeMenuOpenPatch
	{
		[HarmonyTargetMethod]
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("MatchSetupMenu"), "SetEnabled", (Type[])null, (Type[])null);
		}

		[HarmonyPostfix]
		private static void Postfix()
		{
			EnhancedMode.Refresh();
		}
	}
	public static class TeamModeUi
	{
		private static GameObject? _sliderTemplate;

		private static GameObject? _dropdownTemplate;

		private static Transform? _container;

		private static GameObject? _earlyEndRow;

		private static GameObject? _header;

		private static GameObject? _rules;

		private static readonly List<Selectable> _controls = new List<Selectable>();

		public static Transform? RulesContent
		{
			get
			{
				if (!((Object)(object)_container != (Object)null))
				{
					return null;
				}
				return _container.parent;
			}
		}

		public static void SetSection(GameObject header, GameObject rules)
		{
			_header = header;
			_rules = rules;
		}

		public static void Build(GameObject sliderTemplate, GameObject? dropdownTemplate, Transform container)
		{
			_sliderTemplate = sliderTemplate;
			_dropdownTemplate = dropdownTemplate;
			_container = container;
			_controls.Clear();
			_earlyEndRow = null;
			if ((Object)(object)dropdownTemplate != (Object)null)
			{
				AddChoice(dropdownTemplate, container, Lang.Get("Score d'équipe", "Team score"), new List<string>
				{
					Lang.Get("Points", "Points"),
					Lang.Get("Manches", "Rounds")
				}, Plugin.RoundsMode ? 1 : 0, delegate(int v)
				{
					Plugin.RoundsMode = v == 1;
					if ((Object)(object)_earlyEndRow != (Object)null)
					{
						_earlyEndRow.SetActive(Plugin.RoundsMode);
					}
					CustomScoringBridge.Update();
					Plugin.Log.LogInfo((object)("[TeamMode] Team score → " + (Plugin.RoundsMode ? "Rounds" : "Individual + sum")));
					if (NetworkServer.active)
					{
						Plugin.Log.LogInfo((object)"[Sync/Host] Score mode changed → broadcasting full state");
						TeamSyncManager.BroadcastFullState();
					}
				});
				_earlyEndRow = AddToggle(dropdownTemplate, container, Lang.Get("Fin du trou anticipée", "End hole early"), Plugin.EarlyHoleEnd, delegate(bool v)
				{
					Plugin.EarlyHoleEnd = v;
					Plugin.Log.LogInfo((object)("[TeamMode] End hole early → " + (v ? "ON" : "OFF")));
				});
				_earlyEndRow.SetActive(Plugin.RoundsMode);
				AddToggle(dropdownTemplate, container, Lang.Get("Tir ami", "Friendly Fire"), Plugin.FriendlyFireEnabled, delegate(bool v)
				{
					Plugin.FriendlyFireEnabled = v;
					Plugin.Log.LogInfo((object)("[FriendlyFire] " + (v ? "ENABLED ✅ — teammates can hurt each other" : "DISABLED ❌ — teammates are protected")));
					if (NetworkServer.active)
					{
						Plugin.Log.LogInfo((object)"[Sync/Host] FriendlyFire toggled → broadcasting full state");
						TeamSyncManager.BroadcastFullState();
					}
				});
			}
			AddSlider(sliderTemplate, container, Lang.Get("Équipes", "Teams"), Plugin.TeamCount, 1, 4, 1, delegate(int v)
			{
				Plugin.TeamCount = v;
				Plugin.Log.LogInfo((object)$"\ud83c\udff7\ufe0f Team count → {v}");
				RebuildPlayerDropdowns();
				if (NetworkServer.active)
				{
					Plugin.Log.LogInfo((object)"[Sync/Host] TeamCount changed → broadcasting full state");
					TeamSyncManager.BroadcastFullState();
				}
			});
			RebuildPlayerDropdowns();
			UpdateSection();
		}

		public static void UpdateSection()
		{
			_controls.RemoveAll((Selectable c) => (Object)(object)c == (Object)null);
			foreach (Selectable control in _controls)
			{
				control.interactable = true;
			}
			bool enabledSetting = Plugin.EnabledSetting;
			if ((Object)(object)_header != (Object)null)
			{
				_header.SetActive(enabledSetting);
			}
			if ((Object)(object)_rules != (Object)null)
			{
				_rules.SetActive(enabledSetting);
			}
		}

		public static void RebuildPlayerDropdowns()
		{
			if ((Object)(object)_dropdownTemplate == (Object)null || (Object)(object)_container == (Object)null)
			{
				return;
			}
			for (int num = _container.childCount - 1; num >= 0; num--)
			{
				Transform child = _container.GetChild(num);
				if (((Object)child).name.StartsWith("TM_Player_"))
				{
					Object.Destroy((Object)(object)((Component)child).gameObject);
				}
			}
			List<(ulong, string)> connectedPlayers = GetConnectedPlayers();
			Plugin.Log.LogInfo((object)$"\ud83d\udc65 {connectedPlayers.Count} player(s) found for Team Mode");
			foreach (var item3 in connectedPlayers)
			{
				ulong item = item3.Item1;
				string item2 = item3.Item2;
				ulong capturedGuid = item;
				string capturedName = item2;
				int team = Plugin.GetTeam(item);
				AddPlayerDropdown(_dropdownTemplate, _container, item2, team, capturedGuid, delegate(int v)
				{
					Plugin.PlayerTeams[capturedGuid] = v;
					Plugin.Log.LogInfo((object)("\ud83d\udc64 " + capturedName + " → Team " + Plugin.TeamNames[v]));
					if (NetworkServer.active)
					{
						Plugin.Log.LogInfo((object)$"[Sync/Host] Assignment changed → broadcasting guid={capturedGuid} team={Plugin.TeamNames[v]}");
						TeamSyncManager.BroadcastAssignment(capturedGuid, v);
					}
				});
			}
			UpdateSection();
		}

		public static List<(ulong guid, string name)> GetConnectedPlayers()
		{
			List<(ulong, string)> list = new List<(ulong, string)>();
			try
			{
				Type type = AccessTools.TypeByName("GameManager");
				object obj = type?.GetProperty("LocalPlayerInfo", BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy)?.GetValue(null);
				if (obj != null)
				{
					object obj2 = obj.GetType().GetProperty("PlayerId", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj);
					if (obj2 != null)
					{
						ulong item = (ulong)(obj2.GetType().GetProperty("Guid", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj2) ?? ((object)0uL));
						string item2 = (string)(obj2.GetType().GetProperty("PlayerName", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj2) ?? "Local");
						list.Add((item, item2));
					}
				}
				object obj3 = type?.GetProperty("RemotePlayerPerConnectionId", BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy)?.GetValue(null);
				if (obj3 != null)
				{
					object obj4 = obj3.GetType().GetProperty("Values")?.GetValue(obj3);
					if (obj4 is IEnumerable enumerable)
					{
						foreach (object item5 in enumerable)
						{
							object obj5 = item5.GetType().GetProperty("PlayerId", BindingFlags.Instance | BindingFlags.Public)?.GetValue(item5);
							if (obj5 != null)
							{
								ulong item3 = (ulong)(obj5.GetType().GetProperty("Guid", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj5) ?? ((object)0uL));
								string item4 = (string)(obj5.GetType().GetProperty("PlayerName", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj5) ?? "Remote");
								list.Add((item3, item4));
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("GetConnectedPlayers: " + ex.Message));
			}
			return list;
		}

		private static void FullOpacity(GameObject row)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown