diff --git a/.github/workflows/update-credits.yml b/.github/workflows/update-credits.yml index e35d4def7d..87babfa2a6 100644 --- a/.github/workflows/update-credits.yml +++ b/.github/workflows/update-credits.yml @@ -19,6 +19,8 @@ jobs: - name: Get this week's Contributors shell: pwsh + env: + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} run: Tools/dump_github_contributors.ps1 > Resources/Credits/GitHub.txt # TODO diff --git a/Content.Client/Examine/ExamineSystem.cs b/Content.Client/Examine/ExamineSystem.cs index a941f0acff..1c1f1984de 100644 --- a/Content.Client/Examine/ExamineSystem.cs +++ b/Content.Client/Examine/ExamineSystem.cs @@ -1,7 +1,12 @@ +using System.Linq; +using System.Numerics; +using System.Threading; using Content.Client.Verbs; using Content.Shared.Examine; using Content.Shared.IdentityManagement; using Content.Shared.Input; +using Content.Shared.Interaction.Events; +using Content.Shared.Item; using Content.Shared.Verbs; using JetBrains.Annotations; using Robust.Client.GameObjects; @@ -12,13 +17,8 @@ using Robust.Client.UserInterface.Controls; using Robust.Shared.Input.Binding; using Robust.Shared.Map; using Robust.Shared.Utility; -using System.Linq; -using System.Numerics; -using System.Threading; using static Content.Shared.Interaction.SharedInteractionSystem; using static Robust.Client.UserInterface.Controls.BoxContainer; -using Content.Shared.Interaction.Events; -using Content.Shared.Item; using Direction = Robust.Shared.Maths.Direction; namespace Content.Client.Examine @@ -35,7 +35,6 @@ namespace Content.Client.Examine private EntityUid _examinedEntity; private EntityUid _lastExaminedEntity; - private EntityUid _playerEntity; private Popup? _examineTooltipOpen; private ScreenCoordinates _popupPos; private CancellationTokenSource? _requestCancelTokenSource; @@ -74,9 +73,9 @@ namespace Content.Client.Examine public override void Update(float frameTime) { if (_examineTooltipOpen is not {Visible: true}) return; - if (!_examinedEntity.Valid || !_playerEntity.Valid) return; + if (!_examinedEntity.Valid || _playerManager.LocalEntity is not { } player) return; - if (!CanExamine(_playerEntity, _examinedEntity)) + if (!CanExamine(player, _examinedEntity)) CloseTooltip(); } @@ -114,9 +113,8 @@ namespace Content.Client.Examine return false; } - _playerEntity = _playerManager.LocalEntity ?? default; - - if (_playerEntity == default || !CanExamine(_playerEntity, entity)) + if (_playerManager.LocalEntity is not { } player || + !CanExamine(player, entity)) { return false; } diff --git a/Content.Client/Guidebook/GuidebookDataSystem.cs b/Content.Client/Guidebook/GuidebookDataSystem.cs new file mode 100644 index 0000000000..f47ad6ef1b --- /dev/null +++ b/Content.Client/Guidebook/GuidebookDataSystem.cs @@ -0,0 +1,45 @@ +using Content.Shared.Guidebook; + +namespace Content.Client.Guidebook; + +/// +/// Client system for storing and retrieving values extracted from entity prototypes +/// for display in the guidebook (). +/// Requests data from the server on . +/// Can also be pushed new data when the server reloads prototypes. +/// +public sealed class GuidebookDataSystem : EntitySystem +{ + private GuidebookData? _data; + + public override void Initialize() + { + base.Initialize(); + + SubscribeNetworkEvent(OnServerUpdated); + + // Request data from the server + RaiseNetworkEvent(new RequestGuidebookDataEvent()); + } + + private void OnServerUpdated(UpdateGuidebookDataEvent args) + { + // Got new data from the server, either in response to our request, or because prototypes reloaded on the server + _data = args.Data; + _data.Freeze(); + } + + /// + /// Attempts to retrieve a value using the given identifiers. + /// See for more information. + /// + public bool TryGetValue(string prototype, string component, string field, out object? value) + { + if (_data == null) + { + value = null; + return false; + } + return _data.TryGetValue(prototype, component, field, out value); + } +} diff --git a/Content.Client/Guidebook/Richtext/ProtodataTag.cs b/Content.Client/Guidebook/Richtext/ProtodataTag.cs new file mode 100644 index 0000000000..a725fd4e4b --- /dev/null +++ b/Content.Client/Guidebook/Richtext/ProtodataTag.cs @@ -0,0 +1,49 @@ +using System.Globalization; +using Robust.Client.UserInterface.RichText; +using Robust.Shared.Utility; + +namespace Content.Client.Guidebook.RichText; + +/// +/// RichText tag that can display values extracted from entity prototypes. +/// In order to be accessed by this tag, the desired field/property must +/// be tagged with . +/// +public sealed class ProtodataTag : IMarkupTag +{ + [Dependency] private readonly ILogManager _logMan = default!; + [Dependency] private readonly IEntityManager _entMan = default!; + + public string Name => "protodata"; + private ISawmill Log => _log ??= _logMan.GetSawmill("protodata_tag"); + private ISawmill? _log; + + public string TextBefore(MarkupNode node) + { + // Do nothing with an empty tag + if (!node.Value.TryGetString(out var prototype)) + return string.Empty; + + if (!node.Attributes.TryGetValue("comp", out var component)) + return string.Empty; + if (!node.Attributes.TryGetValue("member", out var member)) + return string.Empty; + node.Attributes.TryGetValue("format", out var format); + + var guidebookData = _entMan.System(); + + // Try to get the value + if (!guidebookData.TryGetValue(prototype, component.StringValue!, member.StringValue!, out var value)) + { + Log.Error($"Failed to find protodata for {component}.{member} in {prototype}"); + return "???"; + } + + // If we have a format string and a formattable value, format it as requested + if (!string.IsNullOrEmpty(format.StringValue) && value is IFormattable formattable) + return formattable.ToString(format.StringValue, CultureInfo.CurrentCulture); + + // No format string given, so just use default ToString + return value?.ToString() ?? "NULL"; + } +} diff --git a/Content.Client/MassMedia/Ui/ArticleEditorPanel.xaml b/Content.Client/MassMedia/Ui/ArticleEditorPanel.xaml index 2b600845ca..f4fb9da062 100644 --- a/Content.Client/MassMedia/Ui/ArticleEditorPanel.xaml +++ b/Content.Client/MassMedia/Ui/ArticleEditorPanel.xaml @@ -47,8 +47,10 @@ +