fix: fixed TurnTimer, Lobby and Pipeline
This commit is contained in:
parent
67be103c42
commit
4ace772be0
@ -75,9 +75,11 @@ public class Lobby {
|
|||||||
partyConfig.maxRoundTime,
|
partyConfig.maxRoundTime,
|
||||||
this::turnTimeout);
|
this::turnTimeout);
|
||||||
|
|
||||||
var response = this.game.startGame(player1Characters, player2Characters);
|
var eventsDescribingGameStart = this.game.startGame(player1Characters, player2Characters);
|
||||||
|
|
||||||
this.connection.broadcastEvents(response);
|
this.connection.broadcastEvents(eventsDescribingGameStart);
|
||||||
|
|
||||||
|
updateTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -86,28 +88,32 @@ public class Lobby {
|
|||||||
* @param source the player executing the requests
|
* @param source the player executing the requests
|
||||||
*/
|
*/
|
||||||
public synchronized void receiveRequests(Request[] requests, Participant source) {
|
public synchronized void receiveRequests(Request[] requests, Participant source) {
|
||||||
|
Logger.trace("Received {} requests from participant '{}' of type {}",
|
||||||
|
requests.length,
|
||||||
|
source.name,
|
||||||
|
source.type);
|
||||||
if(activePlayer != source && source.type != ParticipantType.Spectator) {
|
if(activePlayer != source && source.type != ParticipantType.Spectator) {
|
||||||
|
Logger.trace("Resetting bad requests as new participant sent data");
|
||||||
activePlayer = source;
|
activePlayer = source;
|
||||||
badRequests = 0;
|
badRequests = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.info("got {} requests from participant {}",
|
Logger.info("got {} requests from participant {}",
|
||||||
requests.length,
|
requests.length,
|
||||||
source);
|
source.name);
|
||||||
|
|
||||||
Logger.trace("Processing requests through pipeline");
|
Logger.trace("Processing requests through pipeline");
|
||||||
Optional<Event[]> resultingEvents = pipeline.processRequests(requests, source);
|
Optional<List<Event>> resultingEvents = pipeline.processRequests(requests, source);
|
||||||
Logger.debug("generated {} events from the pipeline", resultingEvents.map(x -> x.length).orElse(0));
|
Logger.debug("generated {} events from the pipeline", resultingEvents.map(List::size).orElse(0));
|
||||||
|
|
||||||
//resultingEvents isEmpty when a wrong request appeared
|
//resultingEvents isEmpty when a wrong request appeared
|
||||||
|
Logger.trace("Checking whether resultingEvents (an optional) is empty");
|
||||||
if (resultingEvents.isEmpty()) {
|
if (resultingEvents.isEmpty()) {
|
||||||
|
Logger.debug("Rejecting requests from participant '{}'", source.name);
|
||||||
reject(source);
|
reject(source);
|
||||||
} else {
|
} else {
|
||||||
var events = resultingEvents.get();
|
accept(source, resultingEvents.get());
|
||||||
connection.sendEvents(source, events);
|
|
||||||
badRequests = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTimer();
|
updateTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,26 +123,41 @@ public class Lobby {
|
|||||||
*/
|
*/
|
||||||
void updateTimer() {
|
void updateTimer() {
|
||||||
var currentActiveCharacterType = game.state.getActiveCharacter().type;
|
var currentActiveCharacterType = game.state.getActiveCharacter().type;
|
||||||
|
Logger.trace("Updating turnTimer with current entityType {}", currentActiveCharacterType);
|
||||||
if (pauseSegment.isPaused()) {
|
if (pauseSegment.isPaused()) {
|
||||||
|
Logger.trace("Game is paused, clearing turnTimer");
|
||||||
turnTimer.clear();
|
turnTimer.clear();
|
||||||
} else if (currentActiveCharacterType == EntityType.P1) {
|
} else if (currentActiveCharacterType == EntityType.P1) {
|
||||||
|
Logger.trace("Scheduling turnTimer for Player1");
|
||||||
turnTimer.startTurnTimer(connection.getPlayer1());
|
turnTimer.startTurnTimer(connection.getPlayer1());
|
||||||
} else if (currentActiveCharacterType == EntityType.P2) {
|
} else if (currentActiveCharacterType == EntityType.P2) {
|
||||||
|
Logger.trace("Scheduling turnTimer for Player2");
|
||||||
turnTimer.startTurnTimer(connection.getPlayer2());
|
turnTimer.startTurnTimer(connection.getPlayer2());
|
||||||
} else {
|
} else {
|
||||||
turnTimer.clear();
|
turnTimer.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void accept(Participant source, List<Event> accepted) {
|
||||||
|
Logger.debug("Accepting requests from participant '{}', broadcasting events to all except source",
|
||||||
|
source.name);
|
||||||
|
connection.broadcastToAllExcept(source, accepted.toArray(new Event[0]));
|
||||||
|
|
||||||
|
Logger.trace("Adding ack and sending back to originParticipant");
|
||||||
|
accepted.add(0, new EventBuilder(EventType.Ack).buildGameStateEvent());
|
||||||
|
connection.sendEvents(source, accepted.toArray(new Event[0]));
|
||||||
|
badRequests = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the player executed a false request the request gets rejected.
|
* If the player executed a false request the request gets rejected.
|
||||||
* @param source the executing player
|
* @param source the executing player
|
||||||
*/
|
*/
|
||||||
private synchronized void reject(Participant source) {
|
private void reject(Participant source) {
|
||||||
connection.sendEvents(source, new EventBuilder(EventType.Nack).buildGameEvent(), game.getGameStateEvent());
|
connection.sendEvents(source, new EventBuilder(EventType.Nack).buildGameEvent(), game.getGameStateEvent());
|
||||||
badRequests ++;
|
badRequests ++;
|
||||||
//if the player sends 2 bad messages after one another, the player gets kicked out of the lobby.
|
//if the player sends 2 bad messages after one another, the player gets kicked out of the lobby.
|
||||||
if(badRequests == 2){
|
if(badRequests >= 5){
|
||||||
connection.removeParticipant(source);
|
connection.removeParticipant(source);
|
||||||
if(connection.hasPlayer1()){
|
if(connection.hasPlayer1()){
|
||||||
generateWin(connection.getPlayer1());
|
generateWin(connection.getPlayer1());
|
||||||
@ -178,9 +199,12 @@ public class Lobby {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void turnTimeout(Participant source){
|
/** Skips the current turn, and starts a new one. Exclusively called in the {@link TurnTimer}. */
|
||||||
//source round is over next players turn
|
private synchronized void turnTimeout(Participant source){
|
||||||
connection.sendEvents(source, game.endTurn().toArray(new Event[0]));
|
var nextTurnEvents = game.endTurn();
|
||||||
|
nextTurnEvents.add(game.getGameStateEvent());
|
||||||
|
connection.broadcastEvents();
|
||||||
|
updateTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -189,7 +213,7 @@ public class Lobby {
|
|||||||
*
|
*
|
||||||
* @param winner is the {@link Participant} that won
|
* @param winner is the {@link Participant} that won
|
||||||
*/
|
*/
|
||||||
public synchronized void generateWin(Participant winner){
|
public synchronized void generateWin(Participant winner){
|
||||||
connection.broadcastEvents(
|
connection.broadcastEvents(
|
||||||
new EventBuilder(EventType.WinEvent)
|
new EventBuilder(EventType.WinEvent)
|
||||||
.withPlayerWon(winner.type.equals(ParticipantType.PlayerOne) ? 1 : 2)
|
.withPlayerWon(winner.type.equals(ParticipantType.PlayerOne) ? 1 : 2)
|
||||||
|
@ -1,23 +1,34 @@
|
|||||||
package uulm.teamname.marvelous.server.lobby;
|
package uulm.teamname.marvelous.server.lobby;
|
||||||
|
|
||||||
|
import org.tinylog.Logger;
|
||||||
import uulm.teamname.marvelous.gamelibrary.messages.ParticipantType;
|
import uulm.teamname.marvelous.gamelibrary.messages.ParticipantType;
|
||||||
import uulm.teamname.marvelous.server.lobbymanager.Participant;
|
import uulm.teamname.marvelous.server.lobbymanager.Participant;
|
||||||
|
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
import java.util.concurrent.*;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link TurnTimer} class is called by the {@link Lobby} to limit the amount of time a player has per round.
|
* The {@link TurnTimer} class is called by the {@link Lobby} to limit the amount of time a player has per round.
|
||||||
*/
|
*/
|
||||||
public class TurnTimer {
|
public class TurnTimer {
|
||||||
private final Timer timer;
|
private final ScheduledExecutorService timer;
|
||||||
private final Consumer<Participant> callback;
|
private final Consumer<Participant> callback;
|
||||||
private final int maxRoundTime;
|
private final int maxRoundTime;
|
||||||
|
|
||||||
|
private ScheduledFuture<Participant> current;
|
||||||
|
|
||||||
public TurnTimer(int maxRoundTime, Consumer<Participant> callback) {
|
public TurnTimer(int maxRoundTime, Consumer<Participant> callback) {
|
||||||
this.timer = new Timer();
|
String lobbyThreadName = Thread.currentThread().getName();
|
||||||
this.maxRoundTime = maxRoundTime;
|
ThreadFactory threadFactory = new ThreadFactory() {
|
||||||
|
@Override
|
||||||
|
public Thread newThread(Runnable r) {
|
||||||
|
return new Thread(r, lobbyThreadName + "-timerThread");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.timer = Executors.newSingleThreadScheduledExecutor(threadFactory);
|
||||||
|
this.maxRoundTime = 3;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,21 +37,23 @@ public class TurnTimer {
|
|||||||
* @param participant the timer is for
|
* @param participant the timer is for
|
||||||
*/
|
*/
|
||||||
public void startTurnTimer(Participant participant) {
|
public void startTurnTimer(Participant participant) {
|
||||||
if (participant.type == ParticipantType.Spectator)
|
if (participant.type == ParticipantType.Spectator) {
|
||||||
throw new IllegalStateException("Spectators don't have TurnTime");
|
throw new IllegalStateException("Spectators don't have TurnTime");
|
||||||
|
}
|
||||||
|
|
||||||
// cancel all current timers, and start a new timer
|
clear();
|
||||||
timer.cancel();
|
Logger.debug("Starting turn timer for participant '{}' with role {}",
|
||||||
timer.schedule(new TimerTask() {
|
participant.name, participant.type);
|
||||||
@Override
|
current = timer.schedule(() -> {callback.accept(participant); return participant;},
|
||||||
public void run() {
|
maxRoundTime,
|
||||||
callback.accept(participant);
|
TimeUnit.SECONDS);
|
||||||
}
|
|
||||||
}, maxRoundTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** cancels all currently running timers */
|
/** cancels all currently running timers */
|
||||||
public void clear() {
|
public void clear() {
|
||||||
timer.cancel();
|
Logger.trace("Clearing timer");
|
||||||
|
if (this.current != null) {
|
||||||
|
current.cancel(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ public class Pipeline {
|
|||||||
* out of the {@link Optional}, first check whether the {@link Optional} is empty by doing
|
* out of the {@link Optional}, first check whether the {@link Optional} is empty by doing
|
||||||
* {@link Optional#isEmpty()} or {@link Optional#isPresent()}, and act accordingly.
|
* {@link Optional#isEmpty()} or {@link Optional#isPresent()}, and act accordingly.
|
||||||
*/
|
*/
|
||||||
public Optional<Event[]> processRequests(Request[] requests, Participant origin) {
|
public Optional<List<Event>> processRequests(Request[] requests, Participant origin) {
|
||||||
Logger.trace("Pipeline started RequestProcessing");
|
Logger.trace("Pipeline started RequestProcessing");
|
||||||
// The packet carries the requests, and gets smaller per segment
|
// The packet carries the requests, and gets smaller per segment
|
||||||
Packet packet = new Packet(requests, origin);
|
Packet packet = new Packet(requests, origin);
|
||||||
@ -60,7 +60,7 @@ public class Pipeline {
|
|||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
} else { // else return an optional of the array
|
} else { // else return an optional of the array
|
||||||
Logger.trace("Pipeline executed normally. Returning {} events.", carrier.size());
|
Logger.trace("Pipeline executed normally. Returning {} events.", carrier.size());
|
||||||
return Optional.of(carrier.toArray(new Event[0]));
|
return Optional.of(carrier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user