diff --git a/Content.Client/GameTicking/ClientGameTicker.cs b/Content.Client/GameTicking/ClientGameTicker.cs index 22d9b486fd..8b09cb4db0 100644 --- a/Content.Client/GameTicking/ClientGameTicker.cs +++ b/Content.Client/GameTicking/ClientGameTicker.cs @@ -14,12 +14,10 @@ using Robust.Client.Interfaces.ResourceManagement; using Robust.Client.Interfaces.UserInterface; using Robust.Client.Player; using Robust.Client.UserInterface; -using Robust.Client.UserInterface.Controls; using Robust.Shared.Input; using Robust.Shared.Interfaces.Network; using Robust.Shared.IoC; using Robust.Shared.Localization; -using Robust.Shared.Players; using Robust.Shared.Timing; using Robust.Shared.Utility; using Robust.Shared.ViewVariables; @@ -48,6 +46,7 @@ namespace Content.Client.GameTicking [ViewVariables] private LobbyGui _lobby; [ViewVariables] private bool _gameStarted; [ViewVariables] private DateTime _startTime; + [ViewVariables] private string _serverInfoBlob; public void Initialize() { @@ -56,6 +55,7 @@ namespace Content.Client.GameTicking _netManager.RegisterNetMessage(nameof(MsgTickerJoinLobby), _joinLobby); _netManager.RegisterNetMessage(nameof(MsgTickerJoinGame), _joinGame); _netManager.RegisterNetMessage(nameof(MsgTickerLobbyStatus), _lobbyStatus); + _netManager.RegisterNetMessage(nameof(MsgTickerLobbyInfo), _lobbyInfo); _baseClient.RunLevelChanged += BaseClientOnRunLevelChanged; _playerManager.PlayerListUpdated += PlayerManagerOnPlayerListUpdated; @@ -97,7 +97,7 @@ namespace Content.Client.GameTicking _gameHud.RootControl.Orphan(); } - public void FrameUpdate(FrameEventArgs FrameEventArgs) + public void FrameUpdate(FrameEventArgs frameEventArgs) { if (_lobby == null) { @@ -140,6 +140,13 @@ namespace Content.Client.GameTicking _updateLobbyUi(); } + private void _lobbyInfo(MsgTickerLobbyInfo message) + { + _serverInfoBlob = message.TextBlob; + + _updateLobbyUi(); + } + private void _updateLobbyUi() { if (_lobby == null) @@ -160,6 +167,8 @@ namespace Content.Client.GameTicking _lobby.ReadyButton.ToggleMode = true; _lobby.ReadyButton.Pressed = _areWeReady; } + + _lobby.ServerInfo.SetInfoBlob(_serverInfoBlob); } private void _joinLobby(MsgTickerJoinLobby message) diff --git a/Content.Client/UserInterface/LobbyGui.cs b/Content.Client/UserInterface/LobbyGui.cs index d60dcf1162..a03dead3da 100644 --- a/Content.Client/UserInterface/LobbyGui.cs +++ b/Content.Client/UserInterface/LobbyGui.cs @@ -1,13 +1,15 @@ using Content.Client.Chat; +using Content.Client.Utility; using Robust.Client.Graphics.Drawing; using Robust.Client.Interfaces.ResourceManagement; +using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Shared.Localization; using Robust.Shared.Maths; namespace Content.Client.UserInterface { - internal sealed class LobbyGui : PanelContainer + internal sealed class LobbyGui : Control { public Label ServerName { get; } public Label StartTime { get; } @@ -16,97 +18,195 @@ namespace Content.Client.UserInterface public Button LeaveButton { get; } public ChatBox Chat { get; } public ItemList OnlinePlayerItemList { get; } + public ServerInfo ServerInfo { get; } public LobbyGui(ILocalizationManager localization, IResourceCache resourceCache) { - PanelOverride = new StyleBoxFlat {BackgroundColor = new Color(37, 37, 45)}; - PanelOverride.SetContentMarginOverride(StyleBox.Margin.All, 4); + var panelTex = resourceCache.GetTexture("/Nano/button.svg.96dpi.png"); + var back = new StyleBoxTexture + { + Texture = panelTex, + Modulate = new Color(37, 37, 42), + }; + back.SetPatchMargin(StyleBox.Margin.All, 10); + + var panel = new Panel + { + PanelOverride = back + }; + + AddChild(panel); + + panel.SetAnchorAndMarginPreset(LayoutPreset.Wide); + + var vBox = new VBoxContainer {SeparationOverride = 0}; + + vBox.SetAnchorAndMarginPreset(LayoutPreset.Wide); + + vBox.MarginTop = 40; - var vBox = new VBoxContainer(); AddChild(vBox); + AddChild(new Label { - // Title bar. - var titleContainer = new HBoxContainer(); - vBox.AddChild(titleContainer); + Text = localization.GetString("Lobby"), + StyleClasses = {NanoStyle.StyleClassLabelHeadingBigger}, + MarginBottom = 40, + MarginLeft = 8, + VAlign = Label.VAlignMode.Center + }); - var lobbyTitle = new Label + AddChild(ServerName = new Label + { + StyleClasses = {NanoStyle.StyleClassLabelHeadingBigger}, + MarginBottom = 40, + GrowHorizontal = GrowDirection.Both, + VAlign = Label.VAlignMode.Center + }); + + ServerName.SetAnchorAndMarginPreset(LayoutPreset.CenterTop); + + AddChild(LeaveButton = new Button + { + SizeFlagsHorizontal = SizeFlags.ShrinkEnd, + Text = localization.GetString("Leave"), + StyleClasses = {NanoStyle.StyleClassButtonBig} + }); + + LeaveButton.SetAnchorAndMarginPreset(LayoutPreset.TopRight); + + vBox.AddChild(new Panel + { + PanelOverride = new StyleBoxFlat { - Text = localization.GetString("Lobby"), - SizeFlagsHorizontal = SizeFlags.None - }; - lobbyTitle.AddStyleClass(NanoStyle.StyleClassLabelHeading); - titleContainer.AddChild(lobbyTitle); + BackgroundColor = NanoStyle.NanoGold, + ContentMarginTopOverride = 2 + }, + }); - titleContainer.AddChild(ServerName = new Label - { - SizeFlagsHorizontal = SizeFlags.ShrinkCenter | SizeFlags.Expand - }); - ServerName.AddStyleClass(NanoStyle.StyleClassLabelHeading); - - titleContainer.AddChild(LeaveButton = new Button - { - SizeFlagsHorizontal = SizeFlags.ShrinkEnd, - Text = localization.GetString("Leave") - }); - LeaveButton.AddStyleClass(NanoStyle.StyleClassButtonBig); - } - - var hBox = new HBoxContainer {SizeFlagsVertical = SizeFlags.FillExpand}; + var hBox = new HBoxContainer + { + SizeFlagsVertical = SizeFlags.FillExpand, + SeparationOverride = 0 + }; vBox.AddChild(hBox); + hBox.AddChild(new VBoxContainer { - var leftVBox = new VBoxContainer {SizeFlagsHorizontal = SizeFlags.FillExpand}; - hBox.AddChild(leftVBox); - - leftVBox.AddChild(new Placeholder(resourceCache) + SizeFlagsHorizontal = SizeFlags.FillExpand, + SeparationOverride = 0, + Children = { - SizeFlagsVertical = SizeFlags.FillExpand, - PlaceholderText = localization.GetString("Character UI\nPlaceholder") - }); + new Placeholder(resourceCache) + { + SizeFlagsVertical = SizeFlags.FillExpand, + PlaceholderText = localization.GetString("Character UI\nPlaceholder") + }, - var readyButtons = new HBoxContainer(); + new StripeBack + { + Children = + { + new MarginContainer + { + MarginRightOverride = 3, + MarginLeftOverride = 3, + MarginTopOverride = 3, + MarginBottomOverride = 3, + Children = + { + new HBoxContainer + { + SeparationOverride = 6, + Children = + { + (ObserveButton = new Button + { + Text = localization.GetString("Observe"), + StyleClasses = {NanoStyle.StyleClassButtonBig} + }), + (StartTime = new Label + { + SizeFlagsHorizontal = SizeFlags.FillExpand, + Align = Label.AlignMode.Right, + FontColorOverride = Color.DarkGray, + StyleClasses = { NanoStyle.StyleClassLabelBig } + }), + (ReadyButton = new Button + { + ToggleMode = true, + Text = localization.GetString("Ready Up"), + StyleClasses = {NanoStyle.StyleClassButtonBig} + }), + } + } + } + } + } + }, - leftVBox.AddChild(readyButtons); - readyButtons.AddChild(ObserveButton = new Button - { - Text = localization.GetString("Observe") - }); - ObserveButton.AddStyleClass(NanoStyle.StyleClassButtonBig); + new MarginContainer + { + MarginRightOverride = 3, + MarginLeftOverride = 3, + MarginTopOverride = 3, + MarginBottomOverride = 3, + SizeFlagsVertical = SizeFlags.FillExpand, + Children = + { + (Chat = new ChatBox + { + Input = {PlaceHolder = localization.GetString("Say something!")} + }) + } + }, + } + }); - readyButtons.AddChild(StartTime = new Label + hBox.AddChild(new Panel + { + PanelOverride = new StyleBoxFlat {BackgroundColor = NanoStyle.NanoGold}, CustomMinimumSize = (2, 0) + }); + + { + hBox.AddChild(new VBoxContainer { SizeFlagsHorizontal = SizeFlags.FillExpand, - Align = Label.AlignMode.Right - }); - - readyButtons.AddChild(ReadyButton = new Button - { - ToggleMode = true, - Text = localization.GetString("Ready Up") - }); - ReadyButton.AddStyleClass(NanoStyle.StyleClassButtonBig); - - leftVBox.AddChild(Chat = new ChatBox {SizeFlagsVertical = SizeFlags.FillExpand}); - Chat.Input.PlaceHolder = localization.GetString("Say something!"); - } - - { - var rightVBox = new VBoxContainer {SizeFlagsHorizontal = SizeFlags.FillExpand}; - hBox.AddChild(rightVBox); - rightVBox.AddChild(new Label - { - Text = localization.GetString("Online Players:") - }); - rightVBox.AddChild(OnlinePlayerItemList = new ItemList - { - SizeFlagsVertical = SizeFlags.FillExpand, - //SelectMode = ItemList.ItemListSelectMode.None - }); - rightVBox.AddChild(new Placeholder(resourceCache) - { - SizeFlagsVertical = SizeFlags.FillExpand, - PlaceholderText = localization.GetString("Server Info\nPlaceholder") + Children = + { + new NanoHeading + { + Text = localization.GetString("Online Players"), + }, + new MarginContainer + { + SizeFlagsVertical = SizeFlags.FillExpand, + MarginRightOverride = 3, + MarginLeftOverride = 3, + MarginTopOverride = 3, + MarginBottomOverride = 3, + Children = + { + (OnlinePlayerItemList = new ItemList()) + } + }, + new NanoHeading + { + Text = localization.GetString("Server Info"), + }, + new MarginContainer + { + SizeFlagsVertical = SizeFlags.FillExpand, + MarginRightOverride = 3, + MarginLeftOverride = 3, + MarginTopOverride = 3, + MarginBottomOverride = 2, + Children = + { + (ServerInfo = new ServerInfo(localization)) + } + }, + } }); } } diff --git a/Content.Client/UserInterface/ServerInfo.cs b/Content.Client/UserInterface/ServerInfo.cs new file mode 100644 index 0000000000..91a95b4b8b --- /dev/null +++ b/Content.Client/UserInterface/ServerInfo.cs @@ -0,0 +1,44 @@ +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using Robust.Shared.Utility; + +namespace Content.Client.UserInterface +{ + public class ServerInfo : VBoxContainer + { + private const string DiscordUrl = "https://discordapp.com/invite/t2jac3p"; + private const string WebsiteUrl = "https://spacestation14.io"; + + private readonly RichTextLabel _richTextLabel; + + public ServerInfo(ILocalizationManager localization) + { + _richTextLabel = new RichTextLabel + { + SizeFlagsVertical = SizeFlags.FillExpand + }; + AddChild(_richTextLabel); + + var buttons = new HBoxContainer(); + AddChild(buttons); + + var uriOpener = IoCManager.Resolve(); + + var discordButton = new Button {Text = localization.GetString("Join us on Discord!")}; + discordButton.OnPressed += args => uriOpener.OpenUri(DiscordUrl); + + var websiteButton = new Button {Text = localization.GetString("Website")}; + websiteButton.OnPressed += args => uriOpener.OpenUri(WebsiteUrl); + + buttons.AddChild(discordButton); + buttons.AddChild(websiteButton); + } + + public void SetInfoBlob(string markup) + { + _richTextLabel.SetMessage(FormattedMessage.FromMarkup(markup)); + } + } +} diff --git a/Content.Server/GameTicking/GamePreset.cs b/Content.Server/GameTicking/GamePreset.cs index 1da340d5aa..cf7981b725 100644 --- a/Content.Server/GameTicking/GamePreset.cs +++ b/Content.Server/GameTicking/GamePreset.cs @@ -6,5 +6,6 @@ namespace Content.Server.GameTicking public abstract class GamePreset { public abstract void Start(); + public virtual string Description => "Secret!"; } } diff --git a/Content.Server/GameTicking/GamePresets/PresetDeathMatch.cs b/Content.Server/GameTicking/GamePresets/PresetDeathMatch.cs index 29745d4321..11c716442d 100644 --- a/Content.Server/GameTicking/GamePresets/PresetDeathMatch.cs +++ b/Content.Server/GameTicking/GamePresets/PresetDeathMatch.cs @@ -14,5 +14,7 @@ namespace Content.Server.GameTicking.GamePresets { _gameTicker.AddGameRule(); } + + public override string Description => "Deathmatch, go and kill everybody else to win!"; } } diff --git a/Content.Server/GameTicking/GamePresets/PresetSandbox.cs b/Content.Server/GameTicking/GamePresets/PresetSandbox.cs index cde4f725fb..f22b58df66 100644 --- a/Content.Server/GameTicking/GamePresets/PresetSandbox.cs +++ b/Content.Server/GameTicking/GamePresets/PresetSandbox.cs @@ -14,5 +14,7 @@ namespace Content.Server.GameTicking.GamePresets { _sandboxManager.IsSandboxEnabled = true; } + + public override string Description => "Sandbox, go and build something!"; } } diff --git a/Content.Server/GameTicking/GameTicker.cs b/Content.Server/GameTicking/GameTicker.cs index fd2a51d9c1..5734671a63 100644 --- a/Content.Server/GameTicking/GameTicker.cs +++ b/Content.Server/GameTicking/GameTicker.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using Content.Server.GameObjects; @@ -10,7 +10,6 @@ using Content.Server.Mobs; using Content.Server.Players; using Content.Shared; using Content.Shared.GameObjects.Components.Inventory; -using Robust.Server.Interfaces.Console; using Robust.Server.Interfaces.Maps; using Robust.Server.Interfaces.Player; using Robust.Server.Player; @@ -24,10 +23,10 @@ using Robust.Shared.Interfaces.Network; using Robust.Shared.Interfaces.Random; using Robust.Shared.Interfaces.Timing; using Robust.Shared.IoC; +using Robust.Shared.Localization; using Robust.Shared.Log; using Robust.Shared.Map; using Robust.Shared.Maths; -using Robust.Shared.Network; using Robust.Shared.Random; using Robust.Shared.Timers; using Robust.Shared.Timing; @@ -92,6 +91,7 @@ namespace Content.Server.GameTicking [Dependency] private IChatManager _chatManager; [Dependency] private IServerNetManager _netManager; [Dependency] private IDynamicTypeFactory _dynamicTypeFactory; + [Dependency] private readonly ILocalizationManager _localization; [Dependency] private readonly IRobustRandom _robustRandom; #pragma warning restore 649 @@ -105,6 +105,7 @@ namespace Content.Server.GameTicking _netManager.RegisterNetMessage(nameof(MsgTickerJoinLobby)); _netManager.RegisterNetMessage(nameof(MsgTickerJoinGame)); _netManager.RegisterNetMessage(nameof(MsgTickerLobbyStatus)); + _netManager.RegisterNetMessage(nameof(MsgTickerLobbyInfo)); RestartRound(); @@ -156,7 +157,7 @@ namespace Content.Server.GameTicking RunLevel = GameRunLevel.InRound; - var preset = _dynamicTypeFactory.CreateInstance(_presetType ?? typeof(PresetSandbox)); + var preset = MakeGamePreset(); preset.Start(); foreach (var (playerSession, ready) in _playersInLobby.ToList()) @@ -256,6 +257,7 @@ namespace Content.Server.GameTicking throw new ArgumentException("type must inherit GamePreset"); } _presetType = type; + UpdateInfoText(); } private IEntity _spawnPlayerMob() @@ -461,6 +463,7 @@ namespace Content.Server.GameTicking _netManager.ServerSendMessage(_netManager.CreateNetMessage(), session.ConnectedClient); _netManager.ServerSendMessage(_getStatusMsg(session), session.ConnectedClient); + _netManager.ServerSendMessage(GetInfoMsg(), session.ConnectedClient); } private void _playerJoinGame(IPlayerSession session) @@ -484,6 +487,13 @@ namespace Content.Server.GameTicking return msg; } + private MsgTickerLobbyInfo GetInfoMsg() + { + var msg = _netManager.CreateNetMessage(); + msg.TextBlob = GetInfoText(); + return msg; + } + private void _sendStatusToAll() { foreach (var player in _playersInLobby.Keys) @@ -491,6 +501,26 @@ namespace Content.Server.GameTicking _netManager.ServerSendMessage(_getStatusMsg(player), player.ConnectedClient); } } + + private string GetInfoText() + { + var gameMode = MakeGamePreset().Description; + return _localization.GetString(@"Hi and welcome to [color=white]Space Station 14![/color] + +The current game mode is [color=white]{0}[/color]", gameMode); + } + + private void UpdateInfoText() + { + var infoMsg = GetInfoMsg(); + + _netManager.ServerSendToMany(infoMsg, _playersInLobby.Keys.Select(p => p.ConnectedClient).ToList()); + } + + private GamePreset MakeGamePreset() + { + return _dynamicTypeFactory.CreateInstance(_presetType ?? typeof(PresetSandbox)); + } } public enum GameRunLevel diff --git a/Content.Shared/SharedGameTicker.cs b/Content.Shared/SharedGameTicker.cs index 07f7b089e4..0838142fc3 100644 --- a/Content.Shared/SharedGameTicker.cs +++ b/Content.Shared/SharedGameTicker.cs @@ -90,5 +90,28 @@ namespace Content.Shared buffer.Write(StartTime.Ticks); } } + + protected class MsgTickerLobbyInfo : NetMessage + { + #region REQUIRED + + public const MsgGroups GROUP = MsgGroups.Command; + public const string NAME = nameof(MsgTickerLobbyInfo); + public MsgTickerLobbyInfo(INetChannel channel) : base(NAME, GROUP) { } + + #endregion + + public string TextBlob { get; set; } + + public override void ReadFromBuffer(NetIncomingMessage buffer) + { + TextBlob = buffer.ReadString(); + } + + public override void WriteToBuffer(NetOutgoingMessage buffer) + { + buffer.Write(TextBlob); + } + } } }