diff --git a/Mage.Client/src/main/java/mage/client/MageFrame.java b/Mage.Client/src/main/java/mage/client/MageFrame.java index 0fca6f2f8fc..5a705cea5b0 100644 --- a/Mage.Client/src/main/java/mage/client/MageFrame.java +++ b/Mage.Client/src/main/java/mage/client/MageFrame.java @@ -848,12 +848,30 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { } public void showDeckEditor(DeckEditorMode mode, Deck deck, UUID tableId, int time) { + String name; + if (mode == DeckEditorMode.Sideboard || mode == DeckEditorMode.Limited) + name = "Deck Editor - " + tableId.toString(); + else { + if (deck != null) + name = "Deck Editor - " + deck.getName(); + else + name = "Deck Editor"; + } + JInternalFrame[] windows = desktopPane.getAllFramesInLayer(JLayeredPane.DEFAULT_LAYER); + for (JInternalFrame window : windows) { + if (window instanceof DeckEditorPane) { + if (window.getTitle().equals(name)) { + setActive((MagePane)window); + return; + } + } + } try { DeckEditorPane deckEditorPane = new DeckEditorPane(); desktopPane.add(deckEditorPane, JLayeredPane.DEFAULT_LAYER); deckEditorPane.setMaximum(true); deckEditorPane.setVisible(true); - deckEditorPane.show(mode, deck, tableId, time); + deckEditorPane.show(mode, deck, name, tableId, time); setActive(deckEditorPane); } catch (PropertyVetoException ex) { logger.fatal(null, ex); diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPane.java b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPane.java index 842be6614f7..c2515db4729 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPane.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPane.java @@ -73,11 +73,15 @@ public class DeckEditorPane extends MagePane { } } - public void show(DeckEditorMode mode, Deck deck, UUID tableId, int time) { - if (deck != null) - this.setTitle("Deck Editor - " + deck.getName()); - else - this.setTitle("Deck Editor"); + public void show(DeckEditorMode mode, Deck deck, String name, UUID tableId, int time) { + if (mode == DeckEditorMode.Sideboard || mode == DeckEditorMode.Limited) + this.setTitle("Deck Editor - " + tableId.toString()); + else { + if (deck != null) + this.setTitle("Deck Editor - " + deck.getName()); + else + this.setTitle("Deck Editor"); + } this.deckEditorPanel1.showDeckEditor(mode, deck, tableId, time); this.repaint(); } diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java index 7b995108771..7c50341c347 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java @@ -102,6 +102,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { else { setTimeout("0"); countdown.stop(); + hideDeckEditor(); } } } diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index d1ceb4d56ea..8c6be134afe 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -643,7 +643,7 @@ public class HumanPlayer extends PlayerImpl { @Override public void construct(Tournament tournament, Deck deck) { - tournament.fireConstructEvent(playerId, deck); + tournament.fireConstructEvent(playerId); } @Override diff --git a/Mage.Server/plugins/mage-player-human.jar b/Mage.Server/plugins/mage-player-human.jar index bd0cf1e7a2b..0aead2a8ce1 100644 Binary files a/Mage.Server/plugins/mage-player-human.jar and b/Mage.Server/plugins/mage-player-human.jar differ diff --git a/Mage.Server/src/main/java/mage/server/TableController.java b/Mage.Server/src/main/java/mage/server/TableController.java index 4aa95357ad8..d11cf594941 100644 --- a/Mage.Server/src/main/java/mage/server/TableController.java +++ b/Mage.Server/src/main/java/mage/server/TableController.java @@ -56,7 +56,12 @@ import org.apache.log4j.Logger; import java.util.Map.Entry; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; import mage.cards.decks.InvalidDeckException; +import mage.game.match.MatchPlayer; +import mage.server.util.ThreadExecutor; /** * @@ -74,6 +79,9 @@ public class TableController { private MatchOptions options; private Tournament tournament; private ConcurrentHashMap userPlayerMap = new ConcurrentHashMap(); + + private ScheduledFuture futureTimeout; + protected static ScheduledExecutorService timeoutExecutor = ThreadExecutor.getInstance().getTimeoutExecutor(); public TableController(UUID roomId, UUID userId, MatchOptions options) { this.userId = userId; @@ -111,10 +119,7 @@ public class TableController { try { switch (event.getEventType()) { case SIDEBOARD: - sideboard(event.getPlayerId(), event.getDeck(), event.getTimeout()); - break; - case SUBMIT_DECK: - submitDeck(event.getPlayerId(), event.getDeck()); + sideboard(event.getPlayerId(), event.getDeck()); break; } } catch (MageException ex) { @@ -200,16 +205,18 @@ public class TableController { if (!Main.isTestMode() && !table.getValidator().validate(deck)) { throw new InvalidDeckException("Invalid deck for this format", table.getValidator().getInvalid()); } - submitDeck(playerId, deck); + submitDeck(userId, playerId, deck); return true; } - private void submitDeck(UUID playerId, Deck deck) { + private void submitDeck(UUID userId, UUID playerId, Deck deck) { if (table.getState() == TableState.SIDEBOARDING) { match.submitDeck(playerId, deck); + UserManager.getInstance().getUser(userId).removeSideboarding(table.getId()); } else { TournamentManager.getInstance().submitDeck(tournament.getId(), playerId, deck); + UserManager.getInstance().getUser(userId).removeConstructing(table.getId()); } } @@ -350,17 +357,22 @@ public class TableController { } } - private void sideboard(UUID playerId, Deck deck, int timeout) throws MageException { + private void sideboard(UUID playerId, Deck deck) throws MageException { for (Entry entry: userPlayerMap.entrySet()) { if (entry.getValue().equals(playerId)) { User user = UserManager.getInstance().getUser(entry.getKey()); - if (user != null) - user.sideboard(deck, table.getId(), timeout); + int remaining = (int) futureTimeout.getDelay(TimeUnit.SECONDS); + if (user != null) + user.sideboard(deck, table.getId(), remaining); break; } } } + public int getRemainingTime() { + return (int) futureTimeout.getDelay(TimeUnit.SECONDS); + } + public void construct() { table.construct(); } @@ -374,7 +386,9 @@ public class TableController { try { if (!match.isMatchOver()) { table.sideboard(); + setupTimeout(Match.SIDEBOARD_TIME); match.sideboard(); + cancelTimeout(); startGame(choosingPlayerId); } // else { @@ -385,7 +399,35 @@ public class TableController { } } - public void endDraft(Draft draft) { + private synchronized void setupTimeout(int seconds) { + cancelTimeout(); + if (seconds > 0) { + futureTimeout = timeoutExecutor.schedule( + new Runnable() { + @Override + public void run() { + autoSideboard(); + } + }, + seconds, TimeUnit.SECONDS + ); + } + } + + private synchronized void cancelTimeout() { + if (futureTimeout != null) { + futureTimeout.cancel(false); + } + } + + private void autoSideboard() { + for (MatchPlayer player: match.getPlayers()) { + if (!player.isDoneSideboarding()) + match.submitDeck(player.getPlayer().getId(), player.generateDeck()); + } + } + + public void endDraft(Draft draft) { for (DraftPlayer player: draft.getPlayers()) { tournament.getPlayer(player.getPlayer().getId()).setDeck(player.getDeck()); } diff --git a/Mage.Server/src/main/java/mage/server/TableManager.java b/Mage.Server/src/main/java/mage/server/TableManager.java index 776065ded88..63984059d3d 100644 --- a/Mage.Server/src/main/java/mage/server/TableManager.java +++ b/Mage.Server/src/main/java/mage/server/TableManager.java @@ -96,6 +96,10 @@ public class TableManager { return tables.values(); } + public TableController getController(UUID tableId) { + return controllers.get(tableId); + } + public boolean joinTable(UUID userId, UUID tableId, String name, String playerType, int skill, DeckCardLists deckList) throws MageException { if (controllers.containsKey(tableId)) return controllers.get(tableId).joinTable(userId, name, playerType, skill, deckList); diff --git a/Mage.Server/src/main/java/mage/server/User.java b/Mage.Server/src/main/java/mage/server/User.java index 5d15ac9208e..00d43fb7613 100644 --- a/Mage.Server/src/main/java/mage/server/User.java +++ b/Mage.Server/src/main/java/mage/server/User.java @@ -27,8 +27,10 @@ */ package mage.server; +import java.util.ArrayList; import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.UUID; @@ -62,6 +64,8 @@ public class User { private Map gameSessions = new HashMap(); private Map draftSessions = new HashMap(); private Map tournamentSessions = new HashMap(); + private Map constructing = new HashMap(); + private Map sideboarding = new HashMap(); public User(String userName, String host) { this.userName = userName; @@ -130,6 +134,7 @@ public class User { public void sideboard(final Deck deck, final UUID tableId, final int time) { fireCallback(new ClientCallback("sideboard", tableId, new TableClientMessage(deck, tableId, time))); + sideboarding.put(tableId, deck); } public void construct(final Deck deck, final UUID tableId, final int time) { @@ -187,6 +192,13 @@ public class User { entry.getValue().init(); entry.getValue().update(); } + for (Entry entry: constructing.entrySet()) { + entry.getValue().construct(0); + } + for (Entry entry: sideboarding.entrySet()) { + int remaining = TableManager.getInstance().getController(entry.getKey()).getRemainingTime(); + sideboard(entry.getValue(), entry.getKey(), remaining); + } } public void addGame(UUID playerId, GameSession gameSession) { @@ -220,8 +232,20 @@ public class User { public void removeTable(UUID playerId) { tables.remove(playerId); } + + public void addConstructing(UUID playerId, TournamentSession tournamentSession) { + constructing.put(playerId, tournamentSession); + } - public void kill() { + public void removeConstructing(UUID playerId) { + constructing.remove(playerId); + } + + public void removeSideboarding(UUID tableId) { + sideboarding.remove(tableId); + } + + public void kill() { for (GameSession session: gameSessions.values()) { session.kill(); } 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 495b6b675d7..cd8dc605631 100644 --- a/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java +++ b/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java @@ -91,9 +91,9 @@ public class TournamentController { case START_MATCH: startMatch(event.getPair(), event.getMatchOptions()); break; - case SUBMIT_DECK: - submitDeck(event.getPlayerId(), event.getDeck()); - break; +// case SUBMIT_DECK: +// submitDeck(event.getPlayerId(), event.getDeck()); +// break; case CONSTRUCT: construct(); break; @@ -111,7 +111,7 @@ public class TournamentController { try { switch (event.getQueryType()) { case CONSTRUCT: - construct(event.getPlayerId(), event.getDeck(), event.getMax()); + construct(event.getPlayerId(), event.getMax()); break; } } catch (MageException ex) { @@ -208,9 +208,12 @@ public class TournamentController { TableManager.getInstance().construct(tableId); } - private void construct(UUID playerId, Deck deck, int timeout) throws MageException { - if (tournamentSessions.containsKey(playerId)) - tournamentSessions.get(playerId).construct(deck, timeout); + private void construct(UUID playerId, int timeout) throws MageException { + if (tournamentSessions.containsKey(playerId)) { + TournamentSession tournamentSession = tournamentSessions.get(playerId); + tournamentSession.construct(timeout); + UserManager.getInstance().getUser(getPlayerSessionId(playerId)).addConstructing(playerId, tournamentSession); + } } public void submitDeck(UUID playerId, Deck deck) { @@ -220,7 +223,7 @@ public class TournamentController { public void timeout(UUID userId) { if (userPlayerMap.containsKey(userId)) { TournamentPlayer player = tournament.getPlayer(userPlayerMap.get(userId)); - tournament.autoSubmit(userPlayerMap.get(userId), player.getDeck()); + tournament.autoSubmit(userPlayerMap.get(userId), player.generateDeck()); } } 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 3cb37fed201..7b4fa5e9639 100644 --- a/Mage.Server/src/main/java/mage/server/tournament/TournamentSession.java +++ b/Mage.Server/src/main/java/mage/server/tournament/TournamentSession.java @@ -96,12 +96,13 @@ public class TournamentSession { } } - public void construct(Deck deck, int timeout) throws MageException { + public void construct(int timeout) { if (!killed) { setupTimeout(timeout); User user = UserManager.getInstance().getUser(userId); if (user != null) { - user.construct(deck, tableId, timeout); + int remaining = (int) futureTimeout.getDelay(TimeUnit.SECONDS); + user.construct(tournament.getPlayer(playerId).getDeck(), tableId, remaining); } } } @@ -121,6 +122,8 @@ public class TournamentSession { } private synchronized void setupTimeout(int seconds) { + if (futureTimeout != null && !futureTimeout.isDone()) + return; cancelTimeout(); if (seconds > 0) { futureTimeout = timeoutExecutor.schedule( diff --git a/Mage/src/mage/game/events/PlayerQueryEvent.java b/Mage/src/mage/game/events/PlayerQueryEvent.java index 0ed8cd92cbc..24312db9574 100644 --- a/Mage/src/mage/game/events/PlayerQueryEvent.java +++ b/Mage/src/mage/game/events/PlayerQueryEvent.java @@ -36,7 +36,6 @@ import mage.abilities.ActivatedAbility; import mage.abilities.TriggeredAbilities; import mage.cards.Card; import mage.cards.Cards; -import mage.cards.decks.Deck; import mage.game.permanent.Permanent; /** @@ -61,7 +60,6 @@ public class PlayerQueryEvent extends EventObject implements ExternalEvent, Seri private boolean required; private int min; private int max; - private Deck deck; private Map options; private Map modes; @@ -93,12 +91,11 @@ public class PlayerQueryEvent extends EventObject implements ExternalEvent, Seri this.max = time; } - private PlayerQueryEvent(UUID playerId, String message, QueryType queryType, Deck deck, int time) { + private PlayerQueryEvent(UUID playerId, String message, QueryType queryType, int time) { super(playerId); this.queryType = queryType; this.message = message; this.playerId = playerId; - this.deck = deck; this.max = time; } @@ -179,8 +176,8 @@ public class PlayerQueryEvent extends EventObject implements ExternalEvent, Seri return new PlayerQueryEvent(playerId, message, booster, QueryType.PICK_CARD, time); } - public static PlayerQueryEvent construct(UUID playerId, String message, Deck deck, int time) { - return new PlayerQueryEvent(playerId, message, QueryType.CONSTRUCT, deck, time); + public static PlayerQueryEvent construct(UUID playerId, String message, int time) { + return new PlayerQueryEvent(playerId, message, QueryType.CONSTRUCT, time); } @@ -232,10 +229,6 @@ public class PlayerQueryEvent extends EventObject implements ExternalEvent, Seri return max; } - public Deck getDeck() { - return deck; - } - public Map getOptions() { return options; } diff --git a/Mage/src/mage/game/events/PlayerQueryEventSource.java b/Mage/src/mage/game/events/PlayerQueryEventSource.java index b68c960d453..6a5c902bdd2 100644 --- a/Mage/src/mage/game/events/PlayerQueryEventSource.java +++ b/Mage/src/mage/game/events/PlayerQueryEventSource.java @@ -113,8 +113,8 @@ public class PlayerQueryEventSource implements EventSource, Se dispatcher.fireEvent(PlayerQueryEvent.pickCard(playerId, message, booster, time)); } - public void construct(UUID playerId, String message, Deck deck, int time) { - dispatcher.fireEvent(PlayerQueryEvent.construct(playerId, message, deck, time)); + public void construct(UUID playerId, String message, int time) { + dispatcher.fireEvent(PlayerQueryEvent.construct(playerId, message, time)); } } diff --git a/Mage/src/mage/game/match/Match.java b/Mage/src/mage/game/match/Match.java index f8777118176..f16a8c46172 100644 --- a/Mage/src/mage/game/match/Match.java +++ b/Mage/src/mage/game/match/Match.java @@ -43,7 +43,9 @@ import mage.players.Player; */ public interface Match { - public UUID getId(); + public static final int SIDEBOARD_TIME = 180; + + public UUID getId(); public String getName(); public boolean isMatchOver(); public List getPlayers(); diff --git a/Mage/src/mage/game/match/MatchImpl.java b/Mage/src/mage/game/match/MatchImpl.java index e591aaeeda3..74326818ca1 100644 --- a/Mage/src/mage/game/match/MatchImpl.java +++ b/Mage/src/mage/game/match/MatchImpl.java @@ -31,7 +31,6 @@ package mage.game.match; import java.util.ArrayList; import java.util.List; import java.util.UUID; -import java.util.logging.Logger; import mage.cards.decks.Deck; import mage.game.Game; import mage.game.GameException; @@ -48,7 +47,6 @@ import mage.players.Player; public abstract class MatchImpl implements Match { // private final static Logger logger = Logging.getLogger(MatchImpl.class.getName()); - private static final int SIDEBOARD_TIME = 180; protected UUID id = UUID.randomUUID(); protected String name; @@ -199,7 +197,7 @@ public abstract class MatchImpl implements Match { return true; } - @Override + @Override public void fireSideboardEvent(UUID playerId, Deck deck) { MatchPlayer player = getPlayer(playerId); if (player != null) { diff --git a/Mage/src/mage/game/match/MatchPlayer.java b/Mage/src/mage/game/match/MatchPlayer.java index 6408ad00758..6677783da40 100644 --- a/Mage/src/mage/game/match/MatchPlayer.java +++ b/Mage/src/mage/game/match/MatchPlayer.java @@ -28,6 +28,7 @@ package mage.game.match; +import mage.cards.Card; import mage.cards.decks.Deck; import mage.players.Player; @@ -75,6 +76,16 @@ public class MatchPlayer { this.doneSideboarding = true; } + public Deck generateDeck() { + //TODO: improve this + while (deck.getCards().size() < 40 && deck.getSideboard().size() > 0) { + Card card = deck.getSideboard().iterator().next(); + deck.getCards().add(card); + deck.getSideboard().remove(card); + } + return deck; + } + public Player getPlayer() { return player; } diff --git a/Mage/src/mage/game/tournament/Tournament.java b/Mage/src/mage/game/tournament/Tournament.java index 2f16ef6cfaf..fa9e08afbbb 100644 --- a/Mage/src/mage/game/tournament/Tournament.java +++ b/Mage/src/mage/game/tournament/Tournament.java @@ -59,7 +59,6 @@ public interface Tournament { public void addTableEventListener(Listener listener); public void addPlayerQueryEventListener(Listener listener); - public void fireConstructEvent(UUID playerId, Deck deck); - public void fireSubmitDeckEvent(UUID playerId, Deck deck); + public void fireConstructEvent(UUID playerId); } diff --git a/Mage/src/mage/game/tournament/TournamentImpl.java b/Mage/src/mage/game/tournament/TournamentImpl.java index fdf750c6072..0cc1fac03cc 100644 --- a/Mage/src/mage/game/tournament/TournamentImpl.java +++ b/Mage/src/mage/game/tournament/TournamentImpl.java @@ -214,20 +214,15 @@ public abstract class TournamentImpl implements Tournament { tableEventSource.addListener(listener); } - @Override - public void fireSubmitDeckEvent(UUID playerId, Deck deck) { - tableEventSource.fireTableEvent(EventType.SUBMIT_DECK, playerId, deck, 0); - } - @Override public void addPlayerQueryEventListener(Listener listener) { playerQueryEventSource.addListener(listener); } @Override - public void fireConstructEvent(UUID playerId, Deck deck) { + public void fireConstructEvent(UUID playerId) { TournamentPlayer player = players.get(playerId); - playerQueryEventSource.construct(playerId, "Construct", deck, CONSTRUCT_TIME); + playerQueryEventSource.construct(playerId, "Construct", CONSTRUCT_TIME); } public void construct() { diff --git a/Mage/src/mage/game/tournament/TournamentPlayer.java b/Mage/src/mage/game/tournament/TournamentPlayer.java index 778fed3d386..6dfd2e7dc6d 100644 --- a/Mage/src/mage/game/tournament/TournamentPlayer.java +++ b/Mage/src/mage/game/tournament/TournamentPlayer.java @@ -28,6 +28,7 @@ package mage.game.tournament; +import mage.cards.Card; import mage.cards.decks.Deck; import mage.players.Player; @@ -97,6 +98,16 @@ public class TournamentPlayer { this.doneConstructing = true; } + public Deck generateDeck() { + //TODO: improve this + while (deck.getCards().size() < 40 && deck.getSideboard().size() > 0) { + Card card = deck.getSideboard().iterator().next(); + deck.getCards().add(card); + deck.getSideboard().remove(card); + } + return deck; + } + public boolean isDoneConstructing() { return this.doneConstructing; }