Merge remote-tracking branch 'upstream/master' into ed-13-06-2024-upstream2

# Conflicts:
#	Content.Client/Guidebook/GuidebookSystem.cs
#	Content.Server/Damage/Systems/DamageOtherOnHitSystem.cs
#	Content.Shared/Guidebook/GuideEntry.cs
#	Content.Shared/Preferences/HumanoidCharacterProfile.cs
#	Resources/Prototypes/Accents/word_replacements.yml
#	Resources/Prototypes/Maps/arenas.yml
#	Resources/Prototypes/Maps/atlas.yml
#	Resources/Prototypes/Maps/bagel.yml
#	Resources/Prototypes/Maps/box.yml
#	Resources/Prototypes/Maps/cluster.yml
#	Resources/Prototypes/Maps/core.yml
#	Resources/Prototypes/Maps/debug.yml
#	Resources/Prototypes/Maps/europa.yml
#	Resources/Prototypes/Maps/fland.yml
#	Resources/Prototypes/Maps/marathon.yml
#	Resources/Prototypes/Maps/meta.yml
#	Resources/Prototypes/Maps/oasis.yml
#	Resources/Prototypes/Maps/omega.yml
#	Resources/Prototypes/Maps/origin.yml
#	Resources/Prototypes/Maps/packed.yml
#	Resources/Prototypes/Maps/reach.yml
#	Resources/Prototypes/Maps/saltern.yml
#	Resources/Prototypes/Maps/train.yml
#	Resources/Prototypes/lobbyscreens.yml
This commit is contained in:
Ed
2024-06-13 12:35:00 +03:00
475 changed files with 23765 additions and 12166 deletions

View File

@@ -1,4 +1,5 @@
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
using Content.Shared.Guidebook;
using Robust.Shared.Prototypes;
namespace Content.Client.Guidebook.Components;
@@ -13,9 +14,8 @@ public sealed partial class GuideHelpComponent : Component
/// What guides to include show when opening the guidebook. The first entry will be used to select the currently
/// selected guidebook.
/// </summary>
[DataField("guides", customTypeSerializer: typeof(PrototypeIdListSerializer<GuideEntryPrototype>), required: true)]
[ViewVariables]
public List<string> Guides = new();
[DataField(required: true)]
public List<ProtoId<GuideEntryPrototype>> Guides = new();
/// <summary>
/// Whether or not to automatically include the children of the given guides.

View File

@@ -2,7 +2,7 @@
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
xmlns:fancyTree="clr-namespace:Content.Client.UserInterface.Controls.FancyTree"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
SetSize="750 700"
SetSize="900 700"
MinSize="100 200"
Resizable="True"
Title="{Loc 'guidebook-window-title'}">
@@ -18,12 +18,16 @@
Name="SearchBar"
PlaceHolder="{Loc 'guidebook-filter-placeholder-text'}"
HorizontalExpand="True"
Margin="0 5 10 5">
Margin="0 5 10 5">
</LineEdit>
</BoxContainer>
<BoxContainer Access="Internal" Name="ReturnContainer" Orientation="Horizontal" HorizontalAlignment="Right" Visible="False">
<Button Name="HomeButton" Text="{Loc 'ui-rules-button-home'}" Margin="0 0 10 0"/>
</BoxContainer>
<ScrollContainer Name="Scroll" HScrollEnabled="False" HorizontalExpand="True" VerticalExpand="True">
<Control>
<BoxContainer Orientation="Vertical" Name="EntryContainer" Margin="5 5 5 5" Visible="False"/>
<BoxContainer Orientation="Vertical" Name="EntryContainer" Margin="5 5 5 5" Visible="False">
</BoxContainer>
<BoxContainer Orientation="Vertical" Name="Placeholder" Margin="5 5 5 5">
<Label HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Loc 'guidebook-placeholder-text'}"/>
<Label HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Loc 'guidebook-placeholder-text-2'}"/>

View File

