diff --git a/Mage.Server/src/main/java/mage/server/TableController.java b/Mage.Server/src/main/java/mage/server/TableController.java index 3b76975680..9e361167fd 100644 --- a/Mage.Server/src/main/java/mage/server/TableController.java +++ b/Mage.Server/src/main/java/mage/server/TableController.java @@ -421,12 +421,16 @@ public class TableController { } public void updateDeck(UUID userId, DeckCardLists deckList) throws MageException { + boolean validDeck; UUID playerId = userPlayerMap.get(userId); if (table.getState() != TableState.SIDEBOARDING && table.getState() != TableState.CONSTRUCTING) { return; } Deck deck = Deck.load(deckList, false, false); - updateDeck(userId, playerId, deck); + validDeck = updateDeck(userId, playerId, deck); + if (!validDeck) { + logger.warn(" userId: " + userId + " - Modified deck card list!"); + } } private void submitDeck(UUID userId, UUID playerId, Deck deck) { @@ -439,18 +443,20 @@ public class TableController { } } - private void updateDeck(UUID userId, UUID playerId, Deck deck) { + private boolean updateDeck(UUID userId, UUID playerId, Deck deck) { + boolean validDeck = true; if (table.isTournament()) { if (tournament != null) { - TournamentManager.instance.updateDeck(tournament.getId(), playerId, deck); + validDeck = TournamentManager.instance.updateDeck(tournament.getId(), playerId, deck); } else { logger.fatal("Tournament == null table: " + table.getId() + " userId: " + userId); } } else if (TableState.SIDEBOARDING == table.getState()) { - match.updateDeck(playerId, deck); + validDeck = match.updateDeck(playerId, deck); } else { // deck was meanwhile submitted so the autoupdate can be ignored } + return validDeck; } public boolean watchTable(UUID userId) { @@ -472,13 +478,6 @@ public class TableController { } } - // public boolean replayTable(UUID userId) { -// if (table.getState() != TableState.FINISHED) { -// return false; -// } -// ReplayManager.instance.replayGame(table.getId(), userId); -// return true; -// } private Optional createPlayer(String name, PlayerType playerType, int skill) { Optional playerOpt; if (options == null) { diff --git a/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java b/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java index 4317726854..63eb36ac26 100644 --- a/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java +++ b/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java @@ -349,10 +349,11 @@ public class TournamentController { } } - public void updateDeck(UUID playerId, Deck deck) { + public boolean updateDeck(UUID playerId, Deck deck) { if (tournamentSessions.containsKey(playerId)) { - tournamentSessions.get(playerId).updateDeck(deck); + return tournamentSessions.get(playerId).updateDeck(deck); } + return false; } public void timeout(UUID userId) { diff --git a/Mage.Server/src/main/java/mage/server/tournament/TournamentManager.java b/Mage.Server/src/main/java/mage/server/tournament/TournamentManager.java index 58e8669207..83fad71c75 100644 --- a/Mage.Server/src/main/java/mage/server/tournament/TournamentManager.java +++ b/Mage.Server/src/main/java/mage/server/tournament/TournamentManager.java @@ -24,14 +24,12 @@ * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. -*/ - + */ package mage.server.tournament; import java.util.Optional; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; - import mage.cards.decks.Deck; import mage.game.tournament.Tournament; import mage.view.TournamentView; @@ -74,8 +72,8 @@ public enum TournamentManager { controllers.get(tournamentId).submitDeck(playerId, deck); } - public void updateDeck(UUID tournamentId, UUID playerId, Deck deck) { - controllers.get(tournamentId).updateDeck(playerId, deck); + public boolean updateDeck(UUID tournamentId, UUID playerId, Deck deck) { + return controllers.get(tournamentId).updateDeck(playerId, deck); } public TournamentView getTournamentView(UUID tournamentId) { @@ -87,13 +85,12 @@ public enum TournamentManager { } public Optional getChatId(UUID tournamentId) { - if(controllers.containsKey(tournamentId)) { + if (controllers.containsKey(tournamentId)) { return Optional.of(controllers.get(tournamentId).getChatId()); } return Optional.empty(); } - public void removeTournament(UUID tournamentId) { TournamentController tournamentController = controllers.get(tournamentId); if (tournamentController != null) { diff --git a/Mage.Server/src/main/java/mage/server/tournament/TournamentSession.java b/Mage.Server/src/main/java/mage/server/tournament/TournamentSession.java index 446b3fe688..cf4b16ee86 100644 --- a/Mage.Server/src/main/java/mage/server/tournament/TournamentSession.java +++ b/Mage.Server/src/main/java/mage/server/tournament/TournamentSession.java @@ -24,10 +24,14 @@ * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. -*/ - + */ package mage.server.tournament; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; import mage.cards.decks.Deck; import mage.game.tournament.Tournament; import mage.interfaces.callback.ClientCallback; @@ -38,16 +42,11 @@ import mage.server.util.ThreadExecutor; import mage.view.TournamentView; import org.apache.log4j.Logger; -import java.util.Optional; -import java.util.UUID; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - /** * @author BetaSteward_at_googlemail.com */ public class TournamentSession { + protected final static Logger logger = Logger.getLogger(TournamentSession.class); protected final UUID userId; @@ -79,16 +78,16 @@ public class TournamentSession { public void update() { if (!killed) { - UserManager.instance.getUser(userId).ifPresent(user -> - user.fireCallback(new ClientCallback(ClientCallbackMethod.TOURNAMENT_UPDATE, tournament.getId(), getTournamentView()))); + UserManager.instance.getUser(userId).ifPresent(user + -> user.fireCallback(new ClientCallback(ClientCallbackMethod.TOURNAMENT_UPDATE, tournament.getId(), getTournamentView()))); } } public void gameOver(final String message) { if (!killed) { - UserManager.instance.getUser(userId).ifPresent(user -> - user.fireCallback(new ClientCallback(ClientCallbackMethod.TOURNAMENT_OVER, tournament.getId(), message))); + UserManager.instance.getUser(userId).ifPresent(user + -> user.fireCallback(new ClientCallback(ClientCallbackMethod.TOURNAMENT_OVER, tournament.getId(), message))); } } @@ -108,8 +107,8 @@ public class TournamentSession { tournament.submitDeck(playerId, deck); } - public void updateDeck(Deck deck) { - tournament.updateDeck(playerId, deck); + public boolean updateDeck(Deck deck) { + return tournament.updateDeck(playerId, deck); } public void setKilled() { @@ -171,9 +170,8 @@ public class TournamentSession { } private void removeTournamentForUser() { - UserManager.instance.getUser(userId).ifPresent(user -> - user.removeTournament(playerId)); - + UserManager.instance.getUser(userId).ifPresent(user + -> user.removeTournament(playerId)); } diff --git a/Mage.Tests/src/test/java/org/mage/test/stub/TournamentStub.java b/Mage.Tests/src/test/java/org/mage/test/stub/TournamentStub.java index 018ef65707..c3b2378b2e 100644 --- a/Mage.Tests/src/test/java/org/mage/test/stub/TournamentStub.java +++ b/Mage.Tests/src/test/java/org/mage/test/stub/TournamentStub.java @@ -27,6 +27,10 @@ */ package org.mage.test.stub; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.UUID; import mage.cards.ExpansionSet; import mage.cards.decks.Deck; import mage.game.draft.Draft; @@ -38,11 +42,6 @@ import mage.game.tournament.*; import mage.players.Player; import mage.players.PlayerType; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.UUID; - /** * * @author Quercitron @@ -112,8 +111,8 @@ public class TournamentStub implements Tournament { } @Override - public void updateDeck(UUID playerId, Deck deck) { - + public boolean updateDeck(UUID playerId, Deck deck) { + return true; } @Override diff --git a/Mage/src/main/java/mage/cards/decks/Deck.java b/Mage/src/main/java/mage/cards/decks/Deck.java index 35e715dccc..57c6a1e96f 100644 --- a/Mage/src/main/java/mage/cards/decks/Deck.java +++ b/Mage/src/main/java/mage/cards/decks/Deck.java @@ -48,6 +48,7 @@ public class Deck implements Serializable { private DeckCardLayout cardsLayout; private DeckCardLayout sideboardLayout; private long deckHashCode = 0; + private long deckCompleteHashCode = 0; public static Deck load(DeckCardLists deckCardLists) throws GameException { return Deck.load(deckCardLists, false); @@ -56,10 +57,10 @@ public class Deck implements Serializable { public static Deck load(DeckCardLists deckCardLists, boolean ignoreErrors) throws GameException { return Deck.load(deckCardLists, ignoreErrors, true); } - + public static Deck append(Deck deckToAppend, Deck currentDeck) throws GameException { List deckCardNames = new ArrayList<>(); - + for (Card card : deckToAppend.getCards()) { if (card != null) { currentDeck.cards.add(card); @@ -72,7 +73,7 @@ public class Deck implements Serializable { currentDeck.sideboard.add(card); deckCardNames.add(card.getName()); } - } + } Collections.sort(deckCardNames); Collections.sort(sbCardNames); String deckString = deckCardNames.toString() + sbCardNames.toString(); @@ -90,11 +91,13 @@ public class Deck implements Serializable { for (DeckCardInfo deckCardInfo : deckCardLists.getCards()) { Card card = createCard(deckCardInfo, mockCards); if (card != null) { - if (totalCards < 1000) { - deck.cards.add(card); - deckCardNames.add(card.getName()); - totalCards++; + if (totalCards > 1000) { + break; } + deck.cards.add(card); + deckCardNames.add(card.getName()); + totalCards++; + } else if (!ignoreErrors) { throw createCardNotFoundGameException(deckCardInfo, deckCardLists.getName()); } @@ -103,11 +106,12 @@ public class Deck implements Serializable { for (DeckCardInfo deckCardInfo : deckCardLists.getSideboard()) { Card card = createCard(deckCardInfo, mockCards); if (card != null) { - if (totalCards < 1000) { - deck.sideboard.add(card); - sbCardNames.add(card.getName()); - totalCards++; + if (totalCards > 1000) { + break; } + deck.sideboard.add(card); + sbCardNames.add(card.getName()); + totalCards++; } else if (!ignoreErrors) { throw createCardNotFoundGameException(deckCardInfo, deckCardLists.getName()); } @@ -116,6 +120,15 @@ public class Deck implements Serializable { Collections.sort(sbCardNames); String deckString = deckCardNames.toString() + sbCardNames.toString(); deck.setDeckHashCode(DeckUtil.fixedHash(deckString)); + if (sbCardNames.isEmpty()) { + deck.setDeckCompleteHashCode(deck.getDeckHashCode()); + } else { + List deckAllCardNames = new ArrayList<>(); + deckAllCardNames.addAll(deckCardNames); + deckAllCardNames.addAll(sbCardNames); + Collections.sort(deckAllCardNames); + deck.setDeckCompleteHashCode(DeckUtil.fixedHash(deckAllCardNames.toString())); + } return deck; } @@ -206,6 +219,14 @@ public class Deck implements Serializable { this.deckHashCode = deckHashCode; } + public long getDeckCompleteHashCode() { + return deckCompleteHashCode; + } + + public void setDeckCompleteHashCode(long deckHashCode) { + this.deckCompleteHashCode = deckHashCode; + } + public void clearLayouts() { this.cardsLayout = null; this.sideboardLayout = null; diff --git a/Mage/src/main/java/mage/game/match/Match.java b/Mage/src/main/java/mage/game/match/Match.java index 3f0b432902..73ce1cd88a 100644 --- a/Mage/src/main/java/mage/game/match/Match.java +++ b/Mage/src/main/java/mage/game/match/Match.java @@ -1,16 +1,16 @@ /* * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR @@ -20,26 +20,24 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.game.match; -import mage.cards.decks.Deck; -import mage.game.Game; -import mage.game.GameException; -import mage.game.events.Listener; -import mage.game.events.TableEvent; -import mage.players.Player; - import java.util.Date; import java.util.List; import java.util.UUID; +import mage.cards.decks.Deck; +import mage.game.Game; +import mage.game.GameException; import mage.game.GameInfo; +import mage.game.events.Listener; +import mage.game.events.TableEvent; import mage.game.result.ResultProtos.MatchProto; +import mage.players.Player; /** * @@ -50,52 +48,79 @@ public interface Match { int SIDEBOARD_TIME = 180; UUID getId(); + String getName(); + boolean hasEnded(); + boolean hasStarted(); + boolean checkIfMatchEnds(); + List getPlayers(); + MatchPlayer getPlayer(UUID playerId); void addPlayer(Player player, Deck deck); + boolean quitMatch(UUID playerId); void submitDeck(UUID playerId, Deck deck); - void updateDeck(UUID playerId, Deck deck); + + boolean updateDeck(UUID playerId, Deck deck); + void startMatch(); + void startGame() throws GameException; + void sideboard(); + void endGame(); + Game getGame(); + List getGames(); + int getWinsNeeded(); + int getFreeMulligans(); + void addDraw(); + int getDraws(); + int getNumGames(); + void addGame(); + boolean isDoneSideboarding(); + UUID getChooser(); + MatchOptions getOptions(); void addTableEventListener(Listener listener); + void fireSideboardEvent(UUID playerId, Deck deck); // match times Date getStartTime(); + Date getEndTime(); + /** * Can the games of the match be replayed - * + * * @return */ boolean isReplayAvailable(); + void setReplayAvailable(boolean replayAvailable); - + /** * Free resources no longer needed if match ended and only exists for * information purpose. - * + * * @param isSaveGameActivated * @param isTournament */ @@ -111,6 +136,7 @@ public interface Match { List getGamesInfo(); void setTableId(UUID tableId); + void setTournamentRound(int round); MatchProto toProto(); diff --git a/Mage/src/main/java/mage/game/match/MatchImpl.java b/Mage/src/main/java/mage/game/match/MatchImpl.java index 4f52db281e..961996df32 100644 --- a/Mage/src/main/java/mage/game/match/MatchImpl.java +++ b/Mage/src/main/java/mage/game/match/MatchImpl.java @@ -409,11 +409,18 @@ public abstract class MatchImpl implements Match { } @Override - public void updateDeck(UUID playerId, Deck deck) { + public boolean updateDeck(UUID playerId, Deck deck) { + boolean validDeck = true; MatchPlayer player = getPlayer(playerId); if (player != null) { + // Check if the cards included in the deck are the same as in the original deck + validDeck = (player.getDeck().getDeckCompleteHashCode() == deck.getDeckCompleteHashCode()); + if (validDeck == false) { + deck.getCards().clear(); // Clear the deck so the player cheating looses the game + } player.updateDeck(deck); } + return validDeck; } protected String createGameStartMessage() { @@ -502,10 +509,10 @@ public abstract class MatchImpl implements Match { .setMatchOptions(this.getOptions().toProto()) .setEndTimeMs((this.getEndTime() != null ? this.getEndTime() : new Date()).getTime()); for (MatchPlayer matchPlayer : this.getPlayers()) { - MatchQuitStatus status = !matchPlayer.hasQuit() ? MatchQuitStatus.NO_MATCH_QUIT : - matchPlayer.getPlayer().hasTimerTimeout() ? MatchQuitStatus.TIMER_TIMEOUT : - matchPlayer.getPlayer().hasIdleTimeout() ? MatchQuitStatus.IDLE_TIMEOUT : - MatchQuitStatus.QUIT; + MatchQuitStatus status = !matchPlayer.hasQuit() ? MatchQuitStatus.NO_MATCH_QUIT + : matchPlayer.getPlayer().hasTimerTimeout() ? MatchQuitStatus.TIMER_TIMEOUT + : matchPlayer.getPlayer().hasIdleTimeout() ? MatchQuitStatus.IDLE_TIMEOUT + : MatchQuitStatus.QUIT; builder.addPlayersBuilder() .setName(matchPlayer.getName()) .setHuman(matchPlayer.getPlayer().isHuman()) diff --git a/Mage/src/main/java/mage/game/match/MatchPlayer.java b/Mage/src/main/java/mage/game/match/MatchPlayer.java index 3bc8a66edd..528cb41063 100644 --- a/Mage/src/main/java/mage/game/match/MatchPlayer.java +++ b/Mage/src/main/java/mage/game/match/MatchPlayer.java @@ -98,6 +98,7 @@ public class MatchPlayer implements Serializable { if (this.deck != null) { // preserver deck name, important for Tiny Leaders format deck.setName(this.getDeck().getName()); + // preserve the original deck hash code before sideboarding to give no information if cards were swapped deck.setDeckHashCode(this.getDeck().getDeckHashCode()); } this.deck = deck; diff --git a/Mage/src/main/java/mage/game/tournament/Tournament.java b/Mage/src/main/java/mage/game/tournament/Tournament.java index 7cdad0eebf..73496021fd 100644 --- a/Mage/src/main/java/mage/game/tournament/Tournament.java +++ b/Mage/src/main/java/mage/game/tournament/Tournament.java @@ -27,6 +27,10 @@ */ package mage.game.tournament; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.UUID; import mage.cards.ExpansionSet; import mage.cards.decks.Deck; import mage.game.draft.Draft; @@ -37,11 +41,6 @@ import mage.game.result.ResultProtos.TourneyProto; import mage.players.Player; import mage.players.PlayerType; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.UUID; - /** * * @author BetaSteward_at_googlemail.com @@ -76,7 +75,7 @@ public interface Tournament { void submitDeck(UUID playerId, Deck deck); - void updateDeck(UUID playerId, Deck deck); + boolean updateDeck(UUID playerId, Deck deck); void autoSubmit(UUID playerId, Deck deck); diff --git a/Mage/src/main/java/mage/game/tournament/TournamentImpl.java b/Mage/src/main/java/mage/game/tournament/TournamentImpl.java index b5f5ed2a93..19e66874fb 100644 --- a/Mage/src/main/java/mage/game/tournament/TournamentImpl.java +++ b/Mage/src/main/java/mage/game/tournament/TournamentImpl.java @@ -27,6 +27,8 @@ */ package mage.game.tournament; +import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; import mage.cards.ExpansionSet; import mage.cards.decks.Deck; import mage.constants.TournamentPlayerState; @@ -37,14 +39,16 @@ import mage.game.events.TableEvent.EventType; import mage.game.match.Match; import mage.game.match.MatchPlayer; import mage.game.result.ResultProtos.*; +import mage.game.result.ResultProtos.MatchPlayerProto; +import mage.game.result.ResultProtos.MatchProto; +import mage.game.result.ResultProtos.MatchQuitStatus; +import mage.game.result.ResultProtos.TourneyProto; +import mage.game.result.ResultProtos.TourneyRoundProto; import mage.players.Player; import mage.players.PlayerType; import mage.util.RandomUtil; import org.apache.log4j.Logger; -import java.util.*; -import java.util.concurrent.CopyOnWriteArrayList; - /** * * @author BetaSteward_at_googlemail.com @@ -168,10 +172,11 @@ public abstract class TournamentImpl implements Tournament { } @Override - public void updateDeck(UUID playerId, Deck deck) { + public boolean updateDeck(UUID playerId, Deck deck) { if (players.containsKey(playerId)) { - players.get(playerId).updateDeck(deck); + return players.get(playerId).updateDeck(deck); } + return false; } protected Round createRoundRandom() { @@ -246,12 +251,12 @@ public abstract class TournamentImpl implements Tournament { } updateResults(); } - + protected void playMultiplayerRound(MultiplayerRound round) { playMultiPlayerMatch(round); - + updateResults(); // show points from byes - } + } protected List getActivePlayers() { List activePlayers = new ArrayList<>(); @@ -442,7 +447,7 @@ public abstract class TournamentImpl implements Tournament { options.getMatchOptions().getPlayerTypes().add(pair.getPlayer2().getPlayerType()); tableEventSource.fireTableEvent(EventType.START_MATCH, pair, options.getMatchOptions()); } - + public void playMultiPlayerMatch(MultiplayerRound round) { tableEventSource.fireTableEvent(EventType.START_MULTIPLAYER_MATCH, round, options.getMatchOptions()); } @@ -588,10 +593,10 @@ public abstract class TournamentImpl implements Tournament { private MatchPlayerProto matchToProto(Match match, TournamentPlayer player) { MatchPlayer matchPlayer = match.getPlayer(player.getPlayer().getId()); - MatchQuitStatus quit = !matchPlayer.hasQuit() ? MatchQuitStatus.NO_MATCH_QUIT : - matchPlayer.getPlayer().hasIdleTimeout() ? MatchQuitStatus.IDLE_TIMEOUT : - matchPlayer.getPlayer().hasTimerTimeout() ? MatchQuitStatus.TIMER_TIMEOUT : - MatchQuitStatus.QUIT; + MatchQuitStatus quit = !matchPlayer.hasQuit() ? MatchQuitStatus.NO_MATCH_QUIT + : matchPlayer.getPlayer().hasIdleTimeout() ? MatchQuitStatus.IDLE_TIMEOUT + : matchPlayer.getPlayer().hasTimerTimeout() ? MatchQuitStatus.TIMER_TIMEOUT + : MatchQuitStatus.QUIT; return MatchPlayerProto.newBuilder() .setName(player.getPlayer().getName()) .setHuman(player.getPlayer().isHuman()) diff --git a/Mage/src/main/java/mage/game/tournament/TournamentPlayer.java b/Mage/src/main/java/mage/game/tournament/TournamentPlayer.java index 0e0f6f7f81..710ff68181 100644 --- a/Mage/src/main/java/mage/game/tournament/TournamentPlayer.java +++ b/Mage/src/main/java/mage/game/tournament/TournamentPlayer.java @@ -1,16 +1,16 @@ /* * Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR @@ -20,14 +20,14 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.game.tournament; +import java.util.Set; import mage.cards.decks.Deck; import mage.constants.TournamentPlayerState; import mage.game.result.ResultProtos.TourneyPlayerProto; @@ -36,8 +36,6 @@ import mage.players.Player; import mage.players.PlayerType; import mage.util.TournamentUtil; -import java.util.Set; - /** * * @author BetaSteward_at_googlemail.com @@ -117,8 +115,14 @@ public class TournamentPlayer { this.setState(TournamentPlayerState.WAITING); } - public void updateDeck(Deck deck) { + public boolean updateDeck(Deck deck) { + // Check if the cards included in the deck are the same as in the original deck + boolean validDeck = (getDeck().getDeckCompleteHashCode() == deck.getDeckCompleteHashCode()); + if (validDeck == false) { + deck.getCards().clear(); // Clear the deck so the player cheating looses the game + } this.deck = deck; + return validDeck; } public Deck generateDeck() { @@ -137,15 +141,13 @@ public class TournamentPlayer { deck.getCards().addAll(TournamentUtil.getLands("Swamp", landsPerType, landSets)); deck.getCards().addAll(TournamentUtil.getLands("Forest", landsPerType, landSets)); deck.getCards().addAll(TournamentUtil.getLands("Island", landsPerType, landSets)); - + this.doneConstructing = true; this.setState(TournamentPlayerState.WAITING); - + return deck; } - - public boolean isDoneConstructing() { return this.doneConstructing; } @@ -201,7 +203,7 @@ public class TournamentPlayer { /** * Free resources no longer needed if tournament has ended - * + * */ public void CleanUpOnTournamentEnd() { this.deck = null; @@ -216,7 +218,7 @@ public class TournamentPlayer { this.setState(TournamentPlayerState.FINISHED); } } - + public boolean isInTournament() { return !(this.getState() == TournamentPlayerState.CANCELED) && !(this.getState() == TournamentPlayerState.ELIMINATED) @@ -239,4 +241,3 @@ public class TournamentPlayer { .build(); } } -