feat: partially implemented not yet refactored lobbyManager
This commit is contained in:
parent
e7a8f0e1e4
commit
7db692f790
@ -1,48 +1,196 @@
|
|||||||
package uulm.teamname.marvelous.server.lobbymanager;
|
package uulm.teamname.marvelous.server.lobbymanager;
|
||||||
|
|
||||||
import org.tinylog.Logger;
|
import org.tinylog.Logger;
|
||||||
import uulm.teamname.marvelous.gamelibrary.config.CharacterConfig;
|
import uulm.teamname.marvelous.gamelibrary.Tuple;
|
||||||
import uulm.teamname.marvelous.gamelibrary.config.PartyConfig;
|
import uulm.teamname.marvelous.gamelibrary.config.CharacterProperties;
|
||||||
import uulm.teamname.marvelous.gamelibrary.config.ScenarioConfig;
|
|
||||||
import uulm.teamname.marvelous.gamelibrary.events.Event;
|
import uulm.teamname.marvelous.gamelibrary.events.Event;
|
||||||
|
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.requests.Request;
|
import uulm.teamname.marvelous.gamelibrary.messages.client.CharacterSelectionMessage;
|
||||||
|
import uulm.teamname.marvelous.gamelibrary.messages.client.RequestMessage;
|
||||||
|
import uulm.teamname.marvelous.gamelibrary.messages.server.GameAssignmentMessage;
|
||||||
|
import uulm.teamname.marvelous.server.Server;
|
||||||
import uulm.teamname.marvelous.server.lobby.Lobby;
|
import uulm.teamname.marvelous.server.lobby.Lobby;
|
||||||
|
import uulm.teamname.marvelous.server.netconnector.UserManager;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.*;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class that handles the connection to the lobby. It contains distinct websockets for player1, player2 and spectators.
|
* A class that handles the connection to the lobby. It contains the participants inside of the lobby.
|
||||||
* The class is meant to be used in conjecture with {@link MessageRelay}.
|
* The class is meant to be used in conjecture with {@link MessageRelay}.
|
||||||
*/
|
*/
|
||||||
public class LobbyConnection implements Runnable {
|
public class LobbyConnection implements Runnable {
|
||||||
private final Lobby lobby;
|
private Lobby lobby;
|
||||||
public final String gameID;
|
public final String gameID;
|
||||||
private Participant player1, player2;
|
private Participant player1, player2;
|
||||||
|
private boolean characterSelection;
|
||||||
|
|
||||||
|
/** Whether the character selection phase is reached */
|
||||||
|
private boolean inGame;
|
||||||
private final HashSet<Participant> spectators;
|
private final HashSet<Participant> spectators;
|
||||||
private final BlockingQueue<Request[]> incomingRequests;
|
private final BlockingQueue<Tuple<Participant, BasicMessage>> incomingMessages;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback executed to send a message, originating from the
|
||||||
|
* {@link uulm.teamname.marvelous.server.netconnector.UserManager}
|
||||||
|
*/
|
||||||
|
private final BiConsumer<Participant, BasicMessage> sendMessageCallback;
|
||||||
|
|
||||||
// TODO: FIX THIS JAVADOC
|
// TODO: FIX THIS JAVADOC
|
||||||
/**
|
/** Creates a new LobbyConnection */
|
||||||
* Creates a new LobbyConnection, whereby a new {@link Lobby} is initialized.
|
public LobbyConnection(String gameID, BiConsumer<Participant, BasicMessage> sendMessageCallback) {
|
||||||
*/
|
this.gameID = gameID;
|
||||||
public LobbyConnection(String gameID,
|
this.sendMessageCallback = sendMessageCallback;
|
||||||
PartyConfig partyConfig,
|
this.spectators = new HashSet<>(10);
|
||||||
CharacterConfig characterConfig,
|
this.incomingMessages = new LinkedBlockingQueue<>();
|
||||||
ScenarioConfig scenarioConfig) {
|
this.characterSelection = false;
|
||||||
|
this.inGame = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Logger.info("Starting Lobby thread for lobby '{}'", gameID);
|
||||||
|
Logger.trace("Initializing lobby...");
|
||||||
|
initializeLobby();
|
||||||
|
|
||||||
|
Logger.trace("Activating characterSelection state");
|
||||||
|
this.characterSelection = true;
|
||||||
|
|
||||||
|
|
||||||
|
Logger.info("Starting character selection process");
|
||||||
|
Logger.trace("Finding twenty-four random characters");
|
||||||
|
Tuple<CharacterProperties[], CharacterProperties[]> selectionPossibilities =
|
||||||
|
Server.getCharacterConfig().getDisjointSetsOfPropertiesOfSize(12);
|
||||||
|
|
||||||
|
Logger.info("Sending GameAssignment message with random characters to players");
|
||||||
|
var gameAssignmentMessage = new GameAssignmentMessage();
|
||||||
|
gameAssignmentMessage.gameID = this.gameID;
|
||||||
|
|
||||||
|
// Send to player one with characters for player one
|
||||||
|
gameAssignmentMessage.characterSelection = selectionPossibilities.item1;
|
||||||
|
UserManager.getInstance().sendMessage(player1.getConnection(), gameAssignmentMessage);
|
||||||
|
|
||||||
|
// And send the others to player 2
|
||||||
|
gameAssignmentMessage.characterSelection = selectionPossibilities.item2;
|
||||||
|
UserManager.getInstance().sendMessage(player2.getConnection(), gameAssignmentMessage);
|
||||||
|
|
||||||
|
CharacterProperties[] playerOneSelection = null;
|
||||||
|
CharacterProperties[] playerTwoSelection = null;
|
||||||
|
|
||||||
|
Logger.info("Entering GameAssignment state. Waiting for answer about selected characters from players.");
|
||||||
|
while (characterSelection) {
|
||||||
|
Tuple<Participant, BasicMessage> currentMessage = null;
|
||||||
|
|
||||||
|
try { // TODO: Exact duplication. Maybe extract?
|
||||||
|
Logger.trace("Checking for messages. Currently the amount of messages is {}",
|
||||||
|
incomingMessages.size());
|
||||||
|
|
||||||
|
if (incomingMessages.isEmpty()) {
|
||||||
|
Logger.trace("LobbyConnection thread waiting for new messages...");
|
||||||
|
Thread.currentThread().wait();
|
||||||
|
Logger.trace("Lobby '{}' woken up", gameID);
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.trace("Polling incoming message queue");
|
||||||
|
currentMessage = incomingMessages.poll(100, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Logger.warn("LobbyConnection thread got interrupted. Exception: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentMessage == null) {
|
||||||
|
continue;
|
||||||
|
} else if (currentMessage.item2 instanceof CharacterSelectionMessage) {
|
||||||
|
var origin = currentMessage.item1;
|
||||||
|
var message = (CharacterSelectionMessage) currentMessage.item2;
|
||||||
|
if (origin.type.equals(ParticipantType.Spectator)) {
|
||||||
|
Logger.info("Spectator sent CharacterSelectionMessage. Sending error...");
|
||||||
|
UserManager.getInstance().sendError(
|
||||||
|
origin.getConnection(),
|
||||||
|
"Spectators can't select characters");
|
||||||
|
} else if (origin.type.equals(ParticipantType.PlayerOne)) {
|
||||||
|
if (playerOneSelection == null) { // TODO: Extract this. This isn't beautiful at all.
|
||||||
|
ArrayList<CharacterProperties> chosenCharacters = new ArrayList<>();
|
||||||
|
for (int i = 0; i < 12; i++) {
|
||||||
|
if (message.characters[i]) {
|
||||||
|
chosenCharacters.add(selectionPossibilities.item1[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
playerOneSelection = chosenCharacters.toArray(new CharacterProperties[0]);
|
||||||
|
}
|
||||||
|
Logger.info("Player 1 has selected their characters");
|
||||||
|
} else {
|
||||||
|
if (playerTwoSelection == null) {
|
||||||
|
ArrayList<CharacterProperties> chosenCharacters = new ArrayList<>();
|
||||||
|
for (int i = 0; i < 12; i++) {
|
||||||
|
if (message.characters[i]) {
|
||||||
|
chosenCharacters.add(selectionPossibilities.item2[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
playerTwoSelection = chosenCharacters.toArray(new CharacterProperties[0]);
|
||||||
|
}
|
||||||
|
Logger.info("Player 2 has selected their characters");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
while(inGame) {
|
||||||
|
Tuple<Participant, BasicMessage> currentMessage = null;
|
||||||
|
try {
|
||||||
|
Logger.trace("Checking for messages. Currently the amount of messages is {}",
|
||||||
|
incomingMessages.size());
|
||||||
|
|
||||||
|
if (incomingMessages.isEmpty()) {
|
||||||
|
Logger.trace("LobbyConnection thread waiting for new messages...");
|
||||||
|
Thread.currentThread().wait();
|
||||||
|
Logger.trace("Lobby '{}' woken up", gameID);
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.trace("Polling incoming message queue");
|
||||||
|
currentMessage = incomingMessages.poll(100, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Logger.warn("LobbyConnection thread got interrupted. Exception: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentMessage == null) {
|
||||||
|
Logger.trace("Message was null, continuing");
|
||||||
|
continue;
|
||||||
|
} else if (currentMessage.item2 instanceof CharacterSelectionMessage) {
|
||||||
|
receiveCharacterSelection((CharacterSelectionMessage) currentMessage.item2);
|
||||||
|
} else if (currentMessage.item2 instanceof RequestMessage) {
|
||||||
|
receiveRequests((RequestMessage) currentMessage.item2);
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Send messages to the lobbyConnection */
|
||||||
|
public void receiveMessage(Participant participant, BasicMessage message) {
|
||||||
|
this.incomingMessages.add(Tuple.of(participant, message));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void receiveRequests(RequestMessage message) {
|
||||||
|
// TODO: implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
private void receiveCharacterSelection(CharacterSelectionMessage message) {
|
||||||
|
// TODO: Implement proper character selection
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeLobby() {
|
||||||
|
Logger.trace("Initializing lobby...");
|
||||||
this.lobby = new Lobby(
|
this.lobby = new Lobby(
|
||||||
gameID,
|
gameID,
|
||||||
this,
|
this,
|
||||||
partyConfig,
|
Server.getPartyConfig(),
|
||||||
characterConfig,
|
Server.getCharacterConfig(),
|
||||||
scenarioConfig);
|
Server.getScenarioConfig());
|
||||||
this.gameID = gameID;
|
|
||||||
this.spectators = new HashSet<>(10);
|
|
||||||
this.incomingRequests = new LinkedBlockingQueue<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,9 +200,7 @@ public class LobbyConnection implements Runnable {
|
|||||||
return player1 != null;
|
return player1 != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @return whether there is a player2 */
|
||||||
* @return whether there is a player2
|
|
||||||
*/
|
|
||||||
public boolean hasPlayer2() {
|
public boolean hasPlayer2() {
|
||||||
return player2 != null;
|
return player2 != null;
|
||||||
}
|
}
|
||||||
@ -176,16 +322,35 @@ public class LobbyConnection implements Runnable {
|
|||||||
|
|
||||||
/** Kills all connections to client, as well as the lobby */
|
/** Kills all connections to client, as well as the lobby */
|
||||||
public void terminateConnection() {
|
public void terminateConnection() {
|
||||||
MessageRelay.getInstance().terminate(this);
|
// TODO: implement this
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Send requests to the lobby that the LobbyConnection connects to */
|
|
||||||
public void receiveRequests(Request... requests) {
|
@Override
|
||||||
this.incomingRequests.add(requests);
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
LobbyConnection that = (LobbyConnection) o;
|
||||||
|
return characterSelection == that.characterSelection && inGame == that.inGame && Objects.equals(lobby, that.lobby) && Objects.equals(gameID, that.gameID) && Objects.equals(player1, that.player1) && Objects.equals(player2, that.player2) && Objects.equals(spectators, that.spectators) && Objects.equals(incomingMessages, that.incomingMessages) && Objects.equals(sendMessageCallback, that.sendMessageCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public int hashCode() {
|
||||||
|
return Objects.hash(lobby, gameID, player1, player2, characterSelection, inGame, spectators, incomingMessages, sendMessageCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "LobbyConnection{" +
|
||||||
|
"lobby=" + lobby +
|
||||||
|
", gameID='" + gameID + '\'' +
|
||||||
|
", player1=" + player1 +
|
||||||
|
", player2=" + player2 +
|
||||||
|
", characterSelection=" + characterSelection +
|
||||||
|
", inGame=" + inGame +
|
||||||
|
", spectators=" + spectators +
|
||||||
|
", incomingMessages=" + incomingMessages +
|
||||||
|
", sendMessageCallback=" + sendMessageCallback +
|
||||||
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user