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 670ec53..657a200 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 @@ -67,6 +67,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 ff7e783..5e7a66e 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 @@ -37,7 +37,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) */ 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 aacdf11..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 @@ -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; @@ -13,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; @@ -22,18 +19,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 +91,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 +110,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 +142,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 +166,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/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/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; + } + +} 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 @@ + + + + + + - + + + + + + +