diff --git a/Server/src/main/java/uulm/teamname/marvelous/server/netconnector/UserManager.java b/Server/src/main/java/uulm/teamname/marvelous/server/netconnector/UserManager.java
index d4fec75..627bd1a 100644
--- a/Server/src/main/java/uulm/teamname/marvelous/server/netconnector/UserManager.java
+++ b/Server/src/main/java/uulm/teamname/marvelous/server/netconnector/UserManager.java
@@ -8,15 +8,18 @@ import uulm.teamname.marvelous.gamelibrary.messages.ErrorMessage;
import uulm.teamname.marvelous.gamelibrary.messages.client.*;
import uulm.teamname.marvelous.gamelibrary.messages.server.HelloClientMessage;
import uulm.teamname.marvelous.server.Server;
+import uulm.teamname.marvelous.server.lobbymanager.LobbyManager;
import uulm.teamname.marvelous.server.lobbymanager.Participant;
import org.java_websocket.WebSocket;
import java.util.*;
-/** Class that manages users. It is meant as an extension to the {@link MarvelousServer} class, and should not be called
- * from anywhere else. This is the first place where messages are relayed to after they get received. This class is
- * responsible for handshakes, reconnects and WebSocket-to-Participant matching. It is not thread-safe.
+/** Class that manages users. It is meant as an extension to the {@link MarvelousServer} class. This is the first
+ * place where messages are relayed to after they get received. This class is
+ * responsible for handshakes, reconnects and WebSocket-to-Participant matching.
+ * It is designed to be thread-safe. The Singleton of this class also contains a
+ * {@link LobbyManager}, which manages the lobbys.
*/
public class UserManager {
@@ -33,6 +36,10 @@ public class UserManager {
return instance;
}
+ /** The {@link LobbyManager} associated with the {@link UserManager}. It is therefore a kind of extension
+ * to the current singleton, and may of course not be called from anywhere else */
+ private final LobbyManager lobbyManager;
+
/** A set of users that aren't assigned to lobbies or character selection yet */
private final HashSet newUsers;
@@ -64,12 +71,19 @@ public class UserManager {
this.readyToReconnect = new HashMap<>();
this.inGame = new HashMap<>();
this.activeParticipants = new HashMap<>();
+
+ Logger.trace("Instantiating LobbyManager with message sending callbacks");
+ this.lobbyManager = new LobbyManager(this::sendMessage, this::sendError);
+
+ Logger.trace("Instantiating JSON with the server's CharacterConfig");
this.json = new JSON(Server.getCharacterConfig());
}
/** Called on a new WebSocket connection. Places the WebSocket and its ResourceDescriptor in a HashMap. */
void connectUser(WebSocket conn) {
- newUsers.add(conn);
+ synchronized (newUsers) {
+ newUsers.add(conn);
+ }
}
/**
@@ -106,7 +120,15 @@ public class UserManager {
} else if (parsedMessage instanceof PlayerReadyMessage) {
Logger.trace("Message is instanceof PlayerReadyMessage, assigning lobby");
assignLobby(conn, (PlayerReadyMessage) parsedMessage);
- } else {
+ } else if (parsedMessage instanceof CharacterSelectionMessage) {
+ Logger.trace("Message is instanceof CharacterSelectionMessage, passing to LobbyConnection");
+ charactersSelected(conn, (CharacterSelectionMessage) parsedMessage);
+ } else if (parsedMessage instanceof RequestMessage) {
+ Logger.trace("Message is instanceof RequestMessage, passing to LobbyConnection");
+ relayRequestMessage(conn, (RequestMessage) parsedMessage);
+ }
+
+ else {
Logger.debug("Message '{}' has invalid type, Error will be sent");
sendError(conn, String.format(
"Message '%s' has invalid type, and cannot be processed on the server",
@@ -186,13 +208,48 @@ public class UserManager {
}
void assignLobby(WebSocket conn, PlayerReadyMessage message) {
- // TODO: Assign a lobby
+ if (readyToReconnect.containsKey(conn) || readyToConnect.containsKey(conn)) {
+ if (readyToConnect.containsKey(conn)) {
+ synchronized (readyToConnect) {
+ readyToConnect.remove(conn);
+ }
+ } else {
+ synchronized (readyToReconnect) {
+ readyToReconnect.remove(conn);
+ }
+ }
+ synchronized (inGame) {
+ var participant = lobbyManager.assignLobbyToConnection(conn, "SomeName", message);
+ inGame.put(conn, participant);
+ }
+ } else {
+ Logger.debug(
+ "WebSocket {} sent PlayerReadyMessage to server while not ready to connect, sending error",
+ conn);
+ sendError(conn, "Invalid message, as client is not ready to connect");
+ }
}
void charactersSelected(WebSocket conn, CharacterSelectionMessage message) {
+ if (inGame.containsKey(conn)) {
+ lobbyManager.relayMessageToLobby(inGame.get(conn), message);
+ } else {
+ Logger.debug(
+ "WebSocket {} sent CharacterSelectionMessage to server while not ingame, sending error",
+ conn);
+ sendError(conn, "Invalid message, as client is not ingame");
+ }
}
- void relayRequestMessage(Participant conn, RequestMessage message) {
+ void relayRequestMessage(WebSocket conn, RequestMessage message) {
+ if (inGame.containsKey(conn)) {
+ lobbyManager.relayMessageToLobby(inGame.get(conn), message);
+ } else {
+ Logger.debug(
+ "WebSocket {} sent RequestMessage to server while not ingame, sending error",
+ conn);
+ sendError(conn, "Invalid message, as client is not ingame");
+ }
}
void disconnectUser(WebSocket conn, boolean closedByRemote) {
@@ -200,22 +257,33 @@ public class UserManager {
synchronized (newUsers) {
newUsers.remove(conn);
}
+ synchronized (readyToConnect) {
+ readyToConnect.remove(conn);
+ }
+ synchronized (readyToReconnect) {
+ readyToReconnect.remove(conn);
+ }
synchronized (inGame) {
inGame.remove(conn);
}
}
- public void sendMessage(WebSocket conn, BasicMessage message) {
- var jsonRepresentingMessage = json.stringify(message);
- if (jsonRepresentingMessage.isEmpty()) {
- Logger.warn("Message {} could not be serialized!", message);
+ void sendMessage(WebSocket conn, BasicMessage message) {
+ Logger.trace("Sending message to WebSocket {}", conn);
+ if (conn == null) {
+ Logger.debug("Message sent to non-existent websocket, ignoring");
} else {
- conn.send(jsonRepresentingMessage.get());
+ var jsonRepresentingMessage = json.stringify(message);
+ if (jsonRepresentingMessage.isEmpty()) {
+ Logger.warn("Message {} could not be serialized!", message);
+ } else {
+ conn.send(jsonRepresentingMessage.get());
+ }
}
}
/** Sends an {@link uulm.teamname.marvelous.gamelibrary.messages.ErrorMessage} to the specified user. */
- public void sendError(WebSocket conn, String error) {
+ void sendError(WebSocket conn, String error) {
Logger.debug("Sending error message '{}' to WebSocket {}", error, conn);
var errorMessage = new ErrorMessage();
errorMessage.message = error;
@@ -230,6 +298,7 @@ public class UserManager {
}
public int getUserCount() {
+ // FIXME: This is bugged at the moment
return newUsers.size() + readyToConnect.size() + readyToReconnect.size() + inGame.size();
}