Decompiled source of TPVoting v1.3.0

TPVoting.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using EntityStates;
using MonoMod.RuntimeDetour;
using On.RoR2;
using R2API.Utils;
using RoR2;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("TPVoting")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+f7c41176495831919350cccc9304a33085d7e283")]
[assembly: AssemblyProduct("TPVoting")]
[assembly: AssemblyTitle("TPVoting")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace TPVoting;

public static class ChatHelper
{
	private const string GrayColor = "7e91af";

	private const string RedColor = "ff0000";

	private const string YellowColor = "ffff00";

	private const string GreenColor = "32cd32";

	private const string SilverColor = "c0c0c0";

	public static void UserIsReady(string userName, int numberOfUsersWhoVoted, int numberOfVotingUsers)
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Expected O, but got Unknown
		string baseToken = string.Format("<color=#{0}>{1}</color> is ready! <color=#{2}>({3}/{4})</color>", "32cd32", userName, "7e91af", numberOfUsersWhoVoted, numberOfVotingUsers);
		Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
		{
			baseToken = baseToken
		});
	}

	public static void TPUnlocked()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		string baseToken = "<color=#ff0000>Teleporter</color> is unlocked! <color=#32cd32>Players are free to start it.</color>";
		Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
		{
			baseToken = baseToken
		});
	}

	public static void PlayersNotReady()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		string baseToken = "<color=#ff0000>Players are not ready.</color> Vote by writting <color=#c0c0c0>\"r\"</color> in chat.";
		Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
		{
			baseToken = baseToken
		});
	}

	public static void VotingInstruction()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		string baseToken = "Vote <color=#ff0000>Teleporter</color> by writting <color=#c0c0c0>\"r\"</color> in chat.";
		Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
		{
			baseToken = baseToken
		});
	}

	public static void TPCountdown(uint unlockTime)
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Expected O, but got Unknown
		string baseToken = string.Format("Starting <color=#{0}>Teleporter</color> unlock <color=#{1}>countdown!</color> <color=#{2}>({3} seconds left)</color>", "ff0000", "ffff00", "7e91af", unlockTime);
		Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
		{
			baseToken = baseToken
		});
	}
}
public static class UsersHelper
{
	public static NetworkUser GetUser(Interactor activator)
	{
		CharacterBody body = ((Component)activator).GetComponent<CharacterBody>();
		return ((IEnumerable<NetworkUser>)NetworkUser.readOnlyInstancesList).FirstOrDefault((Func<NetworkUser, bool>)((NetworkUser u) => (Object)(object)u.master.GetBody() == (Object)(object)body));
	}

	public static NetworkUser GetUser(CharacterMaster player)
	{
		return ((IEnumerable<NetworkUser>)NetworkUser.readOnlyInstancesList).FirstOrDefault((Func<NetworkUser, bool>)((NetworkUser u) => (Object)(object)u.master == (Object)(object)player));
	}

	public static bool IsOneUserOnly()
	{
		return NetworkUser.readOnlyInstancesList.Count <= 1;
	}
}
public class TPLocker : NetworkBehaviour
{
	public delegate bool LockedTPInteractibility(NetworkUser user);

	public delegate void LockedTPInteractionAttempt(NetworkUser interactingUser);

	public delegate Interactability orig_GetInteractability(GenericInteraction self, Interactor activator);

	public delegate void orig_OnInteractionBegin(GenericInteraction self, Interactor activator);

	public bool IsTPUnlocked = true;

	public Hook hook_GetInteractability;

	public Hook hook_OnInteractionBegin;

	public LockedTPInteractibility IsLockedTPInteractable { get; set; } = (NetworkUser user) => true;


	public event LockedTPInteractionAttempt OnLockedTPInteractionAttempt;

