Merge remote-tracking branch 'origin/SerainaGui' into SerainaGui

This commit is contained in:
Seraina 2022-04-17 15:11:28 +02:00
commit dad2cf1cd8
4 changed files with 97 additions and 122 deletions

View File

@ -54,13 +54,14 @@ public class ChatController implements Initializable {
public ChatController() { //TODO: why does this get called public ChatController() { //TODO: why does this get called
super(); super();
whisperTargetChosen = new SimpleBooleanProperty(); whisperTargetChosen = new SimpleBooleanProperty();
cmd = "CHATA$"; cmd = "";
LOGGER.info("ChatController empty constructor used");
} }
public ChatController(ClientModel c) { public ChatController(ClientModel c) {
client = c; client = c;
whisperTargetChosen = new SimpleBooleanProperty(); whisperTargetChosen = new SimpleBooleanProperty();
cmd = "CHATA"; cmd = "";
LOGGER.info("ChatController single parameter constructor used");
} }
@ -138,7 +139,7 @@ public class ChatController implements Initializable {
Boolean newValue) { Boolean newValue) {
//is true if {@code whisperTargetSelectedField} has content //is true if {@code whisperTargetSelectedField} has content
if (!newValue) { if (!newValue) {
cmd = whisper + "$"; cmd = whisper + "$" + whisperTargetSelectField.getText() + "$";
} else { } else {
cmd = chatToLobby + "$"; cmd = chatToLobby + "$";
} }

View File

@ -117,10 +117,10 @@ public class ClientHandler implements Runnable {
} }
/** /**
* Lets the client change their username, if the username is already taken, a similar option is * Lets the client change their username, if the username is already taken, a similar option is
* chosen. * chosen.
*
* @param newName The desired new name to replace the old one with. * @param newName The desired new name to replace the old one with.
*/ */
public void changeUsername(String newName) { public void changeUsername(String newName) {
@ -129,7 +129,7 @@ public class ClientHandler implements Runnable {
sendMsgToClient(Protocol.changedUserName + "$" + newName); sendMsgToClient(Protocol.changedUserName + "$" + newName);
broadcastAnnouncementToAll(helper + " has changed their nickname to " + clientUserName); broadcastAnnouncementToAll(helper + " has changed their nickname to " + clientUserName);
try { try {
getLobby().getGame().getGameState().changeUsername(helper,newName); getLobby().getGame().getGameState().changeUsername(helper, newName);
} catch (NullPointerException e) { } catch (NullPointerException e) {
} }
} }
@ -153,8 +153,8 @@ public class ClientHandler implements Runnable {
} }
/** /**
* Returns the Lobby this ClientHandler is in. If this ClientHandler is not in a Lobby, * Returns the Lobby this ClientHandler is in. If this ClientHandler is not in a Lobby, it returns
* it returns null. * null.
*/ */
public Lobby getLobby() { public Lobby getLobby() {
try { try {
@ -165,8 +165,9 @@ public class ClientHandler implements Runnable {
} }
/** /**
* Broadcasts a chat Message to all clients in the same lobby in the form "Username: @msg" * Broadcasts a chat Message to all clients in the same lobby in the form "Username: @msg" If this
* If this client isn't in a lobby, it instead sends the message to everyone not in a lobby * client isn't in a lobby, it instead sends the message to everyone not in a lobby
*
* @param msg the Message to be broadcast * @param msg the Message to be broadcast
*/ */
public void broadcastChatMessageToLobby(String msg) { public void broadcastChatMessageToLobby(String msg) {
@ -177,7 +178,7 @@ public class ClientHandler implements Runnable {
} }
} else { } else {
//send msg to all clients who are not in a lobby. //send msg to all clients who are not in a lobby.
for (ClientHandler client: connectedClients) { for (ClientHandler client : connectedClients) {
if (Lobby.clientIsInLobby(client) == -1) { if (Lobby.clientIsInLobby(client) == -1) {
client.sendMsgToClient(Protocol.printToClientChat + "$" + clientUserName + ": " + msg); client.sendMsgToClient(Protocol.printToClientChat + "$" + clientUserName + ": " + msg);
} }
@ -200,8 +201,9 @@ public class ClientHandler implements Runnable {
} }
/** /**
* Broadcasts a chat Message to all clients across all lobbies & clients who are not in a lobby * Broadcasts a chat Message to all clients across all lobbies & clients who are not in a lobby in
* in the form "Username: @msg" * the form "Username: @msg"
*
* @param msg the Message to be broadcast * @param msg the Message to be broadcast
*/ */
public void broadcastChatMessageToAll(String msg) { public void broadcastChatMessageToAll(String msg) {
@ -213,9 +215,11 @@ public class ClientHandler implements Runnable {
/** /**
* Broadcasts a non-chat Message to all active clients. This can be used for server messages / * Broadcasts a non-chat Message to all active clients. This can be used for server messages /
* announcements rather than chat messages. The message will be printed to the user exactly as it * announcements rather than chat messages. The message will be printed to the user exactly as it
* is given to this method. Unlike eg. broadcastChatMessageToLobby, it will also be printed onto the server * is given to this method. Unlike eg. broadcastChatMessageToLobby, it will also be printed onto
* console. * the server console.
* @param msg the Message to be broadcast. Does not have to be protocol-formatted, this method will take care of that. *
* @param msg the Message to be broadcast. Does not have to be protocol-formatted, this method
* will take care of that.
*/ */
public static void broadcastAnnouncementToAll(String msg) { public static void broadcastAnnouncementToAll(String msg) {
System.out.println(msg); System.out.println(msg);
@ -225,12 +229,13 @@ public class ClientHandler implements Runnable {
} }
/** /**
* Broadcasts a non-chat Message to all clients in the same lobby. This can be used for server messages / * Broadcasts a non-chat Message to all clients in the same lobby. This can be used for server
* announcements rather than chat messages. The message will be printed to the user exactly as it * messages / announcements rather than chat messages. The message will be printed to the user
* is given to this method. The announcement will not be printed on the server console. * exactly as it is given to this method. The announcement will not be printed on the server
* If this clienthandler is not in a lobby, it will instead broadcast to all clients. * 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. * @param msg the Message to be broadcast. Does not have to be protocol-formatted, this method
* will take care of that.
*/ */
public void broadcastAnnouncementToLobby(String msg) { public void broadcastAnnouncementToLobby(String msg) {
Lobby l = getLobby(); Lobby l = getLobby();
@ -247,13 +252,17 @@ public class ClientHandler implements Runnable {
} }
/** /**
* Sends a message only to the specified user, as well as sending a confirmation to the user who sent the message * Sends a message only to the specified user, as well as sending a confirmation to the user who
* that it has been sent. Syntax: * sent the message that it has been sent. Syntax:
*
* @param target MUST NOT BE NULL! * @param target MUST NOT BE NULL!
*/ */
public void whisper(String msg, ClientHandler target) { public void whisper(String msg, ClientHandler target) {
target.sendMsgToClient(Protocol.printToClientChat + "$" + this.getClientUserName() + " whispers: " + msg); target.sendMsgToClient(
sendMsgToClient(Protocol.printToClientChat + "$You whispered to " + target.getClientUserName() + ": " + msg); Protocol.printToClientChat + "$" + this.getClientUserName() + " whispers: " + msg);
sendMsgToClient(
Protocol.printToClientChat + "$You whispered to " + target.getClientUserName() + ": "
+ msg);
} }
/** /**
@ -276,34 +285,56 @@ public class ClientHandler implements Runnable {
} }
/** /**
* Takes a msg of the form position$vote and extracts vote and position from it and saves it * Decode a whisper mesage
* in VoteHandler.getClientVoteData *
* @param msg the messaged to decode * @param msg to decode. the command has been removed from the front
* @return a String[] containing the target at index 0 and the message at index 1.
*/ */
public void decodeVote(String msg){ public String[] decodeWhisper(String msg) {
int msgIndex = msg.indexOf('$');
String target = "";
String chatMsg = "";
LOGGER.debug("incoming whisper to decode is:" + msg);
try {
target = msg.substring(0, msgIndex);
chatMsg = msg.substring(msgIndex + 1);
LOGGER.debug("whisper target is: " + target);
LOGGER.debug("whisper chatMsg is: " + chatMsg);
} catch (Exception e) {
LOGGER.warn("decode whisper issue: " + e.getMessage());
}
return new String[]{target, chatMsg};
}
/**
* Takes a msg of the form position$vote and extracts vote and position from it and saves it in
* VoteHandler.getClientVoteData
*
* @param msg the messaged to decode
*/
public void decodeVote(String msg) {
int msgIndex = msg.indexOf('$'); int msgIndex = msg.indexOf('$');
int vote = Integer.MAX_VALUE; int vote = Integer.MAX_VALUE;
int position = 0; int position = 0;
LOGGER.debug("Message is " + msg); LOGGER.debug("Message is " + msg);
try { try {
position = Integer.parseInt(msg.substring(0,msgIndex)); position = Integer.parseInt(msg.substring(0, msgIndex));
vote = Integer.parseInt(msg.substring(msgIndex + 1)); vote = Integer.parseInt(msg.substring(msgIndex + 1));
LOGGER.debug("Vote is:" + vote); LOGGER.debug("Vote is:" + vote);
} catch (Exception e) { } catch (Exception e) {
LOGGER.warn("Invalid vote " + e.getMessage()); LOGGER.warn("Invalid vote " + e.getMessage());
} }
LOGGER.debug("Vote is:" + vote); LOGGER.debug("Vote is:" + vote);
if(vote != Integer.MAX_VALUE) { //gets MAX_VALUE when the vote wasn't valid if (vote != Integer.MAX_VALUE) { //gets MAX_VALUE when the vote wasn't valid
getLobby().getGame().getGameState().getClientVoteData().setVote(position,vote); getLobby().getGame().getGameState().getClientVoteData().setVote(position, vote);
LOGGER.debug("Player vote: " + vote); LOGGER.debug("Player vote: " + vote);
getLobby().getGame().getGameState().getClientVoteData().setHasVoted(position,true); getLobby().getGame().getGameState().getClientVoteData().setHasVoted(position, true);
} }
} }
/** /**
* Initializes a new Game instance and starts its run method in a new thread. * Initializes a new Game instance and starts its run method in a new thread. Puts the game in the
* Puts the game in the corresponding lobby. Only the admin of this lobby can start a new * corresponding lobby. Only the admin of this lobby can start a new game.
* game.
*/ */
public void startNewGame() { public void startNewGame() {
try { try {
@ -329,9 +360,9 @@ public class ClientHandler implements Runnable {
} }
/** /**
* Sends an announcement to just this client. Essentially the same as broadcastAnnouncementToAll except * Sends an announcement to just this client. Essentially the same as broadcastAnnouncementToAll
* it only sends an announcement to just this client instead of everyone. * except it only sends an announcement to just this client instead of everyone. Can be used for
* Can be used for private non-chat messages (e.g. "You are now a ghost"). * private non-chat messages (e.g. "You are now a ghost").
*/ */
public void sendAnnouncementToClient(String msg) { public void sendAnnouncementToClient(String msg) {
sendMsgToClient(Protocol.printToClientConsole + "$" + msg); sendMsgToClient(Protocol.printToClientConsole + "$" + msg);
@ -348,7 +379,8 @@ public class ClientHandler implements Runnable {
connectedClients.remove(this); connectedClients.remove(this);
disconnectClient(); disconnectClient();
leaveLobby(); leaveLobby();
broadcastAnnouncementToAll(getClientUserName() + " has left the server due to a connection loss."); broadcastAnnouncementToAll(
getClientUserName() + " has left the server due to a connection loss.");
disconnectedClients.add(this); disconnectedClients.add(this);
} }
@ -378,7 +410,9 @@ public class ClientHandler implements Runnable {
} }
/** /**
* The client wants to join the lobby with the index i. If the lobby is closed, the client will be notified. * The client wants to join the lobby with the index i. If the lobby is closed, the client will be
* notified.
*
* @param i the number of the lobby to join * @param i the number of the lobby to join
*/ */
public void joinLobby(int i) { public void joinLobby(int i) {
@ -387,7 +421,8 @@ public class ClientHandler implements Runnable {
if (l.getLobbyIsOpen()) { if (l.getLobbyIsOpen()) {
l.addPlayer(this); l.addPlayer(this);
} else { } else {
sendAnnouncementToClient("The game in Lobby " + l.getLobbyID() + " has already started, or the lobby is already full."); sendAnnouncementToClient("The game in Lobby " + l.getLobbyID()
+ " has already started, or the lobby is already full.");
} }
} else { } else {
sendAnnouncementToClient("Invalid Lobby nr."); sendAnnouncementToClient("Invalid Lobby nr.");
@ -404,7 +439,7 @@ public class ClientHandler implements Runnable {
if (l != null) { if (l != null) {
l.removePlayer(this); l.removePlayer(this);
Game game = l.getGame(); Game game = l.getGame();
if(game != null) { if (game != null) {
l.getGame().getGameState().handleClientDisconnect(this); l.getGame().getGameState().handleClientDisconnect(this);
} }
} }
@ -412,8 +447,8 @@ public class ClientHandler implements Runnable {
/** /**
* Lists all lobbies and their members, along with players outside lobbies * Lists all lobbies and their members, along with players outside lobbies to this clientHandler's
* to this clientHandler's client as an announcement. * client as an announcement.
*/ */
public void listLobbies() { public void listLobbies() {
if (Lobby.lobbies.isEmpty()) { if (Lobby.lobbies.isEmpty()) {
@ -421,7 +456,7 @@ public class ClientHandler implements Runnable {
} else { } else {
for (Lobby l : Lobby.lobbies) { for (Lobby l : Lobby.lobbies) {
String lobbyStatus = "closed"; String lobbyStatus = "closed";
if(l.getLobbyIsOpen()) { if (l.getLobbyIsOpen()) {
lobbyStatus = "open"; lobbyStatus = "open";
} }
sendAnnouncementToClient("Lobby nr. " + l.getLobbyID() + ": (" + lobbyStatus + ")"); sendAnnouncementToClient("Lobby nr. " + l.getLobbyID() + ": (" + lobbyStatus + ")");
@ -435,7 +470,7 @@ public class ClientHandler implements Runnable {
} }
} }
boolean helper = false; //used to print "Clients not in lobbies" only once, if needed. boolean helper = false; //used to print "Clients not in lobbies" only once, if needed.
for (ClientHandler c: connectedClients) { for (ClientHandler c : connectedClients) {
if (Lobby.clientIsInLobby(c) == -1) { if (Lobby.clientIsInLobby(c) == -1) {
if (!helper) { if (!helper) {
helper = true; helper = true;
@ -450,8 +485,8 @@ public class ClientHandler implements Runnable {
} }
/** /**
* Lists all players in the client's lobby. If the client is not in a Lobby, it will say * Lists all players in the client's lobby. If the client is not in a Lobby, it will say "You are
* "You are not in a lobby." * not in a lobby."
*/ */
public void listPlayersInLobby() { public void listPlayersInLobby() {
Lobby l = getLobby(); Lobby l = getLobby();
@ -470,7 +505,8 @@ public class ClientHandler implements Runnable {
} }
/** /**
* Lists all Games currenty running and already finished and displays it to the client handled by this * Lists all Games currenty running and already finished and displays it to the client handled by
* this
*/ */
public void listGames() { public void listGames() {
if (Lobby.runningGames.isEmpty() && Lobby.finishedGames.isEmpty()) { if (Lobby.runningGames.isEmpty() && Lobby.finishedGames.isEmpty()) {
@ -479,7 +515,8 @@ public class ClientHandler implements Runnable {
sendAnnouncementToClient("Running Games:"); sendAnnouncementToClient("Running Games:");
try { try {
for (Game runningGame : Lobby.runningGames) { for (Game runningGame : Lobby.runningGames) {
sendAnnouncementToClient(" - " + runningGame.getName() + ", Lobby" + runningGame.getLobby().getLobbyID()); sendAnnouncementToClient(
" - " + runningGame.getName() + ", Lobby" + runningGame.getLobby().getLobbyID());
} }
} catch (Exception e) { } catch (Exception e) {
sendAnnouncementToClient(" - No running Games"); sendAnnouncementToClient(" - No running Games");
@ -487,7 +524,8 @@ public class ClientHandler implements Runnable {
sendAnnouncementToClient("Finished Games:"); sendAnnouncementToClient("Finished Games:");
try { try {
for (Game finishedGame : Lobby.finishedGames) { for (Game finishedGame : Lobby.finishedGames) {
sendAnnouncementToClient(" - " + finishedGame.getName() + ", Lobby" + finishedGame.getLobby().getLobbyID()); sendAnnouncementToClient(
" - " + finishedGame.getName() + ", Lobby" + finishedGame.getLobby().getLobbyID());
} }
} catch (Exception e) { } catch (Exception e) {
sendAnnouncementToClient(" - No finished Games"); sendAnnouncementToClient(" - No finished Games");
@ -502,8 +540,9 @@ public class ClientHandler implements Runnable {
Lobby l = getLobby(); Lobby l = getLobby();
if (l != null) { if (l != null) {
Game g = l.getGame(); Game g = l.getGame();
if(g != null) if (g != null) {
l.getGame().getGameState().handleClientDisconnect(this); l.getGame().getGameState().handleClientDisconnect(this);
}
} }
socket = this.getSocket(); socket = this.getSocket();
in = this.getIn(); in = this.getIn();

View File

@ -47,8 +47,9 @@ public class JServerProtocolParser {
//find ClientHandler //find ClientHandler
try { try {
ClientHandler target = null; ClientHandler target = null;
String targetName = msg.substring(6, msg.indexOf("$", 6)); String[] targetAndMsg = h.decodeWhisper(msg.substring(6));
String chatMsg = msg.substring(msg.indexOf("$", 6)+1); String targetName = targetAndMsg[0];
String chatMsg = targetAndMsg[1];
System.out.println(targetName); System.out.println(targetName);
System.out.println(chatMsg); System.out.println(chatMsg);
for (ClientHandler c : ClientHandler.getConnectedClients()) { for (ClientHandler c : ClientHandler.getConnectedClients()) {

View File

@ -1,66 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<fx:root maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" type="AnchorPane" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.chat.ChatController">
<children>
<SplitPane fx:id ="chatPaneRoot" dividerPositions="0.5" layoutX="214.0" layoutY="92.0" orientation="VERTICAL" prefHeight="400.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
<children>
<ScrollPane layoutX="149.0" layoutY="-18.0" prefHeight="196.0" prefWidth="598.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<content>
<VBox fx:id="vBoxChatMessages" prefHeight="200.0" prefWidth="581.0" />
</content>
</ScrollPane>
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
<children>
<SplitPane dividerPositions="0.29797979797979796" layoutX="166.0" layoutY="8.0" prefHeight="195.0" prefWidth="598.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<SplitPane dividerPositions="0.5" layoutY="-3.0" orientation="VERTICAL" prefHeight="193.0" prefWidth="174.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
<children>
<Button fx:id="sendButton" layoutX="50.0" layoutY="21.0" mnemonicParsing="false" prefHeight="92.0" prefWidth="172.0" text="Send" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
<children>
<TextField fx:id="whisperTargetSelectField" layoutY="14.0" prefHeight="92.0" prefWidth="172.0" promptText="whisper..." AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
<padding>
<Insets bottom="5.0" left="5.0" top="3.0" />
</padding>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<TextArea fx:id="chatMsgField" layoutX="120.0" layoutY="-30.0" prefHeight="193.0" prefWidth="415.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
<padding>
<Insets bottom="5.0" right="5.0" />
</padding>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</fx:root>