浏览代码

Starting to shift responsibility off of lobby. Now, once a player is connected to Relay, the local player data will update from that instead of from the lobby. The data are still written to the lobby currently, however.

A couple renames for clarity are also included.
/main/staging
nathaniel.buck@unity3d.com 3 年前
当前提交
5fa60706
共有 5 个文件被更改,包括 97 次插入123 次删除
  1. 54
      Assets/Scripts/Entities/GameStateManager.cs
  2. 98
      Assets/Scripts/Entities/LocalLobby.cs
  3. 10
      Assets/Scripts/Lobby/LobbyContentHeartbeat.cs
  4. 54
      Assets/Scripts/Lobby/ToLocalLobby.cs
  5. 4
      Assets/Scripts/UI/JoinMenuUI.cs

54
Assets/Scripts/Entities/GameStateManager.cs


Debug.Log("Signed in.");
m_localUser.ID = Locator.Get.Identity.GetSubIdentity(Auth.IIdentityType.Auth).GetContent("id");
m_localUser.DisplayName = NameGenerator.GetName(m_localUser.ID);
m_localLobby.AddPlayer(m_localUser); // The local LobbyUser object will be hooked into UI before the LocalLobby is populated during lobby join, so the LocalLobby must know about it already when that happens.
}
public void OnReceiveMessage(MessageType type, object msg)

var createLobbyData = (LocalLobby)msg;
LobbyAsyncRequests.Instance.CreateLobbyAsync(createLobbyData.LobbyName, createLobbyData.MaxPlayerCount, createLobbyData.Private, m_localUser, (r) =>
{
lobby.ToLocalLobby.Convert(r, m_localLobby, m_localUser);
lobby.ToLocalLobby.Convert(r, m_localLobby);
LobbyInfo lobbyInfo = (LobbyInfo)msg;
LocalLobby.LobbyData lobbyInfo = (LocalLobby.LobbyData)msg;
lobby.ToLocalLobby.Convert(r, m_localLobby, m_localUser);
lobby.ToLocalLobby.Convert(r, m_localLobby);
OnJoinedLobby();
}, OnFailedJoin);
}

{
SetGameState((GameState)msg);
}
else if (type == MessageType.UserSetEmote)
else if (type == MessageType.UserSetEmote) // TODO: oh what are these doing here
{
EmoteType emote = (EmoteType)msg;
m_localUser.Emote = emote;

m_localUser.DisplayName = "New Player";
Locator.Get.Messenger.Subscribe(this);
DefaultObserverSetup();
InitObservers();
BeginObservers();
}
/// <summary>

Debug.LogWarning($"Scene has less than the default expected Lobby Service Observers, ensure all the observers in the scene that need to watch the lobby service state are registered in the LobbyServiceObservers List.");
}
void InitObservers()
void BeginObservers()
{
if (gameStateObs == null)
{
Debug.LogError("Missing a gameStateObserver, please make sure all GameStateObservers in the scene are registered here.");
continue;
}
}
foreach (var serviceObs in m_LobbyServiceObservers)
serviceObs.BeginObserving(m_lobbyServiceData);
{
if (lobbyObs == null)
{
Debug.LogError("Missing a gameStateObserver, please make sure all GameStateObservers in the scene are registered here.");
continue;
}
}
{
if (userObs == null)
{
Debug.LogError("Missing a gameStateObserver, please make sure all GameStateObservers in the scene are registered here.");
continue;
}
}
foreach (var serviceObs in m_LobbyServiceObservers)
{
if (serviceObs == null)
{
Debug.LogError("Missing a gameStateObserver, please make sure all GameStateObservers in the scene are registered here.");
continue;
}
serviceObs.BeginObserving(m_lobbyServiceData);
}
}
void SetGameState(GameState state)

void ResetLocalLobby()
{
m_localLobby.CopyObserved(new LobbyInfo(), new Dictionary<string, LobbyUser>());
m_localLobby.CopyObserved(new LocalLobby.LobbyData(), new Dictionary<string, LobbyUser>());
m_localLobby.CountDownTime = 0;
m_localLobby.RelayServer = null;
m_readyCheck.EndCheckingForReady();

98
Assets/Scripts/Entities/LocalLobby.cs


CountDown = 2,
InGame = 4
}
public struct LobbyInfo
{
public string LobbyID { get; set; }
public string LobbyCode { get; set; }
public string RelayCode { get; set; }
public string LobbyName { get; set; }
public bool Private { get; set; }
public int MaxPlayerCount { get; set; }
public LobbyState State { get; set; }
public long? AllPlayersReadyTime { get; set; }
public LobbyInfo(LobbyInfo existing)
{
LobbyID = existing.LobbyID;
LobbyCode = existing.LobbyCode;
RelayCode = existing.RelayCode;
LobbyName = existing.LobbyName;
Private = existing.Private;
MaxPlayerCount = existing.MaxPlayerCount;
State = existing.State;
AllPlayersReadyTime = existing.AllPlayersReadyTime;
}
public LobbyInfo(string lobbyCode)
{
LobbyID = null;
LobbyCode = lobbyCode;
RelayCode = null;
LobbyName = null;
Private = false;
MaxPlayerCount = -1;
State = LobbyState.Lobby;
AllPlayersReadyTime = null;
}
}
/// <summary>
/// A local wrapper around a lobby's remote data, with additional functionality for providing that data to UI elements and tracking local player objects.

