package de.towerdefence.server.match.queue; import de.towerdefence.server.match.confirmation.*; 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.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @Service @AllArgsConstructor public class MatchQueueService { private final static int REQUIRED_PLAYER_COUNT = 2; @Autowired private final MatchConfirmationService matchConfirmationService; private final List queue = new ArrayList<>(); private final Map confirmationCallbacks = new HashMap<>(); public void queuePlayer( Player player, FoundCallback foundCallback, QueuedCallback queuedCallback, AbortCallback abortCallback, EstablishedCallback establishedCallback) { queue.add(player); confirmationCallbacks.put(player, new ConfirmationCallbacks( foundCallback, queuedCallback, abortCallback, establishedCallback, this::onRequeue)); tryMatching(); } public void onRequeue( Player player, String matchId, FoundCallback foundCallback, QueuedCallback queuedCallback, AbortCallback abortCallback, EstablishedCallback establishedCallback) { abortCallback.call(player, matchId); try { queuedCallback.call(player); } catch (IOException ignored) { return; } queuePlayer(player, foundCallback, queuedCallback, abortCallback, establishedCallback); } public void unQueuePlayer(Player player) { queue.remove(player); confirmationCallbacks.remove(player); } private void tryMatching() { if (queue.size() < REQUIRED_PLAYER_COUNT) { return; } List loopQueue = new ArrayList<>(queue); for (int i = 0; i < loopQueue.size() / REQUIRED_PLAYER_COUNT; i++) { Player player1 = loopQueue.get(REQUIRED_PLAYER_COUNT * i); Player player2 = loopQueue.get(REQUIRED_PLAYER_COUNT * i + 1); ConfirmationCallbacks player1Callbacks = confirmationCallbacks.get(player1); ConfirmationCallbacks player2Callbacks = confirmationCallbacks.get(player2); UnconfirmedMatch match = this.matchConfirmationService.createMatch( player1, player2, player1Callbacks, player2Callbacks); sentMatchFound( match, player1, player2, player1Callbacks, player2Callbacks); } if (queue.size() > REQUIRED_PLAYER_COUNT) { tryMatching(); } } private void sentMatchFound( UnconfirmedMatch match, Player player1, Player player2, ConfirmationCallbacks player1Callbacks, ConfirmationCallbacks player2Callbacks) { boolean player1disconnected = setMatchFoundToPlayer(player1, player1Callbacks.getFoundCallback(), match); boolean player2disconnected = setMatchFoundToPlayer(player2, player2Callbacks.getFoundCallback(), match); queue.remove(player1); queue.remove(player2); if (!player1disconnected && !player2disconnected) { return; } if (player1disconnected && match.getPlayer2State() != PlayerMatchConfirmState.ABORTED) { player2Callbacks.getRequeueCallback().call( player2, match.getMatchId(), player2Callbacks.getFoundCallback(), player2Callbacks.getQueuedCallback(), player2Callbacks.getAbortCallback(), player2Callbacks.getEstablishedCallback()); } if (player2disconnected && match.getPlayer1State() != PlayerMatchConfirmState.ABORTED) { player1Callbacks.getRequeueCallback().call( player1, match.getMatchId(), player1Callbacks.getFoundCallback(), player1Callbacks.getQueuedCallback(), player1Callbacks.getAbortCallback(), player1Callbacks.getEstablishedCallback()); } } private boolean setMatchFoundToPlayer(Player player, FoundCallback callback, UnconfirmedMatch match) { try { callback.call( player, match.getMatchId(), match.getCreated(), UnconfirmedMatch.TTL); } catch (IOException e) { return true; } return false; } }