@@ -1,15 +1,17 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Client.Guidebook.RichText;
using Content.Client.UserInterface.ControlExtensions;
using Content.Client.UserInterface.Controls;
using Content.Client.UserInterface.Controls.FancyTree;
using JetBrains.Annotations;
using Content.Client.UserInterface.Systems.Info;
using Content.Shared.CCVar;
using Content.Shared.Guidebook;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Configuration;
using Robust.Shared.ContentPack;
using Robust.Shared.Prototypes;
namespace Content.Client.Guidebook.Controls;
@@ -19,7 +21,7 @@ public sealed partial class GuidebookWindow : FancyWindow, ILinkClickHandler
[Dependency] private readonly IResourceManager _resourceManager = default!;
[Dependency] private readonly DocumentParsingManager _parsingMan = default!;
private Dictionary<string, GuideEntry> _entries = new();
private Dictionary<ProtoId<GuideEntryPrototype>, GuideEntry> _entries = new();
public GuidebookWindow()
{
@@ -37,7 +39,13 @@ public sealed partial class GuidebookWindow : FancyWindow, ILinkClickHandler
private void OnSelectionChanged(TreeItem? item)
{
if (item != null && item.Metadata is GuideEntry entry)
{
ShowGuide(entry);
var isRulesEntry = entry.RuleEntry;
ReturnContainer.Visible = isRulesEntry;
HomeButton.OnPressed += _ => ShowGuide(entry);
}
else
ClearSelectedGuide();
}
@@ -69,10 +77,10 @@ public sealed partial class GuidebookWindow : FancyWindow, ILinkClickHandler
}
public void UpdateGuides(
Dictionary<string, GuideEntry> entries,
List<string>? rootEntries = null,
string? forceRoot = null,
string? selected = null)
Dictionary<ProtoId<GuideEntryPrototype>, GuideEntry> entries,
List<ProtoId<GuideEntryPrototype>>? rootEntries = null,
ProtoId<GuideEntryPrototype>? forceRoot = null,
ProtoId<GuideEntryPrototype>? selected = null)
{
_entries = entries;
RepopulateTree(rootEntries, forceRoot);
@@ -98,11 +106,11 @@ public sealed partial class GuidebookWindow : FancyWindow, ILinkClickHandler
}
}
private IEnumerable<GuideEntry> GetSortedEntries(List<string>? rootEntries)
private IEnumerable<GuideEntry> GetSortedEntries(List<ProtoId<GuideEntryPrototype>>? rootEntries)
{
if (rootEntries == null)
{
HashSet<string> entries = new(_entries.Keys);
HashSet<ProtoId<GuideEntryPrototype>> entries = new(_entries.Keys);
foreach (var entry in _entries.Values)
{
if (entry.Children.Count > 0)
@@ -111,7 +119,7 @@ public sealed partial class GuidebookWindow : FancyWindow, ILinkClickHandler
.Select(childId => _entries[childId])
.OrderBy(childEntry => childEntry.Priority)
.ThenBy(childEntry => Loc.GetString(childEntry.Name))
.Select(childEntry => childEntry.Id)
.Select(childEntry => new ProtoId<GuideEntryPrototype>(childEntry.Id))
.ToList();
entry.Children = sortedChildren;
@@ -127,13 +135,13 @@ public sealed partial class GuidebookWindow : FancyWindow, ILinkClickHandler
.ThenBy(rootEntry => Loc.GetString(rootEntry.Name));
}
private void RepopulateTree(List<string>? roots = null, string? forcedRoot = null)
private void RepopulateTree(List<ProtoId<GuideEntryPrototype>>? roots = null, ProtoId<GuideEntryPrototype>? forcedRoot = null)
{
Tree.Clear();
HashSet<string> addedEntries = new();
HashSet<ProtoId<GuideEntryPrototype>> addedEntries = new();
TreeItem? parent = forcedRoot == null ? null : AddEntry(forcedRoot, null, addedEntries);
TreeItem? parent = forcedRoot == null ? null : AddEntry(forcedRoot.Value, null, addedEntries);
foreach (var entry in GetSortedEntries(roots))
{
if (!entry.CrystallPunkAllowed) continue; //CrystallPunk guidebook filter
@@ -142,17 +150,23 @@ public sealed partial class GuidebookWindow : FancyWindow, ILinkClickHandler
Tree.SetAllExpanded(true);
}
private TreeItem? AddEntry(string id, TreeItem? parent, HashSet<string> addedEntries)
private TreeItem? AddEntry(ProtoId<GuideEntryPrototype> id, TreeItem? parent, HashSet<ProtoId<GuideEntryPrototype>> addedEntries)
{
if (!_entries.TryGetValue(id, out var entry))
return null;
if (!addedEntries.Add(id))
{
// TODO GUIDEBOOK Maybe allow duplicate entries?
// E.g., for adding medicine under both chemicals & the chemist job
Logger.Error($"Adding duplicate guide entry: {id}");
return null;
}
var rulesProto = UserInterfaceManager.GetUIController<InfoUIController>().GetCoreRuleEntry();
if (entry.RuleEntry && entry.Id != rulesProto.Id)
return null;
var item = Tree.AddItem(parent);
item.Metadata = entry;
var name = Loc.GetString(entry.Name);

View File

@@ -1,7 +1,10 @@
using System.Linq;
using Content.Client.Guidebook.Richtext;
using Content.Shared.Guidebook;
using Pidgin;
using Robust.Client.UserInterface;
using Robust.Shared.ContentPack;
using Robust.Shared.Prototypes;
using Robust.Shared.Reflection;
using Robust.Shared.Sandboxing;
using static Pidgin.Parser;
@@ -13,7 +16,9 @@ namespace Content.Client.Guidebook;
/// </summary>
public sealed partial class DocumentParsingManager
{
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly IReflectionManager _reflectionManager = default!;
[Dependency] private readonly IResourceManager _resourceManager = default!;
[Dependency] private readonly ISandboxHelper _sandboxHelper = default!;
private readonly Dictionary<string, Parser<char, Control>> _tagControlParsers = new();
@@ -37,6 +42,21 @@ public sealed partial class DocumentParsingManager
ControlParser = SkipWhitespaces.Then(_controlParser.Many());
}
public bool TryAddMarkup(Control control, ProtoId<GuideEntryPrototype> entryId, bool log = true)
{
if (!_prototype.TryIndex(entryId, out var entry))
return false;
using var file = _resourceManager.ContentFileReadText(entry.Text);
return TryAddMarkup(control, file.ReadToEnd(), log);
}
public bool TryAddMarkup(Control control, GuideEntry entry, bool log = true)
{
using var file = _resourceManager.ContentFileReadText(entry.Text);
return TryAddMarkup(control, file.ReadToEnd(), log);
}
public bool TryAddMarkup(Control control, string text, bool log = true)
{
try

View File

@@ -1,51 +0,0 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
using Robust.Shared.Utility;
namespace Content.Client.Guidebook;
[Virtual]
public class GuideEntry
{
/// <summary>
/// The file containing the contents of this guide.
/// </summary>
[DataField("text", required: true)] public ResPath Text = default!;
/// <summary>
/// The unique id for this guide.
/// </summary>
[IdDataField]
public string Id = default!;
/// <summary>
/// The name of this guide. This gets localized.
/// </summary>
[DataField("name", required: true)] public string Name = default!;
/// <summary>
/// The "children" of this guide for when guides are shown in a tree / table of contents.
/// </summary>
[DataField("children", customTypeSerializer:typeof(PrototypeIdListSerializer<GuideEntryPrototype>))]
public List<string> Children = new();
/// <summary>
/// Enable filtering of items.
/// </summary>
[DataField("filterEnabled")] public bool FilterEnabled = default!;
/// <summary>
/// Priority for sorting top-level guides when shown in a tree / table of contents.
/// If the guide is the child of some other guide, the order simply determined by the order of children in <see cref="Children"/>.
/// </summary>
[DataField("priority")] public int Priority = 0;
[DataField]
public bool CrystallPunkAllowed = false;
}
[Prototype("guideEntry")]
public sealed partial class GuideEntryPrototype : GuideEntry, IPrototype
{
public string ID => Id;
}

View File

@@ -2,6 +2,7 @@ using System.Linq;
using Content.Client.Guidebook.Components;
using Content.Client.Light;
using Content.Client.Verbs;
using Content.Shared.Guidebook;
using Content.Shared.Interaction;
using Content.Shared.Light.Components;
using Content.Shared.Speech;
@@ -31,10 +32,14 @@ public sealed class GuidebookSystem : EntitySystem
[Dependency] private readonly RgbLightControllerSystem _rgbLightControllerSystem = default!;
[Dependency] private readonly SharedPointLightSystem _pointLightSystem = default!;
[Dependency] private readonly TagSystem _tags = default!;
[Dependency] private readonly IPrototypeManager _proto = default!; //CrystallPunk guidebook filter
public event Action<List<string>, List<string>?, string?, bool, string?>? OnGuidebookOpen;
public event Action<List<ProtoId<GuideEntryPrototype>>,
List<ProtoId<GuideEntryPrototype>>?,
ProtoId<GuideEntryPrototype>?,
bool,
ProtoId<GuideEntryPrototype>?>? OnGuidebookOpen;
public const string GuideEmbedTag = "GuideEmbeded";
private EntityUid _defaultUser;
@@ -99,7 +104,7 @@ public sealed class GuidebookSystem : EntitySystem
});
}
public void OpenHelp(List<string> guides)
public void OpenHelp(List<ProtoId<GuideEntryPrototype>> guides)
{
OnGuidebookOpen?.Invoke(guides, null, null, true, guides[0]);
}