- * Note that JavaFX has all the bind calls implemented through weak listeners. This means the - * bound property can be garbage collected and stopped from being updated. - * - * @param observable The observable this {@code Property} should be bound to. - * @throws NullPointerException if {@code observable} is {@code null} - */ - @Override - public void bind(ObservableValue observable) { - - } - - /** - * Remove the unidirectional binding for this {@code Property}. - *
- * If the {@code Property} is not bound, calling this method has no effect. - * - * @see #bind(ObservableValue) - */ - @Override - public void unbind() { - - } - - /** - * Can be used to check, if a {@code Property} is bound. - * - * @return {@code true} if the {@code Property} is bound, {@code false} otherwise - * @see #bind(ObservableValue) - */ - @Override - public boolean isBound() { - return false; - } - - /** - * Create a bidirectional binding between this {@code Property} and another one. Bidirectional - * bindings exists independently of unidirectional bindings. So it is possible to add - * unidirectional binding to a property with bidirectional binding and vice-versa. However, this - * practice is discouraged. - *
- * It is possible to have multiple bidirectional bindings of one Property. - *
- * JavaFX bidirectional binding implementation use weak listeners. This means bidirectional - * binding does not prevent properties from being garbage collected. - * - * @param other the other {@code Property} - * @throws NullPointerException if {@code other} is {@code null} - * @throws IllegalArgumentException if {@code other} is {@code this} - */ - @Override - public void bindBidirectional(Property other) { - - } - - /** - * Remove a bidirectional binding between this {@code Property} and another one. - *
- * If no bidirectional binding between the properties exists, calling this method has no effect. - *
- * It is possible to unbind by a call on the second property. This code will work: - * - *
- * - * @param other the other {@code Property} - * @throws NullPointerException if {@code other} is {@code null} - * @throws IllegalArgumentException if {@code other} is {@code this} - */ - @Override - public void unbindBidirectional(Property other) { - - } - - /** - * Returns the {@code Object} that contains this property. If this property is not contained in an - * {@code Object}, {@code null} is returned. - * - * @return the containing {@code Object} or {@code null} - */ - @Override - public Object getBean() { - return null; - } - - /** - * Returns the name of this property. If the property does not have a name, this method returns an - * empty {@code String}. - * - * @return the name or an empty {@code String} - */ - @Override - public String getName() { - return null; - } - - /** - * Adds a {@link ChangeListener} which will be notified whenever the value of the {@code - * ObservableValue} changes. If the same listener is added more than once, then it will be - * notified more than once. That is, no check is made to ensure uniqueness. - *- * property1.bindBirectional(property2); - * property2.unbindBidirectional(property1); - *
- * Note that the same actual {@code ChangeListener} instance may be safely registered for - * different {@code ObservableValues}. - *
- * The {@code ObservableValue} stores a strong reference to the listener which will prevent the - * listener from being garbage collected and may result in a memory leak. It is recommended to - * either unregister a listener by calling {@link #removeListener(ChangeListener) removeListener} - * after use or to use an instance of {@link WeakChangeListener} avoid this situation. - * - * @param listener The listener to register - * @throws NullPointerException if the listener is null - * @see #removeListener(ChangeListener) - */ - @Override - public void addListener(ChangeListener listener) { - - } - - /** - * Removes the given listener from the list of listeners that are notified whenever the value of - * the {@code ObservableValue} changes. - *
- * If the given listener has not been previously registered (i.e. it was never added) then this - * method call is a no-op. If it had been previously added then it will be removed. If it had been - * added more than once, then only the first occurrence will be removed. - * - * @param listener The listener to remove - * @throws NullPointerException if the listener is null - * @see #addListener(ChangeListener) - */ - @Override - public void removeListener(ChangeListener listener) { - - } - - /** - * Returns the current value of this {@code ObservableValue} - * - * @return The current value - */ - @Override - public String getValue() { - return this.incomingChatMsg; - } - - /** - * Set the wrapped value. - * - * @param value The new value - */ - @Override - public void setValue(Object value) { - this.incomingChatMsg = (String) value; - } - - /** - * Adds an {@link InvalidationListener} which will be notified whenever the {@code Observable} - * becomes invalid. If the same listener is added more than once, then it will be notified more - * than once. That is, no check is made to ensure uniqueness. - *
- * Note that the same actual {@code InvalidationListener} instance may be safely registered for - * different {@code Observables}. - *
- * The {@code Observable} stores a strong reference to the listener which will prevent the - * listener from being garbage collected and may result in a memory leak. It is recommended to - * either unregister a listener by calling {@link #removeListener(InvalidationListener) - * removeListener} after use or to use an instance of {@link WeakInvalidationListener} avoid this - * situation. - * - * @param listener The listener to register - * @throws NullPointerException if the listener is null - * @see #removeListener(InvalidationListener) - */ - @Override - public void addListener(InvalidationListener listener) { - - } - - /** - * Removes the given listener from the list of listeners, that are notified whenever the value of - * the {@code Observable} becomes invalid. - *
- * If the given listener has not been previously registered (i.e. it was never added) then this
- * method call is a no-op. If it had been previously added then it will be removed. If it had been
- * added more than once, then only the first occurrence will be removed.
- *
- * @param listener The listener to remove
- * @throws NullPointerException if the listener is null
- * @see #addListener(InvalidationListener)
- */
- @Override
- public void removeListener(InvalidationListener listener) {
-
- }
-}
diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/chat/NodeWithChildren.java b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/chat/NodeWithChildren.java
deleted file mode 100644
index 709c193..0000000
--- a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/chat/NodeWithChildren.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.chat;
-
-import javafx.scene.Node;
-
-/**
- * Any class that represents a JavaFX node and has children should implement this interface
- */
-public interface NodeWithChildren {
-
- void create();
-
- public default Node getChildren() {
- return null;
- }
-
- void createNodeHierarchy();
-}
diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/chat/OutChatObserver.java b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/chat/OutChatObserver.java
deleted file mode 100644
index aa93e98..0000000
--- a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/chat/OutChatObserver.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.chat;
-
-public interface OutChatObserver {
-
-}
diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/chat/OutMsgTargetChooserNode.java b/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/chat/OutMsgTargetChooserNode.java
deleted file mode 100644
index 0a54cbc..0000000
--- a/src/main/java/ch/unibas/dmi/dbis/cs108/multiplayer/client/gui/chat/OutMsgTargetChooserNode.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package ch.unibas.dmi.dbis.cs108.multiplayer.client.gui.chat;
-
-import javafx.collections.ObservableList;
-import javafx.scene.Node;
-import javafx.scene.control.Toggle;
-import javafx.scene.control.ToggleGroup;
-import javafx.scene.layout.HBox;
-import javafx.scene.layout.Pane;
-
-public class OutMsgTargetChooserNode extends ToggleGroup implements NodeWithChildren {
-
- private Pane root;
- private ObservableList
+ * In general, it is considered bad practice to modify the observed value in this method.
+ *
+ * @param observable The {@code ObservableValue} which value changed
+ * @param oldValue The old value
+ * @param newValue
+ */
+ @Override
+ public void changed(ObservableValue observable, Object oldValue, Object newValue) {
+
+ }
+}
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 5d09cbb..5ba0654 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
@@ -314,7 +314,6 @@ public class ClientHandler implements Runnable {
Thread t = new Thread(game);
t.start();
l.addGameToRunningGames(game);
- l.setLobbyIsOpen(false);
} else {
sendAnnouncementToClient("Only the admin can start the game");
}
@@ -378,9 +377,8 @@ public class ClientHandler implements Runnable {
}
/**
- * The client wants to join the lobby with the index i.
- * //todo: needs more doc.
- * @param i
+ * The client wants to join the lobby with the index i. If the lobby is closed, the client will be notified.
+ * @param i the number of the lobby to join
*/
public void joinLobby(int i) {
Lobby l = Lobby.getLobbyFromID(i);
@@ -388,7 +386,7 @@ public class ClientHandler implements Runnable {
if (l.getLobbyIsOpen()) {
l.addPlayer(this);
} else {
- sendAnnouncementToClient("The game in Lobby " + l.getLobbyID() + " has already started");
+ sendAnnouncementToClient("The game in Lobby " + l.getLobbyID() + " has already started, or the lobby is already full.");
}
} else {
sendAnnouncementToClient("Invalid Lobby nr.");
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 1fb87d4..5f5bb5b 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
@@ -23,6 +23,8 @@ public class Lobby {
* The currently ongoing game, is set, when a game is started
*/
private Game game;
+
+
/**
* true by default
* true if game has not started yet, false if game has. If true, potential players can still join the game.
@@ -31,6 +33,8 @@ public class Lobby {
*/
private boolean lobbyIsOpen = true;
+ private boolean gameIsRunning = false;
+
private static final int MAX_NO_OF_CLIENTS = 6;
@@ -119,6 +123,11 @@ public class Lobby {
}
public boolean getLobbyIsOpen() {
+ if (lobbyClients.size() >= MAX_NO_OF_CLIENTS || gameIsRunning ) {
+ setLobbyIsOpen(false);
+ } else {
+ setLobbyIsOpen(true);
+ }
return lobbyIsOpen;
}
@@ -135,12 +144,11 @@ public class Lobby {
this.lobbyIsOpen = lobbyIsOpen;
}
+
/**
* Returns the ID of the lobby that the client is in. If the client is not in any
* lobby, it returns -1.
*/
-
-
public static int clientIsInLobby(ClientHandler h) {
for (Lobby l: lobbies) {
for (ClientHandler clientHandler: l.getLobbyClients()) {
@@ -158,8 +166,7 @@ public class Lobby {
* @param client who wants to join the lobby.
*/
public synchronized boolean addPlayer(ClientHandler client) {
- if (lobbyClients.size() < MAX_NO_OF_CLIENTS) {
- //todo: check that game hasn't started yet (handled in cleintHandler)
+ if (getLobbyIsOpen()) {
if (clientIsInLobby(client) == -1) {
lobbyClients.add(client);
ClientHandler.broadcastAnnouncementToAll(client.getClientUserName() + " has joined lobby " + this.getLobbyID());
@@ -170,7 +177,7 @@ public class Lobby {
client.sendAnnouncementToClient("You are already in lobby nr. " + clientIsInLobby(client));
}
} else {
- client.sendAnnouncementToClient("This lobby is full. Please try joining a different lobby or create a new lobby");
+ client.sendAnnouncementToClient("This lobby is closed. Please try joining a different lobby or create a new lobby");
}
return false;
}
@@ -195,11 +202,19 @@ public class Lobby {
return false;
}
+ /**
+ * Adds game to list of running games and sets its lobby's gameIsRunning to true.
+ */
public void addGameToRunningGames(Game game) {
+ game.getLobby().gameIsRunning = true;
runningGames.add(game);
}
+ /**
+ * Removes game from list of running games and sets its lobby's gameIsRunning to false.
+ */
public void removeGameFromRunningGames(Game game) {
+ game.getLobby().gameIsRunning = false;
runningGames.remove(game);
}
@@ -213,9 +228,10 @@ public class Lobby {
*/
public void closeLobby() {
lobbies.remove(this);
- ClientHandler.broadcastAnnouncementToAll("Lobby nr. " + this.getLobbyID() + " has been closed.");
+ //ClientHandler.broadcastAnnouncementToAll("Lobby nr. " + this.getLobbyID() + " has been closed.");
/*
+ TODO: close game when lobby is closed
Todo: theoretically, this is enough to close a lobby.
ClientHandlers dont have to manually be removed from the lobby
since if the lobby is removed from the lobbies
diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/resources/splitPaneChatView.fxml b/src/main/java/ch/unibas/dmi/dbis/cs108/resources/splitPaneChatView.fxml
new file mode 100644
index 0000000..1ae8b3e
--- /dev/null
+++ b/src/main/java/ch/unibas/dmi/dbis/cs108/resources/splitPaneChatView.fxml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+