Prevent admin-frozen players from ghosting or suiciding, add "Freeze And Mute" verb (#27813)

* prevent admin-frozen players from ghosting or suiciding

* Add "Freeze and Mute" admin verb

* Allow "Freeze And Mute" admin verb when player is already frozen but not muted

* Remove redundant scream handler (scream action just emotes, duh)

* AdminFrozenSystem: clean imports

* Update Content.Server/Chat/Commands/SuicideCommand.cs

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>

* Update Ghost.cs

* retrigger ci (empty commit)

---------

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
This commit is contained in:
no
2024-05-12 16:35:30 +02:00
committed by GitHub
parent 855234aa30
commit 37099e481e
10 changed files with 138 additions and 28 deletions

View File

@@ -0,0 +1,16 @@
using Content.Shared.Administration;
namespace Content.Server.Administration.Systems;
public sealed class AdminFrozenSystem : SharedAdminFrozenSystem
{
/// <summary>
/// Freezes and mutes the given entity.
/// </summary>
public void FreezeAndMute(EntityUid uid)
{
var comp = EnsureComp<AdminFrozenComponent>(uid);
comp.Muted = true;
Dirty(uid, comp);
}
}

View File

@@ -67,6 +67,7 @@ namespace Content.Server.Administration.Systems
[Dependency] private readonly StationSystem _stations = default!;
[Dependency] private readonly StationSpawningSystem _spawning = default!;
[Dependency] private readonly ExamineSystemShared _examine = default!;
[Dependency] private readonly AdminFrozenSystem _freeze = default!;
private readonly Dictionary<ICommonSession, List<EditSolutionsEui>> _openSolutionUis = new();
@@ -131,24 +132,57 @@ namespace Content.Server.Administration.Systems
args.Verbs.Add(prayerVerb);
// Freeze
var frozen = HasComp<AdminFrozenComponent>(args.Target);
args.Verbs.Add(new Verb
var frozen = TryComp<AdminFrozenComponent>(args.Target, out var frozenComp);
var frozenAndMuted = frozenComp?.Muted ?? false;
if (!frozen)
{
Priority = -1, // This is just so it doesn't change position in the menu between freeze/unfreeze.
Text = frozen
? Loc.GetString("admin-verbs-unfreeze")
: Loc.GetString("admin-verbs-freeze"),
Category = VerbCategory.Admin,
Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/snow.svg.192dpi.png")),
Act = () =>
args.Verbs.Add(new Verb
{
if (frozen)
RemComp<AdminFrozenComponent>(args.Target);
else
Priority = -1, // This is just so it doesn't change position in the menu between freeze/unfreeze.
Text = Loc.GetString("admin-verbs-freeze"),
Category = VerbCategory.Admin,
Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/snow.svg.192dpi.png")),
Act = () =>
{
EnsureComp<AdminFrozenComponent>(args.Target);
},
Impact = LogImpact.Medium,
});
},
Impact = LogImpact.Medium,
});
}
if (!frozenAndMuted)
{
// allow you to additionally mute someone when they are already frozen
args.Verbs.Add(new Verb
{
Priority = -1, // This is just so it doesn't change position in the menu between freeze/unfreeze.
Text = Loc.GetString("admin-verbs-freeze-and-mute"),
Category = VerbCategory.Admin,
Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/snow.svg.192dpi.png")),
Act = () =>
{
_freeze.FreezeAndMute(args.Target);
},
Impact = LogImpact.Medium,
});
}
if (frozen)
{
args.Verbs.Add(new Verb
{
Priority = -1, // This is just so it doesn't change position in the menu between freeze/unfreeze.
Text = Loc.GetString("admin-verbs-unfreeze"),
Category = VerbCategory.Admin,
Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/snow.svg.192dpi.png")),
Act = () =>
{
RemComp<AdminFrozenComponent>(args.Target);
},
Impact = LogImpact.Medium,
});
}
// Erase
args.Verbs.Add(new Verb

View File

@@ -1,4 +1,5 @@
using Content.Server.GameTicking;
using Content.Server.Popups;
using Content.Shared.Administration;
using Content.Shared.Mind;
using Robust.Shared.Console;
@@ -26,17 +27,27 @@ namespace Content.Server.Chat.Commands
if (player.Status != SessionStatus.InGame || player.AttachedEntity == null)
return;
var minds = IoCManager.Resolve<IEntityManager>().System<SharedMindSystem>();
var entityManager = IoCManager.Resolve<IEntityManager>();
var minds = entityManager.System<SharedMindSystem>();
// This check also proves mind not-null for at the end when the mob is ghosted.
if (!minds.TryGetMind(player, out var mindId, out var mind) ||
mind.OwnedEntity is not { Valid: true } victim)
{
shell.WriteLine("You don't have a mind!");
shell.WriteLine(Loc.GetString("suicide-command-no-mind"));
return;
}
var gameTicker = EntitySystem.Get<GameTicker>();
var suicideSystem = EntitySystem.Get<SuicideSystem>();
if (entityManager.HasComponent<AdminFrozenComponent>(victim))
{
var deniedMessage = Loc.GetString("suicide-command-denied");
shell.WriteLine(deniedMessage);
entityManager.System<PopupSystem>()
.PopupEntity(deniedMessage, victim, victim);
return;
}
var gameTicker = entityManager.System<GameTicker>();
var suicideSystem = entityManager.System<SuicideSystem>();
if (suicideSystem.Suicide(victim))
{
// Prevent the player from returning to the body.
@@ -48,7 +59,7 @@ namespace Content.Server.Chat.Commands
if (gameTicker.OnGhostAttempt(mindId, true, mind: mind))
return;
shell.WriteLine("You can't ghost right now.");
shell.WriteLine(Loc.GetString("ghost-command-denied"));
}
}
}

View File

@@ -1,4 +1,5 @@
using Content.Server.GameTicking;
using Content.Server.Popups;
using Content.Shared.Administration;
using Content.Shared.Mind;
using Robust.Shared.Console;
@@ -11,15 +12,25 @@ namespace Content.Server.Ghost
[Dependency] private readonly IEntityManager _entities = default!;
public string Command => "ghost";
public string Description => "Give up on life and become a ghost.";
public string Help => "ghost";
public string Description => Loc.GetString("ghost-command-description");
public string Help => Loc.GetString("ghost-command-help-text");
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
var player = shell.Player;
if (player == null)
{
shell.WriteLine("You have no session, you can't ghost.");
shell.WriteLine(Loc.GetString("ghost-command-no-session"));
return;
}
if (player.AttachedEntity is { Valid: true } frozen &&
_entities.HasComponent<AdminFrozenComponent>(frozen))
{
var deniedMessage = Loc.GetString("ghost-command-denied");
shell.WriteLine(deniedMessage);
_entities.System<PopupSystem>()
.PopupEntity(deniedMessage, frozen, frozen);
return;
}
@@ -30,9 +41,9 @@ namespace Content.Server.Ghost
mind = _entities.GetComponent<MindComponent>(mindId);
}
if (!EntitySystem.Get<GameTicker>().OnGhostAttempt(mindId, true, true, mind))
if (!_entities.System<GameTicker>().OnGhostAttempt(mindId, true, true, mind))
{
shell.WriteLine("You can't ghost right now.");
shell.WriteLine(Loc.GetString("ghost-command-denied"));
}
}
}