Decompiled source of PropHunt Fix v1.0.1

PropHunt_Fix.dll

Decompiled 3 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using RepoMods.PropHunt;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("REPOJP")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("zabuMod")]
[assembly: AssemblyTitle("zabuMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace REPOJP.PropHuntFix
{
	[BepInPlugin("REPOJP.PropHunt_Fix", "PropHunt_Fix", "1.0.0")]
	public class PropHuntFixPlugin : BaseUnityPlugin
	{
		internal static PropHuntFixPlugin Instance;

		internal static ManualLogSource Log;

		internal static Harmony Harmony;

		internal const int RecentHunterWeight0 = 100;

		internal const int RecentHunterWeight1 = 50;

		internal const int RecentHunterWeight2 = 20;

		internal const int RecentHunterWeight3 = 5;

		internal const float LowestCountBonusMultiplier = 1.75f;

		internal static ConfigEntry<int> CfgHunterCount;

		internal static ConfigEntry<int> CfgRoundRoomCount;

		internal static ConfigEntry<bool> CfgGiveMapPlayerCountUpgrade;

		internal static ConfigEntry<bool> CfgRefillHuntersWhenHunterLeaves;

		internal static ConfigEntry<bool> CfgEnableHunterAllyNameHighlight;

		internal static ConfigEntry<bool> CfgWriteHunterSelectionLog;

		internal static ConfigEntry<float> CfgEyeRefreshInterval;

		internal static ConfigEntry<int> CfgDeathSoundVolumePercent;

		internal static ConfigEntry<int> CfgWinSoundVolumePercent;

		internal static ConfigEntry<int> CfgCountdownSoundVolumePercent;

		internal static ConfigEntry<int> CfgMainMenuMusicVolumePercent;

		internal static ConfigEntry<FixLanguage> CfgLanguage;

		private GameObject runtimeRoot;

		private void Awake()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Expected O, but got Unknown
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Expected O, but got Unknown
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Expected O, but got Unknown
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Expected O, but got Unknown
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			PropHuntAudioUtil.EnsureReady();
			MainMenuMusicVolumeService.EnsureStarted();
			CfgHunterCount = ((BaseUnityPlugin)this).Config.Bind<int>("Gameplay", "HunterCount", 1, new ConfigDescription("Hunter count per round. ラウンドごとの鬼人数", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>()));
			CfgRoundRoomCount = ((BaseUnityPlugin)this).Config.Bind<int>("MapGeneration", "RoundRoomCount", 2, new ConfigDescription("Generated room count for PropHunt rounds. PropHuntラウンドの生成部屋数", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>()));
			CfgGiveMapPlayerCountUpgrade = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "GiveMapPlayerCountUpgrade", true, "Give the map player count upgrade to all players in PropHunt. PropHunt中に全員へマッププレイヤーカウントアップグレードを配布");
			CfgRefillHuntersWhenHunterLeaves = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "RefillHuntersWhenHunterLeaves", true, "Refill hunter slots if a hunter leaves mid-round. 鬼離脱時の補充");
			CfgEnableHunterAllyNameHighlight = ((BaseUnityPlugin)this).Config.Bind<bool>("Visual", "EnableHunterAllyNameHighlight", true, "Show allied hunter name tags in red for hunters. 鬼同士の赤ネームタグ表示");
			CfgEyeRefreshInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "EyeRefreshInterval", 1f, "Eye color refresh interval in seconds. 目色再適用間隔(秒)");
			CfgDeathSoundVolumePercent = ((BaseUnityPlugin)this).Config.Bind<int>("Audio", "DeathSoundVolumePercent", 20, new ConfigDescription("Death sound volume percent. 死亡音の音量(%)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			CfgWinSoundVolumePercent = ((BaseUnityPlugin)this).Config.Bind<int>("Audio", "WinSoundVolumePercent", 20, new ConfigDescription("Win result sound volume percent. 勝利結果音の音量(%)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			CfgCountdownSoundVolumePercent = ((BaseUnityPlugin)this).Config.Bind<int>("Audio", "CountdownSoundVolumePercent", 30, new ConfigDescription("Hunter unlock countdown beep volume percent. 鬼ロック解除カウントダウン音の音量(%)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			CfgMainMenuMusicVolumePercent = ((BaseUnityPlugin)this).Config.Bind<int>("Audio", "MainMenuMusicVolumePercent", 20, new ConfigDescription("Main menu custom music volume percent. メインメニュー独自BGM音量(%)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			CfgLanguage = ((BaseUnityPlugin)this).Config.Bind<FixLanguage>("Localization", "Language", FixLanguage.English, "Display language. AutoTranslatorConfig.ini Language is used automatically when supported. 表示言語。対応言語の場合はAutoTranslatorConfig.iniのLanguageを自動使用");
			CfgWriteHunterSelectionLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "WriteHunterSelectionLog", true, "Write hunter selection logs. 抽選ログ出力");
			Harmony = new Harmony("REPOJP.PropHunt_Fix");
			Harmony.PatchAll();
			Log.LogInfo((object)"[PropHunt_Fix] Loaded v1.0.0");
		}

		internal static void EnsureRuntimeRoot()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			try
			{
				if (!((Object)(object)Instance == (Object)null) && !((Object)(object)Instance.runtimeRoot != (Object)null))
				{
					GameObject val = new GameObject("PropHunt_Fix_Runtime");
					val.transform.parent = null;
					((Object)val).hideFlags = (HideFlags)61;
					Object.DontDestroyOnLoad((Object)(object)val);
					val.AddComponent<HostConfigSyncService>();
					val.AddComponent<ClientConfigApplyService>();
					val.AddComponent<EyeColorRefreshService>();
					val.AddComponent<ReadySyncService>();
					val.AddComponent<NameTagOriginalPatchDisabler>();
					val.AddComponent<LocalHunterUnlockAudioService>();
					val.AddComponent<PropHuntFixHudService>();
					val.AddComponent<MapPlayerCountUpgradeService>();
					val.AddComponent<DisguiseFlashlightSuppressService>();
					val.AddComponent<PostMatchVoiceAllHearService>();
					Instance.runtimeRoot = val;
					Log.LogInfo((object)"[PropHunt_Fix] Runtime initialized.");
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("[PropHunt_Fix] Runtime init failed: " + ex.Message));
			}
		}
	}
	public enum NonHunterEyeColorMode
	{
		Green,
		Black,
		Pink,
		Yellow,
		None
	}
	public enum FixLanguage
	{
		English,
		Japanese,
		Chinese,
		Korean,
		Russian,
		French,
		Spanish,
		German,
		Portuguese
	}
	internal static class FixLocalization
	{
		private static bool autoLoaded;

		private static bool hasAutoLanguage;

		private static FixLanguage autoLanguage;

		public static FixLanguage Current
		{
			get
			{
				LoadAutoLanguageOnce();
				if (hasAutoLanguage)
				{
					return autoLanguage;
				}
				try
				{
					if (PropHuntFixPlugin.CfgLanguage != null)
					{
						return PropHuntFixPlugin.CfgLanguage.Value;
					}
				}
				catch
				{
				}
				return FixLanguage.English;
			}
		}

		private static void LoadAutoLanguageOnce()
		{
			if (autoLoaded)
			{
				return;
			}
			autoLoaded = true;
			try
			{
				string path = Path.Combine(Paths.ConfigPath, "AutoTranslatorConfig.ini");
				if (!File.Exists(path))
				{
					return;
				}
				string[] array = File.ReadAllLines(path);
				for (int i = 0; i < array.Length; i++)
				{
					string text = array[i];
					if (string.IsNullOrEmpty(text))
					{
						continue;
					}
					text = text.Trim();
					if (text.StartsWith("Language=", StringComparison.OrdinalIgnoreCase))
					{
						if (TryParseLanguageCode(text.Substring("Language=".Length).Trim(), out var language))
						{
							autoLanguage = language;
							hasAutoLanguage = true;
						}
						break;
					}
				}
			}
			catch
			{
			}
		}

		private static bool TryParseLanguageCode(string code, out FixLanguage language)
		{
			language = FixLanguage.English;
			if (string.IsNullOrEmpty(code))
			{
				return false;
			}
			code = code.Trim().ToLowerInvariant();
			int num = code.IndexOf('-');
			if (num >= 0)
			{
				code = code.Substring(0, num);
			}
			if (code == "en")
			{
				language = FixLanguage.English;
				return true;
			}
			if (code == "ja" || code == "jp")
			{
				language = FixLanguage.Japanese;
				return true;
			}
			if (code == "zh" || code == "cn")
			{
				language = FixLanguage.Chinese;
				return true;
			}
			if (code == "ko" || code == "kr")
			{
				language = FixLanguage.Korean;
				return true;
			}
			switch (code)
			{
			case "ru":
				language = FixLanguage.Russian;
				return true;
			case "fr":
				language = FixLanguage.French;
				return true;
			case "es":
				language = FixLanguage.Spanish;
				return true;
			case "de":
				language = FixLanguage.German;
				return true;
			case "pt":
				language = FixLanguage.Portuguese;
				return true;
			default:
				return false;
			}
		}

		public static string Text(string key)
		{
			FixLanguage current = Current;
			return key switch
			{
				"Hunters" => Pick(current, "Hunters", "鬼", "猎人", "술래", "Охотники", "Chasseurs", "Cazadores", "Jäger", "Caçadores"), 
				"Hunter" => Pick(current, "HUNTER", "鬼", "猎人", "술래", "ОХОТНИК", "CHASSEUR", "CAZADOR", "JÄGER", "CAÇADOR"), 
				"Hider" => Pick(current, "HIDER", "逃げ側", "躲藏者", "도망자", "ПРЯЧУЩИЙСЯ", "CACHEUR", "OCULTO", "VERSTECKER", "ESCONDIDO"), 
				"PropHunt" => Pick(current, "PROP HUNT", "プロップハント", "躲猫猫", "프롭 헌트", "ОХОТА НА ПРЕДМЕТЫ", "PROP HUNT", "PROP HUNT", "PROP HUNT", "PROP HUNT"), 
				"ScanHelp" => Pick(current, "RMB: Scan | Miss penalty", "右クリック: スキャン | ミスでHP減少", "右键: 扫描 | 失误扣血", "우클릭: 스캔 | 실패 시 체력 감소", "ПКМ: Скан | Промах снимает HP", "Clic droit: scan | Échec: PV-", "Clic derecho: escanear | Fallo: PV-", "Rechtsklick: Scan | Fehlschuss: HP-", "Botão direito: escanear | Erro: HP-"), 
				"HiderHelp" => Pick(current, "Toggle disguise / View / Lock", "変身 / 視点 / 固定", "切换伪装 / 视角 / 锁定", "변장 / 시점 / 고정", "Маскировка / Вид / Фиксация", "Déguisement / Vue / Verrou", "Disfraz / Vista / Bloqueo", "Tarnung / Ansicht / Sperre", "Disfarce / Visão / Travar"), 
				"HideTime" => Pick(current, "Hide time", "隠れる時間", "躲藏时间", "숨는 시간", "Время прятаться", "Temps de cache", "Tiempo para esconderse", "Versteckzeit", "Tempo para esconder"), 
				"TimeLeft" => Pick(current, "Time left", "残り時間", "剩余时间", "남은 시간", "Осталось", "Temps restant", "Tiempo restante", "Verbleibende Zeit", "Tempo restante"), 
				"HunterLock" => Pick(current, "Hunter lock", "鬼ロック", "猎人锁定", "술래 잠금", "Блокировка охотника", "Blocage chasseur", "Bloqueo cazador", "Jägersperre", "Bloqueio do caçador"), 
				"Disguise" => Pick(current, "Disguise", "変身", "伪装", "변장", "Маскировка", "Déguisement", "Disfraz", "Tarnung", "Disfarce"), 
				"TargetLocked" => Pick(current, "Target locked", "対象固定済み", "目标已锁定", "대상 고정됨", "Цель выбрана", "Cible verrouillée", "Objetivo fijado", "Ziel fixiert", "Alvo travado"), 
				"LookValuable" => Pick(current, "Look at a Valuable to lock target", "貴重品を見て対象を固定", "看向贵重品来锁定目标", "귀중품을 봐서 대상 고정", "Посмотрите на ценность", "Regardez un objet de valeur", "Mira un valioso", "Wertgegenstand ansehen", "Olhe para um valioso"), 
				"Locked" => Pick(current, "LOCKED", "固定中", "已锁定", "고정됨", "ЗАФИКСИРОВАНО", "VERROUILLÉ", "BLOQUEADO", "GESPERRT", "TRAVADO"), 
				"Start" => Pick(current, "START", "スタート", "开始", "시작", "СТАРТ", "DÉPART", "INICIO", "START", "INICIAR"), 
				"NotReady" => Pick(current, "NOT READY", "未導入", "未就绪", "준비 안 됨", "НЕ ГОТОВ", "PAS PRÊT", "NO LISTO", "NICHT BEREIT", "NÃO PRONTO"), 
				"Sec" => Pick(current, "sec", "秒", "秒", "초", "сек", "s", "seg", "Sek", "s"), 
				"Min" => Pick(current, "min", "分", "分钟", "분", "мин", "min", "min", "Min", "min"), 
				"HidersWin" => Pick(current, "HIDERS WIN!", "逃げ側の勝利!", "躲藏者胜利!", "도망자 승리!", "ПРЯЧУЩИЕСЯ ПОБЕДИЛИ!", "CACHEURS GAGNENT!", "¡GANAN LOS OCULTOS!", "VERSTECKER GEWINNEN!", "ESCONDIDOS VENCEM!"), 
				"HunterWins" => Pick(current, "HUNTER WINS!", "鬼の勝利!", "猎人胜利!", "술래 승리!", "ОХОТНИК ПОБЕДИЛ!", "CHASSEUR GAGNE!", "¡GANA EL CAZADOR!", "JÄGER GEWINNT!", "CAÇADOR VENCE!"), 
				"Draw" => Pick(current, "DRAW", "引き分け", "平局", "무승부", "НИЧЬЯ", "ÉGALITÉ", "EMPATE", "UNENTSCHIEDEN", "EMPATE"), 
				"TimeExpired" => Pick(current, "Time expired", "時間切れ", "时间到", "시간 초과", "Время вышло", "Temps écoulé", "Tiempo agotado", "Zeit abgelaufen", "Tempo esgotado"), 
				"HunterEliminated" => Pick(current, "Hunter eliminated", "鬼が全滅", "猎人被消灭", "술래 제거됨", "Охотник устранён", "Chasseur éliminé", "Cazador eliminado", "Jäger eliminiert", "Caçador eliminado"), 
				"AllHidersEliminated" => Pick(current, "All hiders eliminated", "逃げ側が全滅", "躲藏者全灭", "도망자 전멸", "Все прячущиеся устранены", "Tous les cacheurs éliminés", "Todos los ocultos eliminados", "Alle Verstecker eliminiert", "Todos escondidos eliminados"), 
				_ => key, 
			};
		}

		public static string TranslateMessage(string message)
		{
			if (string.IsNullOrEmpty(message))
			{
				return message;
			}
			string text = message;
			text = text.Replace("HIDERS WIN!", Text("HidersWin"));
			text = text.Replace("HUNTER WINS!", Text("HunterWins"));
			text = text.Replace("DRAW", Text("Draw"));
			text = text.Replace("Time expired", Text("TimeExpired"));
			text = text.Replace("Hunter eliminated", Text("HunterEliminated"));
			text = text.Replace("All hiders eliminated", Text("AllHidersEliminated"));
			text = text.Replace("View: third-person", Pick(Current, "View: third-person", "視点: 三人称", "视角: 第三人称", "시점: 3인칭", "Вид: от третьего лица", "Vue: troisième personne", "Vista: tercera persona", "Ansicht: dritte Person", "Visão: terceira pessoa"));
			text = text.Replace("View: first-person", Pick(Current, "View: first-person", "視点: 一人称", "视角: 第一人称", "시점: 1인칭", "Вид: от первого лица", "Vue: première personne", "Vista: primera persona", "Ansicht: erste Person", "Visão: primeira pessoa"));
			text = text.Replace("Position LOCKED", Pick(Current, "Position LOCKED", "位置固定", "位置已锁定", "위치 고정", "Позиция зафиксирована", "Position verrouillée", "Posición bloqueada", "Position gesperrt", "Posição travada"));
			text = text.Replace("Position UNLOCKED", Pick(Current, "Position UNLOCKED", "位置固定解除", "位置解锁", "위치 해제", "Позиция разблокирована", "Position déverrouillée", "Posición desbloqueada", "Position entsperrt", "Posição destravada"));
			text = text.Replace("Disguise cleared.", Pick(Current, "Disguise cleared.", "変身解除", "伪装已解除", "변장 해제", "Маскировка снята", "Déguisement retiré", "Disfraz eliminado", "Tarnung aufgehoben", "Disfarce removido"));
			text = text.Replace("No disguise target. Look at a Valuable.", Pick(Current, "No disguise target. Look at a Valuable.", "変身対象なし。貴重品を見てください", "没有伪装目标。看向贵重品", "변장 대상 없음. 귀중품을 보세요", "Нет цели маскировки. Посмотрите на ценность", "Aucune cible. Regardez un objet de valeur", "Sin objetivo. Mira un valioso", "Kein Ziel. Wertgegenstand ansehen", "Sem alvo. Olhe para um valioso"));
			return text.Replace("Disguised.", Pick(Current, "Disguised.", "変身しました", "已伪装", "변장 완료", "Замаскировано", "Déguisé", "Disfrazado", "Getarnt", "Disfarçado"));
		}

		public static string PickForInternal(string en, string ja, string zh, string ko, string ru, string fr, string es, string de, string pt)
		{
			return Pick(Current, en, ja, zh, ko, ru, fr, es, de, pt);
		}

		private static string Pick(FixLanguage language, string en, string ja, string zh, string ko, string ru, string fr, string es, string de, string pt)
		{
			return language switch
			{
				FixLanguage.Japanese => ja, 
				FixLanguage.Chinese => zh, 
				FixLanguage.Korean => ko, 
				FixLanguage.Russian => ru, 
				FixLanguage.French => fr, 
				FixLanguage.Spanish => es, 
				FixLanguage.German => de, 
				FixLanguage.Portuguese => pt, 
				_ => en, 
			};
		}
	}
	internal static class OriginalPropHuntConfigBridge
	{
		private const float DefaultPreHideSeconds = 30f;

		private const float DefaultHunterLockSeconds = 30f;

		private const float DefaultRoundSeconds = 300f;

		private const int DefaultMissPenaltyHP = 5;

		private const float DefaultGunRangeMeters = 60f;

		private const float DefaultGunCooldownSeconds = 0.18f;

		private static ConfigEntryBase GetConfigEntry(string fieldName)
		{
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(PropHuntPlugin), fieldName);
				if (fieldInfo == null)
				{
					return null;
				}
				object value = fieldInfo.GetValue(null);
				return (ConfigEntryBase)((value is ConfigEntryBase) ? value : null);
			}
			catch
			{
				return null;
			}
		}

		private static float GetFloat(string fieldName, float defaultValue)
		{
			try
			{
				ConfigEntryBase configEntry = GetConfigEntry(fieldName);
				if (configEntry != null && configEntry.BoxedValue != null)
				{
					object boxedValue = configEntry.BoxedValue;
					if (boxedValue is float result)
					{
						return result;
					}
					if (boxedValue is int)
					{
						return (int)boxedValue;
					}
					if (boxedValue is double)
					{
						return (float)(double)boxedValue;
					}
					if (boxedValue is long)
					{
						return (long)boxedValue;
					}
					if (boxedValue is string s && float.TryParse(s, out var result2))
					{
						return result2;
					}
				}
			}
			catch
			{
			}
			return defaultValue;
		}

		private static int GetInt(string fieldName, int defaultValue)
		{
			try
			{
				ConfigEntryBase configEntry = GetConfigEntry(fieldName);
				if (configEntry != null && configEntry.BoxedValue != null)
				{
					object boxedValue = configEntry.BoxedValue;
					if (boxedValue is int result)
					{
						return result;
					}
					if (boxedValue is int result2)
					{
						return result2;
					}
					if (boxedValue is int result3)
					{
						return result3;
					}
					if (boxedValue is long)
					{
						return (int)(long)boxedValue;
					}
					if (boxedValue is float)
					{
						return Mathf.RoundToInt((float)boxedValue);
					}
					if (boxedValue is string s && int.TryParse(s, out var result4))
					{
						return result4;
					}
				}
			}
			catch
			{
			}
			return defaultValue;
		}

		public static float GetPreHideSeconds()
		{
			return Mathf.Max(1f, GetFloat("CfgPreHideSeconds", 30f));
		}

		public static float GetHunterLockSeconds()
		{
			return Mathf.Max(0f, GetFloat("CfgHunterLockSeconds", 30f));
		}

		public static float GetRoundSeconds()
		{
			return Mathf.Max(5f, GetFloat("CfgRoundSeconds", 300f));
		}

		public static int GetMissPenaltyHP()
		{
			return Mathf.Max(0, GetInt("CfgMissPenaltyHP", 5));
		}

		public static float GetGunRangeMeters()
		{
			return Mathf.Max(1f, GetFloat("CfgGunRangeMeters", 60f));
		}

		public static float GetGunCooldownSeconds()
		{
			return Mathf.Max(0f, GetFloat("CfgGunCooldownSeconds", 0.18f));
		}

		public static void SubscribeToOriginalConfigChanges(EventHandler handler)
		{
			SubscribeField("CfgPreHideSeconds", handler);
			SubscribeField("CfgHunterLockSeconds", handler);
			SubscribeField("CfgRoundSeconds", handler);
			SubscribeField("CfgMissPenaltyHP", handler);
			SubscribeField("CfgGunRangeMeters", handler);
			SubscribeField("CfgGunCooldownSeconds", handler);
		}

		private static void SubscribeField(string fieldName, EventHandler handler)
		{
			try
			{
				ConfigEntryBase configEntry = GetConfigEntry(fieldName);
				if (configEntry != null)
				{
					EventInfo @event = ((object)configEntry).GetType().GetEvent("SettingChanged", BindingFlags.Instance | BindingFlags.Public);
					if (@event != null)
					{
						@event.AddEventHandler(configEntry, handler);
					}
				}
			}
			catch
			{
			}
		}
	}
	internal class FixConfigSnapshot
	{
		public float PreHideSeconds;

		public float HunterLockSeconds;

		public float RoundSeconds;

		public int MissPenaltyHP;

		public float GunRangeMeters;

		public float GunCooldownSeconds;

		public int HunterCount;

		public bool RefillHuntersWhenHunterLeaves;

		public int RecentHunterWeight0;

		public int RecentHunterWeight1;

		public int RecentHunterWeight2;

		public int RecentHunterWeight3;

		public float LowestCountBonusMultiplier;

		public NonHunterEyeColorMode NonHunterEyeColor;

		public bool EnableHunterAllyNameHighlight;

		public static FixConfigSnapshot FromLocalConfig()
		{
			FixConfigSnapshot fixConfigSnapshot = new FixConfigSnapshot();
			fixConfigSnapshot.PreHideSeconds = OriginalPropHuntConfigBridge.GetPreHideSeconds();
			fixConfigSnapshot.HunterLockSeconds = OriginalPropHuntConfigBridge.GetHunterLockSeconds();
			fixConfigSnapshot.RoundSeconds = OriginalPropHuntConfigBridge.GetRoundSeconds();
			fixConfigSnapshot.MissPenaltyHP = OriginalPropHuntConfigBridge.GetMissPenaltyHP();
			fixConfigSnapshot.GunRangeMeters = OriginalPropHuntConfigBridge.GetGunRangeMeters();
			fixConfigSnapshot.GunCooldownSeconds = OriginalPropHuntConfigBridge.GetGunCooldownSeconds();
			fixConfigSnapshot.HunterCount = Mathf.Max(1, PropHuntFixPlugin.CfgHunterCount.Value);
			fixConfigSnapshot.RefillHuntersWhenHunterLeaves = PropHuntFixPlugin.CfgRefillHuntersWhenHunterLeaves.Value;
			fixConfigSnapshot.RecentHunterWeight0 = 100;
			fixConfigSnapshot.RecentHunterWeight1 = 50;
			fixConfigSnapshot.RecentHunterWeight2 = 20;
			fixConfigSnapshot.RecentHunterWeight3 = 5;
			fixConfigSnapshot.LowestCountBonusMultiplier = 1.75f;
			fixConfigSnapshot.NonHunterEyeColor = NonHunterEyeColorMode.None;
			fixConfigSnapshot.EnableHunterAllyNameHighlight = PropHuntFixPlugin.CfgEnableHunterAllyNameHighlight.Value;
			return fixConfigSnapshot;
		}

		public bool EqualsTo(FixConfigSnapshot other)
		{
			if (other == null)
			{
				return false;
			}
			return PreHideSeconds == other.PreHideSeconds && HunterLockSeconds == other.HunterLockSeconds && RoundSeconds == other.RoundSeconds && MissPenaltyHP == other.MissPenaltyHP && GunRangeMeters == other.GunRangeMeters && GunCooldownSeconds == other.GunCooldownSeconds && HunterCount == other.HunterCount && RefillHuntersWhenHunterLeaves == other.RefillHuntersWhenHunterLeaves && RecentHunterWeight0 == other.RecentHunterWeight0 && RecentHunterWeight1 == other.RecentHunterWeight1 && RecentHunterWeight2 == other.RecentHunterWeight2 && RecentHunterWeight3 == other.RecentHunterWeight3 && Mathf.Approximately(LowestCountBonusMultiplier, other.LowestCountBonusMultiplier) && NonHunterEyeColor == other.NonHunterEyeColor && EnableHunterAllyNameHighlight == other.EnableHunterAllyNameHighlight;
		}

		public Hashtable ToHashtable()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			Hashtable val = new Hashtable();
			val[(object)"PHFIX_CFG_PreHideSeconds"] = PreHideSeconds;
			val[(object)"PHFIX_CFG_HunterLockSeconds"] = HunterLockSeconds;
			val[(object)"PHFIX_CFG_RoundSeconds"] = RoundSeconds;
			val[(object)"PHFIX_CFG_MissPenaltyHP"] = MissPenaltyHP;
			val[(object)"PHFIX_CFG_GunRangeMeters"] = GunRangeMeters;
			val[(object)"PHFIX_CFG_GunCooldownSeconds"] = GunCooldownSeconds;
			val[(object)"PHFIX_CFG_HunterCount"] = HunterCount;
			val[(object)"PHFIX_CFG_RefillHuntersWhenHunterLeaves"] = RefillHuntersWhenHunterLeaves;
			val[(object)"PHFIX_CFG_RecentHunterWeight0"] = RecentHunterWeight0;
			val[(object)"PHFIX_CFG_RecentHunterWeight1"] = RecentHunterWeight1;
			val[(object)"PHFIX_CFG_RecentHunterWeight2"] = RecentHunterWeight2;
			val[(object)"PHFIX_CFG_RecentHunterWeight3"] = RecentHunterWeight3;
			val[(object)"PHFIX_CFG_LowestCountBonusMultiplier"] = LowestCountBonusMultiplier;
			val[(object)"PHFIX_CFG_NonHunterEyeColor"] = (int)NonHunterEyeColor;
			val[(object)"PHFIX_CFG_EnableHunterAllyNameHighlight"] = EnableHunterAllyNameHighlight;
			return val;
		}

		public static FixConfigSnapshot FromRoomProperties(Hashtable props)
		{
			if (props == null)
			{
				return null;
			}
			FixConfigSnapshot fixConfigSnapshot = new FixConfigSnapshot();
			if (!RoomPropUtil.TryGetFloat(props, "PHFIX_CFG_PreHideSeconds", out fixConfigSnapshot.PreHideSeconds))
			{
				return null;
			}
			if (!RoomPropUtil.TryGetFloat(props, "PHFIX_CFG_HunterLockSeconds", out fixConfigSnapshot.HunterLockSeconds))
			{
				return null;
			}
			if (!RoomPropUtil.TryGetFloat(props, "PHFIX_CFG_RoundSeconds", out fixConfigSnapshot.RoundSeconds))
			{
				return null;
			}
			if (!RoomPropUtil.TryGetInt(props, "PHFIX_CFG_MissPenaltyHP", out fixConfigSnapshot.MissPenaltyHP))
			{
				return null;
			}
			if (!RoomPropUtil.TryGetFloat(props, "PHFIX_CFG_GunRangeMeters", out fixConfigSnapshot.GunRangeMeters))
			{
				return null;
			}
			if (!RoomPropUtil.TryGetFloat(props, "PHFIX_CFG_GunCooldownSeconds", out fixConfigSnapshot.GunCooldownSeconds))
			{
				return null;
			}
			if (!RoomPropUtil.TryGetInt(props, "PHFIX_CFG_HunterCount", out fixConfigSnapshot.HunterCount))
			{
				return null;
			}
			if (!RoomPropUtil.TryGetBool(props, "PHFIX_CFG_RefillHuntersWhenHunterLeaves", out fixConfigSnapshot.RefillHuntersWhenHunterLeaves))
			{
				return null;
			}
			if (!RoomPropUtil.TryGetInt(props, "PHFIX_CFG_RecentHunterWeight0", out fixConfigSnapshot.RecentHunterWeight0))
			{
				return null;
			}
			if (!RoomPropUtil.TryGetInt(props, "PHFIX_CFG_RecentHunterWeight1", out fixConfigSnapshot.RecentHunterWeight1))
			{
				return null;
			}
			if (!RoomPropUtil.TryGetInt(props, "PHFIX_CFG_RecentHunterWeight2", out fixConfigSnapshot.RecentHunterWeight2))
			{
				return null;
			}
			if (!RoomPropUtil.TryGetInt(props, "PHFIX_CFG_RecentHunterWeight3", out fixConfigSnapshot.RecentHunterWeight3))
			{
				return null;
			}
			if (!RoomPropUtil.TryGetFloat(props, "PHFIX_CFG_LowestCountBonusMultiplier", out fixConfigSnapshot.LowestCountBonusMultiplier))
			{
				return null;
			}
			if (!RoomPropUtil.TryGetInt(props, "PHFIX_CFG_NonHunterEyeColor", out var value))
			{
				return null;
			}
			fixConfigSnapshot.NonHunterEyeColor = (NonHunterEyeColorMode)value;
			if (!RoomPropUtil.TryGetBool(props, "PHFIX_CFG_EnableHunterAllyNameHighlight", out fixConfigSnapshot.EnableHunterAllyNameHighlight))
			{
				return null;
			}
			return fixConfigSnapshot;
		}
	}
	internal static class RoomKeys
	{
		public const string Active = "PH_Active";

		public const string Hunter = "PH_Hunter";

		public const string Hunters = "PH_Hunters";

		public const string UnlockAt = "PHFIX_UnlockAt";

		public const string UnlockSerial = "PHFIX_UnlockSerial";

		public const string CfgPreHideSeconds = "PHFIX_CFG_PreHideSeconds";

		public const string CfgHunterLockSeconds = "PHFIX_CFG_HunterLockSeconds";

		public const string CfgRoundSeconds = "PHFIX_CFG_RoundSeconds";

		public const string CfgMissPenaltyHP = "PHFIX_CFG_MissPenaltyHP";

		public const string CfgGunRangeMeters = "PHFIX_CFG_GunRangeMeters";

		public const string CfgGunCooldownSeconds = "PHFIX_CFG_GunCooldownSeconds";

		public const string CfgHunterCount = "PHFIX_CFG_HunterCount";

		public const string CfgRefillHuntersWhenHunterLeaves = "PHFIX_CFG_RefillHuntersWhenHunterLeaves";

		public const string CfgRecentHunterWeight0 = "PHFIX_CFG_RecentHunterWeight0";

		public const string CfgRecentHunterWeight1 = "PHFIX_CFG_RecentHunterWeight1";

		public const string CfgRecentHunterWeight2 = "PHFIX_CFG_RecentHunterWeight2";

		public const string CfgRecentHunterWeight3 = "PHFIX_CFG_RecentHunterWeight3";

		public const string CfgLowestCountBonusMultiplier = "PHFIX_CFG_LowestCountBonusMultiplier";

		public const string CfgNonHunterEyeColor = "PHFIX_CFG_NonHunterEyeColor";

		public const string CfgEnableHunterAllyNameHighlight = "PHFIX_CFG_EnableHunterAllyNameHighlight";
	}
	internal static class PlayerKeys
	{
		public const string Ready = "PHFIX_Ready";

		public const string HasPropHunt = "PHFIX_HasPropHunt";

		public const string HasFix = "PHFIX_HasFix";

		public const string FixVersion = "PHFIX_Version";
	}
	internal static class RoomPropUtil
	{
		public static bool TryGetInt(Hashtable props, string key, out int value)
		{
			value = 0;
			if (props == null || !((Dictionary<object, object>)(object)props).ContainsKey(key))
			{
				return false;
			}
			object obj = props[(object)key];
			try
			{
				if (obj is int)
				{
					value = (int)obj;
					return true;
				}
				if (obj is byte)
				{
					value = (byte)obj;
					return true;
				}
				if (obj is short)
				{
					value = (short)obj;
					return true;
				}
				if (obj is long)
				{
					value = (int)(long)obj;
					return true;
				}
				if (obj is float)
				{
					value = Mathf.RoundToInt((float)obj);
					return true;
				}
				if (obj is double)
				{
					value = (int)(double)obj;
					return true;
				}
				if (obj is string && int.TryParse((string)obj, out value))
				{
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		public static bool TryGetFloat(Hashtable props, string key, out float value)
		{
			value = 0f;
			if (props == null || !((Dictionary<object, object>)(object)props).ContainsKey(key))
			{
				return false;
			}
			object obj = props[(object)key];
			try
			{
				if (obj is float)
				{
					value = (float)obj;
					return true;
				}
				if (obj is int)
				{
					value = (int)obj;
					return true;
				}
				if (obj is double)
				{
					value = (float)(double)obj;
					return true;
				}
				if (obj is long)
				{
					value = (long)obj;
					return true;
				}
				if (obj is string && float.TryParse((string)obj, out value))
				{
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		public static bool TryGetBool(Hashtable props, string key, out bool value)
		{
			value = false;
			if (props == null || !((Dictionary<object, object>)(object)props).ContainsKey(key))
			{
				return false;
			}
			object obj = props[(object)key];
			try
			{
				if (obj is bool)
				{
					value = (bool)obj;
					return true;
				}
				if (obj is int)
				{
					value = (int)obj != 0;
					return true;
				}
				if (obj is byte)
				{
					value = (byte)obj != 0;
					return true;
				}
				if (obj is string && bool.TryParse((string)obj, out value))
				{
					return true;
				}
			}
			catch
			{
			}
			return false;
		}
	}
	internal static class PropHuntFixState
	{
		private static readonly Random Rng = new Random();

		public static readonly HashSet<int> CurrentHunters = new HashSet<int>();

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

		public static readonly Queue<List<string>> RecentHunterHistory = new Queue<List<string>>();

		public static FixConfigSnapshot AppliedSnapshot;

		public static FixConfigSnapshot PendingSnapshot;

		public static bool PendingGameplayApply;

		public static void ResetRoomState()
		{
			CurrentHunters.Clear();
			RecentHunterHistory.Clear();
			TotalHunterCountsByUserKey.Clear();
			PendingSnapshot = null;
			AppliedSnapshot = null;
			PendingGameplayApply = false;
		}

		public static string GetIdentityKey(Player player)
		{
			if (player == null)
			{
				return "unknown";
			}
			try
			{
				if (!string.IsNullOrEmpty(player.UserId))
				{
					return "uid:" + player.UserId;
				}
			}
			catch
			{
			}
			try
			{
				object obj2 = ((AccessTools.Property(typeof(Player), "UserId") != null) ? player.UserId : null);
				if (obj2 != null)
				{
					return "sid:" + obj2.ToString();
				}
			}
			catch
			{
			}
			return "actor:" + player.ActorNumber;
		}

		public static int GetRecentHunterCount(string userKey)
		{
			int num = 0;
			foreach (List<string> item in RecentHunterHistory)
			{
				if (item.Contains(userKey))
				{
					num++;
				}
			}
			return num;
		}

		public static int GetTotalHunterCount(string userKey)
		{
			if (TotalHunterCountsByUserKey.TryGetValue(userKey, out var value))
			{
				return value;
			}
			return 0;
		}

		public static void CommitSelectedHunters(List<Player> selectedPlayers)
		{
			if (selectedPlayers == null || selectedPlayers.Count == 0)
			{
				return;
			}
			List<string> list = new List<string>();
			for (int i = 0; i < selectedPlayers.Count; i++)
			{
				Player player = selectedPlayers[i];
				string identityKey = GetIdentityKey(player);
				list.Add(identityKey);
				if (!TotalHunterCountsByUserKey.ContainsKey(identityKey))
				{
					TotalHunterCountsByUserKey[identityKey] = 0;
				}
				TotalHunterCountsByUserKey[identityKey]++;
			}
			RecentHunterHistory.Enqueue(list);
			while (RecentHunterHistory.Count > 3)
			{
				RecentHunterHistory.Dequeue();
			}
		}

		public static float BuildWeight(Player player, FixConfigSnapshot snapshot, List<Player> allCandidates)
		{
			string identityKey = GetIdentityKey(player);
			int recentHunterCount = GetRecentHunterCount(identityKey);
			int totalHunterCount = GetTotalHunterCount(identityKey);
			int num = int.MaxValue;
			bool flag = true;
			int num2 = int.MinValue;
			for (int i = 0; i < allCandidates.Count; i++)
			{
				int totalHunterCount2 = GetTotalHunterCount(GetIdentityKey(allCandidates[i]));
				if (i == 0)
				{
					num2 = totalHunterCount2;
				}
				else if (num2 != totalHunterCount2)
				{
					flag = false;
				}
				if (totalHunterCount2 < num)
				{
					num = totalHunterCount2;
				}
			}
			float num3 = Mathf.Clamp(recentHunterCount, 0, 3) switch
			{
				0 => snapshot.RecentHunterWeight0, 
				1 => snapshot.RecentHunterWeight1, 
				2 => snapshot.RecentHunterWeight2, 
				_ => snapshot.RecentHunterWeight3, 
			};
			if (!flag && totalHunterCount == num)
			{
				num3 *= snapshot.LowestCountBonusMultiplier;
			}
			return Mathf.Max(0.01f, num3);
		}

		public static List<Player> SelectHunters(List<Player> activePlayers, FixConfigSnapshot snapshot, ICollection<int> excludeActorNumbers)
		{
			List<Player> list = new List<Player>();
			for (int i = 0; i < activePlayers.Count; i++)
			{
				Player val = activePlayers[i];
				if (val != null && !val.IsInactive && (excludeActorNumbers == null || !excludeActorNumbers.Contains(val.ActorNumber)))
				{
					list.Add(val);
				}
			}
			list = list.OrderBy((Player p) => p.ActorNumber).ToList();
			int num = Mathf.Clamp(snapshot.HunterCount, 1, Mathf.Max(1, list.Count));
			if (activePlayers.Count > 0)
			{
				num = Mathf.Min(num, Mathf.Max(1, activePlayers.Count - 1));
			}
			List<Player> list2 = new List<Player>();
			while (list2.Count < num && list.Count > 0)
			{
				float num2 = 0f;
				for (int j = 0; j < list.Count; j++)
				{
					num2 += BuildWeight(list[j], snapshot, list);
				}
				double num3 = Rng.NextDouble() * (double)num2;
				double num4 = 0.0;
				int index = list.Count - 1;
				for (int k = 0; k < list.Count; k++)
				{
					num4 += (double)BuildWeight(list[k], snapshot, list);
					if (num3 <= num4)
					{
						index = k;
						break;
					}
				}
				list2.Add(list[index]);
				list.RemoveAt(index);
			}
			if (PropHuntFixPlugin.CfgWriteHunterSelectionLog.Value)
			{
				LogSelection(activePlayers, list2, snapshot);
			}
			return list2;
		}

		private static void LogSelection(List<Player> activePlayers, List<Player> selected, FixConfigSnapshot snapshot)
		{
			try
			{
				List<string> list = new List<string>();
				for (int i = 0; i < activePlayers.Count; i++)
				{
					Player val = activePlayers[i];
					string identityKey = GetIdentityKey(val);
					list.Add(val.ActorNumber + "=" + GetTotalHunterCount(identityKey));
				}
				List<string> list2 = new List<string>();
				for (int j = 0; j < selected.Count; j++)
				{
					list2.Add(selected[j].ActorNumber.ToString());
				}
				PropHuntFixPlugin.Log.LogInfo((object)("[PropHunt_Fix] Active players: " + activePlayers.Count));
				PropHuntFixPlugin.Log.LogInfo((object)("[PropHunt_Fix] Config hunter count: " + snapshot.HunterCount));
				PropHuntFixPlugin.Log.LogInfo((object)("[PropHunt_Fix] Total hunter counts: " + string.Join(", ", list.ToArray())));
				PropHuntFixPlugin.Log.LogInfo((object)("[PropHunt_Fix] Selected hunters: " + string.Join(", ", list2.ToArray())));
			}
			catch (Exception ex)
			{
				PropHuntFixPlugin.Log.LogWarning((object)("[PropHunt_Fix] Selection log failed: " + ex.Message));
			}
		}

		public static void SyncHuntersFromRoomProperties(Hashtable props)
		{
			CurrentHunters.Clear();
			if (props == null)
			{
				return;
			}
			if (((Dictionary<object, object>)(object)props).ContainsKey("PH_Hunters"))
			{
				object obj = props[(object)"PH_Hunters"];
				if (obj is int[])
				{
					int[] array = (int[])obj;
					for (int i = 0; i < array.Length; i++)
					{
						CurrentHunters.Add(array[i]);
					}
					return;
				}
				if (obj is object[])
				{
					object[] array2 = (object[])obj;
					for (int j = 0; j < array2.Length; j++)
					{
						if (TryToInt(array2[j], out var val))
						{
							CurrentHunters.Add(val);
						}
					}
					return;
				}
			}
			if (RoomPropUtil.TryGetInt(props, "PH_Hunter", out var value))
			{
				CurrentHunters.Add(value);
			}
		}

		public static bool TryToInt(object o, out int val)
		{
			try
			{
				if (o is int)
				{
					val = (int)o;
					return true;
				}
				if (o is byte)
				{
					val = (byte)o;
					return true;
				}
				if (o is short)
				{
					val = (short)o;
					return true;
				}
				if (o is long)
				{
					val = (int)(long)o;
					return true;
				}
				if (o is float)
				{
					val = (int)(float)o;
					return true;
				}
				if (o is double)
				{
					val = (int)(double)o;
					return true;
				}
				if (o is string && int.TryParse((string)o, out val))
				{
					return true;
				}
			}
			catch
			{
			}
			val = -1;
			return false;
		}
	}
	public class ReadySyncService : MonoBehaviourPunCallbacks
	{
		public static bool IsLocalReadySent;

		private void Start()
		{
			TrySendReady();
		}

		public override void OnJoinedRoom()
		{
			TrySendReady();
		}

		private void Update()
		{
			if (!IsLocalReadySent && PhotonNetwork.InRoom)
			{
				TrySendReady();
			}
		}

		private void TrySendReady()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			try
			{
				if (PhotonNetwork.InRoom && PhotonNetwork.LocalPlayer != null)
				{
					bool flag = AccessTools.TypeByName("RepoMods.PropHunt.PropHuntPlugin") != null;
					bool flag2 = (Object)(object)PropHuntFixPlugin.Instance != (Object)null;
					if (flag && flag2)
					{
						Hashtable val = new Hashtable();
						val[(object)"PHFIX_Ready"] = true;
						val[(object)"PHFIX_HasPropHunt"] = flag;
						val[(object)"PHFIX_HasFix"] = flag2;
						val[(object)"PHFIX_Version"] = "1.0.0";
						PhotonNetwork.LocalPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
						IsLocalReadySent = true;
					}
				}
			}
			catch
			{
			}
		}
	}
	public class HunterLockAudioWatcher : MonoBehaviour
	{
	}
	public class HostConfigSyncService : MonoBehaviourPunCallbacks
	{
		private static HostConfigSyncService Instance;

		private FixConfigSnapshot lastWrittenSnapshot;

		private void Awake()
		{
			Instance = this;
			SubscribeConfigChanges();
		}

		public override void OnJoinedRoom()
		{
			TryWriteSnapshot();
		}

		public override void OnLeftRoom()
		{
			lastWrittenSnapshot = null;
		}

		public static void RequestWriteSnapshot()
		{
			try
			{
				if ((Object)(object)Instance != (Object)null)
				{
					Instance.TryWriteSnapshot();
					return;
				}
				HostConfigSyncService hostConfigSyncService = Object.FindObjectOfType<HostConfigSyncService>();
				if ((Object)(object)hostConfigSyncService != (Object)null)
				{
					hostConfigSyncService.TryWriteSnapshot();
				}
			}
			catch
			{
			}
		}

		private void SubscribeConfigChanges()
		{
			OriginalPropHuntConfigBridge.SubscribeToOriginalConfigChanges(OnConfigChanged);
			SubscribeConfigEntry((ConfigEntryBase)(object)PropHuntFixPlugin.CfgHunterCount, OnConfigChanged);
			SubscribeConfigEntry((ConfigEntryBase)(object)PropHuntFixPlugin.CfgRefillHuntersWhenHunterLeaves, OnConfigChanged);
			SubscribeConfigEntry((ConfigEntryBase)(object)PropHuntFixPlugin.CfgEnableHunterAllyNameHighlight, OnConfigChanged);
		}

		private void SubscribeConfigEntry(ConfigEntryBase entry, EventHandler handler)
		{
			try
			{
				if (entry != null)
				{
					EventInfo @event = ((object)entry).GetType().GetEvent("SettingChanged", BindingFlags.Instance | BindingFlags.Public);
					if (@event != null)
					{
						@event.AddEventHandler(entry, handler);
					}
				}
			}
			catch
			{
			}
		}

		private void OnConfigChanged(object sender, EventArgs e)
		{
			TryWriteSnapshot();
		}

		public void TryWriteSnapshot()
		{
			if (!PhotonNetwork.InRoom || !PhotonNetwork.IsMasterClient || PhotonNetwork.CurrentRoom == null)
			{
				return;
			}
			FixConfigSnapshot fixConfigSnapshot = FixConfigSnapshot.FromLocalConfig();
			if (lastWrittenSnapshot != null && fixConfigSnapshot.EqualsTo(lastWrittenSnapshot))
			{
				return;
			}
			try
			{
				PhotonNetwork.CurrentRoom.SetCustomProperties(fixConfigSnapshot.ToHashtable(), (Hashtable)null, (WebFlags)null);
				lastWrittenSnapshot = fixConfigSnapshot;
				if (PropHuntFixPlugin.CfgWriteHunterSelectionLog == null || PropHuntFixPlugin.CfgWriteHunterSelectionLog.Value)
				{
					PropHuntFixPlugin.Log.LogInfo((object)("[PropHunt_Fix] Host config snapshot synchronized. PreHide=" + fixConfigSnapshot.PreHideSeconds.ToString("0.00") + ", HunterLock=" + fixConfigSnapshot.HunterLockSeconds.ToString("0.00") + ", Round=" + fixConfigSnapshot.RoundSeconds.ToString("0.00") + ", MissPenalty=" + fixConfigSnapshot.MissPenaltyHP + ", Range=" + fixConfigSnapshot.GunRangeMeters.ToString("0.00") + ", Cooldown=" + fixConfigSnapshot.GunCooldownSeconds.ToString("0.00") + ", HunterCount=" + fixConfigSnapshot.HunterCount));
				}
			}
			catch (Exception ex)
			{
				PropHuntFixPlugin.Log.LogWarning((object)("[PropHunt_Fix] Host config sync failed: " + ex.Message));
			}
		}
	}
	public class ClientConfigApplyService : MonoBehaviourPunCallbacks
	{
		public static ClientConfigApplyService Instance;

		private void Awake()
		{
			Instance = this;
		}

		public override void OnJoinedRoom()
		{
			QueueSnapshotFromCurrentRoom();
			ApplyPendingVisuals();
			PropHuntFixPlugin.EnsureRuntimeRoot();
		}

		public override void OnLeftRoom()
		{
			PropHuntFixState.ResetRoomState();
		}

		public override void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged)
		{
			QueueSnapshotFromCurrentRoom();
			ApplyPendingVisuals();
		}

		public void QueueSnapshotFromCurrentRoom()
		{
			if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null)
			{
				FixConfigSnapshot fixConfigSnapshot = FixConfigSnapshot.FromRoomProperties(((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties);
				if (fixConfigSnapshot != null)
				{
					PropHuntFixState.PendingSnapshot = fixConfigSnapshot;
				}
			}
		}

		public void ApplyPendingVisuals()
		{
			if (PropHuntFixState.PendingSnapshot != null)
			{
				EyeColorRefreshService.ApplyAllVisiblePlayerEyes();
				NameTagPatch.RefreshAllNameTags();
			}
		}

		public void RequestGameplayApplyForNextRound()
		{
			PropHuntFixState.PendingGameplayApply = true;
		}

		public void ApplyPendingGameplayIfRequested()
		{
			if (PropHuntFixState.PendingGameplayApply && PropHuntFixState.PendingSnapshot != null)
			{
				PropHuntManager instance = PropHuntManager.Instance;
				if (!((Object)(object)instance == (Object)null))
				{
					FixConfigSnapshot pendingSnapshot = PropHuntFixState.PendingSnapshot;
					instance.PreHideSeconds = pendingSnapshot.PreHideSeconds;
					instance.HunterLockSeconds = pendingSnapshot.HunterLockSeconds;
					instance.RoundSeconds = pendingSnapshot.RoundSeconds;
					instance.MissPenaltyHP = pendingSnapshot.MissPenaltyHP;
					instance.GunRangeMeters = pendingSnapshot.GunRangeMeters;
					instance.GunCooldownSeconds = pendingSnapshot.GunCooldownSeconds;
					PropHuntFixState.AppliedSnapshot = pendingSnapshot;
					PropHuntFixState.PendingGameplayApply = false;
					EyeColorRefreshService.ApplyAllVisiblePlayerEyes();
					NameTagPatch.RefreshAllNameTags();
					PropHuntFixPlugin.Log.LogInfo((object)"[PropHunt_Fix] Pending gameplay config applied.");
				}
			}
		}
	}
	public class EyeColorRefreshService : MonoBehaviourPunCallbacks
	{
		private void Update()
		{
			ApplyAllVisiblePlayerEyes();
		}

		private void LateUpdate()
		{
			ApplyAllVisiblePlayerEyes();
		}

		public override void OnJoinedRoom()
		{
			ApplyAllVisiblePlayerEyes();
		}

		public override void OnPlayerEnteredRoom(Player newPlayer)
		{
			ApplyAllVisiblePlayerEyes();
		}

		public override void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged)
		{
			ApplyAllVisiblePlayerEyes();
		}

		public static void ApplyAllVisiblePlayerEyes()
		{
			try
			{
				if (!((Object)(object)GameDirector.instance == (Object)null) && GameDirector.instance.PlayerList != null)
				{
					for (int i = 0; i < GameDirector.instance.PlayerList.Count; i++)
					{
						ApplyEyeColorForAvatar(GameDirector.instance.PlayerList[i]);
					}
				}
			}
			catch
			{
			}
		}

		public static void ApplyEyeColorForAvatar(PlayerAvatar avatar)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)avatar == (Object)null || (Object)(object)avatar.photonView == (Object)null || (Object)(object)avatar.playerHealth == (Object)null || avatar.photonView.Owner == null || !TryGetEyeState(avatar.photonView.Owner.ActorNumber, out var state))
			{
				return;
			}
			try
			{
				avatar.playerHealth.EyeMaterialOverride(state, 0.25f, 999999);
			}
			catch
			{
			}
		}

		private static bool TryGetEyeState(int actorNumber, out EyeOverrideState state)
		{
			if (PropHuntFixState.CurrentHunters.Contains(actorNumber))
			{
				state = (EyeOverrideState)1;
				return true;
			}
			state = (EyeOverrideState)2;
			return false;
		}
	}
	[HarmonyPatch(typeof(PropHuntManager), "Start")]
	public static class Patch_PropHuntManager_Start
	{
		private static void Prefix()
		{
			if (!PhotonNetwork.IsMasterClient || !PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null)
			{
				return;
			}
			Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties;
			if (!((Dictionary<object, object>)(object)customProperties).ContainsKey("PH_Active"))
			{
				FixConfigSnapshot snapshot = PropHuntFixState.PendingSnapshot ?? FixConfigSnapshot.FromLocalConfig();
				List<Player> list = PhotonNetwork.PlayerList.Where((Player p) => p != null && !p.IsInactive).ToList();
				if (list.Count > 1)
				{
					List<Player> list2 = PropHuntFixState.SelectHunters(list, snapshot, null);
					PropHuntFixState.CommitSelectedHunters(list2);
					SetHunterRoomProperties(list2);
					HunterUnlockCountdownController.PublishHostUnlockTimeForNewRound(snapshot);
				}
			}
		}

		private static void Postfix(PropHuntManager __instance)
		{
			PropHuntFixRuntime.ApplyRoomHuntersToManager(__instance);
			if ((Object)(object)ClientConfigApplyService.Instance != (Object)null)
			{
				PropHuntFixPlugin.EnsureRuntimeRoot();
				if ((Object)(object)ClientConfigApplyService.Instance != (Object)null)
				{
					ClientConfigApplyService.Instance.QueueSnapshotFromCurrentRoom();
				}
				PropHuntFixPlugin.EnsureRuntimeRoot();
				if ((Object)(object)ClientConfigApplyService.Instance != (Object)null)
				{
					ClientConfigApplyService.Instance.ApplyPendingGameplayIfRequested();
				}
			}
			EyeColorRefreshService.ApplyAllVisiblePlayerEyes();
		}

		internal static void SetHunterRoomProperties(List<Player> selected)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			if (PhotonNetwork.CurrentRoom != null && selected != null && selected.Count != 0)
			{
				int[] array = new int[selected.Count];
				for (int i = 0; i < selected.Count; i++)
				{
					array[i] = selected[i].ActorNumber;
				}
				Hashtable val = new Hashtable();
				val[(object)"PH_Active"] = 1;
				val[(object)"PH_Hunter"] = array[0];
				val[(object)"PH_Hunters"] = array;
				PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
			}
		}
	}
	[HarmonyPatch(typeof(PropHuntManager), "RepickHunterForNextRound")]
	public static class Patch_PropHuntManager_RepickHunterForNextRound
	{
		private static bool Prefix(PropHuntManager __instance)
		{
			if (!PhotonNetwork.IsMasterClient || !PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null)
			{
				return false;
			}
			FixConfigSnapshot snapshot = PropHuntFixState.PendingSnapshot ?? PropHuntFixState.AppliedSnapshot ?? FixConfigSnapshot.FromLocalConfig();
			List<Player> list = PhotonNetwork.PlayerList.Where((Player p) => p != null && !p.IsInactive).ToList();
			if (list.Count <= 1)
			{
				return false;
			}
			HashSet<int> excludeActorNumbers = new HashSet<int>(PropHuntFixState.CurrentHunters);
			List<Player> list2 = PropHuntFixState.SelectHunters(list, snapshot, null);
			if (list2.Count == 0)
			{
				list2 = PropHuntFixState.SelectHunters(list, snapshot, excludeActorNumbers);
			}
			PropHuntFixState.CommitSelectedHunters(list2);
			Patch_PropHuntManager_Start.SetHunterRoomProperties(list2);
			return false;
		}
	}
	[HarmonyPatch(typeof(PropHuntManager), "OnPlayerLeftRoom")]
	public static class Patch_PropHuntManager_OnPlayerLeftRoom
	{
		private static bool Prefix(PropHuntManager __instance, Player otherPlayer)
		{
			if (!PhotonNetwork.IsMasterClient || !PhotonNetwork.InRoom || otherPlayer == null)
			{
				return false;
			}
			if (!PropHuntFixState.CurrentHunters.Contains(otherPlayer.ActorNumber))
			{
				return false;
			}
			PropHuntFixState.CurrentHunters.Remove(otherPlayer.ActorNumber);
			FixConfigSnapshot fixConfigSnapshot = PropHuntFixState.PendingSnapshot ?? PropHuntFixState.AppliedSnapshot ?? FixConfigSnapshot.FromLocalConfig();
			if (!fixConfigSnapshot.RefillHuntersWhenHunterLeaves)
			{
				Patch_PropHuntManager_Start.SetHunterRoomProperties(PhotonNetwork.PlayerList.Where((Player p) => p != null && PropHuntFixState.CurrentHunters.Contains(p.ActorNumber)).ToList());
				return false;
			}
			List<Player> list = PhotonNetwork.PlayerList.Where((Player p) => p != null && !p.IsInactive && !PropHuntFixState.CurrentHunters.Contains(p.ActorNumber)).ToList();
			if (list.Count > 0)
			{
				List<Player> list2 = PropHuntFixState.SelectHunters(list, fixConfigSnapshot, null);
				if (list2.Count > 1)
				{
					list2 = list2.Take(1).ToList();
				}
				if (list2.Count > 0)
				{
					PropHuntFixState.CurrentHunters.Add(list2[0].ActorNumber);
					PropHuntFixState.CommitSelectedHunters(list2);
				}
			}
			List<Player> list3 = PhotonNetwork.PlayerList.Where((Player p) => p != null && PropHuntFixState.CurrentHunters.Contains(p.ActorNumber)).ToList();
			if (list3.Count > 0)
			{
				Patch_PropHuntManager_Start.SetHunterRoomProperties(list3);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(PropHuntManager), "ApplyRoomState")]
	public static class Patch_PropHuntManager_ApplyRoomState
	{
		private static void Postfix(PropHuntManager __instance, Hashtable props)
		{
			PropHuntFixRuntime.ApplyRoomHuntersToManager(__instance, props);
			EyeColorRefreshService.ApplyAllVisiblePlayerEyes();
			NameTagPatch.RefreshAllNameTags();
		}
	}
	[HarmonyPatch(typeof(PropHuntManager), "OnRoomPropertiesUpdate")]
	public static class Patch_PropHuntManager_OnRoomPropertiesUpdate
	{
		private static void Postfix(PropHuntManager __instance)
		{
			PropHuntFixRuntime.ApplyRoomHuntersToManager(__instance);
			if ((Object)(object)ClientConfigApplyService.Instance != (Object)null)
			{
				PropHuntFixPlugin.EnsureRuntimeRoot();
				if ((Object)(object)ClientConfigApplyService.Instance != (Object)null)
				{
					ClientConfigApplyService.Instance.QueueSnapshotFromCurrentRoom();
				}
				ClientConfigApplyService.Instance.ApplyPendingVisuals();
			}
		}
	}
	[HarmonyPatch(typeof(PropHuntManager), "OnJoinedRoom")]
	public static class Patch_PropHuntManager_OnJoinedRoom
	{
		private static void Postfix(PropHuntManager __instance)
		{
			PropHuntFixRuntime.ApplyRoomHuntersToManager(__instance);
			if ((Object)(object)ClientConfigApplyService.Instance != (Object)null)
			{
				PropHuntFixPlugin.EnsureRuntimeRoot();
				if ((Object)(object)ClientConfigApplyService.Instance != (Object)null)
				{
					ClientConfigApplyService.Instance.QueueSnapshotFromCurrentRoom();
				}
				ClientConfigApplyService.Instance.ApplyPendingVisuals();
			}
			EyeColorRefreshService.ApplyAllVisiblePlayerEyes();
		}
	}
	[HarmonyPatch(typeof(PropHuntManager), "OnPlayerPropertiesUpdate")]
	public static class Patch_PropHuntManager_OnPlayerPropertiesUpdate
	{
		private static void Postfix()
		{
			NameTagPatch.RefreshAllNameTags();
		}
	}
	[HarmonyPatch(typeof(PropHuntManager), "OnEvent")]
	public static class Patch_PropHuntManager_OnEvent
	{
		private static bool Prefix(PropHuntManager __instance, EventData e)
		{
			if (e.Code == 119)
			{
				return HandleFixSoundEvent(e);
			}
			if (e.Code == 101)
			{
				return HandleKillEvent(__instance, e);
			}
			if (e.Code == 102)
			{
				return HandlePlayerDownEvent(__instance, e);
			}
			return true;
		}

		private static bool HandleFixSoundEvent(EventData e)
		{
			try
			{
				if (!(e.CustomData is object[] array) || array.Length < 2)
				{
					return false;
				}
				string text = array[0] as string;
				string text2 = array[1] as string;
				if (text == "PHFIX_SOUND" && !string.IsNullOrEmpty(text2))
				{
					PropHuntAudioUtil.PlayLocalSound(text2);
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool HandleKillEvent(PropHuntManager manager, EventData e)
		{
			if (!(e.CustomData is object[] array) || array.Length < 3)
			{
				return false;
			}
			string text = array[0] as string;
			if (text != "PH1")
			{
				return false;
			}
			if (!PropHuntFixState.TryToInt(array[1], out var val) || !PropHuntFixState.TryToInt(array[2], out var val2))
			{
				return false;
			}
			if (val2 <= 0 || !PropHuntFixState.CurrentHunters.Contains(val))
			{
				return false;
			}
			if (PhotonNetwork.LocalPlayer != null && PhotonNetwork.LocalPlayer.ActorNumber == val2)
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(PropHuntManager), "KillLocalPlayerClean", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					methodInfo.Invoke(manager, null);
				}
			}
			return false;
		}

		private static bool HandlePlayerDownEvent(PropHuntManager manager, EventData e)
		{
			if (!(e.CustomData is object[] array) || array.Length < 2)
			{
				return false;
			}
			string text = array[0] as string;
			if (text != "PH1")
			{
				return false;
			}
			if (!PropHuntFixState.TryToInt(array[1], out var val))
			{
				return false;
			}
			PropHuntAudioUtil.PlayLocalSound("player death01");
			if (PhotonNetwork.LocalPlayer != null && val == PhotonNetwork.LocalPlayer.ActorNumber)
			{
				PlayerAvatar val2 = PropHuntFixRuntime.FindLocalAvatar();
				if ((Object)(object)val2 != (Object)null)
				{
					PropDisguiseController component = ((Component)val2).GetComponent<PropDisguiseController>();
					if ((Object)(object)component != (Object)null)
					{
						component.ApplyClearLocal();
					}
				}
			}
			if (PhotonNetwork.IsMasterClient)
			{
				HashSet<int> value = Traverse.Create((object)manager).Field("_deadActors").GetValue<HashSet<int>>();
				value?.Add(val);
				bool flag = PropHuntFixRuntime.AreAllHuntersDead(value);
				bool flag2 = PropHuntFixRuntime.AreAllHidersDead(value);
				if (flag)
				{
					Traverse.Create((object)manager).Field("_roundArmed").SetValue((object)false);
					PropHuntFixRuntime.BroadcastMatchEnd(manager, (PHWinner)2, "All hunters eliminated");
				}
				else if (flag2)
				{
					Traverse.Create((object)manager).Field("_roundArmed").SetValue((object)false);
					PropHuntFixRuntime.BroadcastMatchEnd(manager, (PHWinner)1, "All hiders eliminated");
				}
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(PropHuntManager), "AllHidersDead")]
	public static class Patch_PropHuntManager_AllHidersDead
	{
		private static bool Prefix(ref bool __result)
		{
			HashSet<int> deadActors = PropHuntFixRuntime.GetDeadActors(PropHuntManager.Instance);
			__result = PropHuntFixRuntime.AreAllHidersDead(deadActors);
			return false;
		}
	}
	[HarmonyPatch(typeof(PropHuntManager), "OnGUI")]
	public static class Patch_PropHuntManager_OnGUI_Localized
	{
		private static readonly FieldInfo FieldEnding = AccessTools.Field(typeof(PropHuntManager), "_ending");

		private static readonly FieldInfo FieldEndUntil = AccessTools.Field(typeof(PropHuntManager), "_endUntil");

		private static readonly FieldInfo FieldWhoWon = AccessTools.Field(typeof(PropHuntManager), "_whoWon");

		private static readonly FieldInfo FieldFlashMsg = AccessTools.Field(typeof(PropHuntManager), "_flashMsg");

		private static readonly FieldInfo FieldFlashMsgUntil = AccessTools.Field(typeof(PropHuntManager), "_flashMsgUntil");

		private static readonly FieldInfo FieldCachedPropPhotonViewId = AccessTools.Field(typeof(PropHuntManager), "_cachedPropPhotonViewId");

		private static GUIStyle boxStyle;

		private static GUIStyle labelStyle;

		private static GUIStyle centerStyle;

		private static GUIStyle subCenterStyle;

		private static bool Prefix(PropHuntManager __instance)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Invalid comparison between Unknown and I4
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)__instance == (Object)null || SemiFunc.MenuLevel() || (Object)(object)LevelGenerator.Instance == (Object)null || (Object)(object)GameDirector.instance == (Object)null || !PhotonNetwork.InRoom)
				{
					return true;
				}
				PHRole localRole = GetLocalRole(__instance);
				if ((int)localRole == 0)
				{
					return true;
				}
				EnsureStyles();
				GUI.depth = 0;
				bool @bool = GetBool(FieldEnding, __instance);
				if (!@bool)
				{
					DrawStatusBox(__instance, localRole);
				}
				DrawFlash(__instance);
				if (@bool)
				{
					DrawEndBanner(__instance);
				}
				return false;
			}
			catch
			{
				return true;
			}
		}

		private static void DrawStatusBox(PropHuntManager manager, PHRole role)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Invalid comparison between Unknown and I4
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Invalid comparison between Unknown and I4
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Invalid comparison between Unknown and I4
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Invalid comparison between Unknown and I4
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Invalid comparison between Unknown and I4
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_036a: Unknown result type (might be due to invalid IL or missing references)
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(20f, 20f, 720f, 180f);
			string text = FixLocalization.Text("PropHunt") + " — " + (((int)role == 1) ? FixLocalization.Text("Hunter") : FixLocalization.Text("Hider"));
			string text2 = (((int)role == 1) ? (FixLocalization.Text("ScanHelp") + ": -" + manager.MissPenaltyHP + " HP") : (((object)(KeyCode)(ref manager.KeyHiderToggle)).ToString() + ": " + FixLocalization.Text("Disguise") + "  |  " + ((object)(KeyCode)(ref manager.KeyDisguiseViewToggle)).ToString() + ": View  |  " + ((object)(KeyCode)(ref manager.KeyLockToggle)).ToString() + ": " + FixLocalization.Text("Locked")));
			GUI.Box(val, text + "\n" + text2, boxStyle);
			float num = ((Rect)(ref val)).yMax + 6f;
			if ((int)role == 2 && manager.PreHidePhaseActive)
			{
				float seconds = Mathf.Max(0f, GetPrivateFloat(manager, "_preHideUntil") - Time.time);
				GUI.Label(new Rect(((Rect)(ref val)).x + 8f, num, ((Rect)(ref val)).width, 24f), FixLocalization.Text("HideTime") + ": " + FormatClock(seconds), labelStyle);
				num += 22f;
			}
			if (manager.RoundIsLive)
			{
				float seconds2 = Mathf.Max(0f, (float)(GetPrivateDouble(manager, "_roundEndRealtime") - (double)Time.time));
				GUI.Label(new Rect(((Rect)(ref val)).x + 8f, num, ((Rect)(ref val)).width, 24f), FixLocalization.Text("TimeLeft") + ": " + FormatClock(seconds2), labelStyle);
				num += 22f;
			}
			if ((int)role == 1 && manager.IsHunterLocked)
			{
				int num2 = Mathf.CeilToInt(Mathf.Max(0f, GetPrivateFloat(manager, "_hunterLockUntil") - Time.time));
				GUI.Label(new Rect(((Rect)(ref val)).x + 8f, num, ((Rect)(ref val)).width, 24f), FixLocalization.Text("HunterLock") + ": " + num2 + FixLocalization.Text("Sec"), labelStyle);
				num += 22f;
			}
			if ((int)role != 2)
			{
				return;
			}
			string text3 = FixLocalization.Text("LookValuable");
			int privateInt = GetPrivateInt(manager, "_cachedPropPhotonViewId");
			if (privateInt != 0 && (Object)(object)PhotonView.Find(privateInt) != (Object)null)
			{
				text3 = FixLocalization.Text("TargetLocked");
			}
			PlayerAvatar val2 = PropHuntFixRuntime.FindLocalAvatar();
			if ((Object)(object)val2 != (Object)null)
			{
				PropDisguiseController component = ((Component)val2).GetComponent<PropDisguiseController>();
				if ((Object)(object)component != (Object)null && component.IsLocked)
				{
					text3 = text3 + " [" + FixLocalization.Text("Locked") + "]";
				}
			}
			GUI.Label(new Rect(((Rect)(ref val)).x + 8f, num, ((Rect)(ref val)).width, 24f), FixLocalization.Text("Disguise") + ": " + text3, labelStyle);
		}

		private static void DrawFlash(PropHuntManager manager)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			float privateFloat = GetPrivateFloat(manager, "_flashMsgUntil");
			if (!(Time.time >= privateFloat))
			{
				string privateString = GetPrivateString(manager, "_flashMsg");
				if (!string.IsNullOrEmpty(privateString))
				{
					GUI.Label(new Rect(30f, 228f, 720f, 28f), FixLocalization.TranslateMessage(privateString), labelStyle);
				}
			}
		}

		private static void DrawEndBanner(PropHuntManager manager)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Invalid comparison between Unknown and I4
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(0f, 0f, (float)Screen.width, (float)Screen.height);
			GUI.color = new Color(0f, 0f, 0f, 0.55f);
			GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture);
			GUI.color = Color.white;
			PHWinner winner = GetWinner(manager);
			string text = (((int)winner == 2) ? FixLocalization.Text("HidersWin") : (((int)winner == 1) ? FixLocalization.Text("HunterWins") : FixLocalization.Text("Draw")));
			float privateFloat = GetPrivateFloat(manager, "_endUntil");
			string text2 = (PhotonNetwork.IsMasterClient ? Mathf.CeilToInt(Mathf.Max(0f, privateFloat - Time.time)).ToString() : "…");
			GUI.Label(new Rect(0f, (float)Screen.height * 0.35f, (float)Screen.width, 80f), text, centerStyle);
			GUI.Label(new Rect(0f, (float)Screen.height * 0.35f + 68f, (float)Screen.width, 60f), FixLocalization.PickForInternal("Next round starting in", "次のラウンド開始まで", "下一回合开始倒计时", "다음 라운드 시작까지", "До следующего раунда", "Prochain round dans", "Siguiente ronda en", "Nächste Runde in", "Próxima rodada em") + " " + text2, subCenterStyle);
		}

		private static void EnsureStyles()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Expected O, but got Unknown
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			if (boxStyle == null)
			{
				boxStyle = new GUIStyle(GUI.skin.box);
				boxStyle.alignment = (TextAnchor)0;
				boxStyle.fontSize = 16;
				boxStyle.wordWrap = true;
				boxStyle.normal.textColor = Color.white;
			}
			if (labelStyle == null)
			{
				labelStyle = new GUIStyle(GUI.skin.label);
				labelStyle.fontSize = 16;
				labelStyle.normal.textColor = Color.white;
			}
			if (centerStyle == null)
			{
				centerStyle = new GUIStyle(GUI.skin.label);
				centerStyle.alignment = (TextAnchor)4;
				centerStyle.fontStyle = (FontStyle)1;
				centerStyle.fontSize = Mathf.RoundToInt(Mathf.Clamp((float)Screen.width * 0.06f, 32f, 72f));
				centerStyle.normal.textColor = Color.white;
			}
			if (subCenterStyle == null)
			{
				subCenterStyle = new GUIStyle(GUI.skin.label);
				subCenterStyle.alignment = (TextAnchor)4;
				subCenterStyle.fontSize = Mathf.RoundToInt(Mathf.Clamp((float)Screen.width * 0.03f, 18f, 36f));
				subCenterStyle.normal.textColor = new Color(1f, 1f, 1f, 0.9f);
			}
		}

		private static PHRole GetLocalRole(PropHuntManager manager)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				object value = Traverse.Create((object)manager).Field("_localRole").GetValue();
				if (value is PHRole)
				{
					return (PHRole)value;
				}
			}
			catch
			{
			}
			return (PHRole)0;
		}

		private static PHWinner GetWinner(PropHuntManager manager)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				object value = Traverse.Create((object)manager).Field("_whoWon").GetValue();
				if (value is PHWinner)
				{
					return (PHWinner)value;
				}
			}
			catch
			{
			}
			return (PHWinner)0;
		}

		private static string FormatClock(float seconds)
		{
			int num = Mathf.CeilToInt(Mathf.Max(0f, seconds));
			return (num / 60).ToString("00") + ":" + (num % 60).ToString("00");
		}

		private static bool GetBool(FieldInfo field, object instance)
		{
			try
			{
				object obj = ((field != null) ? field.GetValue(instance) : null);
				return obj is bool && (bool)obj;
			}
			catch
			{
				return false;
			}
		}

		private static float GetPrivateFloat(PropHuntManager manager, string fieldName)
		{
			try
			{
				object value = Traverse.Create((object)manager).Field(fieldName).GetValue();
				if (value is float result)
				{
					return result;
				}
				if (value is double)
				{
					return (float)(double)value;
				}
			}
			catch
			{
			}
			return 0f;
		}

		private static double GetPrivateDouble(PropHuntManager manager, string fieldName)
		{
			try
			{
				object value = Traverse.Create((object)manager).Field(fieldName).GetValue();
				if (value is double result)
				{
					return result;
				}
				if (value is float)
				{
					return (float)value;
				}
			}
			catch
			{
			}
			return 0.0;
		}

		private static int GetPrivateInt(PropHuntManager manager, string fieldName)
		{
			try
			{
				object value = Traverse.Create((object)manager).Field(fieldName).GetValue();
				if (value is int)
				{
					return (int)value;
				}
			}
			catch
			{
			}
			return 0;
		}

		private static string GetPrivateString(PropHuntManager manager, string fieldName)
		{
			try
			{
				object value = Traverse.Create((object)manager).Field(fieldName).GetValue();
				return value as string;
			}
			catch
			{
			}
			return string.Empty;
		}
	}
	[HarmonyPatch(typeof(PropHuntManager), "Flash")]
	public static class Patch_PropHuntManager_Flash_Localized
	{
		private static void Prefix(ref string msg)
		{
			msg = FixLocalization.TranslateMessage(msg);
		}
	}
	[HarmonyPatch(typeof(PropHuntManager), "Update")]
	public static class Patch_PropHuntManager_Update_LockAudio
	{
		private static void Postfix(PropHuntManager __instance)
		{
			HunterUnlockCountdownController.Tick(__instance);
		}
	}
	[HarmonyPatch(typeof(PropHuntManager), "StartEndBannerLocal")]
	public static class Patch_PropHuntManager_StartEndBannerLocal
	{
		private static void Postfix(PropHuntManager __instance)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(PropHuntManager), "_endMsg");
				if (fieldInfo != null && (Object)(object)__instance != (Object)null)
				{
					string message = fieldInfo.GetValue(__instance) as string;
					fieldInfo.SetValue(__instance, FixLocalization.TranslateMessage(message));
				}
			}
			catch
			{
			}
			PropHuntAudioUtil.PlayLocalSound("extraction point success");
			if (PhotonNetwork.IsMasterClient && PhotonNetwork.CurrentRoom != null)
			{
				Hashtable val = new Hashtable();
				val[(object)"PHFIX_UnlockAt"] = 0.0;
				val[(object)"PHFIX_UnlockSerial"] = 0;
				PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
			}
			HostConfigSyncService.RequestWriteSnapshot();
			if ((Object)(object)ClientConfigApplyService.Instance != (Object)null)
			{
				PropHuntFixPlugin.EnsureRuntimeRoot();
				if ((Object)(object)ClientConfigApplyService.Instance != (Object)null)
				{
					ClientConfigApplyService.Instance.RequestGameplayApplyForNextRound();
				}
			}
		}
	}
	[HarmonyPatch(typeof(PropHuntManager), "SafeAdvanceScene")]
	public static class Patch_PropHuntManager_SafeAdvanceScene
	{
		private static void Prefix()
		{
			HostConfigSyncService.RequestWriteSnapshot();
			if ((Object)(object)ClientConfigApplyService.Instance != (Object)null)
			{
				PropHuntFixPlugin.EnsureRuntimeRoot();
				if ((Object)(object)ClientConfigApplyService.Instance != (Object)null)
				{
					ClientConfigApplyService.Instance.ApplyPendingGameplayIfRequested();
				}
			}
		}
	}
	public class NameTagOriginalPatchDisabler : MonoBehaviour
	{
		private float nextTry;

		private bool done;

		private void Update()
		{
			if (!done && !(Time.unscaledTime < nextTry))
			{
				nextTry = Time.unscaledTime + 1f;
				done = NameTagPatch.TryDisableOriginalHidePatch();
			}
		}
	}
	[HarmonyPatch(typeof(WorldSpaceUIPlayerName), "Update")]
	public static class NameTagPatch
	{
		private static readonly FieldInfo FieldPlayerAvatar = AccessTools.Field(typeof(WorldSpaceUIPlayerName), "playerAvatar");

		private static bool triedImmediateUnpatch;

		public static bool TryDisableOriginalHidePatch()
		{
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(WorldSpaceUIPlayerName), "Update", (Type[])null, (Type[])null);
				if (methodInfo == null || PropHuntFixPlugin.Harmony == null)
				{
					return false;
				}
				Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo);
				if (patchInfo != null && patchInfo.Prefixes != null)
				{
					for (int i = 0; i < patchInfo.Prefixes.Count; i++)
					{
						Patch val = patchInfo.Prefixes[i];
						if (val != null && !string.IsNullOrEmpty(val.owner) && !(val.owner == "REPOJP.PropHunt_Fix"))
						{
							string text = ((val.PatchMethod != null && val.PatchMethod.DeclaringType != null) ? val.PatchMethod.DeclaringType.Name : string.Empty);
							if (val.owner == "omni.repo.prophunt" || text.Contains("Patch_HidePlayerNames"))
							{
								PropHuntFixPlugin.Harmony.Unpatch((MethodBase)methodInfo, (HarmonyPatchType)1, val.owner);
							}
						}
					}
				}
				return true;
			}
			catch
			{
				return false;
			}
		}

		[HarmonyPriority(800)]
		private static bool Prefix()
		{
			if (!triedImmediateUnpatch)
			{
				triedImmediateUnpatch = true;
				TryDisableOriginalHidePatch();
			}
			return true;
		}

		private static void Postfix(WorldSpaceUIPlayerName __instance)
		{
			try
			{
				if (PhotonNetwork.InRoom)
				{
					PropHuntFixPlugin.EnsureRuntimeRoot();
				}
				if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance.text == (Object)null))
				{
					PlayerAvatar targetAvatar = GetTargetAvatar(__instance);
					if (!((Object)(object)targetAvatar == (Object)null))
					{
						ApplyNameTagVisual(__instance, targetAvatar);
					}
				}
			}
			catch
			{
			}
		}

		public static void RefreshAllNameTags()
		{
		}

		private static PlayerAvatar GetTargetAvatar(WorldSpaceUIPlayerName instance)
		{
			try
			{
				if (FieldPlayerAvatar != null)
				{
					object? value = FieldPlayerAvatar.GetValue(instance);
					PlayerAvatar val = (PlayerAvatar)((value is PlayerAvatar) ? value : null);
					if ((Object)(object)val != (Object)null)
					{
						return val;
					}
				}
				if ((Object)(object)instance != (Object)null)
				{
					PlayerAvatar componentInParent = ((Component)instance).GetComponentInParent<PlayerAvatar>();
					if ((Object)(object)componentInParent != (Object)null)
					{
						return componentInParent;
					}
				}
			}
			catch
			{
			}
			return null;
		}

		private static void ApplyNameTagVisual(WorldSpaceUIPlayerName instance, PlayerAvatar targetAvatar)
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.text == (Object)null || (Object)(object)targetAvatar == (Object)null || (Object)(object)targetAvatar.photonView == (Object)null || targetAvatar.photonView.Owner == null)
			{
				return;
			}
			Player localPlayer = PhotonNetwork.LocalPlayer;
			if (localPlayer == null)
			{
				return;
			}
			bool flag = PropHuntFixState.CurrentHunters.Contains(localPlayer.ActorNumber);
			bool flag2 = PropHuntFixState.CurrentHunters.Contains(targetAvatar.photonView.Owner.ActorNumber);
			bool flag3 = SemiFunc.MenuLevel();
			bool isMasterClient = PhotonNetwork.IsMasterClient;
			bool targetReady = IsTargetReady(targetAvatar.photonView.Owner);
			Color color = ((Graphic)instance.text).color;
			float a = color.a;
			if (flag3)
			{
				ApplyReadyUnderline(instance, targetAvatar, isMasterClient, localPlayer, targetReady);
				return;
			}
			RemoveReadyUnderline(instance);
			if (!IsRoundNameTagPatchEnabled() || a <= 0.01f)
			{
				return;
			}
			if (!flag)
			{
				if (flag2)
				{
					((Graphic)instance.text).color = new Color(1f, 0.15f, 0.15f, a);
				}
				else
				{
					((Graphic)instance.text).color = new Color(1f, 1f, 1f, a);
				}
			}
			else if (flag2)
			{
				((Graphic)instance.text).color = new Color(1f, 0.15f, 0.15f, a);
			}
			else
			{
				((Graphic)instance.text).color = new Color(color.r, color.g, color.b, 0f);
			}
		}

		private static bool IsRoundNameTagPatchEnabled()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Invalid comparison between Unknown and I4
			try
			{
				if (!PhotonNetwork.InRoom || SemiFunc.MenuLevel())
				{
					return false;
				}
				if ((Object)(object)GameDirector.instance == (Object)null || (int)GameDirector.instance.currentState != 2)
				{
					return false;
				}
				return (Object)(object)PropHuntManager.Instance != (Object)null;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsTargetReady(Player player)
		{
			try
			{
				if (player == null || player.CustomProperties == null)
				{
					return false;
				}
				Hashtable customProperties = player.CustomProperties;
				bool flag = ReadBoolProperty(customProperties, "PHFIX_Ready");
				bool flag2 = ReadBoolProperty(customProperties, "PHFIX_HasPropHunt");
				bool flag3 = ReadBoolProperty(customProperties, "PHFIX_HasFix");
				return flag && flag2 && flag3;
			}
			catch
			{
			}
			return false;
		}

		private static bool ReadBoolProperty(Hashtable props, string key)
		{
			try
			{
				if (props == null || !((Dictionary<object, object>)(object)props).ContainsKey(key))
				{
					return false;
				}
				object obj = props[(object)key];
				if (obj is bool result)
				{
					return result;
				}
				if (obj is int)
				{
					return (int)obj != 0;
				}
				if (obj is string)
				{
					return string.Equals((string)obj, "true", StringComparison.OrdinalIgnoreCase);
				}
			}
			catch
			{
			}
			return false;
		}

		private static void ApplyReadyUnderline(WorldSpaceUIPlayerName instance, PlayerAvatar targetAvatar, bool isHostView, Player localPlayer, bool targetReady)
		{
			try
			{
				string text = ((TMP_Text)instance.text).text;
				if (string.IsNullOrEmpty(text))
				{
					text = targetAvatar.photonView.Owner.NickName;
				}
				if (string.IsNullOrEmpty(text))
				{
					text = targetAvatar.photonView.Owner.ActorNumber.ToString();
				}
				text = StripReadyLine(text);
				if (isHostView && targetAvatar.photonView.Owner.ActorNumber != localPlayer.ActorNumber && !targetReady)
				{
					text = text + "\n<color=#ff0000><u>" + FixLocalization.Text("NotReady") + "</u></color>";
				}
				((TMP_Text)instance.text).text = text;
			}
			catch
			{
			}
		}

		private static void RemoveReadyUnderline(WorldSpaceUIPlayerName instance)
		{
			try
			{
				((TMP_Text)instance.text).text = StripReadyLine(((TMP_Text)instance.text).text);
			}
			catch
			{
			}
		}

		private static string StripReadyLine(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				return text;
			}
			string value = "<color=#ff0000><u>";
			int num = text.IndexOf(value, StringComparison.OrdinalIgnoreCase);
			if (num < 0)
			{
				return text;
			}
			int num2 = num;
			if (num2 > 0 && text[num2 - 1] == '\n')
			{
				num2--;
			}
			int num3 = text.IndexOf("</u></color>", num, StringComparison.OrdinalIgnoreCase);
			if (num3 < 0)
			{
				return text.Substring(0, num2);
			}
			num3 += "</u></color>".Length;
			return text.Remove(num2, num3 - num2);
		}
	}
	internal static class PropHuntFixRuntime
	{
		public static void ApplyRoomHuntersToManager(PropHuntManager manager)
		{
			Hashtable props = ((PhotonNetwork.CurrentRoom != null) ? ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties : null);
			ApplyRoomHuntersToManager(manager, props);
		}

		public static void ApplyRoomHuntersToManager(PropHuntManager manager, Hashtable props)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)manager == (Object)null)
			{
				return;
			}
			PropHuntFixState.SyncHuntersFromRoomProperties((props != null) ? props : ((PhotonNetwork.CurrentRoom != null) ? ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties : null));
			int num = ((PropHuntFixState.CurrentHunters.Count > 0) ? PropHuntFixState.CurrentHunters.First() : (-1));
			Traverse.Create((object)manager).Field("_hunterActor").SetValue((object)num);
			if (PhotonNetwork.LocalPlayer != null)
			{
				PHRole val = (PHRole)(PropHuntFixState.CurrentHunters.Contains(PhotonNetwork.LocalPlayer.ActorNumber) ? 1 : 2);
				if (props != null && (!((Dictionary<object, object>)(object)props).ContainsKey("PH_Active") || Convert.ToInt32(props[(object)"PH_Active"]) != 1))
				{
					val = (PHRole)0;
				}
				Traverse.Create((object)manager).Field("_localRole").SetValue((object)val);
			}
		}

		public static HashSet<int> GetDeadActors(PropHuntManager manager)
		{
			try
			{
				if ((Object)(object)manager == (Object)null)
				{
					return new HashSet<int>();
				}
				HashSet<int> value = Traverse.Create((object)manager).Field("_deadActors").GetValue<HashSet<int>>();
				return value ?? new HashSet<int>();
			}
			catch
			{
				return new HashSet<int>();
			}
		}

		public static PlayerAvatar FindLocalAvatar()
		{
			if ((Object)(object)GameDirector.instance == (Object)null || GameDirector.instance.PlayerList == null)
			{
				return null;
			}
			for (int i = 0; i < GameDirector.instance.PlayerList.Count; i++)
			{
				PlayerAvatar val = GameDirector.instance.PlayerList[i];
				if ((Object)(object)val != (Object)null && (Object)(object)val.photonView != (Object)null && val.photonView.IsMine)
				{
					return val;
				}
			}
			return null;
		}

		public static bool AreAllHidersDead(HashSet<int> deadActors)
		{
			Player[] playerList = PhotonNetwork.PlayerList;
			foreach (Player val in playerList)
			{
				if (val != null && !val.IsInactive && !PropHuntFixState.CurrentHunters.Contains(val.ActorNumber) && (deadActors == null || !deadActors.Contains(val.ActorNumber)))
				{
					return false;
				}
			}
			return true;
		}

		public static bool AreAllHuntersDead(HashSet<int> deadActors)
		{
			if (PropHuntFixState.CurrentHunters.Count == 0)
			{
				return false;
			}
			foreach (int currentHunter in PropHuntFixState.CurrentHunters)
			{
				if (deadActors == null || !deadActors.Contains(currentHunter))
				{
					return false;
				}
			}
			return true;
		}

		public static void BroadcastMatchEnd(PropHuntManager manager, PHWinner winner, string reason)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected I4, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			object[] array = new object[3]
			{
				"PH1",
				(int)winner,
				reason ?? string.Empty
			};
			PhotonNetwork.RaiseEvent((byte)103, (object)array, new RaiseEventOptions
			{
				Receivers = (ReceiverGroup)1
			}, SendOptions.SendReliable);
			MethodInfo methodInfo = AccessTools.Method(typeof(PropHuntManager), "StartEndBannerLocal", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				methodInfo.Invoke(manager, new object[2] { winner, reason });
			}
		}
	}
	public class MainMenuMusicVolumeService : MonoBehaviour
	{
		private static GameObject serviceObject;

		private float nextApply;

		public static void EnsureStarted()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			try
			{
				if (!((Object)serviceObject != (Object)null))
				{
					serviceObject = new GameObject("REPOJP_PropHuntFix_MainMenuMusicVolume");
					((Object)serviceObject).hideFlags = (HideFlags)61;
					Object.DontDestroyOnLoad((Object)serviceObject);
					serviceObject.AddComponent<MainMenuMusicVolumeService>();
				}
			}
			catch
			{
				serviceObject = null;
			}
		}

		private void Update()
		{
			if (!(Time.unscaledTime < nextApply))
			{
				nextApply = Time.unscaledTime + 0.25f;
				ApplyMainMenuMusicVolume();
			}
		}

		private static void ApplyMainMenuMusicVolume()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			try
			{
				float volume = GetVolume();
				AudioSource[] array = Object.FindObjectsOfType<AudioSource>(true);
				foreach (AudioSource val in array)
				{
					if (!((Object)val == (Object)null) && IsMainMenuSwapSource(val))
					{
						val.volume = volume;
					}
				}
			}
			catch
			{
			}
		}

		private static bool IsMainMenuSwapSource(AudioSource source)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			try
			{
				string text = ((Object)((Component)source).gameObject).name ?? string.Empty;
				string text2 = (((Object)source.clip != (Object)null) ? ((Object)source.clip).name : string.Empty);
				if (text.Equals("MainMenuMusic_Swap", StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
				if (text2.Equals("Constant Music - Main Menu", StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
				return false;
			}
			catch
			{
				return false;
			}
		}

		private static float GetVolume()
		{
			try
			{
				if (PropHuntFixPlugin.CfgMainMenuMusicVolumePercent == null)
				{
					return 0.5f;
				}
				return (float)Mathf.Clamp(PropHuntFixPlugin.CfgMainMenuMusicVolumePercent.Value, 0, 100) / 100f;
			}
			catch
			{
				return 0.5f;
			}
		}
	}
	internal static class PropHuntAudioUtil
	{
		private static readonly Dictionary<string, AudioClip> ClipCache = new Dictionary<string, AudioClip>(StringComparer.OrdinalIgnoreCase);

		private static GameObject audioObject;

		private static AudioSource audioSource;

		public static void EnsureReady()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			try
			{
				if (!((Object)audioSource != (Object)null))
				{
					audioObject = new GameObject("REPOJP_PropHuntFix_AudioSource");
					((Object)audioObject).hideFlags = (HideFlags)61;
					Object.DontDestroyOnLoad((Object)audioObject);
					audioSource = audioObject.AddComponent<AudioSource>();
					audioSource.playOnAwake = false;
					audioSource.loop = false;
					audioSource.mute = false;
					audioSource.volume = 1f;
					audioSource.pitch = 1f;
					audioSource.spatialBlend = 0f;
					audioSource.priority = 0;
					audioSource.dopplerLevel = 0f;
					audioSource.rolloffMode = (AudioRolloffMode)1;
				}
			}
			catch
			{
				audioObject = null;
				audioSource = null;
			}
		}

		public static void PlayLocalSound(string officialClipName)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			try
			{
				if (string.IsNullOrEmpty(officialClipName))
				{
					return;
				}
				AudioClip val = FindOfficialClip(officialClipName);
				if (!((Object)val == (Object)null))
				{
					if ((Object)audioSource == (Object)null)
					{
						EnsureReady();
					}
					if (!((Object)audioSource == (Object)null))
					{
						audioSource.PlayOneShot(val, GetVolume(officialClipName));
					}
				}
			}
			catch
			{
			}
		}

		private static float GetVolume(string officialClipName)
		{
			try
			{
				if (string.Equals(officialClipName, "player death01", StringComparison.OrdinalIgnoreCase))
				{
					return (float)Mathf.Clamp(PropHuntFixPlugin.CfgDeathSoundVolumePercent.Value, 0, 100) / 100f;
				}
				if (string.Equals(officialClipName, "extraction point success", StringComparison.OrdinalIgnoreCase))
				{
					return (float)Mathf.Clamp(PropHuntFixPlugin.CfgWinSoundVolumePercent.Value, 0, 100) / 100f;
				}
			}
			catch
			{
			}
			return 0.5f;
		}

		private static AudioClip FindOfficialClip(string officialClipName)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			if (ClipCache.TryGetValue(officialClipName, out var value) && (Object)value != (Object)null)
			{
				return value;
			}
			try
			{
				AudioClip[] array = Resources.FindObjectsOfTypeAll<AudioClip>();
				foreach (AudioClip val in array)
				{
					if ((Object)val != (Object)null && ((Object)val).name == officialClipName)
					{
						ClipCache[officialClipName] = val;
						return val;
					}
				}
			}
			catch
			{
			}
			return null;
		}
	}
	internal static class PropHuntCountdownBeepUtil
	{
		private static GameObject audioObject;

		private static AudioSource audioSource;

		private static AudioClip shortBeepClip;

		private static AudioClip longBeepClip;

		private static void EnsureReady()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			try
			{
				if (!((Object)audioSource != (Object)null))
				{
					audioObject = new GameObject("REPOJP_PropHuntFix_CountdownAudioSource");
					((Object)audioObject).hideFlags = (HideFlags)61;
					Object.DontDestroyOnLoad((Object)audioObject);
					audioSource = audioObject.AddComponent<AudioSource>();
					audioSource.playOnAwake = false;
					audioSource.loop = false;
					audioSource.mute = false;
					audioSource.volume = 1f;
					audioSource.pitch = 1f;
					audioSource.spatialBlend = 0f;
					audioSource.priority = 0;
					audioSource.dopplerLevel = 0f;
					audioSource.rolloffMode = (AudioRolloffMode)1;
				}
			}
			catch
			{
				audioObject = null;
				audioSource = null;
			}
		}

		public static void PlayShortBeep()
		{
			PlayGeneratedBeep(GetShortBeepClip());
		}

		public static void PlayLongBeep()
		{
			PlayGeneratedBeep(GetLongBeepClip());
		}

		private static void PlayGeneratedBeep(AudioClip clip)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			try
			{
				if (!((Object)clip == (Object)null))
				{
					EnsureReady();
					if (!((Object)audioSource == (Object)null))
					{
						audioSource.PlayOneShot(clip, GetVolume());
					}
				}
			}
			catch
			{
			}
		}

		private static float GetVolume()
		{
			try
			{
				if (PropHuntFixPlugin.CfgCountdownSoundVolumePercent == null)
				{
					return 0.5f;
				}
				return (float)Mathf.Clamp(PropHuntFixPlugin.CfgCountdownSoundVolumePercent.Value, 0, 100) / 100f;
			}
			catch
			{
				return 0.5f;
			}
		}

		private static AudioClip GetShortBeepClip()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			if ((Object)shortBeepClip == (Object)null)
			{
				shortBeepClip = CreateToneClip("REPOJP_PropHuntFix_Countdown_Put", 520f, 0.12f, 44100);
			}
			return shortBeepClip;
		}

		private static AudioClip GetLongBeepClip()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			if ((Object)longBeepClip == (Object)null)
			{
				longBeepClip = CreateToneClip("REPOJP_PropHuntFix_Countdown_Pee", 780f, 0.55f, 44100);
			}
			return longBeepClip;
		}

		private static AudioClip CreateToneClip(string name, float frequency, float duration, int sampleRate)
		{
			int num = Mathf.Max(1, Mathf.CeilToInt((float)sampleRate * duration));
			float[] array = new float[num];
			for (int i = 0; i < num; i++)
			{
				float num2 = (float)i / (float)sampleRate;
				float num3 = 1f;
				if (num2 < 0.01f)
				{
					num3 = num2 / 0.01f;
				}
				else if (num2 > duration - 0.03f)
				{
					num3 = Mathf.Clamp01((duration - num2) / 0.03f);
				}
				array[i] = Mathf.Sin(MathF.PI * 2f * frequency * num2) * 0.55f * num3;
			}
			AudioClip val = AudioClip.Create(name, num, 1, sampleRate, false);
			val.SetData(array, 0);
			return val;
		}
	}
	internal static class HunterUnlockCountdownController
	{
		private class CountdownState
		{
			public double UnlockAtPhoton;

			public bool Beep3Played;

			public bool Beep2Played;

			public bool Beep1Played;

			public bool GoPlayed;
		}

		private static readonly Dictionary<int, CountdownState> States = new Dictionary<int, CountdownState>();

		private static double lastPublishedUnlockAt;

		private static readonly FieldInfo FieldHunterLockUntil = AccessTools.Field(typeof(PropHuntManager), "_hunterLockUntil");

		public static void Tick(PropHuntManager manager)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)manager == (Object)null || !PhotonNetwork.InRoom)
				{
					return;
				}
				PublishHostUnlockTime(manager);
				double sharedUnlockPhotonTime = GetSharedUnlockPhotonTime();
				if (sharedUnlockPhotonTime <= 0.0)
				{
					return;
				}
				double num = sharedUnlockPhotonTime - PhotonNetwork.Time;
				if (!(num < -1.5) && !(num > 10.0))
				{
					SyncLocalHunterLock(manager, num);
					int instanceID = ((Object)manager).GetInstanceID();
					if (!States.TryGetValue(instanceID, out var value))
					{
						value = new CountdownState();
						States[instanceID] = value;
					}
					if (Math.Abs(value.UnlockAtPhoton - sharedUnlockPhotonTime) > 0.05)
					{
						value.UnlockAtPhoton = sharedUnlockPhotonTime;
						value.Beep3Played = num < 2.8;
						value.Beep2Played = num < 1.8;
						value.Beep1Played = num < 0.8;
						value.GoPlayed = num < -0.1;
					}
					if (!value.Beep3Played && num <= 3.0 && num > 2.0)
					{
						value.Beep3Played = true;
						PropHuntCountdownBeepUtil.PlayShortBeep();
					}
					if (!value.Beep2Played && num <= 2.0 && num > 1.0)
					{
						value.Beep2Played = true;
						PropHuntCountdownBeepUtil.PlayShortBeep();
					}
					if (!value.Beep1Played && num <= 1.0 && num > 0.0)
					{
						value.Beep1Played = true;
						PropHuntCountdownBeepUtil.PlayShortBeep();
					}
					if (!value.GoPlayed && num <= 0.0)
					{
						value.GoPlayed = true;
						PropHuntCountdownBeepUtil.PlayLongBeep();
						SyncLocalHunterLock(manager, 0.0);
					}
				}
			}
			catch
			{
			}
		}

		public static double GetSharedRemainingSeconds()
		{
			try
			{
				if (!PhotonNetwork.InRoom)
				{
					return double.NaN;
				}
				double sharedUnlockPhotonTime = GetSharedUnlockPhotonTime();
				if (sharedUnlockPhotonTime <= 0.0)
				{
					return double.NaN;
				}
				return sharedUnlockPhotonTime - PhotonNetwork.Time;
			}
			catch
			{
				return double.NaN;
			}
		}

		public static void PublishHostUnlockTimeForNewRound(FixConfigSnapshot snapshot)
		{
			try
			{
				if (PhotonNetwork.IsMasterClient && PhotonNetwork.CurrentRoom != null && snapshot != null)
				{
					float num = Mathf.Max(0f, snapshot.HunterLockSeconds);
					if (!(num <= 0f))
					{
						double photonUnlockAt = PhotonNetwork.Time + (double)num;
						WriteSharedUnlockTime(photonUnlockAt, num, "new-round");
					}
				}
			}
			catch
			{
			}
		}

		private static void PublishHostUnlockTime(PropHuntManager manager)
		{
			try
			{
				if (!PhotonNetwork.IsMasterClient || PhotonNetwork.CurrentRoom == null || (Object)(object)manager == (Object)null)
				{
					return;
				}
				double sharedUnlockPhotonTime = GetSharedUnlockPhotonTime();
				if (!(sharedUnlockPhotonTime > PhotonNetwork.Time - 0.25) || !(sharedUnlockPhotonTime < PhotonNetwork.Time + 120.0))
				{
					float hunterUnlockTimeLocal = GetHunterUnlockTimeLocal(manager);
					float num = 0f;
					if (hunterUnlockTimeLocal > Time.time)
					{
						num = hunterUnlockTimeLocal - Time.time;
					}
					else if (manager.PreHidePhaseActive && !manager.RoundIsLive)
					{
						num = Mathf.Clamp(Mathf.Max(0f, manager.HunterLockSeconds), 0f, Mathf.Max(0.1f, manager.PreHideSeconds));
					}
					if (!(num <= 0f) && !(num > 120f))
					{
						double photonUnlockAt = PhotonNetwork.Time + (double)num;
						WriteSharedUnlockTime(photonUnlockAt, num, "fallback");
					}
				}
			}
			catch
			{
			}
		}

		private static void WriteSharedUnlockTime(double photonUnlockAt,