Convert rules to use guidebook parsing (#28647)
This commit is contained in:
@@ -2,11 +2,9 @@ using Content.Client.Administration.Managers;
|
||||
using Content.Client.Changelog;
|
||||
using Content.Client.Chat.Managers;
|
||||
using Content.Client.Eui;
|
||||
using Content.Client.Flash;
|
||||
using Content.Client.Fullscreen;
|
||||
using Content.Client.GhostKick;
|
||||
using Content.Client.Guidebook;
|
||||
using Content.Client.Info;
|
||||
using Content.Client.Input;
|
||||
using Content.Client.IoC;
|
||||
using Content.Client.Launcher;
|
||||
@@ -52,7 +50,6 @@ namespace Content.Client.Entry
|
||||
[Dependency] private readonly IScreenshotHook _screenshotHook = default!;
|
||||
[Dependency] private readonly FullscreenHook _fullscreenHook = default!;
|
||||
[Dependency] private readonly ChangelogManager _changelogManager = default!;
|
||||
[Dependency] private readonly RulesManager _rulesManager = default!;
|
||||
[Dependency] private readonly ViewportManager _viewportManager = default!;
|
||||
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
|
||||
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||
@@ -125,7 +122,6 @@ namespace Content.Client.Entry
|
||||
_screenshotHook.Initialize();
|
||||
_fullscreenHook.Initialize();
|
||||
_changelogManager.Initialize();
|
||||
_rulesManager.Initialize();
|
||||
_viewportManager.Initialize();
|
||||
_ghostKick.Initialize();
|
||||
_extendedDisconnectInformation.Initialize();
|
||||
|
||||
@@ -2,6 +2,8 @@ using System.Linq;
|
||||
using Content.Client.Guidebook.Richtext;
|
||||
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 +15,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 +41,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
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
using Content.Shared.Info;
|
||||
using Robust.Shared.Log;
|
||||
|
||||
namespace Content.Client.Info;
|
||||
|
||||
public sealed class InfoSystem : EntitySystem
|
||||
{
|
||||
public RulesMessage Rules = new RulesMessage("Server Rules", "The server did not send any rules.");
|
||||
[Dependency] private readonly RulesManager _rules = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeNetworkEvent<RulesMessage>(OnRulesReceived);
|
||||
Log.Debug("Requested server info.");
|
||||
RaiseNetworkEvent(new RequestRulesMessage());
|
||||
}
|
||||
|
||||
private void OnRulesReceived(RulesMessage message, EntitySessionEventArgs eventArgs)
|
||||
{
|
||||
Log.Debug("Received server rules.");
|
||||
Rules = message;
|
||||
_rules.UpdateRules();
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
using System.Numerics;
|
||||
using Content.Client.UserInterface.Systems.EscapeMenu;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.ContentPack;
|
||||
|
||||
namespace Content.Client.Info
|
||||
@@ -12,7 +10,6 @@ namespace Content.Client.Info
|
||||
public sealed class RulesAndInfoWindow : DefaultWindow
|
||||
{
|
||||
[Dependency] private readonly IResourceManager _resourceManager = default!;
|
||||
[Dependency] private readonly RulesManager _rules = default!;
|
||||
|
||||
public RulesAndInfoWindow()
|
||||
{
|
||||
@@ -22,8 +19,14 @@ namespace Content.Client.Info
|
||||
|
||||
var rootContainer = new TabContainer();
|
||||
|
||||
var rulesList = new Info();
|
||||
var tutorialList = new Info();
|
||||
var rulesList = new RulesControl
|
||||
{
|
||||
Margin = new Thickness(10)
|
||||
};
|
||||
var tutorialList = new Info
|
||||
{
|
||||
Margin = new Thickness(10)
|
||||
};
|
||||
|
||||
rootContainer.AddChild(rulesList);
|
||||
rootContainer.AddChild(tutorialList);
|
||||
@@ -31,7 +34,6 @@ namespace Content.Client.Info
|
||||
TabContainer.SetTabTitle(rulesList, Loc.GetString("ui-info-tab-rules"));
|
||||
TabContainer.SetTabTitle(tutorialList, Loc.GetString("ui-info-tab-tutorial"));
|
||||
|
||||
AddSection(rulesList, _rules.RulesSection());
|
||||
PopulateTutorial(tutorialList);
|
||||
|
||||
Contents.AddChild(rootContainer);
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
<BoxContainer xmlns="https://spacestation14.io"
|
||||
Name="InfoContainer"
|
||||
Orientation="Vertical"
|
||||
Margin="2 2 0 0"
|
||||
SeparationOverride="10"
|
||||
Access="Public"/>
|
||||
<BoxContainer xmlns="https://spacestation14.io" Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True">
|
||||
<Control HorizontalExpand="True" VerticalExpand="True" HorizontalAlignment="Stretch">
|
||||
<ScrollContainer Name="Scroll" HScrollEnabled="False" HorizontalExpand="True" VerticalExpand="True">
|
||||
<BoxContainer Name="RulesContainer" VerticalExpand="True" Margin="0 0 5 0"/>
|
||||
</ScrollContainer>
|
||||
<BoxContainer Margin="0 0 15 0" HorizontalExpand="True" HorizontalAlignment="Right">
|
||||
<Button Name="BackButton"
|
||||
Text="{Loc 'ui-rules-button-back'}"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"/>
|
||||
<Control MinWidth="5"/>
|
||||
<Button Name="HomeButton"
|
||||
Text="{Loc 'ui-rules-button-home'}"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"/>
|
||||
</BoxContainer>
|
||||
</Control>
|
||||
</BoxContainer>
|
||||
|
||||
@@ -1,22 +1,53 @@
|
||||
using System.IO;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Client.Guidebook;
|
||||
using Content.Client.Guidebook.RichText;
|
||||
using Content.Client.UserInterface.Systems.Info;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.Info;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class RulesControl : BoxContainer
|
||||
public sealed partial class RulesControl : BoxContainer, ILinkClickHandler
|
||||
{
|
||||
[Dependency] private readonly RulesManager _rules = default!;
|
||||
[Dependency] private readonly DocumentParsingManager _parsingMan = default!;
|
||||
|
||||
private string? _currentEntry;
|
||||
private readonly Stack<string> _priorEntries = new();
|
||||
|
||||
public RulesControl()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
AddChild(_rules.RulesSection());
|
||||
|
||||
SetGuide();
|
||||
|
||||
HomeButton.OnPressed += _ => SetGuide();
|
||||
|
||||
BackButton.OnPressed += _ => SetGuide(_priorEntries.Pop(), false);
|
||||
}
|
||||
|
||||
public void HandleClick(string link)
|
||||
{
|
||||
SetGuide(link);
|
||||
}
|
||||
|
||||
private void SetGuide(ProtoId<GuideEntryPrototype>? entry = null, bool addToPrior = true)
|
||||
{
|
||||
var coreEntry = UserInterfaceManager.GetUIController<InfoUIController>().GetCoreRuleEntry();
|
||||
entry ??= coreEntry;
|
||||
|
||||
Scroll.SetScrollValue(default);
|
||||
RulesContainer.Children.Clear();
|
||||
if (!_parsingMan.TryAddMarkup(RulesContainer, entry.Value))
|
||||
return;
|
||||
|
||||
if (addToPrior && _currentEntry != null)
|
||||
_priorEntries.Push(_currentEntry);
|
||||
_currentEntry = entry.Value;
|
||||
|
||||
HomeButton.Visible = entry.Value != coreEntry.Id;
|
||||
BackButton.Visible = _priorEntries.Count != 0 && _priorEntries.Peek() != entry.Value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
using Content.Client.Lobby;
|
||||
using Content.Client.Gameplay;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Info;
|
||||
using Robust.Client.Console;
|
||||
using Robust.Client.State;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Client.Info;
|
||||
|
||||
public sealed class RulesManager : SharedRulesManager
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _configManager = default!;
|
||||
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
|
||||
[Dependency] private readonly IStateManager _stateManager = default!;
|
||||
[Dependency] private readonly IClientConsoleHost _consoleHost = default!;
|
||||
[Dependency] private readonly INetManager _netManager = default!;
|
||||
[Dependency] private readonly IEntitySystemManager _sysMan = default!;
|
||||
|
||||
private InfoSection rulesSection = new InfoSection("", "", false);
|
||||
private bool _shouldShowRules = false;
|
||||
|
||||
private RulesPopup? _activePopup;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_netManager.RegisterNetMessage<ShouldShowRulesPopupMessage>(OnShouldShowRules);
|
||||
_netManager.RegisterNetMessage<ShowRulesPopupMessage>(OnShowRulesPopupMessage);
|
||||
_netManager.RegisterNetMessage<RulesAcceptedMessage>();
|
||||
_stateManager.OnStateChanged += OnStateChanged;
|
||||
|
||||
_consoleHost.RegisterCommand("fuckrules", "", "", (_, _, _) =>
|
||||
{
|
||||
OnAcceptPressed();
|
||||
});
|
||||
}
|
||||
|
||||
private void OnShouldShowRules(ShouldShowRulesPopupMessage message)
|
||||
{
|
||||
_shouldShowRules = true;
|
||||
}
|
||||
|
||||
private void OnShowRulesPopupMessage(ShowRulesPopupMessage message)
|
||||
{
|
||||
ShowRules(message.PopupTime);
|
||||
}
|
||||
|
||||
private void OnStateChanged(StateChangedEventArgs args)
|
||||
{
|
||||
if (args.NewState is not (GameplayState or LobbyState))
|
||||
return;
|
||||
|
||||
if (!_shouldShowRules)
|
||||
return;
|
||||
|
||||
_shouldShowRules = false;
|
||||
|
||||
ShowRules(_configManager.GetCVar(CCVars.RulesWaitTime));
|
||||
}
|
||||
|
||||
private void ShowRules(float time)
|
||||
{
|
||||
if (_activePopup != null)
|
||||
return;
|
||||
|
||||
_activePopup = new RulesPopup
|
||||
{
|
||||
Timer = time
|
||||
};
|
||||
|
||||
_activePopup.OnQuitPressed += OnQuitPressed;
|
||||
_activePopup.OnAcceptPressed += OnAcceptPressed;
|
||||
_userInterfaceManager.WindowRoot.AddChild(_activePopup);
|
||||
LayoutContainer.SetAnchorPreset(_activePopup, LayoutContainer.LayoutPreset.Wide);
|
||||
}
|
||||
|
||||
private void OnQuitPressed()
|
||||
{
|
||||
_consoleHost.ExecuteCommand("quit");
|
||||
}
|
||||
|
||||
private void OnAcceptPressed()
|
||||
{
|
||||
_netManager.ClientSendMessage(new RulesAcceptedMessage());
|
||||
|
||||
_activePopup?.Orphan();
|
||||
_activePopup = null;
|
||||
}
|
||||
|
||||
public void UpdateRules()
|
||||
{
|
||||
var rules = _sysMan.GetEntitySystem<InfoSystem>().Rules;
|
||||
rulesSection.SetText(rules.Title, rules.Text, true);
|
||||
}
|
||||
|
||||
public Control RulesSection()
|
||||
{
|
||||
rulesSection = new InfoSection("", "", false);
|
||||
UpdateRules();
|
||||
return rulesSection;
|
||||
}
|
||||
}
|
||||
@@ -5,20 +5,20 @@
|
||||
MouseFilter="Stop">
|
||||
<parallax:ParallaxControl />
|
||||
<Control VerticalExpand="True"
|
||||
MaxWidth="650">
|
||||
MaxWidth="800"
|
||||
MaxHeight="900">
|
||||
<PanelContainer StyleClasses="windowPanel" />
|
||||
<ScrollContainer HScrollEnabled="False">
|
||||
<BoxContainer Orientation="Vertical" SeparationOverride="10">
|
||||
<info:RulesControl />
|
||||
<BoxContainer Orientation="Vertical" SeparationOverride="10" Margin="10 10 5 10">
|
||||
<info:RulesControl/>
|
||||
<Label Name="WaitLabel" />
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<Button Name="AcceptButton"
|
||||
Text="{Loc 'ui-rules-accept'}"
|
||||
Disabled="True" />
|
||||
<Button Name="QuitButton"
|
||||
StyleClasses="Caution"
|
||||
Text="{Loc 'ui-escape-quit'}" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</ScrollContainer>
|
||||
</Control>
|
||||
</Control>
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
using System;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client.Info;
|
||||
|
||||
@@ -4,7 +4,6 @@ using Content.Client.Chat.Managers;
|
||||
using Content.Client.Clickable;
|
||||
using Content.Client.Eui;
|
||||
using Content.Client.GhostKick;
|
||||
using Content.Client.Info;
|
||||
using Content.Client.Launcher;
|
||||
using Content.Client.Parallax.Managers;
|
||||
using Content.Client.Players.PlayTimeTracking;
|
||||
@@ -41,7 +40,6 @@ namespace Content.Client.IoC
|
||||
collection.Register<EuiManager, EuiManager>();
|
||||
collection.Register<IVoteManager, VoteManager>();
|
||||
collection.Register<ChangelogManager, ChangelogManager>();
|
||||
collection.Register<RulesManager, RulesManager>();
|
||||
collection.Register<ViewportManager, ViewportManager>();
|
||||
collection.Register<ISharedAdminLogManager, SharedAdminLogManager>();
|
||||
collection.Register<GhostKickManager>();
|
||||
|
||||
@@ -1,13 +1,73 @@
|
||||
using Content.Client.Gameplay;
|
||||
using System.Globalization;
|
||||
using Content.Client.Gameplay;
|
||||
using Content.Client.Guidebook;
|
||||
using Content.Client.Info;
|
||||
using Content.Shared.Administration.Managers;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Info;
|
||||
using Robust.Client;
|
||||
using Robust.Client.Console;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.UserInterface.Controllers;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.UserInterface.Systems.Info;
|
||||
|
||||
public sealed class InfoUIController : UIController, IOnStateExited<GameplayState>
|
||||
{
|
||||
[Dependency] private readonly IBaseClient _client = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
[Dependency] private readonly IClientConsoleHost _consoleHost = default!;
|
||||
[Dependency] private readonly INetManager _netManager = default!;
|
||||
[Dependency] private readonly ISharedAdminManager _adminManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
|
||||
private RulesPopup? _rulesPopup;
|
||||
private RulesAndInfoWindow? _infoWindow;
|
||||
|
||||
private static DateTime NextRulesReadTime => DateTime.UtcNow + TimeSpan.FromDays(60);
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_client.PlayerJoinedServer += OnJoinedServer;
|
||||
_netManager.RegisterNetMessage<ShowRulesPopupMessage>(OnShowRulesPopupMessage);
|
||||
|
||||
_consoleHost.RegisterCommand("fuckrules",
|
||||
"",
|
||||
"",
|
||||
(_, _, _) =>
|
||||
{
|
||||
OnAcceptPressed();
|
||||
});
|
||||
}
|
||||
|
||||
private void OnJoinedServer(object? sender, PlayerEventArgs args)
|
||||
{
|
||||
if (_playerManager.LocalSession is not { } localSession)
|
||||
return;
|
||||
|
||||
if (_adminManager.IsAdmin(localSession) && _cfg.GetCVar(CCVars.RulesExemptLocal))
|
||||
return;
|
||||
|
||||
var nextReadTarget = DateTime.Parse(_cfg.GetCVar(CCVars.RulesNextPopupTime));
|
||||
if (nextReadTarget >= DateTime.UtcNow)
|
||||
return;
|
||||
|
||||
var time = _cfg.GetCVar(CCVars.RulesWaitTime);
|
||||
ShowRules(time);
|
||||
}
|
||||
|
||||
private void OnShowRulesPopupMessage(ShowRulesPopupMessage message)
|
||||
{
|
||||
ShowRules(message.PopupTime);
|
||||
}
|
||||
|
||||
public void OnStateExited(GameplayState state)
|
||||
{
|
||||
if (_infoWindow == null)
|
||||
@@ -17,12 +77,47 @@ public sealed class InfoUIController : UIController, IOnStateExited<GameplayStat
|
||||
_infoWindow = null;
|
||||
}
|
||||
|
||||
private void ShowRules(float time)
|
||||
{
|
||||
if (_rulesPopup != null)
|
||||
return;
|
||||
|
||||
_rulesPopup = new RulesPopup
|
||||
{
|
||||
Timer = time
|
||||
};
|
||||
|
||||
_rulesPopup.OnQuitPressed += OnQuitPressed;
|
||||
_rulesPopup.OnAcceptPressed += OnAcceptPressed;
|
||||
UIManager.WindowRoot.AddChild(_rulesPopup);
|
||||
LayoutContainer.SetAnchorPreset(_rulesPopup, LayoutContainer.LayoutPreset.Wide);
|
||||
}
|
||||
|
||||
private void OnQuitPressed()
|
||||
{
|
||||
_consoleHost.ExecuteCommand("quit");
|
||||
}
|
||||
|
||||
private void OnAcceptPressed()
|
||||
{
|
||||
_cfg.SetCVar(CCVars.RulesNextPopupTime, NextRulesReadTime.ToString(CultureInfo.InvariantCulture));
|
||||
_cfg.SaveToFile();
|
||||
|
||||
_rulesPopup?.Orphan();
|
||||
_rulesPopup = null;
|
||||
}
|
||||
|
||||
public GuideEntryPrototype GetCoreRuleEntry()
|
||||
{
|
||||
var guide = _cfg.GetCVar(CCVars.RulesFile);
|
||||
var guideEntryPrototype = _prototype.Index<GuideEntryPrototype>(guide);
|
||||
return guideEntryPrototype;
|
||||
}
|
||||
|
||||
public void OpenWindow()
|
||||
{
|
||||
if (_infoWindow == null || _infoWindow.Disposed)
|
||||
{
|
||||
_infoWindow = UIManager.CreateWindow<RulesAndInfoWindow>();
|
||||
}
|
||||
|
||||
_infoWindow?.OpenCentered();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user