namespace CS.Platform.Playfab { public class OnlinePlayer { public CS.Platform.Systems.User.UserInfo userInfo = Systems.User.UserInfo.INVALID_ID; public bool isLocal = false; public bool isReady = false; public PartyCSharpSDK.PARTY_ENDPOINT_HANDLE endPoint = null; public PlayFab.AuthenticationModels.EntityKey titleEntity = null; public PlayFab.AuthenticationModels.EntityKey masterEntity = null; public PlayFab.ClientModels.PlayerProfileModel playfabProfile = null; public PartyCSharpSDK.PARTY_ENDPOINT_HANDLE localEndPoint = null; } public class Network { public const long TIMEOUT_TOTAL = 1000*20;//20 seconds public const byte REQUEST_INFO = 0; public const byte SETUP_READY = 1; [System.Serializable] protected class NetworkInfo { public long timeStamp; public Systems.User.UserInfo hostInfo; public Systems.User.UserInfo[] userList; } private const string PLAYFAB_MASTER_ACCOUNT_TYPE = "master_player_account"; private const string PLAYFAB_TITLE_ACCOUNT_TYPE = "title_player_account"; private const string NETWORK_ID_INVITE_AND_DESCRIPTOR_SEPERATOR = "|"; static public bool EqualNetDescription(PartyCSharpSDK.PARTY_NETWORK_DESCRIPTOR a, PartyCSharpSDK.PARTY_NETWORK_DESCRIPTOR b, bool deep = true) { return ((a?.NetworkIdentifier == b?.NetworkIdentifier) && ((!deep) || (a?.RegionName == b?.RegionName))) ; } static public PartyCSharpSDK.PARTY_NETWORK_DESCRIPTOR NetworkIdToDescriptor(string networkId, out string generatedInvitationId) { generatedInvitationId = null; PartyCSharpSDK.PARTY_NETWORK_DESCRIPTOR partyNetworkDescriptor = null; int indexOfSeperator = networkId.IndexOf(NETWORK_ID_INVITE_AND_DESCRIPTOR_SEPERATOR); if (indexOfSeperator != -1) { generatedInvitationId = networkId.Substring(0, indexOfSeperator); string networkDescriptorString = networkId.Substring(indexOfSeperator + 1); uint result = PartyCSharpSDK.SDK.PartyDeserializeNetworkDescriptor(networkDescriptorString, out partyNetworkDescriptor); if (PartyCSharpSDK.PartyError.FAILED(result)) Utils.Debug.LogErro("[PLAYFAB:NETWORK] NetworkIdToDescriptor: PartyDeserializeNetworkDescriptor failed | Result: {0} | NetworkId: {1}", result, networkId); else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] NetworkIdToDescriptor: PartyDeserializeNetworkDescriptor Complete | Result: {0} | Identifier: {1} | Region: {2}", result, partyNetworkDescriptor?.NetworkIdentifier, partyNetworkDescriptor?.RegionName); } return partyNetworkDescriptor; } static public bool EqualNetHandle(PartyCSharpSDK.PARTY_NETWORK_HANDLE a, PartyCSharpSDK.PARTY_NETWORK_DESCRIPTOR b, bool deep) { uint result = 0; PartyCSharpSDK.PARTY_NETWORK_DESCRIPTOR desc = null; result = PartyCSharpSDK.SDK.PartyNetworkGetNetworkDescriptor(a, out desc); if (PartyCSharpSDK.PartyError.FAILED(result)) Utils.Debug.LogErro("[PLAYFAB:NETWORK] EqualNetHandle: PartyNetworkGetNetworkDescriptor Failed | Result: {0} | NetWork: {1}", result, a); else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] EqualNetHandle: PartyNetworkGetNetworkDescriptor Complete | Result: {0} | NetWork: {1} | Description: {2}", result, a, desc); return (EqualNetDescription(b, desc, deep)); } static string UpdateNetworkId(string invitationId, PartyCSharpSDK.PARTY_NETWORK_DESCRIPTOR networkDescriptor) { string serializedNetworkDescriptor = null; uint result = PartyCSharpSDK.SDK.PartySerializeNetworkDescriptor(networkDescriptor, out serializedNetworkDescriptor); if (PartyCSharpSDK.PartyError.FAILED(result)) { Utils.Debug.LogErro("[PLAYFAB:NETWORK] UpdateNetworkId: PartySerializeNetworkDescriptor Failed | Result: {0} | NetWork: {1} | Region: {2} | Out: {3}", result, networkDescriptor?.NetworkIdentifier, networkDescriptor?.RegionName, serializedNetworkDescriptor); return (null); } else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] UpdateNetworkId: PartySerializeNetworkDescriptor Complete | Result: {0} | NetWork: {1} | Region: {2} | Out: {3}", result, networkDescriptor?.NetworkIdentifier, networkDescriptor?.RegionName, serializedNetworkDescriptor); return (invitationId + NETWORK_ID_INVITE_AND_DESCRIPTOR_SEPERATOR + serializedNetworkDescriptor); } object _locker = new object(); string _titleID = null; PartyManager _manager = null; PartyCSharpSDK.PARTY_DEVICE_HANDLE _deviceHandle = null; PartyCSharpSDK.PARTY_NETWORK_DESCRIPTOR _networkDescription = null; PartyCSharpSDK.PARTY_NETWORK_HANDLE _networkHandle = null; PartyCSharpSDK.PARTY_ENDPOINT_HANDLE _localEndPointHandle = null; PartyCSharpSDK.PARTY_CHAT_CONTROL_HANDLE _localChatContHandle = null; PartyCSharpSDK.PARTY_NETWORK_CONFIGURATION _networkSettings = null; string _networkID = null; public string NetworkID { get { lock (_locker) { return (_networkID); } } } public uint MaxPlayers { get { lock (_locker) { return (_networkSettings?.MaxUserCount ?? 0); } } } public int Total { get { lock (_locker) { return (_setupCache.Count); } } } CS.Platform.Systems.User.LocalID _localID = Systems.User.LocalID.INVALID_ID; CS.Platform.Systems.User.UserInfo _localUser = Systems.User.UserInfo.INVALID_ID; string _forceIdent = null; string _joinNetwork = null; string _generatedInvitationId = null; IPlayerCache _allPlayerCache = null; System.Collections.Generic.List _playerCache = new System.Collections.Generic.List(); System.Collections.Generic.List _setupCache = new System.Collections.Generic.List(); System.Collections.Generic.List _hostCache = new System.Collections.Generic.List(); protected NetworkInfo _networkInfo = null; private byte[] _infoData = null; private byte[] _eventData = new byte[1]; public bool IsHost { get { lock (_locker) { return ((_networkInfo?.hostInfo ?? Systems.User.UserInfo.INVALID_ID) == _localUser); } } } public Systems.User.UserInfo Host { get { lock (_locker) { return (_networkInfo?.hostInfo ?? Systems.User.UserInfo.INVALID_ID); } } } TaskResult _joinTask = null; TaskResult _leaveTask = null; bool _fullyJoinedNetwork = false; bool _leaving = false; bool _left = false; public bool IsFullyJoined { get { lock (_locker) { return (_fullyJoinedNetwork); } } } public bool IsJoining { get { lock (_locker) { return (_joinTask != null); } } } public bool IsLeavingOrLeft { get { lock (_locker) { return (_leaving || _left); } } } System.Timers.Timer _timeoutTracker = null; private int _timeoutCounter = 0; public System.Action OnPlayerJoined = null; public System.Action OnPlayerLefted = null; public System.Action OnJoinedNetwork = null; public System.Action OnLeftNetwork = null; public System.Action OnHostChanged = null; public Network(PartyManager manager, string title, string forceIdent = null, IPlayerCache playerCache = null) { _manager = manager; _titleID = title; _forceIdent = forceIdent; _allPlayerCache = playerCache; //Create _manager.RegisterPartyEvent(PartyCSharpSDK.PARTY_STATE_CHANGE_TYPE.PARTY_STATE_CHANGE_TYPE_CREATE_NEW_NETWORK_COMPLETED, OnCreated); _manager.RegisterPartyEvent(PartyCSharpSDK.PARTY_STATE_CHANGE_TYPE.PARTY_STATE_CHANGE_TYPE_CONNECT_TO_NETWORK_COMPLETED, OnConnected); //Connections _manager.RegisterPartyEvent(PartyCSharpSDK.PARTY_STATE_CHANGE_TYPE.PARTY_STATE_CHANGE_TYPE_ENDPOINT_CREATED, OnEndpointCreated); _manager.RegisterPartyEvent(PartyCSharpSDK.PARTY_STATE_CHANGE_TYPE.PARTY_STATE_CHANGE_TYPE_ENDPOINT_DESTROYED, OnEndpointLost); //Chat //_manager.RegisterPartyEvent(PartyCSharpSDK.PARTY_STATE_CHANGE_TYPE.PARTY_STATE_CHANGE_TYPE_CHAT_CONTROL_CREATED, OnChatCreated); //_manager.RegisterPartyEvent(PartyCSharpSDK.PARTY_STATE_CHANGE_TYPE.PARTY_STATE_CHANGE_TYPE_CHAT_CONTROL_DESTROYED, OnChatLost); //Changed _manager.RegisterPartyEvent(PartyCSharpSDK.PARTY_STATE_CHANGE_TYPE.PARTY_STATE_CHANGE_TYPE_NETWORK_DESCRIPTOR_CHANGED, OnDescriptionChanged); //Leave/lost _manager.RegisterPartyEvent(PartyCSharpSDK.PARTY_STATE_CHANGE_TYPE.PARTY_STATE_CHANGE_TYPE_LEAVE_NETWORK_COMPLETED, OnLeave); _manager.RegisterPartyEvent(PartyCSharpSDK.PARTY_STATE_CHANGE_TYPE.PARTY_STATE_CHANGE_TYPE_NETWORK_DESTROYED, OnDestroyed); _manager.RegisterMessageCheckEvent(OnMessageEvent); } ~Network() { _manager.UnregisterPartyEvent(PartyCSharpSDK.PARTY_STATE_CHANGE_TYPE.PARTY_STATE_CHANGE_TYPE_CREATE_NEW_NETWORK_COMPLETED, OnCreated); _manager.UnregisterPartyEvent(PartyCSharpSDK.PARTY_STATE_CHANGE_TYPE.PARTY_STATE_CHANGE_TYPE_CONNECT_TO_NETWORK_COMPLETED, OnConnected); //Connections _manager.UnregisterPartyEvent(PartyCSharpSDK.PARTY_STATE_CHANGE_TYPE.PARTY_STATE_CHANGE_TYPE_ENDPOINT_CREATED, OnEndpointCreated); _manager.UnregisterPartyEvent(PartyCSharpSDK.PARTY_STATE_CHANGE_TYPE.PARTY_STATE_CHANGE_TYPE_ENDPOINT_DESTROYED, OnEndpointLost); //Chat //_manager.UnregisterPartyEvent(PartyCSharpSDK.PARTY_STATE_CHANGE_TYPE.PARTY_STATE_CHANGE_TYPE_CHAT_CONTROL_CREATED, OnChatCreated); //_manager.UnregisterPartyEvent(PartyCSharpSDK.PARTY_STATE_CHANGE_TYPE.PARTY_STATE_CHANGE_TYPE_CHAT_CONTROL_DESTROYED, OnChatLost); //Changed _manager.UnregisterPartyEvent(PartyCSharpSDK.PARTY_STATE_CHANGE_TYPE.PARTY_STATE_CHANGE_TYPE_NETWORK_DESCRIPTOR_CHANGED, OnDescriptionChanged); //Leave/lost _manager.UnregisterPartyEvent(PartyCSharpSDK.PARTY_STATE_CHANGE_TYPE.PARTY_STATE_CHANGE_TYPE_LEAVE_NETWORK_COMPLETED, OnLeave); _manager.UnregisterPartyEvent(PartyCSharpSDK.PARTY_STATE_CHANGE_TYPE.PARTY_STATE_CHANGE_TYPE_NETWORK_DESTROYED, OnDestroyed); _manager.UnregisterMessageCheckEvent(OnMessageEvent); ClearNetwork(true); } public void ClearNetwork(bool triggerLeave = false) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] ClearNetwork: Started | Trigger: {0}", triggerLeave); lock (_manager.Locker) { lock (_locker) { _networkDescription = null; _left = true; _networkID = null; _joinTask = null; _leaveTask = null; _forceIdent = null; _generatedInvitationId = null; for (int i = 0; i<_playerCache.Count; i++) { OnlinePlayer removing = _playerCache[i]; _allPlayerCache?.RemovePlayer(removing.userInfo, removing); } _playerCache.Clear(); _setupCache.Clear(); _fullyJoinedNetwork = false; _deviceHandle = null; _networkDescription = null; if ((_networkHandle!=null) && (!_leaving) && (triggerLeave)) { uint result = PartyCSharpSDK.SDK.PartyNetworkLeaveNetwork(_networkHandle, null); Utils.Debug.LogWarn("[PLAYFAB:NETWORK] ClearNetwork: Trigger leave | Result: {0} | Party: {1}", result, _networkHandle); _networkHandle = null; } _leaving = false; _left = false; _localEndPointHandle = null; _localChatContHandle = null; _networkSettings = null; StopTimeout(); } } } public TaskResult CreateNetwork(CS.Platform.Systems.User.LocalID localID, uint maxUsers, TaskResult taskResult = null, uint maxDevices = 0, uint maxEndpointsPerDevice = 0, uint maxUsersPerDevice = 0, uint maxDevicesPerUser = 1) { if (taskResult==null) taskResult = new TaskResult(); taskResult.Result = this; lock (_locker) { if (_joinTask != null) { Utils.Debug.LogErro("[PLAYFAB:NETWORK] CreateNetwork: Already active | Joining: {0}", _joinNetwork!=null); taskResult.Fail((_joinNetwork != null) ? Utils.ErrorCode.LOBBY_ALREADY_SEARCHING : Utils.ErrorCode.LOBBY_ALREADY_CREATING); } else { _joinTask = taskResult; _networkSettings = new PartyCSharpSDK.PARTY_NETWORK_CONFIGURATION(); _networkSettings.MaxDeviceCount = ((maxDevices == 0) ? maxUsers : maxDevices); _networkSettings.MaxDevicesPerUserCount = maxDevicesPerUser; _networkSettings.MaxEndpointsPerDeviceCount = ((maxEndpointsPerDevice == 0) ? maxUsers : maxEndpointsPerDevice); _networkSettings.MaxUserCount = maxUsers; _networkSettings.MaxUsersPerDeviceCount = ((maxUsersPerDevice == 0) ? maxUsers : maxUsersPerDevice); Utils.Debug.LogInfo("[PLAYFAB:NETWORK] CreateNetwork: Ready to create | Max: {0}", maxUsers); _localID = localID; _localUser = CS.Platform.Users.GetUserInfo(localID); _networkInfo = new NetworkInfo(); _networkInfo.hostInfo = _localUser; _networkInfo.userList = new Systems.User.UserInfo[maxUsers]; _networkInfo.timeStamp = System.DateTime.Now.Ticks; Utils.Debug.LogInfo("[PLAYFAB:NETWORK] CreateNetwork: Check setup | LocalID: {0}", _localID); if (!_manager.SetupNetwork(CreateNetwork)) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] CreateNetwork: Wait for setup"); return (taskResult); } CreateNetwork(); } } return (taskResult); } private void CreateNetwork() { lock (_manager.Locker) { lock (_locker) { _left = false; uint result = PartyCSharpSDK.SDK.PartyGetLocalDevice(_manager.PartyHandle, out _deviceHandle); if (PartyCSharpSDK.PartyError.FAILED(result)) { Utils.Debug.LogErro("[PLAYFAB:NETWORK] CreateNetwork: PartyGetLocalDevice failed | Result: {0} | Party: {1}", result, _manager.PartyHandle); PlayfabErrorLog.PrintErrorMessage(result); TriggerFailJoinPlayfab(result); return; } else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] CreateNetwork: PartyGetLocalDevice Complete | Result: {0} | Party: {1} | Device: {2}", result, _manager.PartyHandle, _deviceHandle); var partyInvitationConfiguration = new PartyCSharpSDK.PARTY_INVITATION_CONFIGURATION { Identifier = (System.String.IsNullOrEmpty(_forceIdent) ? System.Guid.NewGuid().ToString() : _forceIdent), Revocability = PartyCSharpSDK.PARTY_INVITATION_REVOCABILITY.PARTY_INVITATION_REVOCABILITY_ANYONE, EntityIds = null }; PartyCSharpSDK.PARTY_REGION[] regions = { }; _generatedInvitationId = string.Empty; result = PartyCSharpSDK.SDK.PartyCreateNewNetwork( _manager.PartyHandle, _manager.UserHandle, _networkSettings, regions, partyInvitationConfiguration, null, out _networkDescription, out _generatedInvitationId); if (PartyCSharpSDK.PartyError.FAILED(result)) { Utils.Debug.LogErro("[PLAYFAB:NETWORK] CreateNetwork: PartyCreateNewNetwork failed | Result: {0} | Party: {1} | User: {2}", result, _manager.PartyHandle, _manager.UserHandle); PlayfabErrorLog.PrintErrorMessage(result); TriggerFailJoinPlayfab(result); return; } else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] CreateNetwork: PartyCreateNewNetwork Complete | Result: {0} | NetworkIdentifier: {1} | RegionName: {2} | Invite: {3}", result, _networkDescription?.NetworkIdentifier, _networkDescription?.RegionName, _generatedInvitationId); result = PartyCSharpSDK.SDK.PartyConnectToNetwork( _manager.PartyHandle, _networkDescription, null, out _networkHandle); if (PartyCSharpSDK.PartyError.FAILED(result)) { Utils.Debug.LogErro("[PLAYFAB:NETWORK] CreateNetwork: PartyConnectToNetwork failed | Result: {0} | Party: {1} | Description: {2}", result, _manager.PartyHandle, _networkDescription); PlayfabErrorLog.PrintErrorMessage(result); TriggerFailJoinPlayfab(result); return; } else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] CreateNetwork: PartyConnectToNetwork Complete | Result: {0} | Party: {1} | Description: {2} | Handle: {3}", result, _manager.PartyHandle, _networkDescription, _networkHandle); _networkID = UpdateNetworkId(_generatedInvitationId, _networkDescription); Utils.Debug.LogInfo("[PLAYFAB:NETWORK] CreateNetwork: UpdateNetworkId | NetWork: {0} | InvitationId: {1}", _networkID, _generatedInvitationId); _networkInfo.hostInfo = CS.Platform.Users.GetUserInfo(_localID); } } } public TaskResult JoinNetwork(CS.Platform.Systems.User.LocalID localID, string networkID, TaskResult taskResult = null) { if (taskResult==null) taskResult = new TaskResult(); taskResult.Result = this; lock (_manager.Locker) { lock (_locker) { if (_joinTask != null) { Utils.Debug.LogErro("[PLAYFAB:NETWORK] JoinNetwork: Already active | Joining: {0}", _joinNetwork!=null); taskResult.Fail((_joinNetwork != null) ? Utils.ErrorCode.LOBBY_ALREADY_SEARCHING : Utils.ErrorCode.LOBBY_ALREADY_CREATING); } else { _joinTask = taskResult; _joinNetwork = networkID; _localID = localID; _localUser = CS.Platform.Users.GetUserInfo(localID); Utils.Debug.LogInfo("[PLAYFAB:NETWORK] JoinNetwork: Check setup"); if (!_manager.SetupNetwork(JoinNetwork)) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] JoinNetwork: Wait for setup"); return (taskResult); } Utils.Debug.LogInfo("[PLAYFAB:NETWORK] JoinNetwork: Ready to create"); JoinNetwork(); } } } return (taskResult); } private void JoinNetwork() { lock (_manager.Locker) { lock (_locker) { _left = false; uint result = PartyCSharpSDK.SDK.PartyGetLocalDevice(_manager.PartyHandle, out _deviceHandle); if (PartyCSharpSDK.PartyError.FAILED(result)) { Utils.Debug.LogErro("[PLAYFAB:NETWORK] JoinNetwork: PartyGetLocalDevice failed | Result: {0} | Party: {1}", result, _manager.PartyHandle); PlayfabErrorLog.PrintErrorMessage(result); TriggerFailJoinPlayfab(result); return; } else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] JoinNetwork: PartyGetLocalDevice Complete | Result: {0} | Party: {1} | Device: {2}", result, _manager.PartyHandle, _deviceHandle); _networkDescription = NetworkIdToDescriptor(_joinNetwork, out _generatedInvitationId); if (_networkDescription == null) { Utils.Debug.LogErro("[PLAYFAB:NETWORK] JoinNetwork: NetworkIdToDescriptor failed | Result: {0} | NetworkID: {1} | InvitationId: {2}", result, _forceIdent, _generatedInvitationId); PlayfabErrorLog.PrintErrorMessage(result); TriggerFailJoin(Utils.ErrorCode.INVALID_INPUT); return; } else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] JoinNetwork: Created description | NetworkIdentifier: {0} | RegionName: {1}", _networkDescription?.NetworkIdentifier, _networkDescription?.RegionName); result = PartyCSharpSDK.SDK.PartyConnectToNetwork( _manager.PartyHandle, _networkDescription, null, out _networkHandle); if (PartyCSharpSDK.PartyError.FAILED(result)) { if (result == 4102) { PartyCSharpSDK.PARTY_NETWORK_HANDLE[] allNetworks = null; result = PartyCSharpSDK.SDK.PartyGetNetworks(_manager.PartyHandle, out allNetworks); if (_networkDescription == null) { Utils.Debug.LogErro("[PLAYFAB:NETWORK] JoinNetwork: PartyGetNetworks failed | Result: {0} | NetworkID: {1} | InvitationId: {2}", result, _forceIdent, _generatedInvitationId); PlayfabErrorLog.PrintErrorMessage(result); TriggerFailJoinPlayfab(result); return; } else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] JoinNetwork: Got networks | NetworkIdentifier: {0} | RegionName: {1}", _networkDescription?.NetworkIdentifier, _networkDescription?.RegionName); for (int i = 0; i < (allNetworks?.Length ?? 0); i++) { if (EqualNetHandle(allNetworks[i], _networkDescription, true)) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] JoinNetwork: Found wanted network | Index: {0}", i); _networkHandle = allNetworks[i]; SetupLocalNetworkConnections(); return; } } Utils.Debug.LogErro("[PLAYFAB:NETWORK] JoinNetwork: Failed to find network | Count: {0}", (allNetworks?.Length ?? -1)); PlayfabErrorLog.PrintErrorMessage(result); TriggerFailJoin(Utils.ErrorCode.NOT_FOUND); return; } else { Utils.Debug.LogErro("[PLAYFAB:NETWORK] JoinNetwork: PartyConnectToNetwork failed | Result: {0} | Party: {1} | Description: {2}", result, _manager.PartyHandle, _networkID); PlayfabErrorLog.PrintErrorMessage(result); TriggerFailJoinPlayfab(result); return; } } else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] JoinNetwork: PartyConnectToNetwork Complete | Result: {0} | Party: {1} | Description: {2} | Handle: {3}", result, _manager.PartyHandle, _networkID, _networkHandle); } } } public TaskResult LeaveNetwork(TaskResult taskResult = null) { if (taskResult==null) taskResult = new TaskResult(); taskResult.Result = this; lock (_manager.Locker) { lock (_locker) { if (!_fullyJoinedNetwork || _left) { Utils.Debug.LogErro("[PLAYFAB:NETWORK] LeaveNetwork: Already left | State: {0} | Left: {1}", _fullyJoinedNetwork, _left); taskResult.Fail(Utils.ErrorCode.INVALID_SETUP); } else if (_leaveTask != null) { Utils.Debug.LogErro("[PLAYFAB:NETWORK] LeaveNetwork: Already leaving | State: {0} | Leaving: {1}", _fullyJoinedNetwork, (_leaveTask != null)); taskResult.Fail(Utils.ErrorCode.INVALID_SETUP); } else { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] LeaveNetwork: Start leaving | State: {0}", _fullyJoinedNetwork); _leaveTask = taskResult; uint result = PartyCSharpSDK.SDK.PartyNetworkLeaveNetwork(_networkHandle, null); if (PartyCSharpSDK.PartyError.FAILED(result)) Utils.Debug.LogErro("[PLAYFAB:NETWORK] LeaveNetwork: PartyNetworkLeaveNetwork failed | Result: {0} | Handle: {1} | NetID: {2}", result, _networkHandle, _networkID); else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] LeaveNetwork: PartyNetworkLeaveNetwork completed | Result: {0} | Handle: {1} | NetID: {2}", result, _networkHandle, _networkID); _leaving = true; } } } return (taskResult); } private void StartTimeout() { lock (_locker) { _timeoutCounter = 0; _timeoutTracker = new System.Timers.Timer(); _timeoutTracker.AutoReset = true; _timeoutTracker.Enabled = true; _timeoutTracker.Interval = TIMEOUT_TOTAL; _timeoutTracker.Elapsed += TimeoutPassed; _timeoutTracker.Start(); Utils.Debug.LogInfo("[PLAYFAB:NETWORK] StartTimeout: Started"); } } private void TimeoutPassed(object sender, System.Timers.ElapsedEventArgs e) { lock (_locker) { if (_timeoutTracker == null) Utils.Debug.LogInfo("[PLAYFAB:NETWORK] TimeoutPassed: No timer set"); else { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] TimeoutPassed: Timeout passed | Time: {0}", e.SignalTime); if (CheckCompletedJoining(true)) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] TimeoutPassed: Complated | Ticks: {0}", _timeoutCounter); StopTimeout(); } else { _timeoutCounter++; if ((2 <= _timeoutCounter) && (_playerCache?.Count < _timeoutCounter)) { Utils.Debug.LogErro("[PLAYFAB:NETWORK] TimeoutPassed: Lost player while joining and only me left so leave | Setup: {0} | Cache: {1} | Timeout: {2}", _setupCache.Count, _playerCache.Count, _timeoutCounter); uint result = PartyCSharpSDK.SDK.PartyNetworkLeaveNetwork(_networkHandle, null); if (PartyCSharpSDK.PartyError.FAILED(result)) Utils.Debug.LogErro("[PLAYFAB:NETWORK] TimeoutPassed: PartyNetworkLeaveNetwork failed | Result: {0} | Handle: {1} | NetID: {2}", result, _networkHandle, _networkID); else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] TimeoutPassed: PartyNetworkLeaveNetwork completed | Result: {0} | Handle: {1} | NetID: {2}", result, _networkHandle, _networkID); _leaving = true; TriggerFailJoin(Utils.ErrorCode.LOBBY_CONNECTION_LOST); } else { Utils.Debug.LogWarn("[PLAYFAB:NETWORK] TimeoutPassed: Timeout ticked warning | Ticks: {0} | Info: {1}", _timeoutCounter, (_networkInfo != null)); if (_infoData == null) RequestNetInfo(null); } } } } } private void StopTimeout() { if (_timeoutTracker != null) { _timeoutTracker.Enabled = false; _timeoutTracker.Dispose(); _timeoutTracker = null; Utils.Debug.LogInfo("[PLAYFAB:NETWORK] StopTimeout: Stopped"); } } private void OnCreated(PartyCSharpSDK.PARTY_CREATE_NEW_NETWORK_COMPLETED_STATE_CHANGE obj) { lock (_manager.Locker) { lock (_locker) { if (!EqualNetDescription(obj.networkDescriptor, _networkDescription, false)) return; if (PartyCSharpSDK.PartyError.FAILED(obj.errorDetail)) { Utils.Debug.LogErro("[PLAYFAB:NETWORK] OnCreated: Failed creating | Error: {0} | NetworkIdentifier: {1}", obj.errorDetail, _networkDescription?.NetworkIdentifier); TriggerFailJoinPlayfab(obj.errorDetail); return; } StartTimeout(); } } } private void OnConnected(PartyCSharpSDK.PARTY_CONNECT_TO_NETWORK_COMPLETED_STATE_CHANGE obj) { lock (_manager.Locker) { lock (_locker) { if (!EqualNetDescription(obj.networkDescriptor, _networkDescription, false)) return; if (PartyCSharpSDK.PartyError.FAILED(obj.errorDetail)) { Utils.Debug.LogErro("[PLAYFAB:NETWORK] OnConnected: Failed connecting | Error: {0} | NetworkIdentifier: {1}", obj.errorDetail, _networkDescription?.NetworkIdentifier); return; } _networkDescription = obj.networkDescriptor; Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnConnected: Updated network descriptor | NetworkIdentifier: {0} | RegionName: {1}", _networkDescription?.NetworkIdentifier, _networkDescription?.RegionName); SetupLocalNetworkConnections(); } } } private void SetupLocalNetworkConnections() { lock (_manager.Locker) { lock (_locker) { uint result = PartyCSharpSDK.SDK.PartyNetworkAuthenticateLocalUser(_networkHandle, _manager.UserHandle, _generatedInvitationId, null); if (PartyCSharpSDK.PartyError.FAILED(result)) { Utils.Debug.LogErro("[PLAYFAB:NETWORK] SetupLocalNetworkConnections: PartyNetworkAuthenticateLocalUser Failed | Result: {0} | NetWork: {1} | InvitationId: {2}", result, _networkHandle, _generatedInvitationId); PlayfabErrorLog.PrintErrorMessage(result); TriggerFailJoinPlayfab(result); return; } else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] SetupLocalNetworkConnections: PartyNetworkAuthenticateLocalUser Complete | Result: {0} | NetWork: {1} | InvitationId: {2}", result, _networkHandle, _generatedInvitationId); _networkID = UpdateNetworkId(_generatedInvitationId, _networkDescription); Utils.Debug.LogInfo("[PLAYFAB:NETWORK] SetupLocalNetworkConnections: UpdateNetworkId | NetWork: {0} | InvitationId: {1}", _networkID, _generatedInvitationId); result = PartyCSharpSDK.SDK.PartyNetworkCreateEndpoint(_networkHandle, _manager.UserHandle, null, null, out _localEndPointHandle); if (PartyCSharpSDK.PartyError.FAILED(result)) { Utils.Debug.LogErro("[PLAYFAB:NETWORK] SetupLocalNetworkConnections: PartyNetworkCreateEndpoint Failed | Result: {0} | NetWork: {1}", result, _networkHandle); PlayfabErrorLog.PrintErrorMessage(result); TriggerFailJoinPlayfab(result); return; } else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] SetupLocalNetworkConnections: PartyNetworkCreateEndpoint Complete | Result: {0} | NetWork: {1} | Endpoint: {2}", result, _networkHandle, _localEndPointHandle); } } } private void OnEndpointCreated(PartyCSharpSDK.PARTY_ENDPOINT_CREATED_STATE_CHANGE obj) { lock (_manager.Locker) { lock (_locker) { if (!EqualNetHandle(obj.network, _networkDescription, true)) return; string entityID = null; uint result = PartyCSharpSDK.SDK.PartyEndpointGetEntityId(obj.endpoint, out entityID); if (PartyCSharpSDK.PartyError.FAILED(result)) Utils.Debug.LogErro("[PLAYFAB:NETWORK] OnEndpointCreated: PartyEndpointGetEntityId Failed | Result: {0} | NetWork: {1}", result, _networkHandle); else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnEndpointCreated: PartyEndpointGetEntityId Complete | Result: {0} | NetWork: {1} | Entity: {2}", result, _networkHandle, entityID); bool isLocal = false; result = PartyCSharpSDK.SDK.PartyEndpointIsLocal(obj.endpoint, out isLocal); if (PartyCSharpSDK.PartyError.FAILED(result)) Utils.Debug.LogErro("[PLAYFAB:NETWORK] OnEndpointCreated: PartyEndpointIsLocal Failed | Result: {0} | NetWork: {1}", result, obj.endpoint); else { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnEndpointCreated: PartyEndpointIsLocal is result | Result: {0} | Local: {1}", result, isLocal); OnlinePlayer newPlayer = this[entityID, PLAYFAB_TITLE_ACCOUNT_TYPE]; bool isNew = true; if (newPlayer == null) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnEndpointCreated: new Player | Result: {0} | Local: {1} | Entity: {2}", result, isLocal, entityID); newPlayer = new OnlinePlayer(); newPlayer.titleEntity = new PlayFab.AuthenticationModels.EntityKey(); newPlayer.titleEntity.Id = entityID; newPlayer.titleEntity.Type = PLAYFAB_TITLE_ACCOUNT_TYPE; } else { isNew = false; Utils.Debug.LogWarn("[PLAYFAB:NETWORK] OnEndpointCreated: is old Player | Result: {0} | Local: {1} | Entity: {2}", result, isLocal, newPlayer.titleEntity); } newPlayer.isLocal = isLocal; newPlayer.endPoint = obj.endpoint; if (isNew) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnEndpointCreated: Player added | Result: {0} | Local: {1} | Entity: {2}", result, isLocal, newPlayer.titleEntity); _playerCache.Add(newPlayer); PlayFab.ProfilesModels.GetEntityProfileRequest req = new PlayFab.ProfilesModels.GetEntityProfileRequest(); var reqEntity = new PlayFab.ProfilesModels.EntityKey(); reqEntity.Id = newPlayer.titleEntity.Id; reqEntity.Type = newPlayer.titleEntity.Type; req.Entity = reqEntity; Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnEndpointCreated: Player joined network requesting info | ID: {0} | Type: {1}", req.Entity.Id, req.Entity.Type); PlayFab.PlayFabProfilesAPI.GetProfile(req, OnEntityProfileSuccess, OnProfileError); } else Utils.Debug.LogWarn("[PLAYFAB:NETWORK] OnEndpointCreated: old Player updated | Result: {0} | Local: {1} | Entity: {2}", result, isLocal, newPlayer.titleEntity); if (isLocal) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnEndpointCreated: Update network config | Result: {0} | NetWork: {1} | Current: {2}", result, _networkHandle, _networkSettings?.MaxDeviceCount); PartyCSharpSDK.PARTY_NETWORK_CONFIGURATION networkConfig = null; result = PartyCSharpSDK.SDK.PartyNetworkGetNetworkConfiguration(_networkHandle, out networkConfig); if (PartyCSharpSDK.PartyError.FAILED(result)) Utils.Debug.LogErro("[PLAYFAB:NETWORK] OnEndpointCreated: PartyNetworkGetNetworkConfiguration Failed | Result: {0} | NetWork: {1}", result, _networkHandle); else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnEndpointCreated: PartyNetworkGetNetworkConfiguration Complete | Result: {0} | NetWork: {1} | ChatController: {2}", result, _networkHandle, _localEndPointHandle); if (networkConfig == null) Utils.Debug.LogErro("[PLAYFAB:NETWORK] OnEndpointCreated: Config returned null | MaxDevices: {0} >> {1} | MaxUsers: {2} >> {3}", _networkSettings?.MaxDeviceCount, networkConfig?.MaxDeviceCount, _networkSettings?.MaxUserCount, networkConfig?.MaxUserCount); else if (_networkSettings != networkConfig) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnEndpointCreated: Config updated | MaxDevices: {0} >> {1} | MaxUsers: {2} >> {3}", _networkSettings?.MaxDeviceCount, networkConfig?.MaxDeviceCount, _networkSettings?.MaxUserCount, networkConfig?.MaxUserCount); _networkSettings = networkConfig; } else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnEndpointCreated: Config the same | MaxDevices: {0} >> {1} | MaxUsers: {2} >> {3}", _networkSettings?.MaxDeviceCount, networkConfig?.MaxDeviceCount, _networkSettings?.MaxUserCount, networkConfig?.MaxUserCount); } } } } } private void OnEntityProfileSuccess(PlayFab.ProfilesModels.GetEntityProfileResponse result) { lock (_manager.Locker) { lock (_locker) { if (result.Profile == null) Utils.Debug.LogErro("[PLAYFAB:NETWORK] OnEntityProfileSuccess: Player profile returned Null | Request: {0}", result.Request?.ToJson() ?? "NULL"); else { string playerID = result?.Profile?.Lineage?.TitlePlayerAccountId; string playfabID = result?.Profile?.Lineage?.MasterPlayerAccountId; if ((playerID == null) || (playfabID == null)) { Utils.Debug.LogErro("[PLAYFAB:NETWORK] OnEntityProfileSuccess: Failed to read profile IDs | TitleAccountID: {0} | MasterID: {1}", playerID, playfabID); } else { OnlinePlayer onlinePlayer = this[playerID, PLAYFAB_TITLE_ACCOUNT_TYPE]; if (onlinePlayer == null) Utils.Debug.LogErro("[PLAYFAB:NETWORK] OnEntityProfileSuccess: Player not wanted | TitleAccountID: {0} | MasterID: {1}", playerID, playfabID); else { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnEntityProfileSuccess: Requesting player profile | TitleAccountID: {0} | MasterID: {1}", playerID, playfabID); onlinePlayer.masterEntity = new PlayFab.AuthenticationModels.EntityKey(); onlinePlayer.masterEntity.Id = playfabID; onlinePlayer.masterEntity.Type = PLAYFAB_MASTER_ACCOUNT_TYPE; PlayFab.ClientModels.GetPlayerProfileRequest req = new PlayFab.ClientModels.GetPlayerProfileRequest(); PlayFab.ClientModels.PlayerProfileViewConstraints reqInfo = new PlayFab.ClientModels.PlayerProfileViewConstraints(); reqInfo.ShowDisplayName = true; reqInfo.ShowLinkedAccounts = true; reqInfo.ShowOrigination = true; req.ProfileConstraints = reqInfo; req.PlayFabId = playfabID; PlayFab.PlayFabClientAPI.GetPlayerProfile(req, OnProfileSuccess, OnProfileError); } } } } } } void OnProfileSuccess(PlayFab.ClientModels.GetPlayerProfileResult result) { lock (_manager.Locker) { lock (_locker) { if (result.PlayerProfile == null) Utils.Debug.LogErro("[PLAYFAB:NETWORK] OnProfileSuccess: Player profile returned Null | Player: {0}", result.PlayerProfile?.PlayerId ?? "NULL"); else { OnlinePlayer onlinePlayer = this[result.PlayerProfile.PlayerId, PLAYFAB_MASTER_ACCOUNT_TYPE]; if (onlinePlayer == null) Utils.Debug.LogWarn("[PLAYFAB:NETWORK] OnProfileSuccess: Player profile not wanted | Player: {0} | PublisherId: {1}", result.PlayerProfile?.PlayerId ?? "NULL", result.PlayerProfile?.PublisherId ?? "NULL"); else { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnProfileSuccess: Player profile returned | Player: {0}", result.PlayerProfile?.PlayerId ?? "NULL"); onlinePlayer.userInfo = AccountUtils.GetUserInfo(result.PlayerProfile); onlinePlayer.playfabProfile = result.PlayerProfile; if (_setupCache.Contains(onlinePlayer)) Utils.Debug.LogWarn("[PLAYFAB:NETWORK] OnProfileSuccess: Player already setup | Player: {0} | User: {1} | Display: {2}", result.PlayerProfile?.PlayerId ?? "NULL", onlinePlayer.userInfo, onlinePlayer.playfabProfile?.DisplayName); else { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnProfileSuccess: Player profile setup | Player: {0} | User: {1} | Display: {2}", result.PlayerProfile?.PlayerId ?? "NULL", onlinePlayer.userInfo, onlinePlayer.playfabProfile?.DisplayName); _setupCache.Add(onlinePlayer); _allPlayerCache?.LogPlayer(onlinePlayer.userInfo, onlinePlayer); onlinePlayer.localEndPoint = _localEndPointHandle; UpdatedInfo(Systems.User.UserInfo.INVALID_ID); if (CheckCompletedJoining(false)) OnPlayerJoined?.Invoke(this, onlinePlayer); else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnProfileSuccess: Not needed to trigger | Player: {0} | User: {1} | FullyJoined: {2}", result.PlayerProfile?.PlayerId ?? "NULL", onlinePlayer.userInfo, _fullyJoinedNetwork); } if (_networkInfo == null) RequestNetInfo(onlinePlayer); } } } } } void RequestNetInfo(OnlinePlayer onlinePlayer) { if (onlinePlayer?.isLocal ?? false) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] RequestNetInfo: Requesting from local finding other | IsLocal: {0}", onlinePlayer?.isLocal); onlinePlayer = null; } if (onlinePlayer == null) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] RequestNetInfo: Need to find a user to request | Players: {0}", _setupCache.Count); for (int i = 0; i<_setupCache.Count; i++) { if (!_setupCache[i].isLocal) { onlinePlayer = _setupCache[i]; break; } } } if (onlinePlayer==null) Utils.Debug.LogErro("[PLAYFAB:NETWORK] RequestNetInfo: No setup users to request | Players: {0}", _setupCache.Count); else { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] RequestNetInfo: Send network update request | Player: {0} | User: {1}", onlinePlayer.playfabProfile?.PlayerId ?? "NULL", onlinePlayer.userInfo); _eventData[0] = REQUEST_INFO; uint hresult = _manager.SendMetaMessage(onlinePlayer.localEndPoint, onlinePlayer.endPoint, PartyManager.NETWORK_UPDATE_MESSAGE, _eventData, 1, true); if (Utils.ErrorCode.IsError(hresult)) Utils.Debug.LogErro("[PLAYFAB:NETWORK] RequestNetInfo: Failed sending | Result: {0} | User: {1} | Title: {2}", hresult, onlinePlayer.userInfo, onlinePlayer.titleEntity.Id); else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] RequestNetInfo: Request sent | Targets: {0}", onlinePlayer.titleEntity.Id); } } void OnProfileError(PlayFab.PlayFabError req) { PlayfabErrorLog.LogErro("[PLAYFAB:NETWORK] OnProfileError: Player profile failed | ", req); } private void OnEndpointLost(PartyCSharpSDK.PARTY_ENDPOINT_DESTROYED_STATE_CHANGE obj) { lock (_manager.Locker) { lock (_locker) { if (!EqualNetHandle(obj.network, _networkDescription, true)) return; string entityID = null; uint result = PartyCSharpSDK.SDK.PartyEndpointGetEntityId(obj.endpoint, out entityID); if (PartyCSharpSDK.PartyError.FAILED(result)) Utils.Debug.LogErro("[PLAYFAB:NETWORK] OnEndpointLost: PartyEndpointGetEntityId Failed | Result: {0} | NetWork: {1}", result, _networkHandle); else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnEndpointLost: PartyEndpointGetEntityId Complete | Result: {0} | NetWork: {1} | Entity: {2}", result, _networkHandle, entityID); bool isLocal = false; result = PartyCSharpSDK.SDK.PartyEndpointIsLocal(obj.endpoint, out isLocal); if (PartyCSharpSDK.PartyError.FAILED(result)) Utils.Debug.LogErro("[PLAYFAB:NETWORK] OnEndpointLost: PartyEndpointIsLocal Failed | Result: {0} | NetWork: {1}", result, obj.endpoint); else { OnlinePlayer onlinePlayer = this[entityID, PLAYFAB_TITLE_ACCOUNT_TYPE]; if (onlinePlayer == null) Utils.Debug.LogWarn("[PLAYFAB:NETWORK] OnEndpointLost: Player profile not wanted | Player: {0}", entityID); else { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnEndpointLost: Player profile returned | Player: {0} | User: {1}", entityID, onlinePlayer.userInfo); _setupCache.Remove(onlinePlayer); _playerCache.Remove(onlinePlayer); _allPlayerCache?.RemovePlayer(onlinePlayer.userInfo, onlinePlayer); onlinePlayer.endPoint = null; if (!isLocal) UpdatedInfo(onlinePlayer.userInfo); if (_leaving) { if (!isLocal) Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnEndpointLost: no trigger as leaving | Player: {0} | User: {1} | FullyJoined: {2}", entityID, onlinePlayer.userInfo, _fullyJoinedNetwork); } else if (onlinePlayer.userInfo.IsValid() && CheckCompletedJoining(true)) OnPlayerLefted?.Invoke(this, onlinePlayer); else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnEndpointLost: Not needed to trigger | Player: {0} | User: {1} | FullyJoined: {2}", entityID, onlinePlayer.userInfo, _fullyJoinedNetwork); } if (isLocal) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnEndpointLost: Lost local connection leave complete | Player: {0} | User: {1} | FullyJoined: {2}", entityID, onlinePlayer.userInfo, _fullyJoinedNetwork); TriggerLeave(); } } } } } private void OnDescriptionChanged(PartyCSharpSDK.PARTY_NETWORK_DESCRIPTOR_CHANGED_STATE_CHANGE obj) { lock (_manager.Locker) { lock (_locker) { uint result = 0; PartyCSharpSDK.PARTY_NETWORK_DESCRIPTOR eventDesc = null; result = PartyCSharpSDK.SDK.PartyNetworkGetNetworkDescriptor(_networkHandle, out eventDesc); if (PartyCSharpSDK.PartyError.FAILED(result)) Utils.Debug.LogErro("[PLAYFAB:NETWORK] OnEndpointCreated: PartyNetworkGetNetworkDescriptor event Failed | Result: {0} | NetWork: {1}", result, _networkHandle); else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnEndpointCreated: PartyNetworkGetNetworkDescriptor event Complete | Result: {0} | NetWork: {1} | Description: {2}", result, _networkHandle, eventDesc); PartyCSharpSDK.PARTY_NETWORK_DESCRIPTOR myDesc = null; result = PartyCSharpSDK.SDK.PartyNetworkGetNetworkDescriptor(_networkHandle, out myDesc); if (PartyCSharpSDK.PartyError.FAILED(result)) Utils.Debug.LogErro("[PLAYFAB:NETWORK] OnEndpointCreated: PartyNetworkGetNetworkDescriptor my Failed | Result: {0} | NetWork: {1}", result, _networkHandle); else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnEndpointCreated: PartyNetworkGetNetworkDescriptor my Complete | Result: {0} | NetWork: {1} | Description: {2}", result, _networkHandle, myDesc); if (EqualNetDescription(eventDesc, myDesc)) { if (EqualNetDescription(myDesc, _networkDescription)) Utils.Debug.LogErro("[PLAYFAB:NETWORK] OnEndpointCreated: My changed but still same | Result: {0} | NetWork: {1}", result, _networkHandle); else { Utils.Debug.LogErro("[PLAYFAB:NETWORK] OnEndpointCreated: My changed force leave | Result: {0} | NetWork: {1}", result, _networkHandle); LeaveNetwork(); } } } } } private void OnLeave(PartyCSharpSDK.PARTY_LEAVE_NETWORK_COMPLETED_STATE_CHANGE obj) { lock (_manager.Locker) { lock (_locker) { if (!EqualNetHandle(obj.network, _networkDescription, true)) return; Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnLeave: Trigger leave | Left: {0} | NetworkID: {1}", _left, _networkID); TriggerLeave(); } } } private void OnDestroyed(PartyCSharpSDK.PARTY_NETWORK_DESTROYED_STATE_CHANGE obj) { lock (_manager.Locker) { lock (_locker) { if (!EqualNetHandle(obj.network, _networkDescription, true)) return; Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnDestroyed: Trigger leave | Left: {0} | NetworkID: {1}", _left, _networkID); TriggerLeave(); } } } void TriggerFailJoinPlayfab(uint playfabresult) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] TriggerFailJoinPlayfab: Trigger fail | Result: {0} | Task: {1}", playfabresult, _joinTask!=null); TriggerFailJoin(Utils.ErrorCode.PLATFORM_SDK); } void TriggerFailJoin(uint errorCode) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] TriggerFailJoin: Trigger fail | Result: {0} | Task: {1}", errorCode, _joinTask!=null); var task = _joinTask; _joinTask = null; task?.Fail(errorCode); ClearNetwork(true); } bool CheckCompletedJoining(bool lostPlayer) { lock (_manager.Locker) { lock (_locker) { if (_fullyJoinedNetwork) return (true); Utils.Debug.LogInfo("[PLAYFAB:NETWORK] CheckCompletedJoining: Checking complete | Setup: {0} | Cache: {1} | Info: {2}", _setupCache.Count, _playerCache.Count, (_networkInfo != null)); if ((_setupCache.Count == _playerCache.Count) && (_setupCache.Count!=0) && (_networkInfo != null)) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] CheckCompletedJoining: Trigger joined | Setup: {0} | Cache: {1}", _setupCache.Count, _playerCache.Count); _fullyJoinedNetwork = true; OnJoinedNetwork?.Invoke(this); Utils.Debug.LogInfo("[PLAYFAB:NETWORK] CheckCompletedJoining: Trigger joined task | Task: {0}", _joinTask != null); var task = _joinTask; _joinTask = null; task?.Complete(Utils.ErrorCode.NONE); StopTimeout(); if (_leaveTask!=null) { Utils.Debug.LogWarn("[PLAYFAB:NETWORK] CheckCompletedJoining: Leave task waiting leave"); uint result = PartyCSharpSDK.SDK.PartyNetworkLeaveNetwork(_networkHandle, null); if (PartyCSharpSDK.PartyError.FAILED(result)) Utils.Debug.LogErro("[PLAYFAB:NETWORK] CheckCompletedJoining: PartyNetworkLeaveNetwork failed | Result: {0} | Handle: {1} | NetID: {2}", result, _networkHandle, _networkID); else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] CheckCompletedJoining: PartyNetworkLeaveNetwork completed | Result: {0} | Handle: {1} | NetID: {2}", result, _networkHandle, _networkID); _leaving = true; } else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] CheckCompletedJoining: Finish joining | Network: {0}", _generatedInvitationId); } else { if ((lostPlayer) && (_playerCache.Count <= 1)) { if ((_playerCache.Count == 1) && (!_playerCache[0].isLocal)) { Utils.Debug.LogWarn("[PLAYFAB:NETWORK] CheckCompletedJoining: Lost player while joining and but last connection is not me | Setup: {0} | Cache: {1} | Info: {2}", _setupCache.Count, _playerCache.Count, (_networkInfo != null)); } else { Utils.Debug.LogErro("[PLAYFAB:NETWORK] CheckCompletedJoining: Lost player while joining and only me left so leave | Setup: {0} | Cache: {1} | Info: {2}", _setupCache.Count, _playerCache.Count, (_networkInfo != null)); uint result = PartyCSharpSDK.SDK.PartyNetworkLeaveNetwork(_networkHandle, null); if (PartyCSharpSDK.PartyError.FAILED(result)) Utils.Debug.LogErro("[PLAYFAB:NETWORK] CheckCompletedJoining: PartyNetworkLeaveNetwork failed | Result: {0} | Handle: {1} | NetID: {2}", result, _networkHandle, _networkID); else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] CheckCompletedJoining: PartyNetworkLeaveNetwork completed | Result: {0} | Handle: {1} | NetID: {2}", result, _networkHandle, _networkID); _leaving = true; TriggerFailJoin(Utils.ErrorCode.LOBBY_CONNECTION_LOST); } } else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] CheckCompletedJoining: still joining | Setup: {0} | Cache: {1} | Info: {2}", _setupCache.Count, _playerCache.Count, (_networkInfo != null)); } } } return (false); } void TriggerLeave() { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] TriggerLeave: running leave | Entered: {0} | Network: {1}", _fullyJoinedNetwork, _networkID); if (!_left) { _left = true; OnLeftNetwork?.Invoke(this); } var task = _joinTask; _joinTask = null; task?.Fail(Utils.ErrorCode.PLATFORM_SDK); task = _leaveTask; _leaveTask = null; _leaveTask?.Complete(Utils.ErrorCode.NONE); ClearNetwork(); } public OnlinePlayer this[Systems.User.UserInfo profile] { get { lock (_locker) { for (int i = 0; i<_playerCache.Count; i++) { if (_playerCache[i].userInfo == profile) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] this[UserInfo]: player found | UserInfo: {0}", profile); return (_playerCache[i]); } } } Utils.Debug.LogInfo("[PLAYFAB:NETWORK] this[UserInfo]: player not found | UserInfo: {0}", profile); return (null); } } public OnlinePlayer this[string entityid, string type] { get { lock (_locker) { switch (type) { case (PLAYFAB_MASTER_ACCOUNT_TYPE): for (int i = 0; i<_playerCache.Count; i++) { if (_playerCache[i].masterEntity.Id == entityid) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] this[entityid,type]: player found | Entity: {0} | Type: {1}", entityid, type); return (_playerCache[i]); } } break; case (PLAYFAB_TITLE_ACCOUNT_TYPE): for (int i = 0; i<_playerCache.Count; i++) { if (_playerCache[i].titleEntity.Id == entityid) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] this[entityid,type]: player found | Entity: {0} | Type: {1}", entityid, type); return (_playerCache[i]); } } break; default: Utils.Debug.LogInfo("[PLAYFAB:NETWORK] this[entityid,type]: Unknown type | Entity: {0} | Type: {1}", entityid, type); return (null); } Utils.Debug.LogInfo("[PLAYFAB:NETWORK] this[entityid,type]: player not found | Entity: {0} | Type: {1}", entityid, type); return (null); } } } public int GetUsers(ref System.Collections.Generic.List users) { if (users==null) users = new System.Collections.Generic.List(); lock (_locker) { if (_fullyJoinedNetwork) { users.AddRange(_setupCache); Utils.Debug.LogInfo("[PLAYFAB:NETWORK] GetUsers(OnlinePlayer): Added | Players: {0} | Setup: {1}", _playerCache.Count, _setupCache.Count); return (_setupCache.Count); } Utils.Debug.LogInfo("[PLAYFAB:NETWORK] GetUsers(OnlinePlayer): Not joined | Players: {0} | Setup: {1}", _playerCache.Count, _setupCache.Count); return (unchecked((int)Utils.ErrorCode.INVALID_SETUP)); } } public int GetUsers(ref System.Collections.Generic.List users) { if (users==null) users = new System.Collections.Generic.List(); lock (_locker) { if (_fullyJoinedNetwork) { for (int i = 0; i<_setupCache.Count; i++) { users.Add(_setupCache[i].userInfo); } Utils.Debug.LogInfo("[PLAYFAB:NETWORK] GetUsers(UserInfo): Added | Players: {0} | Setup: {1}", _playerCache.Count, _setupCache.Count); return (_setupCache.Count); } Utils.Debug.LogInfo("[PLAYFAB:NETWORK] GetUsers(UserInfo): Not joined | Players: {0} | Setup: {1}", _playerCache.Count, _setupCache.Count); return (unchecked((int)Utils.ErrorCode.INVALID_SETUP)); } } public string GetUserName(Systems.User.UserInfo userInfo) { lock (_locker) { return (this[userInfo]?.playfabProfile?.DisplayName ?? null); } } private void OnMessageEvent(PartyMessageEvent obj) { lock (_locker) { if ((obj.used) || (!EqualNetDescription(_networkDescription, obj.networkDescription))) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnMessageEvent: Don't check | Used: {0} | Left: {1} | Network: {2}", obj.used, _networkDescription?.NetworkIdentifier ?? "NULL"); return; } for (int i = 0; i<_playerCache.Count; i++) { if (_playerCache[i].titleEntity.Id == obj.senderEntity) { obj.senderInfo = _playerCache[i].userInfo; Utils.Debug.Log(Utils.Debug.Level.INFO | Utils.Debug.Level.SPAM, "[PLAYFAB:NETWORK] OnMessageEvent: Found sender | Index: {0} | User: {1}", i, _playerCache[i].userInfo); break; } } if (!obj.senderInfo.IsValid()) Utils.Debug.LogWarn("[PLAYFAB:NETWORK] OnMessageEvent: Unknown sender | Entity: {0}", obj.senderEntity); else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnMessageEvent: Sender | Sender: {0} | Key: {1}", obj.senderInfo, obj.dataRaw[0]); obj.triggerMain = false; switch (obj.dataRaw[0]) { case (PartyManager.NETWORK_UPDATE_MESSAGE): switch (obj.dataRaw[1]) { case (REQUEST_INFO): SendInfo(); break; case (SETUP_READY): default: break; } break; case (PartyManager.NETWORK_MESSAGE): try { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] OnMessageEvent: Network update"); NetworkInfo newInfo = null; uint result = Utils.Data.Deserialize(obj.dataRaw, out newInfo, 1); if (Utils.ErrorCode.IsError(result)) Utils.Debug.LogErro("[PLAYFAB:NETWORK] OnMessageEvent: Failed Deserialize | Result: {0}"); else CheckNetworkInfo(newInfo); } catch (System.Exception exc) { Utils.Debug.LogExce("[PLAYFAB:NETWORK] OnMessageEvent: Failed Deserialize | ", exc); } break; default: obj.triggerMain = true; break; } obj.used = true; } } private void CheckNetworkInfo(NetworkInfo newInfo) { lock (_locker) { if (newInfo == null) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] CheckNetworkInfo: New info null"); return; } if (newInfo.timeStamp <= (_networkInfo?.timeStamp ?? 0)) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] CheckNetworkInfo: New info old | Current: {0} | Old: {1}", (_networkInfo?.timeStamp ?? 0), newInfo.timeStamp); return; } Utils.Debug.LogInfo("[PLAYFAB:NETWORK] CheckNetworkInfo: New info | Time: {0} | Host: {1} | Users: {2}", newInfo.timeStamp, newInfo.hostInfo, newInfo.userList.Length); NetworkInfo oldInfo = _networkInfo; _networkInfo = newInfo; if ((Utils.Debug.ActiveLevel & (Utils.Debug.Level.DEEP | Utils.Debug.Level.INFO)) == (Utils.Debug.Level.DEEP | Utils.Debug.Level.INFO)) { string debugUsers = null; for (int i = 0; i<_networkInfo.userList.Length; i++) { if (_networkInfo.userList[i].IsValid()) debugUsers += (_networkInfo.userList[i].ToString() + " | "); } Utils.Debug.LogInfo("[PLAYFAB:NETWORK] CheckNetworkInfo: New info | Users: {0}", debugUsers); } if (CheckCompletedJoining(false)) { if (_networkInfo.hostInfo != (oldInfo?.hostInfo ?? Systems.User.UserInfo.INVALID_ID)) OnHostChanged?.Invoke(this); else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] CheckNetworkInfo: Host not changed | Users: {0}", _networkInfo?.hostInfo); } else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] CheckNetworkInfo: Not needed to trigger | Host: {0} | FullyJoined: {1}", _networkInfo?.hostInfo, _fullyJoinedNetwork); } } private void UpdatedInfo(Systems.User.UserInfo checkLost, bool send = true) { System.Action triggerEvent = null; lock (_locker) { if (_fullyJoinedNetwork) { if (checkLost == _networkInfo.hostInfo) { Systems.User.UserInfo expectedHost = Systems.User.UserInfo.INVALID_ID; for (int i = 0; i<_networkInfo.userList.Length; i++) { if ((_networkInfo.userList[i].IsValid()) && (_networkInfo.userList[i] != checkLost)) { expectedHost = _networkInfo.userList[i]; Utils.Debug.LogInfo("[PLAYFAB:NETWORK] UpdatedInfo: New host found | Host: {0} | Index: {1}", expectedHost, i); } } if (expectedHost == _localUser) { _networkInfo.hostInfo = expectedHost; Utils.Debug.LogInfo("[PLAYFAB:NETWORK] UpdatedInfo: I am now host | Host: {0}", _networkInfo.hostInfo); if (CheckCompletedJoining(false)) { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] UpdatedInfo: Trigger change | Host: {0}", _networkInfo.hostInfo); triggerEvent = OnHostChanged; } else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] CheckNetworkInfo: Waiting | Host: {0} | FullyJoined: {1}", _networkInfo.hostInfo, _fullyJoinedNetwork); if (send) SendInfo(); } } } } CS.Platform.Core.AddOffThreadAction(() => { triggerEvent?.Invoke(this); }); } private void SendInfo() { lock (_manager.Locker) { lock (_locker) { if (_networkInfo.hostInfo == _localUser) { _networkInfo.timeStamp = System.DateTime.Now.Ticks; Utils.Debug.LogInfo("[PLAYFAB:NETWORK] SendInfo: Updated time stamp | Time: {0}", _networkInfo.timeStamp); for (int i = 0; i<_networkInfo.userList.Length; i++) { if (i < _setupCache.Count) _networkInfo.userList[i] = _setupCache[i].userInfo; else _networkInfo.userList[i] = Systems.User.UserInfo.INVALID_ID; } Utils.Debug.LogInfo("[PLAYFAB:NETWORK] SendInfo: Updated user list | Users: {0}", _setupCache.Count); try { uint result = Utils.Data.Serialize(_networkInfo, out _infoData); if (Utils.ErrorCode.IsError(result)) Utils.Debug.LogErro("[PLAYFAB:NETWORK] SendInfo: Serialize Failed | Result: {0}", result); else { Utils.Debug.LogInfo("[PLAYFAB:NETWORK] SendInfo: Serialized data | Result: {0} | Amount: {1}", result , _infoData.Length); for (int i = 0; i<_playerCache.Count; i++) { result = _manager.SendMetaMessage(_playerCache[i].localEndPoint, _playerCache[i].endPoint, PartyManager.NETWORK_MESSAGE, _infoData, _infoData.Length, true); if (Utils.ErrorCode.IsError(result)) Utils.Debug.LogErro("[PLAYFAB:NETWORK] SendInfo: Failed sending | Result: {0} | User: {1} | Title: {2}", result, _playerCache[i].userInfo, _playerCache[i].titleEntity.Id); else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] SendInfo: Data sent | Targets: {0}", _playerCache[i].titleEntity.Id); } Utils.Debug.LogInfo("[PLAYFAB:NETWORK] SendInfo: Data sent | Targets: {0}", _playerCache.Count); } } catch (System.Exception exc) { Utils.Debug.LogExce("[PLAYFAB:NETWORK] SendInfo: Failed sending | ", exc); } } else Utils.Debug.LogInfo("[PLAYFAB:NETWORK] SendInfo: I am not host | Host: {0}", _networkInfo.hostInfo); } } } } }