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

92 lines
3.9 KiB
Java

package uulm.teamname.marvelous.server.lobby;
import org.tinylog.Logger;
import uulm.teamname.marvelous.server.lobbymanager.Participant;
import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class TimeoutTimer {
private final ScheduledExecutorService timer;
private ScheduledFuture<Participant> player1AlmostTimeout;
private ScheduledFuture<Participant> player1Timeout;
private ScheduledFuture<Participant> player2AlmostTimeout;
private ScheduledFuture<Participant> player2Timeout;
private final BiConsumer<Participant, Integer> almostTimeoutCallback;
private final Consumer<Participant> timeoutCallback;
private final int almostTimeoutTime;
private final int timeoutTime;
/**
* Class that manages timeouts of players after not sending a message for a long time.
*
* @param timeoutTime is the time that a player has to send any message
* @param almostTimeoutCallback is the callback that is called if the timeoutTime is almost over
* @param timeoutCallback is the callback that is called when the timeoutTime is over
*/
public TimeoutTimer(int timeoutTime,
BiConsumer<Participant, Integer> almostTimeoutCallback,
Consumer<Participant> timeoutCallback) {
this.almostTimeoutCallback = almostTimeoutCallback;
this.timeoutCallback = timeoutCallback;
this.timeoutTime = timeoutTime;
this.almostTimeoutTime = Math.max(timeoutTime - 15, Math.min(timeoutTime, 5));
String lobbyThreadName = Thread.currentThread().getName();
ThreadFactory threadFactory = r -> new Thread(r, lobbyThreadName + "-timeoutTimer");
timer = Executors.newSingleThreadScheduledExecutor(threadFactory);
}
/** Refreshes the timeout timer for the given Participant. This is meant to be used for Players, not Spectators. */
public void refreshTimer(Participant participant) {
Logger.debug("Refreshing turnTimer for participant of type '{}'", participant.type);
switch (participant.type) {
case PlayerOne -> {
Logger.trace("Was playerOne, refreshing...");
if (player1AlmostTimeout != null) player1AlmostTimeout.cancel(false);
player1AlmostTimeout =
timer.schedule(() -> {
almostTimeoutCallback.accept(participant, timeoutTime - almostTimeoutTime);
return participant;
}, this.almostTimeoutTime, TimeUnit.SECONDS);
if (player1Timeout != null) player1Timeout.cancel(false);
player1Timeout =
timer.schedule(() -> {
timeoutCallback.accept(participant);
return participant;
}, this.timeoutTime, TimeUnit.SECONDS);
}
case PlayerTwo -> {
Logger.trace("Was playerOne, refreshing...");
if (player2AlmostTimeout != null) player2AlmostTimeout.cancel(false);
player2AlmostTimeout =
timer.schedule(() -> {
almostTimeoutCallback.accept(participant, timeoutTime - almostTimeoutTime);
return participant;
}, this.almostTimeoutTime, TimeUnit.SECONDS);
if (player2Timeout != null) player2Timeout.cancel(false);
player2Timeout =
timer.schedule(() -> {
timeoutCallback.accept(participant);
return participant;
}, this.timeoutTime, TimeUnit.SECONDS);
}
case Spectator -> Logger.warn("Timeout called on spectator '{}'. This is probably a bug.",
participant.id.getName());
}
}
}