diff --git a/Content.IntegrationTests/Tests/Commands/RestartRoundTest.cs b/Content.IntegrationTests/Tests/Commands/RestartRoundTest.cs index 4a69d5751b..bd1484508e 100644 --- a/Content.IntegrationTests/Tests/Commands/RestartRoundTest.cs +++ b/Content.IntegrationTests/Tests/Commands/RestartRoundTest.cs @@ -1,4 +1,5 @@ using System.Threading.Tasks; +using Content.Server.Commands.GameTicking; using Content.Server.GameTicking; using Content.Server.Interfaces.GameTicking; using Content.Shared; diff --git a/Content.Server/Atmos/AtmosCommands.cs b/Content.Server/Atmos/AtmosCommands.cs deleted file mode 100644 index 546b2e4b63..0000000000 --- a/Content.Server/Atmos/AtmosCommands.cs +++ /dev/null @@ -1,635 +0,0 @@ -#nullable enable -using System; -using Content.Server.Administration; -using Content.Server.GameObjects.Components.Atmos; -using Content.Server.GameObjects.EntitySystems; -using Content.Server.GameObjects.EntitySystems.Atmos; -using Content.Shared.Administration; -using Content.Shared.Atmos; -using Robust.Server.Interfaces.Console; -using Robust.Server.Interfaces.Player; -using Robust.Shared.GameObjects.Systems; -using Robust.Shared.Interfaces.GameObjects; -using Robust.Shared.Interfaces.Map; -using Robust.Shared.IoC; -using Robust.Shared.Map; -using Robust.Shared.Maths; - -namespace Content.Server.Atmos -{ - [AdminCommand(AdminFlags.Debug)] - public class AddAtmos : IClientCommand - { - public string Command => "addatmos"; - public string Description => "Adds atmos support to a grid."; - public string Help => $"{Command} "; - - public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - if (args.Length < 1) - { - shell.SendText(player, Help); - return; - } - - if (!int.TryParse(args[0], out var id)) - { - shell.SendText(player, $"{args[0]} is not a valid integer."); - return; - } - - var gridId = new GridId(id); - - var mapMan = IoCManager.Resolve(); - - if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp)) - { - shell.SendText(player, $"{gridId} is not a valid grid id."); - return; - } - - var entMan = IoCManager.Resolve(); - - if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid)) - { - shell.SendText(player, "Failed to get grid entity."); - return; - } - - if (grid.HasComponent()) - { - shell.SendText(player, "Grid already has an atmosphere."); - return; - } - - grid.AddComponent(); - - shell.SendText(player, $"Added atmosphere to grid {id}."); - } - } - - [AdminCommand(AdminFlags.Debug)] - public class AddUnsimulatedAtmos : IClientCommand - { - public string Command => "addunsimulatedatmos"; - public string Description => "Adds unimulated atmos support to a grid."; - public string Help => $"{Command} "; - - public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - if (args.Length < 1) - { - shell.SendText(player, Help); - return; - } - - if (!int.TryParse(args[0], out var id)) - { - shell.SendText(player, $"{args[0]} is not a valid integer."); - return; - } - - var gridId = new GridId(id); - - var mapMan = IoCManager.Resolve(); - - if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp)) - { - shell.SendText(player, $"{gridId} is not a valid grid id."); - return; - } - - var entMan = IoCManager.Resolve(); - - if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid)) - { - shell.SendText(player, "Failed to get grid entity."); - return; - } - - if (grid.HasComponent()) - { - shell.SendText(player, "Grid already has an atmosphere."); - return; - } - - grid.AddComponent(); - - shell.SendText(player, $"Added unsimulated atmosphere to grid {id}."); - } - } - - [AdminCommand(AdminFlags.Debug)] - public class ListGases : IClientCommand - { - public string Command => "listgases"; - public string Description => "Prints a list of gases and their indices."; - public string Help => "listgases"; - public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - var atmosSystem = EntitySystem.Get(); - - foreach (var gasPrototype in atmosSystem.Gases) - { - shell.SendText(player, $"{gasPrototype.Name} ID: {gasPrototype.ID}"); - } - } - } - - [AdminCommand(AdminFlags.Debug)] - public class AddGas : IClientCommand - { - public string Command => "addgas"; - public string Description => "Adds gas at a certain position."; - public string Help => "addgas "; - public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - if (args.Length < 5) return; - if(!int.TryParse(args[0], out var x) - || !int.TryParse(args[1], out var y) - || !int.TryParse(args[2], out var id) - || !(AtmosCommandUtils.TryParseGasID(args[3], out var gasId)) - || !float.TryParse(args[4], out var moles)) return; - - var gridId = new GridId(id); - - var mapMan = IoCManager.Resolve(); - - if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp)) - { - shell.SendText(player, "Invalid grid ID."); - return; - } - - var entMan = IoCManager.Resolve(); - - if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid)) - { - shell.SendText(player, "Failed to get grid entity."); - return; - } - - if (!grid.HasComponent()) - { - shell.SendText(player, "Grid doesn't have an atmosphere."); - return; - } - - var gam = grid.GetComponent(); - var indices = new Vector2i(x, y); - var tile = gam.GetTile(indices); - - if (tile == null) - { - shell.SendText(player, "Invalid coordinates."); - return; - } - - if (tile.Air == null) - { - shell.SendText(player, "Can't add gas to that tile."); - return; - } - - tile.Air.AdjustMoles(gasId, moles); - gam.Invalidate(indices); - } - } - - [AdminCommand(AdminFlags.Debug)] - public class FillGas : IClientCommand - { - public string Command => "fillgas"; - public string Description => "Adds gas to all tiles in a grid."; - public string Help => "fillgas "; - public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - if (args.Length < 3) return; - if(!int.TryParse(args[0], out var id) - || !(AtmosCommandUtils.TryParseGasID(args[1], out var gasId)) - || !float.TryParse(args[2], out var moles)) return; - - var gridId = new GridId(id); - - var mapMan = IoCManager.Resolve(); - - if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp)) - { - shell.SendText(player, "Invalid grid ID."); - return; - } - - var entMan = IoCManager.Resolve(); - - if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid)) - { - shell.SendText(player, "Failed to get grid entity."); - return; - } - - if (!grid.HasComponent()) - { - shell.SendText(player, "Grid doesn't have an atmosphere."); - return; - } - - var gam = grid.GetComponent(); - - foreach (var tile in gam) - { - tile.Air?.AdjustMoles(gasId, moles); - gam.Invalidate(tile.GridIndices); - } - } - } - - [AdminCommand(AdminFlags.Debug)] - public class RemoveGas : IClientCommand - { - public string Command => "removegas"; - public string Description => "Removes an amount of gases."; - public string Help => "removegas \nIf is true, amount will be treated as the ratio of gas to be removed."; - public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - if (args.Length < 5) return; - if(!int.TryParse(args[0], out var x) - || !int.TryParse(args[1], out var y) - || !int.TryParse(args[2], out var id) - || !float.TryParse(args[3], out var amount) - || !bool.TryParse(args[4], out var ratio)) return; - - var gridId = new GridId(id); - - var mapMan = IoCManager.Resolve(); - - if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp)) - { - shell.SendText(player, "Invalid grid ID."); - return; - } - - var entMan = IoCManager.Resolve(); - - if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid)) - { - shell.SendText(player, "Failed to get grid entity."); - return; - } - - if (!grid.HasComponent()) - { - shell.SendText(player, "Grid doesn't have an atmosphere."); - return; - } - - var gam = grid.GetComponent(); - var indices = new Vector2i(x, y); - var tile = gam.GetTile(indices); - - if (tile == null) - { - shell.SendText(player, "Invalid coordinates."); - return; - } - - if (tile.Air == null) - { - shell.SendText(player, "Can't remove gas from that tile."); - return; - } - - if (ratio) - tile.Air.RemoveRatio(amount); - else - tile.Air.Remove(amount); - - gam.Invalidate(indices); - } - } - - [AdminCommand(AdminFlags.Debug)] - public class SetTemperature : IClientCommand - { - public string Command => "settemp"; - public string Description => "Sets a tile's temperature (in kelvin)."; - public string Help => "Usage: settemp "; - public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - if (args.Length < 4) return; - if(!int.TryParse(args[0], out var x) - || !int.TryParse(args[1], out var y) - || !int.TryParse(args[2], out var id) - || !float.TryParse(args[3], out var temperature)) return; - - var gridId = new GridId(id); - - var mapMan = IoCManager.Resolve(); - - if (temperature < Atmospherics.TCMB) - { - shell.SendText(player, "Invalid temperature."); - return; - } - - if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp)) - { - shell.SendText(player, "Invalid grid ID."); - return; - } - - var entMan = IoCManager.Resolve(); - - if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid)) - { - shell.SendText(player, "Failed to get grid entity."); - return; - } - - if (!grid.HasComponent()) - { - shell.SendText(player, "Grid doesn't have an atmosphere."); - return; - } - - var gam = grid.GetComponent(); - var indices = new Vector2i(x, y); - var tile = gam.GetTile(indices); - - if (tile == null) - { - shell.SendText(player, "Invalid coordinates."); - return; - } - - if (tile.Air == null) - { - shell.SendText(player, "Can't change that tile's temperature."); - return; - } - - tile.Air.Temperature = temperature; - gam.Invalidate(indices); - } - } - - [AdminCommand(AdminFlags.Debug)] - public class SetAtmosTemperature : IClientCommand - { - public string Command => "setatmostemp"; - public string Description => "Sets a grid's temperature (in kelvin)."; - public string Help => "Usage: setatmostemp "; - public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - if (args.Length < 2) return; - if(!int.TryParse(args[0], out var id) - || !float.TryParse(args[1], out var temperature)) return; - - var gridId = new GridId(id); - - var mapMan = IoCManager.Resolve(); - - if (temperature < Atmospherics.TCMB) - { - shell.SendText(player, "Invalid temperature."); - return; - } - - if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp)) - { - shell.SendText(player, "Invalid grid ID."); - return; - } - - var entMan = IoCManager.Resolve(); - - if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid)) - { - shell.SendText(player, "Failed to get grid entity."); - return; - } - - if (!grid.HasComponent()) - { - shell.SendText(player, "Grid doesn't have an atmosphere."); - return; - } - - var gam = grid.GetComponent(); - - var tiles = 0; - foreach (var tile in gam) - { - if (tile.Air == null) - continue; - - tiles++; - - tile.Air.Temperature = temperature; - gam.Invalidate(tile.GridIndices); - } - - shell.SendText(player, $"Changed the temperature of {tiles} tiles."); - } - } - - [AdminCommand(AdminFlags.Debug)] - public class DeleteGasCommand : IClientCommand - { - public string Command => "deletegas"; - public string Description => "Removes all gases from a grid, or just of one type if specified."; - public string Help => $"Usage: {Command} / {Command} / {Command} / {Command}"; - - public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - GridId gridId; - Gas? gas = null; - - switch (args.Length) - { - case 0: - if (player == null) - { - shell.SendText(player, "A grid must be specified when the command isn't used by a player."); - return; - } - - if (player.AttachedEntity == null) - { - shell.SendText(player, "You have no entity to get a grid from."); - return; - } - - gridId = player.AttachedEntity.Transform.GridID; - - if (gridId == GridId.Invalid) - { - shell.SendText(player, "You aren't on a grid to delete gas from."); - return; - } - - break; - case 1: - { - if (!int.TryParse(args[0], out var number)) - { - // Argument is a gas - if (player == null) - { - shell.SendText(player, "A grid id must be specified if not using this command as a player."); - return; - } - - if (player.AttachedEntity == null) - { - shell.SendText(player, "You have no entity from which to get a grid id."); - return; - } - - gridId = player.AttachedEntity.Transform.GridID; - - if (gridId == GridId.Invalid) - { - shell.SendText(player, "You aren't on a grid to delete gas from."); - return; - } - - if (!Enum.TryParse(args[0], true, out var parsedGas)) - { - shell.SendText(player, $"{args[0]} is not a valid gas name."); - return; - } - - gas = parsedGas; - break; - } - - // Argument is a grid - gridId = new GridId(number); - - if (gridId == GridId.Invalid) - { - shell.SendText(player, $"{gridId} is not a valid grid id."); - return; - } - - break; - } - case 2: - { - if (!int.TryParse(args[0], out var first)) - { - shell.SendText(player, $"{args[0]} is not a valid integer for a grid id."); - return; - } - - gridId = new GridId(first); - - if (gridId == GridId.Invalid) - { - shell.SendText(player, $"{gridId} is not a valid grid id."); - return; - } - - if (!Enum.TryParse(args[1], true, out var parsedGas)) - { - shell.SendText(player, $"{args[1]} is not a valid gas."); - return; - } - - gas = parsedGas; - - break; - } - default: - shell.SendText(player, Help); - return; - } - - var mapManager = IoCManager.Resolve(); - - if (!mapManager.TryGetGrid(gridId, out var grid)) - { - shell.SendText(player, $"No grid exists with id {gridId}"); - return; - } - - var entityManager = IoCManager.Resolve(); - - if (!entityManager.TryGetEntity(grid.GridEntityId, out var gridEntity)) - { - shell.SendText(player, $"Grid {gridId} has no entity."); - return; - } - - if (!gridEntity.TryGetComponent(out GridAtmosphereComponent? atmosphere)) - { - shell.SendText(player, $"Grid {gridId} has no {nameof(GridAtmosphereComponent)}"); - return; - } - - var tiles = 0; - var moles = 0f; - - if (gas == null) - { - foreach (var tile in atmosphere) - { - if (tile.Air == null || tile.Air.Immutable) continue; - - tiles++; - moles += tile.Air.TotalMoles; - - tile.Air.Clear(); - - atmosphere.Invalidate(tile.GridIndices); - } - } - else - { - foreach (var tile in atmosphere) - { - if (tile.Air == null || tile.Air.Immutable) continue; - - tiles++; - moles += tile.Air.TotalMoles; - - tile.Air.SetMoles(gas.Value, 0); - - atmosphere.Invalidate(tile.GridIndices); - } - } - - if (gas == null) - { - shell.SendText(player, $"Removed {moles} moles from {tiles} tiles."); - return; - } - - shell.SendText(player, $"Removed {moles} moles of gas {gas} from {tiles} tiles."); - } - } - - [AdminCommand(AdminFlags.Debug)] - public class ShowAtmos : IClientCommand - { - public string Command => "showatmos"; - public string Description => "Toggles seeing atmos debug overlay."; - public string Help => $"Usage: {Command}"; - - public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - if (player == null) - { - shell.SendText(player, "You must be a player to use this command."); - return; - } - - var atmosDebug = EntitySystem.Get(); - var enabled = atmosDebug.ToggleObserver(player); - - shell.SendText(player, enabled - ? "Enabled the atmospherics debug overlay." - : "Disabled the atmospherics debug overlay."); - } - } -} diff --git a/Content.Server/Commands/AI/AddAiCommand.cs b/Content.Server/Commands/AI/AddAiCommand.cs new file mode 100644 index 0000000000..395bae79bf --- /dev/null +++ b/Content.Server/Commands/AI/AddAiCommand.cs @@ -0,0 +1,59 @@ +#nullable enable +using Content.Server.Administration; +using Content.Server.GameObjects.Components.Movement; +using Content.Server.GameObjects.EntitySystems.AI; +using Content.Shared.Administration; +using Content.Shared.GameObjects.Components.Movement; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.AI +{ + [AdminCommand(AdminFlags.Fun)] + public class AddAiCommand : IClientCommand + { + public string Command => "addai"; + public string Description => "Add an ai component with a given processor to an entity."; + public string Help => "Usage: addai " + + "\n processorId: Class that inherits AiLogicProcessor and has an AiLogicProcessor attribute." + + "\n entityID: Uid of entity to add the AiControllerComponent to. Open its VV menu to find this."; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if(args.Length != 2) + { + shell.SendText(player, "Wrong number of args."); + return; + } + + var processorId = args[0]; + var entId = new EntityUid(int.Parse(args[1])); + var ent = IoCManager.Resolve().GetEntity(entId); + var aiSystem = EntitySystem.Get(); + + if (!aiSystem.ProcessorTypeExists(processorId)) + { + shell.SendText(player, "Invalid processor type. Processor must inherit AiLogicProcessor and have an AiLogicProcessor attribute."); + return; + } + if (ent.HasComponent()) + { + shell.SendText(player, "Entity already has an AI component."); + return; + } + + if (ent.HasComponent()) + { + ent.RemoveComponent(); + } + + var comp = ent.AddComponent(); + comp.LogicName = processorId; + shell.SendText(player, "AI component added."); + } + } +} diff --git a/Content.Server/Commands/AI/FactionCommand.cs b/Content.Server/Commands/AI/FactionCommand.cs new file mode 100644 index 0000000000..ae0107ff62 --- /dev/null +++ b/Content.Server/Commands/AI/FactionCommand.cs @@ -0,0 +1,97 @@ +using System; +using System.Text; +using Content.Server.Administration; +using Content.Server.GameObjects.Components.AI; +using Content.Server.GameObjects.EntitySystems.AI; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Localization; + +namespace Content.Server.Commands.AI +{ + [AdminCommand(AdminFlags.Fun)] + public sealed class FactionCommand : IClientCommand + { + public string Command => "factions"; + public string Description => "Update / list factional relationships for NPCs."; + public string Help => "faction target\n" + + "faction list: hostile factions"; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + if (args.Length == 0) + { + var result = new StringBuilder(); + foreach (Faction value in Enum.GetValues(typeof(Faction))) + { + if (value == Faction.None) + continue; + result.Append(value + "\n"); + } + + shell.SendText(player, result.ToString()); + return; + } + + if (args.Length < 2) + { + shell.SendText(player, Loc.GetString("Need more args")); + return; + } + + if (!Enum.TryParse(args[0], true, out Faction faction)) + { + shell.SendText(player, Loc.GetString("Invalid faction")); + return; + } + + Faction targetFaction; + + switch (args[1]) + { + case "friendly": + if (args.Length < 3) + { + shell.SendText(player, Loc.GetString("Need to supply a target faction")); + return; + } + + if (!Enum.TryParse(args[2], true, out targetFaction)) + { + shell.SendText(player, Loc.GetString("Invalid target faction")); + return; + } + + EntitySystem.Get().MakeFriendly(faction, targetFaction); + shell.SendText(player, Loc.GetString("Command successful")); + break; + case "hostile": + if (args.Length < 3) + { + shell.SendText(player, Loc.GetString("Need to supply a target faction")); + return; + } + + if (!Enum.TryParse(args[2], true, out targetFaction)) + { + shell.SendText(player, Loc.GetString("Invalid target faction")); + return; + } + + EntitySystem.Get().MakeHostile(faction, targetFaction); + shell.SendText(player, Loc.GetString("Command successful")); + break; + case "list": + shell.SendText(player, EntitySystem.Get().GetHostileFactions(faction).ToString()); + break; + default: + shell.SendText(player, Loc.GetString("Unknown faction arg")); + break; + } + + return; + } + } +} \ No newline at end of file diff --git a/Content.Server/Commands/Alerts/ClearAlert.cs b/Content.Server/Commands/Alerts/ClearAlert.cs new file mode 100644 index 0000000000..5761df0401 --- /dev/null +++ b/Content.Server/Commands/Alerts/ClearAlert.cs @@ -0,0 +1,55 @@ +#nullable enable +using System; +using Content.Server.Administration; +using Content.Server.GameObjects.Components.Mobs; +using Content.Shared.Administration; +using Content.Shared.Alert; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.Alerts +{ + [AdminCommand(AdminFlags.Debug)] + public sealed class ClearAlert : IClientCommand + { + public string Command => "clearalert"; + public string Description => "Clears an alert for a player, defaulting to current player"; + public string Help => "clearalert "; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + var attachedEntity = player?.AttachedEntity; + + if (attachedEntity == null) + { + shell.SendText(player, "You don't have an entity."); + return; + } + + if (args.Length > 1) + { + var target = args[1]; + if (!CommandUtils.TryGetAttachedEntityByUsernameOrId(shell, target, player, out attachedEntity)) return; + } + + if (!CommandUtils.ValidateAttachedEntity(shell, player, attachedEntity)) return; + + if (!attachedEntity.TryGetComponent(out ServerAlertsComponent? alertsComponent)) + { + shell.SendText(player, "user has no alerts component"); + return; + } + + var alertType = args[0]; + var alertMgr = IoCManager.Resolve(); + if (!alertMgr.TryGet(Enum.Parse(alertType), out var alert)) + { + shell.SendText(player, "unrecognized alertType " + alertType); + return; + } + + alertsComponent.ClearAlert(alert.AlertType); + } + } +} diff --git a/Content.Server/Commands/Alerts/ShowAlert.cs b/Content.Server/Commands/Alerts/ShowAlert.cs new file mode 100644 index 0000000000..ef85091bb5 --- /dev/null +++ b/Content.Server/Commands/Alerts/ShowAlert.cs @@ -0,0 +1,67 @@ +#nullable enable +using System; +using Content.Server.Administration; +using Content.Server.GameObjects.Components.Mobs; +using Content.Shared.Administration; +using Content.Shared.Alert; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.Alerts +{ + [AdminCommand(AdminFlags.Debug)] + public sealed class ShowAlert : IClientCommand + { + public string Command => "showalert"; + public string Description => "Shows an alert for a player, defaulting to current player"; + public string Help => "showalert "; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (player == null) + { + shell.SendText(player, "You cannot run this command from the server."); + return; + } + + var attachedEntity = player.AttachedEntity; + + if (attachedEntity == null) + { + shell.SendText(player, "You don't have an entity."); + return; + } + + if (args.Length > 2) + { + var target = args[2]; + if (!CommandUtils.TryGetAttachedEntityByUsernameOrId(shell, target, player, out attachedEntity)) return; + } + + if (!CommandUtils.ValidateAttachedEntity(shell, player, attachedEntity)) + return; + + if (!attachedEntity.TryGetComponent(out ServerAlertsComponent? alertsComponent)) + { + shell.SendText(player, "user has no alerts component"); + return; + } + + var alertType = args[0]; + var severity = args[1]; + var alertMgr = IoCManager.Resolve(); + if (!alertMgr.TryGet(Enum.Parse(alertType), out var alert)) + { + shell.SendText(player, "unrecognized alertType " + alertType); + return; + } + if (!short.TryParse(severity, out var sevint)) + { + shell.SendText(player, "invalid severity " + sevint); + return; + } + alertsComponent.ShowAlert(alert.AlertType, sevint == -1 ? (short?) null : sevint); + } + } +} diff --git a/Content.Server/Commands/Atmos/AddAtmosCommand.cs b/Content.Server/Commands/Atmos/AddAtmosCommand.cs new file mode 100644 index 0000000000..48298d0641 --- /dev/null +++ b/Content.Server/Commands/Atmos/AddAtmosCommand.cs @@ -0,0 +1,65 @@ +#nullable enable +using Content.Server.Administration; +using Content.Server.Atmos; +using Content.Server.GameObjects.Components.Atmos; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Map; +using Robust.Shared.IoC; +using Robust.Shared.Map; + +namespace Content.Server.Commands.Atmos +{ + [AdminCommand(AdminFlags.Debug)] + public class AddAtmosCommand : IClientCommand + { + public string Command => "addatmos"; + public string Description => "Adds atmos support to a grid."; + public string Help => $"{Command} "; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (args.Length < 1) + { + shell.SendText(player, Help); + return; + } + + if (!int.TryParse(args[0], out var id)) + { + shell.SendText(player, $"{args[0]} is not a valid integer."); + return; + } + + var gridId = new GridId(id); + + var mapMan = IoCManager.Resolve(); + + if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp)) + { + shell.SendText(player, $"{gridId} is not a valid grid id."); + return; + } + + var entMan = IoCManager.Resolve(); + + if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid)) + { + shell.SendText(player, "Failed to get grid entity."); + return; + } + + if (grid.HasComponent()) + { + shell.SendText(player, "Grid already has an atmosphere."); + return; + } + + grid.AddComponent(); + + shell.SendText(player, $"Added atmosphere to grid {id}."); + } + } +} diff --git a/Content.Server/Commands/Atmos/AddGasCommand.cs b/Content.Server/Commands/Atmos/AddGasCommand.cs new file mode 100644 index 0000000000..0599a2408a --- /dev/null +++ b/Content.Server/Commands/Atmos/AddGasCommand.cs @@ -0,0 +1,76 @@ +#nullable enable +using Content.Server.Administration; +using Content.Server.GameObjects.Components.Atmos; +using Content.Shared.Administration; +using Content.Shared.Atmos; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Map; +using Robust.Shared.IoC; +using Robust.Shared.Map; +using Robust.Shared.Maths; + +namespace Content.Server.Commands.Atmos +{ + [AdminCommand(AdminFlags.Debug)] + public class AddGasCommand : IClientCommand + { + public string Command => "addgas"; + public string Description => "Adds gas at a certain position."; + public string Help => "addgas "; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (args.Length < 5) return; + if(!int.TryParse(args[0], out var x) + || !int.TryParse(args[1], out var y) + || !int.TryParse(args[2], out var id) + || !(AtmosCommandUtils.TryParseGasID(args[3], out var gasId)) + || !float.TryParse(args[4], out var moles)) return; + + var gridId = new GridId(id); + + var mapMan = IoCManager.Resolve(); + + if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp)) + { + shell.SendText(player, "Invalid grid ID."); + return; + } + + var entMan = IoCManager.Resolve(); + + if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid)) + { + shell.SendText(player, "Failed to get grid entity."); + return; + } + + if (!grid.HasComponent()) + { + shell.SendText(player, "Grid doesn't have an atmosphere."); + return; + } + + var gam = grid.GetComponent(); + var indices = new Vector2i(x, y); + var tile = gam.GetTile(indices); + + if (tile == null) + { + shell.SendText(player, "Invalid coordinates."); + return; + } + + if (tile.Air == null) + { + shell.SendText(player, "Can't add gas to that tile."); + return; + } + + tile.Air.AdjustMoles(gasId, moles); + gam.Invalidate(indices); + } + } +} diff --git a/Content.Server/Commands/Atmos/AddUnsimulatedAtmosCommand.cs b/Content.Server/Commands/Atmos/AddUnsimulatedAtmosCommand.cs new file mode 100644 index 0000000000..9b39a92653 --- /dev/null +++ b/Content.Server/Commands/Atmos/AddUnsimulatedAtmosCommand.cs @@ -0,0 +1,66 @@ +#nullable enable +using Content.Server.Administration; +using Content.Server.Atmos; +using Content.Server.GameObjects.Components.Atmos; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Map; +using Robust.Shared.IoC; +using Robust.Shared.Map; + +namespace Content.Server.Commands.Atmos +{ + [AdminCommand(AdminFlags.Debug)] + public class AddUnsimulatedAtmosCommand : IClientCommand + { + public string Command => "addunsimulatedatmos"; + public string Description => "Adds unimulated atmos support to a grid."; + public string Help => $"{Command} "; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (args.Length < 1) + { + shell.SendText(player, Help); + return; + } + + if (!int.TryParse(args[0], out var id)) + { + shell.SendText(player, $"{args[0]} is not a valid integer."); + return; + } + + var gridId = new GridId(id); + + var mapMan = IoCManager.Resolve(); + + if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp)) + { + shell.SendText(player, $"{gridId} is not a valid grid id."); + return; + } + + var entMan = IoCManager.Resolve(); + + if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid)) + { + shell.SendText(player, "Failed to get grid entity."); + return; + } + + if (grid.HasComponent()) + { + shell.SendText(player, "Grid already has an atmosphere."); + return; + } + + grid.AddComponent(); + + shell.SendText(player, $"Added unsimulated atmosphere to grid {id}."); + } + } + +} diff --git a/Content.Server/Commands/Atmos/DeleteGasCommand.cs b/Content.Server/Commands/Atmos/DeleteGasCommand.cs new file mode 100644 index 0000000000..570686d158 --- /dev/null +++ b/Content.Server/Commands/Atmos/DeleteGasCommand.cs @@ -0,0 +1,193 @@ +#nullable enable +using System; +using Content.Server.Administration; +using Content.Server.GameObjects.Components.Atmos; +using Content.Shared.Administration; +using Content.Shared.Atmos; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Map; +using Robust.Shared.IoC; +using Robust.Shared.Map; + +namespace Content.Server.Commands.Atmos +{ + [AdminCommand(AdminFlags.Debug)] + public class DeleteGasCommand : IClientCommand + { + public string Command => "deletegas"; + public string Description => "Removes all gases from a grid, or just of one type if specified."; + public string Help => $"Usage: {Command} / {Command} / {Command} / {Command}"; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + GridId gridId; + Gas? gas = null; + + switch (args.Length) + { + case 0: + if (player == null) + { + shell.SendText(player, "A grid must be specified when the command isn't used by a player."); + return; + } + + if (player.AttachedEntity == null) + { + shell.SendText(player, "You have no entity to get a grid from."); + return; + } + + gridId = player.AttachedEntity.Transform.GridID; + + if (gridId == GridId.Invalid) + { + shell.SendText(player, "You aren't on a grid to delete gas from."); + return; + } + + break; + case 1: + { + if (!int.TryParse(args[0], out var number)) + { + // Argument is a gas + if (player == null) + { + shell.SendText(player, "A grid id must be specified if not using this command as a player."); + return; + } + + if (player.AttachedEntity == null) + { + shell.SendText(player, "You have no entity from which to get a grid id."); + return; + } + + gridId = player.AttachedEntity.Transform.GridID; + + if (gridId == GridId.Invalid) + { + shell.SendText(player, "You aren't on a grid to delete gas from."); + return; + } + + if (!Enum.TryParse(args[0], true, out var parsedGas)) + { + shell.SendText(player, $"{args[0]} is not a valid gas name."); + return; + } + + gas = parsedGas; + break; + } + + // Argument is a grid + gridId = new GridId(number); + + if (gridId == GridId.Invalid) + { + shell.SendText(player, $"{gridId} is not a valid grid id."); + return; + } + + break; + } + case 2: + { + if (!int.TryParse(args[0], out var first)) + { + shell.SendText(player, $"{args[0]} is not a valid integer for a grid id."); + return; + } + + gridId = new GridId(first); + + if (gridId == GridId.Invalid) + { + shell.SendText(player, $"{gridId} is not a valid grid id."); + return; + } + + if (!Enum.TryParse(args[1], true, out var parsedGas)) + { + shell.SendText(player, $"{args[1]} is not a valid gas."); + return; + } + + gas = parsedGas; + + break; + } + default: + shell.SendText(player, Help); + return; + } + + var mapManager = IoCManager.Resolve(); + + if (!mapManager.TryGetGrid(gridId, out var grid)) + { + shell.SendText(player, $"No grid exists with id {gridId}"); + return; + } + + var entityManager = IoCManager.Resolve(); + + if (!entityManager.TryGetEntity(grid.GridEntityId, out var gridEntity)) + { + shell.SendText(player, $"Grid {gridId} has no entity."); + return; + } + + if (!gridEntity.TryGetComponent(out GridAtmosphereComponent? atmosphere)) + { + shell.SendText(player, $"Grid {gridId} has no {nameof(GridAtmosphereComponent)}"); + return; + } + + var tiles = 0; + var moles = 0f; + + if (gas == null) + { + foreach (var tile in atmosphere) + { + if (tile.Air == null || tile.Air.Immutable) continue; + + tiles++; + moles += tile.Air.TotalMoles; + + tile.Air.Clear(); + + atmosphere.Invalidate(tile.GridIndices); + } + } + else + { + foreach (var tile in atmosphere) + { + if (tile.Air == null || tile.Air.Immutable) continue; + + tiles++; + moles += tile.Air.TotalMoles; + + tile.Air.SetMoles(gas.Value, 0); + + atmosphere.Invalidate(tile.GridIndices); + } + } + + if (gas == null) + { + shell.SendText(player, $"Removed {moles} moles from {tiles} tiles."); + return; + } + + shell.SendText(player, $"Removed {moles} moles of gas {gas} from {tiles} tiles."); + } + } + +} diff --git a/Content.Server/Commands/Atmos/FillGasCommand.cs b/Content.Server/Commands/Atmos/FillGasCommand.cs new file mode 100644 index 0000000000..75dae44d6c --- /dev/null +++ b/Content.Server/Commands/Atmos/FillGasCommand.cs @@ -0,0 +1,63 @@ +#nullable enable +using Content.Server.Administration; +using Content.Server.GameObjects.Components.Atmos; +using Content.Shared.Administration; +using Content.Shared.Atmos; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Map; +using Robust.Shared.IoC; +using Robust.Shared.Map; + +namespace Content.Server.Commands.Atmos +{ + [AdminCommand(AdminFlags.Debug)] + public class FillGas : IClientCommand + { + public string Command => "fillgas"; + public string Description => "Adds gas to all tiles in a grid."; + public string Help => "fillgas "; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (args.Length < 3) return; + if(!int.TryParse(args[0], out var id) + || !(AtmosCommandUtils.TryParseGasID(args[1], out var gasId)) + || !float.TryParse(args[2], out var moles)) return; + + var gridId = new GridId(id); + + var mapMan = IoCManager.Resolve(); + + if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp)) + { + shell.SendText(player, "Invalid grid ID."); + return; + } + + var entMan = IoCManager.Resolve(); + + if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid)) + { + shell.SendText(player, "Failed to get grid entity."); + return; + } + + if (!grid.HasComponent()) + { + shell.SendText(player, "Grid doesn't have an atmosphere."); + return; + } + + var gam = grid.GetComponent(); + + foreach (var tile in gam) + { + tile.Air?.AdjustMoles(gasId, moles); + gam.Invalidate(tile.GridIndices); + } + } + } + +} diff --git a/Content.Server/Commands/Atmos/ListGasesCommand.cs b/Content.Server/Commands/Atmos/ListGasesCommand.cs new file mode 100644 index 0000000000..57c56c5420 --- /dev/null +++ b/Content.Server/Commands/Atmos/ListGasesCommand.cs @@ -0,0 +1,29 @@ +#nullable enable +using Content.Server.Administration; +using Content.Server.GameObjects.EntitySystems; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.GameObjects.Systems; + +namespace Content.Server.Commands.Atmos +{ + [AdminCommand(AdminFlags.Debug)] + public class ListGasesCommand : IClientCommand + { + public string Command => "listgases"; + public string Description => "Prints a list of gases and their indices."; + public string Help => "listgases"; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + var atmosSystem = EntitySystem.Get(); + + foreach (var gasPrototype in atmosSystem.Gases) + { + shell.SendText(player, $"{gasPrototype.Name} ID: {gasPrototype.ID}"); + } + } + } + +} diff --git a/Content.Server/Commands/Atmos/RemoveGasCommand.cs b/Content.Server/Commands/Atmos/RemoveGasCommand.cs new file mode 100644 index 0000000000..9f85a15ce7 --- /dev/null +++ b/Content.Server/Commands/Atmos/RemoveGasCommand.cs @@ -0,0 +1,80 @@ +#nullable enable +using Content.Server.Administration; +using Content.Server.GameObjects.Components.Atmos; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Map; +using Robust.Shared.IoC; +using Robust.Shared.Map; +using Robust.Shared.Maths; + +namespace Content.Server.Commands.Atmos +{ + [AdminCommand(AdminFlags.Debug)] + public class RemoveGasCommand : IClientCommand + { + public string Command => "removegas"; + public string Description => "Removes an amount of gases."; + public string Help => "removegas \nIf is true, amount will be treated as the ratio of gas to be removed."; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (args.Length < 5) return; + if(!int.TryParse(args[0], out var x) + || !int.TryParse(args[1], out var y) + || !int.TryParse(args[2], out var id) + || !float.TryParse(args[3], out var amount) + || !bool.TryParse(args[4], out var ratio)) return; + + var gridId = new GridId(id); + + var mapMan = IoCManager.Resolve(); + + if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp)) + { + shell.SendText(player, "Invalid grid ID."); + return; + } + + var entMan = IoCManager.Resolve(); + + if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid)) + { + shell.SendText(player, "Failed to get grid entity."); + return; + } + + if (!grid.HasComponent()) + { + shell.SendText(player, "Grid doesn't have an atmosphere."); + return; + } + + var gam = grid.GetComponent(); + var indices = new Vector2i(x, y); + var tile = gam.GetTile(indices); + + if (tile == null) + { + shell.SendText(player, "Invalid coordinates."); + return; + } + + if (tile.Air == null) + { + shell.SendText(player, "Can't remove gas from that tile."); + return; + } + + if (ratio) + tile.Air.RemoveRatio(amount); + else + tile.Air.Remove(amount); + + gam.Invalidate(indices); + } + } + +} diff --git a/Content.Server/Commands/Atmos/SetAtmosTemperatureCommand.cs b/Content.Server/Commands/Atmos/SetAtmosTemperatureCommand.cs new file mode 100644 index 0000000000..08fd4458ed --- /dev/null +++ b/Content.Server/Commands/Atmos/SetAtmosTemperatureCommand.cs @@ -0,0 +1,75 @@ +#nullable enable +using Content.Server.Administration; +using Content.Server.GameObjects.Components.Atmos; +using Content.Shared.Administration; +using Content.Shared.Atmos; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Map; +using Robust.Shared.IoC; +using Robust.Shared.Map; + +namespace Content.Server.Commands.Atmos +{ + [AdminCommand(AdminFlags.Debug)] + public class SetAtmosTemperatureCommand : IClientCommand + { + public string Command => "setatmostemp"; + public string Description => "Sets a grid's temperature (in kelvin)."; + public string Help => "Usage: setatmostemp "; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (args.Length < 2) return; + if(!int.TryParse(args[0], out var id) + || !float.TryParse(args[1], out var temperature)) return; + + var gridId = new GridId(id); + + var mapMan = IoCManager.Resolve(); + + if (temperature < Atmospherics.TCMB) + { + shell.SendText(player, "Invalid temperature."); + return; + } + + if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp)) + { + shell.SendText(player, "Invalid grid ID."); + return; + } + + var entMan = IoCManager.Resolve(); + + if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid)) + { + shell.SendText(player, "Failed to get grid entity."); + return; + } + + if (!grid.HasComponent()) + { + shell.SendText(player, "Grid doesn't have an atmosphere."); + return; + } + + var gam = grid.GetComponent(); + + var tiles = 0; + foreach (var tile in gam) + { + if (tile.Air == null) + continue; + + tiles++; + + tile.Air.Temperature = temperature; + gam.Invalidate(tile.GridIndices); + } + + shell.SendText(player, $"Changed the temperature of {tiles} tiles."); + } + } +} diff --git a/Content.Server/Commands/Atmos/SetTemperatureCommand.cs b/Content.Server/Commands/Atmos/SetTemperatureCommand.cs new file mode 100644 index 0000000000..0e6521e018 --- /dev/null +++ b/Content.Server/Commands/Atmos/SetTemperatureCommand.cs @@ -0,0 +1,81 @@ +#nullable enable +using Content.Server.Administration; +using Content.Server.GameObjects.Components.Atmos; +using Content.Shared.Administration; +using Content.Shared.Atmos; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Map; +using Robust.Shared.IoC; +using Robust.Shared.Map; +using Robust.Shared.Maths; + +namespace Content.Server.Commands.Atmos +{ + [AdminCommand(AdminFlags.Debug)] + public class SetTemperatureCommand : IClientCommand + { + public string Command => "settemp"; + public string Description => "Sets a tile's temperature (in kelvin)."; + public string Help => "Usage: settemp "; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (args.Length < 4) return; + if(!int.TryParse(args[0], out var x) + || !int.TryParse(args[1], out var y) + || !int.TryParse(args[2], out var id) + || !float.TryParse(args[3], out var temperature)) return; + + var gridId = new GridId(id); + + var mapMan = IoCManager.Resolve(); + + if (temperature < Atmospherics.TCMB) + { + shell.SendText(player, "Invalid temperature."); + return; + } + + if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp)) + { + shell.SendText(player, "Invalid grid ID."); + return; + } + + var entMan = IoCManager.Resolve(); + + if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid)) + { + shell.SendText(player, "Failed to get grid entity."); + return; + } + + if (!grid.HasComponent()) + { + shell.SendText(player, "Grid doesn't have an atmosphere."); + return; + } + + var gam = grid.GetComponent(); + var indices = new Vector2i(x, y); + var tile = gam.GetTile(indices); + + if (tile == null) + { + shell.SendText(player, "Invalid coordinates."); + return; + } + + if (tile.Air == null) + { + shell.SendText(player, "Can't change that tile's temperature."); + return; + } + + tile.Air.Temperature = temperature; + gam.Invalidate(indices); + } + } +} diff --git a/Content.Server/Commands/Atmos/ShowAtmosCommand.cs b/Content.Server/Commands/Atmos/ShowAtmosCommand.cs new file mode 100644 index 0000000000..01e1ccc61d --- /dev/null +++ b/Content.Server/Commands/Atmos/ShowAtmosCommand.cs @@ -0,0 +1,34 @@ +#nullable enable +using Content.Server.Administration; +using Content.Server.GameObjects.EntitySystems.Atmos; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.GameObjects.Systems; + +namespace Content.Server.Commands.Atmos +{ + [AdminCommand(AdminFlags.Debug)] + public class ShowAtmos : IClientCommand + { + public string Command => "showatmos"; + public string Description => "Toggles seeing atmos debug overlay."; + public string Help => $"Usage: {Command}"; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (player == null) + { + shell.SendText(player, "You must be a player to use this command."); + return; + } + + var atmosDebug = EntitySystem.Get(); + var enabled = atmosDebug.ToggleObserver(player); + + shell.SendText(player, enabled + ? "Enabled the atmospherics debug overlay." + : "Disabled the atmospherics debug overlay."); + } + } +} diff --git a/Content.Server/GameObjects/Components/Body/BodyCommands.cs b/Content.Server/Commands/Body/AddHandCommand.cs similarity index 61% rename from Content.Server/GameObjects/Components/Body/BodyCommands.cs rename to Content.Server/Commands/Body/AddHandCommand.cs index 66366fffb9..a448df85f7 100644 --- a/Content.Server/GameObjects/Components/Body/BodyCommands.cs +++ b/Content.Server/Commands/Body/AddHandCommand.cs @@ -1,13 +1,8 @@ #nullable enable -using System; -using System.Diagnostics.CodeAnalysis; -using System.Linq; using Content.Server.Administration; using Content.Shared.Administration; -using Content.Shared.Damage; using Content.Shared.GameObjects.Components.Body; using Content.Shared.GameObjects.Components.Body.Part; -using Content.Shared.GameObjects.Components.Damage; using Robust.Server.Interfaces.Console; using Robust.Server.Interfaces.Player; using Robust.Shared.GameObjects; @@ -17,7 +12,7 @@ using Robust.Shared.IoC; using Robust.Shared.Prototypes; using Robust.Shared.Random; -namespace Content.Server.GameObjects.Components.Body +namespace Content.Server.Commands.Body { [AdminCommand(AdminFlags.Fun)] class AddHandCommand : IClientCommand @@ -152,99 +147,4 @@ namespace Content.Server.GameObjects.Components.Body shell.SendText(player, response); } } - - [AdminCommand(AdminFlags.Fun)] - class RemoveHandCommand : IClientCommand - { - public string Command => "removehand"; - public string Description => "Removes a hand from your entity."; - public string Help => $"Usage: {Command}"; - - public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - if (player == null) - { - shell.SendText(player, "Only a player can run this command."); - return; - } - - if (player.AttachedEntity == null) - { - shell.SendText(player, "You have no entity."); - return; - } - - if (!player.AttachedEntity.TryGetComponent(out IBody? body)) - { - var random = IoCManager.Resolve(); - var text = $"You have no body{(random.Prob(0.2f) ? " and you must scream." : ".")}"; - - shell.SendText(player, text); - return; - } - - var hand = body.Parts.FirstOrDefault(x => x.Value.PartType == BodyPartType.Hand); - if (hand.Value.Equals(default)) - { - shell.SendText(player, "You have no hands."); - } - else - { - body.RemovePart(hand.Value); - } - } - } - - [AdminCommand(AdminFlags.Fun)] - class DestroyMechanismCommand : IClientCommand - { - public string Command => "destroymechanism"; - public string Description => "Destroys a mechanism from your entity"; - public string Help => $"Usage: {Command} "; - - public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - if (player == null) - { - shell.SendText(player, "Only a player can run this command."); - return; - } - - if (args.Length == 0) - { - shell.SendText(player, Help); - return; - } - - if (player.AttachedEntity == null) - { - shell.SendText(player, "You have no entity."); - return; - } - - if (!player.AttachedEntity.TryGetComponent(out IBody? body)) - { - var random = IoCManager.Resolve(); - var text = $"You have no body{(random.Prob(0.2f) ? " and you must scream." : ".")}"; - - shell.SendText(player, text); - return; - } - - var mechanismName = string.Join(" ", args).ToLowerInvariant(); - - foreach (var part in body.Parts.Values) - foreach (var mechanism in part.Mechanisms) - { - if (mechanism.Name.ToLowerInvariant() == mechanismName) - { - part.DeleteMechanism(mechanism); - shell.SendText(player, $"Mechanism with name {mechanismName} has been destroyed."); - return; - } - } - - shell.SendText(player, $"No mechanism was found with name {mechanismName}."); - } - } } diff --git a/Content.Server/Commands/Body/DestroyMechanismCommand.cs b/Content.Server/Commands/Body/DestroyMechanismCommand.cs new file mode 100644 index 0000000000..76fe801165 --- /dev/null +++ b/Content.Server/Commands/Body/DestroyMechanismCommand.cs @@ -0,0 +1,65 @@ +#nullable enable +using Content.Server.Administration; +using Content.Shared.Administration; +using Content.Shared.GameObjects.Components.Body; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.Interfaces.Random; +using Robust.Shared.IoC; +using Robust.Shared.Random; + +namespace Content.Server.Commands.Body +{ + [AdminCommand(AdminFlags.Fun)] + class DestroyMechanismCommand : IClientCommand + { + public string Command => "destroymechanism"; + public string Description => "Destroys a mechanism from your entity"; + public string Help => $"Usage: {Command} "; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (player == null) + { + shell.SendText(player, "Only a player can run this command."); + return; + } + + if (args.Length == 0) + { + shell.SendText(player, Help); + return; + } + + if (player.AttachedEntity == null) + { + shell.SendText(player, "You have no entity."); + return; + } + + if (!player.AttachedEntity.TryGetComponent(out IBody? body)) + { + var random = IoCManager.Resolve(); + var text = $"You have no body{(random.Prob(0.2f) ? " and you must scream." : ".")}"; + + shell.SendText(player, text); + return; + } + + var mechanismName = string.Join(" ", args).ToLowerInvariant(); + + foreach (var part in body.Parts.Values) + foreach (var mechanism in part.Mechanisms) + { + if (mechanism.Name.ToLowerInvariant() == mechanismName) + { + part.DeleteMechanism(mechanism); + shell.SendText(player, $"Mechanism with name {mechanismName} has been destroyed."); + return; + } + } + + shell.SendText(player, $"No mechanism was found with name {mechanismName}."); + } + } +} diff --git a/Content.Server/Commands/Body/RemoveHandCommand.cs b/Content.Server/Commands/Body/RemoveHandCommand.cs new file mode 100644 index 0000000000..090927903a --- /dev/null +++ b/Content.Server/Commands/Body/RemoveHandCommand.cs @@ -0,0 +1,56 @@ +#nullable enable +using System.Linq; +using Content.Server.Administration; +using Content.Shared.Administration; +using Content.Shared.GameObjects.Components.Body; +using Content.Shared.GameObjects.Components.Body.Part; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.Interfaces.Random; +using Robust.Shared.IoC; +using Robust.Shared.Random; + +namespace Content.Server.Commands.Body +{ + [AdminCommand(AdminFlags.Fun)] + class RemoveHandCommand : IClientCommand + { + public string Command => "removehand"; + public string Description => "Removes a hand from your entity."; + public string Help => $"Usage: {Command}"; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (player == null) + { + shell.SendText(player, "Only a player can run this command."); + return; + } + + if (player.AttachedEntity == null) + { + shell.SendText(player, "You have no entity."); + return; + } + + if (!player.AttachedEntity.TryGetComponent(out IBody? body)) + { + var random = IoCManager.Resolve(); + var text = $"You have no body{(random.Prob(0.2f) ? " and you must scream." : ".")}"; + + shell.SendText(player, text); + return; + } + + var hand = body.Parts.FirstOrDefault(x => x.Value.PartType == BodyPartType.Hand); + if (hand.Value.Equals(default)) + { + shell.SendText(player, "You have no hands."); + } + else + { + body.RemovePart(hand.Value); + } + } + } +} diff --git a/Content.Server/Commands/Chat/AdminChatCommand.cs b/Content.Server/Commands/Chat/AdminChatCommand.cs new file mode 100644 index 0000000000..9c793b2125 --- /dev/null +++ b/Content.Server/Commands/Chat/AdminChatCommand.cs @@ -0,0 +1,31 @@ +#nullable enable +using Content.Server.Administration; +using Content.Server.Interfaces.Chat; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.Chat +{ + [AdminCommand(AdminFlags.Admin)] + internal class AdminChatCommand : IClientCommand + { + public string Command => "asay"; + public string Description => "Send chat messages to the private admin chat channel."; + public string Help => "asay "; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (args.Length < 1) + return; + + var message = string.Join(" ", args).Trim(); + if (string.IsNullOrEmpty(message)) + return; + + var chat = IoCManager.Resolve(); + chat.SendAdminChat(player, message); + } + } +} diff --git a/Content.Server/Commands/Chat/MeCommand.cs b/Content.Server/Commands/Chat/MeCommand.cs new file mode 100644 index 0000000000..bb371a6c7c --- /dev/null +++ b/Content.Server/Commands/Chat/MeCommand.cs @@ -0,0 +1,49 @@ +#nullable enable +using Content.Server.Administration; +using Content.Server.Interfaces.Chat; +using Content.Server.Players; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.Enums; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.Chat +{ + [AnyCommand] + internal class MeCommand : IClientCommand + { + public string Command => "me"; + public string Description => "Perform an action."; + public string Help => "me "; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (player == null) + { + shell.SendText(player, "This command cannot be run from the server."); + return; + } + + if (player.Status != SessionStatus.InGame || !player.AttachedEntityUid.HasValue) + return; + + if (args.Length < 1) + return; + + var action = string.Join(" ", args).Trim(); + if (string.IsNullOrEmpty(action)) + return; + + var chat = IoCManager.Resolve(); + var mindComponent = player.ContentData()?.Mind; + + if (mindComponent == null) + { + shell.SendText(player, "You don't have a mind!"); + return; + } + + chat.EntityMe(mindComponent.OwnedEntity, action); + } + } +} diff --git a/Content.Server/Commands/Chat/OOCCommand.cs b/Content.Server/Commands/Chat/OOCCommand.cs new file mode 100644 index 0000000000..1c7d85ce53 --- /dev/null +++ b/Content.Server/Commands/Chat/OOCCommand.cs @@ -0,0 +1,30 @@ +#nullable enable +using Content.Server.Administration; +using Content.Server.Interfaces.Chat; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.Chat +{ + [AnyCommand] + internal class OOCCommand : IClientCommand + { + public string Command => "ooc"; + public string Description => "Send Out Of Character chat messages."; + public string Help => "ooc "; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (args.Length < 1) + return; + + var message = string.Join(" ", args).Trim(); + if (string.IsNullOrEmpty(message)) + return; + + var chat = IoCManager.Resolve(); + chat.SendOOC(player, message); + } + } +} diff --git a/Content.Server/Commands/Chat/SayCommand.cs b/Content.Server/Commands/Chat/SayCommand.cs new file mode 100644 index 0000000000..ed01c97006 --- /dev/null +++ b/Content.Server/Commands/Chat/SayCommand.cs @@ -0,0 +1,64 @@ +#nullable enable +using Content.Server.Administration; +using Content.Server.GameObjects.Components.Observer; +using Content.Server.Interfaces.Chat; +using Content.Server.Players; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.Enums; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.Chat +{ + [AnyCommand] + internal class SayCommand : IClientCommand + { + public string Command => "say"; + public string Description => "Send chat messages to the local channel or a specified radio channel."; + public string Help => "say "; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (player == null) + { + shell.SendText(player, "This command cannot be run from the server."); + return; + } + + if (player.Status != SessionStatus.InGame || !player.AttachedEntityUid.HasValue) + return; + + if (args.Length < 1) + return; + + var message = string.Join(" ", args).Trim(); + if (string.IsNullOrEmpty(message)) + return; + + var chat = IoCManager.Resolve(); + var playerEntity = player.AttachedEntity; + + if (playerEntity == null) + { + shell.SendText(player, "You don't have an entity!"); + return; + } + + if (playerEntity.HasComponent()) + chat.SendDeadChat(player, message); + else + { + var mindComponent = player.ContentData()?.Mind; + + if (mindComponent == null) + { + shell.SendText(player, "You don't have a mind!"); + return; + } + + chat.EntitySay(mindComponent.OwnedEntity, message); + } + + } + } +} diff --git a/Content.Server/Chat/ChatCommands.cs b/Content.Server/Commands/Chat/SuicideCommand.cs similarity index 54% rename from Content.Server/Chat/ChatCommands.cs rename to Content.Server/Commands/Chat/SuicideCommand.cs index e2d32aa25c..d27e555cfd 100644 --- a/Content.Server/Chat/ChatCommands.cs +++ b/Content.Server/Commands/Chat/SuicideCommand.cs @@ -1,15 +1,14 @@ -using System; +#nullable enable +using System; using System.Linq; using Content.Server.Administration; +using Content.Server.Commands.Observer; using Content.Server.GameObjects.Components.GUI; using Content.Server.GameObjects.Components.Items.Storage; -using Content.Server.GameObjects.Components.Observer; using Content.Server.Interfaces.Chat; using Content.Server.Interfaces.GameObjects; -using Content.Server.Observer; using Content.Server.Players; using Content.Server.Utility; -using Content.Shared.Administration; using Content.Shared.Damage; using Content.Shared.GameObjects.Components.Damage; using Content.Shared.Interfaces; @@ -20,108 +19,8 @@ using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Localization; -namespace Content.Server.Chat +namespace Content.Server.Commands.Chat { - [AnyCommand] - internal class SayCommand : IClientCommand - { - public string Command => "say"; - public string Description => "Send chat messages to the local channel or a specified radio channel."; - public string Help => "say "; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - if (player.Status != SessionStatus.InGame || !player.AttachedEntityUid.HasValue) - return; - - if (args.Length < 1) - return; - - var message = string.Join(" ", args).Trim(); - if (string.IsNullOrEmpty(message)) - return; - - var chat = IoCManager.Resolve(); - - if (player.AttachedEntity.HasComponent()) - chat.SendDeadChat(player, message); - else - { - var mindComponent = player.ContentData().Mind; - chat.EntitySay(mindComponent.OwnedEntity, message); - } - - } - } - - [AnyCommand] - internal class MeCommand : IClientCommand - { - public string Command => "me"; - public string Description => "Perform an action."; - public string Help => "me "; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - if (player.Status != SessionStatus.InGame || !player.AttachedEntityUid.HasValue) - return; - - if (args.Length < 1) - return; - - var action = string.Join(" ", args).Trim(); - if (string.IsNullOrEmpty(action)) - return; - - var chat = IoCManager.Resolve(); - - var mindComponent = player.ContentData().Mind; - chat.EntityMe(mindComponent.OwnedEntity, action); - } - } - - [AnyCommand] - internal class OOCCommand : IClientCommand - { - public string Command => "ooc"; - public string Description => "Send Out Of Character chat messages."; - public string Help => "ooc "; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - if (args.Length < 1) - return; - - var message = string.Join(" ", args).Trim(); - if (string.IsNullOrEmpty(message)) - return; - - var chat = IoCManager.Resolve(); - chat.SendOOC(player, message); - } - } - - [AdminCommand(AdminFlags.Admin)] - internal class AdminChatCommand : IClientCommand - { - public string Command => "asay"; - public string Description => "Send chat messages to the private admin chat channel."; - public string Help => "asay "; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - if (args.Length < 1) - return; - - var message = string.Join(" ", args).Trim(); - if (string.IsNullOrEmpty(message)) - return; - - var chat = IoCManager.Resolve(); - chat.SendAdminChat(player, message); - } - } - [AnyCommand] internal class SuicideCommand : IClientCommand { @@ -136,7 +35,7 @@ namespace Content.Server.Chat private void DealDamage(ISuicideAct suicide, IChatManager chat, IDamageableComponent damageableComponent, IEntity source, IEntity target) { - SuicideKind kind = suicide.Suicide(target, chat); + var kind = suicide.Suicide(target, chat); if (kind != SuicideKind.Special) { damageableComponent.ChangeDamage(kind switch @@ -158,23 +57,37 @@ namespace Content.Server.Chat } } - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) { + if (player == null) + { + shell.SendText(player, "You cannot run this command from the server."); + return; + } + if (player.Status != SessionStatus.InGame) return; var chat = IoCManager.Resolve(); - var owner = player.ContentData().Mind.OwnedMob.Owner; + var owner = player.ContentData()?.Mind?.OwnedMob.Owner; + + if (owner == null) + { + shell.SendText(player, "You don't have a mind!"); + return; + } + var dmgComponent = owner.GetComponent(); //TODO: needs to check if the mob is actually alive - //TODO: maybe set a suicided flag to prevent ressurection? + //TODO: maybe set a suicided flag to prevent resurrection? // Held item suicide var handsComponent = owner.GetComponent(); var itemComponent = handsComponent.GetActiveHand; if (itemComponent != null) { - ISuicideAct suicide = itemComponent.Owner.GetAllComponents().FirstOrDefault(); + var suicide = itemComponent.Owner.GetAllComponents().FirstOrDefault(); + if (suicide != null) { DealDamage(suicide, chat, dmgComponent, itemComponent.Owner, owner); @@ -182,8 +95,9 @@ namespace Content.Server.Chat } } // Get all entities in range of the suicider - var entities = owner.EntityManager.GetEntitiesInRange(owner, 1, true); - if (entities.Count() > 0) + var entities = owner.EntityManager.GetEntitiesInRange(owner, 1, true).ToArray(); + + if (entities.Length > 0) { foreach (var entity in entities) { diff --git a/Content.Server/Commands/Damage/AddDamageFlagCommand.cs b/Content.Server/Commands/Damage/AddDamageFlagCommand.cs new file mode 100644 index 0000000000..21d353b078 --- /dev/null +++ b/Content.Server/Commands/Damage/AddDamageFlagCommand.cs @@ -0,0 +1,27 @@ +#nullable enable +using Content.Server.Administration; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; + +namespace Content.Server.Commands.Damage +{ + [AdminCommand(AdminFlags.Fun)] + public class AddDamageFlagCommand : DamageFlagCommand + { + public override string Command => "adddamageflag"; + public override string Description => "Adds a damage flag to your entity or another."; + public override string Help => $"Usage: {Command} / {Command} "; + + public override void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (!TryGetEntity(shell, player, args, true, out var entity, out var flag, out var damageable)) + { + return; + } + + damageable.AddFlag(flag); + shell.SendText(player, $"Added damage flag {flag} to entity {entity.Name}"); + } + } +} diff --git a/Content.Server/GameObjects/Components/Damage/DamageCommands.cs b/Content.Server/Commands/Damage/DamageFlagCommand.cs similarity index 50% rename from Content.Server/GameObjects/Components/Damage/DamageCommands.cs rename to Content.Server/Commands/Damage/DamageFlagCommand.cs index 820c858db5..1edf0e973b 100644 --- a/Content.Server/GameObjects/Components/Damage/DamageCommands.cs +++ b/Content.Server/Commands/Damage/DamageFlagCommand.cs @@ -1,18 +1,14 @@ #nullable enable using System; using System.Diagnostics.CodeAnalysis; -using Content.Server.Administration; -using Content.Server.GameObjects.EntitySystems; -using Content.Shared.Administration; using Content.Shared.GameObjects.Components.Damage; using Robust.Server.Interfaces.Console; using Robust.Server.Interfaces.Player; using Robust.Shared.GameObjects; -using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.IoC; -namespace Content.Server.GameObjects.Components.Damage +namespace Content.Server.Commands.Damage { public abstract class DamageFlagCommand : IClientCommand { @@ -117,100 +113,4 @@ namespace Content.Server.GameObjects.Components.Damage return true; } } - - [AdminCommand(AdminFlags.Fun)] - public class AddDamageFlagCommand : DamageFlagCommand - { - public override string Command => "adddamageflag"; - public override string Description => "Adds a damage flag to your entity or another."; - public override string Help => $"Usage: {Command} / {Command} "; - - public override void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - if (!TryGetEntity(shell, player, args, true, out var entity, out var flag, out var damageable)) - { - return; - } - - damageable.AddFlag(flag); - shell.SendText(player, $"Added damage flag {flag} to entity {entity.Name}"); - } - } - - [AdminCommand(AdminFlags.Fun)] - public class RemoveDamageFlagCommand : DamageFlagCommand - { - public override string Command => "removedamageflag"; - public override string Description => "Removes a damage flag from your entity or another."; - public override string Help => $"Usage: {Command} / {Command} "; - - public override void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - if (!TryGetEntity(shell, player, args, false, out var entity, out var flag, out var damageable)) - { - return; - } - - damageable.RemoveFlag(flag); - shell.SendText(player, $"Removed damage flag {flag} from entity {entity.Name}"); - } - } - - [AdminCommand(AdminFlags.Admin)] - public class GodModeCommand : IClientCommand - { - public string Command => "godmode"; - public string Description => "Makes your entity or another invulnerable to almost anything. May have irreversible changes."; - public string Help => $"Usage: {Command} / {Command} "; - - public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - IEntity entity; - - switch (args.Length) - { - case 0: - if (player == null) - { - shell.SendText(player, "An entity needs to be specified when the command isn't used by a player."); - return; - } - - if (player.AttachedEntity == null) - { - shell.SendText(player, "An entity needs to be specified when you aren't attached to an entity."); - return; - } - - entity = player.AttachedEntity; - break; - case 1: - if (!EntityUid.TryParse(args[0], out var id)) - { - shell.SendText(player, $"{args[0]} isn't a valid entity id."); - return; - } - - var entityManager = IoCManager.Resolve(); - if (!entityManager.TryGetEntity(id, out var parsedEntity)) - { - shell.SendText(player, $"No entity found with id {id}."); - return; - } - - entity = parsedEntity; - break; - default: - shell.SendText(player, Help); - return; - } - - var godmodeSystem = EntitySystem.Get(); - var enabled = godmodeSystem.ToggleGodmode(entity); - - shell.SendText(player, enabled - ? $"Enabled godmode for entity {entity.Name} with id {entity.Uid}" - : $"Disabled godmode for entity {entity.Name} with id {entity.Uid}"); - } - } } diff --git a/Content.Server/Commands/Damage/GodModeCommand.cs b/Content.Server/Commands/Damage/GodModeCommand.cs new file mode 100644 index 0000000000..77c05fc24c --- /dev/null +++ b/Content.Server/Commands/Damage/GodModeCommand.cs @@ -0,0 +1,71 @@ +#nullable enable +using Content.Server.Administration; +using Content.Server.GameObjects.EntitySystems; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.Damage +{ + [AdminCommand(AdminFlags.Admin)] + public class GodModeCommand : IClientCommand + { + public string Command => "godmode"; + public string Description => "Makes your entity or another invulnerable to almost anything. May have irreversible changes."; + public string Help => $"Usage: {Command} / {Command} "; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + IEntity entity; + + switch (args.Length) + { + case 0: + if (player == null) + { + shell.SendText(player, "An entity needs to be specified when the command isn't used by a player."); + return; + } + + if (player.AttachedEntity == null) + { + shell.SendText(player, "An entity needs to be specified when you aren't attached to an entity."); + return; + } + + entity = player.AttachedEntity; + break; + case 1: + if (!EntityUid.TryParse(args[0], out var id)) + { + shell.SendText(player, $"{args[0]} isn't a valid entity id."); + return; + } + + var entityManager = IoCManager.Resolve(); + if (!entityManager.TryGetEntity(id, out var parsedEntity)) + { + shell.SendText(player, $"No entity found with id {id}."); + return; + } + + entity = parsedEntity; + break; + default: + shell.SendText(player, Help); + return; + } + + var godmodeSystem = EntitySystem.Get(); + var enabled = godmodeSystem.ToggleGodmode(entity); + + shell.SendText(player, enabled + ? $"Enabled godmode for entity {entity.Name} with id {entity.Uid}" + : $"Disabled godmode for entity {entity.Name} with id {entity.Uid}"); + } + } +} diff --git a/Content.Server/Commands/Damage/RemoveDamageFlagCommand.cs b/Content.Server/Commands/Damage/RemoveDamageFlagCommand.cs new file mode 100644 index 0000000000..631eaae370 --- /dev/null +++ b/Content.Server/Commands/Damage/RemoveDamageFlagCommand.cs @@ -0,0 +1,27 @@ +#nullable enable +using Content.Server.Administration; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; + +namespace Content.Server.Commands.Damage +{ + [AdminCommand(AdminFlags.Fun)] + public class RemoveDamageFlagCommand : DamageFlagCommand + { + public override string Command => "removedamageflag"; + public override string Description => "Removes a damage flag from your entity or another."; + public override string Help => $"Usage: {Command} / {Command} "; + + public override void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (!TryGetEntity(shell, player, args, false, out var entity, out var flag, out var damageable)) + { + return; + } + + damageable.RemoveFlag(flag); + shell.SendText(player, $"Removed damage flag {flag} from entity {entity.Name}"); + } + } +} diff --git a/Content.Server/GameObjects/Components/Disposal/DisposalCommands.cs b/Content.Server/Commands/Disposal/TubeConnectionsCommand.cs similarity index 95% rename from Content.Server/GameObjects/Components/Disposal/DisposalCommands.cs rename to Content.Server/Commands/Disposal/TubeConnectionsCommand.cs index 2f549a8037..eb13975d74 100644 --- a/Content.Server/GameObjects/Components/Disposal/DisposalCommands.cs +++ b/Content.Server/Commands/Disposal/TubeConnectionsCommand.cs @@ -1,5 +1,6 @@ #nullable enable using Content.Server.Administration; +using Content.Server.GameObjects.Components.Disposal; using Content.Shared.Administration; using Robust.Server.Interfaces.Console; using Robust.Server.Interfaces.Player; @@ -8,7 +9,7 @@ using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Localization; -namespace Content.Server.GameObjects.Components.Disposal +namespace Content.Server.Commands.Disposal { [AdminCommand(AdminFlags.Debug)] public class TubeConnectionsCommand : IClientCommand diff --git a/Content.Server/Commands/GameTicking/DelayStartCommand.cs b/Content.Server/Commands/GameTicking/DelayStartCommand.cs new file mode 100644 index 0000000000..ff9a219d58 --- /dev/null +++ b/Content.Server/Commands/GameTicking/DelayStartCommand.cs @@ -0,0 +1,54 @@ +using System; +using Content.Server.Administration; +using Content.Server.GameTicking; +using Content.Server.Interfaces.GameTicking; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.GameTicking +{ + [AdminCommand(AdminFlags.Server)] + class DelayStartCommand : IClientCommand + { + public string Command => "delaystart"; + public string Description => "Delays the round start."; + public string Help => $"Usage: {Command} \nPauses/Resumes the countdown if no argument is provided."; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + var ticker = IoCManager.Resolve(); + if (ticker.RunLevel != GameRunLevel.PreRoundLobby) + { + shell.SendText(player, "This can only be executed while the game is in the pre-round lobby."); + return; + } + + if (args.Length == 0) + { + var paused = ticker.TogglePause(); + shell.SendText(player, paused ? "Paused the countdown." : "Resumed the countdown."); + return; + } + + if (args.Length != 1) + { + shell.SendText(player, "Need zero or one arguments."); + return; + } + + if (!uint.TryParse(args[0], out var seconds) || seconds == 0) + { + shell.SendText(player, $"{args[0]} isn't a valid amount of seconds."); + return; + } + + var time = TimeSpan.FromSeconds(seconds); + if (!ticker.DelayStart(time)) + { + shell.SendText(player, "An unknown error has occurred."); + } + } + } +} \ No newline at end of file diff --git a/Content.Server/Commands/GameTicking/EndRoundCommand.cs b/Content.Server/Commands/GameTicking/EndRoundCommand.cs new file mode 100644 index 0000000000..b274ed61cf --- /dev/null +++ b/Content.Server/Commands/GameTicking/EndRoundCommand.cs @@ -0,0 +1,32 @@ +using System; +using Content.Server.Administration; +using Content.Server.GameTicking; +using Content.Server.Interfaces.GameTicking; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.GameTicking +{ + [AdminCommand(AdminFlags.Server)] + class EndRoundCommand : IClientCommand + { + public string Command => "endround"; + public string Description => "Ends the round and moves the server to PostRound."; + public string Help => String.Empty; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + var ticker = IoCManager.Resolve(); + + if (ticker.RunLevel != GameRunLevel.InRound) + { + shell.SendText(player, "This can only be executed while the game is in a round."); + return; + } + + ticker.EndRound(); + } + } +} \ No newline at end of file diff --git a/Content.Server/Commands/GameTicking/ForcePresetCommand.cs b/Content.Server/Commands/GameTicking/ForcePresetCommand.cs new file mode 100644 index 0000000000..06c7cd67e4 --- /dev/null +++ b/Content.Server/Commands/GameTicking/ForcePresetCommand.cs @@ -0,0 +1,44 @@ +using Content.Server.Administration; +using Content.Server.GameTicking; +using Content.Server.Interfaces.GameTicking; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.GameTicking +{ + [AdminCommand(AdminFlags.Server)] + class ForcePresetCommand : IClientCommand + { + public string Command => "forcepreset"; + public string Description => "Forces a specific game preset to start for the current lobby."; + public string Help => $"Usage: {Command} "; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + var ticker = IoCManager.Resolve(); + if (ticker.RunLevel != GameRunLevel.PreRoundLobby) + { + shell.SendText(player, "This can only be executed while the game is in the pre-round lobby."); + return; + } + + if (args.Length != 1) + { + shell.SendText(player, "Need exactly one argument."); + return; + } + + var name = args[0]; + if (!ticker.TryGetPreset(name, out var type)) + { + shell.SendText(player, $"No preset exists with name {name}."); + return; + } + + ticker.SetStartPreset(type, true); + shell.SendText(player, $"Forced the game to start with preset {name}."); + } + } +} \ No newline at end of file diff --git a/Content.Server/Commands/GameTicking/JoinGameCommand.cs b/Content.Server/Commands/GameTicking/JoinGameCommand.cs new file mode 100644 index 0000000000..95006d5781 --- /dev/null +++ b/Content.Server/Commands/GameTicking/JoinGameCommand.cs @@ -0,0 +1,58 @@ +using System.Collections.Generic; +using Content.Server.Administration; +using Content.Server.GameTicking; +using Content.Server.Interfaces.GameTicking; +using Content.Shared.Roles; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; +using Robust.Shared.Prototypes; + +namespace Content.Server.Commands.GameTicking +{ + [AnyCommand] + class JoinGameCommand : IClientCommand + { + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + + public string Command => "joingame"; + public string Description => ""; + public string Help => ""; + + public JoinGameCommand() + { + IoCManager.InjectDependencies(this); + } + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + var output = string.Join(".", args); + if (player == null) + { + return; + } + + var ticker = IoCManager.Resolve(); + if (ticker.RunLevel == GameRunLevel.PreRoundLobby) + { + shell.SendText(player, "Round has not started."); + return; + } + else if(ticker.RunLevel == GameRunLevel.InRound) + { + string ID = args[0]; + var positions = ticker.GetAvailablePositions(); + + if(positions.GetValueOrDefault(ID, 0) == 0) //n < 0 is treated as infinite + { + var jobPrototype = _prototypeManager.Index(ID); + shell.SendText(player, $"{jobPrototype.Name} has no available slots."); + return; + } + ticker.MakeJoinGame(player, args[0].ToString()); + return; + } + + ticker.MakeJoinGame(player, null); + } + } +} \ No newline at end of file diff --git a/Content.Server/Commands/GameTicking/MappingCommand.cs b/Content.Server/Commands/GameTicking/MappingCommand.cs new file mode 100644 index 0000000000..985362de9d --- /dev/null +++ b/Content.Server/Commands/GameTicking/MappingCommand.cs @@ -0,0 +1,68 @@ +using System.Linq; +using Content.Server.Administration; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.Interfaces.Map; +using Robust.Shared.IoC; +using Robust.Shared.Utility; + +namespace Content.Server.Commands.GameTicking +{ + [AdminCommand(AdminFlags.Server | AdminFlags.Mapping)] + class MappingCommand : IClientCommand + { + public string Command => "mapping"; + public string Description => "Creates and teleports you to a new uninitialized map for mapping."; + public string Help => $"Usage: {Command} / {Command} "; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + if (player == null) + { + shell.SendText(player, "Only players can use this command"); + return; + } + + var mapManager = IoCManager.Resolve(); + int mapId; + string mapName; + + switch (args.Length) + { + case 1: + if (player.AttachedEntity == null) + { + shell.SendText(player, "The map name argument cannot be omitted if you have no entity."); + return; + } + + mapId = (int) mapManager.NextMapId(); + mapName = args[0]; + break; + case 2: + if (!int.TryParse(args[0], out var id)) + { + shell.SendText(player, $"{args[0]} is not a valid integer."); + return; + } + + mapId = id; + mapName = args[1]; + break; + default: + shell.SendText(player, Help); + return; + } + + shell.ExecuteCommand(player, $"addmap {mapId} false"); + shell.ExecuteCommand(player, $"loadbp {mapId} \"{CommandParsing.Escape(mapName)}\""); + shell.ExecuteCommand(player, "aghost"); + shell.ExecuteCommand(player, $"tp 0 0 {mapId}"); + + var newGridId = mapManager.GetAllGrids().Max(g => (int) g.Index); + + shell.SendText(player, $"Created unloaded map from file {mapName} with id {mapId}. Use \"savebp {newGridId} foo.yml\" to save the new grid as a map."); + } + } +} \ No newline at end of file diff --git a/Content.Server/Commands/GameTicking/NewRoundCommand.cs b/Content.Server/Commands/GameTicking/NewRoundCommand.cs new file mode 100644 index 0000000000..da10407a77 --- /dev/null +++ b/Content.Server/Commands/GameTicking/NewRoundCommand.cs @@ -0,0 +1,24 @@ +using System; +using Content.Server.Administration; +using Content.Server.Interfaces.GameTicking; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.GameTicking +{ + [AdminCommand(AdminFlags.Server)] + public class NewRoundCommand : IClientCommand + { + public string Command => "restartround"; + public string Description => "Moves the server from PostRound to a new PreRoundLobby."; + public string Help => String.Empty; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + var ticker = IoCManager.Resolve(); + ticker.RestartRound(); + } + } +} \ No newline at end of file diff --git a/Content.Server/Commands/GameTicking/ObserveCommand.cs b/Content.Server/Commands/GameTicking/ObserveCommand.cs new file mode 100644 index 0000000000..4596418418 --- /dev/null +++ b/Content.Server/Commands/GameTicking/ObserveCommand.cs @@ -0,0 +1,27 @@ +using Content.Server.Administration; +using Content.Server.Interfaces.GameTicking; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.GameTicking +{ + [AnyCommand] + class ObserveCommand : IClientCommand + { + public string Command => "observe"; + public string Description => ""; + public string Help => ""; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + if (player == null) + { + return; + } + + var ticker = IoCManager.Resolve(); + ticker.MakeObserve(player); + } + } +} \ No newline at end of file diff --git a/Content.Server/Commands/GameTicking/RespawnCommand.cs b/Content.Server/Commands/GameTicking/RespawnCommand.cs new file mode 100644 index 0000000000..94286c3bcd --- /dev/null +++ b/Content.Server/Commands/GameTicking/RespawnCommand.cs @@ -0,0 +1,61 @@ +using Content.Server.Interfaces.GameTicking; +using Content.Server.Players; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; +using Robust.Shared.Network; + +namespace Content.Server.Commands.GameTicking +{ + class RespawnCommand : IClientCommand + { + public string Command => "respawn"; + public string Description => "Respawns a player, kicking them back to the lobby."; + public string Help => "respawn [player]"; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + if (args.Length > 1) + { + shell.SendText(player, "Must provide <= 1 argument."); + return; + } + + var playerMgr = IoCManager.Resolve(); + var ticker = IoCManager.Resolve(); + + NetUserId userId; + if (args.Length == 0) + { + if (player == null) + { + shell.SendText((IPlayerSession)null, "If not a player, an argument must be given."); + return; + } + + userId = player.UserId; + } + else if (!playerMgr.TryGetUserId(args[0], out userId)) + { + shell.SendText(player, "Unknown player"); + return; + } + + if (!playerMgr.TryGetSessionById(userId, out var targetPlayer)) + { + if (!playerMgr.TryGetPlayerData(userId, out var data)) + { + shell.SendText(player, "Unknown player"); + return; + } + + data.ContentData().WipeMind(); + shell.SendText(player, + "Player is not currently online, but they will respawn if they come back online"); + return; + } + + ticker.Respawn(targetPlayer); + } + } +} \ No newline at end of file diff --git a/Content.Server/Commands/GameTicking/SetGamePresetCommand.cs b/Content.Server/Commands/GameTicking/SetGamePresetCommand.cs new file mode 100644 index 0000000000..5a5c1c7f90 --- /dev/null +++ b/Content.Server/Commands/GameTicking/SetGamePresetCommand.cs @@ -0,0 +1,30 @@ +using Content.Server.Administration; +using Content.Server.Interfaces.GameTicking; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.GameTicking +{ + [AdminCommand(AdminFlags.Server)] + class SetGamePresetCommand : IClientCommand + { + public string Command => "setgamepreset"; + public string Description => ""; + public string Help => ""; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + if (args.Length != 1) + { + shell.SendText(player, "Need exactly one argument."); + return; + } + + var ticker = IoCManager.Resolve(); + + ticker.SetStartPreset(args[0]); + } + } +} \ No newline at end of file diff --git a/Content.Server/Commands/GameTicking/StartRoundCommand.cs b/Content.Server/Commands/GameTicking/StartRoundCommand.cs new file mode 100644 index 0000000000..b8f3804bbe --- /dev/null +++ b/Content.Server/Commands/GameTicking/StartRoundCommand.cs @@ -0,0 +1,32 @@ +using System; +using Content.Server.Administration; +using Content.Server.GameTicking; +using Content.Server.Interfaces.GameTicking; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.GameTicking +{ + [AdminCommand(AdminFlags.Server)] + class StartRoundCommand : IClientCommand + { + public string Command => "startround"; + public string Description => "Ends PreRoundLobby state and starts the round."; + public string Help => String.Empty; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + var ticker = IoCManager.Resolve(); + + if (ticker.RunLevel != GameRunLevel.PreRoundLobby) + { + shell.SendText(player, "This can only be executed while the game is in the pre-round lobby."); + return; + } + + ticker.StartRound(); + } + } +} \ No newline at end of file diff --git a/Content.Server/Commands/GameTicking/TileWallsCommand.cs b/Content.Server/Commands/GameTicking/TileWallsCommand.cs new file mode 100644 index 0000000000..668ea461c1 --- /dev/null +++ b/Content.Server/Commands/GameTicking/TileWallsCommand.cs @@ -0,0 +1,112 @@ +using Content.Server.Administration; +using Content.Shared.Administration; +using Content.Shared.Maps; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.GameObjects.Components.Transform; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Map; +using Robust.Shared.IoC; +using Robust.Shared.Map; + +namespace Content.Server.Commands.GameTicking +{ + [AdminCommand(AdminFlags.Mapping)] + class TileWallsCommand : IClientCommand + { + // ReSharper disable once StringLiteralTypo + public string Command => "tilewalls"; + public string Description => "Puts an underplating tile below every wall on a grid."; + public string Help => $"Usage: {Command} | {Command}"; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + GridId gridId; + + switch (args.Length) + { + case 0: + if (player?.AttachedEntity == null) + { + shell.SendText((IPlayerSession) null, "Only a player can run this command."); + return; + } + + gridId = player.AttachedEntity.Transform.GridID; + break; + case 1: + if (!int.TryParse(args[0], out var id)) + { + shell.SendText(player, $"{args[0]} is not a valid integer."); + return; + } + + gridId = new GridId(id); + break; + default: + shell.SendText(player, Help); + return; + } + + var mapManager = IoCManager.Resolve(); + if (!mapManager.TryGetGrid(gridId, out var grid)) + { + shell.SendText(player, $"No grid exists with id {gridId}"); + return; + } + + var entityManager = IoCManager.Resolve(); + if (!entityManager.TryGetEntity(grid.GridEntityId, out var gridEntity)) + { + shell.SendText(player, $"Grid {gridId} doesn't have an associated grid entity."); + return; + } + + var tileDefinitionManager = IoCManager.Resolve(); + var underplating = tileDefinitionManager["underplating"]; + var underplatingTile = new Tile(underplating.TileId); + var changed = 0; + foreach (var childUid in gridEntity.Transform.ChildEntityUids) + { + if (!entityManager.TryGetEntity(childUid, out var childEntity)) + { + continue; + } + + var prototype = childEntity.Prototype; + while (true) + { + if (prototype?.Parent == null) + { + break; + } + + prototype = prototype.Parent; + } + + if (prototype?.ID != "base_wall") + { + continue; + } + + if (!childEntity.TryGetComponent(out SnapGridComponent snapGrid)) + { + continue; + } + + var tile = grid.GetTileRef(childEntity.Transform.Coordinates); + var tileDef = (ContentTileDefinition) tileDefinitionManager[tile.Tile.TypeId]; + + if (tileDef.Name == "underplating") + { + continue; + } + + grid.SetTile(childEntity.Transform.Coordinates, underplatingTile); + changed++; + } + + shell.SendText(player, $"Changed {changed} tiles."); + } + } +} diff --git a/Content.Server/Commands/GameTicking/ToggleDisallowLateJoinCommand.cs b/Content.Server/Commands/GameTicking/ToggleDisallowLateJoinCommand.cs new file mode 100644 index 0000000000..ffb1be19c0 --- /dev/null +++ b/Content.Server/Commands/GameTicking/ToggleDisallowLateJoinCommand.cs @@ -0,0 +1,38 @@ +using Content.Server.Administration; +using Content.Server.Interfaces.GameTicking; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.GameTicking +{ + [AdminCommand(AdminFlags.Server)] + class ToggleDisallowLateJoinCommand : IClientCommand + { + public string Command => "toggledisallowlatejoin"; + public string Description => "Allows or disallows latejoining during mid-game."; + public string Help => $"Usage: {Command} "; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + if (args.Length != 1) + { + shell.SendText(player, "Need exactly one argument."); + return; + } + + var ticker = IoCManager.Resolve(); + + if (bool.TryParse(args[0], out var result)) + { + ticker.ToggleDisallowLateJoin(bool.Parse(args[0])); + shell.SendText(player, result ? "Late joining has been disabled." : "Late joining has been enabled."); + } + else + { + shell.SendText(player, "Invalid argument."); + } + } + } +} diff --git a/Content.Server/Commands/GameTicking/ToggleReadyCommand.cs b/Content.Server/Commands/GameTicking/ToggleReadyCommand.cs new file mode 100644 index 0000000000..0f56e148ce --- /dev/null +++ b/Content.Server/Commands/GameTicking/ToggleReadyCommand.cs @@ -0,0 +1,27 @@ +using Content.Server.Administration; +using Content.Server.Interfaces.GameTicking; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.GameTicking +{ + [AnyCommand] + class ToggleReadyCommand : IClientCommand + { + public string Command => "toggleready"; + public string Description => ""; + public string Help => ""; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + if (player == null) + { + return; + } + + var ticker = IoCManager.Resolve(); + ticker.ToggleReady(player, bool.Parse(args[0])); + } + } +} \ No newline at end of file diff --git a/Content.Server/Commands/Interactable/AnchorCommand.cs b/Content.Server/Commands/Interactable/AnchorCommand.cs new file mode 100644 index 0000000000..c84637ebb9 --- /dev/null +++ b/Content.Server/Commands/Interactable/AnchorCommand.cs @@ -0,0 +1,57 @@ +#nullable enable +using System.Linq; +using Content.Server.Administration; +using Content.Server.GameObjects.Components; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.GameObjects; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.Interactable +{ + [AdminCommand(AdminFlags.Debug)] + class AnchorCommand : IClientCommand + { + public string Command => "anchor"; + public string Description => "Anchors all entities in a radius around the user"; + public string Help => $"Usage: {Command} "; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (player?.AttachedEntity == null) + { + return; + } + + if (args.Length != 1) + { + shell.SendText(player, Help); + return; + } + + if (!int.TryParse(args[0], out var radius)) + { + shell.SendText(player, $"{args[0]} isn't a valid integer."); + return; + } + + if (radius < 0) + { + shell.SendText(player, "Radius must be positive."); + return; + } + + var serverEntityManager = IoCManager.Resolve(); + var entities = serverEntityManager.GetEntitiesInRange(player.AttachedEntity, radius).ToList(); + + foreach (var entity in entities) + { + if (entity.TryGetComponent(out AnchorableComponent? anchorable)) + { + _ = anchorable.TryAnchor(player.AttachedEntity, force: true); + } + } + } + } +} diff --git a/Content.Server/Commands/Interactable/TilePryCommand.cs b/Content.Server/Commands/Interactable/TilePryCommand.cs new file mode 100644 index 0000000000..06c390373b --- /dev/null +++ b/Content.Server/Commands/Interactable/TilePryCommand.cs @@ -0,0 +1,71 @@ +#nullable enable +using Content.Server.Administration; +using Content.Server.GameObjects.Components.Interactable; +using Content.Shared.Administration; +using Content.Shared.Maps; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.Interfaces.Map; +using Robust.Shared.IoC; +using Robust.Shared.Map; + +namespace Content.Server.Commands.Interactable +{ + /// + /// + /// + [AdminCommand(AdminFlags.Debug)] + class TilePryCommand : IClientCommand + { + public string Command => "tilepry"; + public string Description => "Pries up all tiles in a radius around the user."; + public string Help => $"Usage: {Command} "; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (player?.AttachedEntity == null) + { + return; + } + + if (args.Length != 1) + { + shell.SendText(player, Help); + return; + } + + if (!int.TryParse(args[0], out var radius)) + { + shell.SendText(player, $"{args[0]} isn't a valid integer."); + return; + } + + if (radius < 0) + { + shell.SendText(player, "Radius must be positive."); + return; + } + + var mapManager = IoCManager.Resolve(); + var playerGrid = player.AttachedEntity.Transform.GridID; + var mapGrid = mapManager.GetGrid(playerGrid); + var playerPosition = player.AttachedEntity.Transform.Coordinates; + var tileDefinitionManager = IoCManager.Resolve(); + + for (var i = -radius; i <= radius; i++) + { + for (var j = -radius; j <= radius; j++) + { + var tile = mapGrid.GetTileRef(playerPosition.Offset((i, j))); + var coordinates = mapGrid.GridTileToLocal(tile.GridIndices); + var tileDef = (ContentTileDefinition) tileDefinitionManager[tile.Tile.TypeId]; + + if (!tileDef.CanCrowbar) continue; + + var underplating = tileDefinitionManager["underplating"]; + mapGrid.SetTile(coordinates, new Tile(underplating.TileId)); + } + } + } + } +} diff --git a/Content.Server/Commands/Interactable/UnAnchorCommand.cs b/Content.Server/Commands/Interactable/UnAnchorCommand.cs new file mode 100644 index 0000000000..3eca799b2e --- /dev/null +++ b/Content.Server/Commands/Interactable/UnAnchorCommand.cs @@ -0,0 +1,57 @@ +#nullable enable +using System.Linq; +using Content.Server.Administration; +using Content.Server.GameObjects.Components; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.GameObjects; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.Interactable +{ + [AdminCommand(AdminFlags.Debug)] + class UnAnchorCommand : IClientCommand + { + public string Command => "unanchor"; + public string Description => "Unanchors all anchorable entities in a radius around the user"; + public string Help => $"Usage: {Command} "; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (player?.AttachedEntity == null) + { + return; + } + + if (args.Length != 1) + { + shell.SendText(player, Help); + return; + } + + if (!int.TryParse(args[0], out var radius)) + { + shell.SendText(player, $"{args[0]} isn't a valid integer."); + return; + } + + if (radius < 0) + { + shell.SendText(player, "Radius must be positive."); + return; + } + + var serverEntityManager = IoCManager.Resolve(); + var entities = serverEntityManager.GetEntitiesInRange(player.AttachedEntity, radius).ToList(); + + foreach (var entity in entities) + { + if (entity.TryGetComponent(out AnchorableComponent? anchorable)) + { + _ = anchorable.TryUnAnchor(player.AttachedEntity, force: true); + } + } + } + } +} diff --git a/Content.Server/Commands/MachineLinking/SignalLinkerCommand.cs b/Content.Server/Commands/MachineLinking/SignalLinkerCommand.cs new file mode 100644 index 0000000000..a836885fe5 --- /dev/null +++ b/Content.Server/Commands/MachineLinking/SignalLinkerCommand.cs @@ -0,0 +1,49 @@ +using Content.Server.Administration; +using Content.Server.GameObjects.EntitySystems; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.MachineLinking +{ + [AdminCommand(AdminFlags.Debug)] + public class SignalLinkerCommand : IClientCommand + { + public string Command => "signallink"; + + public string Description => "Turns on signal linker mode. Click a transmitter to tune that signal and then click on each receiver to tune them to the transmitter signal."; + + public string Help => "signallink (on/off)"; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + bool? enable = null; + if (args.Length > 0) + { + if (args[0] == "on") + enable = true; + else if (args[0] == "off") + enable = false; + else if (bool.TryParse(args[0], out var boolean)) + enable = boolean; + else if (int.TryParse(args[0], out var num)) + { + if (num == 1) + enable = true; + else if (num == 0) + enable = false; + } + } + + if (!IoCManager.Resolve().TryGetEntitySystem(out var system)) + { + return; + } + + var ret = system.SignalLinkerKeybind(player.UserId, enable); + shell.SendText(player, ret ? "Enabled" : "Disabled"); + } + } +} \ No newline at end of file diff --git a/Content.Server/Commands/Mobs/AddOverlayCommand.cs b/Content.Server/Commands/Mobs/AddOverlayCommand.cs new file mode 100644 index 0000000000..4bbf196e48 --- /dev/null +++ b/Content.Server/Commands/Mobs/AddOverlayCommand.cs @@ -0,0 +1,33 @@ +using Content.Server.Administration; +using Content.Server.GameObjects.Components.Mobs; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; + +namespace Content.Server.Commands.Mobs +{ + [AdminCommand(AdminFlags.Debug)] + public class AddOverlayCommand : IClientCommand + { + public string Command => "addoverlay"; + public string Description => "Adds an overlay by its ID"; + public string Help => "addoverlay "; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + if (args.Length != 1) + { + shell.SendText(player, "Expected 1 argument."); + return; + } + + if (player?.AttachedEntity != null) + { + if (player.AttachedEntity.TryGetComponent(out ServerOverlayEffectsComponent overlayEffectsComponent)) + { + overlayEffectsComponent.AddOverlay(args[0]); + } + } + } + } +} \ No newline at end of file diff --git a/Content.Server/Commands/Mobs/AddRoleCommand.cs b/Content.Server/Commands/Mobs/AddRoleCommand.cs new file mode 100644 index 0000000000..af714411f1 --- /dev/null +++ b/Content.Server/Commands/Mobs/AddRoleCommand.cs @@ -0,0 +1,45 @@ +using Content.Server.Administration; +using Content.Server.Mobs.Roles; +using Content.Server.Players; +using Content.Shared.Administration; +using Content.Shared.Roles; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; +using Robust.Shared.Prototypes; + +namespace Content.Server.Commands.Mobs +{ + [AdminCommand(AdminFlags.Fun)] + public class AddRoleCommand : IClientCommand + { + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + + public string Command => "addrole"; + + public string Description => "Adds a role to a player's mind."; + + public string Help => "addrole \nThat role type is the actual C# type name."; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + if (args.Length != 2) + { + shell.SendText(player, "Expected exactly 2 arguments."); + return; + } + + var mgr = IoCManager.Resolve(); + if (mgr.TryGetPlayerDataByUsername(args[0], out var data)) + { + var mind = data.ContentData().Mind; + var role = new Job(mind, _prototypeManager.Index(args[1])); + mind.AddRole(role); + } + else + { + shell.SendText(player, "Can't find that mind"); + } + } + } +} \ No newline at end of file diff --git a/Content.Server/Commands/Mobs/MindInfoCommand.cs b/Content.Server/Commands/Mobs/MindInfoCommand.cs new file mode 100644 index 0000000000..9a546b7ce9 --- /dev/null +++ b/Content.Server/Commands/Mobs/MindInfoCommand.cs @@ -0,0 +1,48 @@ +using System.Text; +using Content.Server.Administration; +using Content.Server.Players; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.Mobs +{ + [AdminCommand(AdminFlags.Admin)] + public class MindInfoCommand : IClientCommand + { + public string Command => "mindinfo"; + + public string Description => "Lists info for the mind of a specific player."; + + public string Help => "mindinfo "; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + if (args.Length != 1) + { + shell.SendText(player, "Expected exactly 1 argument."); + return; + } + + var mgr = IoCManager.Resolve(); + if (mgr.TryGetSessionByUsername(args[0], out var data)) + { + var mind = data.ContentData().Mind; + + var builder = new StringBuilder(); + builder.AppendFormat("player: {0}, mob: {1}\nroles: ", mind.UserId, mind.OwnedMob?.Owner?.Uid); + foreach (var role in mind.AllRoles) + { + builder.AppendFormat("{0} ", role.Name); + } + + shell.SendText(player, builder.ToString()); + } + else + { + shell.SendText(player, "Can't find that mind"); + } + } + } +} \ No newline at end of file diff --git a/Content.Server/Commands/Mobs/RemoveOverlayCommand.cs b/Content.Server/Commands/Mobs/RemoveOverlayCommand.cs new file mode 100644 index 0000000000..c08e8f4ff6 --- /dev/null +++ b/Content.Server/Commands/Mobs/RemoveOverlayCommand.cs @@ -0,0 +1,33 @@ +using Content.Server.Administration; +using Content.Server.GameObjects.Components.Mobs; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; + +namespace Content.Server.Commands.Mobs +{ + [AdminCommand(AdminFlags.Debug)] + public class RemoveOverlayCommand : IClientCommand + { + public string Command => "rmoverlay"; + public string Description => "Removes an overlay by its ID"; + public string Help => "rmoverlay "; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + if (args.Length != 1) + { + shell.SendText(player, "Expected 1 argument."); + return; + } + + if (player?.AttachedEntity != null) + { + if (player.AttachedEntity.TryGetComponent(out ServerOverlayEffectsComponent overlayEffectsComponent)) + { + overlayEffectsComponent.RemoveOverlay(args[0]); + } + } + } + } +} diff --git a/Content.Server/Commands/Mobs/RemoveRoleCommand.cs b/Content.Server/Commands/Mobs/RemoveRoleCommand.cs new file mode 100644 index 0000000000..691082f849 --- /dev/null +++ b/Content.Server/Commands/Mobs/RemoveRoleCommand.cs @@ -0,0 +1,45 @@ +using Content.Server.Administration; +using Content.Server.Mobs.Roles; +using Content.Server.Players; +using Content.Shared.Administration; +using Content.Shared.Roles; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; +using Robust.Shared.Prototypes; + +namespace Content.Server.Commands.Mobs +{ + [AdminCommand(AdminFlags.Fun)] + public class RemoveRoleCommand : IClientCommand + { + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + + public string Command => "rmrole"; + + public string Description => "Removes a role from a player's mind."; + + public string Help => "rmrole \nThat role type is the actual C# type name."; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + if (args.Length != 2) + { + shell.SendText(player, "Expected exactly 2 arguments."); + return; + } + + var mgr = IoCManager.Resolve(); + if (mgr.TryGetPlayerDataByUsername(args[0], out var data)) + { + var mind = data.ContentData().Mind; + var role = new Job(mind, _prototypeManager.Index(args[1])); + mind.RemoveRole(role); + } + else + { + shell.SendText(player, "Can't find that mind"); + } + } + } +} \ No newline at end of file diff --git a/Content.Server/Commands/Notify/PopupMsgCommand.cs b/Content.Server/Commands/Notify/PopupMsgCommand.cs new file mode 100644 index 0000000000..a86e07e217 --- /dev/null +++ b/Content.Server/Commands/Notify/PopupMsgCommand.cs @@ -0,0 +1,30 @@ +using Content.Server.Administration; +using Content.Shared.Administration; +using Content.Shared.Interfaces; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.GameObjects; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.Notify +{ + [AdminCommand(AdminFlags.Debug)] + public class PopupMsgCommand : IClientCommand + { + public string Command => "srvpopupmsg"; + public string Description => ""; + public string Help => ""; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + var entityMgr = IoCManager.Resolve(); + + var source = EntityUid.Parse(args[0]); + var viewer = EntityUid.Parse(args[1]); + var msg = args[2]; + + entityMgr.GetEntity(source).PopupMessage(entityMgr.GetEntity(viewer), msg); + } + } +} diff --git a/Content.Server/Commands/Objectives/AddObjectiveCommand.cs b/Content.Server/Commands/Objectives/AddObjectiveCommand.cs new file mode 100644 index 0000000000..233a2d1650 --- /dev/null +++ b/Content.Server/Commands/Objectives/AddObjectiveCommand.cs @@ -0,0 +1,56 @@ +#nullable enable +using Content.Server.Administration; +using Content.Server.Objectives; +using Content.Server.Players; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; +using Robust.Shared.Prototypes; + +namespace Content.Server.Commands.Objectives +{ + [AdminCommand(AdminFlags.Admin)] + public class AddObjectiveCommand : IClientCommand + { + public string Command => "addobjective"; + public string Description => "Adds an objective to the player's mind."; + public string Help => "addobjective "; + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (args.Length != 2) + { + shell.SendText(player, "Expected exactly 2 arguments."); + return; + } + + var mgr = IoCManager.Resolve(); + if (!mgr.TryGetPlayerDataByUsername(args[0], out var data)) + { + shell.SendText(player, "Can't find the playerdata."); + return; + } + + + var mind = data.ContentData()?.Mind; + if (mind == null) + { + shell.SendText(player, "Can't find the mind."); + return; + } + + if (!IoCManager.Resolve() + .TryIndex(args[1], out var objectivePrototype)) + { + shell.SendText(player, $"Can't find matching ObjectivePrototype {objectivePrototype}"); + return; + } + + if (!mind.TryAddObjective(objectivePrototype)) + { + shell.SendText(player, "Objective requirements dont allow that objective to be added."); + } + + } + } +} diff --git a/Content.Server/Commands/Objectives/ListObjectivesCommand.cs b/Content.Server/Commands/Objectives/ListObjectivesCommand.cs new file mode 100644 index 0000000000..c7b4338a14 --- /dev/null +++ b/Content.Server/Commands/Objectives/ListObjectivesCommand.cs @@ -0,0 +1,51 @@ +#nullable enable +using System.Linq; +using Content.Server.Administration; +using Content.Server.Players; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.Objectives +{ + [AdminCommand(AdminFlags.Admin)] + public class ListObjectivesCommand : IClientCommand + { + public string Command => "lsobjectives"; + public string Description => "Lists all objectives in a players mind."; + public string Help => "lsobjectives []"; + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + IPlayerData? data; + if (args.Length == 0 && player != null) + { + data = player.Data; + } + else if (player == null || !IoCManager.Resolve().TryGetPlayerDataByUsername(args[0], out data)) + { + shell.SendText(player, "Can't find the playerdata."); + return; + } + + var mind = data.ContentData()?.Mind; + if (mind == null) + { + shell.SendText(player, "Can't find the mind."); + return; + } + + shell.SendText(player, $"Objectives for player {data.UserId}:"); + var objectives = mind.AllObjectives.ToList(); + if (objectives.Count == 0) + { + shell.SendText(player, "None."); + } + for (var i = 0; i < objectives.Count; i++) + { + shell.SendText(player, $"- [{i}] {objectives[i]}"); + } + + } + } +} diff --git a/Content.Server/Commands/Objectives/RemoveObjectiveCommand.cs b/Content.Server/Commands/Objectives/RemoveObjectiveCommand.cs new file mode 100644 index 0000000000..2fcc87f646 --- /dev/null +++ b/Content.Server/Commands/Objectives/RemoveObjectiveCommand.cs @@ -0,0 +1,53 @@ +#nullable enable +using Content.Server.Administration; +using Content.Server.Players; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.Objectives +{ + [AdminCommand(AdminFlags.Admin)] + public class RemoveObjectiveCommand : IClientCommand + { + public string Command => "rmobjective"; + public string Description => "Removes an objective from the player's mind."; + public string Help => "rmobjective "; + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (args.Length != 2) + { + shell.SendText(player, "Expected exactly 2 arguments."); + return; + } + + var mgr = IoCManager.Resolve(); + if (mgr.TryGetPlayerDataByUsername(args[0], out var data)) + { + var mind = data.ContentData()?.Mind; + if (mind == null) + { + shell.SendText(player, "Can't find the mind."); + return; + } + + if (int.TryParse(args[1], out var i)) + { + shell.SendText(player, + mind.TryRemoveObjective(i) + ? "Objective successfully removed!" + : "Objective removing failed. Maybe the index is out of bounds? Check lsobjectives!"); + } + else + { + shell.SendText(player, $"Invalid index {args[1]}!"); + } + } + else + { + shell.SendText(player, "Can't find the playerdata."); + } + } + } +} diff --git a/Content.Server/Observer/Ghost.cs b/Content.Server/Commands/Observer/Ghost.cs similarity index 97% rename from Content.Server/Observer/Ghost.cs rename to Content.Server/Commands/Observer/Ghost.cs index 6aca5cff89..07ae0d820a 100644 --- a/Content.Server/Observer/Ghost.cs +++ b/Content.Server/Commands/Observer/Ghost.cs @@ -1,4 +1,4 @@ -using Content.Server.Administration; +using Content.Server.Administration; using Content.Server.GameObjects.Components.Mobs; using Content.Server.GameObjects.Components.Observer; using Content.Server.Interfaces.GameTicking; @@ -11,7 +11,7 @@ using Robust.Server.Interfaces.Player; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.IoC; -namespace Content.Server.Observer +namespace Content.Server.Commands.Observer { [AnyCommand] public class Ghost : IClientCommand diff --git a/Content.Server/Commands/Speech/AddAccent.cs b/Content.Server/Commands/Speech/AddAccent.cs new file mode 100644 index 0000000000..530049c124 --- /dev/null +++ b/Content.Server/Commands/Speech/AddAccent.cs @@ -0,0 +1,86 @@ +#nullable enable +using System; +using System.Linq; +using Content.Server.Administration; +using Content.Server.GameObjects.Components.Mobs.Speech; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; + +namespace Content.Server.Commands.Speech +{ + [AdminCommand(AdminFlags.Fun)] + public class AddAccent : IClientCommand + { + public string Command => "addaccent"; + public string Description => "Add a speech component to the current player"; + public string Help => $"{Command} /?"; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (player?.AttachedEntity == null) + { + shell.SendText(player, "You don't have an entity!"); + return; + } + + if (args.Length == 0) + { + shell.SendText(player, Help); + return; + } + + var compFactory = IoCManager.Resolve(); + + if (args[0] == "?") + { + // Get all components that implement the ISpeechComponent except + var speeches = compFactory.GetAllRefTypes() + .Where(c => typeof(IAccentComponent).IsAssignableFrom(c) && c.IsClass); + var msg = ""; + foreach(var s in speeches) + { + msg += $"{compFactory.GetRegistration(s).Name}\n"; + } + shell.SendText(player, msg); + } + else + { + var name = args[0]; + // Try to get the Component + Type type; + try + { + var comp = compFactory.GetComponent(name); + type = comp.GetType(); + } + catch (Exception) + { + shell.SendText(player, $"Accent {name} not found. Try {Command} ? to get a list of all appliable accents."); + return; + } + + // Check if that already exists + try + { + var comp = player.AttachedEntity.GetComponent(type); + shell.SendText(player, "You already have this accent!"); + return; + } + catch (Exception) + { + // Accent not found + } + + // Generic fuckery + var ensure = typeof(IEntity).GetMethod("AddComponent"); + if (ensure == null) + return; + var method = ensure.MakeGenericMethod(type); + method.Invoke(player.AttachedEntity, null); + } + } + } +} diff --git a/Content.Server/StationEvents/StationEventCommand.cs b/Content.Server/Commands/StationEvents/StationEventCommand.cs similarity index 98% rename from Content.Server/StationEvents/StationEventCommand.cs rename to Content.Server/Commands/StationEvents/StationEventCommand.cs index 2549acded0..2dbcb806fa 100644 --- a/Content.Server/StationEvents/StationEventCommand.cs +++ b/Content.Server/Commands/StationEvents/StationEventCommand.cs @@ -7,7 +7,7 @@ using Robust.Server.Interfaces.Player; using Robust.Shared.GameObjects.Systems; using Robust.Shared.Localization; -namespace Content.Server.StationEvents +namespace Content.Server.Commands.StationEvents { [AdminCommand(AdminFlags.Server)] public sealed class StationEventCommand : IClientCommand diff --git a/Content.Server/GameObjects/Components/Body/BodyComponent.cs b/Content.Server/GameObjects/Components/Body/BodyComponent.cs index 6de7cb07cf..32a9338ad4 100644 --- a/Content.Server/GameObjects/Components/Body/BodyComponent.cs +++ b/Content.Server/GameObjects/Components/Body/BodyComponent.cs @@ -1,5 +1,5 @@ #nullable enable -using Content.Server.Observer; +using Content.Server.Commands.Observer; using Content.Shared.GameObjects.Components.Body; using Content.Shared.GameObjects.Components.Body.Part; using Content.Shared.GameObjects.Components.Damage; diff --git a/Content.Server/GameObjects/Components/Interactable/ToolCommands.cs b/Content.Server/GameObjects/Components/Interactable/ToolCommands.cs deleted file mode 100644 index 18faf899b6..0000000000 --- a/Content.Server/GameObjects/Components/Interactable/ToolCommands.cs +++ /dev/null @@ -1,163 +0,0 @@ -#nullable enable -using System.Linq; -using Content.Server.Administration; -using Content.Shared.Administration; -using Content.Shared.Maps; -using JetBrains.Annotations; -using Robust.Server.Interfaces.Console; -using Robust.Server.Interfaces.GameObjects; -using Robust.Server.Interfaces.Player; -using Robust.Shared.Interfaces.Map; -using Robust.Shared.IoC; -using Robust.Shared.Map; - -namespace Content.Server.GameObjects.Components.Interactable -{ - /// - /// - /// - [AdminCommand(AdminFlags.Debug)] - class TilePryCommand : IClientCommand - { - public string Command => "tilepry"; - public string Description => "Pries up all tiles in a radius around the user."; - public string Help => $"Usage: {Command} "; - - public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - if (player?.AttachedEntity == null) - { - return; - } - - if (args.Length != 1) - { - shell.SendText(player, Help); - return; - } - - if (!int.TryParse(args[0], out var radius)) - { - shell.SendText(player, $"{args[0]} isn't a valid integer."); - return; - } - - if (radius < 0) - { - shell.SendText(player, "Radius must be positive."); - return; - } - - var mapManager = IoCManager.Resolve(); - var playerGrid = player.AttachedEntity.Transform.GridID; - var mapGrid = mapManager.GetGrid(playerGrid); - var playerPosition = player.AttachedEntity.Transform.Coordinates; - var tileDefinitionManager = IoCManager.Resolve(); - - for (var i = -radius; i <= radius; i++) - { - for (var j = -radius; j <= radius; j++) - { - var tile = mapGrid.GetTileRef(playerPosition.Offset((i, j))); - var coordinates = mapGrid.GridTileToLocal(tile.GridIndices); - var tileDef = (ContentTileDefinition) tileDefinitionManager[tile.Tile.TypeId]; - - if (!tileDef.CanCrowbar) continue; - - var underplating = tileDefinitionManager["underplating"]; - mapGrid.SetTile(coordinates, new Tile(underplating.TileId)); - } - } - } - } - - [AdminCommand(AdminFlags.Debug)] - class AnchorCommand : IClientCommand - { - public string Command => "anchor"; - public string Description => "Anchors all entities in a radius around the user"; - public string Help => $"Usage: {Command} "; - - public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - if (player?.AttachedEntity == null) - { - return; - } - - if (args.Length != 1) - { - shell.SendText(player, Help); - return; - } - - if (!int.TryParse(args[0], out var radius)) - { - shell.SendText(player, $"{args[0]} isn't a valid integer."); - return; - } - - if (radius < 0) - { - shell.SendText(player, "Radius must be positive."); - return; - } - - var serverEntityManager = IoCManager.Resolve(); - var entities = serverEntityManager.GetEntitiesInRange(player.AttachedEntity, radius).ToList(); - - foreach (var entity in entities) - { - if (entity.TryGetComponent(out AnchorableComponent? anchorable)) - { - _ = anchorable.TryAnchor(player.AttachedEntity, force: true); - } - } - } - } - - [AdminCommand(AdminFlags.Debug)] - class UnAnchorCommand : IClientCommand - { - public string Command => "unanchor"; - public string Description => "Unanchors all anchorable entities in a radius around the user"; - public string Help => $"Usage: {Command} "; - - public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - if (player?.AttachedEntity == null) - { - return; - } - - if (args.Length != 1) - { - shell.SendText(player, Help); - return; - } - - if (!int.TryParse(args[0], out var radius)) - { - shell.SendText(player, $"{args[0]} isn't a valid integer."); - return; - } - - if (radius < 0) - { - shell.SendText(player, "Radius must be positive."); - return; - } - - var serverEntityManager = IoCManager.Resolve(); - var entities = serverEntityManager.GetEntitiesInRange(player.AttachedEntity, radius).ToList(); - - foreach (var entity in entities) - { - if (entity.TryGetComponent(out AnchorableComponent? anchorable)) - { - _ = anchorable.TryUnAnchor(player.AttachedEntity, force: true); - } - } - } - } -} diff --git a/Content.Server/GameObjects/Components/Mobs/ServerAlertsComponent.cs b/Content.Server/GameObjects/Components/Mobs/ServerAlertsComponent.cs index 37b1465891..f035cedd84 100644 --- a/Content.Server/GameObjects/Components/Mobs/ServerAlertsComponent.cs +++ b/Content.Server/GameObjects/Components/Mobs/ServerAlertsComponent.cs @@ -1,16 +1,9 @@ using System; -using Content.Server.Administration; -using Content.Server.Commands; using Content.Server.GameObjects.EntitySystems; -using Content.Shared.Administration; -using Content.Shared.Alert; using Content.Shared.GameObjects.Components.Mobs; -using Robust.Server.Interfaces.Console; -using Robust.Server.Interfaces.Player; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.Network; -using Robust.Shared.IoC; using Robust.Shared.Log; using Robust.Shared.Players; @@ -89,82 +82,4 @@ namespace Content.Server.GameObjects.Components.Mobs } } } - - [AdminCommand(AdminFlags.Debug)] - public sealed class ShowAlert : IClientCommand - { - public string Command => "showalert"; - public string Description => "Shows an alert for a player, defaulting to current player"; - public string Help => "showalert "; - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - var attachedEntity = player.AttachedEntity; - if (args.Length > 2) - { - var target = args[2]; - if (!Commands.CommandUtils.TryGetAttachedEntityByUsernameOrId(shell, target, player, out attachedEntity)) return; - } - - if (!CommandUtils.ValidateAttachedEntity(shell, player, attachedEntity)) return; - - - if (!attachedEntity.TryGetComponent(out ServerAlertsComponent alertsComponent)) - { - shell.SendText(player, "user has no alerts component"); - return; - } - - var alertType = args[0]; - var severity = args[1]; - var alertMgr = IoCManager.Resolve(); - if (!alertMgr.TryGet(Enum.Parse(alertType), out var alert)) - { - shell.SendText(player, "unrecognized alertType " + alertType); - return; - } - if (!short.TryParse(severity, out var sevint)) - { - shell.SendText(player, "invalid severity " + sevint); - return; - } - alertsComponent.ShowAlert(alert.AlertType, sevint == -1 ? (short?) null : sevint); - - } - } - - [AdminCommand(AdminFlags.Debug)] - public sealed class ClearAlert : IClientCommand - { - public string Command => "clearalert"; - public string Description => "Clears an alert for a player, defaulting to current player"; - public string Help => "clearalert "; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - var attachedEntity = player.AttachedEntity; - if (args.Length > 1) - { - var target = args[1]; - if (!CommandUtils.TryGetAttachedEntityByUsernameOrId(shell, target, player, out attachedEntity)) return; - } - - if (!CommandUtils.ValidateAttachedEntity(shell, player, attachedEntity)) return; - - if (!attachedEntity.TryGetComponent(out ServerAlertsComponent alertsComponent)) - { - shell.SendText(player, "user has no alerts component"); - return; - } - - var alertType = args[0]; - var alertMgr = IoCManager.Resolve(); - if (!alertMgr.TryGet(Enum.Parse(alertType), out var alert)) - { - shell.SendText(player, "unrecognized alertType " + alertType); - return; - } - - alertsComponent.ClearAlert(alert.AlertType); - } - } } diff --git a/Content.Server/GameObjects/Components/Mobs/Speech/SpeechComponent.cs b/Content.Server/GameObjects/Components/Mobs/Speech/SpeechComponent.cs index 3af74dbaa0..35ab69ed11 100644 --- a/Content.Server/GameObjects/Components/Mobs/Speech/SpeechComponent.cs +++ b/Content.Server/GameObjects/Components/Mobs/Speech/SpeechComponent.cs @@ -1,13 +1,4 @@ -using System; -using System.Linq; -using Content.Server.Administration; -using Content.Shared.Administration; -using Robust.Server.Interfaces.Console; -using Robust.Server.Interfaces.Player; -using Robust.Shared.Interfaces.GameObjects; -using Robust.Shared.IoC; - -namespace Content.Server.GameObjects.Components.Mobs.Speech +namespace Content.Server.GameObjects.Components.Mobs.Speech { internal interface IAccentComponent { @@ -18,79 +9,4 @@ namespace Content.Server.GameObjects.Components.Mobs.Speech /// The message after the transformation public string Accentuate(string message); } - - [AdminCommand(AdminFlags.Fun)] - public class AddAccent : IClientCommand - { - public string Command => "addaccent"; - - public string Description => "Add a speech component to the current player"; - - public string Help => $"{Command} /?"; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - if (args.Length == 0) - { - shell.SendText(player, Help); - return; - } - - if (player.AttachedEntity == null) - { - shell.SendText(player, "You don't have a player!"); - return; - } - - var compFactory = IoCManager.Resolve(); - - if (args[0] == "?") - { - // Get all components that implement the ISpeechComponent except - var speeches = compFactory.GetAllRefTypes() - .Where(c => typeof(IAccentComponent).IsAssignableFrom(c) && c.IsClass); - var msg = ""; - foreach(var s in speeches) - { - msg += $"{compFactory.GetRegistration(s).Name}\n"; - } - shell.SendText(player, msg); - } - else - { - var name = args[0]; - // Try to get the Component - Type type; - try - { - var comp = compFactory.GetComponent(name); - type = comp.GetType(); - } - catch (Exception) - { - shell.SendText(player, $"Accent {name} not found. Try {Command} ? to get a list of all appliable accents."); - return; - } - - // Check if that already exists - try - { - var comp = player.AttachedEntity.GetComponent(type); - shell.SendText(player, "You already have this accent!"); - return; - } - catch (Exception) - { - // Accent not found - } - - // Generic fuckery - var ensure = typeof(IEntity).GetMethod("AddComponent"); - if (ensure == null) - return; - var method = ensure.MakeGenericMethod(type); - method.Invoke(player.AttachedEntity, null); - } - } - } } diff --git a/Content.Server/GameObjects/EntitySystems/AI/AiFactionTagSystem.cs b/Content.Server/GameObjects/EntitySystems/AI/AiFactionTagSystem.cs index b9edd66f64..6d84b34939 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/AiFactionTagSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/AiFactionTagSystem.cs @@ -1,14 +1,7 @@ -using System; using System.Collections.Generic; -using System.Text; -using Content.Server.Administration; using Content.Server.GameObjects.Components.AI; -using Content.Shared.Administration; -using Robust.Server.Interfaces.Console; -using Robust.Server.Interfaces.Player; using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.GameObjects; -using Robust.Shared.Localization; namespace Content.Server.GameObjects.EntitySystems.AI { @@ -91,88 +84,4 @@ namespace Content.Server.GameObjects.EntitySystems.AI _hostileFactions[source] = hostileFactions; } } - - [AdminCommand(AdminFlags.Fun)] - public sealed class FactionCommand : IClientCommand - { - public string Command => "factions"; - public string Description => "Update / list factional relationships for NPCs."; - public string Help => "faction target\n" + - "faction list: hostile factions"; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - if (args.Length == 0) - { - var result = new StringBuilder(); - foreach (Faction value in Enum.GetValues(typeof(Faction))) - { - if (value == Faction.None) - continue; - result.Append(value + "\n"); - } - - shell.SendText(player, result.ToString()); - return; - } - - if (args.Length < 2) - { - shell.SendText(player, Loc.GetString("Need more args")); - return; - } - - if (!Enum.TryParse(args[0], true, out Faction faction)) - { - shell.SendText(player, Loc.GetString("Invalid faction")); - return; - } - - Faction targetFaction; - - switch (args[1]) - { - case "friendly": - if (args.Length < 3) - { - shell.SendText(player, Loc.GetString("Need to supply a target faction")); - return; - } - - if (!Enum.TryParse(args[2], true, out targetFaction)) - { - shell.SendText(player, Loc.GetString("Invalid target faction")); - return; - } - - EntitySystem.Get().MakeFriendly(faction, targetFaction); - shell.SendText(player, Loc.GetString("Command successful")); - break; - case "hostile": - if (args.Length < 3) - { - shell.SendText(player, Loc.GetString("Need to supply a target faction")); - return; - } - - if (!Enum.TryParse(args[2], true, out targetFaction)) - { - shell.SendText(player, Loc.GetString("Invalid target faction")); - return; - } - - EntitySystem.Get().MakeHostile(faction, targetFaction); - shell.SendText(player, Loc.GetString("Command successful")); - break; - case "list": - shell.SendText(player, EntitySystem.Get().GetHostileFactions(faction).ToString()); - break; - default: - shell.SendText(player, Loc.GetString("Unknown faction arg")); - break; - } - - return; - } - } } diff --git a/Content.Server/GameObjects/EntitySystems/AI/AiSystem.cs b/Content.Server/GameObjects/EntitySystems/AI/AiSystem.cs index 7ab3bef2b7..33bc8819cc 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/AiSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/AiSystem.cs @@ -144,50 +144,5 @@ namespace Content.Server.GameObjects.EntitySystems.AI } public bool ProcessorTypeExists(string name) => _processorTypes.ContainsKey(name); - - - [AdminCommand(AdminFlags.Fun)] - private class AddAiCommand : IClientCommand - { - public string Command => "addai"; - public string Description => "Add an ai component with a given processor to an entity."; - public string Help => "Usage: addai " - + "\n processorId: Class that inherits AiLogicProcessor and has an AiLogicProcessor attribute." - + "\n entityID: Uid of entity to add the AiControllerComponent to. Open its VV menu to find this."; - - public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - if(args.Length != 2) - { - shell.SendText(player, "Wrong number of args."); - return; - } - - var processorId = args[0]; - var entId = new EntityUid(int.Parse(args[1])); - var ent = IoCManager.Resolve().GetEntity(entId); - var aiSystem = Get(); - - if (!aiSystem.ProcessorTypeExists(processorId)) - { - shell.SendText(player, "Invalid processor type. Processor must inherit AiLogicProcessor and have an AiLogicProcessor attribute."); - return; - } - if (ent.HasComponent()) - { - shell.SendText(player, "Entity already has an AI component."); - return; - } - - if (ent.HasComponent()) - { - ent.RemoveComponent(); - } - - var comp = ent.AddComponent(); - comp.LogicName = processorId; - shell.SendText(player, "AI component added."); - } - } } } diff --git a/Content.Server/GameObjects/EntitySystems/SignalLinkerSystem.cs b/Content.Server/GameObjects/EntitySystems/SignalLinkerSystem.cs index e812d3dd23..2a97408946 100644 --- a/Content.Server/GameObjects/EntitySystems/SignalLinkerSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/SignalLinkerSystem.cs @@ -1,16 +1,10 @@ using System.Collections.Generic; -using Content.Server.Administration; using Content.Server.GameObjects.Components.MachineLinking; using Content.Server.GameObjects.EntitySystems.Click; -using Content.Shared.Administration; -using Robust.Server.Interfaces.Console; -using Robust.Server.Interfaces.Player; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Systems; using Robust.Shared.Input; using Robust.Shared.Input.Binding; -using Robust.Shared.Interfaces.GameObjects; -using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Network; using Robust.Shared.Players; @@ -99,43 +93,4 @@ namespace Content.Server.GameObjects.EntitySystems } } - - [AdminCommand(AdminFlags.Debug)] - public class SignalLinkerCommand : IClientCommand - { - public string Command => "signallink"; - - public string Description => "Turns on signal linker mode. Click a transmitter to tune that signal and then click on each receiver to tune them to the transmitter signal."; - - public string Help => "signallink (on/off)"; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - bool? enable = null; - if (args.Length > 0) - { - if (args[0] == "on") - enable = true; - else if (args[0] == "off") - enable = false; - else if (bool.TryParse(args[0], out var boolean)) - enable = boolean; - else if (int.TryParse(args[0], out var num)) - { - if (num == 1) - enable = true; - else if (num == 0) - enable = false; - } - } - - if (!IoCManager.Resolve().TryGetEntitySystem(out var system)) - { - return; - } - - var ret = system.SignalLinkerKeybind(player.UserId, enable); - shell.SendText(player, ret ? "Enabled" : "Disabled"); - } - } } diff --git a/Content.Server/GameTicking/GameTickerCommands.cs b/Content.Server/GameTicking/GameTickerCommands.cs deleted file mode 100644 index 6fa0f2641a..0000000000 --- a/Content.Server/GameTicking/GameTickerCommands.cs +++ /dev/null @@ -1,497 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Content.Server.Administration; -using Content.Server.Interfaces.GameTicking; -using Content.Server.Players; -using Content.Shared.Administration; -using Content.Shared.Maps; -using Content.Shared.Roles; -using Robust.Server.Interfaces.Console; -using Robust.Server.Interfaces.Player; -using Robust.Shared.GameObjects.Components.Transform; -using Robust.Shared.Interfaces.GameObjects; -using Robust.Shared.Interfaces.Map; -using Robust.Shared.IoC; -using Robust.Shared.Map; -using Robust.Shared.Network; -using Robust.Shared.Prototypes; -using Robust.Shared.Utility; - -namespace Content.Server.GameTicking -{ - [AdminCommand(AdminFlags.Server)] - class DelayStartCommand : IClientCommand - { - public string Command => "delaystart"; - public string Description => "Delays the round start."; - public string Help => $"Usage: {Command} \nPauses/Resumes the countdown if no argument is provided."; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - var ticker = IoCManager.Resolve(); - if (ticker.RunLevel != GameRunLevel.PreRoundLobby) - { - shell.SendText(player, "This can only be executed while the game is in the pre-round lobby."); - return; - } - - if (args.Length == 0) - { - var paused = ticker.TogglePause(); - shell.SendText(player, paused ? "Paused the countdown." : "Resumed the countdown."); - return; - } - - if (args.Length != 1) - { - shell.SendText(player, "Need zero or one arguments."); - return; - } - - if (!uint.TryParse(args[0], out var seconds) || seconds == 0) - { - shell.SendText(player, $"{args[0]} isn't a valid amount of seconds."); - return; - } - - var time = TimeSpan.FromSeconds(seconds); - if (!ticker.DelayStart(time)) - { - shell.SendText(player, "An unknown error has occurred."); - } - } - } - - [AdminCommand(AdminFlags.Server)] - class StartRoundCommand : IClientCommand - { - public string Command => "startround"; - public string Description => "Ends PreRoundLobby state and starts the round."; - public string Help => String.Empty; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - var ticker = IoCManager.Resolve(); - - if (ticker.RunLevel != GameRunLevel.PreRoundLobby) - { - shell.SendText(player, "This can only be executed while the game is in the pre-round lobby."); - return; - } - - ticker.StartRound(); - } - } - - [AdminCommand(AdminFlags.Server)] - class EndRoundCommand : IClientCommand - { - public string Command => "endround"; - public string Description => "Ends the round and moves the server to PostRound."; - public string Help => String.Empty; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - var ticker = IoCManager.Resolve(); - - if (ticker.RunLevel != GameRunLevel.InRound) - { - shell.SendText(player, "This can only be executed while the game is in a round."); - return; - } - - ticker.EndRound(); - } - } - - [AdminCommand(AdminFlags.Server)] - public class NewRoundCommand : IClientCommand - { - public string Command => "restartround"; - public string Description => "Moves the server from PostRound to a new PreRoundLobby."; - public string Help => String.Empty; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - var ticker = IoCManager.Resolve(); - ticker.RestartRound(); - } - } - - class RespawnCommand : IClientCommand - { - public string Command => "respawn"; - public string Description => "Respawns a player, kicking them back to the lobby."; - public string Help => "respawn [player]"; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - if (args.Length > 1) - { - shell.SendText(player, "Must provide <= 1 argument."); - return; - } - - var playerMgr = IoCManager.Resolve(); - var ticker = IoCManager.Resolve(); - - NetUserId userId; - if (args.Length == 0) - { - if (player == null) - { - shell.SendText((IPlayerSession)null, "If not a player, an argument must be given."); - return; - } - - userId = player.UserId; - } - else if (!playerMgr.TryGetUserId(args[0], out userId)) - { - shell.SendText(player, "Unknown player"); - return; - } - - if (!playerMgr.TryGetSessionById(userId, out var targetPlayer)) - { - if (!playerMgr.TryGetPlayerData(userId, out var data)) - { - shell.SendText(player, "Unknown player"); - return; - } - - data.ContentData().WipeMind(); - shell.SendText(player, - "Player is not currently online, but they will respawn if they come back online"); - return; - } - - ticker.Respawn(targetPlayer); - } - } - - [AnyCommand] - class ObserveCommand : IClientCommand - { - public string Command => "observe"; - public string Description => ""; - public string Help => ""; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - if (player == null) - { - return; - } - - var ticker = IoCManager.Resolve(); - ticker.MakeObserve(player); - } - } - - [AnyCommand] - class JoinGameCommand : IClientCommand - { - [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - - public string Command => "joingame"; - public string Description => ""; - public string Help => ""; - - public JoinGameCommand() - { - IoCManager.InjectDependencies(this); - } - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - var output = string.Join(".", args); - if (player == null) - { - return; - } - - var ticker = IoCManager.Resolve(); - if (ticker.RunLevel == GameRunLevel.PreRoundLobby) - { - shell.SendText(player, "Round has not started."); - return; - } - else if(ticker.RunLevel == GameRunLevel.InRound) - { - string ID = args[0]; - var positions = ticker.GetAvailablePositions(); - - if(positions.GetValueOrDefault(ID, 0) == 0) //n < 0 is treated as infinite - { - var jobPrototype = _prototypeManager.Index(ID); - shell.SendText(player, $"{jobPrototype.Name} has no available slots."); - return; - } - ticker.MakeJoinGame(player, args[0].ToString()); - return; - } - - ticker.MakeJoinGame(player, null); - } - } - - [AnyCommand] - class ToggleReadyCommand : IClientCommand - { - public string Command => "toggleready"; - public string Description => ""; - public string Help => ""; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - if (player == null) - { - return; - } - - var ticker = IoCManager.Resolve(); - ticker.ToggleReady(player, bool.Parse(args[0])); - } - } - - [AdminCommand(AdminFlags.Server)] - class ToggleDisallowLateJoinCommand: IClientCommand - { - public string Command => "toggledisallowlatejoin"; - public string Description => "Allows or disallows latejoining during mid-game."; - public string Help => $"Usage: {Command} "; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - if (args.Length != 1) - { - shell.SendText(player, "Need exactly one argument."); - return; - } - - var ticker = IoCManager.Resolve(); - - if (bool.TryParse(args[0], out var result)) - { - ticker.ToggleDisallowLateJoin(bool.Parse(args[0])); - shell.SendText(player, result ? "Late joining has been disabled." : "Late joining has been enabled."); - } - else - { - shell.SendText(player, "Invalid argument."); - } - } - } - - [AdminCommand(AdminFlags.Server)] - class SetGamePresetCommand : IClientCommand - { - public string Command => "setgamepreset"; - public string Description => ""; - public string Help => ""; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - if (args.Length != 1) - { - shell.SendText(player, "Need exactly one argument."); - return; - } - - var ticker = IoCManager.Resolve(); - - ticker.SetStartPreset(args[0]); - } - } - - [AdminCommand(AdminFlags.Server)] - class ForcePresetCommand : IClientCommand - { - public string Command => "forcepreset"; - public string Description => "Forces a specific game preset to start for the current lobby."; - public string Help => $"Usage: {Command} "; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - var ticker = IoCManager.Resolve(); - if (ticker.RunLevel != GameRunLevel.PreRoundLobby) - { - shell.SendText(player, "This can only be executed while the game is in the pre-round lobby."); - return; - } - - if (args.Length != 1) - { - shell.SendText(player, "Need exactly one argument."); - return; - } - - var name = args[0]; - if (!ticker.TryGetPreset(name, out var type)) - { - shell.SendText(player, $"No preset exists with name {name}."); - return; - } - - ticker.SetStartPreset(type, true); - shell.SendText(player, $"Forced the game to start with preset {name}."); - } - } - - [AdminCommand(AdminFlags.Server | AdminFlags.Mapping)] - class MappingCommand : IClientCommand - { - public string Command => "mapping"; - public string Description => "Creates and teleports you to a new uninitialized map for mapping."; - public string Help => $"Usage: {Command} / {Command} "; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - if (player == null) - { - shell.SendText(player, "Only players can use this command"); - return; - } - - var mapManager = IoCManager.Resolve(); - int mapId; - string mapName; - - switch (args.Length) - { - case 1: - if (player.AttachedEntity == null) - { - shell.SendText(player, "The map name argument cannot be omitted if you have no entity."); - return; - } - - mapId = (int) mapManager.NextMapId(); - mapName = args[0]; - break; - case 2: - if (!int.TryParse(args[0], out var id)) - { - shell.SendText(player, $"{args[0]} is not a valid integer."); - return; - } - - mapId = id; - mapName = args[1]; - break; - default: - shell.SendText(player, Help); - return; - } - - shell.ExecuteCommand(player, $"addmap {mapId} false"); - shell.ExecuteCommand(player, $"loadbp {mapId} \"{CommandParsing.Escape(mapName)}\""); - shell.ExecuteCommand(player, "aghost"); - shell.ExecuteCommand(player, $"tp 0 0 {mapId}"); - - var newGridId = mapManager.GetAllGrids().Max(g => (int) g.Index); - - shell.SendText(player, $"Created unloaded map from file {mapName} with id {mapId}. Use \"savebp {newGridId} foo.yml\" to save the new grid as a map."); - } - } - - [AdminCommand(AdminFlags.Mapping)] - class TileWallsCommand : IClientCommand - { - // ReSharper disable once StringLiteralTypo - public string Command => "tilewalls"; - public string Description => "Puts an underplating tile below every wall on a grid."; - public string Help => $"Usage: {Command} | {Command}"; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - GridId gridId; - - switch (args.Length) - { - case 0: - if (player?.AttachedEntity == null) - { - shell.SendText((IPlayerSession) null, "Only a player can run this command."); - return; - } - - gridId = player.AttachedEntity.Transform.GridID; - break; - case 1: - if (!int.TryParse(args[0], out var id)) - { - shell.SendText(player, $"{args[0]} is not a valid integer."); - return; - } - - gridId = new GridId(id); - break; - default: - shell.SendText(player, Help); - return; - } - - var mapManager = IoCManager.Resolve(); - if (!mapManager.TryGetGrid(gridId, out var grid)) - { - shell.SendText(player, $"No grid exists with id {gridId}"); - return; - } - - var entityManager = IoCManager.Resolve(); - if (!entityManager.TryGetEntity(grid.GridEntityId, out var gridEntity)) - { - shell.SendText(player, $"Grid {gridId} doesn't have an associated grid entity."); - return; - } - - var tileDefinitionManager = IoCManager.Resolve(); - var underplating = tileDefinitionManager["underplating"]; - var underplatingTile = new Tile(underplating.TileId); - var changed = 0; - foreach (var childUid in gridEntity.Transform.ChildEntityUids) - { - if (!entityManager.TryGetEntity(childUid, out var childEntity)) - { - continue; - } - - var prototype = childEntity.Prototype; - while (true) - { - if (prototype?.Parent == null) - { - break; - } - - prototype = prototype.Parent; - } - - if (prototype?.ID != "base_wall") - { - continue; - } - - if (!childEntity.TryGetComponent(out SnapGridComponent snapGrid)) - { - continue; - } - - var tile = grid.GetTileRef(childEntity.Transform.Coordinates); - var tileDef = (ContentTileDefinition) tileDefinitionManager[tile.Tile.TypeId]; - - if (tileDef.Name == "underplating") - { - continue; - } - - grid.SetTile(childEntity.Transform.Coordinates, underplatingTile); - changed++; - } - - shell.SendText(player, $"Changed {changed} tiles."); - } - } -} diff --git a/Content.Server/Mobs/Commands.cs b/Content.Server/Mobs/Commands.cs deleted file mode 100644 index 45af6e11b6..0000000000 --- a/Content.Server/Mobs/Commands.cs +++ /dev/null @@ -1,170 +0,0 @@ -using System.Text; -using Content.Server.Administration; -using Content.Server.GameObjects.Components.Mobs; -using Content.Server.Mobs.Roles; -using Content.Server.Players; -using Content.Shared.Administration; -using Content.Shared.Roles; -using Robust.Server.Interfaces.Console; -using Robust.Server.Interfaces.Player; -using Robust.Shared.IoC; -using Robust.Shared.Network; -using Robust.Shared.Prototypes; - -namespace Content.Server.Mobs -{ - - [AdminCommand(AdminFlags.Admin)] - public class MindInfoCommand : IClientCommand - { - public string Command => "mindinfo"; - - public string Description => "Lists info for the mind of a specific player."; - - public string Help => "mindinfo "; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - if (args.Length != 1) - { - shell.SendText(player, "Expected exactly 1 argument."); - return; - } - - var mgr = IoCManager.Resolve(); - if (mgr.TryGetSessionByUsername(args[0], out var data)) - { - var mind = data.ContentData().Mind; - - var builder = new StringBuilder(); - builder.AppendFormat("player: {0}, mob: {1}\nroles: ", mind.UserId, mind.OwnedMob?.Owner?.Uid); - foreach (var role in mind.AllRoles) - { - builder.AppendFormat("{0} ", role.Name); - } - - shell.SendText(player, builder.ToString()); - } - else - { - shell.SendText(player, "Can't find that mind"); - } - } - } - - [AdminCommand(AdminFlags.Fun)] - public class AddRoleCommand : IClientCommand - { - [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - - public string Command => "addrole"; - - public string Description => "Adds a role to a player's mind."; - - public string Help => "addrole \nThat role type is the actual C# type name."; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - if (args.Length != 2) - { - shell.SendText(player, "Expected exactly 2 arguments."); - return; - } - - var mgr = IoCManager.Resolve(); - if (mgr.TryGetPlayerDataByUsername(args[0], out var data)) - { - var mind = data.ContentData().Mind; - var role = new Job(mind, _prototypeManager.Index(args[1])); - mind.AddRole(role); - } - else - { - shell.SendText(player, "Can't find that mind"); - } - } - } - - [AdminCommand(AdminFlags.Fun)] - public class RemoveRoleCommand : IClientCommand - { - [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - - public string Command => "rmrole"; - - public string Description => "Removes a role from a player's mind."; - - public string Help => "rmrole \nThat role type is the actual C# type name."; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - if (args.Length != 2) - { - shell.SendText(player, "Expected exactly 2 arguments."); - return; - } - - var mgr = IoCManager.Resolve(); - if (mgr.TryGetPlayerDataByUsername(args[0], out var data)) - { - var mind = data.ContentData().Mind; - var role = new Job(mind, _prototypeManager.Index(args[1])); - mind.RemoveRole(role); - } - else - { - shell.SendText(player, "Can't find that mind"); - } - } - } - - [AdminCommand(AdminFlags.Debug)] - public class AddOverlayCommand : IClientCommand - { - public string Command => "addoverlay"; - public string Description => "Adds an overlay by its ID"; - public string Help => "addoverlay "; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - if (args.Length != 1) - { - shell.SendText(player, "Expected 1 argument."); - return; - } - - if (player?.AttachedEntity != null) - { - if (player.AttachedEntity.TryGetComponent(out ServerOverlayEffectsComponent overlayEffectsComponent)) - { - overlayEffectsComponent.AddOverlay(args[0]); - } - } - } - } - - [AdminCommand(AdminFlags.Debug)] - public class RemoveOverlayCommand : IClientCommand - { - public string Command => "rmoverlay"; - public string Description => "Removes an overlay by its ID"; - public string Help => "rmoverlay "; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - if (args.Length != 1) - { - shell.SendText(player, "Expected 1 argument."); - return; - } - - if (player?.AttachedEntity != null) - { - if (player.AttachedEntity.TryGetComponent(out ServerOverlayEffectsComponent overlayEffectsComponent)) - { - overlayEffectsComponent.RemoveOverlay(args[0]); - } - } - } - } -} diff --git a/Content.Server/Objectives/Commands.cs b/Content.Server/Objectives/Commands.cs deleted file mode 100644 index 47ecdd4f8a..0000000000 --- a/Content.Server/Objectives/Commands.cs +++ /dev/null @@ -1,139 +0,0 @@ -#nullable enable -using System.Linq; -using Content.Server.Administration; -using Content.Server.Players; -using Content.Shared.Administration; -using Robust.Server.Interfaces.Console; -using Robust.Server.Interfaces.Player; -using Robust.Shared.IoC; -using Robust.Shared.Prototypes; - -namespace Content.Server.Objectives -{ - [AdminCommand(AdminFlags.Admin)] - public class AddObjectiveCommand : IClientCommand - { - public string Command => "addobjective"; - public string Description => "Adds an objective to the player's mind."; - public string Help => "addobjective "; - public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - if (args.Length != 2) - { - shell.SendText(player, "Expected exactly 2 arguments."); - return; - } - - var mgr = IoCManager.Resolve(); - if (!mgr.TryGetPlayerDataByUsername(args[0], out var data)) - { - shell.SendText(player, "Can't find the playerdata."); - return; - } - - - var mind = data.ContentData()?.Mind; - if (mind == null) - { - shell.SendText(player, "Can't find the mind."); - return; - } - - if (!IoCManager.Resolve() - .TryIndex(args[1], out var objectivePrototype)) - { - shell.SendText(player, $"Can't find matching ObjectivePrototype {objectivePrototype}"); - return; - } - - if (!mind.TryAddObjective(objectivePrototype)) - { - shell.SendText(player, "Objective requirements dont allow that objective to be added."); - } - - } - } - - [AdminCommand(AdminFlags.Admin)] - public class ListObjectivesCommand : IClientCommand - { - public string Command => "lsobjectives"; - public string Description => "Lists all objectives in a players mind."; - public string Help => "lsobjectives []"; - public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - IPlayerData? data; - if (args.Length == 0 && player != null) - { - data = player.Data; - } - else if (player == null || !IoCManager.Resolve().TryGetPlayerDataByUsername(args[0], out data)) - { - shell.SendText(player, "Can't find the playerdata."); - return; - } - - var mind = data.ContentData()?.Mind; - if (mind == null) - { - shell.SendText(player, "Can't find the mind."); - return; - } - - shell.SendText(player, $"Objectives for player {data.UserId}:"); - var objectives = mind.AllObjectives.ToList(); - if (objectives.Count == 0) - { - shell.SendText(player, "None."); - } - for (var i = 0; i < objectives.Count; i++) - { - shell.SendText(player, $"- [{i}] {objectives[i]}"); - } - - } - } - - [AdminCommand(AdminFlags.Admin)] - public class RemoveObjectiveCommand : IClientCommand - { - public string Command => "rmobjective"; - public string Description => "Removes an objective from the player's mind."; - public string Help => "rmobjective "; - public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) - { - if (args.Length != 2) - { - shell.SendText(player, "Expected exactly 2 arguments."); - return; - } - - var mgr = IoCManager.Resolve(); - if (mgr.TryGetPlayerDataByUsername(args[0], out var data)) - { - var mind = data.ContentData()?.Mind; - if (mind == null) - { - shell.SendText(player, "Can't find the mind."); - return; - } - - if (int.TryParse(args[1], out var i)) - { - shell.SendText(player, - mind.TryRemoveObjective(i) - ? "Objective successfully removed!" - : "Objective removing failed. Maybe the index is out of bounds? Check lsobjectives!"); - } - else - { - shell.SendText(player, $"Invalid index {args[1]}!"); - } - } - else - { - shell.SendText(player, "Can't find the playerdata."); - } - } - } -} diff --git a/Content.Server/ServerNotifyManager.cs b/Content.Server/ServerNotifyManager.cs index aac886c0aa..6206e9838e 100644 --- a/Content.Server/ServerNotifyManager.cs +++ b/Content.Server/ServerNotifyManager.cs @@ -72,24 +72,5 @@ namespace Content.Server _netManager.ServerSendMessage(netMessage, actor.playerSession.ConnectedClient); } - - [AdminCommand(AdminFlags.Debug)] - public class PopupMsgCommand : IClientCommand - { - public string Command => "srvpopupmsg"; - public string Description => ""; - public string Help => ""; - - public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) - { - var entityMgr = IoCManager.Resolve(); - - var source = EntityUid.Parse(args[0]); - var viewer = EntityUid.Parse(args[1]); - var msg = args[2]; - - entityMgr.GetEntity(source).PopupMessage(entityMgr.GetEntity(viewer), msg); - } - } } }