feat: implemented callback-based message sending

This commit is contained in:
Yannik Bretschneider 2021-06-06 17:46:00 +02:00
parent 2acf340482
commit 6043a21e22

View File

@ -5,9 +5,10 @@ import org.tinylog.Logger;
import uulm.teamname.marvelous.gamelibrary.messages.BasicMessage; import uulm.teamname.marvelous.gamelibrary.messages.BasicMessage;
import uulm.teamname.marvelous.gamelibrary.messages.ParticipantType; import uulm.teamname.marvelous.gamelibrary.messages.ParticipantType;
import uulm.teamname.marvelous.gamelibrary.messages.RoleEnum; import uulm.teamname.marvelous.gamelibrary.messages.RoleEnum;
import uulm.teamname.marvelous.gamelibrary.messages.client.CharacterSelectionMessage;
import uulm.teamname.marvelous.gamelibrary.messages.client.PlayerReadyMessage; import uulm.teamname.marvelous.gamelibrary.messages.client.PlayerReadyMessage;
import uulm.teamname.marvelous.gamelibrary.messages.server.GameAssignmentMessage; import uulm.teamname.marvelous.gamelibrary.messages.client.RequestMessage;
import uulm.teamname.marvelous.server.Server; import uulm.teamname.marvelous.gamelibrary.messages.server.EventMessage;
import uulm.teamname.marvelous.server.lobby.Lobby; import uulm.teamname.marvelous.server.lobby.Lobby;
import java.util.HashMap; import java.util.HashMap;
@ -18,10 +19,15 @@ public class LobbyManager {
private final HashMap<Participant, LobbyConnection> lobbies; private final HashMap<Participant, LobbyConnection> lobbies;
private final HashMap<String, LobbyConnection> resourceDescriptorToLobby; private final HashMap<String, LobbyConnection> resourceDescriptorToLobby;
private String localResourceDescriptor; private String localResourceDescriptor;
private final BiConsumer<WebSocket, BasicMessage> sendMessageCallback;
private final BiConsumer<WebSocket, String> sendErrorCallback;
public LobbyManager() { public LobbyManager(BiConsumer<WebSocket, BasicMessage> sendMessageCallback,
BiConsumer<WebSocket, String> sendErrorCallback) {
this.lobbies = new HashMap<>(); this.lobbies = new HashMap<>();
this.resourceDescriptorToLobby = new HashMap<>(); this.resourceDescriptorToLobby = new HashMap<>();
this.sendMessageCallback = sendMessageCallback;
this.sendErrorCallback = sendErrorCallback;
} }
/** /**
@ -31,10 +37,12 @@ public class LobbyManager {
* to a lobby with a similar resourceDescriptor if the lobby they requested is already full * to a lobby with a similar resourceDescriptor if the lobby they requested is already full
* @param playerName is the name of the player be assigned to a lobby * @param playerName is the name of the player be assigned to a lobby
* @param message is the {@link PlayerReadyMessage} sent by the participant that triggered the LobbyAssignment * @param message is the {@link PlayerReadyMessage} sent by the participant that triggered the LobbyAssignment
* @return the {@link Participant} that was actually assigned to the lobby
*/ */
public void assignLobbyToParticipant(WebSocket connection, String playerName, PlayerReadyMessage message) { public Participant assignLobbyToConnection(WebSocket connection, String playerName, PlayerReadyMessage message) {
Logger.info("Assigning lobby to player '{}'", playerName); Logger.info("Assigning lobby to player '{}'", playerName);
// If no resourceDescriptor is given, generate new one
var resourceDescriptor = connection.getResourceDescriptor(); var resourceDescriptor = connection.getResourceDescriptor();
if (resourceDescriptor == null || resourceDescriptor.length() == 0) { if (resourceDescriptor == null || resourceDescriptor.length() == 0) {
Logger.trace("Resource descriptor is null, getting local one"); Logger.trace("Resource descriptor is null, getting local one");
@ -42,21 +50,30 @@ public class LobbyManager {
} }
LobbyConnection targetedLobby = resourceDescriptorToLobby.get(resourceDescriptor); LobbyConnection targetedLobby = resourceDescriptorToLobby.get(resourceDescriptor);
Participant participant;
if (targetedLobby == null || !targetedLobby.hasFreePlayerSpot()) { // If lobby is filled, generate a new ResourceDescriptor
if (targetedLobby == null) {
if (LobbyRunner.getInstance().canAddLobby()) {
Logger.info("Lobby '{}' is non-existent, initializing lobby...", resourceDescriptor);
targetedLobby = initializeNewLobby(resourceDescriptor);
} else {
Logger.info("No free lobby spot available, sending error and disconnecting Client");
}
} else if (targetedLobby.isFull() && !message.role.equals(RoleEnum.SPECTATOR)) {
Logger.info("Lobby '{}' is already full, assigning player '{}' to new lobby",
resourceDescriptor,
playerName);
resourceDescriptor = getLocalResourceDescriptor();
Logger.info("Lobby '{}' is non-existent, initializing lobby...", resourceDescriptor); Logger.info("Lobby '{}' is non-existent, initializing lobby...", resourceDescriptor);
targetedLobby = initializeNewLobby(resourceDescriptor); targetedLobby = initializeNewLobby(resourceDescriptor);
Logger.info("Adding mapping from resourceDescriptor {} to new lobby...", resourceDescriptor);
synchronized (resourceDescriptorToLobby) {
resourceDescriptorToLobby.put(resourceDescriptor, targetedLobby);
}
} }
Logger.trace("Obtaining lock on targetedLobby '{}'", targetedLobby.gameID); Logger.trace("Obtaining lock on targetedLobby '{}'", targetedLobby.gameID);
synchronized (targetedLobby) { synchronized (targetedLobby) {
Participant participant;
Logger.debug("Assigning participant to lobby"); Logger.debug("Assigning participant to lobby");
if (message.role.equals(RoleEnum.SPECTATOR)) { if (message.role.equals(RoleEnum.SPECTATOR)) {
Logger.trace("Generating new participant with type spectator"); Logger.trace("Generating new participant with type spectator");
@ -78,19 +95,60 @@ public class LobbyManager {
} }
} }
Logger.trace("Adding mapping from participant '{}' to lobby {}", Logger.trace("Adding mapping from participant '{}' to lobby '{}'",
participant.name, targetedLobby.gameID); participant.name, targetedLobby.gameID);
synchronized (lobbies) { synchronized (lobbies) {
lobbies.put(participant, targetedLobby); lobbies.put(participant, targetedLobby);
} }
Logger.trace("Relaying message to newly created Lobby"); if (targetedLobby.isFull() && !LobbyRunner.getInstance().isStarted(targetedLobby)) {
targetedLobby.receiveMessage(participant, message); Logger.info("Lobby '{}' was full, starting...", targetedLobby.gameID);
LobbyRunner.getInstance().startLobby(targetedLobby);
}
} }
return participant;
} }
public void relayMessageToLobby(Participant origin, CharacterSelectionMessage message) {
var targetedLobby = lobbies.get(origin);
if (targetedLobby == null) {
Logger.warn("Tried to send character selection message to non-existent lobby. This is probably a bug.");
} else if (!targetedLobby.isActive()) {
Logger.info("Tried sending message to inactive lobby, sending error...");
sendErrorCallback.accept(origin.getConnection(), "message could not be processed as " +
"lobby has not yet started as you are the only player in the lobby at the moment");
} else {
targetedLobby.receiveMessage(origin, message);
}
}
public void relayMessageToLobby(Participant origin, RequestMessage message) {
var targetedLobby = lobbies.get(origin);
if (targetedLobby == null) {
Logger.warn("Tried to send event message to non-existent lobby. This is probably a bug.");
} else if (!targetedLobby.isActive()) {
Logger.info("Tried sending message to inactive lobby, sending error...");
sendErrorCallback.accept(origin.getConnection(), "message could not be processed as " +
"lobby has not yet started as you are the only player in the lobby at the moment");
} else {
targetedLobby.receiveMessage(origin, message);
}
}
/**
* Initializes a new {@link LobbyConnection} with a not yet initialized {@link Lobby}. The {@link LobbyConnection}
* gets some GameID, and also the sendMessageCallback and sendErrorCallback from the
* {@link uulm.teamname.marvelous.server.netconnector.UserManager}.
* @param gameID is the ID that the {@link LobbyConnection} is initialized with. This is normally
* the resourceDescriptor.
* @return the newly initialized LobbyConnection
*/
private LobbyConnection initializeNewLobby(String gameID) { private LobbyConnection initializeNewLobby(String gameID) {
return new LobbyConnection(gameID); var lobby = new LobbyConnection(gameID, sendMessageCallback, sendErrorCallback);
Logger.debug("Adding mapping from gameID (resourceDescriptor) '{}' to new lobby...", gameID);
synchronized (resourceDescriptorToLobby) {
resourceDescriptorToLobby.put(gameID, lobby);
}
return lobby;
} }
/** /**
@ -106,7 +164,7 @@ public class LobbyManager {
} }
var lobby = resourceDescriptorToLobby.get(localResourceDescriptor); var lobby = resourceDescriptorToLobby.get(localResourceDescriptor);
if (lobby != null) { if (lobby != null) {
if (!lobby.hasFreePlayerSpot()) { if (lobby.isFull()) {
Logger.debug("Lobby is full, generating new local resourceDescriptor"); Logger.debug("Lobby is full, generating new local resourceDescriptor");
while (resourceDescriptorToLobby.get(localResourceDescriptor) != null) { while (resourceDescriptorToLobby.get(localResourceDescriptor) != null) {
localResourceDescriptor = RandomWordGenerator.generateTwoWords(); localResourceDescriptor = RandomWordGenerator.generateTwoWords();