Merge remote-tracking branch 'origin/master'

This commit is contained in:
Seraina
2022-04-28 18:31:29 +02:00
32 changed files with 900 additions and 64 deletions

View File

@@ -7,6 +7,7 @@ import ch.unibas.dmi.dbis.cs108.gamelogic.klassenstruktur.GhostPlayer;
import ch.unibas.dmi.dbis.cs108.gamelogic.klassenstruktur.HumanNPC;
import ch.unibas.dmi.dbis.cs108.gamelogic.klassenstruktur.HumanPlayer;
import ch.unibas.dmi.dbis.cs108.gamelogic.klassenstruktur.Passenger;
import ch.unibas.dmi.dbis.cs108.highscore.OgGhostHighScore;
import ch.unibas.dmi.dbis.cs108.multiplayer.server.ClientHandler;
import ch.unibas.dmi.dbis.cs108.multiplayer.server.Lobby;
import java.util.HashSet;
@@ -64,6 +65,17 @@ public class Game implements Runnable {
isOngoing = ongoing;
}
Passenger getOgGhost(){
int[] order = gameState.getTrain().getOrderOfTrain();
Passenger[] passengerTrain = gameState.getPassengerTrain();
for (int i = 0; i < 6; i++) {
if (passengerTrain[i].getIsOG()) {
return passengerTrain[i];
}
}
return null;
}
/**
* Starts a new game, creates a passenger array and saves it in gameState, sets the OG
* currently at gameState.train[3] fills the passengerTrain moving from left to rigth in the
@@ -121,6 +133,9 @@ public class Game implements Runnable {
}
if (gameOverCheck.equals(ClientGameInfoHandler.gameOverGhostsWin) || gameOverCheck.equals(
ClientGameInfoHandler.gameOverHumansWin)) {
if (gameOverCheck.equals(ClientGameInfoHandler.gameOverGhostsWin) && getOgGhost().getIsPlayer()) {
OgGhostHighScore.addOgGhostWinner(getOgGhost().getName());
}
lobby.getAdmin().broadcastAnnouncementToLobby(gameOverCheck);
lobby.removeGameFromRunningGames(this);
lobby.addGameToFinishedGames(this);

View File

@@ -19,8 +19,8 @@ public class GameState {
**/
public final int nrOfPlayers; //sets the length of the train
public final int nrOfGhosts; // sets how many Ghosts we start witch
public final int nrOfUsers; // safes how many clients are active in this Game
public final Train train; // safes who sits where
public final int nrOfUsers; // saves how many clients are active in this Game
public final Train train; // saves who sits where
/**
* contains all Passengers on train, needs to be updated
*/

View File

