Decompiled source of Sharks and Minnows v0.1.2

com.github.glarmer.SharksAndMinnows.dll

Decompiled 18 hours ago
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using Gamemode_Lib;
using Gamemode_Lib.Patches.Features;
using Gamemode_Lib.Teams;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using SharksAndMinnows.Patches;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: IgnoresAccessChecksTo("GameAssembly")]
[assembly: IgnoresAccessChecksTo("SharedAssembly")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.github.glarmer.SharksAndMinnows")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("com.github.glarmer.SharksAndMinnows")]
[assembly: AssemblyTitle("SharksAndMinnows")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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")]
	[Microsoft.CodeAnalysis.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")]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace SharksAndMinnows
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.github.glarmer.SharksAndMinnows", "SharksAndMinnows", "0.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin Instance;

		public const string Id = "com.github.glarmer.SharksAndMinnows";

		internal static ManualLogSource Log { get; private set; }

		public static string Name => "SharksAndMinnows";

		public static string Version => "0.1.0";

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			GameModeUtilities.RegisterGameMode((IGamemode)(object)new SharksAndMinnows());
			Log.LogInfo((object)("Plugin " + Name + " is loaded!"));
		}
	}
	public class SharksAndMinnows : IGamemode
	{
		public static int SHARKS_TEAM = 1;

		public static int MINNOWS_TEAM = 0;

		public float MINNOWS_SPEED_MULTIPLIER = 2f;

		public Harmony GamemodeHarmony { get; init; }

		public string Name { get; } = "SharksAndMinnows";


		public string ModId { get; } = "com.github.glarmer.SharksAndMinnows";


		public int MinPlayers { get; } = 2;


		public int MaxPlayers { get; } = 200;


		public bool IsTeamBased { get; } = true;


		public bool IsNormalStartProcedure { get; } = true;


		public int TeamCount { get; } = 2;


		public string Description { get; } = "The Minnows must score their ball at all costs, but can they do it with the Sharks hunting them? Only time will tell!";


		public SharksAndMinnows()
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			GamemodeHarmony = new Harmony(((IGamemode)this).GameModeId);
		}

		public void OnGameStart()
		{
			StopAutoNextHole.END_GAME = false;
			GamemodeHarmony.PatchAll(typeof(ItemSpawnerPatches));
			GamemodeHarmony.PatchAll(typeof(HoleProgressBarUIPatches));
			GamemodeHarmony.PatchAll(typeof(StopCountdownToMatchEnd));
			GamemodeHarmony.PatchAll(typeof(StopAutoNextHole));
			GamemodeHarmony.PatchAll(typeof(PlayerGolferPatches));
			GamemodeHarmony.PatchAll(typeof(PlayerMovementPatches));
			GamemodeHarmony.PatchAll(typeof(AheadOfBallMessagePatches));
			PlayerTag.PlayerTagged += OnPlayerTagged;
			if ((Object)(object)TeamManager.Instance != (Object)null)
			{
				TeamManager.Instance.AllPlayersOnOneTeam += OnAllPlayersOnOneTeam;
			}
			GameObject val = GameObject.Find("Hole progress bar");
			if ((Object)(object)val != (Object)null)
			{
				val.SetActive(false);
			}
			TeamManager instance = TeamManager.Instance;
			if ((Object)(object)instance.LocalPlayerTeam != (Object)null && instance.LocalPlayerTeam.teamId == SHARKS_TEAM)
			{
				SetMoveSpeedsShark(MINNOWS_SPEED_MULTIPLIER / 2f);
			}
			else
			{
				SetMoveSpeedsMinnow(MINNOWS_SPEED_MULTIPLIER);
			}
		}

		private void OnAllPlayersOnOneTeam(TeamData teamData)
		{
			//IL_0024: 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_0030: 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)
			if (teamData.ID == SHARKS_TEAM)
			{
				StopAutoNextHole.END_GAME = true;
				PlayerGolferPatches.ResetMinnowScoreTracking();
				MatchState matchState = SingletonNetworkBehaviour<CourseManager>.Instance.matchState;
				SingletonNetworkBehaviour<CourseManager>.Instance.matchState = (MatchState)6;
				SingletonNetworkBehaviour<CourseManager>.Instance.OnMatchStateChanged(matchState, (MatchState)6);
			}
		}

		public static void OnAllMinnowsScored()
		{
			//IL_001c: 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_0028: 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)
			Plugin.Log.LogInfo((object)"[SharksAndMinnows] All Minnows have scored. Resetting Minnow score tracking.");
			PlayerGolferPatches.ResetMinnowScoreTracking();
			MatchState matchState = SingletonNetworkBehaviour<CourseManager>.Instance.matchState;
			SingletonNetworkBehaviour<CourseManager>.Instance.matchState = (MatchState)6;
			SingletonNetworkBehaviour<CourseManager>.Instance.OnMatchStateChanged(matchState, (MatchState)6);
		}

		public void OnGameEnd()
		{
			PlayerTag.PlayerTagged -= OnPlayerTagged;
			if ((Object)(object)TeamManager.Instance != (Object)null)
			{
				TeamManager.Instance.AllPlayersOnOneTeam -= OnAllPlayersOnOneTeam;
			}
			GamemodeHarmony.UnpatchSelf();
		}

		public bool CanStart(int playerCount)
		{
			return true;
		}

		public static void SetMoveSpeedsMinnow(float multiplier)
		{
			PlayerMovementSettings playerMovementSettings = SingletonBehaviour<GameManager>.Instance.playerMovementSettings;
			playerMovementSettings.DefaultMoveSpeed *= multiplier;
			playerMovementSettings.WalkMoveSpeed *= multiplier;
			playerMovementSettings.WadingInWaterSpeed *= multiplier;
			playerMovementSettings.SpeedBoostSpeedFactor *= multiplier;
			playerMovementSettings.DiveHorizontalSpeed *= multiplier;
			playerMovementSettings.DiveGetUpDuration *= 0.75f;
			playerMovementSettings.JumpUpwardsSpeed *= multiplier;
		}

		public static void SetMoveSpeedsShark(float multiplier)
		{
			PlayerMovementSettings playerMovementSettings = SingletonBehaviour<GameManager>.Instance.playerMovementSettings;
			playerMovementSettings.DefaultMoveSpeed *= multiplier;
			playerMovementSettings.WalkMoveSpeed *= multiplier;
			playerMovementSettings.WadingInWaterSpeed *= multiplier;
			playerMovementSettings.SpeedBoostSpeedFactor *= multiplier;
			playerMovementSettings.DiveUpwardsSpeed *= multiplier;
			playerMovementSettings.DiveHorizontalSpeed *= multiplier * 2.5f;
		}

		private static void OnPlayerTagged(PlayerInfo victim, PlayerInfo hitter, TagHitType hitType)
		{
			if (!NetworkServer.active || (Object)(object)victim == (Object)null || (Object)(object)hitter == (Object)null)
			{
				return;
			}
			TeamManager instance = TeamManager.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				PlayerTeam val = instance.EnsurePlayerTeam(victim);
				PlayerTeam val2 = instance.EnsurePlayerTeam(hitter);
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null) && val2.teamId == SHARKS_TEAM && val.teamId == MINNOWS_TEAM)
				{
					val.SetLocalTeam(SHARKS_TEAM);
					instance.SendTeamToClients(victim, SHARKS_TEAM);
				}
			}
		}

		void IGamemode.set_GamemodeHarmony(Harmony value)
		{
			GamemodeHarmony = value;
		}
	}
}
namespace SharksAndMinnows.Patches
{
	public class AheadOfBallMessagePatches
	{
		[HarmonyPatch(typeof(AheadOfBallMessage), "Update")]
		[HarmonyPrefix]
		public static void Update_Prefix(AheadOfBallMessage __instance)
		{
			if (TeamManager.Instance.LocalPlayerTeam.teamId == SharksAndMinnows.SHARKS_TEAM)
			{
				if (SingletonBehaviour<RestartPrompt>.HasInstance)
				{
					RestartPrompt instance = SingletonBehaviour<RestartPrompt>.Instance;
					Object.Destroy((Object)(object)instance);
				}
				Transform val = ((Component)__instance).transform.Find("Background");
				if (PlayerMovementPatches._timeInZone != 0f)
				{
					TextMeshProUGUI component = ((Component)val.Find("Message")).GetComponent<TextMeshProUGUI>();
					int num = Mathf.CeilToInt(PlayerMovementPatches._timeInZone + PlayerMovementPatches._maxTimeInZone - Time.time);
					num = Mathf.Max(num, 0);
					((TMP_Text)component).text = $"Turn back Sharky! \n {num}";
					__instance.ShowInternal();
				}
				else
				{
					__instance.HideInternal();
				}
			}
		}
	}
	public class HoleProgressBarUIPatches
	{
		[HarmonyPatch(typeof(HoleProgressBarUi), "Awake")]
		[HarmonyPrefix]
		public static bool Awake_Prefix(HoleProgressBarUi __instance)
		{
			((Component)((Component)__instance).transform).gameObject.SetActive(false);
			return false;
		}

