using System; using System.Linq; using Content.Client.Chat; using Content.Client.Interfaces; using Content.Client.Interfaces.Chat; using Content.Client.UserInterface; using Content.Shared; using Content.Shared.Input; using Robust.Client; using Robust.Client.Console; using Robust.Client.Interfaces; using Robust.Client.Interfaces.Input; using Robust.Client.Interfaces.ResourceManagement; using Robust.Client.Interfaces.UserInterface; using Robust.Client.Player; using Robust.Client.UserInterface.Controls; using Robust.Shared.Input; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Network; using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Prototypes; using Robust.Shared.Timing; using Robust.Shared.Utility; using Robust.Shared.ViewVariables; namespace Content.Client.GameTicking { public class ClientGameTicker : SharedGameTicker, IClientGameTicker { #pragma warning disable 649 [Dependency] private IClientNetManager _netManager; [Dependency] private IUserInterfaceManager _userInterfaceManager; [Dependency] private IInputManager _inputManager; [Dependency] private IBaseClient _baseClient; [Dependency] private IChatManager _chatManager; [Dependency] private IClientConsole _console; [Dependency] private ILocalizationManager _localization; [Dependency] private IResourceCache _resourceCache; [Dependency] private IPlayerManager _playerManager; [Dependency] private IGameHud _gameHud; [Dependency] private IEntityManager _entityManager; [Dependency] private IClientPreferencesManager _preferencesManager; [Dependency] private IPrototypeManager _prototypeManager; #pragma warning restore 649 [ViewVariables] private bool _areWeReady; [ViewVariables] private CharacterSetupGui _characterSetup; [ViewVariables] private ChatBox _gameChat; [ViewVariables] private bool _gameStarted; [ViewVariables] private bool _initialized; [ViewVariables] private LobbyGui _lobby; [ViewVariables] private string _serverInfoBlob; [ViewVariables] private DateTime _startTime; [ViewVariables] private TickerState _tickerState; public void Initialize() { DebugTools.Assert(!_initialized); _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; _initialized = true; } private void PlayerManagerOnPlayerListUpdated(object sender, EventArgs e) { if (_lobby == null) { return; } _updatePlayerList(); } private void _updatePlayerList() { _lobby.OnlinePlayerItemList.Clear(); foreach (var session in _playerManager.Sessions.OrderBy(s => s.Name)) { _lobby.OnlinePlayerItemList.AddItem(session.Name); } } private void BaseClientOnRunLevelChanged(object sender, RunLevelChangedEventArgs e) { if (e.NewLevel != ClientRunLevel.Initialize) { return; } _tickerState = TickerState.Unset; _lobby?.Dispose(); _lobby = null; _gameChat?.Dispose(); _gameChat = null; _gameHud.RootControl.Orphan(); } public void FrameUpdate(FrameEventArgs frameEventArgs) { if (_lobby == null) { return; } if (_gameStarted) { _lobby.StartTime.Text = ""; return; } string text; var difference = _startTime - DateTime.UtcNow; if (difference.Ticks < 0) { if (difference.TotalSeconds < -5) { text = _localization.GetString("Right Now?"); } else { text = _localization.GetString("Right Now"); } } else { text = $"{(int) Math.Floor(difference.TotalMinutes)}:{difference.Seconds:D2}"; } _lobby.StartTime.Text = _localization.GetString("Round Starts In: {0}", text); } private void _lobbyStatus(MsgTickerLobbyStatus message) { _startTime = message.StartTime; _gameStarted = message.IsRoundStarted; _areWeReady = message.YouAreReady; _updateLobbyUi(); } private void _lobbyInfo(MsgTickerLobbyInfo message) { _serverInfoBlob = message.TextBlob; _updateLobbyUi(); } private void _updateLobbyUi() { if (_lobby == null) { return; } if (_gameStarted) { _lobby.ReadyButton.Text = _localization.GetString("Join"); _lobby.ReadyButton.ToggleMode = false; _lobby.ReadyButton.Pressed = false; } else { _lobby.StartTime.Text = ""; _lobby.ReadyButton.Text = _localization.GetString("Ready Up"); _lobby.ReadyButton.ToggleMode = true; _lobby.ReadyButton.Pressed = _areWeReady; } _lobby.ServerInfo.SetInfoBlob(_serverInfoBlob); } private void _joinLobby(MsgTickerJoinLobby message) { if (_tickerState == TickerState.InLobby) { return; } if (_gameChat != null) { _gameChat.Dispose(); _gameChat = null; } _gameHud.RootControl.Orphan(); _tickerState = TickerState.InLobby; _characterSetup = new CharacterSetupGui(_entityManager, _localization, _resourceCache, _preferencesManager, _prototypeManager); LayoutContainer.SetAnchorPreset(_characterSetup, LayoutContainer.LayoutPreset.Wide); _characterSetup.CloseButton.OnPressed += args => { _lobby.CharacterPreview.UpdateUI(); _userInterfaceManager.StateRoot.AddChild(_lobby); _userInterfaceManager.StateRoot.RemoveChild(_characterSetup); }; _lobby = new LobbyGui(_entityManager, _localization, _resourceCache, _preferencesManager); _userInterfaceManager.StateRoot.AddChild(_lobby); LayoutContainer.SetAnchorPreset(_lobby, LayoutContainer.LayoutPreset.Wide); _chatManager.SetChatBox(_lobby.Chat); _lobby.Chat.DefaultChatFormat = "ooc \"{0}\""; _lobby.ServerName.Text = _baseClient.GameInfo.ServerName; _inputManager.SetInputCommand(ContentKeyFunctions.FocusChat, InputCmdHandler.FromDelegate(s => _focusChat(_lobby.Chat))); _updateLobbyUi(); _lobby.CharacterPreview.CharacterSetupButton.OnPressed += args => { _userInterfaceManager.StateRoot.RemoveChild(_lobby); _userInterfaceManager.StateRoot.AddChild(_characterSetup); }; _lobby.ObserveButton.OnPressed += args => _console.ProcessCommand("observe"); _lobby.ReadyButton.OnPressed += args => { if (!_gameStarted) { return; } _console.ProcessCommand("joingame"); }; _lobby.ReadyButton.OnToggled += args => { if (_gameStarted) { return; } _console.ProcessCommand($"toggleready {args.Pressed}"); }; _lobby.LeaveButton.OnPressed += args => _console.ProcessCommand("disconnect"); _updatePlayerList(); } private void _joinGame(MsgTickerJoinGame message) { if (_tickerState == TickerState.InGame) { return; } _tickerState = TickerState.InGame; if (_lobby != null) { _lobby.Dispose(); _lobby = null; } _gameChat = new ChatBox(); _userInterfaceManager.StateRoot.AddChild(_gameChat); LayoutContainer.SetAnchorAndMarginPreset(_gameChat, LayoutContainer.LayoutPreset.TopRight, margin: 10); LayoutContainer.SetAnchorAndMarginPreset(_gameChat, LayoutContainer.LayoutPreset.TopRight, margin: 10); LayoutContainer.SetMarginLeft(_gameChat, -475); LayoutContainer.SetMarginBottom(_gameChat, 235); _userInterfaceManager.StateRoot.AddChild(_gameHud.RootControl); _chatManager.SetChatBox(_gameChat); _gameChat.DefaultChatFormat = "say \"{0}\""; _gameChat.Input.PlaceHolder = _localization.GetString("Say something! [ for OOC"); _inputManager.SetInputCommand(ContentKeyFunctions.FocusChat, InputCmdHandler.FromDelegate(s => _focusChat(_gameChat))); } private void _focusChat(ChatBox chat) { if (_userInterfaceManager.KeyboardFocused != null) { return; } chat.Input.IgnoreNext = true; chat.Input.GrabKeyboardFocus(); } private enum TickerState { Unset = 0, /// /// The client is in the lobby. /// InLobby = 1, /// /// The client is NOT in the lobby. /// Do not confuse this with the client session status. /// InGame = 2 } } }