diff --git a/README.md b/README.md index 7513ae9..33c18e8 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,9 @@ Votes are held in the night for the ghosts to decide who will be next and during * /w _username$message_ - sends a message to the specified user only. * /g - create (&join) a new lobby. * /j _1_ - join lobby 1. To join lobby 2, use /j _2_, etc. -* /l - list all connected clients and all lobbies +* /l - list all connected clients and all lobbies and their status * /p - list all players in your lobby. +* /z - list all games on the server and their status * /e - exit your lobby * /n _name_ - changes player name. If unavailable, it adds a fun and quirky suffix * /q - quit diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/ClientVoteData.java b/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/ClientVoteData.java index bcf72a9..bf884c7 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/ClientVoteData.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/ClientVoteData.java @@ -1,6 +1,9 @@ package ch.unibas.dmi.dbis.cs108.gamelogic; +import ch.unibas.dmi.dbis.cs108.BudaLogConfig; import java.util.Arrays; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; /** * Data structure that is used to store clientVotes in an array, where the index correponds to the @@ -8,6 +11,8 @@ import java.util.Arrays; */ public class ClientVoteData { + public static final Logger LOGGER = LogManager.getLogger(); + public static final BudaLogConfig l = new BudaLogConfig(LOGGER); private int[] vote; //saves vote of clientHandler for later transmission to passenger, by default MAX_VALUE, index corresponds to Passenger position private boolean[] hasVoted; //saves hasVoted status of clientHandler for later transmission to passenger, by default false, index corresponds to Passenger position @@ -33,7 +38,14 @@ public class ClientVoteData { * @param vote the vote value */ public void setVote(int position, int vote) { - this.vote[position] = vote; + if (vote == Integer.MAX_VALUE) { + setHasVoted(position, false); + } + try { + this.vote[position] = vote; + } catch (IndexOutOfBoundsException e) { + LOGGER.info("Position is: " + position); + } } /** 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 c29fb1d..214b5f2 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 @@ -19,9 +19,7 @@ public class Game implements Runnable { /** * Can be extended for optional Game-settings **/ - protected final int nrOfPlayers; //sets the length of the train - protected final int nrOfGhosts; // sets how many Ghosts we start witch - protected int nrOfUsers; // safes how many clients are active in this Game + protected GameState gameState; protected boolean isDay = false; //false means it is night, it is night by default protected VoteHandler voteHandler = new VoteHandler(); @@ -38,36 +36,23 @@ public class Game implements Runnable { */ public Game(int nrOfPlayers, int nrOfGhosts, int nrOfUsers, Lobby lobby) throws TrainOverflow { //ToDo: Who handles Exception how and where - this.nrOfPlayers = nrOfPlayers; - this.nrOfGhosts = nrOfGhosts; - this.nrOfUsers = nrOfUsers; this.gameState = new GameState(nrOfPlayers, nrOfGhosts, nrOfUsers); this.lobby = lobby; nameCounter++; - this.name = "Game-" + nameCounter; + this.name = "Game" + nameCounter; } public GameState getGameState() { return gameState; } - public int getNrOfGhosts() { - return nrOfGhosts; - } - - public int getNrOfPlayers() { - return nrOfPlayers; - } - - public int getNrOfUsers() { - return nrOfUsers; - } - public Lobby getLobby() { return lobby; } - public boolean getIsDay() {return isDay;} + public boolean getIsDay() {return isDay; } + + public String getName() {return name; } public void setDay(boolean day) { isDay = day; 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 f386313..600e32b 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 @@ -76,6 +76,18 @@ public class GameState { return train; } + public int getNrOfUsers() { + return nrOfUsers; + } + + public int getNrOfPlayers() { + return nrOfPlayers; + } + + public int getNrOfGhosts() { + return nrOfGhosts; + } + /** * * 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 ff85517..5c985da 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 @@ -11,7 +11,7 @@ import org.apache.logging.log4j.Logger; * vote / ghost vote) and handles votes accordingly. - Sends voting request to passengers that need * to be concerned - collects voting results - calculates who was voted for - decides consequence of * vote: - Is it OG ghost: humans win - Is it last human: ghosts win - Is it just a human: message - * "x is a human" - Is it a peasant ghost -> kickoff + * "x is a human" - Is it a peasant ghost - kickoff * *

(All messages going to Clients are handled via ServerGameInfoHandler) * @@ -44,7 +44,7 @@ public class VoteHandler { * @param passengers: passengers on the train */ - public void ghostVote(Passenger[] passengers, Game game) { + public String ghostVote(Passenger[] passengers, Game game) { LOGGER.debug("ghostVote has been called"); LOGGER.info(game.getGameState().toString()); @@ -106,12 +106,23 @@ public class VoteHandler { n.noiseNotifier(passengers, passengers[i], g, game); } } + int humanCounter = 0; + for(Passenger passenger : passengers) { + if(!passenger.getIsGhost()) { //if it is a human + humanCounter++; + } + } + + if (humanCounter == 0) { + return ClientGameInfoHandler.gameOverGhostsWin; + } LOGGER.info(game.getGameState().toString()); // set hasVoted to false for all passengers for future votings for (Passenger passenger : passengers) { passenger.setHasVoted(false); } + return ""; } /** diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/klassenstruktur/GhostNPC.java b/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/klassenstruktur/GhostNPC.java index d4918d7..3ae5858 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/klassenstruktur/GhostNPC.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/gamelogic/klassenstruktur/GhostNPC.java @@ -43,26 +43,31 @@ public class GhostNPC extends Ghost { * but only for positions where there aren't any ghosts and sets hasVoted to true * TODO: Make NPC smarter */ - public void vote(Game game){ + public void vote(Game game) { int ghostCounter = 0; Passenger[] train = game.getGameState().getPassengerTrain(); - for(Passenger passenger : train) { - if(passenger.isGhost) { + for (Passenger passenger : train) { + if (passenger.isGhost) { ghostCounter++; } } - int[] humanPositions = new int[game.getNrOfPlayers() - ghostCounter ]; - int j = 0; - for (int i = 0; i < train.length; i++) { - if (!train[i].isGhost) { //is human - humanPositions[j] = train[i].getPosition(); - j++; + int[] humanPositions = new int[game.getGameState().getNrOfPlayers() - ghostCounter]; + if (humanPositions.length == 0) { + vote = Integer.MAX_VALUE; + } else { + + int j = 0; + for (int i = 0; i < train.length; i++) { + if (!train[i].isGhost) { //is human + humanPositions[j] = train[i].getPosition(); + j++; + } } + int randomPosition = (int) (Math.random() * humanPositions.length); + vote = humanPositions[randomPosition]; + hasVoted = true; + LOGGER.info("GhostNPC at Position: " + this.getPosition() + " has voted for: " + vote); } - int randomPosition = (int) (Math.random()*humanPositions.length); - vote = humanPositions[randomPosition]; - hasVoted = true; - LOGGER.info("GhostNPC at Position: " + this.getPosition() + " has voted for: " + vote); } /** 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 1d7133e..8a4e6da 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 @@ -53,7 +53,7 @@ public class GhostPlayer extends Ghost { public void getVoteFromGameState(ClientVoteData clientVoteData, Game game) { vote = clientVoteData.getVote()[position]; hasVoted = clientVoteData.getHasVoted()[position]; - clientVoteData.setVote(position,Integer.MAX_VALUE); + clientVoteData.setVote(position, Integer.MAX_VALUE); clientVoteData.setHasVoted(position,false); LOGGER.info("Ghost at Pos: " + position + " has voted for: " + vote); /* 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 185cb78..38c9ca6 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 @@ -65,6 +65,9 @@ public class MessageFormatter { case "/p": stringBuilder.append(Protocol.listPlayersInLobby); break; + case "/z": + stringBuilder.append(Protocol.listGames); + break; case "/j": stringBuilder.append(Protocol.joinLobby + "$"); try { @@ -93,7 +96,6 @@ public class MessageFormatter { break; case "/s": stringBuilder.append(Protocol.startANewGame); - break; default: s = msg; 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 b974ff4..f53c17a 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 @@ -122,10 +122,17 @@ public class Protocol { /** - * A Client decides to start the game. + * A Client decides to start the game. The game is started in the lobby the message came from. + * Only one game can be started per lobby at a time. */ public static final String startANewGame = "STGAM"; + /** + * Client request to see a list of all games, ongoing and finished. + */ + + public static final String listGames = "LISTG"; + /** * Client informs server that they have voted and delivers this vote in the form of "CVOTE$position$vote" */ 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 a475f9f..ea26ec9 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 @@ -423,7 +423,7 @@ public class ClientHandler implements Runnable { */ public void listLobbies() { if (Lobby.lobbies.isEmpty()) { - sendAnnouncementToClient("No open Lobbies."); + sendAnnouncementToClient("No Lobbies."); } else { for (Lobby l : Lobby.lobbies) { String lobbyStatus = "closed"; @@ -475,6 +475,32 @@ public class ClientHandler implements Runnable { } } + /** + * Lists all Games currenty running and already finished and displays it to the client handled by this + */ + public void listGames() { + if (Lobby.runningGames.isEmpty() && Lobby.finishedGames.isEmpty()) { + sendAnnouncementToClient("No Games"); + } else { + sendAnnouncementToClient("Running Games:"); + try { + for (Game runningGame : Lobby.runningGames) { + sendAnnouncementToClient(" - " + runningGame.getName() + ", Lobby" + runningGame.getLobby().getLobbyID()); + } + } catch (Exception e) { + sendAnnouncementToClient(" - No running Games"); + } + sendAnnouncementToClient("Finished Games"); + try { + for (Game finishedGame : Lobby.finishedGames) { + sendAnnouncementToClient(" - " + finishedGame.getName() + ", Lobby" + finishedGame.getLobby().getLobbyID()); + } + } catch (Exception e) { + sendAnnouncementToClient(" - No finished Games"); + } + } + } + /** * Closes the client's socket, in, and out. and removes from global list of clients. */ 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 06a4120..d1ab373 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 @@ -111,6 +111,9 @@ public class JServerProtocolParser { case Protocol.startANewGame: h.startNewGame(); break; + case Protocol.listGames: + h.listGames(); + break; default: System.out.println("Received unknown command"); } diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/server/Lobby.java b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/server/Lobby.java index 21bc958..92cdbfb 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/server/Lobby.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/server/Lobby.java @@ -108,13 +108,6 @@ public class Lobby { return null; } - public static HashSet getFinishedGames() { - return finishedGames; - } - - public static HashSet getRunningGames() { - return runningGames; - } /** * Returns the game that the clients in this lobby are in