Ready Indicator in the lobby (#1771)
* Ready Indicator in the lobby * Use SessionID instead of Name * Don't show ready state when game is already running * Make Ready List not selectable * -Remove disconnected sessions from Ready -Fix showing ReadyStatus when staying in lobby
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Content.Client.Interfaces;
|
using Content.Client.Interfaces;
|
||||||
using Content.Client.State;
|
using Content.Client.State;
|
||||||
using Content.Client.UserInterface;
|
using Content.Client.UserInterface;
|
||||||
@@ -8,6 +9,7 @@ using Robust.Client.Interfaces.Graphics;
|
|||||||
using Robust.Client.Interfaces.State;
|
using Robust.Client.Interfaces.State;
|
||||||
using Robust.Shared.Interfaces.Network;
|
using Robust.Shared.Interfaces.Network;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Network;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
using Robust.Shared.ViewVariables;
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
@@ -27,9 +29,11 @@ namespace Content.Client.GameTicking
|
|||||||
[ViewVariables] public string ServerInfoBlob { get; private set; }
|
[ViewVariables] public string ServerInfoBlob { get; private set; }
|
||||||
[ViewVariables] public DateTime StartTime { get; private set; }
|
[ViewVariables] public DateTime StartTime { get; private set; }
|
||||||
[ViewVariables] public bool Paused { get; private set; }
|
[ViewVariables] public bool Paused { get; private set; }
|
||||||
|
[ViewVariables] public Dictionary<NetSessionId, bool> Ready { get; private set; }
|
||||||
|
|
||||||
public event Action InfoBlobUpdated;
|
public event Action InfoBlobUpdated;
|
||||||
public event Action LobbyStatusUpdated;
|
public event Action LobbyStatusUpdated;
|
||||||
|
public event Action LobbyReadyUpdated;
|
||||||
|
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
@@ -40,12 +44,14 @@ namespace Content.Client.GameTicking
|
|||||||
_netManager.RegisterNetMessage<MsgTickerLobbyStatus>(nameof(MsgTickerLobbyStatus), LobbyStatus);
|
_netManager.RegisterNetMessage<MsgTickerLobbyStatus>(nameof(MsgTickerLobbyStatus), LobbyStatus);
|
||||||
_netManager.RegisterNetMessage<MsgTickerLobbyInfo>(nameof(MsgTickerLobbyInfo), LobbyInfo);
|
_netManager.RegisterNetMessage<MsgTickerLobbyInfo>(nameof(MsgTickerLobbyInfo), LobbyInfo);
|
||||||
_netManager.RegisterNetMessage<MsgTickerLobbyCountdown>(nameof(MsgTickerLobbyCountdown), LobbyCountdown);
|
_netManager.RegisterNetMessage<MsgTickerLobbyCountdown>(nameof(MsgTickerLobbyCountdown), LobbyCountdown);
|
||||||
|
_netManager.RegisterNetMessage<MsgTickerLobbyReady>(nameof(MsgTickerLobbyReady), LobbyReady);
|
||||||
_netManager.RegisterNetMessage<MsgRoundEndMessage>(nameof(MsgRoundEndMessage), RoundEnd);
|
_netManager.RegisterNetMessage<MsgRoundEndMessage>(nameof(MsgRoundEndMessage), RoundEnd);
|
||||||
_netManager.RegisterNetMessage<MsgRequestWindowAttention>(nameof(MsgRequestWindowAttention), msg =>
|
_netManager.RegisterNetMessage<MsgRequestWindowAttention>(nameof(MsgRequestWindowAttention), msg =>
|
||||||
{
|
{
|
||||||
IoCManager.Resolve<IClyde>().RequestWindowAttention();
|
IoCManager.Resolve<IClyde>().RequestWindowAttention();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Ready = new Dictionary<NetSessionId, bool>();
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,6 +68,8 @@ namespace Content.Client.GameTicking
|
|||||||
IsGameStarted = message.IsRoundStarted;
|
IsGameStarted = message.IsRoundStarted;
|
||||||
AreWeReady = message.YouAreReady;
|
AreWeReady = message.YouAreReady;
|
||||||
Paused = message.Paused;
|
Paused = message.Paused;
|
||||||
|
if (IsGameStarted)
|
||||||
|
Ready.Clear();
|
||||||
|
|
||||||
LobbyStatusUpdated?.Invoke();
|
LobbyStatusUpdated?.Invoke();
|
||||||
}
|
}
|
||||||
@@ -84,9 +92,18 @@ namespace Content.Client.GameTicking
|
|||||||
Paused = message.Paused;
|
Paused = message.Paused;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void LobbyReady(MsgTickerLobbyReady message)
|
||||||
|
{
|
||||||
|
// Merge the Dictionaries
|
||||||
|
foreach (var p in message.PlayerReady)
|
||||||
|
{
|
||||||
|
Ready[p.Key] = p.Value;
|
||||||
|
}
|
||||||
|
LobbyReadyUpdated?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
private void RoundEnd(MsgRoundEndMessage message)
|
private void RoundEnd(MsgRoundEndMessage message)
|
||||||
{
|
{
|
||||||
|
|
||||||
//This is not ideal at all, but I don't see an immediately better fit anywhere else.
|
//This is not ideal at all, but I don't see an immediately better fit anywhere else.
|
||||||
var roundEnd = new RoundEndSummaryWindow(message.GamemodeTitle, message.RoundDuration, message.AllPlayersEndInfo);
|
var roundEnd = new RoundEndSummaryWindow(message.GamemodeTitle, message.RoundDuration, message.AllPlayersEndInfo);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
using Robust.Shared.Network;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Content.Client.Interfaces
|
namespace Content.Client.Interfaces
|
||||||
{
|
{
|
||||||
@@ -9,9 +11,11 @@ namespace Content.Client.Interfaces
|
|||||||
bool AreWeReady { get; }
|
bool AreWeReady { get; }
|
||||||
DateTime StartTime { get; }
|
DateTime StartTime { get; }
|
||||||
bool Paused { get; }
|
bool Paused { get; }
|
||||||
|
Dictionary<NetSessionId, bool> Ready { get; }
|
||||||
|
|
||||||
void Initialize();
|
void Initialize();
|
||||||
event Action InfoBlobUpdated;
|
event Action InfoBlobUpdated;
|
||||||
event Action LobbyStatusUpdated;
|
event Action LobbyStatusUpdated;
|
||||||
|
event Action LobbyReadyUpdated;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,7 +99,8 @@ namespace Content.Client.State
|
|||||||
|
|
||||||
_playerManager.PlayerListUpdated += PlayerManagerOnPlayerListUpdated;
|
_playerManager.PlayerListUpdated += PlayerManagerOnPlayerListUpdated;
|
||||||
_clientGameTicker.InfoBlobUpdated += UpdateLobbyUi;
|
_clientGameTicker.InfoBlobUpdated += UpdateLobbyUi;
|
||||||
_clientGameTicker.LobbyStatusUpdated += UpdateLobbyUi;
|
_clientGameTicker.LobbyStatusUpdated += LobbyStatusUpdated;
|
||||||
|
_clientGameTicker.LobbyReadyUpdated += LobbyReadyUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Shutdown()
|
public override void Shutdown()
|
||||||
@@ -149,7 +150,25 @@ namespace Content.Client.State
|
|||||||
_lobby.StartTime.Text = Loc.GetString("Round Starts In: {0}", text);
|
_lobby.StartTime.Text = Loc.GetString("Round Starts In: {0}", text);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PlayerManagerOnPlayerListUpdated(object sender, EventArgs e) => UpdatePlayerList();
|
private void PlayerManagerOnPlayerListUpdated(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
// Remove disconnected sessions from the Ready Dict
|
||||||
|
foreach (var p in _clientGameTicker.Ready)
|
||||||
|
{
|
||||||
|
if (!_playerManager.SessionsDict.TryGetValue(p.Key, out _))
|
||||||
|
{
|
||||||
|
_clientGameTicker.Ready.Remove(p.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UpdatePlayerList();
|
||||||
|
}
|
||||||
|
private void LobbyReadyUpdated() => UpdatePlayerList();
|
||||||
|
|
||||||
|
private void LobbyStatusUpdated()
|
||||||
|
{
|
||||||
|
UpdatePlayerList();
|
||||||
|
UpdateLobbyUi();
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateLobbyUi()
|
private void UpdateLobbyUi()
|
||||||
{
|
{
|
||||||
@@ -178,10 +197,24 @@ namespace Content.Client.State
|
|||||||
private void UpdatePlayerList()
|
private void UpdatePlayerList()
|
||||||
{
|
{
|
||||||
_lobby.OnlinePlayerItemList.Clear();
|
_lobby.OnlinePlayerItemList.Clear();
|
||||||
|
_lobby.PlayerReadyList.Clear();
|
||||||
|
|
||||||
foreach (var session in _playerManager.Sessions.OrderBy(s => s.Name))
|
foreach (var session in _playerManager.Sessions.OrderBy(s => s.Name))
|
||||||
{
|
{
|
||||||
_lobby.OnlinePlayerItemList.AddItem(session.Name);
|
_lobby.OnlinePlayerItemList.AddItem(session.Name);
|
||||||
|
|
||||||
|
var readyState = "";
|
||||||
|
// Don't show ready state if we're ingame
|
||||||
|
if (!_clientGameTicker.IsGameStarted)
|
||||||
|
{
|
||||||
|
var ready = false;
|
||||||
|
if (session.SessionId == _playerManager.LocalPlayer.SessionId)
|
||||||
|
ready = _clientGameTicker.AreWeReady;
|
||||||
|
else
|
||||||
|
_clientGameTicker.Ready.TryGetValue(session.SessionId, out ready);
|
||||||
|
readyState = ready ? Loc.GetString("Ready") : Loc.GetString("Not Ready");
|
||||||
|
}
|
||||||
|
_lobby.PlayerReadyList.AddItem(readyState, null, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,6 +226,7 @@ namespace Content.Client.State
|
|||||||
}
|
}
|
||||||
|
|
||||||
_console.ProcessCommand($"toggleready {newReady}");
|
_console.ProcessCommand($"toggleready {newReady}");
|
||||||
|
UpdatePlayerList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Content.Client.Chat;
|
using Content.Client.Chat;
|
||||||
using Content.Client.Interfaces;
|
using Content.Client.Interfaces;
|
||||||
using Content.Client.UserInterface.Stylesheets;
|
using Content.Client.UserInterface.Stylesheets;
|
||||||
using Content.Client.Utility;
|
using Content.Client.Utility;
|
||||||
@@ -22,6 +22,7 @@ namespace Content.Client.UserInterface
|
|||||||
public Button LeaveButton { get; }
|
public Button LeaveButton { get; }
|
||||||
public ChatBox Chat { get; }
|
public ChatBox Chat { get; }
|
||||||
public ItemList OnlinePlayerItemList { get; }
|
public ItemList OnlinePlayerItemList { get; }
|
||||||
|
public ItemList PlayerReadyList { get; }
|
||||||
public ServerInfo ServerInfo { get; }
|
public ServerInfo ServerInfo { get; }
|
||||||
public LobbyCharacterPreviewPanel CharacterPreview { get; }
|
public LobbyCharacterPreviewPanel CharacterPreview { get; }
|
||||||
|
|
||||||
@@ -219,7 +220,25 @@ namespace Content.Client.UserInterface
|
|||||||
MarginBottomOverride = 3,
|
MarginBottomOverride = 3,
|
||||||
Children =
|
Children =
|
||||||
{
|
{
|
||||||
(OnlinePlayerItemList = new ItemList())
|
new HBoxContainer
|
||||||
|
{
|
||||||
|
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||||
|
CustomMinimumSize = (50,50),
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
(OnlinePlayerItemList = new ItemList
|
||||||
|
{
|
||||||
|
SizeFlagsVertical = SizeFlags.FillExpand,
|
||||||
|
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||||
|
}),
|
||||||
|
(PlayerReadyList = new ItemList
|
||||||
|
{
|
||||||
|
SizeFlagsVertical = SizeFlags.FillExpand,
|
||||||
|
SizeFlagsHorizontal = SizeFlags.FillExpand,
|
||||||
|
SizeFlagsStretchRatio = 0.2f
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new NanoHeading
|
new NanoHeading
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ using Robust.Shared.Localization;
|
|||||||
using Robust.Shared.Log;
|
using Robust.Shared.Log;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
|
using Robust.Shared.Network;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
@@ -138,6 +139,7 @@ namespace Content.Server.GameTicking
|
|||||||
_netManager.RegisterNetMessage<MsgTickerLobbyStatus>(nameof(MsgTickerLobbyStatus));
|
_netManager.RegisterNetMessage<MsgTickerLobbyStatus>(nameof(MsgTickerLobbyStatus));
|
||||||
_netManager.RegisterNetMessage<MsgTickerLobbyInfo>(nameof(MsgTickerLobbyInfo));
|
_netManager.RegisterNetMessage<MsgTickerLobbyInfo>(nameof(MsgTickerLobbyInfo));
|
||||||
_netManager.RegisterNetMessage<MsgTickerLobbyCountdown>(nameof(MsgTickerLobbyCountdown));
|
_netManager.RegisterNetMessage<MsgTickerLobbyCountdown>(nameof(MsgTickerLobbyCountdown));
|
||||||
|
_netManager.RegisterNetMessage<MsgTickerLobbyReady>(nameof(MsgTickerLobbyReady));
|
||||||
_netManager.RegisterNetMessage<MsgRoundEndMessage>(nameof(MsgRoundEndMessage));
|
_netManager.RegisterNetMessage<MsgRoundEndMessage>(nameof(MsgRoundEndMessage));
|
||||||
_netManager.RegisterNetMessage<MsgRequestWindowAttention>(nameof(MsgRequestWindowAttention));
|
_netManager.RegisterNetMessage<MsgRequestWindowAttention>(nameof(MsgRequestWindowAttention));
|
||||||
|
|
||||||
@@ -381,6 +383,7 @@ namespace Content.Server.GameTicking
|
|||||||
|
|
||||||
_playersInLobby[player] = ready;
|
_playersInLobby[player] = ready;
|
||||||
_netManager.ServerSendMessage(_getStatusMsg(player), player.ConnectedClient);
|
_netManager.ServerSendMessage(_getStatusMsg(player), player.ConnectedClient);
|
||||||
|
_netManager.ServerSendToAll(GetReadySingle(player, ready));
|
||||||
}
|
}
|
||||||
|
|
||||||
public T AddGameRule<T>() where T : GameRule, new()
|
public T AddGameRule<T>() where T : GameRule, new()
|
||||||
@@ -871,6 +874,7 @@ namespace Content.Server.GameTicking
|
|||||||
_netManager.ServerSendMessage(_netManager.CreateNetMessage<MsgTickerJoinLobby>(), session.ConnectedClient);
|
_netManager.ServerSendMessage(_netManager.CreateNetMessage<MsgTickerJoinLobby>(), session.ConnectedClient);
|
||||||
_netManager.ServerSendMessage(_getStatusMsg(session), session.ConnectedClient);
|
_netManager.ServerSendMessage(_getStatusMsg(session), session.ConnectedClient);
|
||||||
_netManager.ServerSendMessage(GetInfoMsg(), session.ConnectedClient);
|
_netManager.ServerSendMessage(GetInfoMsg(), session.ConnectedClient);
|
||||||
|
_netManager.ServerSendMessage(GetReadyStatus(), session.ConnectedClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void _playerJoinGame(IPlayerSession session)
|
private void _playerJoinGame(IPlayerSession session)
|
||||||
@@ -882,6 +886,26 @@ namespace Content.Server.GameTicking
|
|||||||
_netManager.ServerSendMessage(_netManager.CreateNetMessage<MsgTickerJoinGame>(), session.ConnectedClient);
|
_netManager.ServerSendMessage(_netManager.CreateNetMessage<MsgTickerJoinGame>(), session.ConnectedClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MsgTickerLobbyReady GetReadyStatus()
|
||||||
|
{
|
||||||
|
var msg = _netManager.CreateNetMessage<MsgTickerLobbyReady>();
|
||||||
|
msg.PlayerReady = new Dictionary<NetSessionId, bool>();
|
||||||
|
foreach (var player in _playersInLobby.Keys)
|
||||||
|
{
|
||||||
|
_playersInLobby.TryGetValue(player, out var ready);
|
||||||
|
msg.PlayerReady.Add(player.SessionId, ready);
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MsgTickerLobbyReady GetReadySingle(IPlayerSession player, bool ready)
|
||||||
|
{
|
||||||
|
var msg = _netManager.CreateNetMessage<MsgTickerLobbyReady>();
|
||||||
|
msg.PlayerReady = new Dictionary<NetSessionId, bool>();
|
||||||
|
msg.PlayerReady.Add(player.SessionId, ready);
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
private MsgTickerLobbyStatus _getStatusMsg(IPlayerSession session)
|
private MsgTickerLobbyStatus _getStatusMsg(IPlayerSession session)
|
||||||
{
|
{
|
||||||
_playersInLobby.TryGetValue(session, out var ready);
|
_playersInLobby.TryGetValue(session, out var ready);
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using Lidgren.Network;
|
using Lidgren.Network;
|
||||||
using Robust.Shared.Interfaces.Network;
|
using Robust.Shared.Interfaces.Network;
|
||||||
|
using Robust.Shared.Interfaces.Serialization;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
|
|
||||||
namespace Content.Shared
|
namespace Content.Shared
|
||||||
@@ -152,6 +155,57 @@ namespace Content.Shared
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected class MsgTickerLobbyReady : NetMessage
|
||||||
|
{
|
||||||
|
#region REQUIRED
|
||||||
|
|
||||||
|
public const MsgGroups GROUP = MsgGroups.Command;
|
||||||
|
public const string NAME = nameof(MsgTickerLobbyReady);
|
||||||
|
public MsgTickerLobbyReady(INetChannel channel) : base(NAME, GROUP) { }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Players Ready (SessionID:ready)
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<NetSessionId, bool> PlayerReady { get; set; }
|
||||||
|
|
||||||
|
public override void ReadFromBuffer(NetIncomingMessage buffer)
|
||||||
|
{
|
||||||
|
PlayerReady = new Dictionary<NetSessionId, bool>();
|
||||||
|
var length = buffer.ReadInt32();
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
var serializer = IoCManager.Resolve<IRobustSerializer>();
|
||||||
|
var byteLength = buffer.ReadVariableInt32();
|
||||||
|
NetSessionId sessionID;
|
||||||
|
using (var stream = buffer.ReadAsStream(byteLength))
|
||||||
|
{
|
||||||
|
serializer.DeserializeDirect(stream, out sessionID);
|
||||||
|
}
|
||||||
|
var ready = buffer.ReadBoolean();
|
||||||
|
PlayerReady.Add(sessionID, ready);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteToBuffer(NetOutgoingMessage buffer)
|
||||||
|
{
|
||||||
|
var serializer = IoCManager.Resolve<IRobustSerializer>();
|
||||||
|
buffer.Write(PlayerReady.Count);
|
||||||
|
foreach (var p in PlayerReady)
|
||||||
|
{
|
||||||
|
using (var stream = new MemoryStream())
|
||||||
|
{
|
||||||
|
serializer.SerializeDirect(stream, p.Key);
|
||||||
|
buffer.WriteVariableInt32((int) stream.Length);
|
||||||
|
stream.TryGetBuffer(out var segment);
|
||||||
|
buffer.Write(segment);
|
||||||
|
}
|
||||||
|
buffer.Write(p.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public struct RoundEndPlayerInfo
|
public struct RoundEndPlayerInfo
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user