From 81ee9a8841f45b895eca2e0a5b00acbef44c8068 Mon Sep 17 00:00:00 2001 From: Seraina Date: Fri, 29 Apr 2022 16:24:24 +0200 Subject: [PATCH 1/5] Started linking new GameStateModel and Gamelogic, via protocol --- .../gamelogic/ClientGameInfoHandler.java | 9 ++-- .../dmi/dbis/cs108/gamelogic/GameState.java | 28 ++++------ .../dmi/dbis/cs108/gamelogic/VoteHandler.java | 4 +- .../dbis/cs108/multiplayer/client/Client.java | 51 ++++++++++++++++++ .../client/JClientProtocolParser.java | 6 ++- .../client/gui/GameStateModel.java | 50 ++++++++++++++++-- .../client/gui/game/GameController.java | 52 +++++++++++++++++-- .../cs108/multiplayer/helpers/Protocol.java | 8 +++ .../client/gui/game/GameDayAll.fxml | 2 +- 9 files changed, 175 insertions(+), 35 deletions(-) diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/ClientGameInfoHandler.java b/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/ClientGameInfoHandler.java index ba803e8..0ed9285 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/ClientGameInfoHandler.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/ClientGameInfoHandler.java @@ -13,18 +13,21 @@ public class ClientGameInfoHandler { * All messages that are used in VoteHandler * TODO(Seraina-Alex): Adjust strings to be more meaningful */ - //relevant: + //relevant for game logic: public static final String ghostVoteRequest = "Vote on who to ghostify!"; public static final String humanVoteRequest = "Vote for a ghost to kick off!"; public static final String noiseNotification = "Someone passed by you "; public static final String gameOverHumansWin = "Game over: humans win!"; public static final String gameOverGhostsWin = "Game over: ghosts win!"; - //just messages + //relevant for gui public static final String itsNightTime = "Please wait, ghosts are active"; + public static final String itsDayTime = "Please wait, humans are active"; + + //just messages + public static final String youGotGhostyfied = "You are now a ghost!"; public static final String youGotKickedOff = "Bye bye - you've been kicked off"; - public static final String itsDayTime = "Please wait, humans are active"; public static final String humansVotedFor = "Humans voted for: "; public static final String isAHuman = " but they're a human!"; public static final String gotKickedOff = " is a Ghost and got kicked off"; diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/GameState.java b/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/GameState.java index a9467e0..06f041e 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/GameState.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/GameState.java @@ -162,27 +162,17 @@ public class GameState { StringBuilder stringBuilder = new StringBuilder(); String[] print = new String[6]; for (int i = 0; i < array.length; i++) { - if (array[i].getKickedOff()) { - print[i] = "| " + array[i].getName() + ", kicked off: " + array[i].getPosition() + " |"; + if(array[i].getIsSpectator()) { + print[i] = array[i].getName() + ":s:" + array[i].getKickedOff(); + } else if (array[i].getIsGhost()) { + print[i] = array[i].getName() + ":g:" + array[i].getKickedOff(); } else { - if (array[i].getIsPlayer()) { - if (array[i].getIsGhost()) { - print[i] = "| " + array[i].getName() + "(ghostPlayer): " + array[i].getPosition() + " |"; - } else { - print[i] = "| " + array[i].getName() + "(humanPlayer): " + array[i].getPosition() + " |"; - } - } else { - if (array[i].getIsGhost()) { - print[i] = "| " + array[i].getName() + "(ghostNPC): " + array[i].getPosition() + " |"; - } else { - print[i] = "| " + array[i].getName() + "(humanNPC): " + array[i].getPosition() + " |"; - } - } + print[i] = "| " + array[i].getName() + ":h:" + array[i].getKickedOff(); } - } + } for (int i = 0; i < array.length; i++) { - stringBuilder.append(print[i]); + stringBuilder.append("$").append(print[i]); } return stringBuilder.toString(); } @@ -198,11 +188,11 @@ public class GameState { StringBuilder stringBuilder = new StringBuilder(); String[] print = new String[6]; for (int i = 0; i < array.length; i++) { - print[i] = "| " + array[i].getName() + ": " + array[i].getPosition() + " |"; + print[i] = array[i].getName() + "::" + array[i].getKickedOff(); } for (int i = 0; i < array.length; i++) { - stringBuilder.append(print[i]); + stringBuilder.append("$").append(print[i]); } return stringBuilder.toString(); } diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/VoteHandler.java b/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/VoteHandler.java index 93b7a4d..48b3b75 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/VoteHandler.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/VoteHandler.java @@ -52,7 +52,7 @@ public class VoteHandler { //Timer.ghostVoteTimer(game); try { - Thread.sleep(10*1000); + Thread.sleep(20*1000); } catch (InterruptedException e) { LOGGER.warn("Thread " + Thread.currentThread() + " was interrupted"); } @@ -155,7 +155,7 @@ public class VoteHandler { } try { // waits 60 seconds before votes get collected - Thread.sleep(10*1000); + Thread.sleep(20*1000); } catch (InterruptedException e) { LOGGER.warn("Thread " + Thread.currentThread() + " was interrupted"); } diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/Client.java b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/Client.java index 6ad5608..03274f1 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/Client.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/Client.java @@ -1,10 +1,13 @@ package ch.unibas.dmi.dbis.cs108.multiplayer.client; import ch.unibas.dmi.dbis.cs108.BudaLogConfig; +import ch.unibas.dmi.dbis.cs108.gamelogic.ClientGameInfoHandler; import ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.ClientModel; import ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.GUI; +import ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.GameStateModel; import ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.chat.ChatApp; import ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.chat.ChatController; +import ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.game.GameController; import ch.unibas.dmi.dbis.cs108.multiplayer.helpers.ClientPinger; @@ -32,6 +35,8 @@ public class Client { private ChatApp chatApp; private GUI chatGui; + private GameStateModel gameStateModel; + private GameController gameController; /** * Saves the position of the client, gets refreshed everytime the client gets a vote request. @@ -63,6 +68,8 @@ public class Client { this.chatApp = new ChatApp(new ClientModel(systemName, this)); this.chatGui = new GUI(this.chatApp); clientPinger = new ClientPinger(this, this.socket); + this.gameStateModel = new GameStateModel(); + this.gameController = new GameController(ChatApp.getClientModel(),gameStateModel); } catch (IOException e) { e.printStackTrace(); } @@ -124,6 +131,16 @@ public class Client { //LOGGER.debug("just checked next line"); } + /** + * Extracts infromation about names and positions and roles from string and adds it to + * the GameStateModel + * @param msg + */ + public void gameStateModelSetter(String msg) { + + + } + /** * Starts a thread which listens for incoming chat messages / other messages that the user has to @@ -290,4 +307,38 @@ public class Client { public void sendToChat(String substring) { chatApp.getChatController().addChatMsgToView(substring); } + + /** + * funnels a message to the gui, where depending on the message different functions/controls/methods + * of the gui are targeted. The message contains information on what to do, which are extracted + * @param msg a message of the form {@code parameter$msg} + * + */ + public void sendToGUI(String msg) { + int indexFirstDollar = msg.indexOf('$'); + String header = ""; + try { + header = msg.substring(0,indexFirstDollar); + } catch (IndexOutOfBoundsException e) { + LOGGER.info(e.getMessage()); + } + + switch (header) { + case ClientGameInfoHandler.itsNightTime: + gameStateModel.setDayClone(false); + break; + case ClientGameInfoHandler.itsDayTime: + gameStateModel.setDayClone(true); + break; + + default: + gameController.addMessageToNotificationText(msg); //TODO(Sebi,Seraina): should the gameController be in the Application just like the ChatController? + + + } + + + } + + } diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/JClientProtocolParser.java b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/JClientProtocolParser.java index f497bf0..58db92d 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/JClientProtocolParser.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/JClientProtocolParser.java @@ -1,6 +1,7 @@ package ch.unibas.dmi.dbis.cs108.multiplayer.client; import ch.unibas.dmi.dbis.cs108.BudaLogConfig; +import ch.unibas.dmi.dbis.cs108.gamelogic.ClientGameInfoHandler; import ch.unibas.dmi.dbis.cs108.multiplayer.helpers.Protocol; import java.io.OutputStreamWriter; import org.apache.logging.log4j.LogManager; @@ -48,7 +49,7 @@ public class JClientProtocolParser { break; case Protocol.serverRequestsGhostVote: LOGGER.debug("Ghost received Vote request"); - System.out.println("Ghost Vote:"); + //c.sendToGUI(ClientGameInfoHandler.ghostVoteRequest); c.positionSetter(msg.substring(6)); break; case Protocol.serverRequestsHumanVote: @@ -59,6 +60,9 @@ public class JClientProtocolParser { case Protocol.changedUserName: c.changeUsername(msg.substring(6)); break; + case Protocol.printToGUI: + c.sendToGUI(msg.substring(6)); + break; default: System.out.println("Received unknown command"); } diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/GameStateModel.java b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/GameStateModel.java index 67fa925..b140d25 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/GameStateModel.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/GameStateModel.java @@ -11,6 +11,12 @@ public class GameStateModel { */ private boolean isDayClone; + /** + * can take the values h/g/s for human/ghost/spectator. Safes the role the client this GamesStateModel + * lives on currently has + */ + private String yourRole; + /** * A primitive clone of the passengerTrain in the GameState of the server. * in passengerTrainClone[0] the names of the passengers are stored, in passengerTrainClone[1] the roles @@ -18,13 +24,19 @@ public class GameStateModel { */ private String[][] passengerTrainClone; + private boolean[] kickedOff; + /** - * Constructs a GamesStateModel with the passengerTrainClone length at nrOfPlayers - * @param nrOfPlayers the amount of different objects to be saved + * Constructs a GamesStateModel with the passengerTrainClone */ - public void GameStateModel(int nrOfPlayers) { - this.nrOfPlayers = nrOfPlayers; + public GameStateModel() { + this.nrOfPlayers = 6; passengerTrainClone = new String[2][nrOfPlayers]; + for(String role : passengerTrainClone[1]) { + role = ""; + } + kickedOff = new boolean[nrOfPlayers]; + isDayClone = false; } /** @@ -37,4 +49,34 @@ public class GameStateModel { passengerTrainClone[1] = roles; } + + public String[][] getPassengerTrainClone() { + return passengerTrainClone; + } + + /** + * Sets your current role to the specified role, must be h for human, g for ghost or s for spectator + * @param yourRole the role to set this role to + */ + public void setYourRole(String yourRole) { + if(yourRole.equals("h") || yourRole.equals("g") || yourRole.equals("s")) { + this.yourRole = yourRole; + } + } + + public String getYourRole() { + return yourRole; + } + + public int getNrOfPlayers() { + return nrOfPlayers; + } + + public void setDayClone(boolean dayClone) { + isDayClone = dayClone; + } + + public boolean getDayClone() { + return isDayClone; + } } diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/game/GameController.java b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/game/GameController.java index 9e48add..73d5cfd 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/game/GameController.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/game/GameController.java @@ -1,5 +1,6 @@ package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.game; +import ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.GameStateModel; import javafx.event.EventHandler; import ch.unibas.dmi.dbis.cs108.BudaLogConfig; import ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.ClientModel; @@ -35,6 +36,14 @@ public class GameController { private static ClientModel client; + private static GameStateModel gameStateModel; + + //TODO(Seraina, Sebi): Same issue as ChatController? do with setters? + public GameController(ClientModel c, GameStateModel g) { + client = c; + gameStateModel = g; + } + @FXML private AnchorPane gameBG; @FXML @@ -138,14 +147,47 @@ public class GameController { } /** - * Adds a msg to the room Lable at the specified position - * @param names a String array containing all the names + * Updates the labels of the rooms accordingly to the datastructures in GameStateModel */ - public void addRoomLabels(String[] names) { + public void updateRoomLabels() { + String[] names = gameStateModel.getPassengerTrainClone()[0]; + String[] roles = gameStateModel.getPassengerTrainClone()[1]; + Text name0 = new Text(names[0]); + Text name1 = new Text(names[1]); + Text name2 = new Text(names[2]); + Text name3 = new Text(names[3]); + Text name4 = new Text(names[4]); + Text name5 = new Text(names[5]); + Text role0 = new Text(roles[0]); + Text role1 = new Text(roles[1]); + Text role2 = new Text(roles[2]); + Text role3 = new Text(roles[3]); + Text role4 = new Text(roles[4]); + Text role5 = new Text(roles[5]); + lableRoom0.getChildren().clear(); + lableRoom0.getChildren().add(name0); + lableRoom0.getChildren().add(role0); + lableRoom1.getChildren().clear(); + lableRoom1.getChildren().add(name1); + lableRoom1.getChildren().add(role1); + lableRoom2.getChildren().clear(); + lableRoom2.getChildren().add(name2); + lableRoom2.getChildren().add(role2); + lableRoom3.getChildren().clear(); + lableRoom3.getChildren().add(name3); + lableRoom3.getChildren().add(role3); + lableRoom4.getChildren().clear(); + lableRoom4.getChildren().add(name4); + lableRoom4.getChildren().add(role4); + lableRoom5.getChildren().clear(); + lableRoom5.getChildren().add(name5); + lableRoom5.getChildren().add(role5); } - - + public void setGameStateModel( + GameStateModel gameStateModel) { + GameController.gameStateModel = gameStateModel; + } } 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 2fc4bad..a4f5931 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 @@ -194,5 +194,13 @@ public class Protocol { */ public static final String changedUserName = "CHNAM"; + /** + * Sends a message to a client containing information for the gui. The command is structured {@code PTGUI$parameter$msg} + * where the parameter specifies what exactly to do in de gui (i.e. change scene) and the optional + * message contains information the gui needs from the server to execute the command specified in the parameter + * + */ + public static final String printToGUI = "PTGUI"; + } diff --git a/src/main/resources/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/game/GameDayAll.fxml b/src/main/resources/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/game/GameDayAll.fxml index a08b086..f36cb4a 100644 --- a/src/main/resources/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/game/GameDayAll.fxml +++ b/src/main/resources/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/game/GameDayAll.fxml @@ -97,7 +97,7 @@ - From fc737012c76710a24939104a2204365e55ed621e Mon Sep 17 00:00:00 2001 From: Jonas Date: Fri, 29 Apr 2022 21:25:03 +0200 Subject: [PATCH 2/5] Timers fully implemented. --- .../unibas/dmi/dbis/cs108/gamelogic/Game.java | 3 + .../dmi/dbis/cs108/gamelogic/Timer.java | 67 ++++++++++++++++--- .../dmi/dbis/cs108/gamelogic/VoteHandler.java | 43 +++++------- .../klassenstruktur/GhostPlayer.java | 4 +- 4 files changed, 81 insertions(+), 36 deletions(-) diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/Game.java b/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/Game.java index 27f3f04..0a8e641 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/Game.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/Game.java @@ -65,6 +65,9 @@ public class Game implements Runnable { isOngoing = ongoing; } + /** + * Returns this game's OG ghost as a Passenger object + */ Passenger getOgGhost(){ int[] order = gameState.getTrain().getOrderOfTrain(); Passenger[] passengerTrain = gameState.getPassengerTrain(); diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/Timer.java b/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/Timer.java index 74072f4..e5eef8e 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/Timer.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/Timer.java @@ -1,11 +1,13 @@ package ch.unibas.dmi.dbis.cs108.gamelogic; import ch.unibas.dmi.dbis.cs108.BudaLogConfig; +import ch.unibas.dmi.dbis.cs108.gamelogic.klassenstruktur.Passenger; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; /** - * A class that handles all timed events in the game, such as vote times + * A class that handles all timed events in the game, such as vote times. This class essentially + * is used to pause the main game thread for a given time / until a given event. */ public class Timer { public static final Logger LOGGER = LogManager.getLogger(Timer.class); @@ -14,36 +16,68 @@ public class Timer { /** * The maximum length of the ghost vote in the night, in seconds */ - public static final int ghostVote = 30; + public static final int ghostVoteTime = 30; + + /** + * The length of time in seconds after the ghost vote during which the ghosts visually walk to / + * from their victim and the timespan within which humans will hear a noise. After this, the day starts. + */ + public static final int ghostAfterVoteTime = 7; /** * The maximum length of the human vote in the day, in seconds */ - public static final int humanVote = 60; + public static final int humanVoteTime = 60; /** - * The checking intervall in seconds + * The length of time in seconds after the human vote, as the 'winner' of the vote is announced, + * before the night begins */ - public static final int intervall = 1; + public static final int humanAfterVoteTime = 5; /** - * The timer for the ghost vote. Checks every {@code intervall} seconds if every ghost has already voted. - * If all have voted or if the {@code ghostVote} value is reached, the timer ends + * The checking interval in seconds + */ + public static final int interval = 1; + + /** + * The timer for the ghost vote. Checks every {@code interval} seconds if every ghost has already voted. + * If all have voted or if the {@code ghostVoteTime} value is reached, the timer ends * @param game the game this Timer has been called in */ public static void ghostVoteTimer(Game game) { int counter = 0; - while(counter < ghostVote) { + while(counter < ghostVoteTime) { if(haveAllGhostsVoted(game)) { //if all ghost have voted return; } try { - Thread.sleep(intervall*1000); + Thread.sleep(interval*1000); } catch (InterruptedException e) { LOGGER.warn("Thread " + Thread.currentThread() + " was interrupted"); } - counter = counter + (intervall*1000); + counter += (interval); } + } + public static void humanVoteTimer(Game game) { + int counter = 0; + while (counter < humanVoteTime) { + if (haveAllHumansVoted(game)) return; + try { + Thread.sleep(interval*1000); + } catch (InterruptedException e) { + LOGGER.warn("Thread " + Thread.currentThread() + " was interrupted"); + } + counter += interval; + } + } + + public static void ghostAfterVoteTimer() { + try { + Thread.sleep(ghostAfterVoteTime *1000); + } catch (InterruptedException e) { + LOGGER.warn("Thread " + Thread.currentThread() + " was interrupted"); + } } /** @@ -71,5 +105,18 @@ public class Timer { return nrOfGhosts == j; } + /** + * Checks if all humans have already voted, returns true if so, else returns false + */ + public static boolean haveAllHumansVoted(Game game) { + boolean[] whoHasVoted = game.getGameState().getClientVoteData().getHasVoted(); + Passenger[] passengerArray = game.getGameState().getPassengerTrain(); + for(int i = 0; i < whoHasVoted.length; i++) { + if(!passengerArray[i].getIsGhost() && !whoHasVoted[i]) { + return false; + } + } + return true; + } } diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/VoteHandler.java b/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/VoteHandler.java index 48b3b75..377def6 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/VoteHandler.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/VoteHandler.java @@ -50,42 +50,34 @@ public class VoteHandler { } } - //Timer.ghostVoteTimer(game); - try { - Thread.sleep(20*1000); - } catch (InterruptedException e) { - LOGGER.warn("Thread " + Thread.currentThread() + " was interrupted"); - } + Timer.ghostVoteTimer(game); + int currentMax = ghostVoteEvaluation(passengers, votesForPlayers, game.getGameState().getClientVoteData(), game); LOGGER.debug("Most votes: " + currentMax + " vote(s)"); // ghostify the player with most votes - int ghostPosition = 0; + int newGhostPosition = 0; for (int i = 0; i < votesForPlayers.length; i++) { if (votesForPlayers[i] == currentMax) { // if player at position i has most votes - ghostPosition = i; + newGhostPosition = i; LOGGER.debug("Most votes for Passenger " + i); } } - LOGGER.info("Most votes for: " + ghostPosition); + LOGGER.info("Most votes for: " + newGhostPosition); for(Passenger passenger : passengers) { if(passenger.getIsGhost() || passenger.getIsSpectator()) { - passenger.send(passengers[ghostPosition].getName() + ClientGameInfoHandler.gotGhostyfied, game); + passenger.send(passengers[newGhostPosition].getName() + ClientGameInfoHandler.gotGhostyfied, game); } } - Passenger g = GhostifyHandler.ghost(passengers[ghostPosition], game); - passengers[ghostPosition] = g; - if (!passengers[ghostPosition].getIsSpectator()) { - passengers[ghostPosition].send( + Passenger g = GhostifyHandler.ghost(passengers[newGhostPosition], game); + passengers[newGhostPosition] = g; + if (!passengers[newGhostPosition].getIsSpectator()) { + passengers[newGhostPosition].send( ClientGameInfoHandler.youGotGhostyfied, game); - } - try { - Thread.sleep(10); - } catch (InterruptedException e) { - LOGGER.warn("Thread " + Thread.currentThread() + " was interrupted"); + passengers[newGhostPosition].send(game.gameState.toString(), game); } /* notify passengers the ghosts passed by - for each ghost that ghostified a player, an instance of NoiseHandler @@ -96,7 +88,7 @@ public class VoteHandler { int[] noiseAmount = new int[6]; for (int i = 0; i < passengers.length; i++) { - if (passengers[i].getIsGhost() && i != ghostPosition) { + if (passengers[i].getIsGhost() && i != newGhostPosition) { NoiseHandler n = new NoiseHandler(); noiseAmount = n.noiseNotifier(passengers[i], g, noiseAmount); } @@ -107,6 +99,11 @@ public class VoteHandler { } } + /* used to wait for some time so the humans have time to hear noises and so the ghosts (& victim) + can see the infection happen. */ + Timer.ghostAfterVoteTimer(); + + // no humans left in the game --> everyone has been ghostified, ghosts win int humanCounter = 0; for(Passenger passenger : passengers) { @@ -154,11 +151,7 @@ public class VoteHandler { } } - try { // waits 60 seconds before votes get collected - Thread.sleep(20*1000); - } catch (InterruptedException e) { - LOGGER.warn("Thread " + Thread.currentThread() + " was interrupted"); - } + Timer.humanVoteTimer(game); int currentMax = humanVoteEvaluation(passengers, votesForPlayers, game.getGameState().getClientVoteData(), game); diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/klassenstruktur/GhostPlayer.java b/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/klassenstruktur/GhostPlayer.java index a9aaa32..9049128 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/klassenstruktur/GhostPlayer.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/klassenstruktur/GhostPlayer.java @@ -35,7 +35,9 @@ public class GhostPlayer extends Ghost { } /** - * Sends a message to the client handled bye this client handler + * Sends a message to the client handled by this client handler. By default, it adds the + * protocol signature to print the given msg as is to the client console. For more detail on + * how the message gets formatted, look at the ServerGameInfoHandler.format() method. * @param msg the message that is sent to this player. * @param game the game the GhostPlayer lives on (in game.gameState.passengerTrain) */ From d2907aa8ac4cb9d8e6927608f745bc46dac6d4a9 Mon Sep 17 00:00:00 2001 From: Sebastian Lenzlinger Date: Sat, 30 Apr 2022 13:48:21 +0200 Subject: [PATCH 3/5] Cleaned up ChatController a bit and added a chat label configurator classed used by the chat controller. --- .../client/gui/chat/ChatController.java | 66 +++++-------------- .../gui/utils/ChatLabelConfigurator.java | 36 ++++++++++ 2 files changed, 51 insertions(+), 51 deletions(-) create mode 100644 src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/utils/ChatLabelConfigurator.java diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/chat/ChatController.java b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/chat/ChatController.java index aacdf11..122f1a3 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/chat/ChatController.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/chat/ChatController.java @@ -3,9 +3,8 @@ package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.chat; import ch.unibas.dmi.dbis.cs108.BudaLogConfig; import ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.ClientModel; +import ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.utils.ChatLabelConfigurator; import ch.unibas.dmi.dbis.cs108.multiplayer.helpers.Protocol; -import com.sun.javafx.scene.control.Properties; -import com.sun.javafx.scene.control.inputmap.KeyBinding; import java.net.URL; import java.util.ResourceBundle; import javafx.application.Platform; @@ -22,18 +21,13 @@ import javafx.scene.Node; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; -import javafx.scene.control.SplitPane; -import javafx.scene.control.TextArea; import javafx.scene.control.TextField; -import javafx.scene.input.KeyCode; -import javafx.scene.input.KeyEvent; import javafx.scene.layout.Background; import javafx.scene.layout.GridPane; import javafx.scene.layout.Pane; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.text.Text; -import javafx.scene.text.TextFlow; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -99,20 +93,14 @@ public class ChatController implements Initializable { public void initialize(URL location, ResourceBundle resources) { setClient(ChatApp.getClientModel()); ChatApp.setChatController(this); - vBoxChatMessages.getChildren().addListener(new ListChangeListener() { - @Override - public void onChanged(Change c) { - vBoxChatMessages.setMaxHeight(vBoxChatMessages.getMaxHeight() * 2); - } - }); + vBoxChatMessages.getChildren().addListener( + (ListChangeListener) c -> vBoxChatMessages.setMaxHeight( + vBoxChatMessages.getMaxHeight() * 2)); - vBoxChatMessages.heightProperty().addListener(new ChangeListener() { + vBoxChatMessages.heightProperty().addListener(new ChangeListener<>() { /** * TODO: implement - * Adjust the hight when new messages come in. - * @param observable - * @param oldValue - * @param newValue + * Adjust the height when new messages come in. */ @Override public void changed(ObservableValue observable, Number oldValue, @@ -124,30 +112,15 @@ public class ChatController implements Initializable { /** * Initialize what happens when the send button is pressed */ - sendButton.setOnAction(new EventHandler() { - @Override - public void handle(ActionEvent event) { - sendChatMsg(); - } - }); + sendButton.setOnAction(event -> sendChatMsg()); - chatMsgField.setOnAction(new EventHandler() { - @Override - public void handle(ActionEvent event) { - sendChatMsg(); - } - }); + chatMsgField.setOnAction(event -> sendChatMsg()); /** * Initialize the change of the TextArea field holding potential chat messages */ - chatMsgField.textProperty().addListener(new ChangeListener() { - @Override - public void changed(ObservableValue observable, String oldValue, - String newValue) { - chatMsgField.setText(newValue); - } - }); + chatMsgField.textProperty().addListener( + (observable, oldValue, newValue) -> chatMsgField.setText(newValue)); //Possibly now the whisperTargetChosenProperty is obsolete whisperTargetSelectField.textProperty().addListener(new ChangeListener() { @@ -171,19 +144,10 @@ public class ChatController implements Initializable { client.getClient().sendMsgToServer(cmd.toString() + msg); LOGGER.info("Message trying to send is: " + cmd.toString() + msg); Text t; - Label l; - if (cmd.startsWith(whisper)) { - t = new Text("You whispered to " + whisperTargetSelectField.getText() + ": " + msg); - l = new Label("You whispered to " + whisperTargetSelectField.getText() + ": " + msg); - l.setBackground(Background.fill(Color.LAVENDERBLUSH)); - } else { - t = new Text(client.getUsername() + " (you): " + msg); - l = new Label(client.getUsername() + " (you): " + msg); - l.setBackground(Background.fill(Color.LAVENDER)); - l.setWrapText(true); - l.setMaxHeight(Double.MAX_VALUE); - l.setScaleShape(true); - } + + //Configure what to put in the Users ChatView + Label l = ChatLabelConfigurator.configure(cmd,msg,whisperTargetSelectField,client); + vBoxChatMessages.getChildren().add(l); chatMsgField.clear(); } else { @@ -204,7 +168,7 @@ public class ChatController implements Initializable { * @param client who's gui controller this should be */ public void setClient(ClientModel client) { - this.client = client; + ChatController.client = client; } public Pane getChatPaneRoot() { diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/utils/ChatLabelConfigurator.java b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/utils/ChatLabelConfigurator.java new file mode 100644 index 0000000..21705d0 --- /dev/null +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/utils/ChatLabelConfigurator.java @@ -0,0 +1,36 @@ +package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.utils; + +import static ch.unibas.dmi.dbis.cs108.multiplayer.helpers.Protocol.whisper; + + +import ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.ClientModel; +import javafx.scene.control.Label; +import javafx.scene.control.TextField; +import javafx.scene.layout.Background; +import javafx.scene.paint.Color; +import javafx.scene.text.Text; + +/** + * Provides utilities to configure Labels for the ChatView {@see ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.chat.ChatView.fxml} + * within {@link ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.chat.ChatController} + */ +public class ChatLabelConfigurator { + + public static Label configure(String cmd, String msg, TextField whisperTargetSelectField, ClientModel client) { + Label l; + if (cmd.startsWith(whisper)) { + //t = new Text("You whispered to " + whisperTargetSelectField.getText() + ": " + msg); + l = new Label("You whispered to " + whisperTargetSelectField.getText() + ": " + msg); + l.setBackground(Background.fill(Color.LAVENDERBLUSH)); + } else { + //t = new Text(client.getUsername() + " (you): " + msg); + l = new Label(client.getUsername() + " (you): " + msg); + l.setBackground(Background.fill(Color.LAVENDER)); + l.setWrapText(true); + l.setMaxHeight(Double.MAX_VALUE); + l.setScaleShape(true); + } + return l; + } + +} From 9f7fc2556ba2cf19540d9f13be8a7d409f5059ab Mon Sep 17 00:00:00 2001 From: Sebastian Lenzlinger Date: Sat, 30 Apr 2022 16:35:54 +0200 Subject: [PATCH 4/5] Adding Functionality to the view --- .../multiplayer/client/gui/ClientModel.java | 40 ++++++++++ .../client/gui/chat/ChatController.java | 2 - .../client/gui/lounge/ClientListItem.java | 40 ++++++++++ .../client/gui/lounge/LobbyListItem.java | 18 +++-- .../gui/lounge/LoungeSceneViewController.java | 73 ++++++++++++++++++- .../client/gui/lounge/LoungeSceneView.fxml | 41 ++++++++++- 6 files changed, 205 insertions(+), 9 deletions(-) create mode 100644 src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/lounge/ClientListItem.java diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/ClientModel.java b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/ClientModel.java index 7444913..7afc932 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/ClientModel.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/ClientModel.java @@ -2,6 +2,19 @@ package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui; import ch.unibas.dmi.dbis.cs108.BudaLogConfig; import ch.unibas.dmi.dbis.cs108.multiplayer.client.Client; +import ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.lounge.ClientListItem; +import ch.unibas.dmi.dbis.cs108.multiplayer.server.Lobby; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import javafx.beans.property.SimpleListProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.collections.ObservableMap; +import javafx.collections.ObservableSet; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -14,9 +27,17 @@ public class ClientModel { private Client client; private String incomingChatMsg; + private ObservableList allClients; + private ObservableMap idToNameMap; + + + private HashSet clientsOnServer; + public ClientModel(String username, Client client) { this.username = username; this.client = client; + this.allClients = FXCollections.observableArrayList(); + this.idToNameMap = FXCollections.observableHashMap(); } //private Number; @@ -36,4 +57,23 @@ public class ClientModel { public void setUsername(String username) { this.username = username; } + + public ObservableList getAllClients() { + return allClients; + } + + public void addClientToList(ClientListItem nameAndId) { + this.allClients.add(nameAndId); + } + + public void removeClientFromList(int id){ + Iterator it = allClients.iterator(); + while(it.hasNext()){ + int uid = it.next().getId(); + if(uid == id){ + it.remove(); + break; + } + } + } } diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/chat/ChatController.java b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/chat/ChatController.java index 122f1a3..16f186f 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/chat/ChatController.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/chat/ChatController.java @@ -12,8 +12,6 @@ import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.ListChangeListener; -import javafx.event.ActionEvent; -import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.Group; diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/lounge/ClientListItem.java b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/lounge/ClientListItem.java new file mode 100644 index 0000000..b0f17c5 --- /dev/null +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/lounge/ClientListItem.java @@ -0,0 +1,40 @@ +package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.lounge; + +import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.property.SimpleStringProperty; + +public class ClientListItem { + + private SimpleStringProperty name; + private final SimpleIntegerProperty id; + + public ClientListItem(SimpleStringProperty name, SimpleIntegerProperty id) { + this.name = name; + this.id = id; + } + + @Override + public String toString(){ + return name + " ID: " + id; + } + + public String getName() { + return name.get(); + } + + public SimpleStringProperty nameProperty() { + return name; + } + + public void setName(String name) { + this.name.set(name); + } + + public int getId() { + return id.get(); + } + + public SimpleIntegerProperty idProperty() { + return id; + } +} diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/lounge/LobbyListItem.java b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/lounge/LobbyListItem.java index 4793b9c..5259334 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/lounge/LobbyListItem.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/lounge/LobbyListItem.java @@ -1,14 +1,22 @@ package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.lounge; -import java.util.List; +import java.util.Set; +import javafx.beans.property.StringProperty; import javafx.scene.control.Label; import javafx.scene.control.ToggleButton; public class LobbyListItem { - private Label lobbyID; - private Label adminName; - private List clientInLobby; - private ToggleButton button; + private final Label lobbyID; + private final Label adminName; + private Set clientsInLobby; + private final ToggleButton button; + public LobbyListItem(Label lobbyID, Label adminName, + Set clientsInLobby, ToggleButton button) { + this.lobbyID = lobbyID; + this.adminName = adminName; + this.clientsInLobby = clientsInLobby; + this.button = button; + } } diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/lounge/LoungeSceneViewController.java b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/lounge/LoungeSceneViewController.java index 9a72b54..53cbf57 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/lounge/LoungeSceneViewController.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/lounge/LoungeSceneViewController.java @@ -1,5 +1,76 @@ package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.lounge; -public class LoungeSceneViewController { +import ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.ClientModel; +import ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.events.ChangeNameButtonPressedEventHandler; +import ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.events.LeaveServerButtonPressedEventHandler; +import java.net.URL; +import java.util.ResourceBundle; +import javafx.beans.property.StringProperty; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.Button; +import javafx.scene.control.ListCell; +import javafx.scene.control.ListView; +import javafx.scene.control.ToolBar; +import javafx.scene.control.TreeView; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.HBox; +public class LoungeSceneViewController implements Initializable { + + + @FXML + private TreeView LobbyTreeView; + @FXML + private ListView ClientListView; + @FXML + private Button ChangeNameButton; + @FXML + private Button LeaveServerButton; + @FXML + private AnchorPane ChatArea; + @FXML + private HBox ChatAreaHBox; + @FXML + private BorderPane LoungeSceneBorderPane; + @FXML + private ToolBar NTtBToolBar; + + public static ClientModel client; + + + /** + * Called to initialize a controller after its root element has been completely processed. + * + * @param location The location used to resolve relative paths for the root object, or {@code + * null} if the location is not known. + * @param resources The resources used to localize the root object, or {@code null} if + */ + @Override + public void initialize(URL location, ResourceBundle resources) { + ChangeNameButton.setOnAction(new ChangeNameButtonPressedEventHandler()); + LeaveServerButton.setOnAction(new LeaveServerButtonPressedEventHandler()); + } + + public void updateLobbyListView(){ + + } + + public void updateClientListView(){ + + } + + public void addClientToList(ClientListItem player) { + ListCell playerCell = new ListCell<>(); + ClientListView.ite + } + + /** + * Utility to set the client model for this class + * @param client, the client model + */ + public static void setClient(ClientModel client) { + LoungeSceneViewController.client = client; + } } diff --git a/src/main/resources/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/lounge/LoungeSceneView.fxml b/src/main/resources/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/lounge/LoungeSceneView.fxml index 92ce78d..ddd29bb 100644 --- a/src/main/resources/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/lounge/LoungeSceneView.fxml +++ b/src/main/resources/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/lounge/LoungeSceneView.fxml @@ -1,6 +1,45 @@ + + + + + + - + + + + + + +