浏览代码

Renamed LobbyUser to LobbyPlayer

Renamed ObservedValue to CallbackValue
Started Converting LocalLobby to containing a Lobby
Started converting LobbyPlayer to containing a player
/main/staging/2021_Upgrade/Async_Refactor
当前提交
3afa3f3b
共有 24 个文件被更改,包括 254 次插入223 次删除
  1. 13
      Assets/Scripts/GameLobby/Game/GameManager.cs
  2. 4
      Assets/Scripts/GameLobby/Game/LobbyUserObserver.cs
  3. 37
      Assets/Scripts/GameLobby/Game/LocalLobby.cs
  4. 2
      Assets/Scripts/GameLobby/Game/LocalLobbyList.cs
  5. 6
      Assets/Scripts/GameLobby/Infrastructure/Actionvalue.cs
  6. 12
      Assets/Scripts/GameLobby/Lobby/LobbyConverters.cs
  7. 8
      Assets/Scripts/GameLobby/Lobby/LobbyManager.cs
  8. 4
      Assets/Scripts/GameLobby/Lobby/LobbySynchronizer.cs
  9. 2
      Assets/Scripts/GameLobby/NGO/InGameRunner.cs
  10. 4
      Assets/Scripts/GameLobby/NGO/SetupInGame.cs
  11. 10
      Assets/Scripts/GameLobby/Relay/RelayUtpClient.cs
  12. 2
      Assets/Scripts/GameLobby/Relay/RelayUtpHost.cs
  13. 4
      Assets/Scripts/GameLobby/Relay/RelayUtpSetup.cs
  14. 4
      Assets/Scripts/GameLobby/Tests/PlayMode/LobbyRoundtripTests.cs
  15. 8
      Assets/Scripts/GameLobby/UI/DisplayCodeUI.cs
  16. 10
      Assets/Scripts/GameLobby/UI/InLobbyUserUI.cs
  17. 2
      Assets/Scripts/GameLobby/UI/LobbyNameUI.cs
  18. 4
      Assets/Scripts/GameLobby/UI/SpinnerUI.cs
  19. 4
      Assets/Scripts/GameLobby/UI/UserNameUI.cs
  20. 6
      Assets/Scripts/GameLobby/UI/UserStateVisibilityUI.cs
  21. 2
      ProjectSettings/RiderScriptEditorPersistedState.asset
  22. 179
      Assets/Scripts/GameLobby/Game/LocalPlayer.cs
  23. 150
      Assets/Scripts/GameLobby/Game/LobbyUser.cs
  24. 0
      /Assets/Scripts/GameLobby/Game/LocalPlayer.cs.meta

13
Assets/Scripts/GameLobby/Game/GameManager.cs


#endregion
public LocalLobby LocalLobby => m_LocalLobby;
public LobbyUser LocalUser => m_LocalUser;
public LocalPlayer LocalUser => m_LocalUser;
LobbyUser m_LocalUser;
LocalPlayer m_LocalUser;
LocalLobby m_LocalLobby;
LobbySynchronizer m_LobbySynchronizer;

