浏览代码

Adding logic to supply the relay allocation and join code to a lobby, to enable automatic disconnect (i.e. if relay disconnects a player, the lobby detects that and also disconnects the player). It doesn't currently *work* but I'm working with the lobby team to see why, since as far as I'm aware it should be working with what I have.

/main/staging
nathaniel.buck@unity3d.com 3 年前
当前提交
265c2b37
共有 8 个文件被更改,包括 40 次插入20 次删除
  1. 6
      Assets/Scripts/Lobby/LobbyAPIInterface.cs
  2. 29
      Assets/Scripts/Lobby/LobbyAsyncRequests.cs
  3. 2
      Assets/Scripts/Lobby/ToLocalLobby.cs
  4. 2
      Assets/Scripts/Relay/RelayUtpHost.cs
  5. 16
      Assets/Scripts/Relay/RelayUtpSetup.cs
  6. 5
      Assets/Scripts/Game/GameStateManager.cs
  7. 0
      /Assets/Scripts/Game.meta
  8. 0
      /Assets/Scripts/Game

6
Assets/Scripts/Lobby/LobbyAPIInterface.cs


new InProgressRequest<Response<Lobby>>(task, onComplete);
}
public static void UpdatePlayerAsync(string lobbyId, string playerId, Dictionary<string, PlayerDataObject> data, Action<Response<Lobby>> onComplete)
public static void UpdatePlayerAsync(string lobbyId, string playerId, Dictionary<string, PlayerDataObject> data, Action<Response<Lobby>> onComplete, string allocationId, string connectionInfo)
data: data
data: data,
allocationId: allocationId,
connectionInfo: connectionInfo
));
var task = LobbyService.LobbyApiClient.UpdatePlayerAsync(updateRequest);
new InProgressRequest<Response<Lobby>>(task, onComplete);

29
Assets/Scripts/Lobby/LobbyAsyncRequests.cs


public void EndTracking()
{
m_currentLobbyId = null;
m_lastKnownLobby = null;
}
private void UpdateLobby(float unused)

