当前提交
28ad491f
共有 28 个文件被更改,包括 1049 次插入 和 2084 次删除
-
940Assets/Art/Font/CheckboxFLF SDF.asset
-
2Assets/Art/Icons/CursorIcon.png.meta
-
66Assets/Prefabs/UI/LobbyCanvas.prefab
-
72Assets/Scenes/mainScene.unity
-
2Assets/Scripts/GameLobby.meta
-
75Assets/Scripts/GameLobby/Game/GameManager.cs
-
132Assets/Scripts/GameLobby/Game/LocalLobby.cs
-
2Assets/Scripts/GameLobby/Infrastructure/Messenger.cs
-
31Assets/Scripts/GameLobby/Lobby/LobbyAPIInterface.cs
-
144Assets/Scripts/GameLobby/Lobby/LobbyAsyncRequests.cs
-
2Assets/Scripts/GameLobby/Relay/RelayAPIInterface.cs
-
32Assets/Scripts/GameLobby/Vivox/VivoxUserHandler.cs
-
25Packages/manifest.json
-
66Packages/packages-lock.json
-
2ProjectSettings/GraphicsSettings.asset
-
34ProjectSettings/PackageManagerSettings.asset
-
18ProjectSettings/Packages/com.unity.services.vivox/Settings.json
-
13ProjectSettings/ProjectSettings.asset
-
4ProjectSettings/UnityConnectSettings.asset
-
999~Documentation/Images/2_lobby.PNG
-
138Assets/Scripts/GameLobby/Lobby/LobbyContentUpdater.cs
-
105Assets/Scripts/GameLobby/Lobby/LobbyConverters.cs
-
76Assets/Scripts/GameLobby/Lobby/ToLocalLobby.cs
-
153Assets/Scripts/GameLobby/Lobby/LobbyContentHeartbeat.cs
-
0/Assets/Prefabs/UI/LobbyCanvas.prefab.meta
-
0/Assets/Prefabs/UI/LobbyCanvas.prefab
-
0/Assets/Scripts/GameLobby/Lobby/LobbyContentUpdater.cs.meta
-
0/Assets/Scripts/GameLobby/Lobby/LobbyConverters.cs.meta
940
Assets/Art/Font/CheckboxFLF SDF.asset
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
999
~Documentation/Images/2_lobby.PNG
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
|
|||
using System; |
|||
using LobbyRelaySample.lobby; |
|||
using Unity.Services.Lobbies.Models; |
|||
using UnityEngine; |
|||
|
|||
namespace LobbyRelaySample |
|||
{ |
|||
/// <summary>
|
|||
/// Keep updated on changes to a joined lobby, at a speed compliant with Lobby's rate limiting.
|
|||
/// </summary>
|
|||
public class LobbyContentUpdater : IReceiveMessages |
|||
{ |
|||
private LocalLobby m_LocalLobby; |
|||
private LobbyUser m_LocalUser; |
|||
private bool m_ShouldPushData = false; |
|||
|
|||
private const float k_approvalMaxTime = 10; // Used for determining if a user should timeout if they are unable to connect.
|
|||
private float m_lifetime = 0; |
|||
|
|||
public void BeginTracking(LocalLobby localLobby, LobbyUser localUser) |
|||
{ |
|||
m_LocalUser = localUser; |
|||
m_LocalLobby = localLobby; |
|||
m_LocalLobby.onChanged += OnLocalLobbyChanged; |
|||
m_ShouldPushData = true; |
|||
Locator.Get.Messenger.Subscribe(this); |
|||
Locator.Get.UpdateSlow.Subscribe(OnUpdate, 1.5f); |
|||
m_lifetime = 0; |
|||
LobbyAsyncRequests.Instance.onLobbyUpdated += OnRemoteLobbyUpdated; |
|||
} |
|||
|
|||
public void EndTracking() |
|||
{ |
|||
m_ShouldPushData = false; |
|||
|
|||
Locator.Get.Messenger.Unsubscribe(this); |
|||
Locator.Get.UpdateSlow.Unsubscribe(OnUpdate); |
|||
if (m_LocalLobby != null) |
|||
m_LocalLobby.onChanged -= OnLocalLobbyChanged; |
|||
LobbyAsyncRequests.Instance.onLobbyUpdated -= OnRemoteLobbyUpdated; |
|||
|
|||
m_LocalLobby = null; |
|||
} |
|||
|
|||
public void OnReceiveMessage(MessageType type, object msg) |
|||
{ |
|||
if (type == MessageType.ClientUserSeekingDisapproval) |
|||
{ |
|||
bool shouldDisapprove = m_LocalLobby.State != LobbyState.Lobby; // By not refreshing, it's possible to have a lobby in the lobby list UI after its countdown starts and then try joining.
|
|||
if (shouldDisapprove) |
|||
(msg as Action<relay.Approval>)?.Invoke(relay.Approval.GameAlreadyStarted); |
|||
} |
|||
} |
|||
|
|||
void OnLocalLobbyChanged(LocalLobby changed) |
|||
{ |
|||
if (string.IsNullOrEmpty(changed.LobbyID)) // When the player leaves, their LocalLobby is cleared out but maintained.
|
|||
{ |
|||
EndTracking(); |
|||
return; |
|||
} |
|||
|
|||
if (changed.pullUpdate) |
|||
{ |
|||
changed.pullUpdate = false; |
|||
return; |
|||
} |
|||
|
|||
m_ShouldPushData = true; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// If there have been any data changes since the last update, push them to Lobby. Regardless, pull for the most recent data.
|
|||
/// (Unless we're already awaiting a query, in which case continue waiting.)
|
|||
/// </summary>
|
|||
private void OnUpdate(float dt) |
|||
{ |
|||
m_lifetime += dt; |
|||
if (m_LocalLobby == null) |
|||
return; |
|||
if (m_LocalUser.IsHost) |
|||
LobbyAsyncRequests.Instance.DoLobbyHeartbeat(dt); |
|||
|
|||
if (!m_LocalUser.IsApproved && m_lifetime > k_approvalMaxTime) |
|||
{ |
|||
Locator.Get.Messenger.OnReceiveMessage(MessageType.DisplayErrorPopup, "Connection attempt timed out!"); |
|||
Locator.Get.Messenger.OnReceiveMessage(MessageType.ChangeMenuState, GameState.JoinMenu); |
|||
} |
|||
|
|||
if (m_ShouldPushData) |
|||
PushDataToLobby(); |
|||
|
|||
void PushDataToLobby() |
|||
{ |
|||
m_ShouldPushData = false; |
|||
|
|||
if (m_LocalUser.IsHost) |
|||
{ |
|||
DoLobbyDataPush(); |
|||
} |
|||
|
|||
DoPlayerDataPush(); |
|||
} |
|||
|
|||
void DoLobbyDataPush() |
|||
{ |
|||
LobbyAsyncRequests.Instance.UpdateLobbyDataAsync(LobbyConverters.LocalToRemoteData(m_LocalLobby), null); |
|||
} |
|||
|
|||
void DoPlayerDataPush() |
|||
{ |
|||
LobbyAsyncRequests.Instance.UpdatePlayerDataAsync(LobbyConverters.LocalToRemoteUserData(m_LocalUser), null); |
|||
} |
|||
} |
|||
|
|||
void OnRemoteLobbyUpdated(Lobby lobby) |
|||
{ |
|||
m_LocalLobby.pullUpdate = true; |
|||
|
|||
//synching our local lobby
|
|||
LobbyConverters.RemoteToLocal(lobby, m_LocalLobby); |
|||
|
|||
//Dont push data this tick, since we "pulled"s
|
|||
if (!m_LocalUser.IsHost) |
|||
{ |
|||
foreach (var lobbyUser in m_LocalLobby.LobbyUsers) |
|||
{ |
|||
if (lobbyUser.Value.IsHost) |
|||
return; |
|||
} |
|||
|
|||
Locator.Get.Messenger.OnReceiveMessage(MessageType.DisplayErrorPopup, "Host left the lobby! Disconnecting..."); |
|||
Locator.Get.Messenger.OnReceiveMessage(MessageType.EndGame, null); |
|||
Locator.Get.Messenger.OnReceiveMessage(MessageType.ChangeMenuState, GameState.JoinMenu); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
using System.Collections.Generic; |
|||
using Unity.Services.Lobbies.Models; |
|||
using UnityEngine; |
|||
|
|||
namespace LobbyRelaySample.lobby |
|||
{ |
|||
/// <summary>
|
|||
/// QueryToLocalList the lobby resulting from a request into a LocalLobby for use in the game logic.
|
|||
/// </summary>
|
|||
public static class LobbyConverters |
|||
{ |
|||
public static Dictionary<string, string> LocalToRemoteData(LocalLobby lobby) |
|||
{ |
|||
Dictionary<string, string> data = new Dictionary<string, string>(); |
|||
data.Add("RelayCode", lobby.RelayCode); |
|||
data.Add("RelayNGOCode", lobby.RelayNGOCode); |
|||
data.Add("State", ((int)lobby.State).ToString()); // Using an int is smaller than using the enum state's name.
|
|||
data.Add("Color", ((int)lobby.Color).ToString()); |
|||
data.Add("State_LastEdit", lobby.Data.State_LastEdit.ToString()); |
|||
data.Add("Color_LastEdit", lobby.Data.Color_LastEdit.ToString()); |
|||
data.Add("RelayNGOCode_LastEdit", lobby.Data.RelayNGOCode_LastEdit.ToString()); |
|||
return data; |
|||
} |
|||
|
|||
public static Dictionary<string, string> LocalToRemoteUserData(LobbyUser user) |
|||
{ |
|||
Dictionary<string, string> data = new Dictionary<string, string>(); |
|||
if (user == null || string.IsNullOrEmpty(user.ID)) |
|||
return data; |
|||
data.Add("DisplayName", user.DisplayName); // The lobby doesn't need to know any data beyond the name and state; Relay will handle the rest.
|
|||
data.Add("UserStatus", ((int)user.UserStatus).ToString()); |
|||
return data; |
|||
} |
|||
|
|||
/// <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 RemoteToLocal(Lobby lobby, LocalLobby lobbyToUpdate) |
|||
{ |
|||
//Copy Data from Lobby into Local lobby fields
|
|||
LocalLobby.LobbyData info = new LocalLobby.LobbyData(lobbyToUpdate.Data) |
|||
{ |
|||
LobbyID = lobby.Id, |
|||
LobbyCode = lobby.LobbyCode, |
|||
Private = lobby.IsPrivate, |
|||
LobbyName = lobby.Name, |
|||
MaxPlayerCount = lobby.MaxPlayers, |
|||
RelayCode = lobby.Data?.ContainsKey("RelayCode") == true ? lobby.Data["RelayCode"].Value : lobbyToUpdate.RelayCode, // By providing RelayCode through the lobby data with Member visibility, we ensure a client is connected to the lobby before they could attempt a relay connection, preventing timing issues between them.
|
|||
RelayNGOCode = lobby.Data?.ContainsKey("RelayNGOCode") == true ? lobby.Data["RelayNGOCode"].Value : lobbyToUpdate.RelayNGOCode, |
|||
State = lobby.Data?.ContainsKey("State") == true ? (LobbyState)int.Parse(lobby.Data["State"].Value) : LobbyState.Lobby, |
|||
Color = lobby.Data?.ContainsKey("Color") == true ? (LobbyColor)int.Parse(lobby.Data["Color"].Value) : LobbyColor.None, |
|||
State_LastEdit = lobby.Data?.ContainsKey("State_LastEdit") == true ? long.Parse(lobby.Data["State_LastEdit"].Value) : lobbyToUpdate.Data.State_LastEdit, |
|||
Color_LastEdit = lobby.Data?.ContainsKey("Color_LastEdit") == true ? long.Parse(lobby.Data["Color_LastEdit"].Value) : lobbyToUpdate.Data.Color_LastEdit, |
|||
RelayNGOCode_LastEdit = lobby.Data?.ContainsKey("RelayNGOCode_LastEdit") == true ? long.Parse(lobby.Data["RelayNGOCode_LastEdit"].Value) : lobbyToUpdate.Data.RelayNGOCode_LastEdit |
|||
}; |
|||
|
|||
Dictionary<string, LobbyUser> lobbyUsers = new Dictionary<string, LobbyUser>(); |
|||
foreach (var player in lobby.Players) |
|||
{ |
|||
// 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)) |
|||
{ |
|||
if (status > (int)UserStatus.Connecting && lobbyToUpdate.LobbyUsers.ContainsKey(player.Id)) |
|||
{ |
|||
lobbyUsers.Add(player.Id, lobbyToUpdate.LobbyUsers[player.Id]); |
|||
continue; |
|||
} |
|||
} |
|||
|
|||
// If the player isn't connected to Relay, get the most recent data that the lobby knows.
|
|||
// (If we haven't seen this player yet, a new local representation of the player will have already been added by the LocalLobby.)
|
|||
LobbyUser incomingData = new LobbyUser |
|||
{ |
|||
IsHost = lobby.HostId.Equals(player.Id), |
|||
DisplayName = player.Data?.ContainsKey("DisplayName") == true ? player.Data["DisplayName"].Value : default, |
|||
Emote = player.Data?.ContainsKey("Emote") == true ? (EmoteType)int.Parse(player.Data["Emote"].Value) : default, |
|||
UserStatus = player.Data?.ContainsKey("UserStatus") == true ? (UserStatus)int.Parse(player.Data["UserStatus"].Value) : UserStatus.Connecting, |
|||
ID = player.Id |
|||
}; |
|||
lobbyUsers.Add(incomingData.ID, incomingData); |
|||
} |
|||
|
|||
//Push all the data at once so we don't call OnChanged for each variable
|
|||
lobbyToUpdate.CopyObserved(info, lobbyUsers); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Create a list of new LocalLobbies from the result of a lobby list query.
|
|||
/// </summary>
|
|||
public static List<LocalLobby> QueryToLocalList(QueryResponse response) |
|||
{ |
|||
List<LocalLobby> retLst = new List<LocalLobby>(); |
|||
foreach (var lobby in response.Results) |
|||
retLst.Add(RemoteToNewLocal(lobby)); |
|||
return retLst; |
|||
} |
|||
|
|||
private static LocalLobby RemoteToNewLocal(Lobby lobby) |
|||
{ |
|||
LocalLobby data = new LocalLobby(); |
|||
RemoteToLocal(lobby, data); |
|||
return data; |
|||
} |
|||
} |
|||
} |
|
|||
using System.Collections.Generic; |
|||
using Unity.Services.Lobbies.Models; |
|||
|
|||
namespace LobbyRelaySample.lobby |
|||
{ |
|||
/// <summary>
|
|||
/// Convert the lobby resulting from a request into a LocalLobby for use in the game logic.
|
|||
/// </summary>
|
|||
public static class ToLocalLobby |
|||
{ |
|||
/// <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) |
|||
{ |
|||
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.
|
|||
{ LobbyID = lobby.Id, |
|||
LobbyCode = lobby.LobbyCode, |
|||
Private = lobby.IsPrivate, |
|||
LobbyName = lobby.Name, |
|||
MaxPlayerCount = lobby.MaxPlayers, |
|||
RelayCode = lobby.Data?.ContainsKey("RelayCode") == true ? lobby.Data["RelayCode"].Value : null, // By providing RelayCode through the lobby data with Member visibility, we ensure a client is connected to the lobby before they could attempt a relay connection, preventing timing issues between them.
|
|||
RelayNGOCode = lobby.Data?.ContainsKey("RelayNGOCode") == true ? lobby.Data["RelayNGOCode"].Value : null, |
|||
State = lobby.Data?.ContainsKey("State") == true ? (LobbyState) int.Parse(lobby.Data["State"].Value) : LobbyState.Lobby, |
|||
Color = lobby.Data?.ContainsKey("Color") == true ? (LobbyColor) int.Parse(lobby.Data["Color"].Value) : LobbyColor.None, |
|||
State_LastEdit = lobby.Data?.ContainsKey("State_LastEdit") == true ? long.Parse(lobby.Data["State_LastEdit"].Value) : 0, |
|||
Color_LastEdit = lobby.Data?.ContainsKey("Color_LastEdit") == true ? long.Parse(lobby.Data["Color_LastEdit"].Value) : 0, |
|||
RelayNGOCode_LastEdit = lobby.Data?.ContainsKey("RelayNGOCode_LastEdit") == true ? long.Parse(lobby.Data["RelayNGOCode_LastEdit"].Value) : 0, |
|||
}; |
|||
|
|||
Dictionary<string, LobbyUser> lobbyUsers = new Dictionary<string, LobbyUser>(); |
|||
foreach (var player in lobby.Players) |
|||
{ |
|||
// 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)) |
|||
{ |
|||
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, get the most recent data that the lobby knows.
|
|||
// (If we haven't seen this player yet, a new local representation of the player will have already been added by the LocalLobby.)
|
|||
LobbyUser incomingData = new LobbyUser |
|||
{ |
|||
IsHost = lobby.HostId.Equals(player.Id), |
|||
DisplayName = player.Data?.ContainsKey("DisplayName") == true ? player.Data["DisplayName"].Value : default, |
|||
Emote = player.Data?.ContainsKey("Emote") == true ? (EmoteType)int.Parse(player.Data["Emote"].Value) : default, |
|||
UserStatus = player.Data?.ContainsKey("UserStatus") == true ? (UserStatus)int.Parse(player.Data["UserStatus"].Value) : UserStatus.Connecting, |
|||
ID = player.Id |
|||
}; |
|||
lobbyUsers.Add(incomingData.ID, incomingData); |
|||
} |
|||
outputToHere.CopyObserved(info, lobbyUsers); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Create a list of new LocalLobbies from the result of a lobby list query.
|
|||
/// </summary>
|
|||
public static List<LocalLobby> Convert(QueryResponse response) |
|||
{ |
|||
List<LocalLobby> retLst = new List<LocalLobby>(); |
|||
foreach (var lobby in response.Results) |
|||
retLst.Add(Convert(lobby)); |
|||
return retLst; |
|||
} |
|||
private static LocalLobby Convert(Lobby lobby) |
|||
{ |
|||
LocalLobby data = new LocalLobby(); |
|||
Convert(lobby, data); |
|||
return data; |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using LobbyRemote = Unity.Services.Lobbies.Models.Lobby; |
|||
|
|||
namespace LobbyRelaySample |
|||
{ |
|||
/// <summary>
|
|||
/// Keep updated on changes to a joined lobby, at a speed compliant with Lobby's rate limiting.
|
|||
/// </summary>
|
|||
public class LobbyContentHeartbeat : IReceiveMessages |
|||
{ |
|||
private LocalLobby m_localLobby; |
|||
private LobbyUser m_localUser; |
|||
private int m_awaitingQueryCount = 0; |
|||
private bool m_shouldPushData = false; |
|||
|
|||
private const float k_approvalMaxTime = 10; // Used for determining if a user should timeout if they are unable to connect.
|
|||
private float m_lifetime = 0; |
|||
|
|||
public void BeginTracking(LocalLobby lobby, LobbyUser localUser) |
|||
{ |
|||
m_localLobby = lobby; |
|||
m_localUser = localUser; |
|||
Locator.Get.UpdateSlow.Subscribe(OnUpdate, 1.5f); |
|||
Locator.Get.Messenger.Subscribe(this); |
|||
m_localLobby.onChanged += OnLocalLobbyChanged; |
|||
m_shouldPushData = true; // Ensure the initial presence of a new player is pushed to the lobby; otherwise, when a non-host joins, the LocalLobby never receives their data until they push something new.
|
|||
m_lifetime = 0; |
|||
} |
|||
|
|||
public void EndTracking() |
|||
{ |
|||
m_shouldPushData = false; |
|||
Locator.Get.UpdateSlow.Unsubscribe(OnUpdate); |
|||
Locator.Get.Messenger.Unsubscribe(this); |
|||
if (m_localLobby != null) |
|||
m_localLobby.onChanged -= OnLocalLobbyChanged; |
|||
m_localLobby = null; |
|||
m_localUser = null; |
|||
} |
|||
|
|||
private void OnLocalLobbyChanged(LocalLobby changed) |
|||
{ |
|||
if (string.IsNullOrEmpty(changed.LobbyID)) // When the player leaves, their LocalLobby is cleared out but maintained.
|
|||
EndTracking(); |
|||
m_shouldPushData = true; |
|||
} |
|||
|
|||
public void OnReceiveMessage(MessageType type, object msg) |
|||
{ |
|||
if (type == MessageType.ClientUserSeekingDisapproval) |
|||
{ |
|||
bool shouldDisapprove = m_localLobby.State != LobbyState.Lobby; // By not refreshing, it's possible to have a lobby in the lobby list UI after its countdown starts and then try joining.
|
|||
if (shouldDisapprove) |
|||
(msg as Action<relay.Approval>)?.Invoke(relay.Approval.GameAlreadyStarted); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// If there have been any data changes since the last update, push them to Lobby. Regardless, pull for the most recent data.
|
|||
/// (Unless we're already awaiting a query, in which case continue waiting.)
|
|||
/// </summary>
|
|||
private void OnUpdate(float dt) |
|||
{ |
|||
m_lifetime += dt; |
|||
if (m_awaitingQueryCount > 0 || m_localLobby == null) |
|||
return; |
|||
if (m_localUser.IsHost) |
|||
LobbyAsyncRequests.Instance.DoLobbyHeartbeat(dt); |
|||
|
|||
if (!m_localUser.IsApproved && m_lifetime > k_approvalMaxTime) |
|||
{ |
|||
Locator.Get.Messenger.OnReceiveMessage(MessageType.DisplayErrorPopup, "Connection attempt timed out!"); |
|||
Locator.Get.Messenger.OnReceiveMessage(MessageType.ChangeMenuState, GameState.JoinMenu); |
|||
} |
|||
|
|||
if (m_shouldPushData) |
|||
PushDataToLobby(); |
|||
else |
|||
OnRetrieve(); |
|||
|
|||
|
|||
void PushDataToLobby() |
|||
{ |
|||
m_shouldPushData = false; |
|||
|
|||
if (m_localUser.IsHost) |
|||
{ |
|||
m_awaitingQueryCount++; |
|||
DoLobbyDataPush(); |
|||
} |
|||
m_awaitingQueryCount++; |
|||
DoPlayerDataPush(); |
|||
} |
|||
|
|||
void DoLobbyDataPush() |
|||
{ |
|||
LobbyAsyncRequests.Instance.UpdateLobbyDataAsync(RetrieveLobbyData(m_localLobby), () => { if (--m_awaitingQueryCount <= 0) OnRetrieve(); }); |
|||
} |
|||
|
|||
void DoPlayerDataPush() |
|||
{ |
|||
LobbyAsyncRequests.Instance.UpdatePlayerDataAsync(RetrieveUserData(m_localUser), () => { if (--m_awaitingQueryCount <= 0) OnRetrieve(); }); |
|||
} |
|||
|
|||
void OnRetrieve() |
|||
{ |
|||
LobbyRemote lobbyRemote = LobbyAsyncRequests.Instance.CurrentLobby; |
|||
if (lobbyRemote == null) return; |
|||
bool prevShouldPush = m_shouldPushData; |
|||
var prevState = m_localLobby.State; |
|||
lobby.ToLocalLobby.Convert(lobbyRemote, m_localLobby); |
|||
m_shouldPushData = prevShouldPush; |
|||
|
|||
// If the host suddenly leaves, the Lobby service will automatically handle disconnects after about 30s, but we can try to do a disconnect sooner if we detect it.
|
|||
if (!m_localUser.IsHost) |
|||
{ |
|||
foreach (var lobbyUser in m_localLobby.LobbyUsers) |
|||
{ |
|||
if (lobbyUser.Value.IsHost) |
|||
return; |
|||
} |
|||
Locator.Get.Messenger.OnReceiveMessage(MessageType.DisplayErrorPopup, "Host left the lobby! Disconnecting..."); |
|||
Locator.Get.Messenger.OnReceiveMessage(MessageType.EndGame, null); |
|||
Locator.Get.Messenger.OnReceiveMessage(MessageType.ChangeMenuState, GameState.JoinMenu); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private static Dictionary<string, string> RetrieveLobbyData(LocalLobby lobby) |
|||
{ |
|||
Dictionary<string, string> data = new Dictionary<string, string>(); |
|||
data.Add("RelayCode", lobby.RelayCode); |
|||
data.Add("RelayNGOCode", lobby.RelayNGOCode); |
|||
data.Add("State", ((int)lobby.State).ToString()); // Using an int is smaller than using the enum state's name.
|
|||
data.Add("Color", ((int)lobby.Color).ToString()); |
|||
data.Add("State_LastEdit", lobby.Data.State_LastEdit.ToString()); |
|||
data.Add("Color_LastEdit", lobby.Data.Color_LastEdit.ToString()); |
|||
data.Add("RelayNGOCode_LastEdit", lobby.Data.RelayNGOCode_LastEdit.ToString()); |
|||
return data; |
|||
} |
|||
|
|||
private static Dictionary<string, string> RetrieveUserData(LobbyUser user) |
|||
{ |
|||
Dictionary<string, string> data = new Dictionary<string, string>(); |
|||
if (user == null || string.IsNullOrEmpty(user.ID)) |
|||
return data; |
|||
data.Add("DisplayName", user.DisplayName); // The lobby doesn't need to know any data beyond the name and state; Relay will handle the rest.
|
|||
data.Add("UserStatus", ((int)user.UserStatus).ToString()); |
|||
return data; |
|||
} |
|||
} |
|||
} |
撰写
预览
正在加载...
取消
保存
Reference in new issue