diff --git a/Content.Server/Administration/Commands/Station/AdjustStationJobCommand.cs b/Content.Server/Administration/Commands/Station/AdjustStationJobCommand.cs new file mode 100644 index 0000000000..2a697cab2e --- /dev/null +++ b/Content.Server/Administration/Commands/Station/AdjustStationJobCommand.cs @@ -0,0 +1,57 @@ +using Content.Server.Station; +using Content.Shared.Administration; +using Content.Shared.Roles; +using Content.Shared.Station; +using Robust.Shared.Console; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using Robust.Shared.Prototypes; + +namespace Content.Server.Administration.Commands.Station; + +[AdminCommand(AdminFlags.Spawn)] +public class AdjustStationJobCommand : IConsoleCommand +{ + public string Command => "adjstationjob"; + + public string Description => "Adjust the job manifest on a station."; + + public string Help => "adjstationjob "; + + public void Execute(IConsoleShell shell, string argStr, string[] args) + { + if (args.Length != 3) + { + shell.WriteError(Loc.GetString("shell-wrong-arguments-number")); + return; + } + + + var stationSystem = EntitySystem.Get(); + + if (!uint.TryParse(args[0], out var station) || !stationSystem.StationInfo.ContainsKey(new StationId(station))) + { + shell.WriteError(Loc.GetString("shell-argument-station-id-invalid", ("index", 1))); + return; + } + + var prototypeManager = IoCManager.Resolve(); + + if (!prototypeManager.TryIndex(args[1], out var job)) + { + shell.WriteError(Loc.GetString("shell-argument-must-be-prototype", + ("index", 2), ("prototypeName", nameof(JobPrototype)))); + return; + } + + if (!int.TryParse(args[2], out var amount) || amount < -1) + { + shell.WriteError(Loc.GetString("shell-argument-number-must-be-between", + ("index", 3), ("lower", -1), ("upper", int.MaxValue))); + return; + } + + stationSystem.AdjustJobsAvailableOnStation(new StationId(station), job, amount); + } +} diff --git a/Content.Server/Administration/Commands/Station/ListStationJobsCommand.cs b/Content.Server/Administration/Commands/Station/ListStationJobsCommand.cs new file mode 100644 index 0000000000..68458c6d01 --- /dev/null +++ b/Content.Server/Administration/Commands/Station/ListStationJobsCommand.cs @@ -0,0 +1,40 @@ +using Content.Server.Station; +using Content.Shared.Administration; +using Content.Shared.Station; +using Robust.Shared.Console; +using Robust.Shared.GameObjects; +using Robust.Shared.Localization; + +namespace Content.Server.Administration.Commands.Station; + +[AdminCommand(AdminFlags.Admin)] +public class ListStationJobsCommand : IConsoleCommand +{ + public string Command => "lsstationjobs"; + + public string Description => "Lists all jobs on the given station."; + + public string Help => "lsstationjobs "; + + public void Execute(IConsoleShell shell, string argStr, string[] args) + { + if (args.Length != 1) + { + shell.WriteError(Loc.GetString("shell-wrong-arguments-number")); + return; + } + + var stationSystem = EntitySystem.Get(); + + if (!uint.TryParse(args[0], out var station) || !stationSystem.StationInfo.ContainsKey(new StationId(station))) + { + shell.WriteError(Loc.GetString("shell-argument-station-id-invalid", ("index", 1))); + return; + } + + foreach (var (job, amount) in stationSystem.StationInfo[new StationId(station)].JobList) + { + shell.WriteLine($"{job}: {amount}"); + } + } +} diff --git a/Content.Server/Administration/Commands/Station/ListStationsCommand.cs b/Content.Server/Administration/Commands/Station/ListStationsCommand.cs new file mode 100644 index 0000000000..29a513f317 --- /dev/null +++ b/Content.Server/Administration/Commands/Station/ListStationsCommand.cs @@ -0,0 +1,24 @@ +using Content.Server.Station; +using Content.Shared.Administration; +using Robust.Shared.Console; +using Robust.Shared.GameObjects; + +namespace Content.Server.Administration.Commands.Station; + +[AdminCommand(AdminFlags.Admin)] +public class ListStationsCommand : IConsoleCommand +{ + public string Command => "lsstations"; + + public string Description => "List all active stations"; + + public string Help => "lsstations"; + + public void Execute(IConsoleShell shell, string argStr, string[] args) + { + foreach (var (id, station) in EntitySystem.Get().StationInfo) + { + shell.WriteLine($"{id.Id, -2} | {station.Name} | {station.MapPrototype.ID}"); + } + } +} diff --git a/Content.Server/Administration/Commands/Station/RenameStationCommand.cs b/Content.Server/Administration/Commands/Station/RenameStationCommand.cs new file mode 100644 index 0000000000..c0b742779a --- /dev/null +++ b/Content.Server/Administration/Commands/Station/RenameStationCommand.cs @@ -0,0 +1,37 @@ +using Content.Server.Station; +using Content.Shared.Administration; +using Content.Shared.Station; +using Robust.Shared.Console; +using Robust.Shared.GameObjects; +using Robust.Shared.Localization; + +namespace Content.Server.Administration.Commands.Station; + +[AdminCommand(AdminFlags.Admin)] +public class RenameStationCommand : IConsoleCommand +{ + public string Command => "renamestation"; + + public string Description => "Renames the given station"; + + public string Help => "renamestation "; + + public void Execute(IConsoleShell shell, string argStr, string[] args) + { + if (args.Length != 2) + { + shell.WriteError(Loc.GetString("shell-wrong-arguments-number")); + return; + } + + var stationSystem = EntitySystem.Get(); + + if (!uint.TryParse(args[0], out var station) || !stationSystem.StationInfo.ContainsKey(new StationId(station))) + { + shell.WriteError(Loc.GetString("shell-argument-station-id-invalid", ("index", 1))); + return; + } + + stationSystem.RenameStation(new StationId(station), args[1]); + } +} diff --git a/Content.Server/GameTicking/Commands/JoinGameCommand.cs b/Content.Server/GameTicking/Commands/JoinGameCommand.cs index 176a8a430e..fb966c32b8 100644 --- a/Content.Server/GameTicking/Commands/JoinGameCommand.cs +++ b/Content.Server/GameTicking/Commands/JoinGameCommand.cs @@ -65,9 +65,9 @@ namespace Content.Server.GameTicking.Commands } var stationId = new StationId(sid); - if(!stationSystem.IsJobAvailableOnStation(stationId, id)) + var jobPrototype = _prototypeManager.Index(id); + if(!stationSystem.IsJobAvailableOnStation(stationId, jobPrototype)) { - var jobPrototype = _prototypeManager.Index(id); shell.WriteLine($"{jobPrototype.Name} has no available slots."); return; } diff --git a/Content.Server/GameTicking/GameTicker.Spawning.cs b/Content.Server/GameTicking/GameTicker.Spawning.cs index f13b067b8d..00bde9cc6b 100644 --- a/Content.Server/GameTicking/GameTicker.Spawning.cs +++ b/Content.Server/GameTicking/GameTicker.Spawning.cs @@ -134,7 +134,7 @@ namespace Content.Server.GameTicking jobSpecial.AfterEquip(mob); } - _stationSystem.TryAssignJobToStation(station, jobId); + _stationSystem.TryAssignJobToStation(station, jobPrototype); if (lateJoin) _adminLogSystem.Add(LogType.LateJoin, LogImpact.Medium, $"Player {player.Name} late joined as {character.Name:characterName} on station {_stationSystem.StationInfo[station].Name:stationName} with {mob} as a {job.Name:jobName}."); diff --git a/Content.Server/Station/StationSystem.cs b/Content.Server/Station/StationSystem.cs index b6411a507d..19fa9be7af 100644 --- a/Content.Server/Station/StationSystem.cs +++ b/Content.Server/Station/StationSystem.cs @@ -1,12 +1,15 @@ using System; using System.Collections.Generic; using System.Linq; +using Content.Server.Chat.Managers; using Content.Server.GameTicking; using Content.Server.Maps; +using Content.Shared.Roles; using Content.Shared.Station; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Log; +using Robust.Shared.Utility; namespace Content.Server.Station; @@ -16,6 +19,7 @@ namespace Content.Server.Station; public class StationSystem : EntitySystem { [Dependency] private GameTicker _gameTicker = default!; + [Dependency] private IChatManager _chatManager = default!; [Dependency] private IGameMapManager _gameMapManager = default!; private uint _idCounter = 1; @@ -42,7 +46,7 @@ public class StationSystem : EntitySystem public class StationInfoData { - public readonly string Name; + public string Name; /// /// Job list associated with the game map. @@ -83,6 +87,13 @@ public class StationSystem : EntitySystem return false; } } + + public bool AdjustJobAmount(string jobName, int amount) + { + DebugTools.Assert(amount >= -1); + _jobList[jobName] = amount; + return true; + } } /// @@ -133,14 +144,15 @@ public class StationSystem : EntitySystem /// /// Attempts to assign a job on the given station. + /// Does NOT inform the gameticker that the job roster has changed. /// /// station to assign to - /// name of the job + /// name of the job /// assignment success - public bool TryAssignJobToStation(StationId stationId, string jobName) + public bool TryAssignJobToStation(StationId stationId, JobPrototype job) { if (stationId != StationId.Invalid) - return _stationInfo[stationId].TryAssignJob(jobName); + return _stationInfo[stationId].TryAssignJob(job.ID); else return false; } @@ -149,11 +161,11 @@ public class StationSystem : EntitySystem /// Checks if the given job is available. /// /// station to check - /// name of the job + /// name of the job /// job availability - public bool IsJobAvailableOnStation(StationId stationId, string jobName) + public bool IsJobAvailableOnStation(StationId stationId, JobPrototype job) { - if (_stationInfo[stationId].JobList.TryGetValue(jobName, out var amount)) + if (_stationInfo[stationId].JobList.TryGetValue(job.ID, out var amount)) return amount != 0; return false; @@ -163,4 +175,24 @@ public class StationSystem : EntitySystem { return new StationId(_idCounter++); } + + public bool AdjustJobsAvailableOnStation(StationId stationId, JobPrototype job, int amount) + { + var ret = _stationInfo[stationId].AdjustJobAmount(job.ID, amount); + _gameTicker.UpdateJobsAvailable(); + return ret; + } + + public void RenameStation(StationId stationId, string name, bool loud = true) + { + var oldName = _stationInfo[stationId].Name; + _stationInfo[stationId].Name = name; + if (loud) + { + _chatManager.DispatchStationAnnouncement($"The station {oldName} has been renamed to {name}."); + } + + // Make sure lobby gets the memo. + _gameTicker.UpdateJobsAvailable(); + } } diff --git a/Resources/Locale/en-US/shell.ftl b/Resources/Locale/en-US/shell.ftl index ee3d6d7fff..0c6cbcabf4 100644 --- a/Resources/Locale/en-US/shell.ftl +++ b/Resources/Locale/en-US/shell.ftl @@ -30,3 +30,6 @@ shell-invalid-color-hex = Invalid color hex! shell-target-player-does-not-exist = Target player does not exist! shell-target-entity-does-not-have-message = Target entity does not have a(n) {$missing}! shell-timespan-minutes-must-be-correct = {$span} is not a valid minutes timespan. +shell-argument-must-be-prototype = Argument {$index} must be a ${prototypeName}! +shell-argument-number-must-be-between = Argument {$index} must be a number between {$lower} and {$upper}! +shell-argument-station-id-invalid = Argument {$index} must be a valid station id!