/// <param name="data">Key-value pairs, which will overwrite any existing data for these keys. Presumed to be available to all lobby members but not publicly.</param>
public void UpdatePlayerDataAsync(Dictionary<string, string> data, Action onComplete)
{
if (!ShouldUpdateData(() => { UpdatePlayerDataAsync(data, onComplete); }, onComplete))
if (!ShouldUpdateData(() => { UpdatePlayerDataAsync(data, onComplete); }, onComplete, false))
Lobby lobby = m_lastKnownLobby;
string playerId = Locator.Get.Identity.GetSubIdentity(Auth.IIdentityType.Auth).GetContent("id");
Dictionary<string, PlayerDataObject> dataCurr = new Dictionary<string, PlayerDataObject>();
foreach (var dataNew in data)
{

dataCurr.Add(dataNew.Key, dataObj);
}
LobbyAPIInterface.UpdatePlayerAsync(lobby.Id, Locator.Get.Identity.GetSubIdentity(Auth.IIdentityType.Auth).GetContent("id"), dataCurr, (r) => { onComplete?.Invoke(); });
LobbyAPIInterface.UpdatePlayerAsync(m_lastKnownLobby.Id, playerId, dataCurr, (r) => { onComplete?.Invoke(); }, null, null);
}
/// <summary>Lobby can be provided info about Relay (or any other remote allocation) so it can add automatic disconnect handling.</summary>
public void UpdatePlayerRelayInfoAsync(string allocationId, string connectionInfo, Action onComplete)
{
if (!ShouldUpdateData(() => { UpdatePlayerRelayInfoAsync(allocationId, connectionInfo, onComplete); }, onComplete, true)) // Do retry here since the RelayUtpSetup that called this might be destroyed right after this.
return;
string playerId = Locator.Get.Identity.GetSubIdentity(Auth.IIdentityType.Auth).GetContent("id");
LobbyAPIInterface.UpdatePlayerAsync(m_lastKnownLobby.Id, playerId, new Dictionary<string, PlayerDataObject>(), (r) => { onComplete?.Invoke(); }, allocationId, connectionInfo);
if (!ShouldUpdateData(() => { UpdateLobbyDataAsync(data, onComplete); }, onComplete))
if (!ShouldUpdateData(() => { UpdateLobbyDataAsync(data, onComplete); }, onComplete, false))
return;
Lobby lobby = m_lastKnownLobby;

LobbyAPIInterface.UpdateLobbyAsync(lobby.Id, dataCurr, (r) => { onComplete?.Invoke(); });
}
private bool ShouldUpdateData(Action caller, Action onComplete)
/// <summary>
/// If we are in the middle of another operation, hold onto any pending ones until after that.
/// If we aren't in a lobby yet, leave it to the caller to decide what to do, since some callers might need to retry and others might not.
/// </summary>
private bool ShouldUpdateData(Action caller, Action onComplete, bool shouldRetryIfLobbyNull)
{
if (m_isMidRetrieve)
{ m_pendingOperations.Enqueue(caller);

if (lobby == null)
{ onComplete?.Invoke();
{
if (shouldRetryIfLobbyNull)
m_pendingOperations.Enqueue(caller);
onComplete?.Invoke();
return false;
}
return true;

2
Assets/Scripts/Lobby/ToLocalLobby.cs


Private = lobby.IsPrivate,
LobbyName = lobby.Name,
MaxPlayerCount = lobby.MaxPlayers,
RelayCode = lobby.Data?.ContainsKey("RelayCode") == true ? lobby.Data["RelayCode"].Value : null, // TODO: Remove?
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.
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...
Color = lobby.Data?.ContainsKey("Color") == true ? (LobbyColor) int.Parse(lobby.Data["Color"].Value) : LobbyColor.None
};

2
Assets/Scripts/Relay/RelayUtpHost.cs


protected override void ProcessDisconnectEvent(NetworkConnection conn, DataStreamReader strm)
{
// TODO: If a client disconnects, see if remaining players are all already ready.
// TEMP logging
UnityEngine.Debug.LogError("Client disconnected!");
}
public void OnReceiveMessage(MessageType type, object msg)

16
Assets/Scripts/Relay/RelayUtpSetup.cs


protected LobbyUser m_localUser;
protected Action<bool, RelayUtpClient> m_onJoinComplete;
public enum MsgType { NewPlayer = 0, Ping = 1, ReadyState = 2, PlayerName = 3, Emote = 4, StartCountdown = 5, CancelCountdown = 6, ConfirmInGame = 7, EndInGame = 8 }
public enum MsgType { NewPlayer = 0, Ping, ReadyState, PlayerName, Emote, StartCountdown, CancelCountdown, ConfirmInGame, EndInGame }
public void BeginRelayJoin(LocalLobby localLobby, LobbyUser localUser, Action<bool, RelayUtpClient> onJoinComplete)
{

[Flags]
private enum JoinState { None = 0, Bound = 1, Joined = 2 }
private JoinState m_joinState = JoinState.None;
private Allocation m_allocation;
protected override void JoinRelay()
{

private void OnAllocation(Allocation allocation)
{
m_allocation = allocation;
RelayInterface.GetJoinCodeAsync(allocation.AllocationId, OnRelayCode);
BindToAllocation(allocation.RelayServer.IpV4, allocation.RelayServer.Port, allocation.AllocationIdBytes, allocation.ConnectionData, allocation.ConnectionData, allocation.Key, 16);
}

m_localLobby.RelayCode = relayCode;
RelayInterface.JoinAsync(m_localLobby.RelayCode, OnJoin);
}
private void OnJoin(JoinAllocation joinAllocation)
{
m_localLobby.RelayServer = new ServerAddress(joinAllocation.RelayServer.IpV4, joinAllocation.RelayServer.Port);
m_localLobby.RelayServer = new ServerAddress(m_allocation.RelayServer.IpV4, m_allocation.RelayServer.Port);
m_joinState |= JoinState.Joined;
CheckForComplete();
}

RelayUtpHost host = gameObject.AddComponent<RelayUtpHost>();
host.Initialize(m_networkDriver, m_connections, m_localUser, m_localLobby);
m_onJoinComplete(true, host);
LobbyAsyncRequests.Instance.UpdatePlayerRelayInfoAsync(m_allocation.AllocationId.ToString(), m_localLobby.RelayCode, null);
}
}
}

private JoinAllocation m_allocation;
protected override void JoinRelay()
{
m_localLobby.onChanged += OnLobbyChange;

{
if (allocation == null)
return;
m_allocation = allocation;
BindToAllocation(allocation.RelayServer.IpV4, allocation.RelayServer.Port, allocation.AllocationIdBytes, allocation.ConnectionData, allocation.HostConnectionData, allocation.Key, 1);
m_localLobby.RelayServer = new ServerAddress(allocation.RelayServer.IpV4, allocation.RelayServer.Port);
}

RelayUtpClient watcher = gameObject.AddComponent<RelayUtpClient>();
watcher.Initialize(m_networkDriver, m_connections, m_localUser, m_localLobby);
m_onJoinComplete(true, watcher);
LobbyAsyncRequests.Instance.UpdatePlayerRelayInfoAsync(m_allocation.AllocationId.ToString(), m_localLobby.RelayCode, null);
}
}
}

5
Assets/Scripts/Game/GameStateManager.cs


IEnumerator LeaveBeforeQuit()
{
ForceLeaveAttempt();
// TEMP: Since we're temporarily (as of 6/31/21) deleting empty lobbies when we leave them manually, we'll delay longer to ensure that happens.
//yield return null;
yield return new WaitForSeconds(0.5f);
yield return null;
Application.Quit();
}
}

/Assets/Scripts/Entities.meta → /Assets/Scripts/Game.meta

/Assets/Scripts/Entities → /Assets/Scripts/Game

正在加载...
取消
保存