	public void Awake()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Expected O, but got Unknown
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Expected O, but got Unknown
		TeleporterInteraction.GetInteractability += new hook_GetInteractability(TeleporterInteraction_GetInteractability);
		TeleporterInteraction.OnInteractionBegin += new hook_OnInteractionBegin(TeleporterInteraction_OnInteractionBegin);
		hook_GetInteractability = new Hook((MethodBase)typeof(GenericInteraction).GetMethod("RoR2.IInteractable.GetInteractability", BindingFlags.Instance | BindingFlags.NonPublic), typeof(TPLocker).GetMethod("GenericInteraction_GetInteractability"), (object)this, default(HookConfig));
		hook_OnInteractionBegin = new Hook((MethodBase)typeof(GenericInteraction).GetMethod("RoR2.IInteractable.OnInteractionBegin", BindingFlags.Instance | BindingFlags.NonPublic), typeof(TPLocker).GetMethod("GenericInteraction_OnInteractionBegin"), (object)this, default(HookConfig));
	}

	public void OnDestroy()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		TeleporterInteraction.GetInteractability -= new hook_GetInteractability(TeleporterInteraction_GetInteractability);
		TeleporterInteraction.OnInteractionBegin -= new hook_OnInteractionBegin(TeleporterInteraction_OnInteractionBegin);
		hook_GetInteractability.Dispose();
		hook_OnInteractionBegin.Dispose();
	}

	private Interactability TeleporterInteraction_GetInteractability(orig_GetInteractability orig, TeleporterInteraction self, Interactor activator)
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		return GetInteractability<orig_GetInteractability, TeleporterInteraction>(orig, self, activator);
	}

	private void TeleporterInteraction_OnInteractionBegin(orig_OnInteractionBegin orig, TeleporterInteraction self, Interactor activator)
	{
		OnInteractionBegin<orig_OnInteractionBegin, TeleporterInteraction>(orig, self, activator);
	}

	public Interactability GenericInteraction_GetInteractability(orig_GetInteractability orig, GenericInteraction self, Interactor activator)
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)self).name.ToLower().Contains("portal"))
		{
			orig(self, activator);
		}
		return GetInteractability<orig_GetInteractability, GenericInteraction>(orig, self, activator);
	}

	public void GenericInteraction_OnInteractionBegin(orig_OnInteractionBegin orig, GenericInteraction self, Interactor activator)
	{
		if (!((Object)self).name.ToLower().Contains("portal"))
		{
			orig(self, activator);
		}
		OnInteractionBegin<orig_OnInteractionBegin, GenericInteraction>(orig, self, activator);
	}

	private Interactability GetInteractability<ORIG, SELF>(ORIG orig, SELF self, Interactor activator) where ORIG : Delegate
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		NetworkUser user = UsersHelper.GetUser(activator);
		if (!IsTPUnlocked && (!Object.op_Implicit((Object)(object)user) || !IsLockedTPInteractable(user)))
		{
			return (Interactability)1;
		}
		return (Interactability)orig.DynamicInvoke(self, activator);
	}

	private void OnInteractionBegin<ORIG, SELF>(ORIG orig, SELF self, Interactor activator) where ORIG : Delegate
	{
		if (IsTPUnlocked)
		{
			orig.DynamicInvoke(self, activator);
			return;
		}
		NetworkUser user = UsersHelper.GetUser(activator);
		if (Object.op_Implicit((Object)(object)user))
		{
			this.OnLockedTPInteractionAttempt?.Invoke(user);
		}
	}
}
public class TPVotingController : NetworkBehaviour
{
	public delegate void TPVotingStarted();

	public delegate void TPVotingEnded();

	private VotingMachine<NetworkUserId> votingMachine = new VotingMachine<NetworkUserId>();

	private IEnumerator majorityTPVotingTimer;

	private bool isMajorityTPVotingTimerRunning;

	public event TPVotingStarted OnTPVotingStarted;

	public event TPVotingEnded OnTPVotingEnded;

	public bool IsVotingStarted()
	{
		return votingMachine.IsVotingStarted;
	}

