Decompiled source of Eights v0.4.1

Eights.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ComputerysModdingUtilities;
using FishNet;
using FishNet.Connection;
using FishNet.Managing;
using FishNet.Managing.Scened;
using FishNet.Object;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using ModMenu.Api;
using MyceliumNetworking;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: StraftatMod(false)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Eights")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.4.1.0")]
[assembly: AssemblyInformationalVersion("0.4.1+c07faeaf0b22e2af10201ebcd73d5cea8f0ba6f6")]
[assembly: AssemblyProduct("Straftat Eights")]
[assembly: AssemblyTitle("Eights")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.4.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
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 Eights
{
	[BepInPlugin("Eights", "Straftat Eights", "0.4.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInProcess("STRAFTAT.exe")]
	public class Plugin : BaseUnityPlugin
	{
		internal const uint AssassinModId = 3141592658u;

		internal static ConfigEntry<bool> AssassinEnabled;

		internal static ConfigEntry<int> MaximumBloodEffects;

		internal const uint CaptureTheFlagModId = 1618033995u;

		internal static ConfigEntry<bool> CaptureTheFlagEnabled;

		internal const uint DefaultGameModeModId = 3141592653u;

		internal static ConfigEntry<bool> DefaultGameModeEnabled;

		internal const uint FFAModId = 2718281828u;

		internal static ConfigEntry<bool> FFAEnabled;

		internal const uint GlobalModifiersModId = 1892737465u;

		internal static ConfigEntry<bool> MovementTweaksEnabled;

		internal static ConfigEntry<bool> WallJumpEnabled;

		internal static ConfigEntry<bool> WallJumpBoostEnabled;

		internal static ConfigEntry<bool> SlidingEnabled;

		internal static ConfigEntry<bool> SlideBoostEnabled;

		internal static ConfigEntry<int> MoveSpeedPercent;

		internal static ConfigEntry<int> AdsSpeedPercent;

		internal static ConfigEntry<int> GravityPercent;

		internal static ConfigEntry<int> MomentumPercent;

		internal static ConfigEntry<int> AirSpeedRatioPercent;

		internal static ConfigEntry<int> ShootingSpeedPercent;

		internal const uint GlobalWeaponsModId = 1618033991u;

		internal static ConfigEntry<bool> WeaponTweaksEnabled;

		internal static ConfigEntry<string> AllowedWeapons;

		internal static ConfigEntry<int> SpareMagazines;

		internal static ConfigEntry<bool> CycleWeapons;

		internal static ConfigEntry<bool> DefaultKnife;

		internal const uint GunGameModId = 1618033990u;

		internal static ConfigEntry<bool> GunGameEnabled;

		internal static ConfigEntry<string> GunGameWeaponOrder;

		internal const uint HardpointModId = 1618033994u;

		internal const float HardpointSpawnRandomness = 0.35f;

		internal static ConfigEntry<bool> HardpointEnabled;

		internal const uint HealthSettingsModId = 1892737466u;

		internal static ConfigEntry<int> MaxHealthPercent;

		internal static ConfigEntry<bool> HealthTweaksEnabled;

		internal static ConfigEntry<bool> HealthRegenEnabled;

		internal static ConfigEntry<int> HealthRegenDelaySeconds;

		internal static ConfigEntry<int> HealthRegenRate;

		internal const uint HotPotatoModId = 2718281830u;

		internal static ConfigEntry<bool> HotPotatoEnabled;

		internal static ConfigEntry<string> HotPotatoWeaponOrder;

		internal static ConfigEntry<bool> NinjaHuntersEnabled;

		internal static ConfigEntry<bool> RabbitHuntersEnabled;

		internal static ConfigEntry<bool> TankBattleEnabled;

		internal const uint HVTModId = 3141592657u;

		internal static ConfigEntry<bool> HVTEnabled;

		internal const uint InfectedModId = 2718281832u;

		internal static ConfigEntry<bool> InfectedEnabled;

		internal const uint InfidelModId = 2718281831u;

		internal static ConfigEntry<bool> InfidelEnabled;

		internal const uint JuggernautModId = 3141592656u;

		internal static ConfigEntry<bool> JuggernautEnabled;

		internal const uint KillTheRatModId = 3141592655u;

		internal static ConfigEntry<bool> KillTheRatEnabled;

		internal const uint MichaelMeyersModId = 3141592654u;

		internal static ConfigEntry<bool> MichaelMeyersEnabled;

		internal const uint OneInTheChamberModId = 2718281829u;

		internal static ConfigEntry<bool> OneInTheChamberEnabled;

		internal static ManualLogSource Logger;

		internal static Plugin Instance;

		internal const uint SearchAndDestroyModId = 1618033996u;

		internal static ConfigEntry<bool> SearchAndDestroyEnabled;

		internal const uint MyceliumTransportModId = 1618033993u;

		internal const uint SniperBattleModId = 1618033992u;

		internal static ConfigEntry<bool> SniperBattleEnabled;

		internal const uint TeamDeathmatchModId = 1618033997u;

		internal const float TeamDeathmatchSpawnRandomness = 0.35f;

		internal static ConfigEntry<bool> TeamDeathmatchEnabled;

		private void InitializeAssassin()
		{
			AssassinEnabled = ModeConfigMigration.BindModeEnabled(((BaseUnityPlugin)this).Config, "Game Mode Settings", "Assassin", "A hidden Assassin hunts the public King while bodyguards protect the King, with role weapons unlocking after a delay. Killing the King awards the Assassin 50 points; eliminating the Assassin awards the King 30 points, each surviving bodyguard 10 points, and a bodyguard killer 20 extra points, with the first player to reach the configured point limit winning.");
			AssassinEnabled.SettingChanged += delegate
			{
				AssassinState.PushSettingsIfHost();
				GameModeManager.OnSettingsChanged();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, 3141592658u, 0);
			ModeLobbyDataSync.RegisterKeys("Eights_Assassin_Settings", "Eights_Assassin_Live");
			MyceliumNetwork.LobbyCreated += AssassinState.OnLobbyEntered;
			MyceliumNetwork.LobbyEntered += AssassinState.OnLobbyEntered;
			MyceliumNetwork.LobbyLeft += AssassinState.OnLobbyLeft;
			MyceliumNetwork.LobbyDataUpdated += AssassinState.OnLobbyDataUpdated;
			MyceliumNetwork.PlayerEntered += AssassinState.OnPlayerEntered;
			MyceliumNetwork.PlayerLeft += AssassinState.OnPlayerLeft;
		}

		[CustomRPC]
		public void SyncAssassinSettings(CSteamID hostId, int roundId, int revision, bool enabled, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && AssassinState.TryAcceptSettingsSnapshot(hostId, roundId, revision))
			{
				AssassinState.ApplySettings(enabled);
			}
		}

		[CustomRPC]
		public void SyncAssassinLiveState(CSteamID hostId, int kingPlayerId, string scoresData, int winnerId, int takeId, bool weaponsUnlocked, int weaponDelaySeconds, float takeTimeRemaining, int roundId, int revision, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				AssassinState.ApplyLiveState(hostId, kingPlayerId, scoresData, winnerId, takeId, weaponsUnlocked, weaponDelaySeconds, takeTimeRemaining, roundId, revision);
			}
		}

		[CustomRPC]
		public void SyncAssassinRole(CSteamID hostId, int takeId, bool isAssassin, bool isKing, bool announce, int weaponDelaySeconds, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				AssassinState.ApplyLocalRole(hostId, takeId, isAssassin, isKing, announce, weaponDelaySeconds);
			}
		}

		[CustomRPC]
		public void AssassinAnnounce(string text, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				GameModeHud.ReceiveAnnouncement(text, 3f, showHud: true);
			}
		}

		private void InitializeBloodCleanup()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			MaximumBloodEffects = ((BaseUnityPlugin)this).Config.Bind<int>("Blood Settings", "Maximum Blood Effects", 50, new ConfigDescription("Local visual limit for live blood effects. Older effects are removed first.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 100), Array.Empty<object>()));
			MaximumBloodEffects.SettingChanged += delegate
			{
				BloodCleanupState.TrimToLimit();
			};
		}

		private void InitializeCaptureTheFlag()
		{
			CaptureTheFlagEnabled = ModeConfigMigration.BindModeEnabled(((BaseUnityPlugin)this).Config, "Game Mode Settings", "Capture The Flag", "Teams steal the enemy flag and return it to their own base while protecting their flag. Each capture awards 25 points, and the first team to reach the configured point limit wins; after time expires, respawns stop and sudden death resolves the match.");
			CaptureTheFlagEnabled.SettingChanged += delegate
			{
				CaptureTheFlagState.PushSettingsIfHost();
				GameModeManager.OnSettingsChanged();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, 1618033995u, 0);
			ModeLobbyDataSync.RegisterKeys("Eights_CTF_Settings", "Eights_CTF_Live");
			MyceliumNetwork.LobbyCreated += CaptureTheFlagState.OnLobbyEntered;
			MyceliumNetwork.LobbyEntered += CaptureTheFlagState.OnLobbyEntered;
			MyceliumNetwork.LobbyLeft += CaptureTheFlagState.OnLobbyLeft;
			MyceliumNetwork.LobbyDataUpdated += CaptureTheFlagState.OnLobbyDataUpdated;
			MyceliumNetwork.PlayerEntered += CaptureTheFlagState.OnPlayerEntered;
			MyceliumNetwork.PlayerLeft += CaptureTheFlagState.OnPlayerLeft;
		}

		[CustomRPC]
		public void SyncCaptureTheFlagSettings(CSteamID hostId, int roundId, int revision, bool enabled, bool ignoredLegacySpawnerFlag, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && CaptureTheFlagState.TryAcceptSettingsSnapshot(hostId, roundId, revision))
			{
				CaptureTheFlagState.ApplySettings(enabled);
			}
		}

		[CustomRPC]
		public void SyncCaptureTheFlagLiveState(CSteamID hostId, string assignmentsData, int teamCount, string scoresData, string flagsData, float matchTimeRemaining, bool suddenDeath, int roundId, int revision, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				CaptureTheFlagState.ApplyLiveState(hostId, assignmentsData, teamCount, scoresData, flagsData, matchTimeRemaining, suddenDeath, roundId, revision);
			}
		}

		private void InitializeDefaultGameMode()
		{
			DefaultGameModeEnabled = ModeConfigMigration.BindModeEnabled(((BaseUnityPlugin)this).Config, "Game Mode Settings", "Default Game Mode", "Use the map's normal weapon spawners, movement, and health. Winning a take awards 50 points, and the first player or team to reach the configured point limit wins.");
			DefaultGameModeEnabled.SettingChanged += delegate
			{
				GameModeManager.OnSettingsChanged();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, 3141592653u, 0);
			ModeLobbyDataSync.RegisterKeys("Eights_Default_Live");
			MyceliumNetwork.LobbyCreated += DefaultGameModeState.OnLobbyEntered;
			MyceliumNetwork.LobbyEntered += DefaultGameModeState.OnLobbyEntered;
			MyceliumNetwork.LobbyDataUpdated += DefaultGameModeState.OnLobbyDataUpdated;
			MyceliumNetwork.PlayerEntered += DefaultGameModeState.OnPlayerEntered;
			MyceliumNetwork.PlayerLeft += DefaultGameModeState.OnPlayerLeft;
		}

		[CustomRPC]
		public void SyncDefaultGameModeLiveState(CSteamID hostId, string scoresData, string aliveData, int takeId, int winnerId, float timeRemaining, int roundId, int revision, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				DefaultGameModeState.ApplyLiveState(hostId, scoresData, aliveData, takeId, winnerId, timeRemaining, roundId, revision);
			}
		}

		[CustomRPC]
		public void DefaultGameModeAnnounce(string text, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				GameModeHud.ReceiveAnnouncement(text, 3f, showHud: true);
			}
		}

		private void InitializeFFA()
		{
			FFAEnabled = ModeConfigMigration.BindModeEnabled(((BaseUnityPlugin)this).Config, "Game Mode Settings", "Free For All", "Every player fights independently and respawns after death. Each kill awards 10 points, and the first player to reach the configured point limit wins.");
			FFAEnabled.SettingChanged += delegate
			{
				FFAState.PushSettingsIfHost();
				GameModeManager.OnSettingsChanged();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, 2718281828u, 0);
			ModeLobbyDataSync.RegisterKeys("Eights_FFA_Settings", "Eights_FFA_Live");
			MyceliumNetwork.LobbyCreated += FFAState.OnLobbyEntered;
			MyceliumNetwork.LobbyEntered += FFAState.OnLobbyEntered;
			MyceliumNetwork.LobbyDataUpdated += FFAState.OnLobbyDataUpdated;
			MyceliumNetwork.PlayerEntered += FFAState.OnPlayerEntered;
			MyceliumNetwork.PlayerLeft += FFAState.OnPlayerLeft;
		}

		[CustomRPC]
		public void SyncFFASettings(CSteamID hostId, int roundId, int revision, bool enabled, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && FFAState.TryAcceptSettingsSnapshot(hostId, roundId, revision))
			{
				FFAState.ApplySettings(enabled);
			}
		}

		[CustomRPC]
		public void SyncFFALiveState(CSteamID hostId, string killsData, int winnerId, int roundId, int revision, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				FFAState.ApplyLiveState(hostId, killsData, winnerId, roundId, revision);
			}
		}

		[CustomRPC]
		public void FFAAnnounce(string text, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				GameModeHud.ReceiveAnnouncement(text, 3f, showHud: true);
			}
		}

		private void InitializeGlobalModifiers()
		{
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Expected O, but got Unknown
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Expected O, but got Unknown
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Expected O, but got Unknown
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Expected O, but got Unknown
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Expected O, but got Unknown
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Expected O, but got Unknown
			MovementTweaksEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Movement Settings", "Movement Tweaks Enabled", true, "Host-controlled: master switch. Turn off for pure stock Straftat movement.");
			WallJumpEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Movement Settings", "Enable Wall Jump", true, "Host-controlled: allows wall jumping for everyone in the lobby.");
			WallJumpBoostEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Movement Settings", "Enable Wall Jump Speed Boost", false, "Host-controlled: whether wall jumping gives the usual Straftat horizontal speed kick (chaining wall jumps for extra speed).");
			SlidingEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Movement Settings", "Enable Sliding", true, "Host-controlled: allows crouch-sliding for everyone in the lobby.");
			SlideBoostEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Movement Settings", "Enable Slide Speed Boost", false, "Host-controlled: whether sliding gives the usual Straftat speed boost. Disable to slide like most other games.");
			MoveSpeedPercent = ((BaseUnityPlugin)this).Config.Bind<int>("Movement Settings", "Move Speed %", 100, new ConfigDescription("Host-controlled: overall movement speed as a percent of normal.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(50, 200), Array.Empty<object>()));
			AdsSpeedPercent = ((BaseUnityPlugin)this).Config.Bind<int>("Movement Settings", "ADS Speed %", 100, new ConfigDescription("Host-controlled: movement speed while aiming down sights, as a percent of normal.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(50, 100), Array.Empty<object>()));
			GravityPercent = ((BaseUnityPlugin)this).Config.Bind<int>("Movement Settings", "Gravity %", 100, new ConfigDescription("Host-controlled: gravity as a percent of normal. Lower = floatier jumps and slower falling.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 100), Array.Empty<object>()));
			MomentumPercent = ((BaseUnityPlugin)this).Config.Bind<int>("Movement Settings", "Momentum %", 100, new ConfigDescription("Host-controlled: how much weight/inertia is behind movement. 100% = stock Straftat snappiness. Higher = heavier, slower to speed up/stop/turn. Lower = snappier, near-instant direction changes.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 400), Array.Empty<object>()));
			AirSpeedRatioPercent = ((BaseUnityPlugin)this).Config.Bind<int>("Movement Settings", "Air Move Speed %", (int)MathF.Round(116.666664f), new ConfigDescription("Host-controlled: air move speed (not air control) as a percent of ground move speed. Stock Straftat is already faster sprinting in the air than on the ground (the default reflects that real ratio). Lower this to slow players down in the air.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(50, 200), Array.Empty<object>()));
			ShootingSpeedPercent = ((BaseUnityPlugin)this).Config.Bind<int>("Movement Settings", "Shooting Speed %", 100, new ConfigDescription("Host-controlled: movement speed while shooting as a percent of normal. 100% = no slowdown.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 100), Array.Empty<object>()));
			WallJumpEnabled.SettingChanged += delegate
			{
				GlobalModifiersState.PushIfHost();
			};
			MovementTweaksEnabled.SettingChanged += delegate
			{
				GlobalModifiersState.PushIfHost();
			};
			SlidingEnabled.SettingChanged += delegate
			{
				GlobalModifiersState.PushIfHost();
			};
			SlideBoostEnabled.SettingChanged += delegate
			{
				GlobalModifiersState.PushIfHost();
			};
			WallJumpBoostEnabled.SettingChanged += delegate
			{
				GlobalModifiersState.PushIfHost();
			};
			MoveSpeedPercent.SettingChanged += delegate
			{
				GlobalModifiersState.PushIfHost();
			};
			AdsSpeedPercent.SettingChanged += delegate
			{
				GlobalModifiersState.PushIfHost();
			};
			GravityPercent.SettingChanged += delegate
			{
				GlobalModifiersState.PushIfHost();
			};
			MomentumPercent.SettingChanged += delegate
			{
				GlobalModifiersState.PushIfHost();
			};
			AirSpeedRatioPercent.SettingChanged += delegate
			{
				GlobalModifiersState.PushIfHost();
			};
			ShootingSpeedPercent.SettingChanged += delegate
			{
				GlobalModifiersState.PushIfHost();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, 1892737465u, 0);
			ModeLobbyDataSync.RegisterKeys("Eights_GlobalModifiers_Settings");
			MyceliumNetwork.LobbyCreated += GlobalModifiersState.OnLobbyEntered;
			MyceliumNetwork.LobbyEntered += GlobalModifiersState.OnLobbyEntered;
			MyceliumNetwork.LobbyDataUpdated += GlobalModifiersState.OnLobbyDataUpdated;
			MyceliumNetwork.PlayerEntered += GlobalModifiersState.OnPlayerEntered;
		}

		[CustomRPC]
		public void SyncMovementSettings(CSteamID hostId, int roundId, int revision, bool enabled, bool wallJump, bool sliding, bool slideBoost, bool wallJumpBoost, int moveSpeedPercent, int adsSpeedPercent, int gravityPercent, int momentumPercent, int airSpeedRatioPercent, int shootingSpeedPercent, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && GlobalModifiersState.TryAcceptSettingsSnapshot(hostId, roundId, revision))
			{
				GlobalModifiersState.Apply(enabled, wallJump, sliding, slideBoost, wallJumpBoost, moveSpeedPercent, adsSpeedPercent, gravityPercent, momentumPercent, airSpeedRatioPercent, shootingSpeedPercent);
			}
		}

		private void InitializeGlobalWeapons()
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			WeaponTweaksEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Weapon Settings", "Weapon Tweaks Enabled", true, "Host-controlled: enables weapon override rules.");
			AllowedWeapons = ((BaseUnityPlugin)this).Config.Bind<string>("Weapon Settings", "Allowed Weapons", "AK-K, AR15, Dispenser, HK_G11, Yangtse, Kusma, M2000, QCW05, SMG, Warden", "Host-controlled: exact weapon IDs allowed on spawners and for cycling.");
			SpareMagazines = ((BaseUnityPlugin)this).Config.Bind<int>("Weapon Settings", "Spare Magazines", 6, new ConfigDescription("Host-controlled: spare magazines granted with a weapon pickup.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 10), Array.Empty<object>()));
			CycleWeapons = ((BaseUnityPlugin)this).Config.Bind<bool>("Weapon Settings", "F8 Cycle Weapons", false, "Host-controlled: F8 cycles through allowed weapons when no active mode owns weapon loadouts, and disables weapon droppers.");
			DefaultKnife = ((BaseUnityPlugin)this).Config.Bind<bool>("Weapon Settings", "Default Knife", false, "Host-controlled: gives players a Couperet after spawn or respawn when the right hand is empty.");
			WeaponTweaksEnabled.SettingChanged += delegate
			{
				WeaponSettingsState.PushIfHost();
			};
			AllowedWeapons.SettingChanged += delegate
			{
				WeaponSettingsState.PushIfHost();
			};
			SpareMagazines.SettingChanged += delegate
			{
				WeaponSettingsState.PushIfHost();
			};
			CycleWeapons.SettingChanged += delegate
			{
				WeaponSettingsState.PushIfHost();
			};
			DefaultKnife.SettingChanged += delegate
			{
				WeaponSettingsState.PushIfHost();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, 1618033991u, 0);
			ModeLobbyDataSync.RegisterKeys("Eights_GlobalWeapons_Settings");
			MyceliumNetwork.LobbyCreated += WeaponSettingsState.OnLobbyEntered;
			MyceliumNetwork.LobbyEntered += WeaponSettingsState.OnLobbyEntered;
			MyceliumNetwork.LobbyDataUpdated += WeaponSettingsState.OnLobbyDataUpdated;
			MyceliumNetwork.PlayerEntered += WeaponSettingsState.OnPlayerEntered;
			MyceliumNetwork.PlayerLeft += WeaponSettingsState.OnPlayerLeft;
		}

		[CustomRPC]
		public void SyncWeaponSettings(CSteamID hostId, int roundId, int revision, bool enabled, string allowedWeapons, int spareMagazines, bool cycleWeapons, bool defaultKnife, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && WeaponSettingsState.TryAcceptSettingsSnapshot(hostId, roundId, revision))
			{
				WeaponSettingsState.Apply(enabled, allowedWeapons, spareMagazines, cycleWeapons, defaultKnife);
			}
		}

		[CustomRPC]
		public void RequestWeaponCycle(int playerId, int requestId, RPCInfo info)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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)
			if (MyceliumNetwork.IsHost && NetworkAuthority.IsPlayerSender(info, playerId) && WeaponSettingsState.TryAcceptCycleRequest(info.SenderSteamID, requestId) && WeaponSettingsState.Enabled && WeaponSettingsState.Cycle)
			{
				WeaponSettingsState.GiveCycledWeapon(playerId);
			}
		}

		[CustomRPC]
		public void RequestWeaponAmmoReload(int playerId, int requestId, int roundId, int weaponObjectId, bool rightHand, RPCInfo info)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (MyceliumNetwork.IsHost && roundId == GameModeManager.RoundId && NetworkAuthority.IsPlayerSender(info, playerId) && WeaponAmmoTuning.TryAcceptReloadRequest(info.SenderSteamID, requestId))
			{
				WeaponAmmoTuning.ApplyServerReload(playerId, requestId, weaponObjectId, rightHand);
			}
		}

		[CustomRPC]
		public void SyncWeaponAmmoReload(int playerId, int requestId, int roundId, int weaponObjectId, int currentAmmo, int spareRounds, bool rightHand, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				WeaponAmmoTuning.ApplyOwnerReloadSnapshot(playerId, requestId, roundId, weaponObjectId, currentAmmo, spareRounds, rightHand);
			}
		}

		[CustomRPC]
		public void AttachServerGrantedWeapon(int playerId, bool rightHand, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && NetworkAuthority.IsLocalPlayer(playerId))
			{
				WeaponService.AttachGrantedWeaponForOwner(playerId, rightHand);
			}
		}

		private void InitializeGunGame()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			GunGameEnabled = ModeConfigMigration.BindModeEnabled(((BaseUnityPlugin)this).Config, "Game Mode Settings", "Gun Game", "Players advance through the configured weapon list by getting kills, receiving the next weapon after each progression step. Each kill adds 10 progression points, and the first player to complete the weapon progression wins.");
			ConfigDefinition val = new ConfigDefinition("Game Mode Settings", "Gun Game Weapon Order");
			ConfigEntry<string> obj = (((BaseUnityPlugin)this).Config.Keys.Contains(val) ? ((BaseUnityPlugin)this).Config.Bind<string>(val, "Glock, Webley, SMG, Bukanee, Shotgun, AR15, QCW05, HK_G11, M2000, Couperet", new ConfigDescription("Host-controlled: exact prefab IDs in progression order.", (AcceptableValueBase)null, Array.Empty<object>())) : null);
			GunGameWeaponOrder = ((BaseUnityPlugin)this).Config.Bind<string>("Weapon Settings", "Gun Game Weapons", obj?.Value ?? "Glock, Webley, SMG, Bukanee, Shotgun, AR15, QCW05, HK_G11, M2000, Couperet", "Host-controlled: exact prefab IDs in progression order.");
			((BaseUnityPlugin)this).Config.Remove(val);
			GunGameEnabled.SettingChanged += delegate
			{
				GunGameState.PushSettingsIfHost();
				GameModeManager.OnSettingsChanged();
			};
			GunGameWeaponOrder.SettingChanged += delegate
			{
				GunGameState.PushSettingsIfHost();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, 1618033990u, 0);
			ModeLobbyDataSync.RegisterKeys("Eights_GunGame_Settings", "Eights_GunGame_Live");
			MyceliumNetwork.LobbyCreated += GunGameState.OnLobbyEntered;
			MyceliumNetwork.LobbyEntered += GunGameState.OnLobbyEntered;
			MyceliumNetwork.LobbyDataUpdated += GunGameState.OnLobbyDataUpdated;
			MyceliumNetwork.PlayerEntered += GunGameState.OnPlayerEntered;
			MyceliumNetwork.PlayerLeft += GunGameState.OnPlayerLeft;
		}

		[CustomRPC]
		public void SyncGunGameSettings(CSteamID hostId, int roundId, int revision, bool enabled, string? weaponOrder, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && GunGameState.TryAcceptSettingsSnapshot(hostId, roundId, revision, "gun-game-rpc"))
			{
				GunGameState.ApplySettings(enabled, weaponOrder ?? string.Empty);
			}
		}

		[CustomRPC]
		public void SyncGunGameLiveState(CSteamID hostId, string? progressData, int roundId, int revision, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				GunGameState.ApplyLiveState(hostId, progressData ?? string.Empty, roundId, revision, "gun-game-rpc");
			}
		}

		private void InitializeHardpoint()
		{
			HardpointEnabled = ModeConfigMigration.BindModeEnabled(((BaseUnityPlugin)this).Config, "Game Mode Settings", "Hardpoint", "Teams rotate between map hardpoints and earn 1 point for every second of uncontested control. The first team to reach the configured point limit wins; if the match timer expires while tied, the game enters sudden death.");
			HardpointEnabled.SettingChanged += delegate
			{
				HardpointState.PushSettingsIfHost();
				GameModeManager.OnSettingsChanged();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, 1618033994u, 0);
			ModeLobbyDataSync.RegisterKeys("Eights_Hardpoint_Settings", "Eights_Hardpoint_Live");
			MyceliumNetwork.LobbyCreated += HardpointState.OnLobbyEntered;
			MyceliumNetwork.LobbyEntered += HardpointState.OnLobbyEntered;
			MyceliumNetwork.LobbyDataUpdated += HardpointState.OnLobbyDataUpdated;
			MyceliumNetwork.PlayerEntered += HardpointState.OnPlayerEntered;
			MyceliumNetwork.PlayerLeft += HardpointState.OnPlayerLeft;
		}

		[CustomRPC]
		public void SyncHardpointSettings(CSteamID hostId, int roundId, int revision, bool enabled, bool ignoredLegacySpawnerFlag, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && HardpointState.TryAcceptSettingsSnapshot(hostId, roundId, revision))
			{
				HardpointState.ApplySettings(enabled);
			}
		}

		[CustomRPC]
		public void SyncHardpointLiveState(CSteamID hostId, string assignmentsData, int teamCount, string scoresData, int objectiveIndex, float objectiveElapsed, float contestTimeRemaining, int controller, bool suddenDeath, int roundId, int revision, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				HardpointState.ApplyLiveState(hostId, assignmentsData, teamCount, scoresData, objectiveIndex, objectiveElapsed, contestTimeRemaining, controller, suddenDeath, roundId, revision);
			}
		}

		private void InitializeHealthSettings()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Expected O, but got Unknown
			HealthTweaksEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Health Settings", "Health Tweaks Enabled", true, "Host-controlled: master switch. Turn off to restore normal health and disable regeneration.");
			MaxHealthPercent = ((BaseUnityPlugin)this).Config.Bind<int>("Health Settings", "Max Health %", 100, new ConfigDescription("Host-controlled: max health as a percent of normal.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 400), Array.Empty<object>()));
			HealthRegenEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Health Settings", "Enable Health Regen", true, "Host-controlled: enables health regeneration after taking damage.");
			HealthRegenDelaySeconds = ((BaseUnityPlugin)this).Config.Bind<int>("Health Settings", "Regen Delay (seconds)", 5, new ConfigDescription("Host-controlled: delay after taking damage before health regeneration starts.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 15), Array.Empty<object>()));
			HealthRegenRate = ((BaseUnityPlugin)this).Config.Bind<int>("Health Settings", "Regen Rate (health per second)", 150, new ConfigDescription("Host-controlled: displayed HUD health restored per second after the regen delay.", (AcceptableValueBase)(object)new AcceptableValueList<int>(new int[6] { 50, 100, 150, 200, 300, 400 }), Array.Empty<object>()));
			if (HealthRegenRate.Value != 50 && HealthRegenRate.Value != 100 && HealthRegenRate.Value != 150 && HealthRegenRate.Value != 200 && HealthRegenRate.Value != 300 && HealthRegenRate.Value != 400)
			{
				HealthRegenRate.Value = 150;
			}
			HealthTweaksEnabled.SettingChanged += delegate
			{
				HealthSettingsState.PushIfHost();
			};
			MaxHealthPercent.SettingChanged += delegate
			{
				HealthSettingsState.PushIfHost();
			};
			HealthRegenEnabled.SettingChanged += delegate
			{
				HealthSettingsState.PushIfHost();
			};
			HealthRegenDelaySeconds.SettingChanged += delegate
			{
				HealthSettingsState.PushIfHost();
			};
			HealthRegenRate.SettingChanged += delegate
			{
				HealthSettingsState.PushIfHost();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, 1892737466u, 0);
			ModeLobbyDataSync.RegisterKeys("Eights_HealthSettings_Settings");
			MyceliumNetwork.LobbyCreated += HealthSettingsState.OnLobbyEntered;
			MyceliumNetwork.LobbyEntered += HealthSettingsState.OnLobbyEntered;
			MyceliumNetwork.LobbyDataUpdated += HealthSettingsState.OnLobbyDataUpdated;
			MyceliumNetwork.PlayerEntered += HealthSettingsState.OnPlayerEntered;
		}

		[CustomRPC]
		public void SyncHealthSettings(CSteamID hostId, int roundId, int revision, bool enabled, int maxHealthPercent, bool regenEnabled, int regenDelaySeconds, int regenRate, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && HealthSettingsState.TryAcceptSettingsSnapshot(hostId, roundId, revision))
			{
				HealthSettingsState.Apply(enabled, maxHealthPercent, regenEnabled, regenDelaySeconds, regenRate);
			}
		}

		private void InitializeHotPotato()
		{
			HotPotatoEnabled = ModeConfigMigration.BindModeEnabled(((BaseUnityPlugin)this).Config, "Game Mode Settings", "Hot Potato", "One player carries a renewable grenade while everyone else rotates through the configured weapons. All players can fight and kill each other. Each kill awards 10 points, the potato passes after its carrier kills, and the first player to reach the configured point limit wins.");
			HotPotatoWeaponOrder = ((BaseUnityPlugin)this).Config.Bind<string>("Weapon Settings", "Hot Potato Weapons", "Shotgun, Tromblonj, Gust, Crisis", "Host-controlled: exact prefab IDs rotated through by non-potato players.");
			HotPotatoEnabled.SettingChanged += delegate
			{
				HotPotatoState.PushSettingsIfHost();
				GameModeManager.OnSettingsChanged();
			};
			HotPotatoWeaponOrder.SettingChanged += delegate
			{
				HotPotatoState.PushSettingsIfHost();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, 2718281830u, 0);
			ModeLobbyDataSync.RegisterKeys("Eights_HotPotato_Settings", "Eights_HotPotato_Live");
			MyceliumNetwork.LobbyCreated += HotPotatoState.OnLobbyEntered;
			MyceliumNetwork.LobbyEntered += HotPotatoState.OnLobbyEntered;
			MyceliumNetwork.LobbyDataUpdated += HotPotatoState.OnLobbyDataUpdated;
			MyceliumNetwork.PlayerEntered += HotPotatoState.OnPlayerEntered;
			MyceliumNetwork.PlayerLeft += HotPotatoState.OnPlayerLeft;
		}

		[CustomRPC]
		public void SyncHotPotatoSettings(CSteamID hostId, int roundId, int revision, bool enabled, string? weaponOrder, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && HotPotatoState.TryAcceptSettingsSnapshot(hostId, roundId, revision))
			{
				HotPotatoState.ApplySettings(enabled, weaponOrder ?? string.Empty);
			}
		}

		[CustomRPC]
		public void SyncHotPotatoLiveState(CSteamID hostId, string killsData, int potatoPlayerId, int winnerId, int roundId, int revision, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				HotPotatoState.ApplyLiveState(hostId, killsData, potatoPlayerId, winnerId, roundId, revision);
			}
		}

		[CustomRPC]
		public void HotPotatoAnnounce(string text, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				GameModeHud.ReceiveAnnouncement(text, 3f, showHud: true);
			}
		}

		private void InitializeNinjaHunters()
		{
			NinjaHuntersEnabled = ModeConfigMigration.BindModeEnabled(((BaseUnityPlugin)this).Config, "Game Mode Settings", "Ninja Hunters", "Ninjas with Katanas fight Hunters with FG42s in single-life team takes. Sides swap each take; when time expires, the first team to hold the first hardpoint uncontested for 5 seconds wins the take.");
			NinjaHuntersEnabled.SettingChanged += delegate
			{
				HuntersState.PushSettingsIfHost();
				GameModeManager.OnSettingsChanged();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, NinjaHuntersDefinition.Value.ModId, 0);
			ModeLobbyDataSync.RegisterKeys(NinjaHuntersDefinition.Value.SettingsLobbyDataKey, NinjaHuntersDefinition.Value.LiveLobbyDataKey);
			MyceliumNetwork.LobbyCreated += HuntersState.OnLobbyEntered;
			MyceliumNetwork.LobbyEntered += HuntersState.OnLobbyEntered;
			MyceliumNetwork.LobbyLeft += HuntersState.OnLobbyLeft;
			MyceliumNetwork.LobbyDataUpdated += HuntersState.OnLobbyDataUpdated;
			MyceliumNetwork.PlayerEntered += HuntersState.OnPlayerEntered;
			MyceliumNetwork.PlayerLeft += HuntersState.OnPlayerLeft;
		}

		[CustomRPC]
		public void SyncNinjaHuntersSettings(CSteamID hostId, int roundId, int revision, bool enabled, RPCInfo info)
		{
			//IL_0009: 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)
			if (GameModeManager.IsActive(GameMode.NinjaHunters) && NetworkAuthority.IsHostSender(info) && HuntersState.TryAcceptSettingsSnapshot(NinjaHuntersDefinition.Value, hostId, roundId, revision))
			{
				HuntersState.ApplySettings(enabled);
			}
		}

		[CustomRPC]
		public void SyncNinjaHuntersLiveState(CSteamID hostId, string assignmentsData, int teamCount, string scoresData, int takeId, int takeWinnerId, int winnerId, float takeTimeRemaining, bool tieBreakActive, int tieBreakController, float tieBreakHoldProgress, int roundId, int revision, RPCInfo info)
		{
			//IL_0009: 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)
			if (GameModeManager.IsActive(GameMode.NinjaHunters) && NetworkAuthority.IsHostSender(info))
			{
				HuntersState.ApplyLiveState(NinjaHuntersDefinition.Value, hostId, assignmentsData, teamCount, scoresData, takeId, takeWinnerId, winnerId, takeTimeRemaining, tieBreakActive, tieBreakController, tieBreakHoldProgress, roundId, revision);
			}
		}

		private void InitializeRabbitHunters()
		{
			RabbitHuntersEnabled = ModeConfigMigration.BindModeEnabled(((BaseUnityPlugin)this).Config, "Game Mode Settings", "Rabbit Hunters", "Hunters with Tromblonjs fight Rabbits with dual-wielded Stylus weapons in single-life team takes. Sides swap each take; when time expires, the first team to hold the first hardpoint uncontested for 5 seconds wins the take.");
			RabbitHuntersEnabled.SettingChanged += delegate
			{
				HuntersState.PushSettingsIfHost(RabbitHuntersDefinition.Value, RabbitHuntersEnabled.Value);
				GameModeManager.OnSettingsChanged();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, RabbitHuntersDefinition.Value.ModId, 0);
			ModeLobbyDataSync.RegisterKeys(RabbitHuntersDefinition.Value.SettingsLobbyDataKey, RabbitHuntersDefinition.Value.LiveLobbyDataKey);
		}

		[CustomRPC]
		public void SyncRabbitHuntersSettings(CSteamID hostId, int roundId, int revision, bool enabled, RPCInfo info)
		{
			//IL_0009: 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)
			if (GameModeManager.IsActive(GameMode.RabbitHunters) && NetworkAuthority.IsHostSender(info) && HuntersState.TryAcceptSettingsSnapshot(RabbitHuntersDefinition.Value, hostId, roundId, revision))
			{
				HuntersState.ApplySettings(enabled);
			}
		}

		[CustomRPC]
		public void SyncRabbitHuntersLiveState(CSteamID hostId, string assignmentsData, int teamCount, string scoresData, int takeId, int takeWinnerId, int winnerId, float takeTimeRemaining, bool tieBreakActive, int tieBreakController, float tieBreakHoldProgress, int roundId, int revision, RPCInfo info)
		{
			//IL_0009: 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)
			if (GameModeManager.IsActive(GameMode.RabbitHunters) && NetworkAuthority.IsHostSender(info))
			{
				HuntersState.ApplyLiveState(RabbitHuntersDefinition.Value, hostId, assignmentsData, teamCount, scoresData, takeId, takeWinnerId, winnerId, takeTimeRemaining, tieBreakActive, tieBreakController, tieBreakHoldProgress, roundId, revision);
			}
		}

		private void InitializeTankBattle()
		{
			TankBattleEnabled = ModeConfigMigration.BindModeEnabled(((BaseUnityPlugin)this).Config, "Game Mode Settings", "Tank Battle", "Both teams use HK_Caws. Every player has 400 health, cannot regenerate, jump, or slide, and stays crouched while moving slowly.");
			TankBattleEnabled.SettingChanged += delegate
			{
				HuntersState.PushSettingsIfHost(TankBattleDefinition.Value, TankBattleEnabled.Value);
				GameModeManager.OnSettingsChanged();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, TankBattleDefinition.Value.ModId, 0);
			ModeLobbyDataSync.RegisterKeys(TankBattleDefinition.Value.SettingsLobbyDataKey, TankBattleDefinition.Value.LiveLobbyDataKey);
		}

		[CustomRPC]
		public void SyncTankBattleSettings(CSteamID hostId, int roundId, int revision, bool enabled, RPCInfo info)
		{
			//IL_0009: 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)
			if (GameModeManager.IsActive(GameMode.TankBattle) && NetworkAuthority.IsHostSender(info) && HuntersState.TryAcceptSettingsSnapshot(TankBattleDefinition.Value, hostId, roundId, revision))
			{
				HuntersState.ApplySettings(enabled);
			}
		}

		[CustomRPC]
		public void SyncTankBattleLiveState(CSteamID hostId, string assignmentsData, int teamCount, string scoresData, int takeId, int takeWinnerId, int winnerId, float takeTimeRemaining, bool tieBreakActive, int tieBreakController, float tieBreakHoldProgress, int roundId, int revision, RPCInfo info)
		{
			//IL_0009: 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)
			if (GameModeManager.IsActive(GameMode.TankBattle) && NetworkAuthority.IsHostSender(info))
			{
				HuntersState.ApplyLiveState(TankBattleDefinition.Value, hostId, assignmentsData, teamCount, scoresData, takeId, takeWinnerId, winnerId, takeTimeRemaining, tieBreakActive, tieBreakController, tieBreakHoldProgress, roundId, revision);
			}
		}

		private void InitializeHVT()
		{
			HVTEnabled = ModeConfigMigration.BindModeEnabled(((BaseUnityPlugin)this).Config, "Game Mode Settings", "HVT", "The first legitimate killer becomes the High-Value Target and earns 3 points each second while alive. Other players hunt the HVT, and killing them transfers the role; the first player to reach the configured point limit wins.");
			HVTEnabled.SettingChanged += delegate
			{
				HVTState.PushSettingsIfHost();
				GameModeManager.OnSettingsChanged();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, 3141592657u, 0);
			ModeLobbyDataSync.RegisterKeys("Eights_HVT_Settings", "Eights_HVT_Live");
			MyceliumNetwork.LobbyCreated += HVTState.OnLobbyEntered;
			MyceliumNetwork.LobbyEntered += HVTState.OnLobbyEntered;
			MyceliumNetwork.LobbyDataUpdated += HVTState.OnLobbyDataUpdated;
			MyceliumNetwork.PlayerEntered += HVTState.OnPlayerEntered;
			MyceliumNetwork.PlayerLeft += HVTState.OnPlayerLeft;
		}

		[CustomRPC]
		public void SyncHVTSettings(CSteamID hostId, int roundId, int revision, bool enabled, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && HVTState.TryAcceptSettingsSnapshot(hostId, roundId, revision))
			{
				HVTState.ApplySettings(enabled);
			}
		}

		[CustomRPC]
		public void SyncHVTLiveState(CSteamID hostId, int hvtPlayerId, string pointsData, int winnerId, int roundId, int revision, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				HVTState.ApplyLiveState(hostId, hvtPlayerId, pointsData, winnerId, roundId, revision);
			}
		}

		[CustomRPC]
		public void HVTAnnounce(string text, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				GameModeHud.ReceiveAnnouncement(text, 3f, showHud: true);
			}
		}

		[CustomRPC]
		public void HVTAnnounceTarget(string text, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				GameModeHud.AnnounceTarget(ClientInstance.ReplaceAllPlayerNameTags(text));
			}
		}

		private void InitializeInfected()
		{
			InfectedEnabled = ModeConfigMigration.BindModeEnabled(((BaseUnityPlugin)this).Config, "Game Mode Settings", "Infected", "The host selects one infected player. Infected players use Couperets and cannot pick up guns; survivors use 10 health and random allowed weapons. Survivors who die become infected.");
			InfectedEnabled.SettingChanged += delegate
			{
				InfectedState.PushSettingsIfHost();
				GameModeManager.OnSettingsChanged();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, 2718281832u, 0);
			ModeLobbyDataSync.RegisterKeys("Eights_Infected_Settings", "Eights_Infected_Live");
			MyceliumNetwork.LobbyCreated += InfectedState.OnLobbyEntered;
			MyceliumNetwork.LobbyEntered += InfectedState.OnLobbyEntered;
			MyceliumNetwork.LobbyDataUpdated += InfectedState.OnLobbyDataUpdated;
			MyceliumNetwork.PlayerEntered += InfectedState.OnPlayerEntered;
			MyceliumNetwork.PlayerLeft += InfectedState.OnPlayerLeft;
		}

		[CustomRPC]
		public void SyncInfectedSettings(CSteamID hostId, int roundId, int revision, bool enabled, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && InfectedState.TryAcceptSettingsSnapshot(hostId, roundId, revision))
			{
				InfectedState.ApplySettings(enabled);
			}
		}

		[CustomRPC]
		public void SyncInfectedLiveState(CSteamID hostId, int initialInfectedPlayerId, string infectedData, string scoresData, int winnerId, int roundId, int revision, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				InfectedState.ApplyLiveState(hostId, initialInfectedPlayerId, infectedData, scoresData, winnerId, roundId, revision);
			}
		}

		private void InitializeInfidel()
		{
			InfidelEnabled = ModeConfigMigration.BindModeEnabled(((BaseUnityPlugin)this).Config, "Game Mode Settings", "Infidel", "One hidden Infidel faces the terrorists, with delayed weapons and different health and movement rules for each role. Terrorists earn 30 points for killing the Infidel, while the Infidel earns 50 points for outliving all terrorists; the first to reach the configured point limit wins.");
			InfidelEnabled.SettingChanged += delegate
			{
				InfidelState.PushSettingsIfHost();
				GameModeManager.OnSettingsChanged();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, 2718281831u, 0);
			ModeLobbyDataSync.RegisterKeys("Eights_Infidel_Settings", "Eights_Infidel_Live");
			MyceliumNetwork.LobbyCreated += InfidelState.OnLobbyEntered;
			MyceliumNetwork.LobbyEntered += InfidelState.OnLobbyEntered;
			MyceliumNetwork.LobbyDataUpdated += InfidelState.OnLobbyDataUpdated;
			MyceliumNetwork.PlayerEntered += InfidelState.OnPlayerEntered;
			MyceliumNetwork.PlayerLeft += InfidelState.OnPlayerLeft;
		}

		[CustomRPC]
		public void SyncInfidelSettings(CSteamID hostId, int roundId, int revision, bool enabled, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && InfidelState.TryAcceptSettingsSnapshot(hostId, roundId, revision))
			{
				InfidelState.ApplySettings(enabled);
			}
		}

		[CustomRPC]
		public void SyncInfidelLiveState(CSteamID hostId, string scoresData, int winnerId, int takeId, bool weaponsUnlocked, float takeTimeRemaining, int roundId, int revision, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				InfidelState.ApplyLiveState(hostId, scoresData, winnerId, takeId, weaponsUnlocked, takeTimeRemaining, roundId, revision);
			}
		}

		[CustomRPC]
		public void SyncInfidelRole(CSteamID hostId, int takeId, bool isInfidel, bool announce, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				InfidelState.ApplyLocalRole(hostId, takeId, isInfidel, announce);
			}
		}

		[CustomRPC]
		public void SyncInfidelBeep(CSteamID hostId, int takeId, int beepId, Vector3 position, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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 (NetworkAuthority.IsHostSender(info))
			{
				InfidelState.ApplyInfidelBeep(hostId, takeId, beepId, position);
			}
		}

		private void InitializeJuggernaut()
		{
			JuggernautEnabled = ModeConfigMigration.BindModeEnabled(((BaseUnityPlugin)this).Config, "Game Mode Settings", "Juggernaut", "The first killer becomes the powerful Juggernaut, while everyone else hunts them for the crown. Normal kills award 10 points, killing the Juggernaut awards 20 points to the new holder, and the first player to reach the configured point limit wins.");
			JuggernautEnabled.SettingChanged += delegate
			{
				JuggernautState.PushSettingsIfHost();
				GameModeManager.OnSettingsChanged();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, 3141592656u, 0);
			ModeLobbyDataSync.RegisterKeys("Eights_Juggernaut_Settings", "Eights_Juggernaut_Live");
			MyceliumNetwork.LobbyCreated += JuggernautState.OnLobbyEntered;
			MyceliumNetwork.LobbyEntered += JuggernautState.OnLobbyEntered;
			MyceliumNetwork.LobbyDataUpdated += JuggernautState.OnLobbyDataUpdated;
			MyceliumNetwork.PlayerEntered += JuggernautState.OnPlayerEntered;
			MyceliumNetwork.PlayerLeft += JuggernautState.OnPlayerLeft;
		}

		[CustomRPC]
		public void SyncJuggernautSettings(CSteamID hostId, int roundId, int revision, bool enabled, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && JuggernautState.TryAcceptSettingsSnapshot(hostId, roundId, revision))
			{
				JuggernautState.ApplySettings(enabled);
			}
		}

		[CustomRPC]
		public void SyncJuggernautLiveState(CSteamID hostId, int juggernautPlayerId, int juggernautKills, string pointsData, int roundId, int revision, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				JuggernautState.ApplyLiveState(hostId, juggernautPlayerId, juggernautKills, pointsData, roundId, revision);
			}
		}

		[CustomRPC]
		public void JuggernautAnnounce(string text, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				GameModeHud.ReceiveAnnouncement(text, 3f, showHud: true);
			}
		}

		[CustomRPC]
		public void JuggernautAnnounceTarget(string text, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				GameModeHud.AnnounceTarget(ClientInstance.ReplaceAllPlayerNameTags(text));
			}
		}

		private void InitializeKillTheRat()
		{
			KillTheRatEnabled = ModeConfigMigration.BindModeEnabled(((BaseUnityPlugin)this).Config, "Game Mode Settings", "Kill The Rat", "One player becomes the Rat and earns 3 points each second while alive, while the other players hunt them. Killing the Rat awards 10 points, and the first player to reach the configured point limit wins.");
			KillTheRatEnabled.SettingChanged += delegate
			{
				KillTheRatState.PushSettingsIfHost();
				GameModeManager.OnSettingsChanged();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, 3141592655u, 0);
			ModeLobbyDataSync.RegisterKeys("Eights_KillTheRat_Settings", "Eights_KillTheRat_Live");
			MyceliumNetwork.LobbyCreated += KillTheRatState.OnLobbyEntered;
			MyceliumNetwork.LobbyEntered += KillTheRatState.OnLobbyEntered;
			MyceliumNetwork.LobbyDataUpdated += KillTheRatState.OnLobbyDataUpdated;
			MyceliumNetwork.PlayerEntered += KillTheRatState.OnPlayerEntered;
			MyceliumNetwork.PlayerLeft += KillTheRatState.OnPlayerLeft;
		}

		[CustomRPC]
		public void SyncKillTheRatSettings(CSteamID hostId, int roundId, int revision, bool enabled, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && KillTheRatState.TryAcceptSettingsSnapshot(hostId, roundId, revision))
			{
				KillTheRatState.ApplySettings(enabled);
			}
		}

		[CustomRPC]
		public void SyncKillTheRatLiveState(CSteamID hostId, int ratPlayerId, string pointsData, int winnerId, int roundId, int revision, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				KillTheRatState.ApplyLiveState(hostId, ratPlayerId, pointsData, winnerId, roundId, revision);
			}
		}

		[CustomRPC]
		public void KillTheRatAnnounce(string text, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				GameModeHud.ReceiveAnnouncement(text, 3f, showHud: true);
			}
		}

		private void InitializeMichaelMeyers()
		{
			MichaelMeyersEnabled = ModeConfigMigration.BindModeEnabled(((BaseUnityPlugin)this).Config, "Game Mode Settings", "Michael Meyers", "Michael hunts the other players with a Couperet while everyone else tries to stay alive. Michael moves 5% faster. Everyone has 10 health until the final battle, when the last survivor gets a Couperet and both final players return to 100 health. If at least two players remain after 90 seconds, the take ends without awarding points.");
			MichaelMeyersEnabled.SettingChanged += delegate
			{
				MichaelMeyersState.PushSettingsIfHost();
				GameModeManager.OnSettingsChanged();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, 3141592654u, 0);
			ModeLobbyDataSync.RegisterKeys("Eights_MichaelMeyers_Settings", "Eights_MichaelMeyers_Live");
			MyceliumNetwork.LobbyCreated += MichaelMeyersState.OnLobbyEntered;
			MyceliumNetwork.LobbyEntered += MichaelMeyersState.OnLobbyEntered;
			MyceliumNetwork.LobbyDataUpdated += MichaelMeyersState.OnLobbyDataUpdated;
			MyceliumNetwork.PlayerEntered += MichaelMeyersState.OnPlayerEntered;
			MyceliumNetwork.PlayerLeft += MichaelMeyersState.OnPlayerLeft;
		}

		[CustomRPC]
		public void SyncMichaelMeyersSettings(CSteamID hostId, int roundId, int revision, bool enabled, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && MichaelMeyersState.TryAcceptSettingsSnapshot(hostId, roundId, revision))
			{
				MichaelMeyersState.ApplySettings(enabled);
			}
		}

		[CustomRPC]
		public void SyncMichaelMeyersLiveState(CSteamID hostId, int michaelPlayerId, int survivorCount, bool oneVsOne, string scoresData, float timeRemaining, int roundId, int revision, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				MichaelMeyersState.ApplyLiveState(hostId, michaelPlayerId, survivorCount, oneVsOne, scoresData, timeRemaining, roundId, revision);
			}
		}

		[CustomRPC]
		public void MichaelMeyersAnnounce(string text, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				GameModeHud.ReceiveAnnouncement(text, 3f, showHud: true);
			}
		}

		private void InitializeOneInTheChamber()
		{
			OneInTheChamberEnabled = ModeConfigMigration.BindModeEnabled(((BaseUnityPlugin)this).Config, "Game Mode Settings", "One in the Chamber", "Each player gets one pistol shot and a Couperet, with no respawns during the take. The last player alive wins 50 points, and the first player to reach the configured point limit wins.");
			OneInTheChamberEnabled.SettingChanged += delegate
			{
				OneInTheChamberState.PushSettingsIfHost();
				GameModeManager.OnSettingsChanged();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, 2718281829u, 0);
			ModeLobbyDataSync.RegisterKeys("Eights_OneInTheChamber_Settings", "Eights_OneInTheChamber_Live");
			MyceliumNetwork.LobbyCreated += OneInTheChamberState.OnLobbyEntered;
			MyceliumNetwork.LobbyEntered += OneInTheChamberState.OnLobbyEntered;
			MyceliumNetwork.LobbyDataUpdated += OneInTheChamberState.OnLobbyDataUpdated;
			MyceliumNetwork.PlayerEntered += OneInTheChamberState.OnPlayerEntered;
			MyceliumNetwork.PlayerLeft += OneInTheChamberState.OnPlayerLeft;
		}

		[CustomRPC]
		public void SyncOneInTheChamberSettings(CSteamID hostId, int roundId, int revision, bool enabled, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && OneInTheChamberState.TryAcceptSettingsSnapshot(hostId, roundId, revision))
			{
				OneInTheChamberState.ApplySettings(enabled);
			}
		}

		[CustomRPC]
		public void SyncOneInTheChamberLiveState(CSteamID hostId, string aliveData, string bulletsData, string scoresData, int takeId, int winnerId, float loadoutSecondsRemaining, int roundId, int revision, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				OneInTheChamberState.ApplyLiveState(hostId, aliveData, bulletsData, scoresData, takeId, winnerId, loadoutSecondsRemaining, roundId, revision);
			}
		}

		[CustomRPC]
		public void OneInTheChamberAnnounce(string text, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				GameModeHud.ReceiveAnnouncement(text, 3f, showHud: true);
			}
		}

		private void Awake()
		{
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_036e: Expected O, but got Unknown
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			InitializeSafely("compatibility checks", FishNetCompatibility.LogPreflight);
			InitializeSafely("Mycelium transport recovery", MyceliumTransportRecovery.Initialize);
			InitializeSafely("weapon service", WeaponService.Initialize);
			InitializeSafely("game mode manager", GameModeManager.Initialize);
			InitializeSafely("shared player lookup", PlayerLookup.Initialize);
			InitializeSafely("ModMenu integration", ModMenuIntegration.Initialize);
			InitializeSafely("shared player outline", PlayerOutline.Initialize);
			InitializeSafely("blood cleanup", InitializeBloodCleanup);
			InitializeSafely("global modifiers", InitializeGlobalModifiers);
			InitializeSafely("health settings", InitializeHealthSettings);
			InitializeSafely("global weapons", InitializeGlobalWeapons);
			InitializeSafely("default game mode", InitializeDefaultGameMode);
			InitializeSafely("Michael Meyers", InitializeMichaelMeyers);
			InitializeSafely("Kill The Rat", InitializeKillTheRat);
			InitializeSafely("HVT", InitializeHVT);
			InitializeSafely("Infected", InitializeInfected);
			InitializeSafely("One in the Chamber", InitializeOneInTheChamber);
			InitializeSafely("Hot Potato", InitializeHotPotato);
			InitializeSafely("Infidel", InitializeInfidel);
			InitializeSafely("Assassin", InitializeAssassin);
			InitializeSafely("Free For All", InitializeFFA);
			InitializeSafely("Juggernaut", InitializeJuggernaut);
			InitializeSafely("Gun Game", InitializeGunGame);
			InitializeSafely("Sniper Battle", InitializeSniperBattle);
			InitializeSafely("Hardpoint", InitializeHardpoint);
			InitializeSafely("Capture the Flag", InitializeCaptureTheFlag);
			InitializeSafely("Search and Destroy", InitializeSearchAndDestroy);
			InitializeSafely("Team Deathmatch", InitializeTeamDeathmatch);
			InitializeSafely("Ninja Hunters", InitializeNinjaHunters);
			InitializeSafely("Rabbit Hunters", InitializeRabbitHunters);
			InitializeSafely("Tank Battle", InitializeTankBattle);
			((BaseUnityPlugin)this).Config.Save();
			try
			{
				((Component)this).gameObject.AddComponent<GameModeHud>();
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("[GameModeHud] Startup failed: " + ex.GetBaseException().Message));
			}
			PatchAllSafely(new Harmony("Eights"));
		}

		private static void InitializeSafely(string featureName, Action initialize)
		{
			try
			{
				initialize();
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("[Startup] Failed to initialize " + featureName + ": " + ex.GetBaseException().Message));
			}
		}

		private static void PatchAllSafely(Harmony harmony)
		{
			Type[] array;
			try
			{
				array = (from type2 in AccessTools.GetTypesFromAssembly(typeof(Plugin).Assembly)
					where type2.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0
					select type2).OrderBy<Type, string>((Type type2) => type2.FullName, StringComparer.Ordinal).ToArray();
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("[Harmony] Could not discover patch classes: " + ex.GetBaseException().Message));
				return;
			}
			Type[] array2 = array;
			foreach (Type type in array2)
			{
				try
				{
					if (harmony.CreateClassProcessor(type).Patch().Count() == 0)
					{
						HarmonyPatchStatus.RecordFailure(type, "no patch target was installed");
						Logger.LogError((object)("[Harmony] Disabled patch class " + type.FullName + ": no patch target was installed."));
					}
				}
				catch (Exception ex2)
				{
					HarmonyPatchStatus.RecordFailure(type, ex2.GetBaseException().Message);
					Logger.LogError((object)("[Harmony] Disabled patch class " + type.FullName + ": " + ex2.GetBaseException().Message));
				}
			}
		}

		private void Update()
		{
			BloodCleanupState.Update();
			PositionMarkerDebug.Update();
			MyceliumTransportRecovery.Update();
			GameModeManager.EnsureVanillaScene();
			GameModeManager.UpdatePreRoundTimer();
			GameModeManager.UpdateRoundEndCountdown();
			GameModeManager.PeriodicPushIfHost();
			GameModeManager.PeriodicActiveModePushIfHost();
			GameModeManager.PollLobbyStateIfClient();
			PlayerNameSync.PeriodicPushIfHost();
			PlayerNameSync.PollIfClient();
			DefaultGameModeState.ServerTick(Time.unscaledDeltaTime);
			DefaultGameModeState.ClientTick(Time.unscaledDeltaTime);
			CaptureTheFlagState.ServerTick(Time.unscaledDeltaTime);
			MichaelMeyersState.ServerTick(Time.unscaledDeltaTime);
			MichaelMeyersState.ClientTick(Time.unscaledDeltaTime);
			InfidelState.ServerTick(Time.unscaledDeltaTime);
			InfidelState.ClientTick(Time.unscaledDeltaTime);
			AssassinState.ServerTick(Time.unscaledDeltaTime);
			AssassinState.ClientTick(Time.unscaledDeltaTime);
			SearchAndDestroyState.ServerTick(Time.unscaledDeltaTime);
			HuntersState.ServerTick(Time.unscaledDeltaTime);
			ModeTimeoutState.ServerTick(Time.unscaledDeltaTime);
			ModeTimeoutState.ClientTick(Time.unscaledDeltaTime);
			SearchAndDestroyState.PollLocalInput();
			SearchAndDestroyState.ApplyLocalMovementLock();
			GlobalModifiersState.PeriodicPushIfHost();
			GlobalModifiersState.PollSettingsIfClient();
			HealthSettingsState.PeriodicPushIfHost();
			HealthSettingsState.PollSettingsIfClient();
			GameModeHud.PeriodicPushTakeResult();
			HealthSettingsState.ServerTick();
			WeaponSettingsState.UpdateLocalCycle();
			WeaponSettingsState.PeriodicPushIfHost();
			WeaponSettingsState.PollSettingsIfClient();
			WeaponSettingsState.EnsureCycleLoadouts();
			GameModeManager.EnsureActiveModeLoadouts();
			WeaponSettingsState.EnsureDefaultKnifeLoadouts();
			PlayerOutline.EnforceOutline();
			TeammateMarker.Enforce();
			HardpointMarker.Update();
			HuntersMarker.Update();
			CaptureTheFlagMarker.Update();
			SearchAndDestroyMarker.Update();
			RespawnProtection.Update();
		}

		private void InitializeSearchAndDestroy()
		{
			SearchAndDestroyEnabled = ModeConfigMigration.BindModeEnabled(((BaseUnityPlugin)this).Config, "Game Mode Settings", "Search and Destroy", "Two teams alternate between attacking and defending, with attackers planting a bomb at one of two sites and defenders defusing it or eliminating the attackers. A take win awards 40 points with no respawns, and the first team to reach the configured point limit wins.");
			SearchAndDestroyEnabled.SettingChanged += delegate
			{
				SearchAndDestroyState.PushSettingsIfHost();
				GameModeManager.OnSettingsChanged();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, 1618033996u, 0);
			ModeLobbyDataSync.RegisterKeys("Eights_SnD_Settings", "Eights_SnD_Live");
			MyceliumNetwork.LobbyCreated += SearchAndDestroyState.OnLobbyEntered;
			MyceliumNetwork.LobbyEntered += SearchAndDestroyState.OnLobbyEntered;
			MyceliumNetwork.LobbyLeft += SearchAndDestroyState.OnLobbyLeft;
			MyceliumNetwork.LobbyDataUpdated += SearchAndDestroyState.OnLobbyDataUpdated;
			MyceliumNetwork.PlayerEntered += SearchAndDestroyState.OnPlayerEntered;
			MyceliumNetwork.PlayerLeft += SearchAndDestroyState.OnPlayerLeft;
		}

		[CustomRPC]
		public void SyncSearchAndDestroySettings(CSteamID hostId, int roundId, int revision, bool enabled, bool ignoredLegacySpawnerFlag, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && SearchAndDestroyState.TryAcceptSettingsSnapshot(hostId, roundId, revision))
			{
				SearchAndDestroyState.ApplySettings(enabled);
			}
		}

		[CustomRPC]
		public void SyncSearchAndDestroyLiveState(CSteamID hostId, string assignmentsData, int teamCount, string scoresData, string stateData, int takeId, int winnerId, int roundId, int revision, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				SearchAndDestroyState.ApplyLiveState(hostId, assignmentsData, teamCount, scoresData, stateData, takeId, winnerId, roundId, revision);
			}
		}

		[CustomRPC]
		public void RequestSearchAndDestroyInteraction(int playerId, int commandId, bool pressed, bool lookingAtBomb, RPCInfo info)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			SearchAndDestroyState.HandleInteractionRequest(playerId, commandId, pressed, lookingAtBomb, info);
		}

		[CustomRPC]
		public void SyncScorePopup(int amount, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && amount > 0 && amount <= 100)
			{
				GameModeHud.ShowScorePopup(amount);
			}
		}

		[CustomRPC]
		public void SyncGameModeAnnouncement(string text, float durationSeconds, bool showHud, RPCInfo info)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			if (!MyceliumNetwork.IsHost && NetworkAuthority.IsHostSender(info) && !string.IsNullOrWhiteSpace(text) && !float.IsNaN(durationSeconds) && !float.IsInfinity(durationSeconds))
			{
				GameModeHud.ReceiveAnnouncement(text, Mathf.Clamp(durationSeconds, 1f, 8f), showHud);
			}
		}

		[CustomRPC]
		public void SyncTakeResult(int resultId, string text, float durationSeconds, RPCInfo info)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			if (!MyceliumNetwork.IsHost && NetworkAuthority.IsHostSender(info) && resultId >= 0 && !string.IsNullOrWhiteSpace(text) && !float.IsNaN(durationSeconds) && !float.IsInfinity(durationSeconds))
			{
				GameModeHud.ReceiveTakeResult(resultId, text, Mathf.Clamp(durationSeconds, 1f, 8f));
			}
		}

		[CustomRPC]
		public void SyncGlobalSettings(CSteamID hostId, int roundId, int revision, float respawnDelaySeconds, int preRoundSeconds, int pointsToWin, bool enableMapOverrides, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && GameModeManager.TryAcceptGlobalSettingsSnapshot(hostId, roundId, revision))
			{
				GameModeManager.ApplyGlobalSettings(respawnDelaySeconds, preRoundSeconds, pointsToWin, enableMapOverrides);
			}
		}

		[CustomRPC]
		public void SyncActiveGameMode(CSteamID hostId, int mode, int roundId, int phase, int revision, string mapName, bool mapOverridesEnabled, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && GameModeManager.TryAcceptActiveModeSnapshot(hostId, roundId, revision, "active-mode-rpc"))
			{
				GameModeManager.ApplyActiveMode(mode, roundId, phase, mapName, mapOverridesEnabled);
			}
		}

		[CustomRPC]
		public void SyncModeTimeout(CSteamID hostId, float timeRemaining, bool suddenDeath, int roundId, int revision, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				ModeTimeoutState.ApplyLiveState(hostId, timeRemaining, suddenDeath, roundId, revision);
			}
		}

		[CustomRPC]
		public void MyceliumSessionProbe(int probeId, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			MyceliumTransportRecovery.OnProbe(info.SenderSteamID, probeId);
		}

		[CustomRPC]
		public void MyceliumSessionProbeAck(int probeId, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			MyceliumTransportRecovery.OnProbeAck(info.SenderSteamID, probeId);
		}

		[CustomRPC]
		public void SyncPlayerDisplayNames(CSteamID hostId, int roundId, int revision, string payload, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				PlayerNameSync.ApplySnapshot(hostId, roundId, revision, payload, "rpc");
			}
		}

		[CustomRPC]
		public void SyncOutlineRoleState(CSteamID hostId, int mode, int playerId, int roundId, int revision, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				PlayerOutline.ApplyRoleSnapshot(hostId, mode, playerId, roundId, revision);
			}
		}

		[CustomRPC]
		public void SyncRespawnProtection(int playerId, bool pending, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				RespawnProtection.SetPendingRespawn(playerId, pending);
			}
		}

		private void InitializeSniperBattle()
		{
			SniperBattleEnabled = ModeConfigMigration.BindModeEnabled(((BaseUnityPlugin)this).Config, "Game Mode Settings", "Sniper Battle", "Players respawn with only the M2000 sniper rifle, unlimited ammunition, and reduced health. Each kill awards 10 points, and the first player to reach the configured point limit wins.");
			SniperBattleEnabled.SettingChanged += delegate
			{
				SniperBattleState.PushSettingsIfHost();
				GameModeManager.OnSettingsChanged();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, 1618033992u, 0);
			ModeLobbyDataSync.RegisterKeys("Eights_SniperBattle_Settings", "Eights_SniperBattle_Live");
			MyceliumNetwork.LobbyCreated += SniperBattleState.OnLobbyEntered;
			MyceliumNetwork.LobbyEntered += SniperBattleState.OnLobbyEntered;
			MyceliumNetwork.LobbyDataUpdated += SniperBattleState.OnLobbyDataUpdated;
			MyceliumNetwork.PlayerEntered += SniperBattleState.OnPlayerEntered;
			MyceliumNetwork.PlayerLeft += SniperBattleState.OnPlayerLeft;
		}

		[CustomRPC]
		public void SyncSniperBattleSettings(CSteamID hostId, int roundId, int revision, bool enabled, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && SniperBattleState.TryAcceptSettingsSnapshot(hostId, roundId, revision, "sniper-battle-rpc"))
			{
				SniperBattleState.ApplySettings(enabled);
			}
		}

		[CustomRPC]
		public void SyncSniperBattleLiveState(CSteamID hostId, string pointsData, int winnerId, int roundId, int revision, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				SniperBattleState.ApplyLiveState(hostId, pointsData, winnerId, roundId, revision, "rpc");
			}
		}

		[CustomRPC]
		public void SniperBattleAnnounce(string text, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				GameModeHud.ReceiveAnnouncement(text, 3f, showHud: true);
			}
		}

		private void InitializeTeamDeathmatch()
		{
			TeamDeathmatchEnabled = ModeConfigMigration.BindModeEnabled(((BaseUnityPlugin)this).Config, "Game Mode Settings", "Team Deathmatch", "Teams respawn and fight for kills throughout the match. Each kill awards 10 points to the team, and the first team to reach the configured point limit wins.");
			TeamDeathmatchEnabled.SettingChanged += delegate
			{
				TeamDeathmatchState.PushSettingsIfHost();
				GameModeManager.OnSettingsChanged();
			};
			MyceliumNetwork.RegisterNetworkObject((object)this, 1618033997u, 0);
			ModeLobbyDataSync.RegisterKeys("Eights_TDM_Settings", "Eights_TDM_Live");
			MyceliumNetwork.LobbyCreated += TeamDeathmatchState.OnLobbyEntered;
			MyceliumNetwork.LobbyEntered += TeamDeathmatchState.OnLobbyEntered;
			MyceliumNetwork.LobbyLeft += TeamDeathmatchState.OnLobbyLeft;
			MyceliumNetwork.LobbyDataUpdated += TeamDeathmatchState.OnLobbyDataUpdated;
			MyceliumNetwork.PlayerEntered += TeamDeathmatchState.OnPlayerEntered;
			MyceliumNetwork.PlayerLeft += TeamDeathmatchState.OnPlayerLeft;
		}

		[CustomRPC]
		public void SyncTeamDeathmatchSettings(CSteamID hostId, int roundId, int revision, bool enabled, bool ignoredLegacySpawnerFlag, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info) && TeamDeathmatchState.TryAcceptSettingsSnapshot(hostId, roundId, revision))
			{
				TeamDeathmatchState.ApplySettings(enabled);
			}
		}

		[CustomRPC]
		public void SyncTeamDeathmatchLiveState(CSteamID hostId, string assignmentsData, int teamCount, string scoresData, int roundId, int revision, RPCInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkAuthority.IsHostSender(info))
			{
				TeamDeathmatchState.ApplyLiveState(hostId, assignmentsData, teamCount, scoresData, roundId, revision);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerManager), "SpawnPlayer", new Type[]
	{
		typeof(int),
		typeof(int),
		typeof(Vector3),
		typeof(Quaternion)
	})]
	internal static class PlayerManager_AssassinSpawn_Patch
	{
		private static void Postfix(PlayerManager __instance)
		{
			if (GameModeManager.IsActive(GameMode.Assassin) && !WeaponService.IsFinalGameScreen && !((Object)(object)__instance.player == (Object)null))
			{
				ClientInstance component = ((Component)__instance).GetComponent<ClientInstance>();
				if ((Object)(object)component != (Object)null)
				{
					AssassinState.RequestLoadout(component.PlayerId);
				}
			}
		}
	}
	internal static class AssassinState
	{
		internal const string SettingsLobbyDataKey = "Eights_Assassin_Settings";

		internal const string LiveLobbyDataKey = "Eights_Assassin_Live";

		internal const string AssassinWeaponName = "Silenzzio";

		internal const string KingWeaponName = "Taser";

		internal const string BodyguardWeaponName = "Glock";

		internal const int MinWeaponDelaySeconds = 5;

		internal const int MaxWeaponDelaySeconds = 30;

		private const int DefaultWeaponDelaySeconds = 15;

		internal const int PointsForAssassinWin = 50;

		internal const int PointsForKingSurvival = 30;

		internal const int PointsForBodyguardSurvival = 10;

		internal const int PointsForBodyguardKill = 20;

		internal const float DefaultTakeTimeLimitSeconds = 90f;

		internal static bool Enabled;

		internal static readonly Dictionary<int, int> Scores = new Dictionary<int, int>();

		private static readonly HashSet<int> AlivePlayers = new HashSet<int>();

		private static readonly Dictionary<int, float> PendingLoadouts = new Dictionary<int, float>();

		private static readonly ModeSyncState Sync = new ModeSyncState();

		private static float _nextLoadoutCheckTime;

		private static float _nextClientLivePollTime;

		private static float _takeTimeRemaining;

		private static int _takeId;

		private static int _localRoleTakeId = -1;

		private static int _localRoleAnnouncedTakeId = -1;

		private static bool _localRoleAnnouncementPending;

		private static bool _startRetryPending;

		private static bool _takeEnding;

		internal static int KingPlayerId { get; private set; } = -1;

		internal static int WinnerId { get; private set; } = -1;

		internal static int PointsToWin => GameModeManager.EffectivePointsToWin;

		internal static bool WeaponsUnlocked { get; private set; }

		internal static int WeaponDelaySeconds { get; private set; } = 15;

		internal static float TakeTimeRemaining => Mathf.Max(0f, _takeTimeRemaining);

		internal static float RoleAnnouncementDuration => (float)WeaponDelaySeconds + 10f;

		internal static bool LocalIsAssassin { get; private set; }

		internal static bool LocalIsKing { get; private set; }

		private static int AssassinPlayerId { get; set; } = -1;

		internal static void ApplySettings(bool enabled)
		{
			bool num = Enabled != enabled;
			Enabled = enabled;
			if (num)
			{
				ResetMatchState();
			}
		}

		private static void ApplySettingsFromHostConfig()
		{
			ApplySettings(Plugin.AssassinEnabled.Value);
		}

		internal static void PushSettingsIfHost()
		{
			//IL_0024: 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)
			if (MyceliumNetwork.InLobby && MyceliumNetwork.IsHost)
			{
				ApplySettingsFromHostConfig();
				int num = Sync.NextSettingsRevision();
				ModeLobbyDataSync.Publish("Eights_Assassin_Settings", MyceliumNetwork.LobbyHost, GameModeManager.RoundId, num, Plugin.AssassinEnabled.Value ? "1" : "0");
				MyceliumNetwork.RPC(3141592658u, "SyncAssassinSettings", (ReliableType)1, new object[4]
				{
					MyceliumNetwork.LobbyHost,
					GameModeManager.RoundId,
					num,
					Plugin.AssassinEnabled.Value
				});
			}
		}

		internal static void PeriodicPushSettingsIfHost()
		{
			if (Sync.IsSettingsPushDue())
			{
				PushSettingsIfHost();
			}
		}

		internal static void PeriodicPushIfHost()
		{
			if (Sync.IsLivePushDue())
			{
				BroadcastLiveState();
				SendRoleStates(announce: true);
			}
		}

		internal static void PollLiveStateIfClient()
		{
			if (!MyceliumNetwork.IsHost && MyceliumNetwork.InLobby && GameModeManager.IsActive(GameMode.Assassin) && !(Time.unscaledTime < _nextClientLivePollTime))
			{
				_nextClientLivePollTime = Time.unscaledTime + 1f;
				ApplyLobbyLiveSnapshot();
			}
		}

		internal static void OnLobbyEntered()
		{
			Sync.ResetForLobby();
			_nextClientLivePollTime = 0f;
			if (MyceliumNetwork.IsHost)
			{
				ApplySettingsFromHostConfig();
				ResetMatchState();
				PushSettingsIfHost();
				BroadcastLiveState();
			}
			else
			{
				ApplyLobbySettingsSnapshot();
				ApplyLobbyLiveSnapshot();
			}
		}

		internal static void OnLobbyLeft()
		{
			Sync.ResetForLobby();
			_nextClientLivePollTime = 0f;
			ResetMatchState();
		}

		internal static void OnLobbyDataUpdated(List<string> keys)
		{
			if (!MyceliumNetwork.IsHost && MyceliumNetwork.InLobby)
			{
				if (ModeLobbyDataSync.ContainsKey(keys, "Eights_Assassin_Settings"))
				{
					ApplyLobbySettingsSnapshot();
				}
				if (ModeLobbyDataSync.ContainsKey(keys, "Eights_Assassin_Live"))
				{
					ApplyLobbyLiveSnapshot();
				}
			}
		}

		internal static void OnPlayerEntered(CSteamID player)
		{
			//IL_0012: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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_0125: Unknown result type (might be due to invalid IL or missing references)
			if (!MyceliumNetwork.IsHost)
			{
				return;
			}
			MyceliumNetwork.RPCTarget(3141592658u, "SyncAssassinSettings", player, (ReliableType)1, new object[4]
			{
				MyceliumNetwork.LobbyHost,
				GameModeManager.RoundId,
				Sync.SettingsRevision,
				Plugin.AssassinEnabled.Value
			});
			MyceliumNetwork.RPCTarget(3141592658u, "SyncAssassinLiveState", player, (ReliableType)1, new object[10]
			{
				MyceliumNetwork.LobbyHost,
				KingPlayerId,
				SerializeScores(),
				WinnerId,
				_takeId,
				WeaponsUnlocked,
				WeaponDelaySeconds,
				_takeTimeRemaining,
				GameModeManager.RoundId,
				Sync.LiveRevision
			});
			if (TakeIsActive())
			{
				int num = FindPlayerId(player);
				if (num >= 0)
				{
					AlivePlayers.Add(num);
					Scores.TryAdd(num, 0);
					SendRoleToPlayer(player, num, announce: true);
				}
			}
		}

		internal static void OnPlayerLeft(CSteamID player)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (!MyceliumNetwork.IsHost)
			{
				return;
			}
			int num = PlayerLookup.FindPlayerId(player);
			int num2;
			if (num >= 0)
			{
				num2 = (AlivePlayers.Contains(num) ? 1 : 0);
				if (num2 != 0 && GameModeManager.IsActive(GameMode.Assassin) && WinnerId < 0 && !_takeEnding)
				{
					OnServerKill(num, -1);
				}
			}
			else
			{
				num2 = 0;
			}
			bool flag = num2 != 0 || (num >= 0 && Scores.Remove(num));
			PendingLoadouts.Remove(num);
			AlivePlayers.Remove(num);
			if (num >= 0 && AssassinPlayerId == num)
			{
				AssassinPlayerId = -1;
				flag = true;
			}
			if (num >= 0 && KingPlayerId == num)
			{
				KingPlayerId = -1;
				flag = true;
			}
			if (flag && GameModeManager.IsActive(GameMode.Assassin))
			{
				BroadcastLiveState();
			}
		}

		internal static bool TryAcceptSettingsSnapshot(CSteamID hostId, int roundId, int revision)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return Sync.TryAcceptSettingsSnapshot(hostId, roundId, revision);
		}

		internal static void ResetMatchState()
		{
			Sync.ResetLiveState();
			_nextLoadoutCheckTime = 0f;
			_takeTimeRemaining = 0f;
			_takeId = 0;
			WeaponDelaySeconds = 15;
			_localRoleTakeId = -1;
			_localRoleAnnouncedTakeId = -1;
			_localRoleAnnouncementPending = false;
			_startRetryPending = false;
			_takeEnding = false;
			AssassinPlayerId = -1;
			KingPlayerId = -1;
			WinnerId = -1;
			WeaponsUnlocked = false;
			LocalIsAssassin = false;
			LocalIsKing = false;
			AlivePlayers.Clear();
			PendingLoadouts.Clear();
			Scores.Clear();
		}

		internal static void ApplyLiveState(CSteamID hostId, int kingPlayerId, string scoresData, int winnerId, int takeId, bool weaponsUnlocked, int weaponDelaySeconds, float takeTimeRemaining, int roundId, int revision, string source = "rpc")
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			int lastLiveRoundId = Sync.LastLiveRoundId;
			if (kingPlayerId < -1 || winnerId < -1 || weaponDelaySeconds < 5 || weaponDelaySeconds > 30 || takeTimeRemaining < 0f || float.IsNaN(takeTimeRemaining) || float.IsInfinity(takeTimeRemaining) || takeTimeRemaining > 90f || !Sync.TryAcceptLiveSnapshot(hostId, roundId, revision, source))
			{
				return;
			}
			KingPlayerId = kingPlayerId;
			_takeId = ((roundId != lastLiveRoundId) ? takeId : Math.Max(_takeId, takeId));
			WinnerId = winnerId;
			WeaponsUnlocked = weaponsUnlocked;
			WeaponDelaySeconds = weaponDelaySeconds;
			_takeTimeRemaining = takeTimeRemaining;
			Scores.Clear();
			foreach (KeyValuePair<int, int> item in ScoreCodec.Parse(scoresData, PointsToWin))
			{
				Scores[item.Key] = item.Value;
			}
		}

		internal static void OnRoundStarted()
		{
			if (Enabled && GameModeManager.IsActive(GameMode.Assassin) && MyceliumNetwork.IsHost)
			{
				Scores.Clear();
				WinnerId = -1;
				StartTake();
			}
		}

		internal static void ServerTick(float deltaTime)
		{
			if (Enabled && MyceliumNetwork.IsHost && GameModeManager.IsActive(GameMode.Assassin) && GameModeManager.IsRoundGameplayActive && WinnerId < 0 && TakeIsActive())
			{
				_takeTimeRemaining = Mathf.Max(0f, _takeTimeRemaining - Mathf.Max(0f, deltaTime));
				if (_takeTimeRemaining <= 0f)
				{
					CompleteTimeoutWin();
				}
			}
		}

		internal static void ClientTick(float deltaTime)
		{
			TryAnnounceLocalRole();
			if (!MyceliumNetwork.IsHost && Enabled && GameModeManager.IsActive(GameMode.Assassin) && GameModeManager.IsRoundGameplayActive && WinnerId < 0 && TakeIsActive())
			{
				_takeTimeRemaining = Mathf.Max(0f, _takeTimeRemaining - Mathf.Max(0f, deltaTime));
			}
		}

		internal static void OnServerKill(int deadPlayerId, int killerId)
		{
			if (!Enabled || !GameModeManager.IsActive(GameMode.Assassin) || WinnerId >= 0 || _takeEnding)
			{
				return;
			}
			bool num = AlivePlayers.Remove(deadPlayerId);
			bool flag = deadPlayerId == KingPlayerId;
			bool flag2 = deadPlayerId == AssassinPlayerId;
			if (!num && !flag && !flag2)
			{
				return;
			}
			if (AssassinRules.IsTerminalDeath(flag, flag2) && flag)
			{
				AwardScore(AssassinPlayerId, AssassinRules.GetAssassinAward(flag));
				GameModeHud.BroadcastTakeResult("<b>" + PlayerLookup.GetPlayerNameTag(AssassinPlayerId) + " won the take</b>\n<i>The king was eliminated</i>");
				AnnounceResult("The King was killed. The Assassin was " + PlayerLookup.GetPlayerNameTag(AssassinPlayerId) + ".");
				FinishTake();
			}
			else if (flag2)
			{
				AwardScore(KingPlayerId, AssassinRules.GetKingAward(flag2));
				foreach (int key in Scores.Keys)
				{
					if (key != KingPlayerId && key != AssassinPlayerId)
					{
						AwardScore(key, AssassinRules.GetBodyguardAward(flag2));
					}
				}
				bool flag3 = killerId >= 0 && killerId != deadPlayerId && killerId != KingPlayerId && killerId != AssassinPlayerId;
				if (flag3)
				{
					AwardScore(killerId, AssassinRules.GetBodyguardKillerAward(flag2, flag3, killerId == deadPlayerId));
				}
				string text = ((KingPlayerId >= 0) ? PlayerLookup.GetPlayerNameTag(KingPlayerId) : "the king");
				GameModeHud.BroadcastTakeResult("<b>" + text + " and the bodyguards won the take</b>\n<i>The assassin was eliminated</i>");
				AnnounceResult("The Assassin was " + PlayerLookup.GetPlayerNameTag(AssassinPlayerId) + " and was stopped.");
				FinishTake();
			}
			else
			{
				BroadcastLiveState();
			}
		}

		internal static void RequestLoadout(int playerId)
		{
			if (Enabled && GameModeManager.IsActive(GameMode.Assassin) && MyceliumNetwork.IsHost)
			{
				if (!WeaponsUnlocked && !IsKingPlayer(playerId))
				{
					PendingLoadouts.Remove(playerId);
					ClearPlayerWeapons(playerId);
				}
				else
				{
					GiveWeapon(playerId);
				}
			}
		}

		internal static bool IsAllowedWeapon(Weapon weapon, int playerId)
		{
			if ((Object)(object)weapon == (Object)null || (!WeaponsUnlocked && !IsKingPlayer(playerId)))
			{
				return false;
			}
			string expectedWeaponName = GetExpectedWeaponName(playerId);
			if (expectedWeaponName != null)
			{
				return ((Object)weapon).name.StartsWith(expectedWeaponName, StringComparison.Ordinal);
			}
			return false;
		}

		internal static bool IsUnlimitedWeapon(Weapon weapon)
		{
			if (!WeaponsUnlocked && !IsKingPlayer(GetWeaponPlayerId(weapon)))
			{
				return false;
			}
			return IsAllowedWeapon(weapon, GetWeaponPlayerId(weapon));
		}

		internal static bool IsKingPlayer(int playerId)
		{
			if (playerId >= 0)
			{
				return playerId == KingPlayerId;
			}
			return false;
		}

		internal static void ApplyLocalRole(CSteamID hostId, int takeId, bool isAssassin, bool isKing, bool announce, int weaponDelaySeconds)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			if (!(hostId != MyceliumNetwork.LobbyHost) && takeId >= _localRoleTakeId && weaponDelaySeconds >= 5 && weaponDelaySeconds <= 30)
			{
				_localRoleTakeId = takeId;
				WeaponDelaySeconds = weaponDelaySeconds;
				LocalIsAssassin = isAssassin;
				LocalIsKing = isKing;
				if (announce && _localRoleAnnouncedTakeId != takeId)
				{
					_localRoleAnnouncementPending = true;
					TryAnnounceLocalRole();
				}
			}
		}

		private static void TryAnnounceLocalRole()
		{
			if (_localRoleAnnouncementPending && _localRoleTakeId >= 0 && Enabled && GameModeManager.IsActive(GameMode.Assassin) && GameModeManager.IsRoundGameplayActive && !GameModeManager.IsMatchOver && _localRoleAnnouncedTakeId != _localRoleTakeId)
			{
				_localRoleAnnouncementPending = false;
				_localRoleAnnouncedTakeId = _localRoleTakeId;
				GameModeHud.AnnounceTarget(LocalIsAssassin ? "You are the <color=#CC2222><b>assassin</b></color>." : (LocalIsKing ? "You are the <color=#35D05F><b>king</b></color>." : "You are a <color=#4D9BFF><b>bodyguard</b></color>."), RoleAnnouncementDuration);
			}
		}

		internal static void EnsureLoadouts()
		{
			if (!Enabled || !GameModeManager.IsActive(GameMode.Assassin) || !MyceliumNetwork.InLobby || !MyceliumNetwork.IsHost || WeaponService.IsFinalGameScreen || Time.unscaledTime < _nextLoadoutCheckTime)
			{
				return;
			}
			_nextLoadoutCheckTime = Time.unscaledTime + 0.5f;
			foreach (ClientInstance value2 in ClientInstance.playerInstances.Values)
			{
				if ((Object)(object)value2 == (Object)null || !Object.op_Implicit((Object)(object)value2) || (Object)(object)value2.PlayerSpawner == (Object)null || !Object.op_Implicit((Object)(object)value2.PlayerSpawner) || (Object)(object)value2.PlayerSpawner.player == (Object)null || !Object.op_Implicit((Object)(object)value2.PlayerSpawner.player) || !((Component)value2.PlayerSpawner.player).gameObject.activeInHierarchy)
				{
					continue;
				}
				PlayerPickup playerPickupScript = value2.PlayerSpawner.player.playerPickupScript;
				if (!WeaponsUnlocked && !IsKingPlayer(value2.PlayerId))
				{
					if ((Object)(object)playerPickupScript != (Object)null && (((Object)(object)playerPickupScript.objInHand != (Object)null && Object.op_Implicit((Object)(object)playerPickupScript.objInHand)) || ((Object)(object)playerPickupScript.objInLeftHand != (Object)null && Object.op_Implicit((Object)(object)playerPickupScript.objInLeftHand))))
					{
						WeaponService.ClearHeldWeapons(playerPickupScript);
					}
					continue;
				}
				Weapon weapon = GetWeapon(playerPickupScript?.objInHand);
				float value;
				if ((Object)(object)weapon != (Object)null && IsAllowedWeapon(weapon, value2.PlayerId))
				{
					PendingLoadouts.Remove(value2.PlayerId);
				}
				else if (!PendingLoadouts.TryGetValue(value2.PlayerId, out value) || Time.unscaledTime >= value)
				{
					GiveWeapon(value2.PlayerId);
				}
			}
		}

		private static void StartTake()
		{
			if (WinnerId >= 0 || !MyceliumNetwork.IsHost)
			{
				return;
			}
			List<int> list = new List<int>();
			foreach (ClientInstance value in ClientInstance.playerInstances.Values)
			{
				if ((Object)(object)value != (Object)null && Object.op_Implicit((Object)(object)value))
				{
					list.Add(value.PlayerId);
				}
			}
			if (list.Count < 2)
			{
				AssassinPlayerId = -1;
				KingPlayerId = -1;
				ScheduleStartTakeRetry();
				return;
			}
			_takeId++;
			_takeEnding = false;
			_takeTimeRemaining = 90f;
			WeaponDelaySeconds = Random.Range(5, 31);
			WeaponsUnlocked = false;
			_nextLoadoutCheckTime = 0f;
			PendingLoadouts.Clear();
			AlivePlayers.Clear();
			foreach (int item in list)
			{
				AlivePlayers.Add(item);
				Scores.TryAdd(item, 0);
			}
			AssassinPlayerId = DistributionRandom.SelectPlayer("Assassin", list);
			List<int> candidates = list.Where((int playerId) => playerId != AssassinPlayerId).ToList();
			KingPlayerId = DistributionRandom.SelectPlayer("King", candidates);
			ClearCurrentWeapons();
			SendRoleStates(announce: true);
			EnsureLoadouts();
			BroadcastLiveState();
			Announce(PlayerLookup.GetPlayerNameTag(KingPlayerId) + " is the <color=#35D05F><b>KING</b></color>.");
			if ((Object)(object)Plugin.Instance != (Object)null)
			{
				int takeId = _takeId;
				((MonoBehaviour)Plugin.Instance).StartCoroutine(UnlockWeaponsAfterDelay(takeId, SessionState.Generation, GameModeManager.RoundId, WeaponDelaySeconds));
			}
		}

		private static void ScheduleStartTakeRetry()
		{
			if (!_startRetryPending && !((Object)(object)Plugin.Instance == (Object)null))
			{
				_startRetryPending = true;
				((MonoBehaviour)Plugin.Instance).StartCoroutine(RetryStartTake(SessionState.Generation, GameModeManager.RoundId, _takeId));
			}
		}

		private static IEnumerator RetryStartTake(int sessionGeneration, int roundId, int previousTakeId)
		{
			for (int attempt = 0; attempt < 20; attempt++)
			{
				yield return (object)new WaitForSeconds(0.25f);
				if (!SessionState.IsCurrent(sessionGeneration) || GameModeManager.RoundId != roundId || WinnerId >= 0 || _takeEnding || !GameModeManager.IsActive(GameMode.Assassin))
				{
					break;
				}
				StartTake();
				if (_takeId > previousTakeId)
				{
					break;
				}
			}
			_startRetryPending = false;
		}

		private static IEnumerator UnlockWeaponsAfterDelay(int token, int sessionGeneration, int roundId, int weaponDelaySeconds)
		{
			yield return (object)new WaitForSeconds((float)weaponDelaySeconds);
			if (SessionState.IsCurrent(sessionGeneration) && GameModeManager.RoundId == roundId && token == _takeId && !_takeEnding && WinnerId < 0 && GameModeManager.IsActive(GameMode.Assassin))
			{
				WeaponsUnlocked = true;
				EnsureLoadouts();
				BroadcastLiveState();
			}
		}

		private static void FinishTake()
		{
			BroadcastLiveState();
			if (WinnerId >= 0)
			{
				GameModeManager.CompleteCustomRound(TeamAssignment.ResolveTeamId(WinnerId));
			}
			else
			{
				BeginNextTake();
			}
		}

		private static void CompleteTimeoutWin()
		{
			if (_takeEnding || WinnerId >= 0)
			{
				return;
			}
			if (KingPlayerId >= 0 && AlivePlayers.Contains(KingPlayerId))
			{
				AwardScore(KingPlayerId, AssassinRules.GetKingAward(deadWasAssassin: true));
			}
			foreach (int alivePlayer in AlivePlayers)
			{
				if (alivePlayer != KingPlayerId && alivePlayer != AssassinPlayerId)
				{
					AwardScore(alivePlayer, AssassinRules.GetBodyguardAward(deadWasAssassin: true));
				}
			}
			GameModeHud.BroadcastTakeResult("<b>The King and bodyguards won the take</b>\n<i>The Assassin ran out of time</i>");
			Announce("The Assassin did not eliminate the King in time.");
			FinishTake();
		}

		private static void BeginNextTake()
		{
			if (_t