Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 78 additions & 93 deletions Essentials/Commands/VotingModule.cs
Original file line number Diff line number Diff line change
@@ -1,27 +1,41 @@
using System;
using System.Text;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using NLog;
using Sandbox.Game.World;
using Sandbox.Engine.Multiplayer;
using Torch.API.Managers;
using Torch.Commands;
using Torch.Commands.Permissions;
using Torch.Mod;
using Torch.Mod.Messages;
using VRage.Game.ModAPI;


namespace Essentials.Commands
{
public class VotingModule : CommandModule
{
private static Random rnd = new Random();
private static int _cooldown = rnd.Next(5, 30);
public enum Status
{
voteStandby,
voteInProgress,
voteCancel,

// Last vote
voteFail,
voteSuccess
}

private static readonly Logger Log = LogManager.GetLogger("Essentials Voting");
private static readonly Random rnd = new Random();
private static AutoCommand _command;
private static readonly int _cooldown = rnd.Next(5, 30);
private static string voteInProgress;
private static Dictionary<ulong, DateTime> _voteReg = new Dictionary<ulong, DateTime>();
private static Dictionary<ulong, DateTime> _voteCooldown = new Dictionary<ulong, DateTime>();
private static readonly Dictionary<ulong, DateTime> _voteReg = new Dictionary<ulong, DateTime>();
private static readonly Dictionary<ulong, DateTime> _voteCooldown = new Dictionary<ulong, DateTime>();
public static Status VoteStatus = Status.voteStandby;

//last vote info for debugging
Expand All @@ -38,70 +52,66 @@ public void Vote(string name)

if (VoteStatus == Status.voteInProgress)
{
Context.Respond($"vote for {voteInProgress} is currently active. Use [!yes] to vote and [!no] to retract vote");
Context.Respond(
$"vote for {voteInProgress} is currently active. Use !yes to vote and !no to retract vote");
return;
}

var command = EssentialsPlugin.Instance.Config.AutoCommands.FirstOrDefault(c => c.Name.Equals(name));
_command = EssentialsPlugin.Instance.Config.AutoCommands.FirstOrDefault(c => c.Name.Equals(name));

if (command == null || command.CommandTrigger != Trigger.Vote)
if (_command == null || _command.CommandTrigger != Trigger.Vote)
{
Context.Respond($"Couldn't find any votable command with the name [{name}]");
Context.Respond($"Couldn't find any votable command with the name {name}");
_command = null;
return;
}


// Rexxar's spam blocker. Timing is random as fuck and unique to each player.
var steamid = Context.Player.SteamUserId;
if (_voteCooldown.TryGetValue(steamid, out DateTime activeCooldown))
if (_voteCooldown.TryGetValue(steamid, out var activeCooldown))
{
TimeSpan difference = activeCooldown - DateTime.Now;
var difference = activeCooldown - DateTime.Now;
if (difference.TotalSeconds > 0)
{
Context.Respond($"Cooldown active. You can use this command again in {difference.Minutes:N0} minutes : {difference.Seconds:N0} seconds");
Context.Respond(
$"Cooldown active. You can use this command again in {difference.Minutes:N0} minutes : {difference.Seconds:N0} seconds");
return;
}
else
{
_voteCooldown[steamid] = DateTime.Now.AddMinutes(_cooldown);
}

_voteCooldown[steamid] = DateTime.Now.AddMinutes(_cooldown);
}

else _voteCooldown.Add(steamid, DateTime.Now.AddMinutes(_cooldown));
else
{
_voteCooldown.Add(steamid, DateTime.Now.AddMinutes(_cooldown));
}

TimeSpan _voteDuration = TimeSpan.Parse(command.Interval);
var _voteDuration = TimeSpan.Parse(_command.Interval);
// voting status
voteInProgress = name;
VoteStatus = Status.voteInProgress;
VoteYes();
var sb = new StringBuilder();
sb.AppendLine($"Voting started for {name} by {Context.Player.DisplayName}.");
sb.AppendLine("Use !yes to vote and !no to retract your vote");
ModCommunication.SendMessageToClients(new NotificationMessage(sb.ToString(), 15000, "Blue"));
//vote countdown
Task.Run(() =>
{
var countdown = VoteCountdown(_voteDuration).GetEnumerator();
while (countdown.MoveNext())
{
Thread.Sleep(1000);
}
while (countdown.MoveNext()) Thread.Sleep(1000);
});

lastVoteName = voteInProgress;


Context.Torch.CurrentSession?.Managers?.GetManager<IChatManagerServer>()?.SendMessageAsSelf($"Voting started for {name} by {Context.Player.DisplayName}. " +
$"Use [!yes] to vote and [!no] to retract your vote");

}

[Command("vote cancel", "Cancels current vote in progress")]
[Permission(MyPromoteLevel.Admin)]
public void VoteCancel()
{
if (VoteStatus == Status.voteInProgress)
{
VoteStatus = Status.voteCancel;

}
else
Context.Respond("A vote is not in progress");
}
Expand All @@ -115,101 +125,94 @@ public void VoteNo()

if (VoteStatus == Status.voteStandby)
{
Context.Respond($"no vote in progress");
Context.Respond("no vote in progress");
return;
}

var steamid = Context.Player.SteamUserId;

_voteReg.Remove(steamid);
Context.Respond("your vote has been retracted");

}

