feat: partially implemented GameAssignment
This commit is contained in:
parent
7ce16fd81f
commit
02b2a58cce
@ -12,32 +12,29 @@ public class MarvelousServer extends WebSocketServer {
|
|||||||
@Override
|
@Override
|
||||||
public void onOpen(WebSocket conn, ClientHandshake handshake) {
|
public void onOpen(WebSocket conn, ClientHandshake handshake) {
|
||||||
Logger.info("New client connected. Adding new User.");
|
Logger.info("New client connected. Adding new User.");
|
||||||
userManager.connectUser(conn, handshake);
|
userManager.connectUser(conn);
|
||||||
// TODO: Send messages to UserManager, which then packages that stuff and sends it further
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
|
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
|
||||||
Logger.info("Client disconnected");
|
Logger.info("Client disconnected");
|
||||||
userManager.disconnectUser(conn, remote);
|
userManager.disconnectUser(conn, remote);
|
||||||
// TODO: Send messages to UserManager, which then removes the user and such
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessage(WebSocket conn, String message) {
|
public void onMessage(WebSocket conn, String message) {
|
||||||
Logger.debug("Message received: {}", message);
|
Logger.debug("Message received: {}", message);
|
||||||
userManager.messageReceived(conn, message);
|
userManager.messageReceived(conn, message);
|
||||||
// TODO: Send messages to UserManager, which then packages them and sends them further
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(WebSocket conn, Exception ex) {
|
public void onError(WebSocket conn, Exception ex) {
|
||||||
// TODO: Send errors to UserManager, which then answers with even more errors
|
Logger.warn("WebSocket-Error occurred: {}", ex.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
// TODO: Get the UserManager, and tell it that this thing is active
|
Logger.info("MarvelousServer started on Address {}", this.getAddress().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private final UserManager userManager;
|
private final UserManager userManager;
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
package uulm.teamname.marvelous.server.netconnector;
|
package uulm.teamname.marvelous.server.netconnector;
|
||||||
|
|
||||||
import org.java_websocket.handshake.ClientHandshake;
|
|
||||||
import org.tinylog.Logger;
|
import org.tinylog.Logger;
|
||||||
import uulm.teamname.marvelous.gamelibrary.json.JSON;
|
import uulm.teamname.marvelous.gamelibrary.json.JSON;
|
||||||
import uulm.teamname.marvelous.gamelibrary.messages.BasicMessage;
|
import uulm.teamname.marvelous.gamelibrary.json.ValidationUtility;
|
||||||
import uulm.teamname.marvelous.gamelibrary.messages.ErrorMessage;
|
import uulm.teamname.marvelous.gamelibrary.messages.ErrorMessage;
|
||||||
import uulm.teamname.marvelous.gamelibrary.messages.client.*;
|
import uulm.teamname.marvelous.gamelibrary.messages.client.*;
|
||||||
import uulm.teamname.marvelous.server.lobbymanager.Participant;
|
import uulm.teamname.marvelous.server.lobbymanager.Participant;
|
||||||
@ -12,13 +11,17 @@ import org.java_websocket.WebSocket;
|
|||||||
|
|
||||||
import java.util.*;
|
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. <b>It is not thread-safe.</b>
|
||||||
|
*/
|
||||||
public class UserManager {
|
public class UserManager {
|
||||||
|
|
||||||
/** A set of users that aren't assigned to lobbies or character selection yet */
|
/** A set of users that aren't assigned to lobbies or character selection yet */
|
||||||
private final HashSet<WebSocket> newUsers;
|
private final HashSet<WebSocket> newUsers;
|
||||||
|
|
||||||
/** A set of users that can reconnect if they wish to do so, and their matching Participants */
|
/** A set of users that can reconnect if they wish to do so, and their matching Participants */
|
||||||
private final HashMap<WebSocket, Participant> readyToReconnect;
|
private final HashMap<WebSocket, SUID> readyToReconnect;
|
||||||
|
|
||||||
/** A set of users that only have to send the
|
/** A set of users that only have to send the
|
||||||
* {@link uulm.teamname.marvelous.gamelibrary.messages.client.PlayerReadyMessage} to be assigned
|
* {@link uulm.teamname.marvelous.gamelibrary.messages.client.PlayerReadyMessage} to be assigned
|
||||||
@ -49,24 +52,51 @@ public class UserManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Called on a new WebSocket connection. Places the WebSocket and its ResourceDescriptor in a HashMap. */
|
/** Called on a new WebSocket connection. Places the WebSocket and its ResourceDescriptor in a HashMap. */
|
||||||
public void connectUser(WebSocket conn, ClientHandshake handshake) {
|
public void connectUser(WebSocket conn) {
|
||||||
synchronized (newUsers) {
|
newUsers.add(conn);
|
||||||
newUsers.add(conn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called on any received messages. The method checks the message for validity, and then relays it
|
||||||
|
* accordingly. {@link HelloServerMessage HelloServerMessages} and {@link ReconnectMessage ReconnectMessages}
|
||||||
|
* are handled in this component, whereby a handshake or reconnect is performed, respectively.
|
||||||
|
* @param conn is the {@link WebSocket} that sent the message
|
||||||
|
* @param message is the {@link String} sent by the connection
|
||||||
|
*/
|
||||||
public void messageReceived(WebSocket conn, String message) {
|
public void messageReceived(WebSocket conn, String message) {
|
||||||
// TODO: Implement more than only a basic handshake
|
Logger.trace("Parsing message...");
|
||||||
|
|
||||||
var parsedMessageOptional = json.parse(message);
|
var parsedMessageOptional = json.parse(message);
|
||||||
if (parsedMessageOptional.isEmpty()) {
|
if (parsedMessageOptional.isEmpty()) {
|
||||||
Logger.debug("Invalid message '{}' received, sending error", message);
|
Logger.debug("Message '{}' was invalid, sending error", message);
|
||||||
sendError(conn, "Message could not be parsed");
|
sendError(conn, "Message could not be parsed");
|
||||||
} else {
|
} else {
|
||||||
var parsedMessage = parsedMessageOptional.get();
|
var parsedMessage = parsedMessageOptional.get();
|
||||||
|
|
||||||
if (parsedMessage instanceof HelloServerMessage)
|
Logger.trace("Validating message...");
|
||||||
handshake(conn, (HelloServerMessage) parsedMessage);
|
var violations = ValidationUtility.validate(parsedMessage);
|
||||||
|
|
||||||
|
if (violations.isPresent()) {
|
||||||
|
Logger.debug("Message '{}' was invalid: {}, sending error", message, violations.get());
|
||||||
|
sendError(conn, violations.get());
|
||||||
|
} else {
|
||||||
|
Logger.trace("Message was valid. Checking type of message...");
|
||||||
|
|
||||||
|
if (parsedMessage instanceof HelloServerMessage) {
|
||||||
|
Logger.trace("Message is instanceof HelloServerMessage, initiating handshake");
|
||||||
|
handshake(conn, (HelloServerMessage) parsedMessage);
|
||||||
|
} else if (parsedMessage instanceof ReconnectMessage) {
|
||||||
|
Logger.trace("Message is instanceof ReconnectMessage, initiating reconnect");
|
||||||
|
reconnectClient(conn, (ReconnectMessage) parsedMessage);
|
||||||
|
} else if (parsedMessage instanceof PlayerReadyMessage) {
|
||||||
|
Logger.trace("Message is instanceof PlayerReadyMessage, assigning lobby");
|
||||||
|
assignLobby(conn, (PlayerReadyMessage) 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",
|
||||||
|
message));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +115,7 @@ public class UserManager {
|
|||||||
var participant = activeParticipants.get(clientID);
|
var participant = activeParticipants.get(clientID);
|
||||||
if (participant != null) {
|
if (participant != null) {
|
||||||
synchronized (readyToReconnect) {
|
synchronized (readyToReconnect) {
|
||||||
readyToReconnect.put(conn, participant);
|
readyToReconnect.put(conn, clientID);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Logger.trace("removing handshaking user from newUsers");
|
Logger.trace("removing handshaking user from newUsers");
|
||||||
@ -99,33 +129,37 @@ public class UserManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reconnectClient(WebSocket conn, ReconnectMessage message) {
|
void reconnectClient(WebSocket conn, ReconnectMessage message) {
|
||||||
if (!readyToConnect.containsKey(conn)) {
|
if (!readyToReconnect.containsKey(conn)) {
|
||||||
Logger.debug("Non-reconnect-allowed client has sent reconnect message, sending error");
|
Logger.debug("Non-reconnect-allowed client has sent reconnect message, sending error");
|
||||||
sendError(conn, "Reconnect is not possible");
|
sendError(conn, "Reconnect is not possible");
|
||||||
return;
|
} else if (message.reconnect) {
|
||||||
}
|
Logger.info("Reconnecting client {} to their lobby", conn);
|
||||||
Logger.info("Reconnecting client {} to their lobby");
|
var clientID = readyToReconnect.get(conn);
|
||||||
var participantToRestore = readyToReconnect.get(conn);
|
var participantToRestore = activeParticipants.get(clientID);
|
||||||
synchronized (participantToRestore) {
|
|
||||||
participantToRestore.setConnection(conn);
|
participantToRestore.setConnection(conn);
|
||||||
}
|
readyToReconnect.remove(conn);
|
||||||
synchronized (readyToReconnect) {
|
inGame.put(conn, participantToRestore);
|
||||||
|
// activeParticipants remains the same, as no players have been removed from the game
|
||||||
|
} else {
|
||||||
|
Logger.debug(
|
||||||
|
"Client {} refused reconnection, will therefore be put into readyToConnect clients",
|
||||||
|
conn);
|
||||||
|
|
||||||
|
var clientID = readyToReconnect.get(conn);
|
||||||
|
readyToConnect.put(conn, clientID);
|
||||||
readyToReconnect.remove(conn);
|
readyToReconnect.remove(conn);
|
||||||
}
|
}
|
||||||
synchronized (inGame) {
|
|
||||||
inGame.put(conn, participantToRestore);
|
|
||||||
}
|
|
||||||
// activeParticipants remains the same, as no players have been removed from the game
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assignLobby(WebSocket conn, PlayerReadyMessage message) {
|
void assignLobby(WebSocket conn, PlayerReadyMessage message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void charactersSelected(WebSocket conn, CharacterSelectionMessage message) {
|
void charactersSelected(WebSocket conn, CharacterSelectionMessage message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void relayRequestMessage(Participant conn, RequestMessage message) {
|
void relayRequestMessage(Participant conn, RequestMessage message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sends an {@link uulm.teamname.marvelous.gamelibrary.messages.ErrorMessage} to the specified user. */
|
/** Sends an {@link uulm.teamname.marvelous.gamelibrary.messages.ErrorMessage} to the specified user. */
|
||||||
@ -158,26 +192,31 @@ public class UserManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Package-private getter for mutable newUsers HashSet, meant for testing */
|
/** Package-private getter for mutable newUsers HashSet, meant for testing */
|
||||||
|
@Deprecated
|
||||||
HashSet<WebSocket> getNewUsers() {
|
HashSet<WebSocket> getNewUsers() {
|
||||||
return newUsers;
|
return newUsers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Package-private getter for mutable readyToReconnect HashMap, meant for testing */
|
/** Package-private getter for mutable readyToReconnect HashMap, meant for testing */
|
||||||
HashMap<WebSocket, Participant> getReadyToReconnect() {
|
@Deprecated
|
||||||
|
HashMap<WebSocket, SUID> getReadyToReconnect() {
|
||||||
return readyToReconnect;
|
return readyToReconnect;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Package-private getter for mutable readyToConnect HashMap, meant for testing */
|
/** Package-private getter for mutable readyToConnect HashMap, meant for testing */
|
||||||
|
@Deprecated
|
||||||
HashMap<WebSocket, SUID> getReadyToConnect() {
|
HashMap<WebSocket, SUID> getReadyToConnect() {
|
||||||
return readyToConnect;
|
return readyToConnect;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Package-private getter for mutable inGame HashMap, meant for testing */
|
/** Package-private getter for mutable inGame HashMap, meant for testing */
|
||||||
|
@Deprecated
|
||||||
HashMap<WebSocket, Participant> getInGame() {
|
HashMap<WebSocket, Participant> getInGame() {
|
||||||
return inGame;
|
return inGame;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Package-private getter for mutable activeParticipants HashMap, meant for testing */
|
/** Package-private getter for mutable activeParticipants HashMap, meant for testing */
|
||||||
|
@Deprecated
|
||||||
HashMap<SUID, Participant> getActiveParticipants() {
|
HashMap<SUID, Participant> getActiveParticipants() {
|
||||||
return activeParticipants;
|
return activeParticipants;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user