		[HarmonyPatch(typeof(HoleProgressBarUi), "Start")]
		[HarmonyPrefix]
		public static bool Start_Prefix(HoleProgressBarUi __instance)
		{
			((Component)((Component)__instance).transform).gameObject.SetActive(false);
			return false;
		}
	}
	public class ItemSpawnerPatches
	{
		[HarmonyPatch(typeof(ItemSpawner), "OnTriggerEnter")]
		[HarmonyPrefix]
		public static bool OnTriggerEnter_Prefix(ItemSpawner __instance, Collider other)
		{
			PlayerTeam val = default(PlayerTeam);
			ComponentExtensions.TryGetComponentInParent<PlayerTeam>((Component)(object)other, ref val, true);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			if (val.teamId == SharksAndMinnows.MINNOWS_TEAM)
			{
				return false;
			}
			return true;
		}
	}
	public class PlayerGolferPatches
	{
		private static readonly HashSet<ulong> _minnowRoster = new HashSet<ulong>();

		private static readonly HashSet<ulong> _minnowsThatScored = new HashSet<ulong>();

		internal static void ResetMinnowScoreTracking()
		{
			_minnowRoster.Clear();
			_minnowsThatScored.Clear();
		}

		[HarmonyPatch(typeof(PlayerGolfer), "InformScored")]
		[HarmonyPrefix]
		public static void InformScored_Prefix(PlayerGolfer __instance)
		{
			if (!NetworkServer.active)
			{
				return;
			}
			TeamManager instance = TeamManager.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			PlayerInfo val = (((Object)(object)__instance != (Object)null) ? __instance.PlayerInfo : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			PlayerTeam val2 = instance.EnsurePlayerTeam(val);
			if ((Object)(object)val2 == (Object)null || val2.teamId != SharksAndMinnows.MINNOWS_TEAM)
			{
				return;
			}
			if (_minnowRoster.Count == 0)
			{
				for (int num = instance.Players.Count - 1; num >= 0; num--)
				{
					PlayerTeam val3 = instance.Players[num];
					if ((Object)(object)val3 == (Object)null)
					{
						instance.Players.RemoveAt(num);
					}
					else if (val3.teamId == SharksAndMinnows.MINNOWS_TEAM && !((Object)(object)val3.playerInfo == (Object)null))
					{
						_minnowRoster.Add(val3.playerInfo.PlayerId.guid);
					}
				}
			}
			_minnowsThatScored.Add(val.PlayerId.guid);
			if (_minnowRoster.Count > 0 && _minnowsThatScored.IsSupersetOf(_minnowRoster))
			{
				SharksAndMinnows.OnAllMinnowsScored();
			}
		}
	}
	public class PlayerMovementPatches
	{
		internal static float _timeInZone = 0f;

		internal static readonly float _maxTimeInZone = 2f;

