Re-organize all projects (#4166)

This commit is contained in:
DrSmugleaf
2021-06-09 22:19:39 +02:00
committed by GitHub
parent 9f50e4061b
commit ff1a2d97ea
1773 changed files with 5258 additions and 5508 deletions

View File

@@ -1,159 +0,0 @@
using System.Linq;
using Content.Client.Administration;
using Content.Client.Chat;
using Content.Client.Construction;
using Content.Client.Interfaces.Chat;
using Content.Client.UserInterface;
using Content.Client.Voting;
using Content.Shared;
using Content.Shared.Chat;
using Content.Shared.Input;
using Robust.Client.Graphics;
using Robust.Client.Input;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Configuration;
using Robust.Shared.Input.Binding;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Timing;
using Robust.Shared.ViewVariables;
namespace Content.Client.State
{
public class GameScreen : GameScreenBase, IMainViewportState
{
public static readonly Vector2i ViewportSize = (EyeManager.PixelsPerMeter * 21, EyeManager.PixelsPerMeter * 15);
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
[Dependency] private readonly IGameHud _gameHud = default!;
[Dependency] private readonly IInputManager _inputManager = default!;
[Dependency] private readonly IChatManager _chatManager = default!;
[Dependency] private readonly IVoteManager _voteManager = default!;
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
[Dependency] private readonly IClientAdminManager _adminManager = default!;
[Dependency] private readonly IClyde _clyde = default!;
[Dependency] private readonly IEyeManager _eyeManager = default!;
[ViewVariables] private ChatBox? _gameChat;
private ConstructionMenuPresenter? _constructionMenu;
public MainViewport Viewport { get; private set; } = default!;
public override void Startup()
{
base.Startup();
_gameChat = new ChatBox();
Viewport = new MainViewport
{
Viewport =
{
ViewportSize = ViewportSize
}
};
_userInterfaceManager.StateRoot.AddChild(Viewport);
LayoutContainer.SetAnchorPreset(Viewport, LayoutContainer.LayoutPreset.Wide);
Viewport.SetPositionFirst();
_userInterfaceManager.StateRoot.AddChild(_gameHud.RootControl);
_chatManager.SetChatBox(_gameChat);
_voteManager.SetPopupContainer(_gameHud.VoteContainer);
_gameChat.DefaultChatFormat = "say \"{0}\"";
_inputManager.SetInputCommand(ContentKeyFunctions.FocusChat,
InputCmdHandler.FromDelegate(_ => FocusChat(_gameChat)));
_inputManager.SetInputCommand(ContentKeyFunctions.FocusOOC,
InputCmdHandler.FromDelegate(_ => FocusChannel(_gameChat, ChatChannel.OOC)));
_inputManager.SetInputCommand(ContentKeyFunctions.FocusLocalChat,
InputCmdHandler.FromDelegate(_ => FocusChannel(_gameChat, ChatChannel.Local)));
_inputManager.SetInputCommand(ContentKeyFunctions.FocusRadio,
InputCmdHandler.FromDelegate(_ => FocusChannel(_gameChat, ChatChannel.Radio)));
_inputManager.SetInputCommand(ContentKeyFunctions.FocusAdminChat,
InputCmdHandler.FromDelegate(_ => FocusChannel(_gameChat, ChatChannel.AdminChat)));
_inputManager.SetInputCommand(ContentKeyFunctions.CycleChatChannelForward,
InputCmdHandler.FromDelegate(_ => _gameChat.CycleChatChannel(true)));
_inputManager.SetInputCommand(ContentKeyFunctions.CycleChatChannelBackward,
InputCmdHandler.FromDelegate(_ => _gameChat.CycleChatChannel(false)));
SetupPresenters();
_eyeManager.MainViewport = Viewport.Viewport;
}
public override void Shutdown()
{
DisposePresenters();
base.Shutdown();
_gameChat?.Dispose();
Viewport.Dispose();
_gameHud.RootControl.Orphan();
// Clear viewport to some fallback, whatever.
_eyeManager.MainViewport = _userInterfaceManager.MainViewport;
}
/// <summary>
/// All UI Presenters should be constructed in here.
/// </summary>
private void SetupPresenters()
{
_constructionMenu = new ConstructionMenuPresenter(_gameHud);
}
/// <summary>
/// All UI Presenters should be disposed in here.
/// </summary>
private void DisposePresenters()
{
_constructionMenu?.Dispose();
}
internal static void FocusChat(ChatBox chat)
{
if (chat.UserInterfaceManager.KeyboardFocused != null)
{
return;
}
chat.Input.IgnoreNext = true;
chat.Input.GrabKeyboardFocus();
}
internal static void FocusChannel(ChatBox chat, ChatChannel channel)
{
if (chat.UserInterfaceManager.KeyboardFocused != null)
{
return;
}
chat.SelectChannel(channel);
chat.Input.IgnoreNext = true;
chat.Input.GrabKeyboardFocus();
}
public override void FrameUpdate(FrameEventArgs e)
{
base.FrameUpdate(e);
Viewport.Viewport.Eye = _eyeManager.CurrentEye;
}
protected override void OnKeyBindStateChanged(ViewportBoundKeyEventArgs args)
{
if (args.Viewport == null)
base.OnKeyBindStateChanged(new ViewportBoundKeyEventArgs(args.KeyEventArgs, Viewport.Viewport));
else
base.OnKeyBindStateChanged(args);
}
}
}

View File

@@ -1,250 +0,0 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Content.Client.GameObjects.Components;
using Content.Client.UserInterface;
using Content.Client.Utility;
using Content.Shared;
using Robust.Client.GameObjects;
using Robust.Client.Input;
using Robust.Client.Player;
using Robust.Client.State;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Configuration;
using Robust.Shared.GameObjects;
using Robust.Shared.Input;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Timing;
namespace Content.Client.State
{
// OH GOD.
// Ok actually it's fine.
// Instantiated dynamically through the StateManager, Dependencies will be resolved.
public partial class GameScreenBase : Robust.Client.State.State, IEntityEventSubscriber
{
[Dependency] protected readonly IClientEntityManager EntityManager = default!;
[Dependency] protected readonly IInputManager InputManager = default!;
[Dependency] protected readonly IPlayerManager PlayerManager = default!;
[Dependency] protected readonly IEntitySystemManager EntitySystemManager = default!;
[Dependency] protected readonly IGameTiming Timing = default!;
[Dependency] protected readonly IMapManager MapManager = default!;
[Dependency] protected readonly IUserInterfaceManager UserInterfaceManager = default!;
[Dependency] protected readonly IConfigurationManager ConfigurationManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
private IEventBus _eventBus => _entityManager.EventBus;
private IEntity? _lastHoveredEntity;
private bool _outlineEnabled = true;
public override void Startup()
{
InputManager.KeyBindStateChanged += OnKeyBindStateChanged;
_eventBus.SubscribeEvent<OutlineToggleMessage>(EventSource.Local, this, HandleOutlineToggle);
}
public override void Shutdown()
{
InputManager.KeyBindStateChanged -= OnKeyBindStateChanged;
_eventBus.UnsubscribeEvent<OutlineToggleMessage>(EventSource.Local, this);
}
private void HandleOutlineToggle(OutlineToggleMessage message)
{
_outlineEnabled = message.Enabled;
}
public override void FrameUpdate(FrameEventArgs e)
{
base.FrameUpdate(e);
// If there is no local player, there is no session, and therefore nothing to do here.
var localPlayer = PlayerManager.LocalPlayer;
if (localPlayer == null)
return;
IEntity? entityToClick = null;
var renderScale = 1;
if (UserInterfaceManager.CurrentlyHovered is IViewportControl vp)
{
var mousePosWorld = vp.ScreenToMap(InputManager.MouseScreenPosition.Position);
entityToClick = GetEntityUnderPosition(mousePosWorld);
if (vp is ScalingViewport svp)
{
renderScale = svp.CurrentRenderScale;
}
}
var inRange = false;
if (localPlayer.ControlledEntity != null && entityToClick != null)
{
inRange = localPlayer.InRangeUnobstructed(entityToClick, ignoreInsideBlocker: true);
}
InteractionOutlineComponent? outline;
if(!_outlineEnabled || !ConfigurationManager.GetCVar(CCVars.OutlineEnabled))
{
if(entityToClick != null && entityToClick.TryGetComponent(out outline))
{
outline.OnMouseLeave(); //Prevent outline remains from persisting post command.
}
return;
}
if (entityToClick == _lastHoveredEntity)
{
if (entityToClick != null && entityToClick.TryGetComponent(out outline))
{
outline.UpdateInRange(inRange, renderScale);
}
return;
}
if (_lastHoveredEntity != null && !_lastHoveredEntity.Deleted &&
_lastHoveredEntity.TryGetComponent(out outline))
{
outline.OnMouseLeave();
}
_lastHoveredEntity = entityToClick;
if (_lastHoveredEntity != null && _lastHoveredEntity.TryGetComponent(out outline))
{
outline.OnMouseEnter(inRange, renderScale);
}
}
public IEntity? GetEntityUnderPosition(MapCoordinates coordinates)
{
var entitiesUnderPosition = GetEntitiesUnderPosition(coordinates);
return entitiesUnderPosition.Count > 0 ? entitiesUnderPosition[0] : null;
}
public IList<IEntity> GetEntitiesUnderPosition(EntityCoordinates coordinates)
{
return GetEntitiesUnderPosition(coordinates.ToMap(EntityManager));
}
public IList<IEntity> GetEntitiesUnderPosition(MapCoordinates coordinates)
{
// Find all the entities intersecting our click
var entities = IoCManager.Resolve<IEntityLookup>().GetEntitiesIntersecting(coordinates.MapId,
Box2.CenteredAround(coordinates.Position, (1, 1)));
// Check the entities against whether or not we can click them
var foundEntities = new List<(IEntity clicked, int drawDepth, uint renderOrder)>();
foreach (var entity in entities)
{
if (entity.TryGetComponent<ClickableComponent>(out var component)
&& entity.Transform.IsMapTransform
&& component.CheckClick(coordinates.Position, out var drawDepthClicked, out var renderOrder))
{
foundEntities.Add((entity, drawDepthClicked, renderOrder));
}
}
if (foundEntities.Count == 0)
return new List<IEntity>();
foundEntities.Sort(new ClickableEntityComparer());
// 0 is the top element.
foundEntities.Reverse();
return foundEntities.Select(a => a.clicked).ToList();
}
/// <summary>
/// Gets all entities intersecting the given position.
///
/// Static alternative to GetEntitiesUnderPosition to cut out
/// some of the boilerplate needed to get state manager and check the current state.
/// </summary>
/// <param name="stateManager">state manager to use to get the current game screen</param>
/// <param name="coordinates">coordinates to check</param>
/// <returns>the entities under the position, empty list if none found</returns>
public static IList<IEntity> GetEntitiesUnderPosition(IStateManager stateManager, EntityCoordinates coordinates)
{
if (stateManager.CurrentState is GameScreenBase gameScreenBase)
{
return gameScreenBase.GetEntitiesUnderPosition(coordinates);
}
return ImmutableList<IEntity>.Empty;
}
internal class ClickableEntityComparer : IComparer<(IEntity clicked, int depth, uint renderOrder)>
{
public int Compare((IEntity clicked, int depth, uint renderOrder) x,
(IEntity clicked, int depth, uint renderOrder) y)
{
var val = x.depth.CompareTo(y.depth);
if (val != 0)
{
return val;
}
// Turning this off it can make picking stuff out of lockers and such up a bit annoying.
/*
val = x.renderOrder.CompareTo(y.renderOrder);
if (val != 0)
{
return val;
}
*/
var transX = x.clicked.Transform;
var transY = y.clicked.Transform;
val = transX.Coordinates.Y.CompareTo(transY.Coordinates.Y);
if (val != 0)
{
return val;
}
return x.clicked.Uid.CompareTo(y.clicked.Uid);
}
}
/// <summary>
/// Converts a state change event from outside the simulation to inside the simulation.
/// </summary>
/// <param name="args">Event data values for a bound key state change.</param>
protected virtual void OnKeyBindStateChanged(ViewportBoundKeyEventArgs args)
{
// If there is no InputSystem, then there is nothing to forward to, and nothing to do here.
if(!EntitySystemManager.TryGetEntitySystem(out InputSystem? inputSys))
return;
var kArgs = args.KeyEventArgs;
var func = kArgs.Function;
var funcId = InputManager.NetworkBindMap.KeyFunctionID(func);
EntityCoordinates coordinates = default;
EntityUid entityToClick = default;
if (args.Viewport is IViewportControl vp)
{
var mousePosWorld = vp.ScreenToMap(kArgs.PointerLocation.Position);
entityToClick = GetEntityUnderPosition(mousePosWorld)?.Uid ?? EntityUid.Invalid;
coordinates = MapManager.TryFindGridAt(mousePosWorld, out var grid) ? grid.MapToGrid(mousePosWorld) :
EntityCoordinates.FromMap(EntityManager, MapManager, mousePosWorld);
}
var message = new FullInputCmdMessage(Timing.CurTick, Timing.TickFraction, funcId, kArgs.State,
coordinates , kArgs.PointerLocation,
entityToClick);
// client side command handlers will always be sent the local player session.
var session = PlayerManager.LocalPlayer?.Session;
if (inputSys.HandleInputCommand(session, func, message))
{
kArgs.Handle();
}
}
}
}

View File

@@ -1,15 +0,0 @@
using Content.Client.UserInterface;
namespace Content.Client.State
{
/// <summary>
/// Client state that has a main viewport.
/// </summary>
/// <remarks>
/// Used for taking no-UI screenshots (including things like flash overlay).
/// </remarks>
public interface IMainViewportState
{
public MainViewport Viewport { get; }
}
}

View File

@@ -1,98 +0,0 @@
using System;
using Content.Client.UserInterface;
using Robust.Client;
using Robust.Client.UserInterface;
using Robust.Shared.IoC;
using Robust.Shared.Network;
namespace Content.Client.State
{
public class LauncherConnecting : Robust.Client.State.State
{
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
[Dependency] private readonly IClientNetManager _clientNetManager = default!;
[Dependency] private readonly IGameController _gameController = default!;
[Dependency] private readonly IBaseClient _baseClient = default!;
private LauncherConnectingGui? _control;
private Page _currentPage;
private string? _connectFailReason;
public string? Address => _gameController.LaunchState.Ss14Address ?? _gameController.LaunchState.ConnectAddress;
public string? ConnectFailReason
{
get => _connectFailReason;
private set
{
_connectFailReason = value;
ConnectFailReasonChanged?.Invoke(value);
}
}
public Page CurrentPage
{
get => _currentPage;
private set
{
_currentPage = value;
PageChanged?.Invoke(value);
}
}
public ClientConnectionState ConnectionState => _clientNetManager.ClientConnectState;
public event Action<Page>? PageChanged;
public event Action<string?>? ConnectFailReasonChanged;
public event Action<ClientConnectionState>? ConnectionStateChanged;
public override void Startup()
{
_control = new LauncherConnectingGui(this);
_userInterfaceManager.StateRoot.AddChild(_control);
_clientNetManager.ConnectFailed += (_, args) =>
{
ConnectFailReason = args.Reason;
CurrentPage = Page.ConnectFailed;
};
_clientNetManager.ClientConnectStateChanged += state => ConnectionStateChanged?.Invoke(state);
CurrentPage = Page.Connecting;
}
public void RetryConnect()
{
if (_gameController.LaunchState.ConnectEndpoint != null)
{
_baseClient.ConnectToServer(_gameController.LaunchState.ConnectEndpoint);
CurrentPage = Page.Connecting;
}
}
public void Exit()
{
_gameController.Shutdown("Exit button pressed");
}
public override void Shutdown()
{
_control?.Dispose();
}
public void SetDisconnected()
{
CurrentPage = Page.Disconnected;
}
public enum Page : byte
{
Connecting,
ConnectFailed,
Disconnected,
}
}
}

View File

@@ -1,271 +0,0 @@
using System;
using System.Linq;
using Content.Client.Interfaces;
using Content.Client.Interfaces.Chat;
using Content.Client.UserInterface;
using Content.Client.Voting;
using Content.Shared.Chat;
using Content.Shared.Input;
using Robust.Client;
using Robust.Client.Console;
using Robust.Client.Input;
using Robust.Client.Player;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.GameObjects;
using Robust.Shared.Input.Binding;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using Robust.Shared.ViewVariables;
using static Content.Shared.GameTicking.SharedGameTicker;
namespace Content.Client.State
{
public class LobbyState : Robust.Client.State.State
{
[Dependency] private readonly IBaseClient _baseClient = default!;
[Dependency] private readonly IClientConsoleHost _consoleHost = default!;
[Dependency] private readonly IChatManager _chatManager = default!;
[Dependency] private readonly IInputManager _inputManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly IClientGameTicker _clientGameTicker = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
[Dependency] private readonly IClientPreferencesManager _preferencesManager = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IVoteManager _voteManager = default!;
[ViewVariables] private CharacterSetupGui _characterSetup = default!;
[ViewVariables] private LobbyGui _lobby = default!;
public override void Startup()
{
_characterSetup = new CharacterSetupGui(_entityManager, _resourceCache, _preferencesManager,
_prototypeManager);
LayoutContainer.SetAnchorPreset(_characterSetup, LayoutContainer.LayoutPreset.Wide);
_characterSetup.CloseButton.OnPressed += _ =>
{
_userInterfaceManager.StateRoot.AddChild(_lobby);
_userInterfaceManager.StateRoot.RemoveChild(_characterSetup);
};
_characterSetup.SaveButton.OnPressed += _ =>
{
_characterSetup.Save();
_lobby?.CharacterPreview.UpdateUI();
};
_lobby = new LobbyGui(_entityManager, _preferencesManager);
_userInterfaceManager.StateRoot.AddChild(_lobby);
LayoutContainer.SetAnchorPreset(_lobby, LayoutContainer.LayoutPreset.Wide);
_chatManager.SetChatBox(_lobby.Chat);
_voteManager.SetPopupContainer(_lobby.VoteContainer);
_lobby.Chat.DefaultChatFormat = "ooc \"{0}\"";
_lobby.ServerName.Text = _baseClient.GameInfo?.ServerName;
_inputManager.SetInputCommand(ContentKeyFunctions.FocusChat,
InputCmdHandler.FromDelegate(_ => GameScreen.FocusChat(_lobby.Chat)));
_inputManager.SetInputCommand(ContentKeyFunctions.FocusOOC,
InputCmdHandler.FromDelegate(_ => GameScreen.FocusChannel(_lobby.Chat, ChatChannel.OOC)));
_inputManager.SetInputCommand(ContentKeyFunctions.FocusAdminChat,
InputCmdHandler.FromDelegate(_ => GameScreen.FocusChannel(_lobby.Chat, ChatChannel.AdminChat)));
_inputManager.SetInputCommand(ContentKeyFunctions.CycleChatChannelForward,
InputCmdHandler.FromDelegate(_ => _lobby.Chat.CycleChatChannel(true)));
_inputManager.SetInputCommand(ContentKeyFunctions.CycleChatChannelBackward,
InputCmdHandler.FromDelegate(_ => _lobby.Chat.CycleChatChannel(false)));
UpdateLobbyUi();
_lobby.CharacterPreview.CharacterSetupButton.OnPressed += _ =>
{
SetReady(false);
_userInterfaceManager.StateRoot.RemoveChild(_lobby);
_userInterfaceManager.StateRoot.AddChild(_characterSetup);
};
_lobby.ObserveButton.OnPressed += _ => _consoleHost.ExecuteCommand("observe");
_lobby.ReadyButton.OnPressed += _ =>
{
if (!_clientGameTicker.IsGameStarted)
{
return;
}
new LateJoinGui().OpenCentered();
};
_lobby.ReadyButton.OnToggled += args =>
{
SetReady(args.Pressed);
};
_lobby.LeaveButton.OnPressed += _ => _consoleHost.ExecuteCommand("disconnect");
_lobby.OptionsButton.OnPressed += _ => new OptionsMenu().Open();
UpdatePlayerList();
_playerManager.PlayerListUpdated += PlayerManagerOnPlayerListUpdated;
_clientGameTicker.InfoBlobUpdated += UpdateLobbyUi;
_clientGameTicker.LobbyStatusUpdated += LobbyStatusUpdated;
_clientGameTicker.LobbyReadyUpdated += LobbyReadyUpdated;
_clientGameTicker.LobbyLateJoinStatusUpdated += LobbyLateJoinStatusUpdated;
}
public override void Shutdown()
{
_playerManager.PlayerListUpdated -= PlayerManagerOnPlayerListUpdated;
_clientGameTicker.InfoBlobUpdated -= UpdateLobbyUi;
_clientGameTicker.LobbyStatusUpdated -= LobbyStatusUpdated;
_clientGameTicker.LobbyReadyUpdated -= LobbyReadyUpdated;
_clientGameTicker.LobbyLateJoinStatusUpdated -= LobbyLateJoinStatusUpdated;
_clientGameTicker.Status.Clear();
_lobby.Dispose();
_characterSetup.Dispose();
}
public override void FrameUpdate(FrameEventArgs e)
{
if (_clientGameTicker.IsGameStarted)
{
_lobby.StartTime.Text = "";
return;
}
string text;
if (_clientGameTicker.Paused)
{
text = Loc.GetString("Paused");
}
else
{
var difference = _clientGameTicker.StartTime - _gameTiming.CurTime;
var seconds = difference.TotalSeconds;
if (seconds < 0)
{
text = Loc.GetString(seconds < -5 ? "Right Now?" : "Right Now");
}
else
{
text = $"{(int) Math.Floor(difference.TotalMinutes / 60)}:{difference.Seconds:D2}";
}
}
_lobby.StartTime.Text = Loc.GetString("Round Starts In: {0}", text);
}
private void PlayerManagerOnPlayerListUpdated(object? sender, EventArgs e)
{
// Remove disconnected sessions from the Ready Dict
foreach (var p in _clientGameTicker.Status)
{
if (!_playerManager.SessionsDict.TryGetValue(p.Key, out _))
{
// This is a shitty fix. Observers can rejoin because they are already in the game.
// So we don't delete them, but keep them if they decide to rejoin
if (p.Value != PlayerStatus.Observer)
_clientGameTicker.Status.Remove(p.Key);
}
}
UpdatePlayerList();
}
private void LobbyReadyUpdated() => UpdatePlayerList();
private void LobbyStatusUpdated()
{
UpdatePlayerList();
UpdateLobbyUi();
}
private void LobbyLateJoinStatusUpdated()
{
_lobby.ReadyButton.Disabled = _clientGameTicker.DisallowedLateJoin;
}
private void UpdateLobbyUi()
{
if (_lobby == null)
{
return;
}
if (_clientGameTicker.IsGameStarted)
{
_lobby.ReadyButton.Text = Loc.GetString("Join");
_lobby.ReadyButton.ToggleMode = false;
_lobby.ReadyButton.Pressed = false;
}
else
{
_lobby.StartTime.Text = "";
_lobby.ReadyButton.Text = Loc.GetString("Ready Up");
_lobby.ReadyButton.ToggleMode = true;
_lobby.ReadyButton.Disabled = false;
_lobby.ReadyButton.Pressed = _clientGameTicker.AreWeReady;
}
if (_clientGameTicker.ServerInfoBlob != null)
{
_lobby.ServerInfo.SetInfoBlob(_clientGameTicker.ServerInfoBlob);
}
}
private void UpdatePlayerList()
{
_lobby.OnlinePlayerList.Clear();
foreach (var session in _playerManager.Sessions.OrderBy(s => s.Name))
{
var readyState = "";
// Don't show ready state if we're ingame
if (!_clientGameTicker.IsGameStarted)
{
PlayerStatus status;
if (session.UserId == _playerManager.LocalPlayer?.UserId)
status = _clientGameTicker.AreWeReady ? PlayerStatus.Ready : PlayerStatus.NotReady;
else
_clientGameTicker.Status.TryGetValue(session.UserId, out status);
readyState = status switch
{
PlayerStatus.NotReady => Loc.GetString("Not Ready"),
PlayerStatus.Ready => Loc.GetString("Ready"),
PlayerStatus.Observer => Loc.GetString("Observer"),
_ => "",
};
}
_lobby.OnlinePlayerList.AddItem(session.Name, readyState);
}
}
private void SetReady(bool newReady)
{
if (_clientGameTicker.IsGameStarted)
{
return;
}
_consoleHost.ExecuteCommand($"toggleready {newReady}");
UpdatePlayerList();
}
}
}

View File

@@ -1,324 +0,0 @@
using System;
using System.Text.RegularExpressions;
using Content.Client.Changelog;
using Content.Client.UserInterface;
using Robust.Client;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared;
using Robust.Shared.Configuration;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Log;
using Robust.Shared.Network;
using Robust.Shared.Utility;
using UsernameHelpers = Robust.Shared.AuthLib.UsernameHelpers;
namespace Content.Client.State
{
/// <summary>
/// Main menu screen that is the first screen to be displayed when the game starts.
/// </summary>
// Instantiated dynamically through the StateManager, Dependencies will be resolved.
public class MainScreen : Robust.Client.State.State
{
private const string PublicServerAddress = "server.spacestation14.io";
[Dependency] private readonly IBaseClient _client = default!;
[Dependency] private readonly IClientNetManager _netManager = default!;
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
[Dependency] private readonly IGameController _controllerProxy = default!;
[Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
private MainMenuControl _mainMenuControl = default!;
private OptionsMenu _optionsMenu = default!;
private bool _isConnecting;
// ReSharper disable once InconsistentNaming
private static readonly Regex IPv6Regex = new(@"\[(.*:.*:.*)](?::(\d+))?");
/// <inheritdoc />
public override void Startup()
{
_mainMenuControl = new MainMenuControl(_resourceCache, _configurationManager);
_userInterfaceManager.StateRoot.AddChild(_mainMenuControl);
_mainMenuControl.QuitButton.OnPressed += QuitButtonPressed;
_mainMenuControl.OptionsButton.OnPressed += OptionsButtonPressed;
_mainMenuControl.DirectConnectButton.OnPressed += DirectConnectButtonPressed;
_mainMenuControl.JoinPublicServerButton.OnPressed += JoinPublicServerButtonPressed;
_mainMenuControl.AddressBox.OnTextEntered += AddressBoxEntered;
_client.RunLevelChanged += RunLevelChanged;
_optionsMenu = new OptionsMenu();
}
/// <inheritdoc />
public override void Shutdown()
{
_client.RunLevelChanged -= RunLevelChanged;
_netManager.ConnectFailed -= _onConnectFailed;
_mainMenuControl.Dispose();
_optionsMenu.Dispose();
}
private void QuitButtonPressed(BaseButton.ButtonEventArgs args)
{
_controllerProxy.Shutdown();
}
private void OptionsButtonPressed(BaseButton.ButtonEventArgs args)
{
_optionsMenu.OpenCentered();
}
private void DirectConnectButtonPressed(BaseButton.ButtonEventArgs args)
{
var input = _mainMenuControl.AddressBox;
TryConnect(input.Text);
}
private void JoinPublicServerButtonPressed(BaseButton.ButtonEventArgs args)
{
TryConnect(PublicServerAddress);
}
private void AddressBoxEntered(LineEdit.LineEditEventArgs args)
{
if (_isConnecting)
{
return;
}
TryConnect(args.Text);
}
private void TryConnect(string address)
{
var inputName = _mainMenuControl.UserNameBox.Text.Trim();
if (!UsernameHelpers.IsNameValid(inputName, out var reason))
{
var invalidReason = Loc.GetString(reason.ToText());
_userInterfaceManager.Popup(
Loc.GetString("Invalid username:\n{0}", invalidReason),
Loc.GetString("Invalid Username"));
return;
}
var configName = _configurationManager.GetCVar(CVars.PlayerName);
if (_mainMenuControl.UserNameBox.Text != configName)
{
_configurationManager.SetCVar(CVars.PlayerName, inputName);
_configurationManager.SaveToFile();
}
_setConnectingState(true);
_netManager.ConnectFailed += _onConnectFailed;
try
{
ParseAddress(address, out var ip, out var port);
_client.ConnectToServer(ip, port);
}
catch (ArgumentException e)
{
_userInterfaceManager.Popup($"Unable to connect: {e.Message}", "Connection error.");
Logger.Warning(e.ToString());
_netManager.ConnectFailed -= _onConnectFailed;
_setConnectingState(false);
}
}
private void RunLevelChanged(object? obj, RunLevelChangedEventArgs args)
{
if (args.NewLevel == ClientRunLevel.Initialize)
{
_setConnectingState(false);
_netManager.ConnectFailed -= _onConnectFailed;
}
}
private void ParseAddress(string address, out string ip, out ushort port)
{
var match6 = IPv6Regex.Match(address);
if (match6 != Match.Empty)
{
ip = match6.Groups[1].Value;
if (!match6.Groups[2].Success)
{
port = _client.DefaultPort;
}
else if (!ushort.TryParse(match6.Groups[2].Value, out port))
{
throw new ArgumentException("Not a valid port.");
}
return;
}
// See if the IP includes a port.
var split = address.Split(':');
ip = address;
port = _client.DefaultPort;
if (split.Length > 2)
{
throw new ArgumentException("Not a valid Address.");
}
// IP:port format.
if (split.Length == 2)
{
ip = split[0];
if (!ushort.TryParse(split[1], out port))
{
throw new ArgumentException("Not a valid port.");
}
}
}
private void _onConnectFailed(object? _, NetConnectFailArgs args)
{
_userInterfaceManager.Popup($"Failed to connect:\n{args.Reason}");
_netManager.ConnectFailed -= _onConnectFailed;
_setConnectingState(false);
}
private void _setConnectingState(bool state)
{
_isConnecting = state;
_mainMenuControl.DirectConnectButton.Disabled = state;
#if FULL_RELEASE
_mainMenuControl.JoinPublicServerButton.Disabled = state;
#endif
}
private sealed class MainMenuControl : Control
{
private readonly IResourceCache _resourceCache;
private readonly IConfigurationManager _configurationManager;
public LineEdit UserNameBox { get; }
public Button JoinPublicServerButton { get; }
public LineEdit AddressBox { get; }
public Button DirectConnectButton { get; }
public Button OptionsButton { get; }
public Button QuitButton { get; }
public Label VersionLabel { get; }
public MainMenuControl(IResourceCache resCache, IConfigurationManager configMan)
{
_resourceCache = resCache;
_configurationManager = configMan;
LayoutContainer.SetAnchorPreset(this, LayoutContainer.LayoutPreset.Wide);
AddChild(new ParallaxControl());
var layout = new LayoutContainer();
AddChild(layout);
var vBox = new VBoxContainer
{
StyleIdentifier = "mainMenuVBox"
};
layout.AddChild(vBox);
LayoutContainer.SetAnchorPreset(vBox, LayoutContainer.LayoutPreset.TopRight);
LayoutContainer.SetMarginRight(vBox, -25);
LayoutContainer.SetMarginTop(vBox, 30);
LayoutContainer.SetGrowHorizontal(vBox, LayoutContainer.GrowDirection.Begin);
var logoTexture = _resourceCache.GetResource<TextureResource>("/Textures/Logo/logo.png");
var logo = new TextureRect
{
Texture = logoTexture,
Stretch = TextureRect.StretchMode.KeepCentered,
};
vBox.AddChild(logo);
var userNameHBox = new HBoxContainer {SeparationOverride = 4};
vBox.AddChild(userNameHBox);
userNameHBox.AddChild(new Label {Text = "Username:"});
var currentUserName = _configurationManager.GetCVar(CVars.PlayerName);
UserNameBox = new LineEdit
{
Text = currentUserName, PlaceHolder = "Username",
HorizontalExpand = true
};
userNameHBox.AddChild(UserNameBox);
JoinPublicServerButton = new Button
{
Text = "Join Public Server",
StyleIdentifier = "mainMenu",
TextAlign = Label.AlignMode.Center,
#if !FULL_RELEASE
Disabled = true,
ToolTip = "Cannot connect to public server with a debug build."
#endif
};
vBox.AddChild(JoinPublicServerButton);
// Separator.
vBox.AddChild(new Control {MinSize = (0, 2)});
AddressBox = new LineEdit
{
Text = "localhost",
PlaceHolder = "server address:port",
HorizontalExpand = true
};
vBox.AddChild(AddressBox);
DirectConnectButton = new Button
{
Text = "Direct Connect",
TextAlign = Label.AlignMode.Center,
StyleIdentifier = "mainMenu",
};
vBox.AddChild(DirectConnectButton);
// Separator.
vBox.AddChild(new Control {MinSize = (0, 2)});
OptionsButton = new Button
{
Text = "Options",
TextAlign = Label.AlignMode.Center,
StyleIdentifier = "mainMenu",
};
vBox.AddChild(OptionsButton);
QuitButton = new Button
{
Text = "Quit",
TextAlign = Label.AlignMode.Center,
StyleIdentifier = "mainMenu",
};
vBox.AddChild(QuitButton);
vBox.AddChild(new ChangelogButton());
VersionLabel = new Label
{
Text = "v0.1"
};
LayoutContainer.SetAnchorPreset(VersionLabel, LayoutContainer.LayoutPreset.BottomRight);
LayoutContainer.SetGrowHorizontal(VersionLabel, LayoutContainer.GrowDirection.Begin);
LayoutContainer.SetGrowVertical(VersionLabel, LayoutContainer.GrowDirection.Begin);
layout.AddChild(VersionLabel);
}
}
}
}