	public bool HasUserVoted(NetworkUser user)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)user))
		{
			return votingMachine.CheckIfVoted(user.id);
		}
		return false;
	}

	public bool Vote(NetworkUser user)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)user) && votingMachine.IsVotingStarted)
		{
			return votingMachine.Vote(user.id);
		}
		return false;
	}

	public void StartVoting(bool showInstruction = true)
	{
		if (!votingMachine.IsVotingStarted)
		{
			votingMachine.StartVoting(NetworkUser.readOnlyInstancesList.Select((NetworkUser l) => l.id).ToList());
			if (showInstruction)
			{
				((MonoBehaviour)this).StartCoroutine(ShowVotingInstruction());
			}
		}
		static IEnumerator ShowVotingInstruction()
		{
			yield return (object)new WaitForSeconds(3f);
			ChatHelper.VotingInstruction();
		}
	}

	public void EndVoting()
	{
		if (votingMachine.IsVotingStarted)
		{
			votingMachine.EndVoting();
		}
	}

	public void Awake()
	{
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Expected O, but got Unknown
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Expected O, but got Unknown
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Expected O, but got Unknown
		votingMachine.CheckVotingEndCondition = delegate(VotingMachine<NetworkUserId> votingMachine)
		{
			uint unlockTime;
			if (votingMachine.CheckIfHalfOrMoreVoted() && !isMajorityTPVotingTimerRunning)
			{
				unlockTime = PluginConfig.MajorityVotesCountdownTime.Value;
				ChatHelper.TPCountdown(unlockTime);
				((MonoBehaviour)this).StartCoroutine(majorityTPVotingTimer = WaitAndEndVoting());
			}
			return votingMachine.CheckIfAllVoted() || votingMachine.CheckIfThereIsOnlyOneVoter();
			IEnumerator WaitAndEndVoting()
			{
				isMajorityTPVotingTimerRunning = true;
				yield return (object)new WaitForSeconds((float)unlockTime);
				votingMachine.EndVoting();
				isMajorityTPVotingTimerRunning = false;
			}
		};
		votingMachine.OnVotingStarted += VotingMachine_OnVotingStarted;
		votingMachine.OnVotingEnded += VotingMachine_OnVotingEnded;
		votingMachine.OnVoterVoted += VotingMachine_OnVoterVoted;
		CharacterMaster.OnBodyDeath += new hook_OnBodyDeath(CharacterMaster_OnBodyDeath);
		NetworkUser.OnDestroy += new hook_OnDestroy(NetworkUser_OnDestroy);
		Chat.SendBroadcastChat_ChatMessageBase += new hook_SendBroadcastChat_ChatMessageBase(Chat_SendBroadcastChat_ChatMessageBase);
	}

	public void OnDestroy()
	{
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Expected O, but got Unknown
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Expected O, but got Unknown
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Expected O, but got Unknown
		votingMachine.OnVotingStarted -= VotingMachine_OnVotingStarted;
		votingMachine.OnVotingEnded -= VotingMachine_OnVotingEnded;
		votingMachine.OnVoterVoted -= VotingMachine_OnVoterVoted;
		CharacterMaster.OnBodyDeath -= new hook_OnBodyDeath(CharacterMaster_OnBodyDeath);
		NetworkUser.OnDestroy -= new hook_OnDestroy(NetworkUser_OnDestroy);
		Chat.SendBroadcastChat_ChatMessageBase -= new hook_SendBroadcastChat_ChatMessageBase(Chat_SendBroadcastChat_ChatMessageBase);
	}

	private void VotingMachine_OnVotingStarted()
	{
		this.OnTPVotingStarted?.Invoke();
	}

	private void VotingMachine_OnVotingEnded()
	{
		((MonoBehaviour)this).StopCoroutine(majorityTPVotingTimer);
		isMajorityTPVotingTimerRunning = false;
		this.OnTPVotingEnded?.Invoke();
	}

	private void VotingMachine_OnVoterVoted(NetworkUserId voterID)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		NetworkUser val = ((IEnumerable<NetworkUser>)NetworkUser.readOnlyInstancesList).FirstOrDefault((Func<NetworkUser, bool>)delegate(NetworkUser l)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			NetworkUserId id = l.id;
			return ((NetworkUserId)(ref id)).Equals(voterID);
		});
		if (Object.op_Implicit((Object)(object)val))
		{
			IReadOnlyDictionary<NetworkUserId, bool> votes = votingMachine.Votes;
			ChatHelper.UserIsReady(val.userName, votes.Count((KeyValuePair<NetworkUserId, bool> ks) => ks.Value), votes.Count);
		}
	}

	private void CharacterMaster_OnBodyDeath(orig_OnBodyDeath orig, CharacterMaster self, CharacterBody body)
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		orig.Invoke(self, body);
		if (votingMachine.IsVotingStarted && PluginConfig.UserAutoVoteOnDeath.Value && self.IsDeadAndOutOfLivesServer())
		{
			NetworkUser user = UsersHelper.GetUser(self);
			if (Object.op_Implicit((Object)(object)user))
			{
				votingMachine.Vote(user.id);
			}
		}
	}

	private void NetworkUser_OnDestroy(orig_OnDestroy orig, NetworkUser self)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		orig.Invoke(self);
		if (votingMachine.IsVotingStarted)
		{
			votingMachine.RemoveVoter(self.id);
		}
	}

	private void Chat_SendBroadcastChat_ChatMessageBase(orig_SendBroadcastChat_ChatMessageBase orig, ChatMessageBase message)
	{
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		if (!votingMachine.IsVotingStarted)
		{
			orig.Invoke(message);
			return;
		}
		UserChatMessage val = (UserChatMessage)(object)((message is UserChatMessage) ? message : null);
		if (val != null)
		{
			NetworkUser component = val.sender.GetComponent<NetworkUser>();
			if (Object.op_Implicit((Object)(object)component))
			{
				string message2 = val.text.ToLower().Trim();
				if (CheckIfReadyMessage(message2) && votingMachine.Vote(component.id))
				{
					return;
				}
			}
		}
		orig.Invoke(message);
	}

	private bool CheckIfReadyMessage(string message)
	{
		return PluginConfig.PlayerIsReadyMessages.Value.Split(',').Contains(message);
	}
}
public class TPVotingSystem : NetworkBehaviour
{
	private TPLocker tpLocker;

