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 1eb22a8bec0..bdee67a73fe 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameController.java +++ b/Mage.Server/src/main/java/mage/server/game/GameController.java @@ -53,6 +53,7 @@ import mage.game.GameException; import mage.game.GameOptions; import mage.game.GameState; import mage.game.Table; +import mage.game.command.Plane; import mage.game.events.Listener; import mage.game.events.PlayerQueryEvent; import mage.game.events.TableEvent; @@ -1174,6 +1175,15 @@ public class GameController implements GameCallback { sb.append(state.getTurnMods()); sb.append("
getTurnNum: "); sb.append(state.getTurnNum()); + + sb.append("
Using plane chase?:" + state.isPlaneChase()); + if (state.isPlaneChase()) { + Plane currentPlane = state.getCurrentPlane(); + if (currentPlane != null) { + sb.append("
Current plane:" + currentPlane.getName()); + } + } + sb.append("
Future Timeout:"); if (futureTimeout != null) { sb.append("Cancelled?="); @@ -1244,7 +1254,7 @@ public class GameController implements GameCallback { } sb.append(game.getPlayer(state.getPriorityPlayerId()).getName()); sb.append(""); - } + } sb.append("
Future Timeout:"); if (futureTimeout != null) { diff --git a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java index 9e459aefe32..1f2adf2d198 100644 --- a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java +++ b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java @@ -42,6 +42,7 @@ public final class SystemUtil { private static final String COMMAND_SHOW_OPPONENT_HAND = "@show opponent hand"; private static final String COMMAND_SHOW_OPPONENT_LIBRARY = "@show opponent library"; private static final Map supportedCommands = new HashMap<>(); + static { supportedCommands.put(COMMAND_MANA_ADD, "MANA ADD"); supportedCommands.put(COMMAND_LANDS_ADD, "LANDS ADD"); @@ -61,31 +62,32 @@ public final class SystemUtil { private static final String PARAM_ABILITIES_COUNT = "abilities count"; private static final String PARAM_ABILITIES_LIST = "abilities list"; - private static class CommandGroup{ + private static class CommandGroup { + String name; boolean isSpecialCommand; ArrayList commands = new ArrayList<>(); - public CommandGroup(String name){ + public CommandGroup(String name) { this(name, false); } - public CommandGroup(String name, boolean isSpecialCommand){ + public CommandGroup(String name, boolean isSpecialCommand) { this.name = name; this.isSpecialCommand = isSpecialCommand; } - public String getPrintName(){ - if(this.isSpecialCommand && supportedCommands.containsKey(this.name)){ + public String getPrintName() { + if (this.isSpecialCommand && supportedCommands.containsKey(this.name)) { return supportedCommands.get(this.name); } else { return this.name; } } - public String getPrintNameWithStats(){ + public String getPrintNameWithStats() { String res = this.getPrintName(); - if(!this.isSpecialCommand){ + if (!this.isSpecialCommand) { res = res + " (" + this.commands.size() + " commands)"; } @@ -144,6 +146,7 @@ public final class SystemUtil { } private static class CardCommandData { + public String source; public String zone; public String player; @@ -214,7 +217,7 @@ public final class SystemUtil { *
* Implementation note:
* 1. Read init.txt line by line
- * 2. Parse line using for searching groups like: [group 1] + * 2. Parse line using for searching groups like: [group 1] * 3. Parse line using the following format: line ::= * :::
* 4. If zone equals to 'hand', add card to player's library
@@ -230,7 +233,7 @@ public final class SystemUtil { try { String fileName = fileSource; - if(fileName == null){ + if (fileName == null) { fileName = INIT_FILE_PATH; } @@ -247,7 +250,6 @@ public final class SystemUtil { // 2. ask user if many groups // 3. process system commands // 4. run commands from selected group - // 1. parse ArrayList groups = new ArrayList<>(); @@ -267,12 +269,12 @@ public final class SystemUtil { Matcher matchGroup = patternGroup.matcher(line); if (matchGroup.matches()) { String groupName = matchGroup.group(1); - if(groupName.startsWith("@")){ + if (groupName.startsWith("@")) { // special command group - if(supportedCommands.containsKey(groupName)){ + if (supportedCommands.containsKey(groupName)) { currentGroup = new CommandGroup(groupName, true); groups.add(currentGroup); - }else { + } else { logger.warn("Special group [" + groupName + "] is not supported."); } continue; @@ -295,18 +297,18 @@ public final class SystemUtil { // 2. ask user CommandGroup runGroup = null; - if(groups.size() == 1) { + if (groups.size() == 1) { // not need to ask runGroup = groups.get(0); - }else if(groups.size() > 1) { + } else if (groups.size() > 1) { // need to ask - logger.info("Founded " + groups.size() + " groups. Need to select."); + logger.info("Found " + groups.size() + " groups. Need to select."); - if(feedbackPlayer != null){ + if (feedbackPlayer != null) { // choice dialog Map list = new LinkedHashMap<>(); Map sort = new LinkedHashMap<>(); - for(Integer i = 0; i < groups.size(); i++){ + for (Integer i = 0; i < groups.size(); i++) { list.put(Integer.toString(i + 1), groups.get(i).getPrintNameWithStats()); sort.put(Integer.toString(i + 1), i); } @@ -318,19 +320,18 @@ public final class SystemUtil { if (feedbackPlayer.choose(Outcome.Benefit, groupChoice, game)) { String need = groupChoice.getChoiceKey(); - if ((need != null) && list.containsKey(need)) - { + if ((need != null) && list.containsKey(need)) { runGroup = groups.get(Integer.parseInt(need) - 1); } } - }else{ + } else { // select default runGroup = groups.get(0); } } - if(runGroup == null) { + if (runGroup == null) { // was canceled logger.info("Command file was empty or canceled"); return; @@ -364,7 +365,7 @@ public final class SystemUtil { } // 4. run commands - for (String line: runGroup.commands) { + for (String line : runGroup.commands) { CardCommandData command = parseCardCommand(line); if (!command.OK) { @@ -399,6 +400,16 @@ public final class SystemUtil { game.addEmblem((mage.game.command.Emblem) emblem, null, player.getId()); continue; } + } else if ("plane".equalsIgnoreCase(command.zone)) { + // eg: plane:Human:BantPlane:1 + Class c = Class.forName("mage.game.command.planes." + command.cardName); + Constructor cons = c.getConstructor(); + Object plane = cons.newInstance(); + if (plane != null && plane instanceof mage.game.command.Plane) { + ((mage.game.command.Plane) plane).setControllerId(player.getId()); + game.addPlane((mage.game.command.Plane) plane, null, player.getId()); + continue; + } } Zone gameZone; @@ -414,6 +425,8 @@ public final class SystemUtil { gameZone = Zone.BATTLEFIELD; } else if ("emblem".equalsIgnoreCase(command.zone)) { gameZone = Zone.COMMAND; + } else if ("plane".equalsIgnoreCase(command.zone)) { + gameZone = Zone.COMMAND; } else { logger.warn("Unknown zone [" + command.zone + "]: " + line); continue; diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index c59cf8dbd3e..b928fc7195d 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -36,7 +36,6 @@ import mage.MageObject; import mage.abilities.*; import mage.abilities.common.AttachableToRestrictedAbility; import mage.abilities.common.CantHaveMoreThanAmountCountersSourceAbility; -import mage.abilities.common.SagaAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffects; import mage.abilities.effects.Effect; @@ -1079,6 +1078,7 @@ public abstract class GameImpl implements Game, Serializable { Plane plane = Plane.getRandomPlane(); plane.setControllerId(getActivePlayerId()); addPlane(plane, null, getActivePlayerId()); + state.setPlaneChase(this, gameOptions.planeChase); } } @@ -1564,6 +1564,14 @@ public abstract class GameImpl implements Game, Serializable { } state.addCommandObject(newPlane); informPlayers("You have planeswalked to " + newPlane.getLogName()); + + // Fire off the planeswalked event + GameEvent event = new GameEvent(GameEvent.EventType.PLANESWALK, newPlane.getId(), null, newPlane.getId(), 0, true); + if (!replaceEvent(event)) { + GameEvent ge = new GameEvent(GameEvent.EventType.PLANESWALKED, newPlane.getId(), null, newPlane.getId(), 0, true); + fireEvent(ge); + } + return true; } @@ -1915,7 +1923,7 @@ public abstract class GameImpl implements Game, Serializable { if (perm.isWorld()) { worldEnchantment.add(perm); } - if (perm.hasSubtype(SubType.AURA, this)) { + if (StaticFilters.FILTER_PERMANENT_AURA.match(perm, this)) { //20091005 - 704.5n, 702.14c if (perm.getAttachedTo() == null) { Card card = this.getCard(perm.getId()); @@ -2005,30 +2013,6 @@ public abstract class GameImpl implements Game, Serializable { } } } - // Remove Saga enchantment if last chapter is reached and chapter ability has left the stack - if (perm.hasSubtype(SubType.SAGA, this)) { - for (Ability sagaAbility : perm.getAbilities()) { - if (sagaAbility instanceof SagaAbility) { - int maxChapter = ((SagaAbility) sagaAbility).getMaxChapter().getNumber(); - if (maxChapter <= perm.getCounters(this).getCount(CounterType.LORE)) { - boolean noChapterAbilityOnStack = true; - // Check chapter abilities on stack - for (StackObject stackObject : getStack()) { - if (stackObject.getSourceId().equals(perm.getId()) && SagaAbility.isChapterAbility(stackObject)) { - noChapterAbilityOnStack = false; - break; - } - } - if (noChapterAbilityOnStack) { - // After the last chapter ability has left the stack, you'll sacrifice the Saga - perm.sacrifice(perm.getId(), this); - somethingHappened = true; - } - } - - } - } - } if (this.getState().isLegendaryRuleActive() && StaticFilters.FILTER_PERMANENT_LEGENDARY.match(perm, this)) { legendary.add(perm); } diff --git a/Mage/src/main/java/mage/game/events/GameEvent.java b/Mage/src/main/java/mage/game/events/GameEvent.java index 5a928d165e1..cee8547a817 100644 --- a/Mage/src/main/java/mage/game/events/GameEvent.java +++ b/Mage/src/main/java/mage/game/events/GameEvent.java @@ -232,6 +232,7 @@ public class GameEvent implements Serializable { FLIP_COIN, COIN_FLIPPED, SCRY, FATESEAL, ROLL_DICE, DICE_ROLLED, ROLL_PLANAR_DIE, PLANAR_DIE_ROLLED, + PLANESWALK, PLANESWALKED, PAID_CUMULATIVE_UPKEEP, DIDNT_PAY_CUMULATIVE_UPKEEP, //permanent events