Skip to content
Next Next commit
update
  • Loading branch information
N1Ran committed Apr 3, 2019
commit dda5ea31c14b4673ca543ec38dcae697a0642d55
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";
}


}

}


}
18 changes: 7 additions & 11 deletions Essentials/Commands/WorldModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -222,16 +222,9 @@ private static bool RemoveFromFaction_Internal(MyIdentity identity)
fac.KickMember(identity.IdentityId);
return true;
}

//Equinox told me you can use delegates for ReflectedMethods.
//He lied.
//private delegate void FactionStateDelegate(MyFactionCollection instance, MyFactionStateChange action, long fromFactionId, long toFactionId, long playerId, long senderId);

[ReflectedMethod(Name = "ApplyFactionStateChange", Type = typeof(MyFactionCollection))]
private static Action<MyFactionCollection, MyFactionStateChange, long, long, long, long> _applyFactionState;


private static MethodInfo _factionChangeSuccessInfo = typeof(MyFactionCollection).GetMethod("FactionStateChangeSuccess", BindingFlags.NonPublic | BindingFlags.Static);
private static readonly MethodInfo _factionStateChangeReq = typeof(MyFactionCollection).GetMethod("FactionStateChangeRequest", BindingFlags.Static | BindingFlags.NonPublic);

//TODO: This should probably be moved into Torch base, but I honestly cannot be bothered
/// <summary>
/// Removes a faction from the server and all clients because Keen fucked up their own system.
Expand Down Expand Up @@ -346,7 +339,9 @@ public void CleanSandbox()
var f = SeedParamField.GetValue(g) as HashSet<MyObjectSeedParams>;
count += f.Count;
f.Clear();


//TODO
/*
foreach (var history in MySession.Static.ChatHistory)
{
if (!validIdentities.Contains(history.Key))
Expand All @@ -370,7 +365,8 @@ public void CleanSandbox()
MySession.Static.FactionChatHistory.RemoveAtFast(i);
}
}

*/

var cf = AllCamerasField.GetValue(CamerasField.GetValue(MySession.Static)) as Dictionary<MyPlayer.PlayerId, Dictionary<long, MyEntityCameraSettings>>;
count += cf.Count;
cf.Clear();
Expand Down
Loading