	public TPVotingController TPVotingController { get; private set; }

	public bool IsTPUnlocked()
	{
		return tpLocker.IsTPUnlocked;
	}

	public void Awake()
	{
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Expected O, but got Unknown
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Expected O, but got Unknown
		TPVotingController = ((Component)this).gameObject.AddComponent<TPVotingController>();
		TPVotingController.OnTPVotingStarted += TPVotingController_OnTPVotingStarted;
		TPVotingController.OnTPVotingEnded += TPVotingController_OnTPVotingEnded;
		tpLocker = ((Component)this).gameObject.AddComponent<TPLocker>();
		tpLocker.IsLockedTPInteractable = (NetworkUser user) => !TPVotingController.HasUserVoted(user);
		tpLocker.OnLockedTPInteractionAttempt += TpLocker_OnLockedTPInteractionAttempt;
		Run.OnServerSceneChanged += new hook_OnServerSceneChanged(Run_OnServerSceneChanged);
		ChargedState.OnEnter += new hook_OnEnter(TeleporterInteraction_ChargedState_OnEnter);
	}

	public void OnDestroy()
	{
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: 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
		TPVotingController.OnTPVotingStarted -= TPVotingController_OnTPVotingStarted;
		TPVotingController.OnTPVotingEnded -= TPVotingController_OnTPVotingEnded;
		Object.Destroy((Object)(object)TPVotingController);
		tpLocker.OnLockedTPInteractionAttempt -= TpLocker_OnLockedTPInteractionAttempt;
		Object.Destroy((Object)(object)tpLocker);
		Run.OnServerSceneChanged -= new hook_OnServerSceneChanged(Run_OnServerSceneChanged);
		ChargedState.OnEnter -= new hook_OnEnter(TeleporterInteraction_ChargedState_OnEnter);
	}

