From 6557e748af492a8b4db9aa45647c663f3d70dbc2 Mon Sep 17 00:00:00 2001 From: Yannik Bretschneider Date: Wed, 2 Jun 2021 18:28:02 +0200 Subject: [PATCH] feat: updated lobby to pipeline-based model --- .../marvelous/server/lobby/Lobby.java | 114 +++++++++--------- 1 file changed, 59 insertions(+), 55 deletions(-) diff --git a/Server/src/main/java/uulm/teamname/marvelous/server/lobby/Lobby.java b/Server/src/main/java/uulm/teamname/marvelous/server/lobby/Lobby.java index 10e965f..31cf498 100644 --- a/Server/src/main/java/uulm/teamname/marvelous/server/lobby/Lobby.java +++ b/Server/src/main/java/uulm/teamname/marvelous/server/lobby/Lobby.java @@ -1,6 +1,6 @@ package uulm.teamname.marvelous.server.lobby; -import uulm.teamname.marvelous.gamelibrary.IntVector2; +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; @@ -10,7 +10,6 @@ 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.gamelibrary.requests.RequestType; import uulm.teamname.marvelous.server.lobby.pipelining.*; import uulm.teamname.marvelous.server.lobbymanager.LobbyConnection; import uulm.teamname.marvelous.server.lobbymanager.Participant; @@ -22,8 +21,9 @@ public class Lobby { public final LobbyConnection connection; public final GameInstance game; public final Pipeline pipeline; - public final PauseSegment pauseSegment; - private final PauseHandler pause = new PauseHandler(); + private Participant activePlayer; + private int badRequests; + private PauseSegment pauseSegment; public Lobby( String gameID, @@ -34,6 +34,8 @@ public class Lobby { this.gameID = gameID; this.connection = connection; + //partyConfig.maxRoundTime; + this.game = new GameInstance( partyConfig, characterConfig, @@ -41,79 +43,77 @@ public class Lobby { ); //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); } - public void receiveRequests(Participant source, Request[] requests) { - ArrayList stateRelevant = new ArrayList<>(); - - for(Request request: requests) { - switch(request.type) { - case MeleeAttackRequest, RangedAttackRequest, MoveRequest, ExchangeInfinityStoneRequest, UseInfinityStoneRequest, EndRoundRequest -> { - if(!pause.isPaused()) { - stateRelevant.add(request); - }else { - // if game is paused, no actions should happen - reject(source); - } - } - case PauseStartRequest, PauseStopRequest -> { - if(request.type == RequestType.PauseStartRequest || pause.isPaused()) { - processRequest(source, request); - }else { - reject(source); - } - return; // only one of these will ever be sent at once, and if that is the case, we wont have any other state relevant events - } - case DisconnectRequest, Req -> { - processRequest(source, request); - return; // only one of these will ever be sent at once, and if that is the case, we wont have any other state relevant events - } - } + /** + * 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; } -// -// if(!game.checkRequestsAndApply(stateRelevant.toArray(new Request[0]))) { TODO: Fix this. -// // requests don't apply, tell the client that they need to update their state -// reject(source); -// } - } - private void processRequest(Participant source, Request request) { - // TODO: Implement as pipeline - switch(request.type) { - case PauseStopRequest -> { - pause.stop(); - connection.sendEvents(source, new EventBuilder(EventType.PauseStopEvent).buildGameStateEvent(), game.getGameStateEvent()); - } - case PauseStartRequest -> { - pause.start(); - connection.sendEvents(source, new EventBuilder(EventType.PauseStartEvent).buildGameStateEvent(), game.getGameStateEvent()); - } - case DisconnectRequest -> { - connection.removePlayer(source); - connection.sendEvents(source, new EventBuilder(EventType.DisconnectEvent).buildGameStateEvent(), game.getGameStateEvent()); - } - case Req -> { - connection.sendEvents(source, game.getGameStateEvent()); - } + Logger.info("got {} requests from participant {}", requests.length, source); + + Logger.trace("Processing requests through pipeline"); + Optional 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, @@ -146,4 +146,8 @@ public class Lobby { .buildGameStateEvent()); connection.terminateConnection(); } + + public PauseSegment getPauseSegment() { + return pauseSegment; + } }