diff --git a/Mage.Server/src/main/java/mage/server/game/GameController.java b/Mage.Server/src/main/java/mage/server/game/GameController.java index c53665fcdd..23dd2e5fd8 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameController.java +++ b/Mage.Server/src/main/java/mage/server/game/GameController.java @@ -50,7 +50,6 @@ import java.util.zip.GZIPOutputStream; import mage.Constants.Zone; import mage.abilities.Ability; -import mage.abilities.Modes; import mage.cards.Card; import mage.cards.Cards; import mage.cards.decks.Deck; @@ -64,6 +63,7 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.server.ChatManager; import mage.server.UserManager; +import mage.server.util.Splitter; import mage.server.util.ThreadExecutor; import mage.sets.Sets; import mage.view.*; @@ -344,75 +344,94 @@ public class GameController implements GameCallback { } } - private synchronized void ask(UUID playerId, String question) throws MageException { - if (gameSessions.containsKey(playerId)) - gameSessions.get(playerId).ask(question); - informOthers(playerId); - } - - private synchronized void chooseAbility(UUID playerId, Collection choices) throws MageException { - if (gameSessions.containsKey(playerId)) - gameSessions.get(playerId).chooseAbility(new AbilityPickerView(choices)); - informOthers(playerId); - } - - private synchronized void chooseMode(UUID playerId, Map modes) throws MageException { - if (gameSessions.containsKey(playerId)) - gameSessions.get(playerId).chooseAbility(new AbilityPickerView(modes)); - informOthers(playerId); - } - - private synchronized void choose(UUID playerId, String message, Set choices) throws MageException { - if (gameSessions.containsKey(playerId)) - gameSessions.get(playerId).choose(message, choices); - informOthers(playerId); - } - - private synchronized void target(UUID playerId, String question, Cards cards, List perms, Set targets, boolean required, Map options) throws MageException { - if (gameSessions.containsKey(playerId)) { - if (cards != null) - gameSessions.get(playerId).target(question, new CardsView(cards.getCards(game)), targets, required, options); - else if (perms != null) { - CardsView permsView = new CardsView(); - for (Permanent perm: perms) { - permsView.put(perm.getId(), new PermanentView(perm, game.getCard(perm.getId()))); - } - gameSessions.get(playerId).target(question, permsView, targets, required, options); + private synchronized void ask(final UUID playerId, final String question) throws MageException { + perform(playerId, new Command() { + public void execute() { + gameSessions.get(playerId).ask(question); } - else - gameSessions.get(playerId).target(question, new CardsView(), targets, required, options); - } - informOthers(playerId); + }); } - private synchronized void target(UUID playerId, String question, Collection abilities, boolean required, Map options) throws MageException { - if (gameSessions.containsKey(playerId)) - gameSessions.get(playerId).target(question, new CardsView(abilities, game), null, required, options); - informOthers(playerId); + private synchronized void chooseAbility(final UUID playerId, final Collection choices) throws MageException { + perform(playerId, new Command() { + public void execute() { + gameSessions.get(playerId).chooseAbility(new AbilityPickerView(choices)); + } + }); } - private synchronized void select(UUID playerId, String message) throws MageException { - if (gameSessions.containsKey(playerId)) - gameSessions.get(playerId).select(message); - informOthers(playerId); + private synchronized void chooseMode(final UUID playerId, final Map modes) throws MageException { + perform(playerId, new Command() { + public void execute() { + gameSessions.get(playerId).chooseAbility(new AbilityPickerView(modes)); + } + }); } - private synchronized void playMana(UUID playerId, String message) throws MageException { - if (gameSessions.containsKey(playerId)) - gameSessions.get(playerId).playMana(message); - informOthers(playerId); + private synchronized void choose(final UUID playerId, final String message, final Set choices) throws MageException { + perform(playerId, new Command() { + public void execute() { + gameSessions.get(playerId).choose(message, choices); + } + }); } - private synchronized void playXMana(UUID playerId, String message) throws MageException { - if (gameSessions.containsKey(playerId)) - gameSessions.get(playerId).playXMana(message); - informOthers(playerId); + private synchronized void target(final UUID playerId, final String question, final Cards cards, final List perms, final Set targets, final boolean required, final Map options) throws MageException { + perform(playerId, new Command() { + public void execute() { + if (cards != null) { + gameSessions.get(playerId).target(question, new CardsView(cards.getCards(game)), targets, required, options); + } else if (perms != null) { + CardsView permsView = new CardsView(); + for (Permanent perm: perms) { + permsView.put(perm.getId(), new PermanentView(perm, game.getCard(perm.getId()))); + } + gameSessions.get(playerId).target(question, permsView, targets, required, options); + } else + gameSessions.get(playerId).target(question, new CardsView(), targets, required, options); + } + }); + } - private synchronized void amount(UUID playerId, String message, int min, int max) throws MageException { - if (gameSessions.containsKey(playerId)) - gameSessions.get(playerId).getAmount(message, min, max); - informOthers(playerId); + private synchronized void target(final UUID playerId, final String question, final Collection abilities, final boolean required, final Map options) throws MageException { + perform(playerId, new Command() { + public void execute() { + gameSessions.get(playerId).target(question, new CardsView(abilities, game), null, required, options); + } + }); + } + + private synchronized void select(final UUID playerId, final String message) throws MageException { + perform(playerId, new Command() { + public void execute() { + gameSessions.get(playerId).select(message); + } + }); + } + + private synchronized void playMana(final UUID playerId, final String message) throws MageException { + perform(playerId, new Command() { + public void execute() { + gameSessions.get(playerId).playMana(message); + } + }); + } + + private synchronized void playXMana(final UUID playerId, final String message) throws MageException { + perform(playerId, new Command() { + public void execute() { + gameSessions.get(playerId).playXMana(message); + } + }); + } + + private synchronized void amount(final UUID playerId, final String message, final int min, final int max) throws MageException { + perform(playerId, new Command() { + public void execute() { + gameSessions.get(playerId).getAmount(message, min, max); + } + }); } private synchronized void revealCards(String name, Cards cards) throws MageException { @@ -421,9 +440,12 @@ public class GameController implements GameCallback { } } - private synchronized void lookAtCards(UUID playerId, String name, Cards cards) throws MageException { - if (gameSessions.containsKey(playerId)) - gameSessions.get(playerId).revealCards(name, new CardsView(cards.getCards(game))); + private synchronized void lookAtCards(final UUID playerId, final String name, final Cards cards) throws MageException { + perform(playerId, new Command() { + public void execute() { + gameSessions.get(playerId).revealCards(name, new CardsView(cards.getCards(game))); + } + }, false); } private void informOthers(UUID playerId) throws MageException { @@ -438,6 +460,24 @@ public class GameController implements GameCallback { } } + private void informOthers(List players) throws MageException { + // first player is always original controller + final String message = "Waiting for " + game.getPlayer(players.get(0)).getName(); + for (final Entry entry: gameSessions.entrySet()) { + boolean skip = false; + for (UUID uuid : players) { + if (entry.getKey().equals(uuid)) { + skip = true; + break; + } + } + if (!skip) entry.getValue().inform(message); + } + for (final GameWatcher watcher: watchers.values()) { + watcher.inform(message); + } + } + private void error(String message) { for (final Entry entry: gameSessions.entrySet()) { entry.getValue().gameError(message); @@ -576,4 +616,27 @@ public class GameController implements GameCallback { } return null; } + + private void perform(UUID playerId, Command command) throws MageException { + perform(playerId, command, true); + } + + private void perform(UUID playerId, Command command, boolean informOthers) throws MageException { + if (game.getPlayer(playerId).isGameUnderControl()) { + if (gameSessions.containsKey(playerId)) + command.execute(); + if (informOthers) informOthers(playerId); + } else { + List players = Splitter.split(game, playerId); + for (UUID uuid : players) { + if (gameSessions.containsKey(uuid)) + command.execute(); + } + if (informOthers) informOthers(players); + } + } + + interface Command { + public void execute(); + } } diff --git a/Mage.Server/src/main/java/mage/server/util/Splitter.java b/Mage.Server/src/main/java/mage/server/util/Splitter.java new file mode 100644 index 0000000000..168017b6bb --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/util/Splitter.java @@ -0,0 +1,24 @@ +package mage.server.util; + +import mage.game.Game; +import mage.players.Player; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * @author nantuko + */ +public class Splitter { + + public static List split(Game game, UUID playerId) { + List players = new ArrayList(); + players.add(playerId); // add original player + Player player = game.getPlayer(playerId); + if (player != null && player.getTurnControlledBy() != null) { + players.add(player.getTurnControlledBy()); + } + return players; + } +} diff --git a/Mage/src/mage/players/Player.java b/Mage/src/mage/players/Player.java index 40a713cb45..fafb702104 100644 --- a/Mage/src/mage/players/Player.java +++ b/Mage/src/mage/players/Player.java @@ -111,24 +111,33 @@ public interface Player extends MageItem, Copyable { public Set getPlayersUnderYourControl(); /** - * Defines player whose turn you control at the moment. + * Defines player whose turn this player controls at the moment. * @param playerId */ public void controlPlayersTurn(Game game, UUID playerId); + /** + * Sets player {@link UUID} who controls this player's turn. + * + * @param playerId + */ + public void setTurnControlledBy(UUID playerId); + + public UUID getTurnControlledBy(); + /** * Resets players whose turns you control at the moment. */ public void resetOtherTurnsControlled(); /** - * Returns false in case you don't control the game. + * Returns false in case player don't control the game. * * Note: For effects like "You control target player during that player's next turn". * * @return */ - public boolean isGameUnderYourControl(); + public boolean isGameUnderControl(); /** * Returns false in case you don't control the game. diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index 27d2ee3707..da76ff413a 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -95,6 +95,7 @@ public abstract class PlayerImpl> implements Player, Ser protected boolean isTestMode = false; protected boolean lifeTotalCanChange = true; protected boolean isGameUnderYourControl = true; + protected UUID turnController; protected Set playersUnderYourControl = new HashSet(); @Override @@ -237,11 +238,12 @@ public abstract class PlayerImpl> implements Player, Ser @Override public void controlPlayersTurn(Game game, UUID playerId) { - if (!playerId.equals(getId())) { + if (!playerId.equals(this.getId())) { this.playersUnderYourControl.add(playerId); Player player = game.getPlayer(playerId); if (!player.hasLeft() && !player.hasLost()) { player.setGameUnderYourControl(false); + player.setTurnControlledBy(this.getId()); } DelayedTriggeredAbility ability = new AtTheEndOfTurnDelayedTriggeredAbility(new LoseControlOnOtherPlayersControllerEffect()); ability.setSourceId(getId()); @@ -250,13 +252,21 @@ public abstract class PlayerImpl> implements Player, Ser } } + public void setTurnControlledBy(UUID playerId) { + this.turnController = playerId; + } + + public UUID getTurnControlledBy() { + return this.turnController; + } + @Override public void resetOtherTurnsControlled() { playersUnderYourControl.clear(); } @Override - public boolean isGameUnderYourControl() { + public boolean isGameUnderControl() { return isGameUnderYourControl; }