private void SendPeerJoinedNotification(PeerJoinedNotification notification)
        {
            IMessage response;

            if (IsHost)
            {
                var resp = new HostWithinLobbyResponse();
                resp.PeerJoinedNotification = notification;
                response = resp;
            }
            else
            {
                var resp = new PeerWithinLobbyResponse();
                resp.PeerJoinedNotification = notification;
                response = resp;
            }
            response.WriteDelimitedTo(stream);
        }
        public IMessage ReceiveWithoutLobbyRequest()
        {
            // so, this happens in 2 cases:
            // 1. either a state has been changed, which would rerun the loop condition and
            //    it would exit into the main loop;
            // 2. or it were not, in which case the reading of stream failed.
            //    Either invalid data has been received or the client has diconnected.
            //    This is also checked in the while conditon.
            // UDPATE: the client.Connected property does not reflect the fact whether the
            //         client is connected. However, the stream does get closed when the connection dies down.
            if (!TryGetMessageOrStateChange(out WithoutLobbyRequest request))
            {
                return(null);
            }

            switch (request.MessageCase)
            {
            // TODO: do stuff with the password
            case CreateLobbyRequest:
            {
                Log("Creating a new lobby...");
                CreateLobbyResponse response = new CreateLobbyResponse();
                if (server.TryCreateLobby(id, out Lobby lobby) && lobby.TryJoin(this))
                {
                    Log($"Creating a new lobby {lobby.id}");
                    joined_lobby     = lobby;
                    response.LobbyId = lobby.id;
                    state            = Tcp_State.HostWithinLobby;
                }
                return(response);
            }

            case JoinLobbyRequest:
            {
                Log($"Joining lobby {request.JoinLobbyRequest.LobbyId}...");
                JoinLobbyResponse response = new JoinLobbyResponse();
                if (server.lobbies.TryGetValue(request.JoinLobbyRequest.LobbyId, out Lobby lobby) &&
                    lobby.TryJoin(this))
                {
                    Log($"Joined lobby {request.JoinLobbyRequest.LobbyId}.");
                    joined_lobby       = lobby;
                    response.LobbyInfo = lobby.GetInfo();
                    state = Tcp_State.PeerWithinLobby;

                    // notify other peers
                    var peer_joined_notification = new PeerJoinedNotification();
                    peer_joined_notification.PeerId = id;

                    foreach (var peer_id in lobby.peers.Keys)
                    {
                        if (peer_id != id)
                        {
                            lobby.peers[peer_id].SendPeerJoinedNotification(peer_joined_notification);
                        }
                    }
                }
                return(response);
            }

            case MyAddressInfoRequest:
            {
                Log($"Sending address info message.");
                return(CreateAddressMessage());
            }

            default:
                Log($"Unexpected WithoutLobby request message. {request}");
                return(null);
            }
        }
 private void AddPeerToLobby(PeerJoinedNotification peer_joined_notification)
 {
     joined_lobby.PeerIds.Add(peer_joined_notification.PeerId);
     PeerJoinedEvent?.Invoke();
 }