public Dictionary<string, LobbyUser> LobbyUsers => m_LobbyUsers;
#region LocalLobbyData
private LobbyInfo m_data;
public LobbyInfo Data
public struct LobbyData
get { return new LobbyInfo(m_data); }
public string LobbyID { get; set; }
public string LobbyCode { get; set; }
public string RelayCode { get; set; }
public string LobbyName { get; set; }
public bool Private { get; set; }
public int MaxPlayerCount { get; set; }
public LobbyState State { get; set; }
public long? AllPlayersReadyTime { get; set; }
public LobbyData(LobbyData existing)
{
LobbyID = existing.LobbyID;
LobbyCode = existing.LobbyCode;
RelayCode = existing.RelayCode;
LobbyName = existing.LobbyName;
Private = existing.Private;
MaxPlayerCount = existing.MaxPlayerCount;
State = existing.State;
AllPlayersReadyTime = existing.AllPlayersReadyTime;
}
public LobbyData(string lobbyCode)
{
LobbyID = null;
LobbyCode = lobbyCode;
RelayCode = null;
LobbyName = null;
Private = false;
MaxPlayerCount = -1;
State = LobbyState.Lobby;
AllPlayersReadyTime = null;
}
}
private LobbyData m_data;
public LobbyData Data
{
get { return new LobbyData(m_data); }
}
float m_CountDownTime;

return statePlayers == playersCount;
}
public void CopyObserved(LobbyInfo info, Dictionary<string, LobbyUser> oldUsers)
public void CopyObserved(LobbyData data, Dictionary<string, LobbyUser> currUsers)
m_data = info;
if (oldUsers == null)
m_data = data;
if (currUsers == null)
foreach (var user in m_LobbyUsers)
foreach (var oldUser in m_LobbyUsers)
if (oldUsers.ContainsKey(user.Key))
user.Value.CopyObserved(oldUsers[user.Key]);
if (currUsers.ContainsKey(oldUser.Key))
oldUser.Value.CopyObserved(currUsers[oldUser.Key]);
toRemove.Add(user.Value);
toRemove.Add(oldUser.Value);
}
foreach (var remove in toRemove)

foreach (var oldUser in oldUsers)
foreach (var currUser in currUsers)
if (!m_LobbyUsers.ContainsKey(oldUser.Key))
DoAddPlayer(oldUser.Value);
if (!m_LobbyUsers.ContainsKey(currUser.Key))
DoAddPlayer(currUser.Value);
}
}

10
Assets/Scripts/Lobby/LobbyContentHeartbeat.cs


