All checks were successful
Quality Check / Validate OAS (push) Successful in 42s
Quality Check / Linting (push) Successful in 1m22s
Quality Check / Validate OAS (pull_request) Successful in 41s
Quality Check / Static Analysis (push) Successful in 1m29s
Quality Check / Testing (push) Successful in 1m21s
Quality Check / Linting (pull_request) Successful in 1m13s
Quality Check / Testing (pull_request) Successful in 1m5s
Quality Check / Static Analysis (pull_request) Successful in 1m9s
222 lines
8.4 KiB
Java
222 lines
8.4 KiB
Java
package de.towerdefence.server.match.confirmation;
|
|
|
|
import de.towerdefence.server.match.MatchService;
|
|
import de.towerdefence.server.player.Player;
|
|
import lombok.AllArgsConstructor;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import java.io.IOException;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
import java.util.Optional;
|
|
import java.util.concurrent.*;
|
|
|
|
@AllArgsConstructor
|
|
@Service
|
|
public class MatchConfirmationService {
|
|
private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
|
private final Map<Player, UnconfirmedMatch> unconfirmedMatch = new HashMap<>();
|
|
final Map<UnconfirmedMatch, ScheduledFuture<?>> matchAbortTasks = new ConcurrentHashMap<>();
|
|
|
|
@Autowired
|
|
private final MatchService matchService;
|
|
|
|
public UnconfirmedMatch createMatch(Player player1,
|
|
Player player2,
|
|
ConfirmationCallbacks player1Callbacks,
|
|
ConfirmationCallbacks player2Callbacks) {
|
|
UnconfirmedMatch match = new UnconfirmedMatch(
|
|
player1,
|
|
player2,
|
|
player1Callbacks,
|
|
player2Callbacks);
|
|
unconfirmedMatch.put(player1, match);
|
|
unconfirmedMatch.put(player2, match);
|
|
ScheduledFuture<?> scheduledTask = scheduler.schedule(
|
|
() -> {
|
|
matchAbortTasks.remove(match);
|
|
unconfirmedMatch.remove(match.getPlayer1());
|
|
unconfirmedMatch.remove(match.getPlayer2());
|
|
if (match.getPlayer1State() == PlayerMatchConfirmState.CONFIRMED ) {
|
|
player1Callbacks.getRequeueCallback().call(
|
|
match.getPlayer1(),
|
|
match.getMatchId(),
|
|
player1Callbacks.getFoundCallback(),
|
|
player1Callbacks.getQueuedCallback(),
|
|
player1Callbacks.getAbortCallback(),
|
|
player1Callbacks.getEstablishedCallback());
|
|
} else {
|
|
player1Callbacks.getAbortCallback().call(
|
|
match.getPlayer1(),
|
|
match.getMatchId()
|
|
);
|
|
}
|
|
if (match.getPlayer2State() == PlayerMatchConfirmState.CONFIRMED) {
|
|
player2Callbacks.getRequeueCallback().call(
|
|
match.getPlayer2(),
|
|
match.getMatchId(),
|
|
player2Callbacks.getFoundCallback(),
|
|
player2Callbacks.getQueuedCallback(),
|
|
player2Callbacks.getAbortCallback(),
|
|
player2Callbacks.getEstablishedCallback());
|
|
} else {
|
|
player2Callbacks.getAbortCallback().call(
|
|
match.getPlayer2(),
|
|
match.getMatchId()
|
|
);
|
|
}
|
|
},
|
|
UnconfirmedMatch.TTL,
|
|
TimeUnit.MILLISECONDS
|
|
);
|
|
matchAbortTasks.put(match, scheduledTask);
|
|
return match;
|
|
}
|
|
|
|
public void accept(Player player, String matchId) {
|
|
setPlayerAcceptState(player, matchId, PlayerMatchConfirmState.CONFIRMED);
|
|
}
|
|
|
|
public void decline(Player player, String matchId) {
|
|
setPlayerAcceptState(player, matchId, PlayerMatchConfirmState.ABORTED);
|
|
}
|
|
|
|
private void setPlayerAcceptState(Player player, String matchId, PlayerMatchConfirmState state) {
|
|
Optional<UnconfirmedMatch> optionalMatch = getPlayerMatch(player, matchId);
|
|
if (optionalMatch.isEmpty()) {
|
|
return;
|
|
}
|
|
UnconfirmedMatch match = optionalMatch.get();
|
|
|
|
Optional<PlayerMatchConfirmState> optionalPlayerState = match.getPlayerState(player);
|
|
if (optionalPlayerState.isEmpty()) {
|
|
unconfirmedMatch.remove(player);
|
|
return;
|
|
}
|
|
|
|
if (optionalPlayerState.get() != PlayerMatchConfirmState.UNKNOWN) {
|
|
return;
|
|
}
|
|
|
|
Optional<UnconfirmedMatchState> matchState = match.setPlayerConfirmState(player, state);
|
|
if (matchState.isEmpty()) {
|
|
unconfirmedMatch.remove(player);
|
|
return;
|
|
}
|
|
handleMatchConfirmation(match, matchState.get());
|
|
}
|
|
|
|
private void handleMatchConfirmation(UnconfirmedMatch match, UnconfirmedMatchState state) {
|
|
if (state == UnconfirmedMatchState.WAITING) {
|
|
return;
|
|
}
|
|
matchAbortTasks.get(match).cancel(true);
|
|
matchAbortTasks.remove(match);
|
|
|
|
unconfirmedMatch.remove(match.getPlayer1());
|
|
unconfirmedMatch.remove(match.getPlayer2());
|
|
|
|
ConfirmationCallbacks player1Callbacks = match.getPlayer1Callbacks();
|
|
ConfirmationCallbacks player2Callbacks = match.getPlayer2Callbacks();
|
|
|
|
switch (state) {
|
|
case ABORTED -> {
|
|
if (match.getPlayer1State() != PlayerMatchConfirmState.ABORTED ) {
|
|
player1Callbacks.getRequeueCallback().call(
|
|
match.getPlayer1(),
|
|
match.getMatchId(),
|
|
player1Callbacks.getFoundCallback(),
|
|
player1Callbacks.getQueuedCallback(),
|
|
player1Callbacks.getAbortCallback(),
|
|
player1Callbacks.getEstablishedCallback());
|
|
} else {
|
|
player1Callbacks.getAbortCallback().call(
|
|
match.getPlayer1(),
|
|
match.getMatchId()
|
|
);
|
|
}
|
|
if (match.getPlayer2State() != PlayerMatchConfirmState.ABORTED) {
|
|
player2Callbacks.getRequeueCallback().call(
|
|
match.getPlayer2(),
|
|
match.getMatchId(),
|
|
player2Callbacks.getFoundCallback(),
|
|
player2Callbacks.getQueuedCallback(),
|
|
player2Callbacks.getAbortCallback(),
|
|
player2Callbacks.getEstablishedCallback());
|
|
} else {
|
|
player2Callbacks.getAbortCallback().call(
|
|
match.getPlayer2(),
|
|
match.getMatchId()
|
|
);
|
|
}
|
|
}
|
|
case CONFIRMED -> {
|
|
|
|
boolean player1successful = sendPlayerEstablished(
|
|
match.getMatchId(),
|
|
player1Callbacks.getEstablishedCallback(),
|
|
match.getPlayer1(),
|
|
match.getPlayer2()
|
|
);
|
|
boolean player2successful = sendPlayerEstablished(
|
|
match.getMatchId(),
|
|
player2Callbacks.getEstablishedCallback(),
|
|
match.getPlayer2(),
|
|
match.getPlayer1()
|
|
);
|
|
if (!player1successful || !player2successful) {
|
|
if (player1successful) {
|
|
player1Callbacks.getRequeueCallback().call(
|
|
match.getPlayer1(),
|
|
match.getMatchId(),
|
|
player1Callbacks.getFoundCallback(),
|
|
player1Callbacks.getQueuedCallback(),
|
|
player1Callbacks.getAbortCallback(),
|
|
player1Callbacks.getEstablishedCallback());
|
|
}
|
|
if (player2successful) {
|
|
player2Callbacks.getRequeueCallback().call(
|
|
match.getPlayer2(),
|
|
match.getMatchId(),
|
|
player2Callbacks.getFoundCallback(),
|
|
player2Callbacks.getQueuedCallback(),
|
|
player2Callbacks.getAbortCallback(),
|
|
player2Callbacks.getEstablishedCallback());
|
|
}
|
|
return;
|
|
}
|
|
matchService.createMatch(match.getMatchId(), match.getPlayer1(), match.getPlayer2());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return if successful
|
|
*/
|
|
private boolean sendPlayerEstablished(
|
|
String matchId,
|
|
EstablishedCallback callback,
|
|
Player player,
|
|
Player opponent
|
|
) {
|
|
try {
|
|
callback.call(player, matchId, opponent);
|
|
} catch (IOException ignored) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private Optional<UnconfirmedMatch> getPlayerMatch(Player player, String matchId) {
|
|
UnconfirmedMatch match = unconfirmedMatch.get(player);
|
|
if (match == null) {
|
|
return Optional.empty();
|
|
}
|
|
if (!match.getMatchId().equals(matchId)) {
|
|
unconfirmedMatch.remove(player);
|
|
return Optional.empty();
|
|
}
|
|
return Optional.of(match);
|
|
}
|
|
}
|