Server/Server/src/main/java/uulm/teamname/marvelous/server/lobby/Lobby.java

154 lines
5.4 KiB
Java

package uulm.teamname.marvelous.server.lobby;
import org.tinylog.Logger;
import uulm.teamname.marvelous.gamelibrary.events.Event;
import uulm.teamname.marvelous.gamelibrary.events.EventBuilder;
import uulm.teamname.marvelous.gamelibrary.events.EventType;
import uulm.teamname.marvelous.gamelibrary.gamelogic.GameInstance;
import uulm.teamname.marvelous.server.ParticipantType;
import uulm.teamname.marvelous.gamelibrary.config.CharacterConfig;
import uulm.teamname.marvelous.gamelibrary.config.PartyConfig;
import uulm.teamname.marvelous.gamelibrary.config.ScenarioConfig;
import uulm.teamname.marvelous.gamelibrary.requests.Request;
import uulm.teamname.marvelous.server.lobby.pipelining.*;
import uulm.teamname.marvelous.server.lobbymanager.LobbyConnection;
import uulm.teamname.marvelous.server.lobbymanager.Participant;
import java.util.*;
public class Lobby {
public final String gameID;
public final LobbyConnection connection;
public final GameInstance game;
public final Pipeline pipeline;
private Participant activePlayer;
private int badRequests;
private PauseSegment pauseSegment;
public Lobby(
String gameID,
LobbyConnection connection,
PartyConfig partyConfig,
CharacterConfig characterConfig,
ScenarioConfig scenarioConfig) {
this.gameID = gameID;
this.connection = connection;
//partyConfig.maxRoundTime;
this.game = new GameInstance(
partyConfig,
characterConfig,
scenarioConfig
); //TODO: Add config objects here
this.pipeline = new Pipeline();
var reqSegment = new RequestGameStateSegment(this.game);
this.pauseSegment = new PauseSegment();
var disconnectSegment = new DisconnectSegment(this);
var gameStateSegment = new GameStateSegment(this.game);
pipeline.addSegment(reqSegment)
.addSegment(pauseSegment)
.addSegment(disconnectSegment)
.addSegment(gameStateSegment);
}
/**
* Called by {@link LobbyConnection} to handle requests
* @param requests to be processed
* @param source the player executing the requests
*/
public void receiveRequests(Request[] requests, Participant source) {
if(activePlayer != source && source.type != ParticipantType.Spectator) {
activePlayer = source;
badRequests = 0;
}
Logger.info("got {} requests from participant {}", requests.length, source);
Logger.trace("Processing requests through pipeline");
Optional<Event[]> resultingEvents = pipeline.processRequests(requests, source);
//resultingEvents isEmpty when a wrong request appeared
if (resultingEvents.isEmpty()) {
reject(source);
} else {
var events = resultingEvents.get();
connection.sendEvents(source, events);
badRequests = 0;
}
}
/**
* If the player executed a false request the request gets rejected.
* @param source the executing player
*/
private void reject(Participant source) {
connection.sendEvents(source, new EventBuilder(EventType.Nack).buildGameEvent(), game.getGameStateEvent());
badRequests ++;
//if the player sends 2 bad messages after one another, the player gets kicked out of the lobby.
if(badRequests == 2){
connection.removePlayer(source);
if(connection.hasPlayer1()){
generateWin(connection.getPlayer1());
}
else if(connection.hasPlayer2()) {
generateWin(connection.getPlayer2());
}
}
}
/**
* Warns the player he get timeouted soon.
* @param source soon to be timeouted player
*/
public void soonTimeout (Participant source){
connection.sendEvents(
source,
new EventBuilder(EventType.TimeoutWarningEvent).buildGameStateEvent());
}
/**
* If a player times out the other player automatically wins.
* @param source is the timeouted player
*/
public void Timeout(Participant source){
connection.sendEvents(
source,
new EventBuilder(EventType.TimeoutEvent).buildGameStateEvent());
connection.removePlayer(source);
if(connection.hasPlayer1()){
generateWin(connection.getPlayer1());
}
else if(connection.hasPlayer2()) {
generateWin(connection.getPlayer2());
}
else {
throw new IllegalStateException("Spectator was time-outed which is impossible");
}
}
/**
* The method generates a Win event for a {@link Participant}.
* Afterwards it sends a Disconnect to everyone, and terminates the connection.
*
* @param winner is the {@link Participant} that won
*/
public void generateWin(Participant winner){
connection.broadcastEvents(
new EventBuilder(EventType.WinEvent)
.withPlayerWon(winner.type.equals(ParticipantType.Player1) ? 1 : 2)
.buildGameStateEvent(),
new EventBuilder(EventType.DisconnectEvent)
.buildGameStateEvent());
connection.terminateConnection();
}
public PauseSegment getPauseSegment() {
return pauseSegment;
}
}