namespace LobbyRelaySample
{
// TODO: It might make sense to change UpdateSlow to, rather than have a fixed cycle on which everything is bound, be able to track when each thing should update?
// I.e. what I want here now is for when a lobby async request comes in, if it has already been long enough, it immediately fires and then sets a cooldown.
// This is still necessary for detecting new players, although I think we could hit a case where the relay join ends up coming in before the cooldown?
// So, we should be able to create a new LobbyUser that way as well.
// That is, creating a (local) player via Relay or via Lobby should go through the same mechanism...? Or do we hold onto the Relay data until the player exists?
/// <summary>
/// Keep updated on changes to a joined lobby.
/// </summary>

if (lobbyRemote == null) return;
bool prevShouldPush = m_shouldPushData;
var prevState = m_localLobby.State;
lobby.ToLocalLobby.Convert(lobbyRemote, m_localLobby, m_localUser);
lobby.ToLocalLobby.Convert(lobbyRemote, m_localLobby);
m_shouldPushData = prevShouldPush;
CheckForAllPlayersReady();

54
Assets/Scripts/Lobby/ToLocalLobby.cs


using System;
using System.Collections.Generic;
using System.Collections.Generic;
using Unity.Services.Lobbies.Models;
namespace LobbyRelaySample.lobby

/// <summary>
/// Create a new LocalLobby from the content of a retrieved lobby. Its data can be copied into an existing LocalLobby for use.
/// </summary>
public static void Convert(Lobby lobby, LocalLobby outputToHere, LobbyUser existingLocalUser = null)
public static void Convert(Lobby lobby, LocalLobby outputToHere)
LobbyInfo info = new LobbyInfo
LocalLobby.LobbyData info = new LocalLobby.LobbyData // Technically, this is largely redundant after the first assignment, but it won't do any harm to assign it again.
RelayCode = lobby.Data?.ContainsKey("RelayCode") == true ? lobby.Data["RelayCode"].Value : null,
State = lobby.Data?.ContainsKey("State") == true ? (LobbyState) int.Parse(lobby.Data["State"].Value) : LobbyState.Lobby,
AllPlayersReadyTime = lobby.Data?.ContainsKey("AllPlayersReady") == true ? long.Parse(lobby.Data["AllPlayersReady"].Value) : (long?)null
RelayCode = lobby.Data?.ContainsKey("RelayCode") == true ? lobby.Data["RelayCode"].Value : null, // TODO: Remove?
State = lobby.Data?.ContainsKey("State") == true ? (LobbyState) int.Parse(lobby.Data["State"].Value) : LobbyState.Lobby, // TODO: Consider TryParse, just in case (and below). Although, we don't have fail logic anyway...
AllPlayersReadyTime = lobby.Data?.ContainsKey("AllPlayersReady") == true ? long.Parse(lobby.Data["AllPlayersReady"].Value) : (long?)null // TODO: Remove
Dictionary<string, LobbyUser> lobbyUsers = new Dictionary<string, LobbyUser>();
Dictionary<string, LobbyUser> lobbyUsers = new Dictionary<string, LobbyUser>(); // TODO: So, right, why this?
if (existingLocalUser != null && player.Id.Equals(existingLocalUser.ID))
// If we already know about this player and this player is already connected to Relay, don't overwrite things that Relay might be changing.
if (player.Data?.ContainsKey("UserStatus") == true && int.TryParse(player.Data["UserStatus"].Value, out int status))
existingLocalUser.IsHost = lobby.HostId.Equals(player.Id);
existingLocalUser.DisplayName = player.Data?.ContainsKey("DisplayName") == true ? player.Data["DisplayName"].Value : existingLocalUser.DisplayName;
existingLocalUser.Emote = player.Data?.ContainsKey("Emote") == true ? (EmoteType) int.Parse(player.Data["Emote"].Value) : existingLocalUser.Emote;
lobbyUsers.Add(existingLocalUser.ID, existingLocalUser);
}
else
{
LobbyUser user = new LobbyUser(
displayName: player.Data?.ContainsKey("DisplayName") == true ? player.Data["DisplayName"].Value : "NewPlayer",
isHost: lobby.HostId.Equals(player.Id),
id: player.Id,
emote: player.Data?.ContainsKey("Emote") == true ? (EmoteType)int.Parse(player.Data["Emote"].Value) : EmoteType.None,
userStatus: player.Data?.ContainsKey("UserStatus") == true ? player.Data["UserStatus"].Value : UserStatus.Lobby.ToString()
);
lobbyUsers.Add(user.ID, user);
if (status > (int)UserStatus.Connecting && outputToHere.LobbyUsers.ContainsKey(player.Id))
{
lobbyUsers.Add(player.Id, outputToHere.LobbyUsers[player.Id]);
continue;
}
// If the player isn't connected to Relay, or if we just don't know about them yet, get the most recent data that the lobby knows. // TODO: Relay should handle the latter case.
// (If we have no local representation of the player, that gets added by the LocalLobby.)
LobbyUser incomingData = new LobbyUser(); // TODO: This is unclear; this should be just a data object replacing that of the user, not a new user whose data are taken.
incomingData.IsHost = lobby.HostId.Equals(player.Id);
incomingData.DisplayName = player.Data?.ContainsKey("DisplayName") == true ? player.Data["DisplayName"].Value : default;
incomingData.Emote = player.Data?.ContainsKey("Emote") == true ? (EmoteType)int.Parse(player.Data["Emote"].Value) : default;
incomingData.UserStatus = player.Data?.ContainsKey("UserStatus") == true ? (UserStatus)int.Parse(player.Data["UserStatus"].Value) : default;
incomingData.ID = player.Id;
lobbyUsers.Add(incomingData.ID, incomingData);
outputToHere.CopyObserved(info, lobbyUsers);
}

private static LocalLobby Convert(Lobby lobby)
{
LocalLobby data = new LocalLobby();
Convert(lobby, data, null);
Convert(lobby, data);
return data;
}

return data;
data.Add("DisplayName", user.DisplayName);
data.Add("Emote", ((int)user.Emote).ToString());
data.Add("UserStatus", user.UserStatus.ToString());
data.Add("UserStatus", ((int)user.UserStatus).ToString());
return data;
}
}

4
Assets/Scripts/UI/JoinMenuUI.cs


Dictionary<string, LocalLobby> m_LocalLobby = new Dictionary<string, LocalLobby>();
/// <summary>Contains some amount of information used to join an existing lobby.</summary>
LobbyInfo m_LocalLobbySelected;
LocalLobby.LobbyData m_LocalLobbySelected;
public void LobbyButtonSelected(LocalLobby lobby)
{

public void OnJoinCodeInputFieldChanged(string newCode)
{
if (!string.IsNullOrEmpty(newCode))
m_LocalLobbySelected = new LobbyInfo(newCode.ToUpper());
m_LocalLobbySelected = new LocalLobby.LobbyData(newCode.ToUpper());
}
public void OnJoinButtonPressed()

正在加载...
取消
保存