fix: fixed TurnTimer, Lobby and Pipeline
This commit is contained in:
parent
67be103c42
commit
4ace772be0
@ -75,9 +75,11 @@ public class Lobby {
|
||||
partyConfig.maxRoundTime,
|
||||
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
|
||||
*/
|
||||
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) {
|
||||
Logger.trace("Resetting bad requests as new participant sent data");
|
||||
activePlayer = source;
|
||||
badRequests = 0;
|
||||
}
|
||||
|
||||
Logger.info("got {} requests from participant {}",
|
||||
requests.length,
|
||||
source);
|
||||
source.name);
|
||||
|
||||
Logger.trace("Processing requests through pipeline");
|
||||
Optional<Event[]> resultingEvents = pipeline.processRequests(requests, source);
|
||||
Logger.debug("generated {} events from the pipeline", resultingEvents.map(x -> x.length).orElse(0));
|
||||
Optional<List<Event>> resultingEvents = pipeline.processRequests(requests, source);
|
||||
Logger.debug("generated {} events from the pipeline", resultingEvents.map(List::size).orElse(0));
|
||||
|
||||
//resultingEvents isEmpty when a wrong request appeared
|
||||
Logger.trace("Checking whether resultingEvents (an optional) is empty");
|
||||
if (resultingEvents.isEmpty()) {
|
||||
Logger.debug("Rejecting requests from participant '{}'", source.name);
|
||||
reject(source);
|
||||
} else {
|
||||
var events = resultingEvents.get();
|
||||
connection.sendEvents(source, events);
|
||||
badRequests = 0;
|
||||
accept(source, resultingEvents.get());
|
||||
}
|
||||
|
||||
updateTimer();
|
||||
}
|
||||
|
||||
@ -117,26 +123,41 @@ public class Lobby {
|
||||
*/
|
||||
void updateTimer() {
|
||||
var currentActiveCharacterType = game.state.getActiveCharacter().type;
|
||||
Logger.trace("Updating turnTimer with current entityType {}", currentActiveCharacterType);
|
||||
if (pauseSegment.isPaused()) {
|
||||
Logger.trace("Game is paused, clearing turnTimer");
|
||||
turnTimer.clear();
|
||||
} else if (currentActiveCharacterType == EntityType.P1) {
|
||||
Logger.trace("Scheduling turnTimer for Player1");
|
||||
turnTimer.startTurnTimer(connection.getPlayer1());
|
||||
} else if (currentActiveCharacterType == EntityType.P2) {
|
||||
Logger.trace("Scheduling turnTimer for Player2");
|
||||
turnTimer.startTurnTimer(connection.getPlayer2());
|
||||
} else {
|
||||
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.
|
||||
* @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());
|
||||
badRequests ++;
|
||||
//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);
|
||||
if(connection.hasPlayer1()){
|
||||
generateWin(connection.getPlayer1());
|
||||
@ -178,9 +199,12 @@ public class Lobby {
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void turnTimeout(Participant source){
|
||||
//source round is over next players turn
|
||||
connection.sendEvents(source, game.endTurn().toArray(new Event[0]));
|
||||
/** Skips the current turn, and starts a new one. Exclusively called in the {@link TurnTimer}. */
|
||||
private synchronized void turnTimeout(Participant source){
|
||||
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
|
||||
*/
|
||||
public synchronized void generateWin(Participant winner){
|
||||
public synchronized void generateWin(Participant winner){
|
||||
connection.broadcastEvents(
|
||||
new EventBuilder(EventType.WinEvent)
|
||||
.withPlayerWon(winner.type.equals(ParticipantType.PlayerOne) ? 1 : 2)
|
||||
|
@ -1,23 +1,34 @@
|
||||
package uulm.teamname.marvelous.server.lobby;
|
||||
|
||||
import org.tinylog.Logger;
|
||||
import uulm.teamname.marvelous.gamelibrary.messages.ParticipantType;
|
||||
import uulm.teamname.marvelous.server.lobbymanager.Participant;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.*;
|
||||
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.
|
||||
*/
|
||||
public class TurnTimer {
|
||||
private final Timer timer;
|
||||
private final ScheduledExecutorService timer;
|
||||
private final Consumer<Participant> callback;
|
||||
private final int maxRoundTime;
|
||||
|
||||
private ScheduledFuture<Participant> current;
|
||||
|
||||
public TurnTimer(int maxRoundTime, Consumer<Participant> callback) {
|
||||
this.timer = new Timer();
|
||||
this.maxRoundTime = maxRoundTime;
|
||||
String lobbyThreadName = Thread.currentThread().getName();
|
||||
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;
|
||||
}
|
||||
|
||||
@ -26,21 +37,23 @@ public class TurnTimer {
|
||||
* @param participant the timer is for
|
||||
*/
|
||||
public void startTurnTimer(Participant participant) {
|
||||
if (participant.type == ParticipantType.Spectator)
|
||||
if (participant.type == ParticipantType.Spectator) {
|
||||
throw new IllegalStateException("Spectators don't have TurnTime");
|
||||
}
|
||||
|
||||
// cancel all current timers, and start a new timer
|
||||
timer.cancel();
|
||||
timer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.accept(participant);
|
||||
}
|
||||
}, maxRoundTime);
|
||||
clear();
|
||||
Logger.debug("Starting turn timer for participant '{}' with role {}",
|
||||
participant.name, participant.type);
|
||||
current = timer.schedule(() -> {callback.accept(participant); return participant;},
|
||||
maxRoundTime,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/** cancels all currently running timers */
|
||||
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
|
||||
* {@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");
|
||||
// The packet carries the requests, and gets smaller per segment
|
||||
Packet packet = new Packet(requests, origin);
|
||||
@ -60,7 +60,7 @@ public class Pipeline {
|
||||
return Optional.empty();
|
||||
} else { // else return an optional of the array
|
||||
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