Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of TPVoting v1.4.0
TPVoting.dll
Decompiled 4 months agousing 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 System.Security.Permissions; using BepInEx; using BepInEx.Configuration; 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+3063853c475e386ae336ba18ed364e3e4ea7ed33")] [assembly: AssemblyProduct("TPVoting")] [assembly: AssemblyTitle("TPVoting")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [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(); [CompilerGenerated] private sealed class <<StartVoting>g__ShowVotingInstruction|14_1>d : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <<StartVoting>g__ShowVotingInstruction|14_1>d(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(3f); <>1__state = 1; return true; case 1: <>1__state = -1; ChatHelper.VotingInstruction(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <>c__DisplayClass16_0 { public VotingMachine<NetworkUserId> votingMachine; public uint unlockTime; public TPVotingController <>4__this; } 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()); } } [IteratorStateMachine(typeof(<<StartVoting>g__ShowVotingInstruction|14_1>d))] static IEnumerator ShowVotingInstruction() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <<StartVoting>g__ShowVotingInstruction|14_1>d(0); } } 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) { <>c__DisplayClass16_0 CS$<>8__locals0 = new <>c__DisplayClass16_0(); CS$<>8__locals0.<>4__this = this; CS$<>8__locals0.votingMachine = votingMachine; if (CS$<>8__locals0.votingMachine.CheckIfHalfOrMoreVoted() && !isMajorityTPVotingTimerRunning) { CS$<>8__locals0.unlockTime = PluginConfig.MajorityVotesCountdownTime.Value; ChatHelper.TPCountdown(CS$<>8__locals0.unlockTime); ((MonoBehaviour)this).StartCoroutine(majorityTPVotingTimer = WaitAndEndVoting()); } return CS$<>8__locals0.votingMachine.CheckIfAllVoted() || CS$<>8__locals0.votingMachine.CheckIfThereIsOnlyOneVoter(); [IteratorStateMachine(typeof(<>c__DisplayClass16_0.<<Awake>g__WaitAndEndVoting|1>d))] IEnumerator WaitAndEndVoting() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <>c__DisplayClass16_0.<<Awake>g__WaitAndEndVoting|1>d(0) { <>4__this = CS$<>8__locals0 }; } }; 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() { if (majorityTPVotingTimer != null) { ((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, ChargedState 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.4.0")] public class TPVotingPlugin : BaseUnityPlugin { public const string ModVer = "1.4.0"; 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."); } }