void InitializeLocalValues()
{
m_LocalLobby = new LocalLobby { LobbyState = LobbyState.Lobby };
m_LocalUser = new LobbyUser();
m_LocalUser = new LocalPlayer();
m_LocalLobby.AddPlayer(m_LocalUser); // The local LobbyUser object will be hooked into UI
m_LocalLobby.AddPlayer(m_LocalUser); // The local LocalPlayer object will be hooked into UI
/// <summary>
/// TODO Wire is a good update to remove the monolithic observers and move to observed values instead, on a Singleton gameManager
/// </summary>
void BeginObservers()
{
foreach (var lobbyObs in m_LocalLobbyObservers)

void ResetLocalLobby()
{
m_LocalLobby.CopyObserved(new LocalLobby.LobbyData(), new Dictionary<string, LobbyUser>());
m_LocalLobby.CopyObserved(new LocalLobby.LobbyData(), new Dictionary<string, LocalPlayer>());
m_LocalLobby
.AddPlayer(m_LocalUser); // As before, the local player will need to be plugged into UI before the lobby join actually happens.
m_LocalLobby.RelayServer = null;

4
Assets/Scripts/GameLobby/Game/LobbyUserObserver.cs


namespace LobbyRelaySample
{
/// <summary>
/// Holds a LobbyUser value and notifies all subscribers when it has been changed.
/// Holds a LocalPlayer value and notifies all subscribers when it has been changed.
public class LobbyUserObserver : ObserverBehaviour<LobbyUser> { }
public class LobbyUserObserver : ObserverBehaviour<LocalPlayer> { }
}

37
Assets/Scripts/GameLobby/Game/LocalLobby.cs


using System;
using System.Collections.Generic;
using System.Text;
using Unity.Services.Lobbies.Models;
using UnityEngine;
using UnityEngine.Serialization;

//This is because we could get more than just our changes when we receive the latest lobby from our calls.
public bool changedByLobbySynch;
public Action<LocalLobby> onLobbyChanged { get; set; }
public Action<Dictionary<string, LobbyUser>> onUserListChanged;
public Action<Dictionary<string, LocalPlayer>> onUserListChanged;
Dictionary<string, LobbyUser> m_LobbyUsers = new Dictionary<string, LobbyUser>();
public Dictionary<string, LobbyUser> LobbyUsers => m_LobbyUsers;
Dictionary<string, LocalPlayer> m_LobbyUsers = new Dictionary<string, LocalPlayer>();
public Dictionary<string, LocalPlayer> LobbyUsers => m_LobbyUsers;
public Lobby CloudLobby => m_CloudLobby;
Lobby m_CloudLobby;
#region LocalLobbyData
public struct LobbyData

public LocalLobby()
{
m_CloudLobby = new Lobby();
onChanged += (lobby) => { m_Data.LastEdit = DateTime.Now.ToFileTimeUtc(); };
}

public void AddPlayer(LobbyUser user)
public void AddPlayer(LocalPlayer user)
{
if (m_LobbyUsers.ContainsKey(user.ID))
{

onUserListChanged?.Invoke(m_LobbyUsers);
}
void AddUser(LobbyUser user)
void AddUser(LocalPlayer user)
m_CloudLobby.Players.Add(new Player());
public void RemovePlayer(LobbyUser user)
public void RemovePlayer(LocalPlayer user)
private void DoRemoveUser(LobbyUser user)
private void DoRemoveUser(LocalPlayer user)
{
if (!m_LobbyUsers.ContainsKey(user.ID))
{

m_LobbyUsers.Remove(user.ID);
}
public ObservedValue<string> LobbyID = new ObservedValue<string>();
public CallbackValue<string> LobbyID = new CallbackValue<string>();
public ObservedValue<string> LobbyCode = new ObservedValue<string>();
public CallbackValue<string> LobbyCode = new CallbackValue<string>();
public ObservedValue<string> RelayCode = new ObservedValue<string>();
public CallbackValue<string> RelayCode = new CallbackValue<string>();
public ObservedValue<string> RelayNGOCode = new ObservedValue<string>();
public CallbackValue<string> RelayNGOCode = new CallbackValue<string>();
public ObservedValue<ServerAddress> RelayServer = new ObservedValue<ServerAddress>();
public CallbackValue<ServerAddress> RelayServer = new CallbackValue<ServerAddress>();
public ObservedValue<string> LobbyName = new ObservedValue<string>();
public CallbackValue<string> LobbyName = new CallbackValue<string>();
public LobbyState LobbyState
{

onLobbyChanged?.Invoke(this);
}
public void CopyObserved(LobbyData lobbyData, Dictionary<string, LobbyUser> lobbyUsers)
public void CopyObserved(LobbyData lobbyData, Dictionary<string, LocalPlayer> lobbyUsers)
{
// It's possible for the host to edit the lobby in between the time they last pushed lobby data and the time their pull for new lobby data completes.
// If that happens, the edit will be lost, so instead we maintain the time of last edit to detect that case.

m_Data.RelayNGOCode = lobbyData.RelayNGOCode;
if (lobbyUsers == null)
m_LobbyUsers = new Dictionary<string, LobbyUser>();
m_LobbyUsers = new Dictionary<string, LocalPlayer>();
List<LobbyUser> toRemove = new List<LobbyUser>();
List<LocalPlayer> toRemove = new List<LocalPlayer>();
foreach (var oldUser in m_LobbyUsers)
{
if (lobbyUsers.ContainsKey(oldUser.Key))

2
Assets/Scripts/GameLobby/Game/LocalLobbyList.cs


{
LobbyQueryState m_CurrentState = LobbyQueryState.Empty;
public ObservedValue<LobbyQueryState> QueryState = new ObservedValue<LobbyQueryState>();
public CallbackValue<LobbyQueryState> QueryState = new CallbackValue<LobbyQueryState>();
public Action<Dictionary<string, LocalLobby>> onLobbyListChange;
Dictionary<string, LocalLobby> m_currentLobbies = new Dictionary<string, LocalLobby>();

6
Assets/Scripts/GameLobby/Infrastructure/Actionvalue.cs


namespace LobbyRelaySample
{
public class ObservedValue<T>
public class CallbackValue<T>
public Action<T> onValueChanged;
public Action<T> onChanged;
public T Value
{

if (m_CachedValue.Equals(value))
return;
m_CachedValue = value;
onValueChanged?.Invoke(m_CachedValue);
onChanged?.Invoke(m_CachedValue);
}
}

12
Assets/Scripts/GameLobby/Lobby/LobbyConverters.cs


const string key_LobbyColor = nameof(LocalLobby.LobbyData.LobbyColor);
const string key_LastEdit = nameof(LocalLobby.LobbyData.LastEdit);
const string key_Displayname = nameof(LobbyUser.DisplayName);
const string key_Userstatus = nameof(LobbyUser.UserStatus);
const string key_Emote = nameof(LobbyUser.Emote);
const string key_Displayname = nameof(LocalPlayer.DisplayName);
const string key_Userstatus = nameof(LocalPlayer.UserStatus);
const string key_Emote = nameof(LocalPlayer.Emote);
public static Dictionary<string, string> LocalToRemoteData(LocalLobby lobby)

return data;
}
public static Dictionary<string, string> LocalToRemoteUserData(LobbyUser user)
public static Dictionary<string, string> LocalToRemoteUserData(LocalPlayer user)
{
Dictionary<string, string> data = new Dictionary<string, string>();
if (user == null || string.IsNullOrEmpty(user.ID))

LobbyColor = remoteLobby.Data?.ContainsKey(key_LobbyColor) == true ? (LobbyColor)int.Parse(remoteLobby.Data[key_LobbyColor].Value) : LobbyColor.None,
};
Dictionary<string, LobbyUser> lobbyUsers = new Dictionary<string, LobbyUser>();
Dictionary<string, LocalPlayer> lobbyUsers = new Dictionary<string, LocalPlayer>();
LobbyUser incomingData = new LobbyUser
LocalPlayer incomingData = new LocalPlayer
{
IsHost = remoteLobby.HostId.Equals(player.Id),
DisplayName = player.Data?.ContainsKey(key_Displayname) == true ? player.Data[key_Displayname].Value : default,

8
Assets/Scripts/GameLobby/Lobby/LobbyManager.cs


#endregion
Dictionary<string, PlayerDataObject> CreateInitialPlayerData(LobbyUser user)
Dictionary<string, PlayerDataObject> CreateInitialPlayerData(LocalPlayer user)
{
Dictionary<string, PlayerDataObject> data = new Dictionary<string, PlayerDataObject>();

}
public async Task<Lobby> CreateLobbyAsync(string lobbyName, int maxPlayers, bool isPrivate, LobbyUser localUser)
public async Task<Lobby> CreateLobbyAsync(string lobbyName, int maxPlayers, bool isPrivate, LocalPlayer localUser)
{
if (m_CreateCooldown.IsInCooldown)
{

}
}
public async Task<Lobby> JoinLobbyAsync(string lobbyId, string lobbyCode, LobbyUser localUser)
public async Task<Lobby> JoinLobbyAsync(string lobbyId, string lobbyCode, LocalPlayer localUser)
{
if (m_JoinCooldown.IsInCooldown ||
(lobbyId == null && lobbyCode == null))

return m_CurrentLobby;
}
public async Task<Lobby> QuickJoinLobbyAsync(LobbyUser localUser, LobbyColor limitToColor = LobbyColor.None)
public async Task<Lobby> QuickJoinLobbyAsync(LocalPlayer localUser, LobbyColor limitToColor = LobbyColor.None)
{
//We dont want to queue a quickjoin
if (m_QuickJoinCooldown.IsInCooldown)

4
Assets/Scripts/GameLobby/Lobby/LobbySynchronizer.cs


public class LobbySynchronizer : IReceiveMessages, IDisposable
{
LocalLobby m_LocalLobby;
LobbyUser m_LocalUser;
LocalPlayer m_LocalUser;
LobbyManager m_LobbyManager;
bool m_LocalChanges = false;

m_LobbyManager = lobbyManager;
}
public void StartSynch(LocalLobby localLobby, LobbyUser localUser)
public void StartSynch(LocalLobby localLobby, LocalPlayer localUser)
{
m_LocalUser = localUser;
m_LocalLobby = localLobby;

2
Assets/Scripts/GameLobby/NGO/InGameRunner.cs


private Transform m_symbolContainerInstance;
private PlayerData m_localUserData; // This has an ID that's not necessarily the OwnerClientId, since all clients will see all spawned objects regardless of ownership.
public void Initialize(Action onConnectionVerified, int expectedPlayerCount, Action onGameEnd, LobbyUser localUser)
public void Initialize(Action onConnectionVerified, int expectedPlayerCount, Action onGameEnd, LocalPlayer localUser)
{
m_onConnectionVerified = onConnectionVerified;
m_expectedPlayerCount = expectedPlayerCount;

4
Assets/Scripts/GameLobby/NGO/SetupInGame.cs


private bool m_hasConnectedViaNGO = false;
private LocalLobby m_lobby;
private LobbyUser m_localUser;
private LocalPlayer m_localUser;
public void Start()

public void OnLobbyChange(LocalLobby lobby)
{ m_lobby = lobby; // Most of the time this is redundant, but we need to get multiple members of the lobby to the Relay setup components, so might as well just hold onto the whole thing.
}
public void OnLocalUserChange(LobbyUser user)
public void OnLocalUserChange(LocalPlayer user)
{ m_localUser = user; // Same, regarding redundancy.
}

10
Assets/Scripts/GameLobby/Relay/RelayUtpClient.cs


/// </summary>
public class RelayUtpClient : MonoBehaviour, IDisposable // This is a MonoBehaviour merely to have access to Update.
{
protected LobbyUser m_localUser;
protected LocalPlayer m_localUser;
protected LocalLobby m_localLobby;
protected NetworkDriver m_networkDriver;
protected List<NetworkConnection> m_connections; // For clients, this has just one member, but for hosts it will have more.

protected enum MsgType { Ping = 0, NewPlayer, PlayerApprovalState, ReadyState, PlayerName, Emote, StartCountdown, CancelCountdown, ConfirmInGame, EndInGame, PlayerDisconnect }
public virtual void Initialize(NetworkDriver networkDriver, List<NetworkConnection> connections, LobbyUser localUser, LocalLobby localLobby)
public virtual void Initialize(NetworkDriver networkDriver, List<NetworkConnection> connections, LocalPlayer localUser, LocalLobby localLobby)
{
m_localUser = localUser;
m_localLobby = localLobby;

Dispose();
}
private void OnLocalChange(LobbyUser localUser)
private void OnLocalChange(LocalPlayer localUser)
{
if (m_connections.Count == 0) // This could be the case for the host alone in the lobby.
return;

/// <summary>
/// When player data is updated, send out events for just the data that actually changed.
/// </summary>
private void DoUserUpdate(NetworkDriver driver, NetworkConnection connection, LobbyUser user)
private void DoUserUpdate(NetworkDriver driver, NetworkConnection connection, LocalPlayer user)
{
}

protected void ForceFullUserUpdate(NetworkDriver driver, NetworkConnection connection, LobbyUser user)
protected void ForceFullUserUpdate(NetworkDriver driver, NetworkConnection connection, LocalPlayer user)
{
// Note that it would be better to send a single message with the full state, but for the sake of shorter code we'll leave that out here.
WriteString(driver, connection, user.ID, MsgType.PlayerName, user.DisplayName);

2
Assets/Scripts/GameLobby/Relay/RelayUtpHost.cs


/// </summary>
public class RelayUtpHost : RelayUtpClient, IReceiveMessages
{
public override void Initialize(NetworkDriver networkDriver, List<NetworkConnection> connections, LobbyUser localUser, LocalLobby localLobby)
public override void Initialize(NetworkDriver networkDriver, List<NetworkConnection> connections, LocalPlayer localUser, LocalLobby localLobby)
{
base.Initialize(networkDriver, connections, localUser, localLobby);
m_hasSentInitialMessage = true; // The host will be alone in the lobby at first, so they need not send any messages right away.

4
Assets/Scripts/GameLobby/Relay/RelayUtpSetup.cs


protected List<NetworkConnection> m_connections;
protected NetworkEndPoint m_endpointForServer;
protected LocalLobby m_localLobby;
protected LobbyUser m_localUser;
protected LocalPlayer m_localUser;
protected Action<bool, RelayUtpClient> m_onJoinComplete;
public static string AddressFromEndpoint(NetworkEndPoint endpoint)

public void BeginRelayJoin(
LocalLobby localLobby,
LobbyUser localUser,
LocalPlayer localUser,
Action<bool, RelayUtpClient> onJoinComplete)
{
m_localLobby = localLobby;

4
Assets/Scripts/GameLobby/Tests/PlayMode/LobbyRoundtripTests.cs


Dictionary<string, PlayerDataObject>
m_mockUserData; // This is handled in the LobbyAsyncRequest calls normally, but we need to supply this for the direct Lobby API calls.
LobbyUser m_LocalUser;
LocalPlayer m_LocalUser;
LobbyManager m_LobbyManager;
[OneTimeSetUp]

m_mockUserData.Add("DisplayName",
new PlayerDataObject(PlayerDataObject.VisibilityOptions.Member, "TestUser123"));
m_LocalUser = new LobbyUser(true);
m_LocalUser = new LocalPlayer(true);
m_LobbyManager = new LobbyManager();
#pragma warning disable 4014

8
Assets/Scripts/GameLobby/UI/DisplayCodeUI.cs


{
base.Start();
if(m_codeType==CodeType.Lobby)
Manager.LocalLobby.LobbyCode.onValueChanged += LobbyCodeChanged;
Manager.LocalLobby.LobbyCode.onChanged += LobbyCodeChanged;
Manager.LocalLobby.RelayCode.onValueChanged += LobbyCodeChanged;
Manager.LocalLobby.RelayCode.onChanged += LobbyCodeChanged;
}
void OnDestroy()

if(m_codeType==CodeType.Lobby)
Manager.LocalLobby.LobbyCode.onValueChanged -= LobbyCodeChanged;
Manager.LocalLobby.LobbyCode.onChanged -= LobbyCodeChanged;
Manager.LocalLobby.RelayCode.onValueChanged -= LobbyCodeChanged;
Manager.LocalLobby.RelayCode.onChanged -= LobbyCodeChanged;
}
}
}

10
Assets/Scripts/GameLobby/UI/InLobbyUserUI.cs


/// When inside a lobby, this will show information about a player, whether local or remote.
/// </summary>
[RequireComponent(typeof(LobbyUserObserver))]
public class InLobbyUserUI : ObserverPanel<LobbyUser>
public class InLobbyUserUI : ObserverPanel<LocalPlayer>
{
[SerializeField]
TMP_Text m_DisplayNameText;

public string UserId { get; set; }
LobbyUserObserver m_observer;
public void SetUser(LobbyUser myLobbyUser)
public void SetUser(LocalPlayer myLocalPlayer)
m_observer.BeginObserving(myLobbyUser);
UserId = myLobbyUser.ID;
m_observer.BeginObserving(myLocalPlayer);
UserId = myLocalPlayer.ID;
m_vivoxUserHandler.SetId(UserId);
}

m_observer.EndObserving();
}
public override void ObservedUpdated(LobbyUser observed)
public override void ObservedUpdated(LocalPlayer observed)
{
m_DisplayNameText.SetText(observed.DisplayName);
m_StatusText.SetText(SetStatusFancy(observed.UserStatus));

2
Assets/Scripts/GameLobby/UI/LobbyNameUI.cs


public void Start()
{
base.Start();
Manager.LocalLobby.LobbyName.onValueChanged += (s) => { m_lobbyNameText.SetText(s); };
Manager.LocalLobby.LobbyName.onChanged += (s) => { m_lobbyNameText.SetText(s); };
}
}
}

4
Assets/Scripts/GameLobby/UI/SpinnerUI.cs


public override void Start()
{
base.Start();
Manager.LobbyList.QueryState.onValueChanged += QueryStateChanged;
Manager.LobbyList.QueryState.onChanged += QueryStateChanged;
}
void OnDestroy()

Manager.LobbyList.QueryState.onValueChanged -= QueryStateChanged;
Manager.LobbyList.QueryState.onChanged -= QueryStateChanged;
}

4
Assets/Scripts/GameLobby/UI/UserNameUI.cs


/// <summary>
/// Displays the player's name.
/// </summary>
public class UserNameUI : ObserverPanel<LobbyUser>
public class UserNameUI : ObserverPanel<LocalPlayer>
public override void ObservedUpdated(LobbyUser observed)
public override void ObservedUpdated(LocalPlayer observed)
{
m_TextField.SetText(observed.DisplayName);
}

6
Assets/Scripts/GameLobby/UI/UserStateVisibilityUI.cs


}
/// <summary>
/// Shows the UI when the LobbyUser matches some conditions, including having the target permissions.
/// Shows the UI when the LocalPlayer matches some conditions, including having the target permissions.
public class UserStateVisibilityUI : ObserverPanel<LobbyUser>
public class UserStateVisibilityUI : ObserverPanel<LocalPlayer>
public override void ObservedUpdated(LobbyUser observed)
public override void ObservedUpdated(LocalPlayer observed)
{
var hasStatusFlags = ShowThisWhen.HasFlag(observed.UserStatus);

2
ProjectSettings/RiderScriptEditorPersistedState.asset


m_Script: {fileID: 0}
m_Name:
m_EditorClassIdentifier: Unity.Rider.Editor:Packages.Rider.Editor:RiderScriptEditorPersistedState
lastWriteTicks: -8585463664984316469
lastWriteTicks: -8585462928069479823

179
Assets/Scripts/GameLobby/Game/LocalPlayer.cs


using System;
using Unity.Services.Lobbies.Models;
using UnityEngine;
namespace LobbyRelaySample
{
/// <summary>
/// Current state of the user in the lobby.
/// This is a Flags enum to allow for the Inspector to select multiples for various UI features.
/// </summary>
[Flags]
public enum UserStatus
{
None = 0,
Connecting = 1, // User has joined a lobby but has not yet connected to Relay.
Lobby = 2, // User is in a lobby and connected to Relay.
Ready = 4, // User has selected the ready button, to ready for the "game" to start.
InGame = 8, // User is part of a "game" that has started.
Menu = 16 // User is not in a lobby, in one of the main menus.
}
/// <summary>
/// Data for a local player instance. This will update data and is observed to know when to push local player changes to the entire lobby.
/// </summary>
[Serializable]
public class LocalPlayer : Observed<LocalPlayer>
{
public LocalPlayer(bool isHost = false, string displayName = null, string id = null,
EmoteType emote = EmoteType.None, UserStatus userStatus = UserStatus.Menu, bool isApproved = false)
{
m_data = new UserData(isHost, displayName, id, emote, userStatus, isApproved);
}
const string key_Displayname = nameof(DisplayName);
const string key_Userstatus = nameof(UserStatus);
const string key_Emote = nameof(Emote);
#region Local UserData
public Player CloudPlayer { get; private set; }
public struct UserData
{
public bool IsHost { get; set; }
public string DisplayName { get; set; }
public string ID { get; set; }
public EmoteType Emote { get; set; }
public UserStatus UserStatus { get; set; }
public bool IsApproved { get; set; }
public UserData(bool isHost, string displayName, string id, EmoteType emote, UserStatus userStatus,
bool isApproved)
{
IsHost = isHost;
DisplayName = displayName;
ID = id;
Emote = emote;
UserStatus = userStatus;
IsApproved = isApproved;
}
}
UserData m_data;
public LocalPlayer()
{
CloudPlayer = new Player();
DeesplayName.onChanged += SynchDisplayName;
}
public void ResetState()
{
m_data = new UserData(false, m_data.DisplayName, m_data.ID, EmoteType.None, UserStatus.Menu,
false); // ID and DisplayName should persist since this might be the local user.
}
#endregion
/// <summary>
/// Used for limiting costly OnChanged actions to just the members which actually changed.
/// </summary>
[Flags]
public enum UserMembers
{
IsHost = 1,
DisplayName = 2,
Emote = 4,
ID = 8,
UserStatus = 16,
}
public bool IsHost
{
get { return m_data.IsHost; }
set
{
if (m_data.IsHost == value)
return;
m_data.IsHost = value;
OnChanged(this);
}
}
public CallbackValue<string> DeesplayName = new CallbackValue<string>();
void SynchDisplayName(string name)
{
PlayerDataObject playerDataObject;
if (CloudPlayer.Data.TryGetValue(key_Displayname, out playerDataObject))
{
playerDataObject.Value = name;
}
else
{
CloudPlayer.Data.Add(key_Displayname,
new PlayerDataObject(PlayerDataObject.VisibilityOptions.Member, name));
}
}
//TODO Finish this, for now i'm going to the LocalLobby
public string DisplayName
{
get => CloudPlayer.Data[key_Displayname].Value;
set
{
if (m_data.DisplayName == value)
return;
m_data.DisplayName = value;
OnChanged(this);
}
}
public EmoteType Emote
{
get => m_data.Emote;
set
{
if (m_data.Emote == value)
return;
m_data.Emote = value;
OnChanged(this);
}
}
public string ID
{
get => m_data.ID;
set
{
if (m_data.ID == value)
return;
m_data.ID = value;
OnChanged(this);
}
}
UserStatus m_userStatus = UserStatus.Menu;
public UserStatus UserStatus
{
get => m_userStatus;
set
{
if (m_userStatus == value)
return;
m_userStatus = value;
OnChanged(this);
}
}
public override void CopyObserved(LocalPlayer observed)
{
m_data = observed.m_data;
;
OnChanged(this);
}
}
}

150
Assets/Scripts/GameLobby/Game/LobbyUser.cs


using System;
using UnityEngine;
namespace LobbyRelaySample
{
/// <summary>
/// Current state of the user in the lobby.
/// This is a Flags enum to allow for the Inspector to select multiples for various UI features.
/// </summary>
[Flags]
public enum UserStatus
{
None = 0,
Connecting = 1, // User has joined a lobby but has not yet connected to Relay.
Lobby = 2, // User is in a lobby and connected to Relay.
Ready = 4, // User has selected the ready button, to ready for the "game" to start.
InGame = 8, // User is part of a "game" that has started.
Menu = 16 // User is not in a lobby, in one of the main menus.
}
/// <summary>
/// Data for a local player instance. This will update data and is observed to know when to push local player changes to the entire lobby.
/// </summary>
[Serializable]
public class LobbyUser : Observed<LobbyUser>
{
public LobbyUser(bool isHost = false, string displayName = null, string id = null,
EmoteType emote = EmoteType.None, UserStatus userStatus = UserStatus.Menu, bool isApproved = false)
{
m_data = new UserData(isHost, displayName, id, emote, userStatus, isApproved);
}
#region Local UserData
public struct UserData
{
public bool IsHost { get; set; }
public string DisplayName { get; set; }
public string ID { get; set; }
public EmoteType Emote { get; set; }
public UserStatus UserStatus { get; set; }
public bool IsApproved { get; set; }
public UserData(bool isHost, string displayName, string id, EmoteType emote, UserStatus userStatus,
bool isApproved)
{
IsHost = isHost;
DisplayName = displayName;
ID = id;
Emote = emote;
UserStatus = userStatus;
IsApproved = isApproved;
}
}
UserData m_data;
public void ResetState()
{
m_data = new UserData(false, m_data.DisplayName, m_data.ID, EmoteType.None, UserStatus.Menu,
false); // ID and DisplayName should persist since this might be the local user.
}
#endregion
/// <summary>
/// Used for limiting costly OnChanged actions to just the members which actually changed.
/// </summary>
[Flags]
public enum UserMembers
{
IsHost = 1,
DisplayName = 2,
Emote = 4,
ID = 8,
UserStatus = 16,
}
public bool IsHost
{
get { return m_data.IsHost; }
set
{
if (m_data.IsHost == value)
return;
m_data.IsHost = value;
OnChanged(this);
}
}
public string DisplayName
{
get => m_data.DisplayName;
set
{
if (m_data.DisplayName == value)
return;
m_data.DisplayName = value;
OnChanged(this);
}
}
public EmoteType Emote
{
get => m_data.Emote;
set
{
if (m_data.Emote == value)
return;
m_data.Emote = value;
OnChanged(this);
}
}
public string ID
{
get => m_data.ID;
set
{
if (m_data.ID == value)
return;
m_data.ID = value;
OnChanged(this);
}
}
UserStatus m_userStatus = UserStatus.Menu;
public UserStatus UserStatus
{
get => m_userStatus;
set
{
if (m_userStatus == value)
return;
m_userStatus = value;
OnChanged(this);
}
}
public override void CopyObserved(LobbyUser observed)
{
m_data = observed.m_data;
;
OnChanged(this);
}
}
}

/Assets/Scripts/GameLobby/Game/LobbyUser.cs.meta → /Assets/Scripts/GameLobby/Game/LocalPlayer.cs.meta

正在加载...
取消
保存