public bool Equals(NakamaPlayer _player)
 {
     return((MatchID == _player.MatchID) &&
            (UserPresence.SessionId == _player.UserPresence.SessionId) &&
            (UserPresence.Username == _player.UserPresence.Username) &&
            (UserPresence.UserId == _player.UserPresence.UserId));
 }
        // -------------------------------------------

        /*
         * OnReceivedMatchPresence
         */
        private void OnReceivedMatchPresence(IMatchPresenceEvent _matchPresenceEvent)
        {
            if (DEBUG)
            {
                Debug.LogError("NakamaController::IMatchPresenceEvent::JOINS[" + _matchPresenceEvent.Joins.ToList().Count + "]");
            }

            // For each new user that joins, spawn a player for them.
            foreach (var user in _matchPresenceEvent.Joins)
            {
                RegisterPlayer(_matchPresenceEvent.MatchId, user);
            }

            // For each player that leaves, despawn their player.
            foreach (var user in _matchPresenceEvent.Leaves)
            {
                for (int i = 0; i < m_players.Count; i++)
                {
                    NakamaPlayer player = m_players[i];
                    if (player.UserPresence.SessionId == user.SessionId)
                    {
                        m_players.RemoveAt(i);
                        i--;
                    }
                }
            }
        }
        // -------------------------------------------

        /*
         * GetNakamaPlayer
         */
        private NakamaPlayer GetNakamaPlayer(string _userID)
        {
            for (int i = 0; i < m_players.Count; i++)
            {
                NakamaPlayer player = m_players[i];
                if (player.UserPresence.UserId == _userID)
                {
                    return(player);
                }
            }
            return(null);
        }
        // -------------------------------------------

        /*
         * SpawnPlayer
         *		<param name="matchId">The match the player is connected to.</param>
         *		<param name="user">The player's network presence data.</param>
         */
        private async void RegisterPlayer(string _matchId, IUserPresence _user)
        {
            if (DEBUG)
            {
                Debug.LogError("+++++++++++++++++++++++++++++++++++++++++++++REGISTERPLAYER::_user.UserId=" + _user.UserId);
            }

            NakamaPlayer newPlayer = new NakamaPlayer(_user.UserId, _matchId, _user);

            bool found = false;

            foreach (NakamaPlayer player in m_players)
            {
                if (player.Equals(newPlayer))
                {
                    found = true;
                }
            }

            if (!found)
            {
                m_players.Add(newPlayer);
            }

            if (m_isGameCreator)
            {
                if (m_players.Count == m_totalPlayers)
                {
                    if (DEBUG)
                    {
                        Debug.LogError("RegisterPlayer::SENDING UIDS");
                    }
                    await SendUIDsPlayers();
                }
            }
        }
        // -------------------------------------------

        /*
         * OnReceivedMatchState
         */
        private void OnProcessReceivedMatchState(string _userSessionId, long _opCode, string _matchStateData)
        {
            Dictionary <string, string> state = _matchStateData.Length > 0 ? _matchStateData.FromJson <Dictionary <string, string> >() : null;

            // Decide what to do based on the Operation Code as defined in OpCodes.
            switch (_opCode)
            {
            case OpCodes.AssignUID:
                BasicSystemEventController.Instance.ClearBasicSystemEvents(EVENT_NAKAMACONTROLLER_TIMEOUT_SEND_UIDS);
                foreach (KeyValuePair <string, string> playerUID in state)
                {
                    NakamaPlayer nakamaPlayer = GetNakamaPlayer(playerUID.Key);
                    if (nakamaPlayer != null)
                    {
                        nakamaPlayer.UID = int.Parse(playerUID.Value);
                        if (nakamaPlayer.Equals(m_localUser))
                        {
                            m_uid = nakamaPlayer.UID;
                            if (DEBUG)
                            {
                                Debug.LogError("+++++++++++++++++++ASSIGNED UID[" + m_uid + "]");
                            }
                        }
                    }
                }
                BasicSystemEventController.Instance.DelayBasicSystemEvent(NakamaController.EVENT_NAKAMACONTROLLER_GAME_STARTED, 0.1f + (m_uid * 0.2F));
                break;

            case OpCodes.Message:
                string eventName = "";
                state.TryGetValue(MatchDataJson.EVENTNAME_KEY, out eventName);
                string origin = "";
                state.TryGetValue(MatchDataJson.ORIGIN_KEY, out origin);
                string target = "";
                state.TryGetValue(MatchDataJson.TARGET_KEY, out target);
                string data = "";
                state.TryGetValue(MatchDataJson.DATA_KEY, out data);

                // Debug.LogError("+++++++++++++++++++MESSAGE RECEIVED::eventName[" + eventName + "]::data["+ data + "]");

                if (eventName.Length > 0)
                {
                    string[] paramData = data.Split(ClientTCPEventsController.TOKEN_SEPARATOR_EVENTS);
                    NetworkEventController.Instance.DispatchCustomNetworkEvent(eventName, true, int.Parse(origin), int.Parse(target), paramData);
                }
                break;

            case OpCodes.Transform:
                string netid = "";
                state.TryGetValue(MatchDataJson.NETID_KEY, out netid);
                string uid = "";
                state.TryGetValue(MatchDataJson.UID_KEY, out uid);
                string indexPrefab = "";
                state.TryGetValue(MatchDataJson.INDEX_KEY, out indexPrefab);
                string position = "";
                state.TryGetValue(MatchDataJson.POSITION_KEY, out position);
                string rotation = "";
                state.TryGetValue(MatchDataJson.ROTATION_KEY, out rotation);
                string scale = "";
                state.TryGetValue(MatchDataJson.SCALE_KEY, out scale);

                NetworkEventController.Instance.DispatchLocalEvent(ClientTCPEventsController.EVENT_CLIENT_TCP_TRANSFORM_DATA, int.Parse(netid), int.Parse(uid), int.Parse(indexPrefab), Utilities.StringToVector3(position), Utilities.StringToVector3(rotation), Utilities.StringToVector3(scale));
                break;

            default:
                break;
            }
        }