From 920ea3fba9510b87e17dbc78d611715c382f9e39 Mon Sep 17 00:00:00 2001 From: Jonas Date: Tue, 12 Apr 2022 11:38:40 +0200 Subject: [PATCH] Implemented broadcast to all clients across lobbies (/b), other small changes to chat & leaving lobbies: -bugfix for LEAVL -/c now defaults to message within lobby -broadcast chat to lobby when called by someone outside lobby just broadcasts to all clients not in lobbies --- .../multiplayer/client/MessageFormatter.java | 14 +++++++++---- .../cs108/multiplayer/helpers/Protocol.java | 9 +++++++++ .../multiplayer/server/ClientHandler.java | 20 ++++++++++++------- .../server/JServerProtocolParser.java | 3 +++ .../unibas/dmi/dbis/cs108/sebaschi/Lobby.java | 6 +++++- 5 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/MessageFormatter.java b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/MessageFormatter.java index c72cd7a..066b7a1 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/MessageFormatter.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/MessageFormatter.java @@ -11,8 +11,8 @@ public class MessageFormatter { public static final BudaLogConfig l = new BudaLogConfig(LOGGER); /** - * Takes a given Message and reformats it to where the JServerProtocolParser.parse() method can - * handle it (see Protocol.java). May need to be redesigned once the games uses a GUI + * Takes a given client input and reformats it to where the JServerProtocolParser.parse() method can + * handle it (see Protocol.java). May need to be redesigned once the game uses a GUI. * * @param msg the Messaged to be reformatted * @return the reformatted message in the form HEADR$msg @@ -29,6 +29,14 @@ public class MessageFormatter { } switch (header) { case "/c": + stringBuilder.append(Protocol.chatMsgToLobby + "$"); + try { + s = msg.substring(3); + } catch (Exception e) { + System.out.println("You didn't even write a chat line, you silly billy!"); + } + break; + case "/b": stringBuilder.append(Protocol.chatMsgToAll + "$"); try { s = msg.substring(3); @@ -49,10 +57,8 @@ public class MessageFormatter { } break; case "/g": - //CRTGM command stringBuilder.append(Protocol.createNewLobby + "$"); s = ""; //command has no parameters - //TODO add LOGGER msg. Find out if .info or .debug. break; case "/l": //LISTL command diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/helpers/Protocol.java b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/helpers/Protocol.java index 73c0e32..1c18590 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/helpers/Protocol.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/helpers/Protocol.java @@ -41,6 +41,15 @@ public class Protocol { */ public static final String chatMsgToAll = "CHATA"; + /** + * When the server receives this, it broadcasts a chat message to all clients in the same Lobby. + * The message has to be given in the protocol message after {@code CHATL$}, for example the protocol message {@code + * CHATL$Hello everybody!}, if sent from the user named Poirot, will print {@code Poirot: Hello + * everybody!} to the chat console of every client in the lobby (note the absence / presence of spaces). + * If the client is not in a lobby, the chat message will be sent to everyone not in a lobby. + */ + public static final String chatMsgToLobby = "CHATL"; + /** * The message sent by the client on login to set their name. For example, {@code LOGIN$Poirot} * will use the clientHandler.setUsernameOnLogin() method to set this client's username to Poirot, diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/server/ClientHandler.java b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/server/ClientHandler.java index def8fef..47b4b53 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/server/ClientHandler.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/server/ClientHandler.java @@ -162,7 +162,7 @@ public class ClientHandler implements Runnable { /** * Broadcasts a chat Message to all clients in the same lobby in the form "Username: @msg" - * If this client isn't in a lobby, it instead defers the message to broadcastChatMessageToAll + * If this client isn't in a lobby, it instead sends the message to everyone not in a lobby * @param msg the Message to be broadcast */ public void broadcastChatMessageToLobby(String msg) { @@ -172,9 +172,12 @@ public class ClientHandler implements Runnable { client.sendMsgToClient(Protocol.printToClientChat + "$" + clientUserName + ": " + msg); } } else { - LOGGER.debug("Could not send chat message; probably client isn't in a lobby." - + "Will broadcast across all lobbies now."); - broadcastChatMessageToAll(msg); + //send msg to all clients who are not in a lobby. + for (ClientHandler client: connectedClients) { + if (Lobby.clientIsInLobby(client) == -1) { + client.sendMsgToClient(Protocol.printToClientChat + "$" + clientUserName + ": " + msg); + } + } } } @@ -207,6 +210,7 @@ public class ClientHandler implements Runnable { * Broadcasts a non-chat Message to all clients in the same lobby. This can be used for server messages / * announcements rather than chat messages. The message will be printed to the user exactly as it * is given to this method. The announcement will not be printed on the server console. + * If this clienthandler is not in a lobby, it will instead broadcast to all clients. * * @param msg the Message to be broadcast. Does not have to be protocol-formatted, this method will take care of that. */ @@ -307,9 +311,11 @@ public class ClientHandler implements Runnable { } public void leaveLobby() { - for (Lobby l : Lobby.lobbies) { - boolean b = l.removePlayer(this); - if (b) broadcastAnnouncementToAll(this.getClientUserName() + " has left lobby nr. " + l.getLobbyID()); + Lobby l = Lobby.getLobbyFromID(Lobby.clientIsInLobby(this)); + if (l != null) { + l.removePlayer(this); + } else { + sendMsgToClient(Protocol.printToClientConsole + "$Unable to leave lobby."); } } diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/server/JServerProtocolParser.java b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/server/JServerProtocolParser.java index e12d3ce..b42e1da 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/server/JServerProtocolParser.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/server/JServerProtocolParser.java @@ -35,6 +35,9 @@ public class JServerProtocolParser { } switch (header) { case Protocol.chatMsgToAll: + h.broadcastChatMessageToAll(msg.substring(6)); + break; + case Protocol.chatMsgToLobby: h.broadcastChatMessageToLobby(msg.substring(6)); break; case Protocol.clientLogin: diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/sebaschi/Lobby.java b/src/main/java/ch/unibas/dmi/dbis/cs108/sebaschi/Lobby.java index 18ce3cf..f24bfb0 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/sebaschi/Lobby.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/sebaschi/Lobby.java @@ -145,9 +145,13 @@ public class Lobby { public synchronized boolean removePlayer(ClientHandler player) { //if the player who leaves the lobby is the admin, the lobby is closed. if (player.equals(getAdmin())) { + ClientHandler.broadcastAnnouncementToAll(player.getClientUserName() + " has closed lobby nr. " + this.getLobbyID()); closeLobby(); + } else if (this.getLobbyClients().remove(player)){ + ClientHandler.broadcastAnnouncementToAll(player.getClientUserName() + " has left lobby nr. " + this.getLobbyID()); + return true; } - return this.getLobbyClients().remove(player); + return false; } /**