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
1 changed files with 76 additions and 18 deletions

View File

@ -5,9 +5,10 @@ import org.tinylog.Logger;
import uulm.teamname.marvelous.gamelibrary.messages.BasicMessage;
import uulm.teamname.marvelous.gamelibrary.messages.ParticipantType;
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.server.GameAssignmentMessage;
import uulm.teamname.marvelous.server.Server;
import uulm.teamname.marvelous.gamelibrary.messages.client.RequestMessage;
import uulm.teamname.marvelous.gamelibrary.messages.server.EventMessage;
import uulm.teamname.marvelous.server.lobby.Lobby;
import java.util.HashMap;
@ -18,10 +19,15 @@ public class LobbyManager {
private final HashMap<Participant, LobbyConnection> lobbies;
private final HashMap<String, LobbyConnection> resourceDescriptorToLobby;
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.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
* @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
* @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);
// If no resourceDescriptor is given, generate new one
var resourceDescriptor = connection.getResourceDescriptor();
if (resourceDescriptor == null || resourceDescriptor.length() == 0) {
Logger.trace("Resource descriptor is null, getting local one");
@ -42,21 +50,30 @@ public class LobbyManager {
}
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);
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);
synchronized (targetedLobby) {
Participant participant;
Logger.debug("Assigning participant to lobby");
if (message.role.equals(RoleEnum.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);
synchronized (lobbies) {
lobbies.put(participant, targetedLobby);
}
Logger.trace("Relaying message to newly created Lobby");
targetedLobby.receiveMessage(participant, message);
if (targetedLobby.isFull() && !LobbyRunner.getInstance().isStarted(targetedLobby)) {
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) {
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);
if (lobby != null) {
if (!lobby.hasFreePlayerSpot()) {
if (lobby.isFull()) {
Logger.debug("Lobby is full, generating new local resourceDescriptor");
while (resourceDescriptorToLobby.get(localResourceDescriptor) != null) {
localResourceDescriptor = RandomWordGenerator.generateTwoWords();