	private void TPVotingController_OnTPVotingStarted()
	{
		tpLocker.IsTPUnlocked = false;
	}

	private void TPVotingController_OnTPVotingEnded()
	{
		tpLocker.IsTPUnlocked = true;
		ChatHelper.TPUnlocked();
	}

	private void TpLocker_OnLockedTPInteractionAttempt(NetworkUser interactingUser)
	{
		if (!TPVotingController.Vote(interactingUser))
		{
			ChatHelper.PlayersNotReady();
		}
	}

	private void Run_OnServerSceneChanged(orig_OnServerSceneChanged orig, Run self, string sceneName)
	{
		orig.Invoke(self, sceneName);
		TryStartVoting(showInstruction: true);
	}

	private void TeleporterInteraction_ChargedState_OnEnter(orig_OnEnter orig, BaseState self)
	{
		orig.Invoke(self);
		if (PluginConfig.VoteAfterTPEvent.Value)
		{
			TryStartVoting(showInstruction: false);
		}
	}

	private void TryStartVoting(bool showInstruction)
	{
		tpLocker.IsTPUnlocked = true;
		TPVotingController.EndVoting();
		if (!UsersHelper.IsOneUserOnly() && CheckIfCurrentStageQualifyForTPVoting())
		{
			TPVotingController.StartVoting(showInstruction);
		}
	}

	private bool CheckIfCurrentStageQualifyForTPVoting()
	{
		return !PluginGlobals.IgnoredStages.Contains(SceneCatalog.GetSceneDefForCurrentScene().baseSceneName);
	}
}
public class VotingMachine<VoterID>
{
	public delegate bool VotingEndCondition(VotingMachine<VoterID> votingMachine);

	public delegate void VotingUpdated();

	public delegate void VotingStarted();

	public delegate void VotingEnded();

	public delegate void VoterVoted(VoterID voterID);

	public delegate void VoterRemoved(VoterID voterID);

	private Dictionary<VoterID, bool> votes = new Dictionary<VoterID, bool>();

	public IReadOnlyDictionary<VoterID, bool> Votes => new ReadOnlyDictionary<VoterID, bool>(votes);

	public bool IsVotingStarted { get; private set; }

	public VotingEndCondition CheckVotingEndCondition { get; set; } = (VotingMachine<VoterID> votingMachine) => votingMachine.CheckIfAllVoted();


	public event VotingUpdated OnVotingUpdated;

	public event VotingStarted OnVotingStarted;

	public event VotingEnded OnVotingEnded;

	public event VoterVoted OnVoterVoted;

	public event VoterRemoved OnVoterRemoved;

	public void StartVoting(IReadOnlyCollection<VoterID> voterIDs)
	{
		votes.Clear();
		foreach (VoterID voterID in voterIDs)
		{
			votes[voterID] = false;
		}
		IsVotingStarted = true;
		this.OnVotingStarted?.Invoke();
		PostVotingUpdate();
	}

	public void EndVoting()
	{
		if (!IsVotingStarted)
		{
			Debug.LogWarning((object)"VotingMachine::EndVoting: Trying to end voting while there is no voting started");
			return;
		}
		votes.Clear();
		IsVotingStarted = false;
		this.OnVotingEnded?.Invoke();
		PostVotingUpdate();
	}

	public bool Vote(VoterID voterID)
	{
		if (!IsVotingStarted)
		{
			Debug.LogWarning((object)"VotingMachine::Vote: Trying to set vote while voting is not started");
			return false;
		}
		if (votes.ContainsKey(voterID) && !votes[voterID])
		{
			votes[voterID] = true;
			this.OnVoterVoted?.Invoke(voterID);
			PostVotingUpdate();
			return true;
		}
		Debug.LogWarning((object)$"VotingMachine::Vote: Failed to find voter ID {voterID} in voter list");
		return false;
	}

