From 0ea73b19df2ea30a00d679a5aee5008141afac0d Mon Sep 17 00:00:00 2001 From: John Hitchings Date: Sun, 17 Mar 2019 14:28:14 -0700 Subject: [PATCH 01/28] Refactor Sets.saveDeck into a deck exporter series of classes. --- .../deck/generator/DeckGeneratorDialog.java | 5 +- .../client/deckeditor/DeckEditorPanel.java | 8 +- Mage/src/main/java/mage/cards/Sets.java | 74 --------------- .../java/mage/cards/decks/DeckFormats.java | 90 +++++++++++++++++++ .../cards/decks/exporter/DckExporter.java | 82 +++++++++++++++++ .../cards/decks/exporter/DeckExporter.java | 24 +++++ .../cards/decks/exporter/MtgoExporter.java | 43 +++++++++ .../cards/decks/exporter/DckExporterTest.java | 32 +++++++ .../decks/exporter/MtgoExporterTest.java | 32 +++++++ 9 files changed, 310 insertions(+), 80 deletions(-) create mode 100644 Mage/src/main/java/mage/cards/decks/DeckFormats.java create mode 100644 Mage/src/main/java/mage/cards/decks/exporter/DckExporter.java create mode 100644 Mage/src/main/java/mage/cards/decks/exporter/DeckExporter.java create mode 100644 Mage/src/main/java/mage/cards/decks/exporter/MtgoExporter.java create mode 100644 Mage/src/test/java/mage/cards/decks/exporter/DckExporterTest.java create mode 100644 Mage/src/test/java/mage/cards/decks/exporter/MtgoExporterTest.java diff --git a/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorDialog.java b/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorDialog.java index a16607fa29c..1665bc23098 100644 --- a/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorDialog.java +++ b/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorDialog.java @@ -11,7 +11,6 @@ import javax.swing.*; import javax.swing.border.CompoundBorder; import javax.swing.border.EmptyBorder; import javax.swing.border.EtchedBorder; -import mage.cards.Sets; import mage.cards.decks.Deck; import mage.client.MageFrame; import mage.client.dialog.PreferencesDialog; @@ -19,6 +18,8 @@ import mage.client.util.gui.ColorsChooser; import mage.client.util.gui.FastSearchUtil; import mage.client.util.sets.ConstructedFormats; +import static mage.cards.decks.DeckFormats.DCK; + /** * * @author Simown @@ -328,7 +329,7 @@ public class DeckGeneratorDialog { tmp.getParentFile().mkdirs(); tmp.createNewFile(); deck.setName(deckName); - Sets.saveDeck(tmp.getAbsolutePath(), deck.getDeckCardLists()); + DCK.getExporter().writeDeck(tmp.getAbsolutePath(), deck.getDeckCardLists()); cleanUp(); return tmp.getAbsolutePath(); } catch (Exception e) { 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 d0c6d7c6dfa..48175a54cb8 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java @@ -1,7 +1,6 @@ package mage.client.deckeditor; import mage.cards.Card; -import mage.cards.Sets; import mage.cards.decks.Deck; import mage.cards.decks.DeckCardLists; import mage.cards.decks.DnDDeckTargetListener; @@ -35,12 +34,13 @@ import java.awt.*; import java.awt.dnd.DropTarget; import java.awt.event.*; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.util.List; import java.util.*; import java.util.concurrent.*; +import static mage.cards.decks.DeckFormats.DCK; + /** * @author BetaSteward_at_googlemail.com */ @@ -965,8 +965,8 @@ public class DeckEditorPanel extends javax.swing.JPanel { DeckCardLists cardLists = deck.getDeckCardLists(); cardLists.setCardLayout(deckArea.getCardLayout()); cardLists.setSideboardLayout(deckArea.getSideboardLayout()); - Sets.saveDeck(fileName, cardLists); - } catch (FileNotFoundException ex) { + DCK.getExporter().writeDeck(fileName, cardLists); + } catch (IOException ex) { JOptionPane.showMessageDialog(MageFrame.getDesktop(), ex.getMessage() + "\nTry ensuring that the selected directory is writable.", "Error saving deck", JOptionPane.ERROR_MESSAGE); } finally { MageFrame.getDesktop().setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); diff --git a/Mage/src/main/java/mage/cards/Sets.java b/Mage/src/main/java/mage/cards/Sets.java index 741acfd59c2..1c3bde2f14f 100644 --- a/Mage/src/main/java/mage/cards/Sets.java +++ b/Mage/src/main/java/mage/cards/Sets.java @@ -1,9 +1,6 @@ package mage.cards; import mage.Mana; -import mage.cards.decks.DeckCardInfo; -import mage.cards.decks.DeckCardLayout; -import mage.cards.decks.DeckCardLists; import mage.cards.repository.CardCriteria; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; @@ -16,8 +13,6 @@ import mage.util.RandomUtil; import org.apache.log4j.Logger; import org.junit.Assert; -import java.io.FileNotFoundException; -import java.io.PrintWriter; import java.util.*; /** @@ -205,73 +200,4 @@ public class Sets extends HashMap { return null; } - public static void saveDeck(String file, DeckCardLists deck) throws FileNotFoundException { - Map deckCards = new HashMap<>(); - Map sideboard = new HashMap<>(); - try (PrintWriter out = new PrintWriter(file)) { - if (deck.getName() != null && !deck.getName().isEmpty()) { - out.println("NAME:" + deck.getName()); - } - if (deck.getAuthor() != null && !deck.getAuthor().isEmpty()) { - out.println("AUTHOR:" + deck.getAuthor()); - } - for (DeckCardInfo deckCardInfo : deck.getCards()) { - if (deckCards.containsKey(deckCardInfo.getCardKey())) { - deckCards.put(deckCardInfo.getCardKey(), deckCards.get(deckCardInfo.getCardKey()).increaseQuantity()); - } else { - deckCards.put(deckCardInfo.getCardKey(), deckCardInfo); - } - } - - for (DeckCardInfo deckCardInfo : deck.getSideboard()) { - if (sideboard.containsKey(deckCardInfo.getCardKey())) { - sideboard.put(deckCardInfo.getCardKey(), sideboard.get(deckCardInfo.getCardKey()).increaseQuantity()); - } else { - sideboard.put(deckCardInfo.getCardKey(), deckCardInfo); - } - } - - // Write out all of the cards - for (Entry entry : deckCards.entrySet()) { - out.printf("%d [%s:%s] %s%n", entry.getValue().getQuantity(), entry.getValue().getSetCode(), entry.getValue().getCardNum(), entry.getValue().getCardName()); - } - for (Entry entry : sideboard.entrySet()) { - out.printf("SB: %d [%s:%s] %s%n", entry.getValue().getQuantity(), entry.getValue().getSetCode(), entry.getValue().getCardNum(), entry.getValue().getCardName()); - } - - // Write out the layout - out.print("LAYOUT MAIN:"); - writeCardLayout(out, deck.getCardLayout()); - out.print("\n"); - out.print("LAYOUT SIDEBOARD:"); - writeCardLayout(out, deck.getSideboardLayout()); - out.print("\n"); - } - } - - private static void writeCardLayout(PrintWriter out, DeckCardLayout layout) { - if (layout == null) { - return; - } - List>> cardGrid = layout.getCards(); - int height = cardGrid.size(); - int width = (height > 0) ? cardGrid.get(0).size() : 0; - out.print("(" + height + ',' + width + ')'); - out.print(layout.getSettings()); - out.print("|"); - for (List> row : cardGrid) { - for (List stack : row) { - out.print("("); - for (int i = 0; i < stack.size(); ++i) { - DeckCardInfo info = stack.get(i); - out.printf("[%s:%s]", info.getSetCode(), info.getCardNum()); - if (i != stack.size() - 1) { - out.print(","); - } - } - out.print(")"); - } - } - } - } diff --git a/Mage/src/main/java/mage/cards/decks/DeckFormats.java b/Mage/src/main/java/mage/cards/decks/DeckFormats.java new file mode 100644 index 00000000000..272baf4956d --- /dev/null +++ b/Mage/src/main/java/mage/cards/decks/DeckFormats.java @@ -0,0 +1,90 @@ +package mage.cards.decks; + +import mage.cards.decks.exporter.DckExporter; +import mage.cards.decks.exporter.DeckExporter; +import mage.cards.decks.exporter.MtgoExporter; + +import java.io.*; +import java.util.Optional; + +public enum DeckFormats { + + DCK(new DckExporter()), + MTGO(new MtgoExporter()); + + private final DeckExporter exporter; + + DeckFormats(DeckExporter exporter) { + this.exporter = exporter; + } + + public DeckExporter getExporter() { + return exporter; + } + + public static Optional getFormatForExtension(String filename) { + return getExtension(filename).map(c -> { + try { + return DeckFormats.valueOf(c); + } catch (IllegalArgumentException e) { + return null; + } + }); + } + + public static Optional getExtension(String filename) { + int i = filename.lastIndexOf('.'); + if (i > 0) { + return Optional.of(filename.substring(i+1).toUpperCase()); + } else { + return Optional.empty(); + } + } + + public static void writeDeck(String file, DeckCardLists deck) throws IOException { + writeDeck(new File(file), deck); + } + + public static void writeDeck(String file, DeckCardLists deck, DeckFormats format) throws IOException { + writeDeck(new File(file), deck, format); + } + + public static void writeDeck(String file, DeckCardLists deck, DeckExporter exporter) throws IOException { + writeDeck(new File(file), deck, exporter); + } + + public static void writeDeck(File file, DeckCardLists deck) throws IOException { + DeckFormats format = DeckFormats.getFormatForExtension(file.getName()).orElseGet(() -> { + throw new IllegalArgumentException("Could not determine deck export format."); + }); + writeDeck(file, deck, format); + } + + public static void writeDeck(File file, DeckCardLists deck, DeckFormats format) throws IOException { + writeDeck(file, deck, format.getExporter()); + } + + public static void writeDeck(File file, DeckCardLists deck, DeckExporter exporter) throws IOException { + try (FileOutputStream out = new FileOutputStream(file)){ + writeDeck(out, deck, exporter); + } + } + + public static void writeDeck(OutputStream out, DeckCardLists deck, DeckFormats format) { + writeDeck(new PrintWriter(out), deck, format); + } + + public static void writeDeck(OutputStream out, DeckCardLists deck, DeckExporter exporter) { + writeDeck(new PrintWriter(out), deck, exporter); + } + + public static void writeDeck(PrintWriter out, DeckCardLists deck, DeckFormats format) { + writeDeck(out, deck, format.getExporter()); + } + + public static void writeDeck(PrintWriter out, DeckCardLists deck, DeckExporter exporter) { + exporter.writeDeck(out, deck); + out.flush(); + } + +} diff --git a/Mage/src/main/java/mage/cards/decks/exporter/DckExporter.java b/Mage/src/main/java/mage/cards/decks/exporter/DckExporter.java new file mode 100644 index 00000000000..3d673e7eb82 --- /dev/null +++ b/Mage/src/main/java/mage/cards/decks/exporter/DckExporter.java @@ -0,0 +1,82 @@ +package mage.cards.decks.exporter; + +import mage.cards.decks.DeckCardInfo; +import mage.cards.decks.DeckCardLayout; +import mage.cards.decks.DeckCardLists; + +import java.io.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class DckExporter extends DeckExporter { + + public void writeDeck(PrintWriter out, DeckCardLists deck) { + Map deckCards = new HashMap<>(); + Map sideboard = new HashMap<>(); + + if (deck.getName() != null && !deck.getName().isEmpty()) { + out.println("NAME:" + deck.getName()); + } + if (deck.getAuthor() != null && !deck.getAuthor().isEmpty()) { + out.println("AUTHOR:" + deck.getAuthor()); + } + for (DeckCardInfo deckCardInfo : deck.getCards()) { + if (deckCards.containsKey(deckCardInfo.getCardKey())) { + deckCards.put(deckCardInfo.getCardKey(), deckCards.get(deckCardInfo.getCardKey()).increaseQuantity()); + } else { + deckCards.put(deckCardInfo.getCardKey(), deckCardInfo); + } + } + + for (DeckCardInfo deckCardInfo : deck.getSideboard()) { + if (sideboard.containsKey(deckCardInfo.getCardKey())) { + sideboard.put(deckCardInfo.getCardKey(), sideboard.get(deckCardInfo.getCardKey()).increaseQuantity()); + } else { + sideboard.put(deckCardInfo.getCardKey(), deckCardInfo); + } + } + + // Write out all of the cards + for (Map.Entry entry : deckCards.entrySet()) { + out.printf("%d [%s:%s] %s%n", entry.getValue().getQuantity(), entry.getValue().getSetCode(), entry.getValue().getCardNum(), entry.getValue().getCardName()); + } + for (Map.Entry entry : sideboard.entrySet()) { + out.printf("SB: %d [%s:%s] %s%n", entry.getValue().getQuantity(), entry.getValue().getSetCode(), entry.getValue().getCardNum(), entry.getValue().getCardName()); + } + + // Write out the layout + out.print("LAYOUT MAIN:"); + writeCardLayout(out, deck.getCardLayout()); + out.print("\n"); + out.print("LAYOUT SIDEBOARD:"); + writeCardLayout(out, deck.getSideboardLayout()); + out.print("\n"); + } + + private static void writeCardLayout(PrintWriter out, DeckCardLayout layout) { + if (layout == null) { + return; + } + List>> cardGrid = layout.getCards(); + int height = cardGrid.size(); + int width = (height > 0) ? cardGrid.get(0).size() : 0; + out.print("(" + height + ',' + width + ')'); + out.print(layout.getSettings()); + out.print("|"); + for (List> row : cardGrid) { + for (List stack : row) { + out.print("("); + for (int i = 0; i < stack.size(); ++i) { + DeckCardInfo info = stack.get(i); + out.printf("[%s:%s]", info.getSetCode(), info.getCardNum()); + if (i != stack.size() - 1) { + out.print(","); + } + } + out.print(")"); + } + } + } + +} diff --git a/Mage/src/main/java/mage/cards/decks/exporter/DeckExporter.java b/Mage/src/main/java/mage/cards/decks/exporter/DeckExporter.java new file mode 100644 index 00000000000..57960bef3ae --- /dev/null +++ b/Mage/src/main/java/mage/cards/decks/exporter/DeckExporter.java @@ -0,0 +1,24 @@ +package mage.cards.decks.exporter; + +import mage.cards.decks.DeckCardLists; +import mage.cards.decks.DeckFormats; + +import java.io.*; + +public abstract class DeckExporter { + + public void writeDeck(String file, DeckCardLists deck) throws IOException { + DeckFormats.writeDeck(file, deck, this); + } + + public void writeDeck(File file, DeckCardLists deck) throws IOException { + DeckFormats.writeDeck(file, deck, this); + } + + public void writeDeck(OutputStream out, DeckCardLists deck) { + DeckFormats.writeDeck(out, deck, this); + } + + public abstract void writeDeck(PrintWriter out, DeckCardLists deck); + +} diff --git a/Mage/src/main/java/mage/cards/decks/exporter/MtgoExporter.java b/Mage/src/main/java/mage/cards/decks/exporter/MtgoExporter.java new file mode 100644 index 00000000000..41d3e39139b --- /dev/null +++ b/Mage/src/main/java/mage/cards/decks/exporter/MtgoExporter.java @@ -0,0 +1,43 @@ +package mage.cards.decks.exporter; + +import mage.cards.decks.DeckCardInfo; +import mage.cards.decks.DeckCardLists; + +import java.io.PrintWriter; +import java.util.List; +import java.util.TreeMap; + +public class MtgoExporter extends DeckExporter { + + @Override + public void writeDeck(PrintWriter out, DeckCardLists deck) { + TreeMap deckCards = toCardMap(deck.getCards()); + TreeMap sideboard = toCardMap(deck.getSideboard()); + deckCards.forEach((name, count) -> { + out.print(count); + out.print(' '); + out.println(name); + }); + + out.println(); + out.println(); + + sideboard.forEach((name, count) -> { + out.print(count); + out.print(' '); + out.println(name); + }); + + out.println(); + } + + private TreeMap toCardMap(List cards) { + TreeMap counts = new TreeMap<>(); + for (DeckCardInfo card : cards) { + int count = counts.getOrDefault(card.getCardName(), 0) + card.getQuantity(); + counts.put(card.getCardName(), count); + } + return counts; + } + +} diff --git a/Mage/src/test/java/mage/cards/decks/exporter/DckExporterTest.java b/Mage/src/test/java/mage/cards/decks/exporter/DckExporterTest.java new file mode 100644 index 00000000000..d1b843dbecb --- /dev/null +++ b/Mage/src/test/java/mage/cards/decks/exporter/DckExporterTest.java @@ -0,0 +1,32 @@ +package mage.cards.decks.exporter; + +import mage.cards.decks.DeckCardInfo; +import mage.cards.decks.DeckCardLists; +import org.junit.Test; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import static org.junit.Assert.assertEquals; + +public class DckExporterTest { + + @Test + public void writeDeck() throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DeckCardLists deck = new DeckCardLists(); + deck.getCards().add(new DeckCardInfo("Forest", "RNA", "1", 2)); + deck.getCards().add(new DeckCardInfo("Plains", "RNA", "2", 3)); + deck.getSideboard().add(new DeckCardInfo("Island", "RNA", "3", 2)); + DckExporter exporter = new DckExporter(); + exporter.writeDeck(baos, deck); + assertEquals( + "2 [1:RNA] Forest\n" + + "3 [2:RNA] Plains\n" + + "SB: 2 [3:RNA] Island\n" + + "LAYOUT MAIN:\n" + + "LAYOUT SIDEBOARD:\n", + new String(baos.toByteArray())); + } + +} \ No newline at end of file diff --git a/Mage/src/test/java/mage/cards/decks/exporter/MtgoExporterTest.java b/Mage/src/test/java/mage/cards/decks/exporter/MtgoExporterTest.java new file mode 100644 index 00000000000..de3681c0bd9 --- /dev/null +++ b/Mage/src/test/java/mage/cards/decks/exporter/MtgoExporterTest.java @@ -0,0 +1,32 @@ +package mage.cards.decks.exporter; + +import mage.cards.decks.DeckCardInfo; +import mage.cards.decks.DeckCardLists; +import org.junit.Test; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import static org.junit.Assert.assertEquals; + +public class MtgoExporterTest { + + @Test + public void writeDeck() throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DeckCardLists deck = new DeckCardLists(); + deck.getCards().add(new DeckCardInfo("Forest", "RNA", "1", 2)); + deck.getCards().add(new DeckCardInfo("Plains", "RNA", "2", 3)); + deck.getSideboard().add(new DeckCardInfo("Island", "RNA", "3", 2)); + MtgoExporter exporter = new MtgoExporter(); + exporter.writeDeck(baos, deck); + assertEquals( + "2 Forest\n" + + "3 Plains\n" + + "\n" + + "\n" + + "2 Island\n" + + "\n", new String(baos.toByteArray())); + } + +} \ No newline at end of file From ae00a74b4c2238488987ab63fcbb2aa2ad7a3822 Mon Sep 17 00:00:00 2001 From: Jeff Date: Sun, 17 Mar 2019 17:34:13 -0500 Subject: [PATCH 02/28] - refactored Krovikan Vampire. --- .../src/mage/cards/k/KrovikanVampire.java | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/Mage.Sets/src/mage/cards/k/KrovikanVampire.java b/Mage.Sets/src/mage/cards/k/KrovikanVampire.java index 22e57a47fe6..47197080a50 100644 --- a/Mage.Sets/src/mage/cards/k/KrovikanVampire.java +++ b/Mage.Sets/src/mage/cards/k/KrovikanVampire.java @@ -47,7 +47,7 @@ public final class KrovikanVampire extends CardImpl { Zone.BATTLEFIELD, new KrovikanVampireEffect(), TargetController.ANY, - KrovikanVampireInterveningIfCondition.instance, + new KrovikanVampireInterveningIfCondition(), false); ability.addWatcher(new KrovikanVampireCreaturesDamagedWatcher()); ability.addWatcher(new KrovikanVampireCreaturesDiedWatcher()); @@ -85,14 +85,17 @@ class KrovikanVampireEffect extends OneShotEffect { if (creaturesAffected != null && controller != null && krovikanVampire != null) { - for (UUID creatureId : creaturesAffected) { + creaturesAffected.stream().map((creatureId) -> { controller.moveCards(game.getCard(creatureId), Zone.BATTLEFIELD, source, game, false, false, false, null); + return creatureId; + }).map((creatureId) -> { OneShotEffect effect = new SacrificeTargetEffect(); effect.setText("Sacrifice this if Krovikan Vampire leaves the battlefield or its current controller loses control of it."); effect.setTargetPointer(new FixedTarget(creatureId)); - KrovikanVampireDelayedTriggeredAbility dTA = new KrovikanVampireDelayedTriggeredAbility(effect, krovikanVampire.getId()); + return effect; + }).map((effect) -> new KrovikanVampireDelayedTriggeredAbility(effect, krovikanVampire.getId())).forEachOrdered((dTA) -> { game.addDelayedTriggeredAbility(dTA, source); - } + }); creaturesAffected.clear(); return true; } @@ -105,9 +108,8 @@ class KrovikanVampireEffect extends OneShotEffect { } } -enum KrovikanVampireInterveningIfCondition implements Condition { +class KrovikanVampireInterveningIfCondition implements Condition { - instance; Set creaturesAffected = new HashSet<>(); @Override @@ -116,16 +118,12 @@ enum KrovikanVampireInterveningIfCondition implements Condition { KrovikanVampireCreaturesDamagedWatcher watcherDamaged = game.getState().getWatcher(KrovikanVampireCreaturesDamagedWatcher.class); if (watcherDied != null) { Set creaturesThatDiedThisTurn = watcherDied.getDiedThisTurn(); - for (UUID mor : creaturesThatDiedThisTurn) { - if (watcherDamaged != null) { - for (UUID mor2 : watcherDamaged.getDamagedBySource()) { - if (mor2 != null - && mor == mor2) { - creaturesAffected.add(mor); - } - } - } - } + creaturesThatDiedThisTurn.stream().filter((mor) -> (watcherDamaged != null)).forEachOrdered((mor) -> { + watcherDamaged.getDamagedBySource().stream().filter((mor2) -> (mor2 != null + && mor == mor2)).forEachOrdered((_item) -> { + creaturesAffected.add(mor); + }); + }); if (creaturesAffected != null && creaturesAffected.size() > 0) { game.getState().setValue(source.getSourceId() + "creatureToGainControl", creaturesAffected); From 410fd689961433f05cadb1a0b8052870ca6a8f5d Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Mon, 18 Mar 2019 06:10:08 +0400 Subject: [PATCH 03/28] Fixed that triggered abilities shows cancel button in target definition; --- Mage/src/main/java/mage/abilities/AbilityImpl.java | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java index 49b06d14483..e00b0049769 100644 --- a/Mage/src/main/java/mage/abilities/AbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java @@ -325,15 +325,9 @@ public abstract class AbilityImpl implements Ability { } if (!getTargets().isEmpty()) { Outcome outcome = getEffects().isEmpty() ? Outcome.Detriment : getEffects().get(0).getOutcome(); - // can be cancel by user - if (getTargets().chooseTargets(outcome, this.controllerId, this, noMana, game, true) == false) { - /* - if ((variableManaCost != null) || (announceString != null && !announceString.isEmpty())) { - // ?debug message? - game.informPlayer(controller, (sourceObject != null ? sourceObject.getIdName() : "") + ": no valid targets"); - } - */ - // when activation of ability is canceled during target selection + // only activated abilities can be canceled by user (not triggered) + if (!getTargets().chooseTargets(outcome, this.controllerId, this, noMana, game, this instanceof ActivatedAbility)) { + // was canceled during targer selection return false; } } From 2a0d2d125bf8d0cbebdcfdd6bcd24a8bc21fedb9 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Mon, 18 Mar 2019 09:00:27 +0400 Subject: [PATCH 04/28] * UI: fixed error message window for long text (auto-size), improved wrong version message; --- .../mage/client/dialog/UserRequestDialog.java | 63 +++++++++---------- .../mage/remote/MageVersionException.java | 8 ++- .../java/mage/view/UserRequestMessage.java | 15 +++-- 3 files changed, 40 insertions(+), 46 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/dialog/UserRequestDialog.java b/Mage.Client/src/main/java/mage/client/dialog/UserRequestDialog.java index c9c9394a83b..368e6b3422b 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/UserRequestDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/UserRequestDialog.java @@ -1,22 +1,15 @@ - - /* - * ErrorDialog.java - * - * Created on Dec 23, 2009, 11:01:32 AM - */ package mage.client.dialog; -import java.awt.Dimension; -import java.awt.Font; -import javax.swing.JComponent; -import javax.swing.plaf.basic.BasicInternalFrameUI; import mage.client.MageFrame; import mage.client.util.GUISizeHelper; import mage.constants.PlayerAction; import mage.view.UserRequestMessage; +import javax.swing.*; +import javax.swing.plaf.basic.BasicInternalFrameUI; +import java.awt.*; + /** - * * @author BetaSteward_at_googlemail.com */ public class UserRequestDialog extends MageDialog { @@ -34,7 +27,7 @@ public class UserRequestDialog extends MageDialog { private void setGUISize() { Font font = GUISizeHelper.gameRequestsFont; lblText.setFont(font); - lblText.setMaximumSize(new Dimension(300 + font.getSize() * 15, 20 + font.getSize() * 5)); + lblText.setMaximumSize(new Dimension(300 + font.getSize() * 15, 200 + font.getSize() * 5)); lblText.setMinimumSize(new Dimension(300 + font.getSize() * 15, 20 + font.getSize() * 5)); lblText.setPreferredSize(new Dimension(300 + font.getSize() * 15, 20 + font.getSize() * 5)); btn1.setFont(font); @@ -58,7 +51,7 @@ public class UserRequestDialog extends MageDialog { public void showDialog(UserRequestMessage userRequestMessage) { this.userRequestMessage = userRequestMessage; - this.setTitle(userRequestMessage.getTitel()); + this.setTitle(userRequestMessage.getTitle()); String text = "