@@ -15,15 +15,13 @@ public class NoiseHandler {
* predator infecting a victim, so if there are already multiple ghosts in the game, the method
* should be called for each of them individually.
* @param passengers passengers of the train the game is played in
* @param predator ghost that has infected a human player during this night (called upon as
* passenger for convenience reasons)
* @param victim human player who has been turned into a ghost this night
* @param noiseAmount array containing information about how many times each passenger heard a noise this night
* @param game current game instance
* @return updated array with info on who heard how many noises
*/
public int[] noiseNotifier(Passenger[] passengers, Passenger predator, Passenger victim, int[] noiseAmount, Game game) {
public int[] noiseNotifier(Passenger predator, Passenger victim, int[] noiseAmount) {
if (predator.getPosition() - victim.getPosition()
> 0) { // if predator is to the right of victim
for (int i = predator.getPosition() - 1; i > victim.getPosition(); i--) {

View File

@@ -59,7 +59,7 @@ public class VoteHandler {
int currentMax = ghostVoteEvaluation(passengers, votesForPlayers, game.getGameState().getClientVoteData(), game);
LOGGER.debug("Most votes: " + currentMax + " vote");
LOGGER.debug("Most votes: " + currentMax + " vote(s)");
// ghostify the player with most votes
int ghostPosition = 0;
@@ -98,7 +98,7 @@ public class VoteHandler {
for (int i = 0; i < passengers.length; i++) {
if (passengers[i].getIsGhost() && i != ghostPosition) {
NoiseHandler n = new NoiseHandler();
noiseAmount = n.noiseNotifier(passengers, passengers[i], g, noiseAmount, game);
noiseAmount = n.noiseNotifier(passengers[i], g, noiseAmount);
}
}
for (int i = 0; i < passengers.length; i++) {

View File

@@ -0,0 +1,110 @@
package ch.unibas.dmi.dbis.cs108.highscore;
import ch.unibas.dmi.dbis.cs108.BudaLogConfig;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* used for logging OG ghost highscore
*/
public class OgGhostHighScore {
public static final Logger LOGGER = LogManager.getLogger(OgGhostHighScore.class);
public static final BudaLogConfig l = new BudaLogConfig(LOGGER);
static ArrayList<String> ogGhostWinners = new ArrayList<>();
static final File ogGhostFile = new File("OgGhostWinners.txt");
/**
* Writes the current state of the ogGhostWinners String[] to the ogGhostFile, then closes
* the fileWriter.
*/
static void writeOgGhostWinnersToFile() {
try {
FileWriter fileWriter = new FileWriter(ogGhostFile, false);
for (String name : ogGhostWinners) {
fileWriter.write(name);
fileWriter.write(System.lineSeparator());
}
fileWriter.close();
} catch (Exception e) {
LOGGER.debug("Exception while trying to write ogGhostWinners to file.");
LOGGER.debug(e.getMessage());
}
}
/**
* adds the given name to the list of og ghost winners and updates the file listing the og ghost
* winners via writeOgGhostWinnersToFile
*/
public static void addOgGhostWinner(String name){
ogGhostWinners.add(name);
writeOgGhostWinnersToFile();
}
/**
* outputs the highscore list as it could be shown to clients.
* @return
*/
public static String formatGhostHighscoreList() {
//create the hashMap which lists all names along with their number of appearances
//int max = 0;
HashMap<String, Integer> hm = new HashMap<>();
for (String name: ogGhostWinners) {
if (hm.containsKey(name)) {
hm.replace(name, hm.get(name) + 1);
} else {
hm.put(name, 1);
}
//if (max < hm.get(name)) max = hm.get(name);
}
StringBuilder sb = new StringBuilder();
//add the 5 highest scoring peeps to the StringBuilder sb
for (int i = 0; i < 5; i++) {
//find first place among the remaining members of hm. ("remaining" because we remove people once theyre listed)
if (!hm.isEmpty()) {
String firstplace = (String) hm.keySet().toArray()[0]; //choose one candidate for first place just so we dont get null pointer
for (String name: hm.keySet()) {
if (hm.get(name) > hm.get(firstplace)) firstplace = name;
}
sb.append(firstplace).append(": ").append(hm.get(firstplace)).append(" wins.")
.append(System.lineSeparator());
hm.remove(firstplace);
}
}
return sb.toString();
}
/**
* reads the highscore file (or if not yet present create it) and reads the ogGhostWinners;
*/
public static void main(String[] args) {
try {
ogGhostWinners = new ArrayList<>();
//if not already present, the following creates the file.
//if already present, it reads what's already in the file into the ogGhostWinners array.
if (!ogGhostFile.createNewFile()) {
BufferedReader buffreader = new BufferedReader(new FileReader(ogGhostFile));
String line = buffreader.readLine();
while (line != null) {
ogGhostWinners.add(line);
line = buffreader.readLine();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@@ -98,6 +98,9 @@ public class MessageFormatter {
case "/s":
stringBuilder.append(Protocol.startANewGame);
break;
case "/h":
stringBuilder.append(Protocol.highScoreList);
break;
default:
s = msg;
}

View File

@@ -0,0 +1,5 @@
package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui;
public class ClientListViewController {
}

View File

@@ -0,0 +1,5 @@
package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui;
public class LobbySceneViewController {
}

View File

@@ -0,0 +1,5 @@
package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui;
public class ServerMessageViewController {
}

View File

@@ -0,0 +1,7 @@
package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.buttons;
import javafx.scene.control.Button;
public class ChangeNameButton extends Button {
}

View File

@@ -0,0 +1,7 @@
package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.buttons;
import java.awt.Button;
public class JoinGameButton extends Button {
}

View File

@@ -0,0 +1,7 @@
package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.buttons;
import javafx.scene.control.Button;
public class LeaveServerButton extends Button {
}

View File

@@ -0,0 +1,7 @@
package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.buttons;
import javafx.scene.control.Button;
public class NewGameButton extends Button {
}

View File

@@ -4,6 +4,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.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;
@@ -15,16 +17,23 @@ import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Group;
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;
@@ -33,6 +42,12 @@ public class ChatController implements Initializable {
public static final Logger LOGGER = LogManager.getLogger(ChatController.class);
public static final BudaLogConfig l = new BudaLogConfig(LOGGER);
@FXML
private Group vboxGroup;
@FXML
private GridPane vBoxGridPane;
@FXML
private ScrollPane ChatScrollPane;
@FXML
private VBox vBoxServerMessage;
@FXML
@@ -103,32 +118,23 @@ public class ChatController implements Initializable {
public void changed(ObservableValue<? extends Number> observable, Number oldValue,
Number newValue) {
vBoxChatMessages.setMaxHeight(newValue.doubleValue());
ChatScrollPane.setMaxHeight(newValue.doubleValue() * 2);
}
});
/**
* Initialize what happens when the send button is pressed
*/
sendButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
String msg = chatMsgField.getText().split("\\R")[0]; //cut off extra lines, if present.
if (!msg.isEmpty()) {
client.getClient().sendMsgToServer(cmd.toString() + msg);
LOGGER.info("Message trying to send is: " + cmd.toString() + msg);
Label l;
if (cmd.startsWith(whisper)) {
l = new Label("You whispered to " + whisperTargetSelectField.getText() + ": " + msg);
l.setBackground(Background.fill(Color.LAVENDERBLUSH));
} else {
l = new Label(client.getUsername() + " (you): " + msg);
l.setBackground(Background.fill(Color.LAVENDER));
}
vBoxChatMessages.getChildren().add(l);
chatMsgField.clear();
} else {
LOGGER.debug("Trying to send an empty message.");
}
sendChatMsg();
}
});
chatMsgField.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
sendChatMsg();
}
});
@@ -158,6 +164,33 @@ public class ChatController implements Initializable {
});
}
//TODO figure out if to use Text or Label & how to make wrapping work finally @Sebastian
private void sendChatMsg() {
String msg = chatMsgField.getText();//.split("\\R")[0]; //cut off extra lines, if present.
if (!msg.isEmpty()) {
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);
}
vBoxChatMessages.getChildren().add(l);
chatMsgField.clear();
} else {
LOGGER.debug("Trying to send an empty message.");
}
}
/**
* @return the ClientModel whose chat controller this is
*/
@@ -185,6 +218,8 @@ public class ChatController implements Initializable {
*/
public void addChatMsgToView(String msg) {
Label l = new Label(msg);
l.setWrapText(true);
l.setMaxHeight(Double.MAX_VALUE);
if (msg.contains("whispers")) {
l.setBackground(Background.fill(Color.SLATEBLUE));
} else {

View File

@@ -0,0 +1,17 @@
package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.events;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
public class ChangeNameButtonPressedEventHandler implements EventHandler<ActionEvent> {
/**
* Invoked when a specific event of the type for which this handler is registered happens.
*
* @param event the event which occurred
*/
@Override
public void handle(ActionEvent event) {
}
}

View File

@@ -0,0 +1,17 @@
package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.events;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
public class JoinGameButtonPressedEventHandler implements EventHandler<ActionEvent> {
/**
* Invoked when a specific event of the type for which this handler is registered happens.
*
* @param event the event which occurred
*/
@Override
public void handle(ActionEvent event) {
}
}

View File

@@ -0,0 +1,17 @@
package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.events;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
public class LeaveServerButtonPressedEventHandler implements EventHandler<ActionEvent> {
/**
* Invoked when a specific event of the type for which this handler is registered happens.
*
* @param event the event which occurred
*/
@Override
public void handle(ActionEvent event) {
}
}

View File

@@ -0,0 +1,17 @@
package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.events;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
public class NewGameButtonPressedEventHandler implements EventHandler<ActionEvent> {
/**
* Invoked when a specific event of the type for which this handler is registered happens.
*
* @param event the event which occurred
*/
@Override
public void handle(ActionEvent event) {
}
}

View File

@@ -0,0 +1,14 @@
package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.lounge;
import java.util.List;
import javafx.scene.control.Label;
import javafx.scene.control.ToggleButton;
public class LobbyListItem {
private Label lobbyID;
private Label adminName;
private List<String> clientInLobby;
private ToggleButton button;
}

View File

@@ -0,0 +1,5 @@
package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.lounge;
public class LoungeSceneViewController {
}

View File

@@ -138,6 +138,13 @@ public class Protocol {
*/
public static final String votedFor = "CVOTE";
/**
* Client requests high score list.
*/
public static final String highScoreList = "HSCOR";
//SERVER TO CLIENT COMMANDS

View File

@@ -4,6 +4,7 @@ import ch.unibas.dmi.dbis.cs108.BudaLogConfig;
import ch.unibas.dmi.dbis.cs108.gamelogic.Game;
import ch.unibas.dmi.dbis.cs108.gamelogic.TrainOverflow;
import ch.unibas.dmi.dbis.cs108.gamelogic.VoteHandler;
import ch.unibas.dmi.dbis.cs108.highscore.OgGhostHighScore;
import ch.unibas.dmi.dbis.cs108.multiplayer.helpers.Protocol;
import ch.unibas.dmi.dbis.cs108.multiplayer.helpers.ServerPinger;
@@ -594,4 +595,11 @@ public class ClientHandler implements Runnable {
}
public void sendHighScoreList() {
String list = OgGhostHighScore.formatGhostHighscoreList();
String[] listarray = list.split("\\R");
for (String s: listarray) {
sendAnnouncementToClient(s);
}
}
}

View File

@@ -109,6 +109,9 @@ public class JServerProtocolParser {
case Protocol.listGames:
h.listGames();
break;
case Protocol.highScoreList:
h.sendHighScoreList();
break;
default:
System.out.println("Received unknown command");
}

View File

@@ -2,6 +2,7 @@ package ch.unibas.dmi.dbis.cs108.multiplayer.server;
import ch.unibas.dmi.dbis.cs108.BudaLogConfig;
import ch.unibas.dmi.dbis.cs108.highscore.OgGhostHighScore;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
@@ -30,6 +31,7 @@ public class Server {
public void startServer() {
try {
System.out.println("Port " + gamePort + " is open.");
OgGhostHighScore.main(null);
while (!serverSocket.isClosed()) {
Socket socket = serverSocket.accept();
ClientHandler nextClient = new ClientHandler(socket, socket.getInetAddress());