Fixed players being able to join 1v1 limited games after they start to force more rounds

This commit is contained in:
jakub.salavec
2025-04-14 13:32:46 +02:00
parent c2bb9eead0
commit 62334bb638
11 changed files with 73 additions and 21 deletions

View File

@@ -666,6 +666,7 @@ var GempLotrHallUI = Class.extend({
var stage = tournament.getAttribute("stage");
if(stage !== null)
stage = stage.toLowerCase();
var joinable = tournament.getAttribute("joinable") === "true";
var abandoned = tournament.getAttribute("abandoned") === "true";
if (action == "add" || action == "update") {
var actionsField = $("<td></td>");
@@ -763,8 +764,7 @@ var GempLotrHallUI = Class.extend({
actionsField.append(but);
}
else if(!abandoned){
if(!(type === "table_draft") && (stage === "deck-building" || stage === "drafting" || stage === "awaiting kickoff"
|| stage === "preparing" || stage === "paused between rounds")) {
if(joinable) {
var but = $("<button>Join Tournament</button>");
$(but).button().click((
function(tourneyInfo) {

View File

@@ -128,7 +128,7 @@ public class HallCommunicationChannel implements LongPollableResource {
@Override
public void visitTournament(String tournamentKey, String collectionName, String formatName, String tournamentName, String type, String pairingDescription,
String tournamentStage, int round, int playerCount, String playerList, boolean playerInCompetition, boolean abandoned) {
String tournamentStage, int round, int playerCount, String playerList, boolean playerInCompetition, boolean abandoned, boolean joinable) {
Map<String, String> props = new HashMap<>();
props.put("collection", collectionName);
props.put("format", formatName);
@@ -141,6 +141,7 @@ public class HallCommunicationChannel implements LongPollableResource {
props.put("playerList", playerList);
props.put("signedUp", String.valueOf(playerInCompetition));
props.put("abandoned", String.valueOf(abandoned));
props.put("joinable", String.valueOf(joinable));
tournamentsOnServer.put(tournamentKey, props);
}

View File

@@ -18,7 +18,7 @@ public interface HallInfoVisitor {
int readyCheckSecsRemaining, boolean confirmedReadyCheck);
public void visitTournament(String tournamentKey, String collectionName, String formatName, String tournamentName, String type,
String pairingDescription, String tournamentStage, int round, int playerCount, String playerList, boolean playerInCompetition, boolean abandoned);
String pairingDescription, String tournamentStage, int round, int playerCount, String playerList, boolean playerInCompetition, boolean abandoned, boolean joinable);
public void runningPlayerGame(String gameId);
}

View File

@@ -1,6 +1,9 @@
package com.gempukku.lotro.hall;
import com.gempukku.lotro.*;
import com.gempukku.lotro.AbstractServer;
import com.gempukku.lotro.PrivateInformationException;
import com.gempukku.lotro.SubscriptionConflictException;
import com.gempukku.lotro.SubscriptionExpiredException;
import com.gempukku.lotro.chat.ChatCommandCallback;
import com.gempukku.lotro.chat.ChatCommandErrorException;
import com.gempukku.lotro.chat.ChatRoomMediator;
@@ -18,7 +21,10 @@ import com.gempukku.lotro.logic.GameUtils;
import com.gempukku.lotro.logic.timing.GameResultListener;
import com.gempukku.lotro.logic.vo.LotroDeck;
import com.gempukku.lotro.service.AdminService;
import com.gempukku.lotro.tournament.*;
import com.gempukku.lotro.tournament.Tournament;
import com.gempukku.lotro.tournament.TournamentCallback;
import com.gempukku.lotro.tournament.TournamentQueue;
import com.gempukku.lotro.tournament.TournamentService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -540,24 +546,21 @@ public class HallServer extends AbstractServer {
try {
String result = "";
var tournament = _tournamentService.getTournamentById(tournamentId);
if (tournament != null) {
var stage = tournament.getInfo().Stage;
if(stage == Tournament.Stage.STARTING || stage == Tournament.Stage.DECK_BUILDING ||
stage == Tournament.Stage.PAUSED || stage == Tournament.Stage.AWAITING_KICKOFF) {
LotroDeck lotroDeck = null;
if (tournament.getInfo().Parameters().requiresDeck) {
lotroDeck = validateUserAndDeck(_formatLibrary.getFormat(tournament.getFormatCode()), player, deckName, tournament.getCollectionType());
}
_tournamentService.recordTournamentPlayer(tournamentId, player.getName(), lotroDeck);
tournament.issuePlayerMaterial(player.getName());
if (tournament == null) {
result = "That tournament is already over.";
} else if (!tournament.isJoinable()) {
result = "That tournament does not allow late joining.";
} else {
LotroDeck lotroDeck = null;
if (tournament.getInfo().Parameters().requiresDeck) {
lotroDeck = validateUserAndDeck(_formatLibrary.getFormat(tournament.getFormatCode()), player, deckName, tournament.getCollectionType());
}
_tournamentService.recordTournamentPlayer(tournamentId, player.getName(), lotroDeck);
tournament.issuePlayerMaterial(player.getName());
result = "Joined tournament <b>" + tournament.getTournamentName() + "</b> successfully.";
hallChanged();
}
else {
result = "That tournament is already over.";
}
return result;
}

View File

@@ -127,4 +127,13 @@ public class ConstructedTournament extends BaseTournament implements Tournament
//This is for draft only
}
@Override
public boolean isJoinable() {
Set<String> activePlayers = new HashSet<>(_players);
activePlayers.removeAll(_droppedPlayers);
int maximumPlayers = _tournamentInfo._params.maximumPlayers;
return (getTournamentStage() == Tournament.Stage.STARTING || getTournamentStage() == Stage.PREPARING ||
getTournamentStage() == Tournament.Stage.PAUSED || getTournamentStage() == Tournament.Stage.AWAITING_KICKOFF)
&& (maximumPlayers > activePlayers.size() || maximumPlayers < 0);
}
}

View File

@@ -238,4 +238,13 @@ public class SealedTournament extends BaseTournament implements Tournament {
//This is for draft only
}
@Override
public boolean isJoinable() {
Set<String> activePlayers = new HashSet<>(_players);
activePlayers.removeAll(_droppedPlayers);
int maximumPlayers = _tournamentInfo._params.maximumPlayers;
return (getTournamentStage() == Stage.STARTING || getTournamentStage() == Stage.DECK_BUILDING || getTournamentStage() == Stage.DECK_REGISTRATION ||
getTournamentStage() == Tournament.Stage.PAUSED || getTournamentStage() == Tournament.Stage.AWAITING_KICKOFF)
&& (maximumPlayers > activePlayers.size() || maximumPlayers < 0);
}
}

View File

@@ -252,4 +252,14 @@ public class SoloDraftTournament extends BaseTournament implements Tournament {
public CollectionType getCollectionType() {
return _soloDraftInfo.generateCollectionInfo();
}
@Override
public boolean isJoinable() {
Set<String> activePlayers = new HashSet<>(_players);
activePlayers.removeAll(_droppedPlayers);
int maximumPlayers = _tournamentInfo._params.maximumPlayers;
return (getTournamentStage() == Stage.STARTING || getTournamentStage() == Stage.DECK_BUILDING || getTournamentStage() == Stage.DECK_REGISTRATION ||
getTournamentStage() == Tournament.Stage.PAUSED || getTournamentStage() == Tournament.Stage.AWAITING_KICKOFF)
&& (maximumPlayers > activePlayers.size() || maximumPlayers < 0);
}
}

View File

@@ -235,4 +235,14 @@ public class SoloTableDraftTournament extends BaseTournament implements Tourname
public CollectionType getCollectionType() {
return soloTableDraftInfo.generateCollectionInfo();
}
@Override
public boolean isJoinable() {
Set<String> activePlayers = new HashSet<>(_players);
activePlayers.removeAll(_droppedPlayers);
int maximumPlayers = _tournamentInfo._params.maximumPlayers;
return (getTournamentStage() == Stage.STARTING || getTournamentStage() == Stage.DECK_BUILDING || getTournamentStage() == Stage.DECK_REGISTRATION ||
getTournamentStage() == Tournament.Stage.PAUSED || getTournamentStage() == Tournament.Stage.AWAITING_KICKOFF)
&& (maximumPlayers > activePlayers.size() || maximumPlayers < 0);
}
}

View File

@@ -257,4 +257,9 @@ public class TableDraftTournament extends BaseTournament implements Tournament {
public CollectionType getCollectionType() {
return tableDraftInfo.generateCollectionInfo();
}
@Override
public boolean isJoinable() {
return false; // cannot join draft in progress
}
}

View File

@@ -204,4 +204,6 @@ public interface Tournament {
String produceReport(DeckRenderer renderer) throws CardNotFoundException;
TournamentInfo getInfo();
boolean isJoinable();
}

View File

@@ -101,6 +101,7 @@ public class TournamentService {
sealedParams.name = queueName;
sealedParams.cost = 0;
sealedParams.minimumPlayers = 2;
sealedParams.maximumPlayers = 2;
sealedParams.playoff = Tournament.PairingType.SINGLE_ELIMINATION;
sealedParams.prizes = Tournament.PrizeType.NONE;
@@ -128,6 +129,7 @@ public class TournamentService {
soloDraftParams.name = queueName;
soloDraftParams.cost = 0;
soloDraftParams.minimumPlayers = 2;
soloDraftParams.maximumPlayers = 2;
soloDraftParams.playoff = Tournament.PairingType.SINGLE_ELIMINATION;
soloDraftParams.prizes = Tournament.PrizeType.NONE;
@@ -265,7 +267,8 @@ public class TournamentService {
visitor.visitTournament(tourneyID, tournament.getCollectionType().getFullName(),
formatLibrary.getFormat(tournament.getFormatCode()).getName(), tournament.getTournamentName(), tournament.getInfo().Parameters().type.toString(), tournament.getPlayOffSystem(),
tournament.getTournamentStage().getHumanReadable(),
tournament.getCurrentRound(), tournament.getPlayersInCompetitionCount(), tournament.getPlayerList(), tournament.isPlayerInCompetition(player.getName()), tournament.isPlayerAbandoned(player.getName()));
tournament.getCurrentRound(), tournament.getPlayersInCompetitionCount(), tournament.getPlayerList(), tournament.isPlayerInCompetition(player.getName()), tournament.isPlayerAbandoned(player.getName()),
tournament.isJoinable());
}
}