	public bool RemoveVoter(VoterID voterID)
	{
		if (!IsVotingStarted)
		{
			return false;
		}
		if (votes.ContainsKey(voterID))
		{
			votes.Remove(voterID);
			this.OnVoterRemoved?.Invoke(voterID);
			PostVotingUpdate();
			return true;
		}
		return false;
	}

	private void PostVotingUpdate()
	{
		this.OnVotingUpdated?.Invoke();
		if (IsVotingStarted && CheckVotingEndCondition(this))
		{
			EndVoting();
		}
	}

	public bool CheckIfVoted(VoterID voterID)
	{
		bool value;
		return votes.TryGetValue(voterID, out value) && value;
	}

	public bool CheckIfAllVoted()
	{
		return votes.All((KeyValuePair<VoterID, bool> kv) => kv.Value);
	}

	public bool CheckIfThereIsOnlyOneVoter()
	{
		return votes.Count == 1;
	}

	public bool CheckIfHalfOrMoreVoted()
	{
		return votes.Count((KeyValuePair<VoterID, bool> kv) => kv.Value) >= Mathf.CeilToInt((float)votes.Count / 2f);
	}
}
internal class PluginConfig
{
	public static ConfigEntry<string> PlayerIsReadyMessages;

	public static ConfigEntry<string> IgnoredGameModes;

	public static ConfigEntry<uint> MajorityVotesCountdownTime;

	public static ConfigEntry<bool> UserAutoVoteOnDeath;

	public static ConfigEntry<bool> VoteAfterTPEvent;
}
public static class PluginGlobals
{
	public static List<string> IgnoredStages = new List<string> { "arena", "moon", "moon2", "limbo", "outro", "voidraid" };
}
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
[BepInPlugin("com.Mordrog.TPVoting", "TPVoting", "1.2.3")]
public class TPVotingPlugin : BaseUnityPlugin
{
	public const string ModVer = "1.2.3";

	public const string ModName = "TPVoting";

	public const string ModGuid = "com.Mordrog.TPVoting";

	public TPVotingSystem TPVotingSystem { get; private set; }

	public TPVotingPlugin()
	{
		InitConfig();
	}

	public void Awake()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		Run.Awake += new hook_Awake(Run_Awake);
		Run.OnDestroy += new hook_OnDestroy(Run_OnDestroy);
	}

	private void Run_Awake(orig_Awake orig, Run self)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		orig.Invoke(self);
		if (!PluginConfig.IgnoredGameModes.Value.Contains(GameModeCatalog.GetGameModeName(self.gameModeIndex)))
		{
			TPVotingSystem = ((Component)this).gameObject.AddComponent<TPVotingSystem>();
		}
	}

	private void Run_OnDestroy(orig_OnDestroy orig, Run self)
	{
		orig.Invoke(self);
		if (Object.op_Implicit((Object)(object)TPVotingSystem))
		{
			Object.Destroy((Object)(object)TPVotingSystem);
		}
	}

	private void InitConfig()
	{
		PluginConfig.PlayerIsReadyMessages = ((BaseUnityPlugin)this).Config.Bind<string>("Settings", "PlayerIsReadyMessages", "r,rdy,ready", "The message the player has to write in the chat to confirm they are ready. Values must be separated by comma.");
		PluginConfig.IgnoredGameModes = ((BaseUnityPlugin)this).Config.Bind<string>("Settings", "IgnoredGameModes", "InfiniteTowerRun", "Gamemode in which tp voting should not work.");
		PluginConfig.MajorityVotesCountdownTime = ((BaseUnityPlugin)this).Config.Bind<uint>("Settings", "MajorityVotesCountdownTime", 30u, "Countdown in seconds to unlock the teleporter when half or most of the players are ready.");
		PluginConfig.UserAutoVoteOnDeath = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "UserAutoVoteOnDeath", true, "Should players auto vote tp when they die.");
		PluginConfig.VoteAfterTPEvent = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "VoteAfterTPEvent", false, "Should tp voting also be activated after tp event.");
	}
}