diff --git a/.github/workflows/prtitlecase.yml b/.github/workflows/prtitlecase.yml index b3150dcc7e9..4dc90019282 100644 --- a/.github/workflows/prtitlecase.yml +++ b/.github/workflows/prtitlecase.yml @@ -1,7 +1,8 @@ name: PR Title Case on: - pull_request_target: - types: [opened, edited, synchronize] + workflow_dispatch: + #pull_request_target: + # types: [opened, edited, synchronize] env: GITHUB_TOKEN: ${{ secrets.BOT_TOKEN }} diff --git a/.vscode/tasks.json b/.vscode/tasks.json index f51933bac0e..df2cf16c01d 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -72,6 +72,50 @@ "/consoleloggerparameters:NoSummary" ], "problemMatcher": "$msCompile" + }, + { + "label": "test", + "command": "dotnet", + "type": "shell", + "args": [ + "test", + "--no-build", + "--configuration", + "DebugOpt", + "Content.Tests/Content.Tests.csproj", + "--", + "NUnit.ConsoleOut=0" + ], + "group": { + "kind": "test" + }, + "presentation": { + "reveal": "silent" + }, + "problemMatcher": "$msCompile" + }, + { + "label": "integration-test", + "command": "dotnet", + "type": "shell", + "args": [ + "test", + "--no-build", + "--configuration", + "DebugOpt", + "Content.IntegrationTests/Content.IntegrationTests.csproj", + "--", + "NUnit.ConsoleOut=0", + "NUnit.MapWarningTo=Failed.ConsoleOut=0", + "NUnit.MapWarningTo=Failed" + ], + "group": { + "kind": "test" + }, + "presentation": { + "reveal": "silent" + }, + "problemMatcher": "$msCompile" } ] } diff --git a/Content.Client/Access/UI/IdCardConsoleWindow.xaml.cs b/Content.Client/Access/UI/IdCardConsoleWindow.xaml.cs index d79f4710513..4d586f85ae2 100644 --- a/Content.Client/Access/UI/IdCardConsoleWindow.xaml.cs +++ b/Content.Client/Access/UI/IdCardConsoleWindow.xaml.cs @@ -29,6 +29,9 @@ public sealed partial class IdCardConsoleWindow : DefaultWindow private string? _lastJobTitle; private string? _lastJobProto; + // The job that will be picked if the ID doesn't have a job on the station. + private static ProtoId _defaultJob = "Passenger"; + public IdCardConsoleWindow(IdCardConsoleBoundUserInterface owner, IPrototypeManager prototypeManager, List> accessLevels) { @@ -67,7 +70,6 @@ public IdCardConsoleWindow(IdCardConsoleBoundUserInterface owner, IPrototypeMana } JobPresetOptionButton.OnItemSelected += SelectJobPreset; - _accessButtons.Populate(accessLevels, prototypeManager); AccessLevelControlContainer.AddChild(_accessButtons); @@ -174,11 +176,15 @@ public void UpdateState(IdCardConsoleBoundUserInterfaceState state) new List>()); var jobIndex = _jobPrototypeIds.IndexOf(state.TargetIdJobPrototype); - if (jobIndex >= 0) + // If the job index is < 0 that means they don't have a job registered in the station records. + // For example, a new ID from a box would have no job index. + if (jobIndex < 0) { - JobPresetOptionButton.SelectId(jobIndex); + jobIndex = _jobPrototypeIds.IndexOf(_defaultJob); } + JobPresetOptionButton.SelectId(jobIndex); + _lastFullName = state.TargetIdFullName; _lastJobTitle = state.TargetIdJobTitle; _lastJobProto = state.TargetIdJobPrototype; diff --git a/Content.Client/Actions/ActionsSystem.cs b/Content.Client/Actions/ActionsSystem.cs index ba282b187c3..6b7402e0b3d 100644 --- a/Content.Client/Actions/ActionsSystem.cs +++ b/Content.Client/Actions/ActionsSystem.cs @@ -139,6 +139,7 @@ private void BaseHandleState(EntityUid uid, BaseActionComponent component, Ba component.Priority = state.Priority; component.AttachedEntity = EnsureEntity(state.AttachedEntity, uid); component.RaiseOnUser = state.RaiseOnUser; + component.RaiseOnAction = state.RaiseOnAction; component.AutoPopulate = state.AutoPopulate; component.Temporary = state.Temporary; component.ItemIconStyle = state.ItemIconStyle; @@ -260,13 +261,13 @@ public void UnlinkAllActions() public void LinkAllActions(ActionsComponent? actions = null) { - if (_playerManager.LocalEntity is not { } user || - !Resolve(user, ref actions, false)) - { - return; - } + if (_playerManager.LocalEntity is not { } user || + !Resolve(user, ref actions, false)) + { + return; + } - LinkActions?.Invoke(actions); + LinkActions?.Invoke(actions); } public override void Shutdown() diff --git a/Content.Client/Actions/UI/ActionAlertTooltip.cs b/Content.Client/Actions/UI/ActionAlertTooltip.cs index c126c27ce7c..2425cdefb91 100644 --- a/Content.Client/Actions/UI/ActionAlertTooltip.cs +++ b/Content.Client/Actions/UI/ActionAlertTooltip.cs @@ -77,14 +77,12 @@ public ActionAlertTooltip(FormattedMessage name, FormattedMessage? desc, string? MaxWidth = TooltipTextMaxWidth, StyleClasses = {StyleNano.StyleClassTooltipActionRequirements} }; - try - { - requiresLabel.SetMessage(FormattedMessage.FromMarkupOrThrow("[color=#635c5c]" + requires + "[/color]")); - } - catch(Exception e) - { - requiresLabel.SetMessage(e.Message); - } + + if (!FormattedMessage.TryFromMarkup("[color=#635c5c]" + requires + "[/color]", out var markup)) + return; + + requiresLabel.SetMessage(markup); + vbox.AddChild(requiresLabel); } } @@ -102,16 +100,11 @@ protected override void FrameUpdate(FrameEventArgs args) if (timeLeft > TimeSpan.Zero) { var duration = Cooldown.Value.End - Cooldown.Value.Start; - try - { - _cooldownLabel.SetMessage(FormattedMessage.FromMarkupOrThrow( - $"[color=#a10505]{(int) duration.TotalSeconds} sec cooldown ({(int) timeLeft.TotalSeconds + 1} sec remaining)[/color]")); - } - catch(Exception e) - { - _cooldownLabel.SetMessage(e.Message); - } + if (!FormattedMessage.TryFromMarkup(Loc.GetString("ui-actionslot-duration", ("duration", (int)duration.TotalSeconds), ("timeLeft", (int)timeLeft.TotalSeconds + 1)), out var markup)) + return; + + _cooldownLabel.SetMessage(markup); _cooldownLabel.Visible = true; } else diff --git a/Content.Client/Administration/AdminNameOverlay.cs b/Content.Client/Administration/AdminNameOverlay.cs index c17ecc7813a..3c968ec17cc 100644 --- a/Content.Client/Administration/AdminNameOverlay.cs +++ b/Content.Client/Administration/AdminNameOverlay.cs @@ -15,7 +15,6 @@ namespace Content.Client.Administration; internal sealed class AdminNameOverlay : Overlay { [Dependency] private readonly IConfigurationManager _config = default!; - [Dependency] private ILocalizationManager _localization = default!; private readonly AdminSystem _system; private readonly IEntityManager _entityManager; @@ -27,13 +26,13 @@ internal sealed class AdminNameOverlay : Overlay //TODO make this adjustable via GUI private readonly ProtoId[] _filter = ["SoloAntagonist", "TeamAntagonist", "SiliconAntagonist", "FreeAgent"]; - private readonly string _antagLabelClassic = ""; + private readonly string _antagLabelClassic = Loc.GetString("admin-overlay-antag-classic"); private readonly Color _antagColorClassic = Color.OrangeRed; public AdminNameOverlay(AdminSystem system, IEntityManager entityManager, IEyeManager eyeManager, IResourceCache resourceCache, EntityLookupSystem entityLookup, IUserInterfaceManager userInterfaceManager) { IoCManager.InjectDependencies(this); - _antagLabelClassic = _localization.GetString("admin-overlay-antag-classic"); + _system = system; _entityManager = entityManager; _eyeManager = eyeManager; @@ -51,6 +50,8 @@ protected override void Draw(in OverlayDrawArgs args) //TODO make this adjustable via GUI var classic = _config.GetCVar(CCVars.AdminOverlayClassic); + var playTime = _config.GetCVar(CCVars.AdminOverlayPlaytime); + var startingJob = _config.GetCVar(CCVars.AdminOverlayStartingJob); foreach (var playerInfo in _system.PlayerList) { @@ -77,25 +78,44 @@ protected override void Draw(in OverlayDrawArgs args) } var uiScale = _userInterfaceManager.RootControl.UIScale; - var lineoffset = new Vector2(0f, 11f) * uiScale; + var lineoffset = new Vector2(0f, 14f) * uiScale; var screenCoordinates = _eyeManager.WorldToScreen(aabb.Center + new Angle(-_eyeManager.CurrentEye.Rotation).RotateVec( aabb.TopRight - aabb.Center)) + new Vector2(1f, 7f); - if (classic && playerInfo.Antag) + var currentOffset = Vector2.Zero; + + args.ScreenHandle.DrawString(_font, screenCoordinates + currentOffset, playerInfo.CharacterName, uiScale, playerInfo.Connected ? Color.Aquamarine : Color.White); + currentOffset += lineoffset; + + args.ScreenHandle.DrawString(_font, screenCoordinates + currentOffset, playerInfo.Username, uiScale, playerInfo.Connected ? Color.Yellow : Color.White); + currentOffset += lineoffset; + + if (!string.IsNullOrEmpty(playerInfo.PlaytimeString) && playTime) { - args.ScreenHandle.DrawString(_font, screenCoordinates + (lineoffset * 2), _antagLabelClassic, uiScale, _antagColorClassic); + args.ScreenHandle.DrawString(_font, screenCoordinates + currentOffset, playerInfo.PlaytimeString, uiScale, playerInfo.Connected ? Color.Orange : Color.White); + currentOffset += lineoffset; } - else if (!classic && _filter.Contains(playerInfo.RoleProto.ID)) + + if (!string.IsNullOrEmpty(playerInfo.StartingJob) && startingJob) { - var label = _localization.GetString(playerInfo.RoleProto.Name).ToUpper(); - var color = playerInfo.RoleProto.Color; + args.ScreenHandle.DrawString(_font, screenCoordinates + currentOffset, Loc.GetString(playerInfo.StartingJob), uiScale, playerInfo.Connected ? Color.GreenYellow : Color.White); + currentOffset += lineoffset; + } - args.ScreenHandle.DrawString(_font, screenCoordinates + (lineoffset * 2), label, uiScale, color); + if (classic && playerInfo.Antag) + { + args.ScreenHandle.DrawString(_font, screenCoordinates + currentOffset, _antagLabelClassic, uiScale, Color.OrangeRed); + currentOffset += lineoffset; } + else if (!classic && _filter.Contains(playerInfo.RoleProto)) + { + var label = Loc.GetString(playerInfo.RoleProto.Name).ToUpper(); + var color = playerInfo.RoleProto.Color; - args.ScreenHandle.DrawString(_font, screenCoordinates + lineoffset, playerInfo.Username, uiScale, playerInfo.Connected ? Color.Yellow : Color.White); - args.ScreenHandle.DrawString(_font, screenCoordinates, playerInfo.CharacterName, uiScale, playerInfo.Connected ? Color.Aquamarine : Color.White); + args.ScreenHandle.DrawString(_font, screenCoordinates + currentOffset, label, uiScale, color); + currentOffset += lineoffset; + } } } } diff --git a/Content.Client/Administration/Systems/BwoinkSystem.cs b/Content.Client/Administration/Systems/BwoinkSystem.cs index a3b295d6b6e..c4f2607746f 100644 --- a/Content.Client/Administration/Systems/BwoinkSystem.cs +++ b/Content.Client/Administration/Systems/BwoinkSystem.cs @@ -24,7 +24,7 @@ protected override void OnBwoinkTextMessage(BwoinkTextMessage message, EntitySes OnBwoinkTextMessageRecieved?.Invoke(this, message); } - public void Send(NetUserId channelId, string text, bool playSound) + public void Send(NetUserId channelId, string text, bool playSound, bool adminOnly) { var info = _adminSystem.PlayerInfos.GetValueOrDefault(channelId)?.Connected ?? true; _audio.PlayGlobal(info ? AHelpUIController.AHelpSendSound : AHelpUIController.AHelpErrorSound, @@ -32,7 +32,7 @@ public void Send(NetUserId channelId, string text, bool playSound) // Reuse the channel ID as the 'true sender'. // Server will ignore this and if someone makes it not ignore this (which is bad, allows impersonation!!!), that will help. - RaiseNetworkEvent(new BwoinkTextMessage(channelId, channelId, text, playSound: playSound)); + RaiseNetworkEvent(new BwoinkTextMessage(channelId, channelId, text, playSound: playSound, adminOnly: adminOnly)); SendInputTextUpdated(channelId, false); } diff --git a/Content.Client/Administration/UI/AdminMenuWindow.xaml b/Content.Client/Administration/UI/AdminMenuWindow.xaml index d3d3df02d93..311d67b826c 100644 --- a/Content.Client/Administration/UI/AdminMenuWindow.xaml +++ b/Content.Client/Administration/UI/AdminMenuWindow.xaml @@ -6,8 +6,7 @@ xmlns:tabs="clr-namespace:Content.Client.Administration.UI.Tabs" xmlns:playerTab="clr-namespace:Content.Client.Administration.UI.Tabs.PlayerTab" xmlns:objectsTab="clr-namespace:Content.Client.Administration.UI.Tabs.ObjectsTab" - xmlns:panic="clr-namespace:Content.Client.Administration.UI.Tabs.PanicBunkerTab" - xmlns:baby="clr-namespace:Content.Client.Administration.UI.Tabs.BabyJailTab"> + xmlns:panic="clr-namespace:Content.Client.Administration.UI.Tabs.PanicBunkerTab"> @@ -15,7 +14,6 @@ - diff --git a/Content.Client/Administration/UI/AdminMenuWindow.xaml.cs b/Content.Client/Administration/UI/AdminMenuWindow.xaml.cs index b990f3e01e4..0aac0be6884 100644 --- a/Content.Client/Administration/UI/AdminMenuWindow.xaml.cs +++ b/Content.Client/Administration/UI/AdminMenuWindow.xaml.cs @@ -9,25 +9,21 @@ namespace Content.Client.Administration.UI; public sealed partial class AdminMenuWindow : DefaultWindow { public event Action? OnDisposed; - [Dependency] private readonly ILocalizationManager _localization = default!; + public AdminMenuWindow() { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); MinSize = new Vector2(650, 250); - Title = _localization.GetString("admin-menu-title"); - MasterTabContainer.SetTabTitle((int) TabIndex.Admin, _localization.GetString("admin-menu-admin-tab")); - MasterTabContainer.SetTabTitle((int) TabIndex.Adminbus, _localization.GetString("admin-menu-adminbus-tab")); - MasterTabContainer.SetTabTitle((int) TabIndex.Atmos, _localization.GetString("admin-menu-atmos-tab")); - MasterTabContainer.SetTabTitle((int) TabIndex.Round, _localization.GetString("admin-menu-round-tab")); - MasterTabContainer.SetTabTitle((int) TabIndex.Server, _localization.GetString("admin-menu-server-tab")); - MasterTabContainer.SetTabTitle((int) TabIndex.PanicBunker, _localization.GetString("admin-menu-panic-bunker-tab")); - /* - * TODO: Remove baby jail code once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future. - */ - MasterTabContainer.SetTabTitle((int) TabIndex.BabyJail, _localization.GetString("admin-menu-baby-jail-tab")); - MasterTabContainer.SetTabTitle((int) TabIndex.Players, _localization.GetString("admin-menu-players-tab")); - MasterTabContainer.SetTabTitle((int) TabIndex.Objects, _localization.GetString("admin-menu-objects-tab")); + Title = Loc.GetString("admin-menu-title"); + MasterTabContainer.SetTabTitle((int) TabIndex.Admin, Loc.GetString("admin-menu-admin-tab")); + MasterTabContainer.SetTabTitle((int) TabIndex.Adminbus, Loc.GetString("admin-menu-adminbus-tab")); + MasterTabContainer.SetTabTitle((int) TabIndex.Atmos, Loc.GetString("admin-menu-atmos-tab")); + MasterTabContainer.SetTabTitle((int) TabIndex.Round, Loc.GetString("admin-menu-round-tab")); + MasterTabContainer.SetTabTitle((int) TabIndex.Server, Loc.GetString("admin-menu-server-tab")); + MasterTabContainer.SetTabTitle((int) TabIndex.PanicBunker, Loc.GetString("admin-menu-panic-bunker-tab")); + MasterTabContainer.SetTabTitle((int) TabIndex.Players, Loc.GetString("admin-menu-players-tab")); + MasterTabContainer.SetTabTitle((int) TabIndex.Objects, Loc.GetString("admin-menu-objects-tab")); MasterTabContainer.OnTabChanged += OnTabChanged; } @@ -53,7 +49,6 @@ private enum TabIndex Round, Server, PanicBunker, - BabyJail, Players, Objects, } diff --git a/Content.Client/Administration/UI/Bwoink/BwoinkControl.xaml b/Content.Client/Administration/UI/Bwoink/BwoinkControl.xaml index 39ea50edbef..d53101f68e9 100644 --- a/Content.Client/Administration/UI/Bwoink/BwoinkControl.xaml +++ b/Content.Client/Administration/UI/Bwoink/BwoinkControl.xaml @@ -2,22 +2,26 @@ xmlns="https://spacestation14.io" xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"> - - - - - - - - + +