in MRTK Tutorials/Assets/Photon/PhotonRealtime/Code/LoadBalancingClient.cs [2606:2929]
public virtual void OnOperationResponse(OperationResponse operationResponse)
{
// if (operationResponse.ReturnCode != 0) this.DebugReturn(DebugLevel.ERROR, operationResponse.ToStringFull());
// use the "secret" or "token" whenever we get it. doesn't really matter if it's in AuthResponse.
if (operationResponse.Parameters.ContainsKey(ParameterCode.Token))
{
if (this.AuthValues == null)
{
this.AuthValues = new AuthenticationValues();
//this.DebugReturn(DebugLevel.ERROR, "Server returned secret. Created AuthValues.");
}
this.AuthValues.Token = operationResponse[ParameterCode.Token] as string;
this.tokenCache = this.AuthValues.Token;
}
// if the operation limit was reached, disconnect (but still execute the operation response).
if (operationResponse.ReturnCode == ErrorCode.OperationLimitReached)
{
this.Disconnect(DisconnectCause.DisconnectByOperationLimit);
}
switch (operationResponse.OperationCode)
{
case OperationCode.Authenticate:
case OperationCode.AuthenticateOnce:
{
if (operationResponse.ReturnCode != 0)
{
this.DebugReturn(DebugLevel.ERROR, operationResponse.ToStringFull() + " Server: " + this.Server + " Address: " + this.LoadBalancingPeer.ServerAddress);
switch (operationResponse.ReturnCode)
{
case ErrorCode.InvalidAuthentication:
this.DisconnectedCause = DisconnectCause.InvalidAuthentication;
break;
case ErrorCode.CustomAuthenticationFailed:
this.DisconnectedCause = DisconnectCause.CustomAuthenticationFailed;
this.ConnectionCallbackTargets.OnCustomAuthenticationFailed(operationResponse.DebugMessage);
break;
case ErrorCode.InvalidRegion:
this.DisconnectedCause = DisconnectCause.InvalidRegion;
break;
case ErrorCode.MaxCcuReached:
this.DisconnectedCause = DisconnectCause.MaxCcuReached;
break;
case ErrorCode.InvalidOperation:
case ErrorCode.OperationNotAllowedInCurrentState:
this.DisconnectedCause = DisconnectCause.OperationNotAllowedInCurrentState;
break;
case ErrorCode.AuthenticationTicketExpired:
this.DisconnectedCause = DisconnectCause.AuthenticationTicketExpired;
break;
}
this.Disconnect(this.DisconnectedCause);
break; // if auth didn't succeed, we disconnect (above) and exit this operation's handling
}
if (this.Server == ServerConnection.NameServer || this.Server == ServerConnection.MasterServer)
{
if (operationResponse.Parameters.ContainsKey(ParameterCode.UserId))
{
string incomingId = (string)operationResponse.Parameters[ParameterCode.UserId];
if (!string.IsNullOrEmpty(incomingId))
{
this.UserId = incomingId;
this.LocalPlayer.UserId = incomingId;
this.DebugReturn(DebugLevel.INFO, string.Format("Received your UserID from server. Updating local value to: {0}", this.UserId));
}
}
if (operationResponse.Parameters.ContainsKey(ParameterCode.NickName))
{
this.NickName = (string)operationResponse.Parameters[ParameterCode.NickName];
this.DebugReturn(DebugLevel.INFO, string.Format("Received your NickName from server. Updating local value to: {0}", this.NickName));
}
if (operationResponse.Parameters.ContainsKey(ParameterCode.EncryptionData))
{
this.SetupEncryption((Dictionary<byte, object>)operationResponse.Parameters[ParameterCode.EncryptionData]);
}
}
if (this.Server == ServerConnection.NameServer)
{
string receivedCluster = operationResponse[ParameterCode.Cluster] as string;
if (!string.IsNullOrEmpty(receivedCluster))
{
this.CurrentCluster = receivedCluster;
}
// on the NameServer, authenticate returns the MasterServer address for a region and we hop off to there
this.MasterServerAddress = operationResponse[ParameterCode.Address] as string;
if (this.ServerPortOverrides.MasterServerPort != 0)
{
//Debug.LogWarning("Incoming MasterServer Address: "+this.MasterServerAddress);
this.MasterServerAddress = ReplacePortWithAlternative(this.MasterServerAddress, this.ServerPortOverrides.MasterServerPort);
//Debug.LogWarning("New MasterServer Address: "+this.MasterServerAddress);
}
if (this.AuthMode == AuthModeOption.AuthOnceWss && this.ExpectedProtocol != null)
{
this.DebugReturn(DebugLevel.INFO, string.Format("AuthOnceWss mode. Auth response switches TransportProtocol to ExpectedProtocol: {0}.", this.ExpectedProtocol));
this.LoadBalancingPeer.TransportProtocol = (ConnectionProtocol)this.ExpectedProtocol;
this.ExpectedProtocol = null;
}
this.DisconnectToReconnect();
}
else if (this.Server == ServerConnection.MasterServer)
{
this.State = ClientState.ConnectedToMasterServer;
if (this.failedRoomEntryOperation == null)
{
this.ConnectionCallbackTargets.OnConnectedToMaster();
}
else
{
this.CallbackRoomEnterFailed(this.failedRoomEntryOperation);
this.failedRoomEntryOperation = null;
}
if (this.AuthMode != AuthModeOption.Auth)
{
this.LoadBalancingPeer.OpSettings(this.EnableLobbyStatistics);
}
}
else if (this.Server == ServerConnection.GameServer)
{
this.State = ClientState.Joining;
if (this.enterRoomParamsCache.JoinMode == JoinMode.RejoinOnly)
{
this.enterRoomParamsCache.PlayerProperties = null;
}
else
{
Hashtable allProps = new Hashtable();
allProps.Merge(this.LocalPlayer.CustomProperties);
if (!string.IsNullOrEmpty(this.LocalPlayer.NickName))
{
allProps[ActorProperties.PlayerName] = this.LocalPlayer.NickName;
}
this.enterRoomParamsCache.PlayerProperties = allProps;
}
this.enterRoomParamsCache.OnGameServer = true;
if (this.lastJoinType == JoinType.JoinRoom || this.lastJoinType == JoinType.JoinRandomRoom || this.lastJoinType == JoinType.JoinRandomOrCreateRoom || this.lastJoinType == JoinType.JoinOrCreateRoom)
{
this.LoadBalancingPeer.OpJoinRoom(this.enterRoomParamsCache);
}
else if (this.lastJoinType == JoinType.CreateRoom)
{
this.LoadBalancingPeer.OpCreateRoom(this.enterRoomParamsCache);
}
break;
}
// optionally, OpAuth may return some data for the client to use. if it's available, call OnCustomAuthenticationResponse
Dictionary<string, object> data = (Dictionary<string, object>)operationResponse[ParameterCode.Data];
if (data != null)
{
this.ConnectionCallbackTargets.OnCustomAuthenticationResponse(data);
}
break;
}
case OperationCode.GetRegions:
// Debug.Log("GetRegions returned: " + operationResponse.ToStringFull());
if (operationResponse.ReturnCode == ErrorCode.InvalidAuthentication)
{
this.DebugReturn(DebugLevel.ERROR, string.Format("GetRegions failed. AppId is unknown on the (cloud) server. "+operationResponse.DebugMessage));
this.Disconnect(DisconnectCause.InvalidAuthentication);
break;
}
if (operationResponse.ReturnCode != ErrorCode.Ok)
{
this.DebugReturn(DebugLevel.ERROR, "GetRegions failed. Can't provide regions list. ReturnCode: " + operationResponse.ReturnCode + ": " + operationResponse.DebugMessage);
this.Disconnect(DisconnectCause.InvalidAuthentication);
break;
}
if (this.RegionHandler == null)
{
this.RegionHandler = new RegionHandler(this.ServerPortOverrides.MasterServerPort);
}
if (this.RegionHandler.IsPinging)
{
this.DebugReturn(DebugLevel.WARNING, "Received an response for OpGetRegions while the RegionHandler is pinging regions already. Skipping this response in favor of completing the current region-pinging.");
return; // in this particular case, we suppress the duplicate GetRegion response. we don't want a callback for this, cause there is a warning already.
}
this.RegionHandler.SetRegions(operationResponse);
this.ConnectionCallbackTargets.OnRegionListReceived(this.RegionHandler);
if (this.connectToBestRegion)
{
// ping minimal regions (if one is known) and connect
this.RegionHandler.PingMinimumOfRegions(this.OnRegionPingCompleted, this.bestRegionSummaryFromStorage);
}
break;
case OperationCode.JoinRandomGame: // this happens only on the master server. on gameserver this is a "regular" join
case OperationCode.CreateGame:
case OperationCode.JoinGame:
if (operationResponse.ReturnCode != 0)
{
if (this.Server == ServerConnection.GameServer)
{
this.failedRoomEntryOperation = operationResponse;
this.DisconnectToReconnect();
}
else
{
this.State = (this.InLobby) ? ClientState.JoinedLobby : ClientState.ConnectedToMasterServer;
this.CallbackRoomEnterFailed(operationResponse);
}
}
else
{
if (this.Server == ServerConnection.GameServer)
{
this.GameEnteredOnGameServer(operationResponse);
}
else
{
this.GameServerAddress = (string)operationResponse[ParameterCode.Address];
if (this.ServerPortOverrides.GameServerPort != 0)
{
//Debug.LogWarning("Incoming GameServer Address: " + this.GameServerAddress);
this.GameServerAddress = ReplacePortWithAlternative(this.GameServerAddress, this.ServerPortOverrides.GameServerPort);
//Debug.LogWarning("New GameServer Address: " + this.GameServerAddress);
}
string roomName = operationResponse[ParameterCode.RoomName] as string;
if (!string.IsNullOrEmpty(roomName))
{
this.enterRoomParamsCache.RoomName = roomName;
}
this.DisconnectToReconnect();
}
}
break;
case OperationCode.GetGameList:
if (operationResponse.ReturnCode != 0)
{
this.DebugReturn(DebugLevel.ERROR, "GetGameList failed: " + operationResponse.ToStringFull());
break;
}
List<RoomInfo> _RoomInfoList = new List<RoomInfo>();
Hashtable games = (Hashtable)operationResponse[ParameterCode.GameList];
foreach (string gameName in games.Keys)
{
_RoomInfoList.Add(new RoomInfo(gameName, (Hashtable)games[gameName]));
}
this.LobbyCallbackTargets.OnRoomListUpdate(_RoomInfoList);
break;
case OperationCode.JoinLobby:
this.State = ClientState.JoinedLobby;
this.LobbyCallbackTargets.OnJoinedLobby();
break;
case OperationCode.LeaveLobby:
this.State = ClientState.ConnectedToMasterServer;
this.LobbyCallbackTargets.OnLeftLobby();
break;
case OperationCode.Leave:
this.DisconnectToReconnect();
break;
case OperationCode.FindFriends:
if (operationResponse.ReturnCode != 0)
{
this.DebugReturn(DebugLevel.ERROR, "OpFindFriends failed: " + operationResponse.ToStringFull());
this.friendListRequested = null;
break;
}
bool[] onlineList = operationResponse[ParameterCode.FindFriendsResponseOnlineList] as bool[];
string[] roomList = operationResponse[ParameterCode.FindFriendsResponseRoomIdList] as string[];
//if (onlineList == null || roomList == null || this.friendListRequested == null || onlineList.Length != this.friendListRequested.Length)
//{
// // TODO: Check if we should handle this case better / more extensively
// this.DebugReturn(DebugLevel.ERROR, "OpFindFriends failed. Some list is not set. OpResponse: " + operationResponse.ToStringFull());
// this.friendListRequested = null;
// this.isFetchingFriendList = false;
// break;
//}
List<FriendInfo> friendList = new List<FriendInfo>(this.friendListRequested.Length);
for (int index = 0; index < this.friendListRequested.Length; index++)
{
FriendInfo friend = new FriendInfo();
friend.UserId = this.friendListRequested[index];
friend.Room = roomList[index];
friend.IsOnline = onlineList[index];
friendList.Insert(index, friend);
}
this.friendListRequested = null;
this.MatchMakingCallbackTargets.OnFriendListUpdate(friendList);
break;
case OperationCode.WebRpc:
this.WebRpcCallbackTargets.OnWebRpcResponse(operationResponse);
break;
}
if (this.OpResponseReceived != null) this.OpResponseReceived(operationResponse);
}