		[HarmonyPatch(typeof(PlayerMovement), "Update")]
		[HarmonyPostfix]
		public static void InformScored_Prefix(PlayerMovement __instance)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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)
			if (!((NetworkBehaviour)__instance.PlayerInfo).isLocalPlayer || TeamManager.Instance.LocalPlayerTeam.teamId != SharksAndMinnows.SHARKS_TEAM)
			{
				return;
			}
			float num = 0f;
			if ((Object)(object)__instance.PlayerInfo == (Object)null || !GolfHoleManager.HasMaxReferenceDistance)
			{
				num = 1f;
			}
			else
			{
				Vector3 val = ((Component)__instance.PlayerInfo).transform.position - ((Component)GolfHoleManager.MainHole).transform.position;
				num = 1f - BMath.Clamp01(((Vector3)(ref val)).magnitude / GolfHoleManager.MaxReferenceDistance);
			}
			if (num >= 0.85f)
			{
				if (_timeInZone == 0f)
				{
					_timeInZone = Time.time;
					Plugin.Log.LogInfo((object)"I am sharky in the protected area!");
				}
				else if (Time.time > _timeInZone + _maxTimeInZone)
				{
					__instance.TryBeginRespawn(false, (RespawnTarget)0);
					Plugin.Log.LogInfo((object)"I am a bad shark, teleporting back!");
				}
			}
			else
			{
				_timeInZone = 0f;
			}
		}
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ConstantExpectedAttribute : Attribute
	{
		public object? Min { get; set; }

		public object? Max { get; set; }
	}
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ExperimentalAttribute : Attribute
	{
		public string DiagnosticId { get; }

		public string? UrlFormat { get; set; }

		public ExperimentalAttribute(string diagnosticId)
		{
			DiagnosticId = diagnosticId;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	internal sealed class MemberNotNullAttribute : Attribute
	{
		public string[] Members { get; }

		public MemberNotNullAttribute(string member)
		{
			Members = new string[1] { member };
		}

		public MemberNotNullAttribute(params string[] members)
		{
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	internal sealed class MemberNotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public string[] Members { get; }

		public MemberNotNullWhenAttribute(bool returnValue, string member)
		{
			ReturnValue = returnValue;
			Members = new string[1] { member };
		}

		public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
		{
			ReturnValue = returnValue;
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SetsRequiredMembersAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class StringSyntaxAttribute : Attribute
	{
		public const string CompositeFormat = "CompositeFormat";

		public const string DateOnlyFormat = "DateOnlyFormat";

		public const string DateTimeFormat = "DateTimeFormat";

		public const string EnumFormat = "EnumFormat";

		public const string GuidFormat = "GuidFormat";

		public const string Json = "Json";

		public const string NumericFormat = "NumericFormat";

		public const string Regex = "Regex";

		public const string TimeOnlyFormat = "TimeOnlyFormat";

		public const string TimeSpanFormat = "TimeSpanFormat";

		public const string Uri = "Uri";

		public const string Xml = "Xml";

		public string Syntax { get; }

		public object?[] Arguments { get; }

		public StringSyntaxAttribute(string syntax)
		{
			Syntax = syntax;
			Arguments = new object[0];
		}

		public StringSyntaxAttribute(string syntax, params object?[] arguments)
		{
			Syntax = syntax;
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class UnscopedRefAttribute : Attribute
	{
	}
}
namespace System.Runtime.Versioning
{
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresPreviewFeaturesAttribute : Attribute
	{
		public string? Message { get; }

		public string? Url { get; set; }

		public RequiresPreviewFeaturesAttribute()
		{
		}

		public RequiresPreviewFeaturesAttribute(string? message)
		{
			Message = message;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CallerArgumentExpressionAttribute : Attribute
	{
		public string ParameterName { get; }

		public CallerArgumentExpressionAttribute(string parameterName)
		{
			ParameterName = parameterName;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CollectionBuilderAttribute : Attribute
	{
		public Type BuilderType { get; }

		public string MethodName { get; }

		public CollectionBuilderAttribute(Type builderType, string methodName)
		{
			BuilderType = builderType;
			MethodName = methodName;
		}
	}
	[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CompilerFeatureRequiredAttribute : Attribute
	{
		public const string RefStructs = "RefStructs";

		public const string RequiredMembers = "RequiredMembers";

		public string FeatureName { get; }

		public bool IsOptional { get; set; }

		public CompilerFeatureRequiredAttribute(string featureName)
		{
			FeatureName = featureName;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute
	{
		public string[] Arguments { get; }

		public InterpolatedStringHandlerArgumentAttribute(string argument)
		{
			Arguments = new string[1] { argument };
		}

		public InterpolatedStringHandlerArgumentAttribute(params string[] arguments)
		{
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerAttribute : Attribute
	{
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal static class IsExternalInit
	{
	}
	[AttributeUsage(AttributeTargets.Method, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ModuleInitializerAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class OverloadResolutionPriorityAttribute : Attribute
	{
		public int Priority { get; }

		public OverloadResolutionPriorityAttribute(int priority)
		{
			Priority = priority;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ParamCollectionAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiredMemberAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresLocationAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SkipLocalsInitAttribute : Attribute
	{
	}
}

com.github.glarmer.Gamemode_Lib.dll

Decompiled 18 hours ago
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using BepInEx;
using BepInEx.Logging;
using Cysharp.Threading.Tasks;
using Cysharp.Threading.Tasks.CompilerServices;
using Gamemode_Lib.Patches;
using Gamemode_Lib.Teams;
using Gamemode_Lib.TestUsage;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Pool;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: IgnoresAccessChecksTo("GameAssembly")]
[assembly: IgnoresAccessChecksTo("SharedAssembly")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.github.glarmer.Gamemode_Lib")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+2b949b9855c92c18f7297654e667d88b4df047ed")]
[assembly: AssemblyProduct("com.github.glarmer.Gamemode_Lib")]
[assembly: AssemblyTitle("Gamemode_Lib")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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")]
	[Microsoft.CodeAnalysis.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")]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace Gamemode_Lib
{
	public static class GameModeUtilities
	{
		internal static Dictionary<string, IGamemode> Modes { get; } = new Dictionary<string, IGamemode>();


		internal static string CurrentGamemodeId { get; set; }

		public static void RegisterGameMode(IGamemode gamemode)
		{
			if (Modes != null)
			{
				if (Modes.ContainsKey(gamemode.GameModeId))
				{
					Plugin.Log.LogError((object)("Gamemode with same ID: " + gamemode.GameModeId + " has already been registered! We will not re-register..."));
					return;
				}
				Modes.Add(gamemode.GameModeId, gamemode);
				if (gamemode.IsTeamBased)
				{
				}
				Plugin.Log.LogInfo((object)("Gamemode ID: " + gamemode.GameModeId + " has been registered!"));
			}
			else
			{
				Plugin.Log.LogError((object)("Gamemode dictionary was null! " + gamemode.Name + " is not loaded..."));
			}
		}

		public static void ApplyGamemodeStartMessage(GamemodeStartMessage msg)
		{
			Modes[msg.GamemodeId].OnGameStart();
		}
	}
	public interface IGamemode
	{
		Harmony GamemodeHarmony { get; init; }

		string Name { get; }

		string ModId { get; }

		string GameModeId => ModId + ":" + Name;

		int MinPlayers { get; }

		int MaxPlayers { get; }

		bool IsTeamBased { get; }

		bool IsNormalStartProcedure { get; }

		int TeamCount { get; }

		string Description { get; }

		void OnGameStart();

		void OnGameEnd();

		bool CanStart(int playerCount);
	}
	public static class NetworkMessageBootstrap
	{
		private static bool _registered;

		public static void Register()
		{
			if (!_registered)
			{
				_registered = true;
				Writer<TeamAssignMessage>.write = delegate(NetworkWriter writer, TeamAssignMessage msg)
				{
					NetworkWriterExtensions.WriteULong(writer, msg.PlayerGuid);
					NetworkWriterExtensions.WriteInt(writer, msg.TeamId);
				};
				Reader<TeamAssignMessage>.read = delegate(NetworkReader reader)
				{
					TeamAssignMessage result3 = default(TeamAssignMessage);
					result3.PlayerGuid = NetworkReaderExtensions.ReadULong(reader);
					result3.TeamId = NetworkReaderExtensions.ReadInt(reader);
					return result3;
				};
				NetworkClient.RegisterHandler<TeamAssignMessage>((Action<TeamAssignMessage>)delegate(TeamAssignMessage msg)
				{
					TeamManager.Instance?.ApplyTeamMessage(msg);
				}, true);
				Writer<TeamDefinitionMessage>.write = delegate(NetworkWriter writer, TeamDefinitionMessage msg)
				{
					//IL_0010: Unknown result type (might be due to invalid IL or missing references)
					NetworkWriterExtensions.WriteInt(writer, msg.ID);
					NetworkWriterExtensions.WriteColor(writer, msg.Color);
					NetworkWriterExtensions.WriteString(writer, msg.Name);
				};
				Reader<TeamDefinitionMessage>.read = delegate(NetworkReader reader)
				{
					//IL_0018: 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)
					TeamDefinitionMessage result2 = default(TeamDefinitionMessage);
					result2.ID = NetworkReaderExtensions.ReadInt(reader);
					result2.Color = NetworkReaderExtensions.ReadColor(reader);
					result2.Name = NetworkReaderExtensions.ReadString(reader);
					return result2;
				};
				NetworkClient.RegisterHandler<TeamDefinitionMessage>((Action<TeamDefinitionMessage>)delegate(TeamDefinitionMessage msg)
				{
					TeamManager.Instance?.ApplyTeamDefinitionMessage(msg);
				}, true);
				Writer<GamemodeStartMessage>.write = delegate(NetworkWriter writer, GamemodeStartMessage msg)
				{
					NetworkWriterExtensions.WriteString(writer, msg.GamemodeId);
				};
				Reader<GamemodeStartMessage>.read = delegate(NetworkReader reader)
				{
					GamemodeStartMessage result = default(GamemodeStartMessage);
					result.GamemodeId = NetworkReaderExtensions.ReadString(reader);
					return result;
				};
				NetworkClient.RegisterHandler<GamemodeStartMessage>((Action<GamemodeStartMessage>)delegate(GamemodeStartMessage msg)
				{
					GameModeUtilities.ApplyGamemodeStartMessage(msg);
				}, true);
				Plugin.Log.LogInfo((object)"[GamemodeLib] Registered team network messages");
			}
		}

		[HarmonyPatch(typeof(BNetworkManager), "OnStartClient")]
		[HarmonyPostfix]
		public static void OnStartClient_Postfix()
		{
			Register();
		}

		[HarmonyPatch(typeof(BNetworkManager), "OnStartServer")]
		[HarmonyPostfix]
		public static void OnStartServer_Postfix()
		{
			Register();
		}

		[HarmonyPatch(typeof(BNetworkManager), "OnDestroy")]
		[HarmonyPrefix]
		public static void OnDestroy_Prefix()
		{
			GameModeUtilities.Modes[GameModeUtilities.CurrentGamemodeId]?.OnGameEnd();
		}
	}
	[BepInPlugin("com.github.glarmer.Gamemode_Lib", "Gamemode_Lib", "0.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal readonly Harmony _harmony = new Harmony("com.github.glarmer.Gamemode_Lib");

		internal static Plugin Instance;

		public const string Id = "com.github.glarmer.Gamemode_Lib";

		internal static ManualLogSource Log { get; private set; }

		public static string Name => "Gamemode_Lib";

		public static string Version => "0.1.0";

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			_harmony.PatchAll(typeof(NetworkMessageBootstrap));
			_harmony.PatchAll(typeof(ScoreboardPatches));
			_harmony.PatchAll(typeof(MatchSetupPlayerPatches));
			Log.LogInfo((object)("Plugin " + Name + " is patching!"));
			Log.LogInfo((object)"[GamemodeLib] is patching GameManager");
			_harmony.PatchAll(typeof(GameManagerPatches));
			Log.LogInfo((object)"[GamemodeLib] is patching MatchSetup");
			_harmony.PatchAll(typeof(MatchSetupMenuPatches));
			Log.LogInfo((object)"[GamemodeLib] is patching PlayerInfo");
			_harmony.PatchAll(typeof(PlayerInfoPatches));
			Log.LogInfo((object)"[GamemodeLib] is loaded and finished patching.");
			Tests tests = new Tests();
		}
	}
}
namespace Gamemode_Lib.TestUsage
{
	public class Tests
	{
		public Tests()
		{
			Plugin.Log.LogInfo((object)"Debug mode loading, creating and activating a fake gamemode!");
			TestGamemode gamemode = new TestGamemode();
			GameModeUtilities.RegisterGameMode(gamemode);
			TestGamemode gamemode2 = new TestGamemode
			{
				IsTeamBased = true,
				Name = "TeamGameModeTest"
			};
			GameModeUtilities.RegisterGameMode(gamemode2);
			Plugin.Log.LogInfo((object)"Debug mode loaded a test gamemode!");
		}
	}
	public class TestGamemode : IGamemode
	{
		public string Name { get; init; } = "TestGameMode";


		public string ModId { get; init; } = "com.github.glarmer.Gamemode_Lib";


		public int MinPlayers { get; init; } = 1;


		public int MaxPlayers { get; init; } = 20;


		public bool IsTeamBased { get; init; } = false;


		public bool IsNormalStartProcedure { get; init; } = false;


		public int TeamCount { get; init; } = 2;


		public string Description { get; init; } = "This is a test gamemode";


		public Harmony GamemodeHarmony { get; init; } = new Harmony("TestGamemode");


		public void OnGameStart()
		{
			Plugin.Log.LogInfo((object)"[TestGamemode] Test Gamemode started!");
		}

		public void OnGameEnd()
		{
			Plugin.Log.LogInfo((object)"[TestGamemode] Test Gamemode ended!");
		}

		public bool CanStart(int playerCount)
		{
			Plugin.Log.LogInfo((object)"[TestGamemode] This is where player count testing would go!");
			return true;
		}
	}
}
namespace Gamemode_Lib.Patches
{
	public class GameManagerPatches
	{
		[HarmonyPatch(typeof(GameManager), "Awake")]
		[HarmonyPostfix]
		public static void Awake_Postfix(GameManager __instance)
		{
			((Component)__instance).gameObject.AddComponent<TeamManager>();
		}
	}
	public class MatchSetupMenuPatches
	{
		private static readonly Dictionary<TMP_Dropdown, Dictionary<int, string>> DropdownMappings = new Dictionary<TMP_Dropdown, Dictionary<int, string>>();

		private static TMP_Dropdown? _tmpDropdown;

		private static IGamemode? _gameMode;

		[HarmonyPatch(typeof(MatchSetupMenu), "SetEnabled")]
		[HarmonyPostfix]
		public static void SetEnabled_Postfix(MatchSetupMenu __instance)
		{
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected O, but got Unknown
			if ((Object)(object)_tmpDropdown == (Object)null)
			{
				_tmpDropdown = ((IEnumerable<TMP_Dropdown>)Object.FindObjectsOfType<TMP_Dropdown>(true)).FirstOrDefault((Func<TMP_Dropdown, bool>)((TMP_Dropdown dropdown) => dropdown.options != null && dropdown.options.Any((OptionData o) => o.text == "Free-for-all")));
				if ((Object)(object)_tmpDropdown == (Object)null)
				{
					Plugin.Log.LogError((object)"[GamemodeLib] Could not find TMP_Dropdown containing 'Free-for-all'");
					return;
				}
			}
			if (DropdownMappings.ContainsKey(_tmpDropdown))
			{
				return;
			}
			Dictionary<int, string> dictionary = new Dictionary<int, string>();
			int num = _tmpDropdown.options.Count;
			foreach (KeyValuePair<string, IGamemode> mode in GameModeUtilities.Modes)
			{
				string key = mode.Key;
				IGamemode value = mode.Value;
				_tmpDropdown.options.Add(new OptionData(value.Name));
				dictionary[num] = key;
				num++;
			}
			_tmpDropdown.RefreshShownValue();
			DropdownMappings[_tmpDropdown] = dictionary;
			((UnityEvent<int>)(object)_tmpDropdown.onValueChanged).AddListener((UnityAction<int>)delegate(int index)
			{
				Plugin.Log.LogInfo((object)("[GamemodeLib] Selected gamemode: " + _tmpDropdown.options[index].text + ")"));
				_gameMode = null;
				if (DropdownMappings[_tmpDropdown].TryGetValue(index, out string value2))
				{
					IGamemode gamemode = (_gameMode = GameModeUtilities.Modes[value2]);
					Plugin.Log.LogInfo((object)("[GamemodeLib] " + gamemode.Name + " is using GamemodeLib. It's ID is... " + gamemode.GameModeId));
					if (NetworkServer.active)
					{
						TeamManager.Instance.ResetTeams();
						TeamManager.Instance.ClearTeamDefinitions();
						if (_gameMode.IsTeamBased)
						{
							TeamManager.Instance.CreateAndAssignTeams(_gameMode.TeamCount);
						}
					}
				}
			});
			Plugin.Log.LogInfo((object)"[GamemodeLib] Gamemodes injected into dropdown");
		}

		[HarmonyPatch(typeof(MatchSetupMenu), "StartOrCancelMatch")]
		[HarmonyPrefix]
		public static bool StartOrCancelMatch_Prefix(MatchSetupMenu __instance)
		{
			if ((Object)(object)_tmpDropdown == (Object)null)
			{
				return true;
			}
			if (_gameMode == null)
			{
				return true;
			}
			if (_gameMode.CanStart(__instance.maxPlayers))
			{
				Plugin.Log.LogInfo((object)"[GamemodeLib] Starting gamemode.");
				if ((Object)(object)TeamManager.Instance != (Object)null)
				{
					TeamManager.Instance.SaveCurrentTeams();
					TeamManager.Instance.TryRefreshLocalPlayerTeam();
					if ((Object)(object)TeamManager.Instance.LocalPlayerTeam == (Object)null)
					{
						Plugin.Log.LogWarning((object)"[GamemodeLib] LocalPlayerTeam is null immediately before OnGameStart()");
					}
				}
				GameModeUtilities.CurrentGamemodeId = _gameMode.GameModeId;
				_gameMode.OnGameStart();
				if (_gameMode.IsNormalStartProcedure)
				{
					return true;
				}
				Plugin.Log.LogInfo((object)"[GamemodeLib] Custom gamemode is chosen, cancelling default start procedure.");
			}
			else
			{
				Plugin.Log.LogError((object)"[GamemodeLib] Invalid choices, not starting gamemode.");
			}
			return false;
		}

		[HarmonyPatch(typeof(MatchSetupMenu), "StartOrCancelMatch")]
		[HarmonyPostfix]
		public static void StartOrCancelMatch_Postfix(MatchSetupMenu __instance)
		{
			TeamManager.Instance.ReloadSavedTeams();
		}
	}
	public class MatchSetupPlayerPatches
	{
		private const string SwapButtonName = "SwapTeamButton";

		[HarmonyPatch(typeof(MatchSetupPlayer), "Update")]
		[HarmonyPostfix]
		public static void Update_Postfix(MatchSetupPlayer __instance)
		{
			UpdateBackground(__instance);
		}

		[HarmonyPatch(typeof(MatchSetupPlayer), "Awake")]
		[HarmonyPostfix]
		public static void Awake_Postfix(MatchSetupPlayer __instance)
		{
			AddSwapButton(__instance);
		}

		private static void UpdateBackground(MatchSetupPlayer playerUI)
		{
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)TeamManager.Instance == (Object)null)
			{
				return;
			}
			ulong guid = playerUI.Guid;
			PlayerTeam playerTeam = null;
			foreach (PlayerTeam player in TeamManager.Instance.Players)
			{
				if ((Object)(object)player == (Object)null || (Object)(object)player.playerInfo == (Object)null || player.playerInfo.PlayerId.guid != guid)
				{
					continue;
				}
				playerTeam = player;
				break;
			}
			if ((Object)(object)playerTeam == (Object)null || !TeamManager.Instance.TryGetTeam(playerTeam.teamId, out TeamData team))
			{
				return;
			}
			Transform val = ((Component)playerUI).transform.Find("Background");
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Image component = ((Component)val).GetComponent<Image>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			((Graphic)component).color = team.Color;
			Transform val2 = ((Component)playerUI).transform.Find("Portrait");
			if (!((Object)(object)val2 == (Object)null))
			{
				Image component2 = ((Component)val2).GetComponent<Image>();
				if (!((Object)(object)component2 == (Object)null))
				{
					((Graphic)component2).color = team.Color * 0.7f;
				}
			}
		}

		private static void AddSwapButton(MatchSetupPlayer ui)
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Expected O, but got Unknown
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Expected O, but got Unknown
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Expected O, but got Unknown
			MatchSetupPlayer ui2 = ui;
			Transform val = ((Component)ui2).transform.Find("Info").Find("Buttons");
			if ((Object)(object)val == (Object)null || (Object)(object)val.Find("SwapTeamButton") != (Object)null)
			{
				return;
			}
			Button kickButton = ui2.kickButton;
			if ((Object)(object)kickButton == (Object)null)
			{
				return;
			}
			GameObject val2 = Object.Instantiate<GameObject>(((Component)kickButton).gameObject, val);
			((Object)val2).name = "SwapTeamButton";
			Button component = val2.GetComponent<Button>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			foreach (Transform item in val2.transform)
			{
				Transform val3 = item;
				Object.Destroy((Object)(object)((Component)val3).gameObject);
			}
			GameObject val4 = new GameObject("Label", new Type[1] { typeof(RectTransform) });
			val4.transform.SetParent(val2.transform, false);
			RectTransform component2 = val4.GetComponent<RectTransform>();
			component2.anchorMin = Vector2.zero;
			component2.anchorMax = Vector2.one;
			component2.offsetMin = Vector2.zero;
			component2.offsetMax = Vector2.zero;
			TextMeshProUGUI val5 = val4.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val5).text = "<->";
			((TMP_Text)val5).alignment = (TextAlignmentOptions)514;
			((TMP_Text)val5).fontSize = 24f;
			((TMP_Text)val5).enableAutoSizing = true;
			((TMP_Text)val5).fontSizeMin = 12f;
			((TMP_Text)val5).fontSizeMax = 28f;
			((Graphic)val5).raycastTarget = false;
			((TMP_Text)val5).font = TMP_Settings.defaultFontAsset;
			Image component3 = val2.GetComponent<Image>();
			if ((Object)(object)component3 != (Object)null)
			{
				component3.sprite = null;
				((Graphic)component3).color = new Color(0.25f, 0.25f, 0.25f, 0.9f);
			}
			LayoutElement val6 = val2.GetComponent<LayoutElement>();
			if ((Object)(object)val6 == (Object)null)
			{
				val6 = val2.AddComponent<LayoutElement>();
			}
			val6.preferredWidth = 60f;
			val6.preferredHeight = 40f;
			((UnityEventBase)component.onClick).RemoveAllListeners();
			((UnityEvent)component.onClick).AddListener((UnityAction)delegate
			{
				OnSwapClicked(ui2);
			});
			val2.SetActive(NetworkServer.active && NetworkClient.active);
		}

		private static void OnSwapClicked(MatchSetupPlayer ui)
		{
			if (!NetworkServer.active)
			{
				return;
			}
			TeamManager instance = TeamManager.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			ulong guid = ui.Guid;
			foreach (PlayerTeam player in instance.Players)
			{
				if ((Object)(object)player == (Object)null || (Object)(object)player.playerInfo == (Object)null || player.playerInfo.PlayerId.guid != guid)
				{
					continue;
				}
				int nextTeam = GetNextTeam(player.teamId, instance);
				player.SetLocalTeam(nextTeam);
				instance.SendTeamToClients(player.playerInfo, nextTeam);
				break;
			}
		}

		private static int GetNextTeam(int current, TeamManager manager)
		{
			if (manager.Teams.Count == 0)
			{
				return -1;
			}
			List<int> list = manager.Teams.Keys.OrderBy((int x) => x).ToList();
			int num = list.IndexOf(current);
			if (num == -1 || num + 1 >= list.Count)
			{
				return list[0];
			}
			return list[num + 1];
		}
	}
	public class PlayerInfoPatches
	{
		[HarmonyPatch(typeof(PlayerInfo), "Start")]
		[HarmonyPostfix]
		public static void Start_Postfix(PlayerInfo __instance)
		{
			TeamManager.Instance?.EnsurePlayerTeam(__instance);
		}

		[HarmonyPatch(typeof(PlayerInfo), "ServerInitializeAsParticipant")]
		[HarmonyPostfix]
		public static void ServerInitializeAsParticipant_Postfix(PlayerInfo __instance)
		{
			TeamManager instance = TeamManager.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				instance.EnsurePlayerTeam(__instance);
				instance.TryApplySavedTeam(__instance);
			}
		}
	}
	public class ScoreboardPatches
	{
		private class ColorCache
		{
			public Color background;

			public Color statusBackground;

			public Color infoBackground;

			public Color statsBackground;

			public Color stripes;
		}

		private static readonly Dictionary<ScoreboardEntry, ColorCache> OriginalColors = new Dictionary<ScoreboardEntry, ColorCache>();

		[HarmonyPatch(typeof(ScoreboardEntry), "PopulateWith")]
		[HarmonyPostfix]
		public static void PopulateWith_Postfix(ScoreboardEntry __instance, PlayerState playerState)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			CacheOriginalColors(__instance);
			ApplyTeamColors(__instance, playerState);
		}

		private static void CacheOriginalColors(ScoreboardEntry entry)
		{
			//IL_0024: 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_0035: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			if (!OriginalColors.ContainsKey(entry))
			{
				OriginalColors[entry] = new ColorCache
				{
					background = ((Graphic)entry.background).color,
					statusBackground = ((Graphic)entry.statusBackground).color,
					infoBackground = ((Graphic)entry.infoBackground).color,
					statsBackground = ((Graphic)entry.statsBackground).color,
					stripes = ((Graphic)entry.stripes).color
				};
			}
		}

		private static void ApplyTeamColors(ScoreboardEntry entry, PlayerState state)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: 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_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: 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_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			PlayerInfo val = null;
			if (!GameManager.TryFindPlayerByGuid(state.playerGuid, ref val))
			{
				RestoreOriginalColors(entry);
				return;
			}
			if ((Object)(object)val == (Object)null)
			{
				RestoreOriginalColors(entry);
				return;
			}
			PlayerTeam component = ((Component)val).GetComponent<PlayerTeam>();
			if ((Object)(object)component == (Object)null || component.teamId < 0)
			{
				RestoreOriginalColors(entry);
				return;
			}
			if ((Object)(object)TeamManager.Instance == (Object)null)
			{
				RestoreOriginalColors(entry);
				return;
			}
			if (!TeamManager.Instance.TryGetTeam(component.teamId, out TeamData team))
			{
				RestoreOriginalColors(entry);
				return;
			}
			Color color = team.Color;
			Color background = OriginalColors[entry].background;
			((Graphic)entry.background).color = Color.Lerp(background, color, 0.5f);
			((Graphic)entry.statusBackground).color = color;
			((Graphic)entry.infoBackground).color = color;
			Color color2 = color;
			color2.a *= 0.5f;
			((Graphic)entry.statsBackground).color = color2;
			Color stripes = OriginalColors[entry].stripes;
			Color color3 = Color.Lerp(stripes, color, 0.5f);
			color3.a = stripes.a;
			((Graphic)entry.stripes).color = color3;
		}

		private static void RestoreOriginalColors(ScoreboardEntry entry)
		{
			//IL_001e: 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_0042: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			if (OriginalColors.TryGetValue(entry, out ColorCache value))
			{
				((Graphic)entry.background).color = value.background;
				((Graphic)entry.statusBackground).color = value.statusBackground;
				((Graphic)entry.infoBackground).color = value.infoBackground;
				((Graphic)entry.statsBackground).color = value.statsBackground;
				((Graphic)entry.stripes).color = value.stripes;
			}
		}
	}
}
namespace Gamemode_Lib.Patches.Features
{
	public class StopAutoNextHole
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__OnNextClicked;
		}

		[CompilerGenerated]
		private sealed class <FixLayoutNextFrame>d__4 : IAsyncStateMachine
		{
			public int <>1__state;

			public AsyncUniTaskMethodBuilder <>t__builder;

			public RectTransform rect;

			private Awaiter <>u__1;

			private void MoveNext()
			{
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_0057: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: 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_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: 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_0031: Unknown result type (might be due to invalid IL or missing references)
				int num = <>1__state;
				try
				{
					Awaiter awaiter;
					if (num != 0)
					{
						YieldAwaitable val = UniTask.Yield();
						awaiter = ((YieldAwaitable)(ref val)).GetAwaiter();
						if (!((Awaiter)(ref awaiter)).IsCompleted)
						{
							num = (<>1__state = 0);
							<>u__1 = awaiter;
							<FixLayoutNextFrame>d__4 <FixLayoutNextFrame>d__ = this;
							((AsyncUniTaskMethodBuilder)(ref <>t__builder)).AwaitUnsafeOnCompleted<Awaiter, <FixLayoutNextFrame>d__4>(ref awaiter, ref <FixLayoutNextFrame>d__);
							return;
						}
					}
					else
					{
						awaiter = <>u__1;
						<>u__1 = default(Awaiter);
						num = (<>1__state = -1);
					}
					((Awaiter)(ref awaiter)).GetResult();
					if (!((Object)(object)rect == (Object)null))
					{
						LayoutRebuilder.ForceRebuildLayoutImmediate(rect);
						Canvas.ForceUpdateCanvases();
					}
				}
				catch (Exception exception)
				{
					<>1__state = -2;
					((AsyncUniTaskMethodBuilder)(ref <>t__builder)).SetException(exception);
					return;
				}
				<>1__state = -2;
				((AsyncUniTaskMethodBuilder)(ref <>t__builder)).SetResult();
			}

			void IAsyncStateMachine.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				this.MoveNext();
			}

			[DebuggerHidden]
			private void SetStateMachine(IAsyncStateMachine stateMachine)
			{
			}

			void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
			{
				//ILSpy generated this explicit interface implementation from .override directive in SetStateMachine
				this.SetStateMachine(stateMachine);
			}
		}

		private static GameObject nextButtonInstance;

		public static bool END_GAME;

		[HarmonyPatch(typeof(CourseManager), "OnMatchStateChanged")]
		[HarmonyPrefix]
		public static bool OnMatchStateChanged_Prefix(CourseManager __instance, ref MatchState currentState)
		{
			if ((int)currentState == 6)
			{
				currentState = (MatchState)4;
				ServerInitiateMatchFinish(__instance);
				CreateNextButton();
				return false;
			}
			return true;
		}

		public static void CreateNextButton()
		{
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: 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_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Expected O, but got Unknown
			if (!NetworkServer.active || !NetworkClient.active || (Object)(object)nextButtonInstance != (Object)null)
			{
				return;
			}
			GameObject val = ((IEnumerable<GameObject>)Resources.FindObjectsOfTypeAll<GameObject>()).FirstOrDefault((Func<GameObject, bool>)((GameObject o) => ((Object)o).name == "Message Button"));
			if ((Object)(object)val == (Object)null)
			{
				Debug.LogError((object)"Message Button not found!");
				return;
			}
			Canvas val2 = ((IEnumerable<Canvas>)Object.FindObjectsOfType<Canvas>()).FirstOrDefault((Func<Canvas, bool>)((Canvas c) => ((Behaviour)c).isActiveAndEnabled && (int)c.renderMode != 2));
			if ((Object)(object)val2 == (Object)null)
			{
				Debug.LogError((object)"Canvas not found!");
				return;
			}
			nextButtonInstance = Object.Instantiate<GameObject>(val);
			((Object)nextButtonInstance).name = "Next Button";
			nextButtonInstance.transform.SetParent(((Component)val2).transform, false);
			RectTransform component = nextButtonInstance.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0.5f, 0f);
			component.anchorMax = new Vector2(0.5f, 0f);
			component.pivot = new Vector2(0.5f, 0.5f);
			component.anchoredPosition = new Vector2(0f, 120f);
			((Transform)component).localScale = Vector3.one;
			component.sizeDelta = val.GetComponent<RectTransform>().sizeDelta;
			nextButtonInstance.SetActive(true);
			CanvasGroup[] componentsInChildren = nextButtonInstance.GetComponentsInChildren<CanvasGroup>(true);
			foreach (CanvasGroup val3 in componentsInChildren)
			{
				val3.alpha = 1f;
				val3.interactable = true;
				val3.blocksRaycasts = true;
			}
			Graphic[] componentsInChildren2 = nextButtonInstance.GetComponentsInChildren<Graphic>(true);
			foreach (Graphic val4 in componentsInChildren2)
			{
				((Behaviour)val4).enabled = true;
			}
			TextMeshProUGUI componentInChildren = nextButtonInstance.GetComponentInChildren<TextMeshProUGUI>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				((TMP_Text)componentInChildren).text = "Next";
				((TMP_Text)componentInChildren).enableWordWrapping = false;
				((TMP_Text)componentInChildren).alignment = (TextAlignmentOptions)514;
			}
			Button component2 = nextButtonInstance.GetComponent<Button>();
			if ((Object)(object)component2 != (Object)null)
			{
				((UnityEventBase)component2.onClick).RemoveAllListeners();
				ButtonClickedEvent onClick = component2.onClick;
				object obj = <>O.<0>__OnNextClicked;
				if (obj == null)
				{
					UnityAction val5 = OnNextClicked;
					<>O.<0>__OnNextClicked = val5;
					obj = (object)val5;
				}
				((UnityEvent)onClick).AddListener((UnityAction)obj);
			}
			UniTaskExtensions.Forget(FixLayoutNextFrame(component));
			ShowCursor();
		}

		[AsyncStateMachine(typeof(<FixLayoutNextFrame>d__4))]
		[DebuggerStepThrough]
		private static UniTask FixLayoutNextFrame(RectTransform rect)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			<FixLayoutNextFrame>d__4 <FixLayoutNextFrame>d__ = new <FixLayoutNextFrame>d__4();
			<FixLayoutNextFrame>d__.<>t__builder = AsyncUniTaskMethodBuilder.Create();
			<FixLayoutNextFrame>d__.rect = rect;
			<FixLayoutNextFrame>d__.<>1__state = -1;
			((AsyncUniTaskMethodBuilder)(ref <FixLayoutNextFrame>d__.<>t__builder)).Start<<FixLayoutNextFrame>d__4>(ref <FixLayoutNextFrame>d__);
			return ((AsyncUniTaskMethodBuilder)(ref <FixLayoutNextFrame>d__.<>t__builder)).Task;
		}

		private static void ShowCursor()
		{
			CursorManager.SetCursorForceUnlocked(true);
		}

		private static void HideCursor()
		{
			CursorManager.SetCursorForceUnlocked(false);
			CursorManager.ApplyCursorLock();
		}

		private static void OnNextClicked()
		{
			HideCursor();
			CourseManager instance = SingletonNetworkBehaviour<CourseManager>.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				if ((Object)(object)nextButtonInstance != (Object)null)
				{
					Object.Destroy((Object)(object)nextButtonInstance);
					nextButtonInstance = null;
				}
				HideCursor();
				if (!END_GAME)
				{
					SingletonNetworkBehaviour<CourseManager>.Instance.ServerStartNextMatch(false);
				}
				else
				{
					CourseManager.EndCourse();
				}
			}
		}

		private static void ServerInitiateMatchFinish(CourseManager courseManager)
		{
			ServerFinishMatchDelayed(courseManager, isCourseFinished: false);
		}

		private static void AwardCourseBonus(CourseManager courseManager)
		{
			AwardCourseBonusAsync(courseManager);
		}

		private static async void ServerFinishMatchDelayed(CourseManager courseManager, bool isCourseFinished)
		{
			if (!MatchSetupRules.IsCheatsEnabled() && isCourseFinished)
			{
				AwardCourseBonus(courseManager);
			}
			NextMatchCountdown.Show();
			((TMP_Text)SingletonNetworkBehaviour<NextMatchCountdown>.Instance.message).SetText("Waiting for host!");
			float delayDuration = (isCourseFinished ? GameManager.MatchSettings.FinishCourseDelay : GameManager.MatchSettings.StartNextMatchDelay);
			for (float time = 0f; time < delayDuration; time += Time.deltaTime)
			{
				if (!courseManager.forceDisplayScoreboard && time >= GameManager.MatchSettings.MatchEndScoreboardDisplayDelay)
				{
					courseManager.NetworkforceDisplayScoreboard = true;
				}
				await UniTask.Yield();
				if ((Object)(object)courseManager == (Object)null)
				{
					return;
				}
			}
			if (isCourseFinished)
			{
				courseManager.EndCourseInternal();
			}
		}

		private static async void AwardCourseBonusAsync(CourseManager courseManager)
		{
			await UniTask.WaitForSeconds(1f, false, (PlayerLoopTiming)8, default(CancellationToken), false);
			if ((Object)(object)courseManager == (Object)null)
			{
				return;
			}
			List<PlayerState> playerStatesInternal = courseManager.GetSortedPlayerStatesInternal(false);
			if (playerStatesInternal.Count <= 1)
			{
				return;
			}
			List<PlayerState> list = default(List<PlayerState>);
			PooledObject<List<PlayerState>> val = CollectionPool<List<PlayerState>, PlayerState>.Get(ref list);
			try
			{
				NetworkConnectionToClient connection = default(NetworkConnectionToClient);
				for (int i = 0; i < playerStatesInternal.Count; i++)
				{
					PlayerState playerState = playerStatesInternal[i];
					if (playerState.isConnected && !playerState.isSpectator && BNetworkManager.singleton.ServerTryGetConnectionFromPlayerGuid(playerState.playerGuid, ref connection))
					{
						float awardMultiplier = ((i == 0) ? 1f : ((i >= playerStatesInternal.Count / 2) ? 0.5f : 0.75f));
						courseManager.RpcAwardCourseBonus(connection, awardMultiplier);
					}
					connection = null;
				}
			}
			finally
			{
				((IDisposable)val).Dispose();
			}
		}
	}
	public class StopCountdownToMatchEnd
	{
		[HarmonyPatch(typeof(CourseManager), "BeginCountdownToMatchEnd")]
		[HarmonyPrefix]
		public static bool Awake_Postfix(CourseManager __instance)
		{
			return false;
		}
	}
}
namespace Gamemode_Lib.Teams
{
	public struct GamemodeStartMessage : NetworkMessage
	{
		public string GamemodeId;
	}
	public struct TeamAssignMessage : NetworkMessage
	{
		public ulong PlayerGuid;

		public int TeamId;
	}
	public struct TeamDefinitionMessage : NetworkMessage
	{
		public int ID;

		public Color Color;

		public string Name;
	}
	public class PlayerTag : MonoBehaviour
	{
		public enum TagHitType
		{
			Dive,
			GolfSwing
		}

		private Hittable hittable;

		private PlayerTeam playerTeam;

		public static event Action<PlayerInfo, PlayerInfo, TagHitType> PlayerTagged;

		private void Awake()
		{
			hittable = ((Component)this).GetComponent<Hittable>();
			playerTeam = ((Component)this).GetComponent<PlayerTeam>();
			if ((Object)(object)hittable != (Object)null)
			{
				hittable.WasHitByDive += OnWasHitByDive;
				hittable.WasHitByGolfSwing += OnWasHitByGolfSwing;
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)hittable != (Object)null)
			{
				hittable.WasHitByDive -= OnWasHitByDive;
				hittable.WasHitByGolfSwing -= OnWasHitByGolfSwing;
			}
		}

		public void OnWasHitByDive(PlayerMovement hitter)
		{
			PlayerInfo val = (PlayerInfo)(((Object)(object)playerTeam != (Object)null) ? ((object)playerTeam.playerInfo) : ((object)((Component)this).GetComponent<PlayerInfo>()));
			PlayerInfo val2 = (((Object)(object)hitter != (Object)null) ? ((Component)hitter).GetComponent<PlayerInfo>() : null);
			Plugin.Log.LogInfo((object)("Player " + (((val != null) ? ((Object)((Component)val).gameObject).name : null) ?? ((Object)((Component)this).gameObject).name) + " was hit by dive from " + (((val2 != null) ? ((Object)((Component)val2).gameObject).name : null) ?? ((hitter != null) ? ((Object)((Component)hitter).gameObject).name : null) ?? "unknown")));
			PlayerTag.PlayerTagged?.Invoke(val, val2, TagHitType.Dive);
		}

		public void OnWasHitByGolfSwing(PlayerGolfer hitter, Vector3 vector3, float arg3, bool arg4)
		{
			PlayerInfo val = (PlayerInfo)(((Object)(object)playerTeam != (Object)null) ? ((object)playerTeam.playerInfo) : ((object)((Component)this).GetComponent<PlayerInfo>()));
			PlayerInfo val2 = (((Object)(object)hitter != (Object)null) ? ((Component)hitter).GetComponent<PlayerInfo>() : null);
			Plugin.Log.LogInfo((object)("Player " + (((val != null) ? ((Object)((Component)val).gameObject).name : null) ?? ((Object)((Component)this).gameObject).name) + " was hit by swing from " + (((val2 != null) ? ((Object)((Component)val2).gameObject).name : null) ?? ((hitter != null) ? ((Object)((Component)hitter).gameObject).name : null) ?? "unknown")));
			PlayerTag.PlayerTagged?.Invoke(val, val2, TagHitType.GolfSwing);
		}
	}
	public class PlayerTeam : MonoBehaviour
	{
		public int teamId = -1;

		public PlayerInfo playerInfo;

		private void Awake()
		{
			((Component)this).gameObject.AddComponent<PlayerTag>();
			playerInfo = ((Component)this).GetComponent<PlayerInfo>();
			if ((Object)(object)TeamManager.Instance != (Object)null)
			{
				TeamManager.Instance.RegisterPlayer(this);
			}
		}

		public void SetLocalTeam(int newTeam)
		{
			int num = teamId;
			teamId = newTeam;
			Plugin.Log.LogInfo((object)$"[LOCAL] Team changed {num} -> {newTeam}");
			TeamManager.Instance?.NotifyTeamChanged(this, num, newTeam);
		}
	}
	public class TeamData
	{
		public int ID;

		public Color Color;

		public string Name;

		public int Score;

		public List<PlayerInfo> Members = new List<PlayerInfo>();
	}
	public class TeamManager : MonoBehaviour
	{
		public static TeamManager Instance;

		public Dictionary<int, TeamData> Teams = new Dictionary<int, TeamData>();

		public List<PlayerTeam> Players = new List<PlayerTeam>();

		public PlayerTeam LocalPlayerTeam;

		private readonly Dictionary<ulong, int> _savedTeamIdByGuid = new Dictionary<ulong, int>();

		private readonly Dictionary<ulong, int> _pendingTeamIdByGuid = new Dictionary<ulong, int>();

		private int? _lastAllPlayersOnOneTeamId;

		public event Action<TeamData> AllPlayersOnOneTeam;

		private void Awake()
		{
			if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			PlayerInfo[] array = Object.FindObjectsByType<PlayerInfo>((FindObjectsSortMode)0);
			foreach (PlayerInfo val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					EnsurePlayerTeam(val);
				}
			}
		}

		private void BroadcastTeam(PlayerInfo info, int teamId)
		{
			if (NetworkServer.active && !((Object)(object)info == (Object)null))
			{
				TeamAssignMessage teamAssignMessage = default(TeamAssignMessage);
				teamAssignMessage.PlayerGuid = info.PlayerId.guid;
				teamAssignMessage.TeamId = teamId;
				NetworkServer.SendToAll<TeamAssignMessage>(teamAssignMessage, 0, false);
			}
		}

		public void RegisterPlayer(PlayerTeam player)
		{
			if (!((Object)(object)player == (Object)null))
			{
				if (!Players.Contains(player))
				{
					Players.Add(player);
				}
				EvaluateAllPlayersOnOneTeam();
			}
		}

		public PlayerTeam EnsurePlayerTeam(PlayerInfo info)
		{
			if ((Object)(object)info == (Object)null)
			{
				return null;
			}
			PlayerTeam playerTeam = default(PlayerTeam);
			if (!((Component)info).TryGetComponent<PlayerTeam>(ref playerTeam) || (Object)(object)playerTeam == (Object)null)
			{
				playerTeam = ((Component)info).gameObject.AddComponent<PlayerTeam>();
			}
			if (playerTeam.playerInfo != info)
			{
				playerTeam.playerInfo = info;
			}
			RegisterPlayer(playerTeam);
			if ((Object)(object)SingletonBehaviour<GameManager>.Instance != (Object)null && SingletonBehaviour<GameManager>.Instance.localPlayerInfo == info)
			{
				LocalPlayerTeam = playerTeam;
			}
			if (NetworkClient.active && _pendingTeamIdByGuid.TryGetValue(info.PlayerId.guid, out var value))
			{
				playerTeam.SetLocalTeam(value);
				_pendingTeamIdByGuid.Remove(info.PlayerId.guid);
			}
			return playerTeam;
		}

		internal void NotifyTeamChanged(PlayerTeam _player, int _oldTeamId, int _newTeamId)
		{
			EvaluateAllPlayersOnOneTeam();
		}

		public bool TryApplySavedTeam(PlayerInfo info, bool broadcastToClients = true)
		{
			if ((Object)(object)info == (Object)null)
			{
				return false;
			}
			if (!_savedTeamIdByGuid.TryGetValue(info.PlayerId.guid, out var value))
			{
				return false;
			}
			EnsurePlayerTeam(info)?.SetLocalTeam(value);
			if (broadcastToClients)
			{
				BroadcastTeam(info, value);
			}
			return true;
		}

		public bool TryRefreshLocalPlayerTeam()
		{
			PlayerInfo val = SingletonBehaviour<GameManager>.Instance?.localPlayerInfo;
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			LocalPlayerTeam = EnsurePlayerTeam(val);
			return (Object)(object)LocalPlayerTeam != (Object)null;
		}

		public void SaveCurrentTeams()
		{
			_savedTeamIdByGuid.Clear();
			for (int num = Players.Count - 1; num >= 0; num--)
			{
				PlayerTeam playerTeam = Players[num];
				if ((Object)(object)playerTeam == (Object)null)
				{
					Players.RemoveAt(num);
				}
				else
				{
					PlayerInfo playerInfo = playerTeam.playerInfo;
					if (!((Object)(object)playerInfo == (Object)null))
					{
						_savedTeamIdByGuid[playerInfo.PlayerId.guid] = playerTeam.teamId;
					}
				}
			}
		}

		public int ReloadSavedTeams(bool broadcastToClients = true)
		{
			int num = 0;
			for (int num2 = Players.Count - 1; num2 >= 0; num2--)
			{
				PlayerTeam playerTeam = Players[num2];
				if ((Object)(object)playerTeam == (Object)null)
				{
					Players.RemoveAt(num2);
				}
				else
				{
					PlayerInfo playerInfo = playerTeam.playerInfo;
					if (!((Object)(object)playerInfo == (Object)null) && _savedTeamIdByGuid.TryGetValue(playerInfo.PlayerId.guid, out var value))
					{
						playerTeam.SetLocalTeam(value);
						num++;
						if (broadcastToClients)
						{
							BroadcastTeam(playerInfo, value);
						}
					}
				}
			}
			return num;
		}

		public void ApplyTeamMessage(TeamAssignMessage msg)
		{
			if (!NetworkClient.active)
			{
				return;
			}
			for (int num = Players.Count - 1; num >= 0; num--)
			{
				PlayerTeam playerTeam = Players[num];
				if ((Object)(object)playerTeam == (Object)null)
				{
					Players.RemoveAt(num);
				}
				else
				{
					PlayerInfo playerInfo = playerTeam.playerInfo;
					if (!((Object)(object)playerInfo == (Object)null) && playerInfo.PlayerId.guid == msg.PlayerGuid)
					{
						playerTeam.SetLocalTeam(msg.TeamId);
						return;
					}
				}
			}
			PlayerInfo[] array = Object.FindObjectsByType<PlayerInfo>((FindObjectsSortMode)0);
			PlayerInfo[] array2 = array;
			foreach (PlayerInfo val in array2)
			{
				if (!((Object)(object)val == (Object)null) && val.PlayerId.guid == msg.PlayerGuid)
				{
					EnsurePlayerTeam(val).SetLocalTeam(msg.TeamId);
					return;
				}
			}
			_pendingTeamIdByGuid[msg.PlayerGuid] = msg.TeamId;
		}

		public void ApplyTeamDefinitionMessage(TeamDefinitionMessage msg)
		{
			//IL_0020: 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)
			Teams[msg.ID] = new TeamData
			{
				ID = msg.ID,
				Color = msg.Color,
				Name = msg.Name
			};
		}

		public void SendTeamToClients(PlayerInfo playerInfo, int teamId)
		{
			BroadcastTeam(playerInfo, teamId);
		}

		public void SendTeamDefinitionToClients(TeamData team)
		{
			//IL_002d: 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)
			if (NetworkServer.active && team != null)
			{
				TeamDefinitionMessage teamDefinitionMessage = default(TeamDefinitionMessage);
				teamDefinitionMessage.ID = team.ID;
				teamDefinitionMessage.Color = team.Color;
				teamDefinitionMessage.Name = team.Name;
				NetworkServer.SendToAll<TeamDefinitionMessage>(teamDefinitionMessage, 0, false);
			}
		}

		public void CreateAndAssignTeams(int teamCount)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active || teamCount <= 0)
			{
				return;
			}
			Teams.Clear();
			for (int i = 0; i < teamCount; i++)
			{
				TeamData teamData = new TeamData
				{
					ID = i,
					Color = GetDefaultColor(i),
					Name = $"Team {i + 1}"
				};
				Teams[i] = teamData;
				SendTeamDefinitionToClients(teamData);
			}
			int num = 0;
			PlayerInfo[] array = Object.FindObjectsByType<PlayerInfo>((FindObjectsSortMode)0);
			foreach (PlayerInfo val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					PlayerTeam playerTeam = EnsurePlayerTeam(val);
					if (!((Object)(object)playerTeam == (Object)null))
					{
						int num2 = num % teamCount;
						num++;
						playerTeam.SetLocalTeam(num2);
						BroadcastTeam(val, num2);
					}
				}
			}
		}

		public void ResetTeams()
		{
			if (!NetworkServer.active)
			{
				return;
			}
			PlayerInfo[] array = Object.FindObjectsByType<PlayerInfo>((FindObjectsSortMode)0);
			foreach (PlayerInfo val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					PlayerTeam playerTeam = EnsurePlayerTeam(val);
					if (!((Object)(object)playerTeam == (Object)null))
					{
						playerTeam.SetLocalTeam(-1);
						BroadcastTeam(val, -1);
					}
				}
			}
		}

		public void ClearTeamDefinitions()
		{
			Teams.Clear();
		}

		public bool TryGetTeam(int teamId, out TeamData team)
		{
			return Teams.TryGetValue(teamId, out team);
		}

		private static Color GetDefaultColor(int teamId)
		{
			//IL_001c: 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_0024: 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_002c: 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_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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if (1 == 0)
			{
			}
			Color result = (Color)(teamId switch
			{
				0 => Color.red, 
				1 => Color.blue, 
				2 => Color.green, 
				3 => Color.yellow, 
				_ => Color.white, 
			});
			if (1 == 0)
			{
			}
			return result;
		}

		private void EvaluateAllPlayersOnOneTeam()
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			int? allPlayersSingleTeamId = GetAllPlayersSingleTeamId();
			if (!allPlayersSingleTeamId.HasValue)
			{
				_lastAllPlayersOnOneTeamId = null;
			}
			else if (_lastAllPlayersOnOneTeamId != allPlayersSingleTeamId)
			{
				_lastAllPlayersOnOneTeamId = allPlayersSingleTeamId;
				if (!Teams.TryGetValue(allPlayersSingleTeamId.Value, out TeamData value) || value == null)
				{
					value = new TeamData
					{
						ID = allPlayersSingleTeamId.Value,
						Name = $"Team {allPlayersSingleTeamId.Value + 1}",
						Color = GetDefaultColor(allPlayersSingleTeamId.Value)
					};
				}
				this.AllPlayersOnOneTeam?.Invoke(value);
			}
		}

		private int? GetAllPlayersSingleTeamId()
		{
			int num = int.MinValue;
			int num2 = 0;
			for (int num3 = Players.Count - 1; num3 >= 0; num3--)
			{
				PlayerTeam playerTeam = Players[num3];
				if ((Object)(object)playerTeam == (Object)null)
				{
					Players.RemoveAt(num3);
				}
				else
				{
					if (playerTeam.teamId < 0)
					{
						return null;
					}
					if (num2 == 0)
					{
						num = playerTeam.teamId;
					}
					else if (playerTeam.teamId != num)
					{
						return null;
					}
					num2++;
				}
			}
			if (num2 == 0)
			{
				return null;
			}
			return num;
		}
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ConstantExpectedAttribute : Attribute
	{
		public object? Min { get; set; }

		public object? Max { get; set; }
	}
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ExperimentalAttribute : Attribute
	{
		public string DiagnosticId { get; }

		public string? UrlFormat { get; set; }

		public ExperimentalAttribute(string diagnosticId)
		{
			DiagnosticId = diagnosticId;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	internal sealed class MemberNotNullAttribute : Attribute
	{
		public string[] Members { get; }

		public MemberNotNullAttribute(string member)
		{
			Members = new string[1] { member };
		}

		public MemberNotNullAttribute(params string[] members)
		{
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	internal sealed class MemberNotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public string[] Members { get; }

		public MemberNotNullWhenAttribute(bool returnValue, string member)
		{
			ReturnValue = returnValue;
			Members = new string[1] { member };
		}

		public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
		{
			ReturnValue = returnValue;
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SetsRequiredMembersAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class StringSyntaxAttribute : Attribute
	{
		public const string CompositeFormat = "CompositeFormat";

		public const string DateOnlyFormat = "DateOnlyFormat";

		public const string DateTimeFormat = "DateTimeFormat";

		public const string EnumFormat = "EnumFormat";

		public const string GuidFormat = "GuidFormat";

		public const string Json = "Json";

		public const string NumericFormat = "NumericFormat";

		public const string Regex = "Regex";

		public const string TimeOnlyFormat = "TimeOnlyFormat";

		public const string TimeSpanFormat = "TimeSpanFormat";

		public const string Uri = "Uri";

		public const string Xml = "Xml";

		public string Syntax { get; }

		public object?[] Arguments { get; }

		public StringSyntaxAttribute(string syntax)
		{
			Syntax = syntax;
			Arguments = new object[0];
		}

		public StringSyntaxAttribute(string syntax, params object?[] arguments)
		{
			Syntax = syntax;
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class UnscopedRefAttribute : Attribute
	{
	}
}
namespace System.Runtime.Versioning
{
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresPreviewFeaturesAttribute : Attribute
	{
		public string? Message { get; }

		public string? Url { get; set; }

		public RequiresPreviewFeaturesAttribute()
		{
		}

		public RequiresPreviewFeaturesAttribute(string? message)
		{
			Message = message;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CallerArgumentExpressionAttribute : Attribute
	{
		public string ParameterName { get; }

		public CallerArgumentExpressionAttribute(string parameterName)
		{
			ParameterName = parameterName;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CollectionBuilderAttribute : Attribute
	{
		public Type BuilderType { get; }

		public string MethodName { get; }

		public CollectionBuilderAttribute(Type builderType, string methodName)
		{
			BuilderType = builderType;
			MethodName = methodName;
		}
	}
	[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CompilerFeatureRequiredAttribute : Attribute
	{
		public const string RefStructs = "RefStructs";

		public const string RequiredMembers = "RequiredMembers";

		public string FeatureName { get; }

		public bool IsOptional { get; set; }

		public CompilerFeatureRequiredAttribute(string featureName)
		{
			FeatureName = featureName;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute
	{
		public string[] Arguments { get; }

		public InterpolatedStringHandlerArgumentAttribute(string argument)
		{
			Arguments = new string[1] { argument };
		}

		public InterpolatedStringHandlerArgumentAttribute(params string[] arguments)
		{
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerAttribute : Attribute
	{
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal static class IsExternalInit
	{
	}
	[AttributeUsage(AttributeTargets.Method, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ModuleInitializerAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class OverloadResolutionPriorityAttribute : Attribute
	{
		public int Priority { get; }

		public OverloadResolutionPriorityAttribute(int priority)
		{
			Priority = priority;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ParamCollectionAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiredMemberAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresLocationAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SkipLocalsInitAttribute : Attribute
	{
	}
}