Add variables to prevent voting of various kinds (#5361)
* Add a way to disable voting for maximum authoritarianism * Allow disabling specific vote types via cvars * Migrate standard-vote-to-cvar dictionary to being static
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using Content.Client.Stylesheets;
|
using Content.Client.Stylesheets;
|
||||||
using Content.Shared.Voting;
|
using Content.Shared.Voting;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
@@ -104,8 +105,15 @@ namespace Content.Client.Voting.UI
|
|||||||
|
|
||||||
if (!isAvailable)
|
if (!isAvailable)
|
||||||
{
|
{
|
||||||
var remaining = timeout - _gameTiming.RealTime;
|
if (timeout == TimeSpan.Zero)
|
||||||
VoteTypeTimeoutLabel.Text = Loc.GetString("ui-vote-type-timeout", ("remaining", remaining.ToString("mm\\:ss")));
|
{
|
||||||
|
VoteTypeTimeoutLabel.Text = Loc.GetString("ui-vote-type-not-available");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var remaining = timeout - _gameTiming.RealTime;
|
||||||
|
VoteTypeTimeoutLabel.Text = Loc.GetString("ui-vote-type-timeout", ("remaining", remaining.ToString("mm\\:ss")));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -186,7 +186,8 @@ namespace Content.Client.Voting
|
|||||||
_standardVoteTimeouts.Clear();
|
_standardVoteTimeouts.Clear();
|
||||||
foreach (var (type, time) in message.VotesUnavailable)
|
foreach (var (type, time) in message.VotesUnavailable)
|
||||||
{
|
{
|
||||||
_standardVoteTimeouts.Add(type, _gameTiming.RealServerToLocal(time));
|
var fixedTime = (time == TimeSpan.Zero) ? time : _gameTiming.RealServerToLocal(time);
|
||||||
|
_standardVoteTimeouts.Add(type, fixedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
CanCallStandardVotesChanged?.Invoke();
|
CanCallStandardVotesChanged?.Invoke();
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using Content.Server.RoundEnd;
|
|||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Voting;
|
using Content.Shared.Voting;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Localization;
|
using Robust.Shared.Localization;
|
||||||
@@ -16,6 +17,13 @@ namespace Content.Server.Voting.Managers
|
|||||||
{
|
{
|
||||||
public sealed partial class VoteManager
|
public sealed partial class VoteManager
|
||||||
{
|
{
|
||||||
|
private static readonly Dictionary<StandardVoteType, CVarDef<bool>> _voteTypesToEnableCVars = new()
|
||||||
|
{
|
||||||
|
{StandardVoteType.Restart, CCVars.VoteRestartEnabled},
|
||||||
|
{StandardVoteType.Preset, CCVars.VotePresetEnabled},
|
||||||
|
{StandardVoteType.Map, CCVars.VoteMapEnabled},
|
||||||
|
};
|
||||||
|
|
||||||
public void CreateStandardVote(IPlayerSession? initiator, StandardVoteType voteType)
|
public void CreateStandardVote(IPlayerSession? initiator, StandardVoteType voteType)
|
||||||
{
|
{
|
||||||
switch (voteType)
|
switch (voteType)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using Content.Server.Afk;
|
|||||||
using Content.Server.Chat.Managers;
|
using Content.Server.Chat.Managers;
|
||||||
using Content.Server.Maps;
|
using Content.Server.Maps;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Voting;
|
using Content.Shared.Voting;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
@@ -45,6 +46,7 @@ namespace Content.Server.Voting.Managers
|
|||||||
private readonly Dictionary<StandardVoteType, TimeSpan> _standardVoteTimeout = new();
|
private readonly Dictionary<StandardVoteType, TimeSpan> _standardVoteTimeout = new();
|
||||||
private readonly Dictionary<NetUserId, TimeSpan> _voteTimeout = new();
|
private readonly Dictionary<NetUserId, TimeSpan> _voteTimeout = new();
|
||||||
private readonly HashSet<IPlayerSession> _playerCanCallVoteDirty = new();
|
private readonly HashSet<IPlayerSession> _playerCanCallVoteDirty = new();
|
||||||
|
private readonly StandardVoteType[] _standardVoteTypeValues = Enum.GetValues<StandardVoteType>();
|
||||||
|
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
@@ -53,6 +55,17 @@ namespace Content.Server.Voting.Managers
|
|||||||
|
|
||||||
_playerManager.PlayerStatusChanged += PlayerManagerOnPlayerStatusChanged;
|
_playerManager.PlayerStatusChanged += PlayerManagerOnPlayerStatusChanged;
|
||||||
_adminMgr.OnPermsChanged += AdminPermsChanged;
|
_adminMgr.OnPermsChanged += AdminPermsChanged;
|
||||||
|
|
||||||
|
_cfg.OnValueChanged(CCVars.VoteEnabled, value => {
|
||||||
|
DirtyCanCallVoteAll();
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach (var kvp in _voteTypesToEnableCVars)
|
||||||
|
{
|
||||||
|
_cfg.OnValueChanged(kvp.Value, value => {
|
||||||
|
DirtyCanCallVoteAll();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AdminPermsChanged(AdminPermsChangedEventArgs obj)
|
private void AdminPermsChanged(AdminPermsChangedEventArgs obj)
|
||||||
@@ -262,9 +275,21 @@ namespace Content.Server.Voting.Managers
|
|||||||
msg.CanCall = CanCallVote(player, null, out var isAdmin, out var timeSpan);
|
msg.CanCall = CanCallVote(player, null, out var isAdmin, out var timeSpan);
|
||||||
msg.WhenCanCallVote = timeSpan;
|
msg.WhenCanCallVote = timeSpan;
|
||||||
|
|
||||||
msg.VotesUnavailable = isAdmin
|
if (isAdmin)
|
||||||
? Array.Empty<(StandardVoteType, TimeSpan)>()
|
{
|
||||||
: _standardVoteTimeout.Select(kv => (kv.Key, kv.Value)).ToArray();
|
msg.VotesUnavailable = Array.Empty<(StandardVoteType, TimeSpan)>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var votesUnavailable = new List<(StandardVoteType, TimeSpan)>();
|
||||||
|
foreach (var v in _standardVoteTypeValues)
|
||||||
|
{
|
||||||
|
if (CanCallVote(player, v, out var _isAdmin, out var typeTimeSpan))
|
||||||
|
continue;
|
||||||
|
votesUnavailable.Add((v, typeTimeSpan));
|
||||||
|
}
|
||||||
|
msg.VotesUnavailable = votesUnavailable.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
_netManager.ServerSendMessage(msg, player.ConnectedClient);
|
_netManager.ServerSendMessage(msg, player.ConnectedClient);
|
||||||
}
|
}
|
||||||
@@ -285,13 +310,20 @@ namespace Content.Server.Voting.Managers
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If voting is disabled, block votes.
|
||||||
|
if (!_cfg.GetCVar(CCVars.VoteEnabled))
|
||||||
|
return false;
|
||||||
|
// Specific standard vote types can be disabled with cvars.
|
||||||
|
if ((voteType != null) && _voteTypesToEnableCVars.TryGetValue(voteType.Value, out var cvar) && !_cfg.GetCVar(cvar))
|
||||||
|
return false;
|
||||||
|
|
||||||
// Cannot start vote if vote is already active (as non-admin).
|
// Cannot start vote if vote is already active (as non-admin).
|
||||||
if (_votes.Count != 0)
|
if (_votes.Count != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Standard vote on timeout, no calling.
|
// Standard vote on timeout, no calling.
|
||||||
// Ghosts I understand you're dead but stop spamming the restart vote bloody hell.
|
// Ghosts I understand you're dead but stop spamming the restart vote bloody hell.
|
||||||
if (voteType != null && _standardVoteTimeout.ContainsKey(voteType.Value))
|
if (voteType != null && _standardVoteTimeout.TryGetValue(voteType.Value, out timeSpan))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return !_voteTimeout.TryGetValue(initiator.UserId, out timeSpan);
|
return !_voteTimeout.TryGetValue(initiator.UserId, out timeSpan);
|
||||||
|
|||||||
@@ -431,6 +431,30 @@ namespace Content.Shared.CCVar
|
|||||||
* VOTE
|
* VOTE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows enabling/disabling player-started votes for ultimate authority
|
||||||
|
/// </summary>
|
||||||
|
public static readonly CVarDef<bool> VoteEnabled =
|
||||||
|
CVarDef.Create("vote.enabled", true, CVar.SERVERONLY);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// See vote.enabled, but specific to restart votes
|
||||||
|
/// </summary>
|
||||||
|
public static readonly CVarDef<bool> VoteRestartEnabled =
|
||||||
|
CVarDef.Create("vote.restart_enabled", true, CVar.SERVERONLY);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// See vote.enabled, but specific to preset votes
|
||||||
|
/// </summary>
|
||||||
|
public static readonly CVarDef<bool> VotePresetEnabled =
|
||||||
|
CVarDef.Create("vote.preset_enabled", true, CVar.SERVERONLY);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// See vote.enabled, but specific to map votes
|
||||||
|
/// </summary>
|
||||||
|
public static readonly CVarDef<bool> VoteMapEnabled =
|
||||||
|
CVarDef.Create("vote.map_enabled", true, CVar.SERVERONLY);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The required ratio of the server that must agree for a restart round vote to go through.
|
/// The required ratio of the server that must agree for a restart round vote to go through.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ namespace Content.Shared.Voting
|
|||||||
public TimeSpan WhenCanCallVote;
|
public TimeSpan WhenCanCallVote;
|
||||||
|
|
||||||
// Which standard votes are currently unavailable, and when will they become available.
|
// Which standard votes are currently unavailable, and when will they become available.
|
||||||
|
// The whenAvailable can be null if the reason is something not timeout related.
|
||||||
public (StandardVoteType type, TimeSpan whenAvailable)[] VotesUnavailable = default!;
|
public (StandardVoteType type, TimeSpan whenAvailable)[] VotesUnavailable = default!;
|
||||||
|
|
||||||
// It's possible to be able to call votes but all standard votes to be timed out.
|
// It's possible to be able to call votes but all standard votes to be timed out.
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ ui-vote-create-button = Call Vote
|
|||||||
# Timeout text if a standard vote type is currently on timeout.
|
# Timeout text if a standard vote type is currently on timeout.
|
||||||
ui-vote-type-timeout = This vote was called too recently ({$remaining})
|
ui-vote-type-timeout = This vote was called too recently ({$remaining})
|
||||||
|
|
||||||
|
# Unavailable text if a vote type has been disabled manually.
|
||||||
|
ui-vote-type-not-available = This vote type has been disabled
|
||||||
|
|
||||||
# Hue hue hue
|
# Hue hue hue
|
||||||
ui-vote-fluff = Powered by Robust™ Anti-Tamper Technology
|
ui-vote-fluff = Powered by Robust™ Anti-Tamper Technology
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user