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.Bootstrap;
using BepInEx.Configuration;
using MonoMod.RuntimeDetour;
using On.RoR2;
using R2API.Utils;
using RiskOfOptions;
using RiskOfOptions.OptionConfigs;
using RiskOfOptions.Options;
using RoR2;
using UnityEngine;
using UnityEngine.Networking;
[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: AssemblyCompany("TPVoting")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+b3964ee0c4d0768a5c295f86fecb5b5e133e4d0e")]
[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";
private static readonly string ReadyMessages = PluginConfig.CustomReadyMessages.Value;
public static void UserIsReady(string player, int votes, int total)
{
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Expected O, but got Unknown
string text = "";
text = (string.IsNullOrEmpty(ReadyMessages) ? string.Format("<color=#{0}>{1}</color> is ready! <color=#{2}>({3}/{4})</color>", "32cd32", player, "7e91af", votes, total) : (ReadyMessages.Replace("{user}", "<color=#32cd32>" + player + "</color>").Replace("{votes}", string.Format("<color=#{0}>({1}</color>", "7e91af", votes)).Replace("{total}", string.Format("<color=#{0}>/{1})</color>", "7e91af", total)) ?? ""));
Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
{
baseToken = text
});
}
public static void TPUnlocked()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: 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_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: 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_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: 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(int unlockTime)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: 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 void DebugMessage(string debug)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Expected O, but got Unknown
string baseToken = "<color=#c0c0c0>[TPVoting] " + debug + "</color>";
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_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Expected O, but got Unknown
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: 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_0064: Expected O, but got Unknown
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: 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_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: 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_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
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_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
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_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: 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)
NetworkUser user = UsersHelper.GetUser(activator);
if (IsTPUnlocked || (Object.op_Implicit((Object)(object)user) && IsLockedTPInteractable(user)))
{
return (Interactability)orig.DynamicInvoke(self, activator);
}
return (Interactability)1;
}
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_0010: Unknown result type (might be due to invalid IL or missing references)
return Object.op_Implicit((Object)(object)user) && votingMachine.CheckIfVoted(user.id);
}
public bool Vote(NetworkUser user)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
return Object.op_Implicit((Object)(object)user) && votingMachine.IsVotingStarted && votingMachine.Vote(user.id);
}
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();
if (PluginConfig.ShowImportantConfigs.Value)
{
ChatHelper.DebugMessage("Important Configs for TP Voting:\nReady message options: " + PluginConfig.PlayerIsReadyMessages.Value + "\n" + $"Majority Votes Percentage: {PluginConfig.PercentageOfTotal.Value}%\n" + $"User Auto Vote On Death: {PluginConfig.UserAutoVoteOnDeath.Value}\n" + $"Vote after TP: {PluginConfig.VoteAfterTPEvent.Value}" + $"Display Important Configs (this message): {PluginConfig.ShowImportantConfigs.Value}");
}
}
}
public void EndVoting()
{
if (votingMachine.IsVotingStarted)
{
votingMachine.EndVoting();
}
}
public void Awake()
{
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Expected O, but got Unknown
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Expected O, but got Unknown
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Expected O, but got Unknown
votingMachine.CheckVotingEndCondition = delegate(VotingMachine<NetworkUserId> votingMachine)
{
int unlockTime;
if (votingMachine.CheckIfRequiredVoted() && !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_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Expected O, but got Unknown
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: 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
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_0052: 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_0025: 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_006f: 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_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: 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);
TeleporterInteraction.onTeleporterChargedGlobal += OnTeleporterChargedGlobal;
}
public void OnDestroy()
{
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: 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);
TeleporterInteraction.onTeleporterChargedGlobal -= OnTeleporterChargedGlobal;
}
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 OnTeleporterChargedGlobal(TeleporterInteraction teleporterInteraction)
{
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 CheckIfRequiredVoted()
{
int num = Mathf.CeilToInt(PluginConfig.PercentageOfTotal.Value / 100f);
int num2 = Mathf.CeilToInt((float)(votes.Count((KeyValuePair<VoterID, bool> kv) => kv.Value) / votes.Count));
if (num2 >= num)
{
return true;
}
Debug.Log((object)$"VotingMachine::CheckIfRequiredVoted: Not enough votes. Required: {num}, Current: {num2}");
return false;
}
}
internal class PluginConfig
{
public static ConfigEntry<string> PlayerIsReadyMessages;
public static ConfigEntry<string> IgnoredGameModes;
public static ConfigEntry<string> CustomReadyMessages;
public static ConfigEntry<int> MajorityVotesCountdownTime;
public static ConfigEntry<float> PercentageOfTotal;
public static ConfigEntry<bool> UserAutoVoteOnDeath;
public static ConfigEntry<bool> VoteAfterTPEvent;
public static ConfigEntry<bool> ShowImportantConfigs;
}
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.Ehseezed.TPVotingExpanded", "TPVotingExpanded", "0.1.0")]
public class TPVotingPlugin : BaseUnityPlugin
{
public const string ModVer = "0.1.0";
public const string ModName = "TPVotingExpanded";
public const string ModGuid = "com.Ehseezed.TPVotingExpanded";
public TPVotingSystem TPVotingSystem { get; private set; }
public TPVotingPlugin()
{
InitConfig();
}
public void Awake()
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: 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_0014: 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. Values must be separated by comma. Possible values: 'InfiniteTowerRun', 'EclipseRun', 'ClassicRun', 'WeeklyRun'");
PluginConfig.CustomReadyMessages = ((BaseUnityPlugin)this).Config.Bind<string>("Settings", "CustomReadyMessages", "{user} thinks your taking too long! ({votes}/{total})", "The message that appears in chat upon readying. Leave blank for default message. Use {user} for player name, {votes} for number of votes and {total} for total number of players.");
PluginConfig.MajorityVotesCountdownTime = ((BaseUnityPlugin)this).Config.Bind<int>("Settings", "MajorityVotesCountdownTime", 30, "Countdown in seconds to unlock the teleporter when 'majority' of the players are ready.");
PluginConfig.PercentageOfTotal = ((BaseUnityPlugin)this).Config.Bind<float>("Settings", "PercentageOfTotal", 100f, "Percentage of total players that need to be ready to start the countdown. Value must be between 0 and 1.");
PluginConfig.UserAutoVoteOnDeath = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "UserAutoVoteOnDeath", false, "Should players auto vote tp when they die.");
PluginConfig.VoteAfterTPEvent = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "VoteAfterTPEvent", true, "Should tp voting also be activated after tp event.");
PluginConfig.ShowImportantConfigs = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "ShowImportantConfigs", false, "Shows relevant configs whenever voting instructions are shown.");
if (Chainloader.PluginInfos.ContainsKey("com.Ehseezed.TPVotingExpanded"))
{
AddConfigOptions();
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
private static void AddConfigOptions()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Expected O, but got Unknown
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Expected O, but got Unknown
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected O, but got Unknown
//IL_0036: 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)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Expected O, but got Unknown
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Expected O, but got Unknown
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Expected O, but got Unknown
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: 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
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Expected O, but got Unknown
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Expected O, but got Unknown
ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.PlayerIsReadyMessages));
ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.IgnoredGameModes));
ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.CustomReadyMessages));
ModSettingsManager.AddOption((BaseOption)new IntSliderOption(PluginConfig.MajorityVotesCountdownTime, new IntSliderConfig
{
min = 0,
max = 100
}));
ModSettingsManager.AddOption((BaseOption)new SliderOption(PluginConfig.PercentageOfTotal, new SliderConfig
{
min = 0f,
max = 100f
}));
ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.UserAutoVoteOnDeath));
ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.VoteAfterTPEvent));
ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.ShowImportantConfigs));
}
}