Decompiled source of NightVote v1.1.0

BepInEx/plugins/NightVote/NightVote.dll

Decompiled 5 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("NightVote")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("NightVote")]
[assembly: AssemblyTitle("NightVote")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace NightVote
{
	[BepInPlugin("fr.nightvote", "NightVote", "1.0.0")]
	public class NightVotePlugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(Game), "Start")]
		private static class GameStartPatch
		{
			private static void Postfix()
			{
				ZRoutedRpc.instance.Register<string>("NightVote_Cmd", (Action<long, string>)OnCommand);
				ZRoutedRpc.instance.Register<string>("NightVote_Msg", (Action<long, string>)OnMessage);
				ZRoutedRpc.instance.Register<string>("NightVote_Center", (Action<long, string>)OnCenter);
			}
		}

		[HarmonyPatch(typeof(Chat), "InputText")]
		private static class ChatPatch
		{
			private static bool Prefix(Chat __instance)
			{
				string text = ((TMP_InputField)((Terminal)__instance).m_input).text.Trim().ToLowerInvariant();
				if (text != "/vote" && !text.StartsWith("/vote "))
				{
					return true;
				}
				string text2 = ((text.Length > 5) ? text.Substring(6).Trim() : "");
				((TMP_InputField)((Terminal)__instance).m_input).text = "";
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "NightVote_Cmd", new object[1] { text2 });
				return false;
			}
		}

		private const string RpcCmd = "NightVote_Cmd";

		private const string RpcMsg = "NightVote_Msg";

		private const string RpcCenter = "NightVote_Center";

		private static ConfigEntry<float> Duration;

		private static ConfigEntry<int> ThresholdPercent;

		private static ConfigEntry<bool> NightOnly;

		private static ConfigEntry<string> IgnoredNames;

		private static bool active;

		private static float endTime;

		private static readonly Dictionary<long, bool> votes = new Dictionary<long, bool>();

		private void Awake()
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			Duration = ((BaseUnityPlugin)this).Config.Bind<float>("General", "VoteDuration", 60f, "Durée du vote en secondes");
			ThresholdPercent = ((BaseUnityPlugin)this).Config.Bind<int>("General", "ThresholdPercent", 50, "Il faut STRICTEMENT plus que ce % de joueurs en 'yes' (50 = majorité)");
			NightOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "NightOnly", true, "Autoriser le vote uniquement la nuit");
			IgnoredNames = ((BaseUnityPlugin)this).Config.Bind<string>("General", "IgnoredNames", "", "Noms de joueurs à ignorer (bots, RCON...), séparés par des virgules. Ils ne comptent pas dans le total et ne peuvent pas voter.");
			new Harmony("fr.nightvote").PatchAll();
		}

		private void Update()
		{
			if (active && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && Time.time >= endTime)
			{
				active = false;
				Broadcast("Vote terminé : temps écoulé, la nuit continue.");
			}
		}

		private static void OnMessage(long sender, string text)
		{
			if ((Object)(object)Chat.instance != (Object)null)
			{
				((Terminal)Chat.instance).AddString("[Vote] " + text);
			}
		}

		private static void OnCenter(long sender, string text)
		{
			if ((Object)(object)MessageHud.instance != (Object)null)
			{
				MessageHud.instance.ShowMessage((MessageType)2, text, 0, (Sprite)null, false, true);
			}
		}

		private static void OnCommand(long sender, string arg)
		{
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				return;
			}
			string name = GetName(sender);
			if (IsIgnored(name))
			{
				return;
			}
			int num = CountPlayers();
			switch (arg)
			{
			case "yes":
			case "y":
			case "oui":
			case "no":
			case "n":
			case "non":
			{
				if (!active)
				{
					Reply(sender, "Aucun vote en cours. Tape /vote pour en lancer un.");
					return;
				}
				bool flag = arg == "yes" || arg == "y" || arg == "oui";
				votes[sender] = flag;
				Broadcast(string.Format("{0} vote {1} ({2} oui / {3} non sur {4})", name, flag ? "OUI" : "NON", Count(v: true), Count(v: false), num));
				Evaluate(num);
				return;
			}
			}
			if (arg != "")
			{
				Reply(sender, "Usage : /vote  |  /vote yes  |  /vote no");
				return;
			}
			if (active)
			{
				Reply(sender, "Un vote est déjà en cours : /vote yes ou /vote no");
				return;
			}
			if (num < 2)
			{
				Reply(sender, "Tu es seul : va simplement dormir dans un lit.");
				return;
			}
			if (NightOnly.Value && (Object)(object)EnvMan.instance != (Object)null && !EnvMan.IsNight())
			{
				Reply(sender, "Ce n'est pas la nuit.");
				return;
			}
			active = true;
			endTime = Time.time + Duration.Value;
			votes.Clear();
			votes[sender] = true;
			BroadcastCenter(name + " propose de passer la nuit. Votez dans le tchat.");
			Broadcast($"{name} propose de passer la nuit. Tapez /vote yes ou /vote no (vous avez {Duration.Value:0}s)");
			Evaluate(num);
		}

		private static void Evaluate(int total)
		{
			int num = Count(v: true);
			int num2 = Count(v: false);
			if (num * 100 > total * ThresholdPercent.Value)
			{
				active = false;
				Broadcast("Vote accepté : on passe la nuit !");
				if ((Object)(object)EnvMan.instance != (Object)null)
				{
					EnvMan.instance.SkipToMorning();
				}
			}
			else if (num2 * 100 >= total * (100 - ThresholdPercent.Value))
			{
				active = false;
				Broadcast("Vote refusé : la nuit continue.");
			}
		}

		private static bool IsIgnored(string name)
		{
			if (string.IsNullOrWhiteSpace(IgnoredNames.Value))
			{
				return false;
			}
			return IgnoredNames.Value.Split(new char[1] { ',' }).Any((string n) => string.Equals(n.Trim(), name, StringComparison.OrdinalIgnoreCase));
		}

		private static int CountPlayers()
		{
			return ZNet.instance.GetPlayerList().Count((PlayerInfo p) => !IsIgnored(p.m_name));
		}

		private static int Count(bool v)
		{
			return votes.Count((KeyValuePair<long, bool> kv) => kv.Value == v);
		}

		private static string GetName(long uid)
		{
			ZNetPeer peer = ZNet.instance.GetPeer(uid);
			if (peer != null)
			{
				return peer.m_playerName;
			}
			if (!((Object)(object)Player.m_localPlayer != (Object)null))
			{
				return "Hôte";
			}
			return Player.m_localPlayer.GetPlayerName();
		}

		private static void Broadcast(string text)
		{
			ZRoutedRpc.instance.InvokeRoutedRPC(0L, "NightVote_Msg", new object[1] { text });
		}

		private static void BroadcastCenter(string text)
		{
			ZRoutedRpc.instance.InvokeRoutedRPC(0L, "NightVote_Center", new object[1] { text });
		}

		private static void Reply(long uid, string text)
		{
			ZRoutedRpc.instance.InvokeRoutedRPC(uid, "NightVote_Msg", new object[1] { text });
		}
	}
}