[Command("yes", "Submit a yes vote")]
[Permission(MyPromoteLevel.None)]
public void VoteYes()
{

if (Context.Player == null)
return;

if (VoteStatus == Status.voteStandby)
{
Context.Respond($"no vote in progress");
Context.Respond("no vote in progress");
return;
}

var command = EssentialsPlugin.Instance.Config.AutoCommands.FirstOrDefault(c => c.Name.Equals(voteInProgress));
var steamid = Context.Player.SteamUserId;
if (_voteReg.TryGetValue(steamid, out DateTime lastcommand))
if (_voteReg.TryGetValue(steamid, out var lastcommand))
{
TimeSpan difference = DateTime.Now - lastcommand;
TimeSpan _voteDuration = TimeSpan.Parse(command.Interval);
var difference = DateTime.Now - lastcommand;
var _voteDuration = TimeSpan.Parse(_command.Interval);
if (difference.TotalSeconds < _voteDuration.TotalSeconds)
{
Context.Respond($"Your vote has already been submitted.");
Context.Respond("Your vote has already been submitted.");
return;
}
else
{
_voteReg[steamid] = DateTime.Now;
}

_voteReg[steamid] = DateTime.Now;
}
else
{
_voteReg.Add(steamid, DateTime.Now);
}
Context.Respond($"Your vote has been submitted.");

Context.Respond("Your vote has been submitted.");
}

//debug
[Command("vote debug", "prints out info from the voting module")]
[Permission(MyPromoteLevel.Admin)]
public void VoteDebgug()
{
StringBuilder sb = new StringBuilder();
var sb = new StringBuilder();
sb.AppendLine();
sb.AppendLine($"Current Vote Status: {VoteStatus.ToString()}");
sb.AppendLine($"Current Vote Name: {voteInProgress}");
sb.AppendLine($"Current vote count: {_voteReg.Count}");
sb.AppendLine();
sb.AppendLine("Last vote info");
if (lastVoteName != null)
sb.AppendLine($"Last vote: {lastVoteName.ToString()}");
sb.AppendLine($"Last vote: {lastVoteName}");
sb.AppendLine($"Last Vote Result: {voteResult.ToString()}");
sb.AppendLine($"Last vote percent: {voteResultPercentage}");
Context.Respond(sb.ToString());

if (Context.Player == null)
Context.Respond(sb.ToString());
else if (Context?.Player?.SteamUserId > 0)
ModCommunication.SendMessageTo(new DialogMessage("List of Online Players", null, sb.ToString()),
Context.Player.SteamUserId);
}

//vote reset
[Command("vote reset", "Resets the voting module data including cooldowns")]
[Permission(MyPromoteLevel.Admin)]
public void VoteReset()
{
if (VoteStatus == Status.voteInProgress)
{
VoteCancel();
}
if (VoteStatus == Status.voteInProgress) VoteCancel();
_voteReg.Clear();
_voteCooldown.Clear();
lastVoteName = null;
voteResult = Status.voteStandby;
voteResultPercentage = 0;
Context.Respond("Vote reset successful");
Log.Info($"Voting module reset by {Context.Player.DisplayName}");
}


//vote countdown
private IEnumerable VoteCountdown(TimeSpan time)
{


for (var i = time.TotalSeconds; i >= 0; i--)
{

if (VoteStatus != Status.voteInProgress || _voteReg.Count < 1)
{
Context.Torch.CurrentSession.Managers.GetManager<IChatManagerClient>()
Expand All @@ -235,25 +238,22 @@ private IEnumerable VoteCountdown(TimeSpan time)
}
else
{
var command = EssentialsPlugin.Instance.Config.AutoCommands.FirstOrDefault(c => c.Name.Equals(voteInProgress));
double vr = ((_voteReg.Count / MySession.Static.Players.GetOnlinePlayerCount()) * 100);
Task.Delay(5000).ContinueWith(_ =>
double vr = _voteReg.Count / MySession.Static.Players.GetOnlinePlayerCount();
if (vr >= _command.TriggerRatio)
{
Context.Torch.CurrentSession.Managers.GetManager<IChatManagerClient>()
.SendMessageAsSelf($"Vote for {voteInProgress} is successful");
voteResult = Status.voteSuccess;
_command.RunNow();
}
else if (vr < _command.TriggerRatio)
{
if (vr >= command.TriggerRatio)
{
Context.Torch.CurrentSession.Managers.GetManager<IChatManagerClient>()
.SendMessageAsSelf($"Vote for {voteInProgress} is successful");
voteResult = Status.voteSuccess;
command.RunNow();
}
else if (vr < command.TriggerRatio)
{
Context.Torch.CurrentSession.Managers.GetManager<IChatManagerClient>()
.SendMessageAsSelf($"Vote for {voteInProgress} failed");
voteResult = Status.voteFail;
}
});
voteResultPercentage = vr;
Context.Torch.CurrentSession.Managers.GetManager<IChatManagerClient>()
.SendMessageAsSelf($"Vote for {voteInProgress} failed");
voteResult = Status.voteFail;
}

voteResultPercentage = vr * 100;
VoteEnd();
yield break;
}
Expand All @@ -264,30 +264,15 @@ private IEnumerable VoteCountdown(TimeSpan time)
public void VoteEnd()
{
//Make sure it's all good for next round
_command = null;
VoteStatus = Status.voteStandby;
voteInProgress = null;
_voteReg.Clear();
}

public enum Status
{
voteStandby,
voteInProgress,
voteCancel,
voteEnd,

// Last vote
voteFail,
voteSuccess
}
private string Pluralize(double num)
{
return num == 1 ? "" : "s";
}


}

}


}