" + userRequestMessage.getMessage() + "

"; this.lblText.setText(text); if (userRequestMessage.getButton1Text() != null) { @@ -128,30 +121,30 @@ public class UserRequestDialog extends MageDialog { javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(lblText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(layout.createSequentialGroup() - .addComponent(btn3, javax.swing.GroupLayout.PREFERRED_SIZE, 1, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btn2, javax.swing.GroupLayout.PREFERRED_SIZE, 1, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btn1, javax.swing.GroupLayout.PREFERRED_SIZE, 1, Short.MAX_VALUE))) - .addContainerGap()) + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(lblText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(btn3, javax.swing.GroupLayout.PREFERRED_SIZE, 1, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btn2, javax.swing.GroupLayout.PREFERRED_SIZE, 1, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btn1, javax.swing.GroupLayout.PREFERRED_SIZE, 1, Short.MAX_VALUE))) + .addContainerGap()) ); layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addComponent(lblText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(btn1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(btn2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(btn3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addGap(12, 12, 12)) + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(lblText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btn1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btn2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btn3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGap(12, 12, 12)) ); pack(); diff --git a/Mage.Common/src/main/java/mage/remote/MageVersionException.java b/Mage.Common/src/main/java/mage/remote/MageVersionException.java index b5f317be3e3..d67093874fc 100644 --- a/Mage.Common/src/main/java/mage/remote/MageVersionException.java +++ b/Mage.Common/src/main/java/mage/remote/MageVersionException.java @@ -1,11 +1,9 @@ - package mage.remote; import mage.MageException; import mage.utils.MageVersion; /** - * * @author BetaSteward_at_googlemail.com */ public class MageVersionException extends MageException { @@ -13,7 +11,11 @@ public class MageVersionException extends MageException { private final MageVersion serverVersion; public MageVersionException(MageVersion clientVersion, MageVersion serverVersion) { - super("Wrong client version " + clientVersion + ", expecting version " + serverVersion + ". \r\n\r\nPlease download needed version from http://XMage.de or http://www.slightlymagic.net/forum/viewforum.php?f=70"); + super("Wrong client version." + + "
Your version: " + clientVersion + + "
Server version: " + serverVersion + + "
Release app download: http://xmage.de" + + "
BETA app download: http://xmage.today"); this.serverVersion = serverVersion; } diff --git a/Mage.Common/src/main/java/mage/view/UserRequestMessage.java b/Mage.Common/src/main/java/mage/view/UserRequestMessage.java index 71c582b2293..51cb913d0e9 100644 --- a/Mage.Common/src/main/java/mage/view/UserRequestMessage.java +++ b/Mage.Common/src/main/java/mage/view/UserRequestMessage.java @@ -1,19 +1,18 @@ - package mage.view; +import mage.constants.PlayerAction; + import java.io.Serializable; import java.util.UUID; -import mage.constants.PlayerAction; /** - * * @author LevelX2 */ public class UserRequestMessage implements Serializable { private static final long serialVersionUID = 1L; - private final String titel; + private final String title; private final String message; private UUID relatedUserId; private String relatedUserName; @@ -32,8 +31,8 @@ public class UserRequestMessage implements Serializable { private String button3Text; private PlayerAction button3Action; - public UserRequestMessage(String titel, String message) { - this.titel = titel; + public UserRequestMessage(String title, String message) { + this.title = title; this.message = message; this.button1Action = null; this.button2Action = null; @@ -68,8 +67,8 @@ public class UserRequestMessage implements Serializable { this.button3Action = buttonAction; } - public String getTitel() { - return titel; + public String getTitle() { + return title; } public static long getSerialVersionUID() { From b638ef4fad3d9c058a1882439f01b7ddc8861f56 Mon Sep 17 00:00:00 2001 From: Ingmar Goudt Date: Mon, 18 Mar 2019 12:54:19 +0100 Subject: [PATCH 05/28] delete old performance debug code --- Mage/src/main/java/mage/game/GameImpl.java | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 25ec612248d..fcc14333b5a 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -114,9 +114,6 @@ public abstract class GameImpl implements Game, Serializable { protected GameOptions gameOptions; protected String startMessage; - public static volatile int copyCount = 0; - public static volatile long copyTime = 0; - // private final transient LinkedList actions; private Player scorePlayer; // private int score = 0; @@ -154,10 +151,6 @@ public abstract class GameImpl implements Game, Serializable { } public GameImpl(final GameImpl game) { - long t1 = 0; - if (logger.isDebugEnabled()) { - t1 = System.currentTimeMillis(); - } this.id = game.id; this.ready = game.ready; this.startingPlayerId = game.startingPlayerId; @@ -173,10 +166,7 @@ public abstract class GameImpl implements Game, Serializable { this.lkiExtended.putAll(game.lkiExtended); this.shortLivingLKI.putAll(game.shortLivingLKI); this.permanentsEntering.putAll(game.permanentsEntering); - if (logger.isDebugEnabled()) { - copyCount++; - copyTime += (System.currentTimeMillis() - t1); - } + this.stateCheckRequired = game.stateCheckRequired; this.scorePlayer = game.scorePlayer; this.scopeRelevant = game.scopeRelevant; From efb357747d36b6cc115df66dc1d46097b1406cac Mon Sep 17 00:00:00 2001 From: Jeff Date: Mon, 18 Mar 2019 09:18:39 -0500 Subject: [PATCH 06/28] - Fixed #5637 --- .../combat/CanAttackAsThoughItDidntHaveDefenderAllEffect.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/CanAttackAsThoughItDidntHaveDefenderAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/CanAttackAsThoughItDidntHaveDefenderAllEffect.java index 81532ccc94a..d3b865179db 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/CanAttackAsThoughItDidntHaveDefenderAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/CanAttackAsThoughItDidntHaveDefenderAllEffect.java @@ -48,7 +48,8 @@ public class CanAttackAsThoughItDidntHaveDefenderAllEffect extends AsThoughEffec @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { Permanent permanent = game.getPermanent(objectId); - return permanent != null && filter.match(permanent, source.getSourceId(), affectedControllerId, game); + return permanent != null + && filter.match(permanent, source.getSourceId(), source.getControllerId(), game); } private String getText() { From 72c8c267a12920ab3a16ddf9651273f59ce52059 Mon Sep 17 00:00:00 2001 From: Ingmar Goudt Date: Mon, 18 Mar 2019 15:48:35 +0100 Subject: [PATCH 07/28] move Google Guava to mage-root pom in dependencyManagement, so other modules can use it --- Mage.Client/pom.xml | 1 - .../dl/sources/ScryfallImageSupportCards.java | 30 +++++++++---------- .../src/mage/cards/s/ScreechingSilcaw.java | 4 +-- Mage/pom.xml | 4 +++ Mage/src/main/java/mage/cards/CardImpl.java | 7 ++--- .../main/java/mage/players/PlayerImpl.java | 10 +++---- pom.xml | 5 ++++ 7 files changed, 32 insertions(+), 29 deletions(-) diff --git a/Mage.Client/pom.xml b/Mage.Client/pom.xml index 3a2612a36a9..a3264c3aabb 100644 --- a/Mage.Client/pom.xml +++ b/Mage.Client/pom.xml @@ -56,7 +56,6 @@ com.google.guava guava - 20.0 org.swinglabs diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java index 94327e81cd8..0e3ca45c17b 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java @@ -1,5 +1,6 @@ package org.mage.plugins.card.dl.sources; +import com.google.common.collect.ImmutableMap; import org.tritonus.share.ArraySet; import java.util.HashMap; @@ -12,22 +13,19 @@ import java.util.Set; */ public class ScryfallImageSupportCards { - private static final Map xmageSetsToScryfall = new HashMap() { - { - // xmage -> scryfall - put("DD3GVL", "gvl"); - put("DD3JVC", "jvc"); - put("DD3DVD", "dvd"); - put("DD3EVG", "evg"); - put("MPS-AKH", "mp2"); - put("MBP", "pmei"); - put("WMCQ", "pwcq"); - put("EURO", "pelp"); - put("GPX", "pgpx"); - put("MED", "me1"); - put("MEDM", "med"); - } - }; + private static final Map xmageSetsToScryfall = ImmutableMap.builder().put("DD3GVL", "gvl"). + put("DD3JVC", "jvc"). + put("DD3DVD", "dvd"). + put("DD3EVG", "evg"). + put("MPS-AKH", "mp2"). + put("MBP", "pmei"). + put("WMCQ", "pwcq"). + put("EURO", "pelp"). + put("GPX", "pgpx"). + put("MED", "me1"). + put("MEDM", "med").build(); + + private static final Set supportedSets = new ArraySet() { { diff --git a/Mage.Sets/src/mage/cards/s/ScreechingSilcaw.java b/Mage.Sets/src/mage/cards/s/ScreechingSilcaw.java index b356cdac110..da04611f60d 100644 --- a/Mage.Sets/src/mage/cards/s/ScreechingSilcaw.java +++ b/Mage.Sets/src/mage/cards/s/ScreechingSilcaw.java @@ -20,7 +20,7 @@ import mage.constants.SubType; */ public final class ScreechingSilcaw extends CardImpl { - private static final String text = "Metalcraft — Whenever Screeching Silcaw deals combat damage to a player, if you control three or more artifacts, that player puts the top four cards of their library into their graveyard."; + private static final String rule = "Metalcraft — Whenever Screeching Silcaw deals combat damage to a player, if you control three or more artifacts, that player puts the top four cards of their library into their graveyard."; public ScreechingSilcaw(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}"); @@ -34,7 +34,7 @@ public final class ScreechingSilcaw extends CardImpl { //"Metalcraft — Whenever Screeching Silcaw deals combat damage to a player, if you control three or more artifacts, that player puts the top four cards of their library into their graveyard. TriggeredAbility conditional = new ConditionalInterveningIfTriggeredAbility( new DealsCombatDamageToAPlayerTriggeredAbility(new PutLibraryIntoGraveTargetEffect(4), false, true), - MetalcraftCondition.instance, text); + MetalcraftCondition.instance, rule); this.addAbility(conditional); } diff --git a/Mage/pom.xml b/Mage/pom.xml index 80815f55ace..3e5927dd246 100644 --- a/Mage/pom.xml +++ b/Mage/pom.xml @@ -26,6 +26,10 @@ 1.4.197 runtime + + com.google.guava + guava + com.j256.ormlite ormlite-jdbc diff --git a/Mage/src/main/java/mage/cards/CardImpl.java b/Mage/src/main/java/mage/cards/CardImpl.java index e6e1db75cb8..ae22f9da2a2 100644 --- a/Mage/src/main/java/mage/cards/CardImpl.java +++ b/Mage/src/main/java/mage/cards/CardImpl.java @@ -1,5 +1,6 @@ package mage.cards; +import com.google.common.collect.ImmutableList; import mage.MageObject; import mage.MageObjectImpl; import mage.Mana; @@ -224,11 +225,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card { game.getState().getCardState(objectId).addInfo(key, value); } - protected static final ArrayList rulesError = new ArrayList() { - { - add("Exception occurred in rules generation"); - } - }; + protected static final List rulesError = ImmutableList.of("Exception occurred in rules generation"); @Override public List getRules() { diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 9e248bf6270..27191a9765f 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -1,5 +1,6 @@ package mage.players; +import com.google.common.collect.ImmutableMap; import mage.ConditionalMana; import mage.MageObject; import mage.MageObjectReference; @@ -178,11 +179,10 @@ public abstract class PlayerImpl implements Player, Serializable { /** * During some steps we can't play anything */ - protected final Map silentPhaseSteps = new EnumMap(PhaseStep.class) { - { - put(PhaseStep.DECLARE_ATTACKERS, Step.StepPart.PRE); - } - }; + protected final Map silentPhaseSteps = ImmutableMap.builder(). + put(PhaseStep.DECLARE_ATTACKERS, Step.StepPart.PRE).build(); + + public PlayerImpl(String name, RangeOfInfluence range) { this(UUID.randomUUID()); diff --git a/pom.xml b/pom.xml index f197d1c22f1..bf103b4177b 100644 --- a/pom.xml +++ b/pom.xml @@ -109,6 +109,11 @@ slf4j-log4j12 1.8.0-beta2 + + com.google.guava + guava + 20.0 + From bcf02e692cfd7c29ceb174e85c2ee4935c73e57e Mon Sep 17 00:00:00 2001 From: Ingmar Goudt Date: Mon, 18 Mar 2019 16:28:00 +0100 Subject: [PATCH 08/28] rewrite to immutable list builder --- .../deck/generator/DeckGeneratorCMC.java | 94 +++++++++---------- 1 file changed, 43 insertions(+), 51 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorCMC.java b/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorCMC.java index 412e11eeafb..7ed336c88e5 100644 --- a/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorCMC.java +++ b/Mage.Client/src/main/java/mage/client/deck/generator/DeckGeneratorCMC.java @@ -1,53 +1,46 @@ package mage.client.deck.generator; -import java.util.ArrayList; +import com.google.common.collect.ImmutableList; + import java.util.List; public enum DeckGeneratorCMC { - Low( - new ArrayList() {{ - add(new CMC(0, 2, 0.60f)); - add(new CMC(3, 4, 0.30f)); - add(new CMC(5, 6, 0.10f)); - }}, - new ArrayList() {{ - add(new CMC(0, 2, 0.65f)); - add(new CMC(3, 4, 0.30f)); - add(new CMC(5, 5, 0.05f)); - }}), - Default( - new ArrayList() {{ - add(new CMC(0, 2, 0.20f)); - add(new CMC(3, 5, 0.50f)); - add(new CMC(6, 7, 0.25f)); - add(new CMC(8, 100, 0.05f)); - }}, - new ArrayList() {{ - add(new CMC(0, 2, 0.30f)); - add(new CMC(3, 4, 0.45f)); - add(new CMC(5, 6, 0.20f)); - add(new CMC(7, 100, 0.05f)); - }}), - High( - new ArrayList() {{ - add(new CMC(0, 2, 0.05f)); - add(new CMC(3, 5, 0.35f)); - add(new CMC(6, 7, 0.40f)); - add(new CMC(8, 100, 0.15f)); - }}, - new ArrayList() {{ - add(new CMC(0, 2, 0.10f)); - add(new CMC(3, 4, 0.30f)); - add(new CMC(5, 6, 0.45f)); - add(new CMC(7, 100, 0.15f)); - }}); + Low(ImmutableList.builder() + .add(new CMC(0, 2, 0.60f)) + .add(new CMC(3, 4, 0.30f)) + .add(new CMC(5, 6, 0.10f)).build(), + ImmutableList.builder() + .add(new CMC(0, 2, 0.65f)) + .add(new CMC(3, 4, 0.30f)) + .add(new CMC(5, 5, 0.05f)).build()), + Default(ImmutableList.builder() + .add(new CMC(0, 2, 0.20f)) + .add(new CMC(3, 5, 0.50f)) + .add(new CMC(6, 7, 0.25f)) + .add(new CMC(8, 100, 0.05f)).build(), + ImmutableList.builder() + .add(new CMC(0, 2, 0.30f)) + .add(new CMC(3, 4, 0.45f)) + .add(new CMC(5, 6, 0.20f)) + .add(new CMC(7, 100, 0.05f)).build()), - private final ArrayList poolCMCs60; - private final ArrayList poolCMCs40; + High(ImmutableList.builder(). + add(new CMC(0, 2, 0.05f)) + .add(new CMC(3, 5, 0.35f)) + .add(new CMC(6, 7, 0.40f)) + .add(new CMC(8, 100, 0.15f)).build(), + ImmutableList.builder(). + add(new CMC(0, 2, 0.10f)) + .add(new CMC(3, 4, 0.30f)) + .add(new CMC(5, 6, 0.45f)) + .add(new CMC(7, 100, 0.15f)).build()); - DeckGeneratorCMC(ArrayList CMCs60, ArrayList CMCs40) { + private final List poolCMCs60; + private final List poolCMCs40; + + DeckGeneratorCMC(List CMCs60, List CMCs40) { this.poolCMCs60 = CMCs60; this.poolCMCs40 = CMCs40; } @@ -60,8 +53,7 @@ public enum DeckGeneratorCMC { return this.poolCMCs60; } - static class CMC - { + static class CMC { public final int min; public final int max; public final float percentage; @@ -69,12 +61,12 @@ public enum DeckGeneratorCMC { /** * Constructs a CMC range given a minimum and maximum, and the percentage of cards that are in this range. - * @param min the minimum CMC a card in this range can be. - * @param max the maximum CMC a card in this range can be. + * + * @param min the minimum CMC a card in this range can be. + * @param max the maximum CMC a card in this range can be. * @param percentage the percentage of cards in the range (min, max) */ - CMC(int min, int max, float percentage) - { + CMC(int min, int max, float percentage) { this.min = min; this.max = max; this.percentage = percentage; @@ -82,19 +74,19 @@ public enum DeckGeneratorCMC { /** * Sets the amount of cards needed in this CMC range. + * * @param amount the number of cards needed. */ - public void setAmount(int amount) - { + public void setAmount(int amount) { this.amount = amount; } /** * Gets the number of cards needed in this CMC range. + * * @return the number of cards needed in this CMC range. */ - public int getAmount() - { + public int getAmount() { return this.amount; } } From 68181515de5e53a129a2dc97c18f0c2d4311dc83 Mon Sep 17 00:00:00 2001 From: Jeff Date: Mon, 18 Mar 2019 14:23:35 -0500 Subject: [PATCH 09/28] - Fixed #5638 --- Mage.Sets/src/mage/cards/m/MesmericFiend.java | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/Mage.Sets/src/mage/cards/m/MesmericFiend.java b/Mage.Sets/src/mage/cards/m/MesmericFiend.java index ee8645aa7ea..87e8299c2bd 100644 --- a/Mage.Sets/src/mage/cards/m/MesmericFiend.java +++ b/Mage.Sets/src/mage/cards/m/MesmericFiend.java @@ -1,4 +1,3 @@ - package mage.cards.m; import java.util.UUID; @@ -11,15 +10,14 @@ import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.cards.Cards; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.common.FilterNonlandCard; -import mage.game.ExileZone; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.game.permanent.PermanentToken; import mage.players.Player; import mage.target.TargetCard; import mage.target.common.TargetOpponent; @@ -32,7 +30,7 @@ import mage.util.CardUtil; public final class MesmericFiend extends CardImpl { public MesmericFiend(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); this.subtype.add(SubType.NIGHTMARE); this.subtype.add(SubType.HORROR); @@ -79,14 +77,16 @@ class MesmericFiendExileEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); Player opponent = game.getPlayer(source.getFirstTarget()); Permanent sourcePermanent = (Permanent) source.getSourceObject(game); - if (controller != null && opponent != null && sourcePermanent != null) { + if (controller != null + && opponent != null + && sourcePermanent != null) { opponent.revealCards(sourcePermanent.getName(), opponent.getHand(), game); - TargetCard target = new TargetCard(Zone.HAND, new FilterNonlandCard("nonland card to exile")); if (controller.choose(Outcome.Exile, opponent.getHand(), target, game)) { Card card = opponent.getHand().get(target.getFirstTarget(), game); if (card != null) { - controller.moveCardToExileWithInfo(card, CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.HAND, true); + UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); + controller.moveCardsToExile(card, source, game, true, exileId, sourcePermanent.getName()); } } @@ -117,11 +117,14 @@ class MesmericFiendLeaveEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = source.getSourceObject(game); - if (controller != null && sourceObject != null) { - int zoneChangeCounter = (sourceObject instanceof PermanentToken) ? source.getSourceObjectZoneChangeCounter() : source.getSourceObjectZoneChangeCounter() - 1; - ExileZone exZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(), zoneChangeCounter)); - if (exZone != null) { - return controller.moveCards(exZone, Zone.HAND, source, game); + if (controller != null + && sourceObject != null) { + UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter() - 1); + if (exileId != null) { + Cards cards = game.getExile().getExileZone(exileId); + if (!cards.isEmpty()) { + return controller.moveCards(cards, Zone.HAND, source, game); + } } } return false; From a5197ec9543c8178f03805263979b97f81d1a022 Mon Sep 17 00:00:00 2001 From: Jeff Date: Mon, 18 Mar 2019 15:23:13 -0500 Subject: [PATCH 10/28] - Fixed the emblem of Garruk, Apex Predator. --- .../mage/game/command/emblems/GarrukApexPredatorEmblem.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage/src/main/java/mage/game/command/emblems/GarrukApexPredatorEmblem.java b/Mage/src/main/java/mage/game/command/emblems/GarrukApexPredatorEmblem.java index da013f91215..71d2200e311 100644 --- a/Mage/src/main/java/mage/game/command/emblems/GarrukApexPredatorEmblem.java +++ b/Mage/src/main/java/mage/game/command/emblems/GarrukApexPredatorEmblem.java @@ -24,8 +24,8 @@ public final class GarrukApexPredatorEmblem extends Emblem { public GarrukApexPredatorEmblem() { setName("Emblem Garruk"); - Effect effect = new BoostTargetEffect(-1, 0, Duration.EndOfTurn); - effect.setText("it gets -1/-0"); + Effect effect = new BoostTargetEffect(5, 5, Duration.EndOfTurn); + effect.setText("it gets +5/+5"); Ability ability = new AttackedByCreatureTriggeredAbility(Zone.COMMAND, effect, false, SetTargetPointer.PERMANENT); effect = new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn); ability.addEffect(effect.concatBy("and")); From a894e98342b3a926d06b51e9436ddb6c24a8c0a9 Mon Sep 17 00:00:00 2001 From: Richard Coates Date: Mon, 18 Mar 2019 22:42:00 +0100 Subject: [PATCH 11/28] Update AurraSingBaneOfJedi.java Add Legendary to Aurra Planeswalker --- Mage.Sets/src/mage/cards/a/AurraSingBaneOfJedi.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/cards/a/AurraSingBaneOfJedi.java b/Mage.Sets/src/mage/cards/a/AurraSingBaneOfJedi.java index 3ec0575da4f..65d856cb74a 100644 --- a/Mage.Sets/src/mage/cards/a/AurraSingBaneOfJedi.java +++ b/Mage.Sets/src/mage/cards/a/AurraSingBaneOfJedi.java @@ -34,6 +34,7 @@ public final class AurraSingBaneOfJedi extends CardImpl { public AurraSingBaneOfJedi(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{B}{R}"); + this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.AURRA); this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3)); From 7c6d8c42112a1eabf82bb974a111e62d93ade832 Mon Sep 17 00:00:00 2001 From: Richard Coates Date: Mon, 18 Mar 2019 22:43:10 +0100 Subject: [PATCH 12/28] Update DarthTyranusCountOfSerenno.java --- Mage.Sets/src/mage/cards/d/DarthTyranusCountOfSerenno.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/cards/d/DarthTyranusCountOfSerenno.java b/Mage.Sets/src/mage/cards/d/DarthTyranusCountOfSerenno.java index 92b3e495aba..2435cda63a7 100644 --- a/Mage.Sets/src/mage/cards/d/DarthTyranusCountOfSerenno.java +++ b/Mage.Sets/src/mage/cards/d/DarthTyranusCountOfSerenno.java @@ -35,6 +35,7 @@ public final class DarthTyranusCountOfSerenno extends CardImpl { public DarthTyranusCountOfSerenno(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.PLANESWALKER},"{1}{W}{U}{B}"); + this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.DOOKU); this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3)); From 6029808a27296c73d43c0cdb456b0d6482abd4e1 Mon Sep 17 00:00:00 2001 From: Richard Coates Date: Mon, 18 Mar 2019 22:43:53 +0100 Subject: [PATCH 13/28] Update ObiWanKenobi.java Added Legendary Supertype --- Mage.Sets/src/mage/cards/o/ObiWanKenobi.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/cards/o/ObiWanKenobi.java b/Mage.Sets/src/mage/cards/o/ObiWanKenobi.java index 6343c6ef0c6..ff58edb6750 100644 --- a/Mage.Sets/src/mage/cards/o/ObiWanKenobi.java +++ b/Mage.Sets/src/mage/cards/o/ObiWanKenobi.java @@ -27,6 +27,7 @@ public final class ObiWanKenobi extends CardImpl { public ObiWanKenobi(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{3}{W}{U}"); + this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.OBI_WAN); this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5)); From a85ed75c2d6a40763632a547701357af7eafd2de Mon Sep 17 00:00:00 2001 From: Richard Coates Date: Mon, 18 Mar 2019 22:44:34 +0100 Subject: [PATCH 14/28] Update DarthSidiousSithLord.java Added Legendary Supertype --- Mage.Sets/src/mage/cards/d/DarthSidiousSithLord.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/cards/d/DarthSidiousSithLord.java b/Mage.Sets/src/mage/cards/d/DarthSidiousSithLord.java index 27fe59e6722..53a68101cf4 100644 --- a/Mage.Sets/src/mage/cards/d/DarthSidiousSithLord.java +++ b/Mage.Sets/src/mage/cards/d/DarthSidiousSithLord.java @@ -36,6 +36,7 @@ public final class DarthSidiousSithLord extends CardImpl { public DarthSidiousSithLord(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.PLANESWALKER},"{4}{U}{B}{B}{R}"); + this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.SIDIOUS); this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5)); From 053d6e25eaa17187f90cf908f181c15235b0c424 Mon Sep 17 00:00:00 2001 From: Richard Coates Date: Mon, 18 Mar 2019 22:45:39 +0100 Subject: [PATCH 15/28] Update YodaJediMaster.java Added Legendary Supertype --- Mage.Sets/src/mage/cards/y/YodaJediMaster.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/cards/y/YodaJediMaster.java b/Mage.Sets/src/mage/cards/y/YodaJediMaster.java index f2da49f6ed9..17fe2de363f 100644 --- a/Mage.Sets/src/mage/cards/y/YodaJediMaster.java +++ b/Mage.Sets/src/mage/cards/y/YodaJediMaster.java @@ -44,6 +44,7 @@ public final class YodaJediMaster extends CardImpl { public YodaJediMaster(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{1}{G}{U}"); + this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.YODA); this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3)); From 00ce434b6d77672e5ff47c2737c586513b549d12 Mon Sep 17 00:00:00 2001 From: Richard Coates Date: Mon, 18 Mar 2019 22:56:33 +0100 Subject: [PATCH 16/28] Update DarthTyranusCountOfSerenno.java Added Supertype import. --- Mage.Sets/src/mage/cards/d/DarthTyranusCountOfSerenno.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/cards/d/DarthTyranusCountOfSerenno.java b/Mage.Sets/src/mage/cards/d/DarthTyranusCountOfSerenno.java index 2435cda63a7..18839aaa6ac 100644 --- a/Mage.Sets/src/mage/cards/d/DarthTyranusCountOfSerenno.java +++ b/Mage.Sets/src/mage/cards/d/DarthTyranusCountOfSerenno.java @@ -14,6 +14,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.constants.SuperType; import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Zone; From e4feb2932212133beeebeb08fcb8f03d1dabcd23 Mon Sep 17 00:00:00 2001 From: Richard Coates Date: Mon, 18 Mar 2019 22:57:28 +0100 Subject: [PATCH 17/28] Update ObiWanKenobi.java Added import supertype --- Mage.Sets/src/mage/cards/o/ObiWanKenobi.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/cards/o/ObiWanKenobi.java b/Mage.Sets/src/mage/cards/o/ObiWanKenobi.java index ff58edb6750..1eb686645d9 100644 --- a/Mage.Sets/src/mage/cards/o/ObiWanKenobi.java +++ b/Mage.Sets/src/mage/cards/o/ObiWanKenobi.java @@ -15,6 +15,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.constants.SuperType; import mage.constants.Duration; import mage.game.command.emblems.ObiWanKenobiEmblem; import mage.target.common.TargetCreaturePermanent; From 72a792f82906450863e1c709805a8fe099279752 Mon Sep 17 00:00:00 2001 From: Richard Coates Date: Mon, 18 Mar 2019 22:57:57 +0100 Subject: [PATCH 18/28] Update DarthSidiousSithLord.java Added import supertype. --- Mage.Sets/src/mage/cards/d/DarthSidiousSithLord.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/cards/d/DarthSidiousSithLord.java b/Mage.Sets/src/mage/cards/d/DarthSidiousSithLord.java index 53a68101cf4..59cc034dfa4 100644 --- a/Mage.Sets/src/mage/cards/d/DarthSidiousSithLord.java +++ b/Mage.Sets/src/mage/cards/d/DarthSidiousSithLord.java @@ -14,6 +14,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.constants.SuperType; import mage.constants.Duration; import mage.filter.FilterPermanent; import mage.filter.predicate.Predicates; From 025f1f37a4530d088d5f57a85afbd1988c4f9a79 Mon Sep 17 00:00:00 2001 From: Richard Coates Date: Mon, 18 Mar 2019 22:58:17 +0100 Subject: [PATCH 19/28] Update YodaJediMaster.java Added import supertype. --- Mage.Sets/src/mage/cards/y/YodaJediMaster.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/cards/y/YodaJediMaster.java b/Mage.Sets/src/mage/cards/y/YodaJediMaster.java index 17fe2de363f..761caea8c70 100644 --- a/Mage.Sets/src/mage/cards/y/YodaJediMaster.java +++ b/Mage.Sets/src/mage/cards/y/YodaJediMaster.java @@ -16,6 +16,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.constants.SuperType; import mage.constants.Outcome; import mage.constants.TargetController; import mage.constants.Zone; From c154a44bcf928c26ca457f3a55226cc7f63d0a4b Mon Sep 17 00:00:00 2001 From: Richard Coates Date: Mon, 18 Mar 2019 23:38:39 +0100 Subject: [PATCH 20/28] Update AurraSingBaneOfJedi.java Added import Supertype. --- Mage.Sets/src/mage/cards/a/AurraSingBaneOfJedi.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/cards/a/AurraSingBaneOfJedi.java b/Mage.Sets/src/mage/cards/a/AurraSingBaneOfJedi.java index 65d856cb74a..074f1e164db 100644 --- a/Mage.Sets/src/mage/cards/a/AurraSingBaneOfJedi.java +++ b/Mage.Sets/src/mage/cards/a/AurraSingBaneOfJedi.java @@ -15,6 +15,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; +import mage.constants.SuperType; import mage.constants.TargetController; import mage.filter.StaticFilters; import mage.game.Game; From 1b4f126026fad77bdb5fdac85f88b734b22f1f8b Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Tue, 19 Mar 2019 06:07:03 +0400 Subject: [PATCH 21/28] * Bull Rancor - fixed missing trample ability; --- Mage.Sets/src/mage/cards/b/BullRancor.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Mage.Sets/src/mage/cards/b/BullRancor.java b/Mage.Sets/src/mage/cards/b/BullRancor.java index 00a101067b3..00ed2000ab4 100644 --- a/Mage.Sets/src/mage/cards/b/BullRancor.java +++ b/Mage.Sets/src/mage/cards/b/BullRancor.java @@ -9,6 +9,7 @@ import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.MenaceAbility; import mage.abilities.keyword.MonstrosityAbility; +import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -28,6 +29,9 @@ public final class BullRancor extends CardImpl { this.power = new MageInt(7); this.toughness = new MageInt(7); + // Trample + this.addAbility(TrampleAbility.getInstance()); + // {3}{R}{G}{G}{W}: Monstrosity 3. this.addAbility(new MonstrosityAbility("{3}{R}{G}{G}{W}", 3)); From 490d207efe0b496011ac9c997970c1287149b017 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Tue, 19 Mar 2019 06:27:55 +0400 Subject: [PATCH 22/28] Tests: added checks that planeswalkers must be legendary; --- .../test/java/mage/verify/VerifyCardDataTest.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java index e0bac41335a..7d97cd25040 100644 --- a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java +++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java @@ -383,6 +383,19 @@ public class VerifyCardDataTest { } } + // 2. all planeswalkers must be legendary + for (ExpansionSet set : sets) { + for (ExpansionSet.SetCardInfo cardInfo : set.getSetCardInfo()) { + Card card = CardImpl.createCard(cardInfo.getCardClass(), new CardSetInfo(cardInfo.getName(), set.getCode(), + cardInfo.getCardNumber(), cardInfo.getRarity(), cardInfo.getGraphicInfo())); + Assert.assertNotNull(card); + + if (card.getCardType().contains(CardType.PLANESWALKER) && !card.getSuperType().contains(SuperType.LEGENDARY)) { + errorsList.add("error, planeswalker must have legendary type: " + set.getCode() + " - " + set.getName() + " - " + card.getName() + " - " + card.getCardNumber()); + } + } + } + printMessages(warningsList); printMessages(errorsList); if (errorsList.size() > 0) { From ae5cdad951d4e6cd205ec2b1ff4bb9e76e1bffe3 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Tue, 19 Mar 2019 09:13:41 +0400 Subject: [PATCH 23/28] * Jango Fett - fixed wrong damage ability instead boost; --- Mage.Sets/src/mage/cards/j/JangoFett.java | 35 ++++++----------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/Mage.Sets/src/mage/cards/j/JangoFett.java b/Mage.Sets/src/mage/cards/j/JangoFett.java index 92b55230803..fef5ecd7817 100644 --- a/Mage.Sets/src/mage/cards/j/JangoFett.java +++ b/Mage.Sets/src/mage/cards/j/JangoFett.java @@ -1,37 +1,30 @@ - package mage.cards.j; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.MenaceAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Outcome; -import mage.constants.SuperType; -import mage.constants.Zone; +import mage.constants.*; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.filter.predicate.permanent.CounterPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.TargetPermanent; import mage.target.common.TargetOpponentsCreaturePermanent; +import java.util.UUID; + /** - * * @author Styxo/spjspj */ public final class JangoFett extends CardImpl { @@ -55,7 +48,7 @@ public final class JangoFett extends CardImpl { ability.addTarget(new TargetOpponentsCreaturePermanent()); this.addAbility(ability); - // Whenever Jango Fett attacks, it deals X damage to defending player and target creature he or she controls, where X is the number of creatures defending player controls with a bounty counter on them. + // Whenever Jango Fett attacks, it gets +X/+0, where X is the number of creatures defending player controls with a bounty counter on them this.addAbility(new JangoFettTriggeredAbility(new JangoFettEffect(), false)); } @@ -97,11 +90,6 @@ class JangoFettTriggeredAbility extends TriggeredAbilityImpl { if (event.getSourceId().equals(this.getSourceId())) { UUID defenderId = game.getCombat().getDefendingPlayerId(getSourceId(), game); if (defenderId != null) { - this.getTargets().clear(); - FilterCreaturePermanent filter = new FilterCreaturePermanent("target creature defending player controls"); - filter.add(new ControllerIdPredicate(defenderId)); - TargetPermanent target = new TargetPermanent(filter); - this.addTarget(target); return true; } } @@ -125,8 +113,8 @@ class JangoFettTriggeredAbility extends TriggeredAbilityImpl { class JangoFettEffect extends OneShotEffect { public JangoFettEffect() { - super(Outcome.Damage); - this.staticText = "it deals X damage to defending player and target creature he or she controls, where X is the number of creatures defending player controls with a bounty counter on them"; + super(Outcome.BoostCreature); + this.staticText = "it gets +X/+0, where X is the number of creatures defending player controls with a bounty counter on them"; } public JangoFettEffect(final JangoFettEffect ability) { @@ -158,14 +146,7 @@ class JangoFettEffect extends OneShotEffect { return false; } - Permanent targetCreature = game.getPermanent(source.getFirstTarget()); - if (targetCreature != null) { - targetCreature.damage(count, source.getSourceId(), game, false, true); - } - Player defender = game.getPlayer(defenderId); - defender.damage(count, source.getSourceId(), game, false, true); - + game.addEffect(new BoostSourceEffect(count, 0, Duration.WhileOnBattlefield), source); return true; } - } From 3b142d7e79ccc3a5adc1e95853e1c53e74ca294c Mon Sep 17 00:00:00 2001 From: Jeff Date: Tue, 19 Mar 2019 08:39:36 -0500 Subject: [PATCH 24/28] - Fixed #5634 --- Mage.Sets/src/mage/cards/g/GrimFeast.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/cards/g/GrimFeast.java b/Mage.Sets/src/mage/cards/g/GrimFeast.java index ea2bc8f21c2..277773cde9e 100644 --- a/Mage.Sets/src/mage/cards/g/GrimFeast.java +++ b/Mage.Sets/src/mage/cards/g/GrimFeast.java @@ -91,7 +91,7 @@ class GrimFeastEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent creature = game.getPermanentOrLKIBattlefield(source.getFirstTarget()); + Permanent creature = game.getPermanentOrLKIBattlefield(targetPointer.getFirst(game, source)); if (creature == null) { return false; } From a260030069b2b98dcc3e1b90639f50108d8b22ff Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Tue, 19 Mar 2019 21:44:06 +0400 Subject: [PATCH 25/28] Fix tests --- .../mage/cards/decks/exporter/DckExporter.java | 6 +++--- .../mage/cards/decks/exporter/DckExporterTest.java | 13 ++++++------- .../cards/decks/exporter/MtgoExporterTest.java | 14 +++++++------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/Mage/src/main/java/mage/cards/decks/exporter/DckExporter.java b/Mage/src/main/java/mage/cards/decks/exporter/DckExporter.java index 3d673e7eb82..2a9af7a276b 100644 --- a/Mage/src/main/java/mage/cards/decks/exporter/DckExporter.java +++ b/Mage/src/main/java/mage/cards/decks/exporter/DckExporter.java @@ -4,7 +4,7 @@ import mage.cards.decks.DeckCardInfo; import mage.cards.decks.DeckCardLayout; import mage.cards.decks.DeckCardLists; -import java.io.*; +import java.io.PrintWriter; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -48,10 +48,10 @@ public class DckExporter extends DeckExporter { // Write out the layout out.print("LAYOUT MAIN:"); writeCardLayout(out, deck.getCardLayout()); - out.print("\n"); + out.println(""); out.print("LAYOUT SIDEBOARD:"); writeCardLayout(out, deck.getSideboardLayout()); - out.print("\n"); + out.println(""); } private static void writeCardLayout(PrintWriter out, DeckCardLayout layout) { diff --git a/Mage/src/test/java/mage/cards/decks/exporter/DckExporterTest.java b/Mage/src/test/java/mage/cards/decks/exporter/DckExporterTest.java index d1b843dbecb..48d0c4d4cd2 100644 --- a/Mage/src/test/java/mage/cards/decks/exporter/DckExporterTest.java +++ b/Mage/src/test/java/mage/cards/decks/exporter/DckExporterTest.java @@ -20,13 +20,12 @@ public class DckExporterTest { deck.getSideboard().add(new DeckCardInfo("Island", "RNA", "3", 2)); DckExporter exporter = new DckExporter(); exporter.writeDeck(baos, deck); - assertEquals( - "2 [1:RNA] Forest\n" + - "3 [2:RNA] Plains\n" + - "SB: 2 [3:RNA] Island\n" + - "LAYOUT MAIN:\n" + - "LAYOUT SIDEBOARD:\n", - new String(baos.toByteArray())); + assertEquals("2 [1:RNA] Forest" + System.lineSeparator() + + "3 [2:RNA] Plains" + System.lineSeparator() + + "SB: 2 [3:RNA] Island" + System.lineSeparator() + + "LAYOUT MAIN:" + System.lineSeparator() + + "LAYOUT SIDEBOARD:" + System.lineSeparator(), + baos.toString()); } } \ No newline at end of file diff --git a/Mage/src/test/java/mage/cards/decks/exporter/MtgoExporterTest.java b/Mage/src/test/java/mage/cards/decks/exporter/MtgoExporterTest.java index de3681c0bd9..0bbbc7d599d 100644 --- a/Mage/src/test/java/mage/cards/decks/exporter/MtgoExporterTest.java +++ b/Mage/src/test/java/mage/cards/decks/exporter/MtgoExporterTest.java @@ -20,13 +20,13 @@ public class MtgoExporterTest { deck.getSideboard().add(new DeckCardInfo("Island", "RNA", "3", 2)); MtgoExporter exporter = new MtgoExporter(); exporter.writeDeck(baos, deck); - assertEquals( - "2 Forest\n" + - "3 Plains\n" + - "\n" + - "\n" + - "2 Island\n" + - "\n", new String(baos.toByteArray())); + assertEquals("2 Forest" + System.lineSeparator() + + "3 Plains" + System.lineSeparator() + + System.lineSeparator() + + System.lineSeparator() + + "2 Island" + System.lineSeparator() + + System.lineSeparator(), + baos.toString()); } } \ No newline at end of file From a50884f31d7742bd0599153ae19f103cd9229a32 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Tue, 19 Mar 2019 23:20:17 +0400 Subject: [PATCH 26/28] * Images - fixed token images source from tokens.mtg.onl --- .../plugins/card/dl/sources/TokensMtgImageSource.java | 4 ++-- .../java/mage/client/game/TokensMtgImageSourceTest.java | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/TokensMtgImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/TokensMtgImageSource.java index 4f8fc8fd10a..5ac33a0b0ad 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/TokensMtgImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/TokensMtgImageSource.java @@ -89,7 +89,7 @@ public enum TokensMtgImageSource implements CardImageSource { } // Image URL contains token number - // e.g. http://tokens.mtg.onl/tokens/ORI_010-Thopter.jpg -- token number 010 + // e.g. https://tokens.mtg.onl/tokens/ORI_010-Thopter.jpg -- token number 010 // We don't know these numbers, but we can take them from a file // with tokens information that can be downloaded from the site. if (tokensData.isEmpty()) { @@ -115,7 +115,7 @@ public enum TokensMtgImageSource implements CardImageSource { tokenData = list.get(card.getType() - 1); } - String url = "http://tokens.mtg.onl/tokens/" + tokenData.getExpansionSetCode().trim() + '_' + String url = "https://tokens.mtg.onl/tokens/" + tokenData.getExpansionSetCode().trim() + '_' + tokenData.getNumber().trim() + '-' + tokenData.getName().trim() + ".jpg"; url = url.replace(' ', '-'); return new CardImageUrls(url); diff --git a/Mage.Client/src/test/java/mage/client/game/TokensMtgImageSourceTest.java b/Mage.Client/src/test/java/mage/client/game/TokensMtgImageSourceTest.java index 16f4e618f14..6ec7139d3ed 100644 --- a/Mage.Client/src/test/java/mage/client/game/TokensMtgImageSourceTest.java +++ b/Mage.Client/src/test/java/mage/client/game/TokensMtgImageSourceTest.java @@ -19,15 +19,15 @@ public class TokensMtgImageSourceTest { CardImageSource imageSource = TokensMtgImageSource.instance; CardImageUrls url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 1, "ORI", "")); - Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_010-Thopter.jpg", url.baseUrl); + Assert.assertEquals("https://tokens.mtg.onl/tokens/ORI_010-Thopter.jpg", url.baseUrl); url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 2, "ORI", "")); - Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_011-Thopter.jpg", url.baseUrl); + Assert.assertEquals("https://tokens.mtg.onl/tokens/ORI_011-Thopter.jpg", url.baseUrl); url = imageSource.generateTokenUrl(new CardDownloadData("Ashaya, the Awoken World", "ORI", "0", false, 0, "ORI", "")); - Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_007-Ashaya,-the-Awoken-World.jpg", url.baseUrl); + Assert.assertEquals("https://tokens.mtg.onl/tokens/ORI_007-Ashaya,-the-Awoken-World.jpg", url.baseUrl); url = imageSource.generateTokenUrl(new CardDownloadData("Emblem Gideon, Ally of Zendikar", "BFZ", "0", false, 0, null, "")); - Assert.assertEquals("http://tokens.mtg.onl/tokens/BFZ_012-Gideon-Emblem.jpg", url.baseUrl); + Assert.assertEquals("https://tokens.mtg.onl/tokens/BFZ_012-Gideon-Emblem.jpg", url.baseUrl); } } From 468ad0425558781d5bc116631e0663a5eb51b1fb Mon Sep 17 00:00:00 2001 From: Jeff Date: Tue, 19 Mar 2019 15:01:31 -0500 Subject: [PATCH 27/28] - Fixed #5640 --- Mage.Sets/src/mage/cards/p/PithingNeedle.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/cards/p/PithingNeedle.java b/Mage.Sets/src/mage/cards/p/PithingNeedle.java index 402cfba00d8..d8049e8ab00 100644 --- a/Mage.Sets/src/mage/cards/p/PithingNeedle.java +++ b/Mage.Sets/src/mage/cards/p/PithingNeedle.java @@ -1,4 +1,3 @@ - package mage.cards.p; import java.util.Optional; @@ -9,6 +8,7 @@ import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.effects.common.ChooseACardNameEffect; +import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -71,9 +71,10 @@ class PithingNeedleEffect extends ContinuousRuleModifyingEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { MageObject object = game.getObject(event.getSourceId()); Optional ability = game.getAbility(event.getTargetId(), event.getSourceId()); - if (ability.isPresent() && object != null) { + if (ability.isPresent() + && object != null) { if (game.getState().getPlayersInRange(source.getControllerId(), game).contains(event.getPlayerId()) // controller in range - && ability.get().getAbilityType() != AbilityType.MANA + && !(ability.get() instanceof ActivatedManaAbilityImpl) // not an activated mana ability && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY))) { return true; } From f74e4118e0b995fd119a4c229f6f5dc936d80fb6 Mon Sep 17 00:00:00 2001 From: Jeff Date: Tue, 19 Mar 2019 16:39:10 -0500 Subject: [PATCH 28/28] - Fixed #5641 --- .../src/mage/cards/p/PyxisOfPandemonium.java | 65 +++++++++++-------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/Mage.Sets/src/mage/cards/p/PyxisOfPandemonium.java b/Mage.Sets/src/mage/cards/p/PyxisOfPandemonium.java index 9c7e5e2455e..cb8f478b370 100644 --- a/Mage.Sets/src/mage/cards/p/PyxisOfPandemonium.java +++ b/Mage.Sets/src/mage/cards/p/PyxisOfPandemonium.java @@ -1,10 +1,8 @@ - package mage.cards.p; import java.util.HashMap; import java.util.Map; import java.util.UUID; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; @@ -17,6 +15,7 @@ import mage.constants.Outcome; import mage.constants.Zone; import mage.game.ExileZone; import mage.game.Game; +import mage.game.permanent.Permanent; import mage.players.Player; import mage.util.CardUtil; @@ -27,12 +26,19 @@ import mage.util.CardUtil; public final class PyxisOfPandemonium extends CardImpl { public PyxisOfPandemonium(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{1}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); // {T}: Each player exiles the top card of their library face down. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new PyxisOfPandemoniumExileEffect(), new TapSourceCost())); + this.addAbility(new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new PyxisOfPandemoniumExileEffect(), + new TapSourceCost())); + // {7}, {T}, Sacrifice Pyxis of Pandemonium: Each player turns face up all cards he or she owns exiled with Pyxis of Pandemonium, then puts all permanent cards among them onto the battlefield. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PyxisOfPandemoniumPutOntoBattlefieldEffect(), new GenericManaCost(7)); + Ability ability = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new PyxisOfPandemoniumPutOntoBattlefieldEffect(), + new GenericManaCost(7)); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); this.addAbility(ability); @@ -68,10 +74,11 @@ class PyxisOfPandemoniumExileEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - MageObject sourceObject = source.getSourceObject(game); - if (sourceObject != null && controller != null) { + Permanent pyxis = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (pyxis != null + && controller != null) { Map exileIds; - String valueKey = CardUtil.getObjectZoneString("exileIds", sourceObject, game); + String valueKey = CardUtil.getObjectZoneString("exileIds", pyxis, game); Object object = game.getState().getValue(valueKey); if (object instanceof Map) { exileIds = (Map) object; @@ -79,20 +86,22 @@ class PyxisOfPandemoniumExileEffect extends OneShotEffect { exileIds = new HashMap<>(); game.getState().setValue(valueKey, exileIds); } - - for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { - + game.getState().getPlayersInRange(controller.getId(), game).forEach((playerId) -> { Player player = game.getPlayer(playerId); if (player != null) { if (player.getLibrary().hasCards()) { Card card = player.getLibrary().getFromTop(game); - String exileKey = playerId.toString() + CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()).toString(); + String exileKey = playerId.toString() + + CardUtil.getExileZoneId(game, + source.getSourceId(), + pyxis.getZoneChangeCounter(game)); UUID exileId = exileIds.computeIfAbsent(exileKey, k -> UUID.randomUUID()); - player.moveCardsToExile(card, source, game, false, exileId, sourceObject.getIdName() + " (" + player.getName() + ')'); + player.moveCardsToExile(card, source, game, false, + exileId, pyxis.getIdName() + " (" + player.getName() + ')'); card.setFaceDown(true, game); } } - } + }); return true; } return false; @@ -103,7 +112,8 @@ class PyxisOfPandemoniumPutOntoBattlefieldEffect extends OneShotEffect { public PyxisOfPandemoniumPutOntoBattlefieldEffect() { super(Outcome.PutCardInPlay); - this.staticText = "Each player turns face up all cards he or she owns exiled with {this}, then puts all permanent cards among them onto the battlefield"; + this.staticText = "Each player turns face up all cards he or she owns exiled with {this}, " + + "then puts all permanent cards among them onto the battlefield"; } public PyxisOfPandemoniumPutOntoBattlefieldEffect(final PyxisOfPandemoniumPutOntoBattlefieldEffect effect) { @@ -118,10 +128,11 @@ class PyxisOfPandemoniumPutOntoBattlefieldEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - MageObject sourceObject = source.getSourceObject(game); - if (controller != null && sourceObject != null) { + Permanent pyxis = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (controller != null + && pyxis != null) { Map exileIds; - String valueKey = CardUtil.getObjectZoneString("exileIds", sourceObject, game); + String valueKey = CardUtil.getObjectZoneString("exileIds", pyxis, game); Object object = game.getState().getValue(valueKey); if (object instanceof Map) { exileIds = (Map) object; @@ -129,24 +140,26 @@ class PyxisOfPandemoniumPutOntoBattlefieldEffect extends OneShotEffect { return true; } Cards cardsToBringIntoPlay = new CardsImpl(); - for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + game.getState().getPlayersInRange(controller.getId(), game).forEach((playerId) -> { Player player = game.getPlayer(playerId); if (player != null) { - String exileKey = playerId.toString() + CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()).toString(); + String exileKey = playerId.toString() + CardUtil.getExileZoneId(game, + source.getSourceId(), + pyxis.getZoneChangeCounter(game)); UUID exileId = exileIds.get(exileKey); if (exileId != null) { ExileZone exileZone = game.getState().getExile().getExileZone(exileId); if (exileZone != null) { - for (Card card : exileZone.getCards(game)) { + exileZone.getCards(game).stream().map((card) -> { card.setFaceDown(false, game); - if (card.isPermanent()) { - cardsToBringIntoPlay.add(card); - } - } + return card; + }).filter((card) -> (card.isPermanent())).forEachOrdered((card) -> { + cardsToBringIntoPlay.add(card); + }); } } } - } + }); controller.moveCards(cardsToBringIntoPlay.getCards(game), Zone.BATTLEFIELD, source, game, false, false, true, null); return true; }