diff --git a/.gitignore b/.gitignore index 227cae92d1..6f5e1ab0f1 100644 --- a/.gitignore +++ b/.gitignore @@ -92,6 +92,7 @@ hs_err*.log *.txt Mage.Client/serverlist.txt /bin/ +/out/ /target/ client_secrets.json diff --git a/Mage.Client/src/main/java/mage/client/MageFrame.java b/Mage.Client/src/main/java/mage/client/MageFrame.java index 5b60e65ba1..03b2f5a272 100644 --- a/Mage.Client/src/main/java/mage/client/MageFrame.java +++ b/Mage.Client/src/main/java/mage/client/MageFrame.java @@ -277,6 +277,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { try { UIManager.put("desktop", new Color(0, 0, 0, 0)); UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"); + //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); // stop JSplitPane from eating F6 and F8 or any other function keys { Object value = UIManager.get("SplitPane.ancestorInputMap"); diff --git a/Mage.Client/src/main/java/mage/client/cards/Card.java b/Mage.Client/src/main/java/mage/client/cards/Card.java index 1a43fca155..ddfbc789e9 100644 --- a/Mage.Client/src/main/java/mage/client/cards/Card.java +++ b/Mage.Client/src/main/java/mage/client/cards/Card.java @@ -92,6 +92,7 @@ import mage.view.CardView; import mage.view.CounterView; import mage.view.PermanentView; import mage.view.StackAbilityView; +import org.apache.log4j.Logger; /** * @@ -191,7 +192,7 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis gSmall.drawImage(ImageHelper.scaleImage(image, Config.dimensions.frameWidth, Config.dimensions.frameHeight), 0, 0, this); gImage.setFont(new Font("Arial", Font.PLAIN, NAME_FONT_MAX_SIZE)); - gImage.drawString(card.getName(), CONTENT_MAX_XOFFSET, NAME_MAX_YOFFSET); + gImage.drawString(card.getName()+"TEST", CONTENT_MAX_XOFFSET, NAME_MAX_YOFFSET); if (card.getCardTypes().contains(CardType.CREATURE)) { gImage.drawString(card.getPower() + "/" + card.getToughness(), POWBOX_TEXT_MAX_LEFT, POWBOX_TEXT_MAX_TOP); } else if (card.getCardTypes().contains(CardType.PLANESWALKER)) { @@ -205,9 +206,9 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis gImage.dispose(); gSmall.setFont(new Font("Arial", Font.PLAIN, Config.dimensions.nameFontSize)); - gSmall.drawString(card.getName(), Config.dimensions.contentXOffset, Config.dimensions.nameYOffset); + gSmall.drawString(card.getName()+"TEST2", Config.dimensions.contentXOffset, Config.dimensions.nameYOffset); if (card.getCardTypes().contains(CardType.CREATURE)) { - gSmall.drawString(card.getPower() + "/" + card.getToughness(), Config.dimensions.powBoxTextLeft, Config.dimensions.powBoxTextTop); + gSmall.drawString(card.getPower() + "/-/" + card.getToughness(), Config.dimensions.powBoxTextLeft, Config.dimensions.powBoxTextTop); } else if (card.getCardTypes().contains(CardType.PLANESWALKER)) { gSmall.drawString(card.getLoyalty(), Config.dimensions.powBoxTextLeft, Config.dimensions.powBoxTextTop); } @@ -221,7 +222,7 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis } @Override - public void updateImage() { + public void updateArtImage() { } @@ -318,6 +319,19 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis return sbType.toString(); } + + protected void drawDetailed(Graphics2D g) { + // Get the size of the card + int width = getWidth(); + int height = getHeight(); + + g.setColor(Color.black); + g.drawRoundRect(0, 0, width, height, 4, 4); + g.setColor(Color.white); + g.setFont(new Font("Arial", Font.PLAIN, NAME_FONT_MAX_SIZE)); + g.drawString(card.getName(), 0, 0); + Logger.getLogger(Card.class).info("Drawing"); + } /** * This method is called from within the constructor to initialize the form. @@ -355,6 +369,8 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis @Override public void paintComponent(Graphics graphics) { + drawDetailed((Graphics2D)graphics); + /* Graphics2D g2 = (Graphics2D) graphics; g2.drawImage(small, 0, 0, this); @@ -365,6 +381,7 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis g2.setColor(Color.BLACK); } g2.drawRect(0, 0, Config.dimensions.frameWidth - 1, Config.dimensions.frameHeight - 1); + */ } @Override diff --git a/Mage.Client/src/main/java/mage/client/cards/Cards.java b/Mage.Client/src/main/java/mage/client/cards/Cards.java index 67287d54d8..d4b91472b6 100644 --- a/Mage.Client/src/main/java/mage/client/cards/Cards.java +++ b/Mage.Client/src/main/java/mage/client/cards/Cards.java @@ -114,7 +114,7 @@ public class Cards extends javax.swing.JPanel { setGUISize(); for (MageCard mageCard : cards.values()) { mageCard.setCardBounds(0, 0, getCardDimension().width, getCardDimension().height); - mageCard.updateImage(); + mageCard.updateArtImage(); mageCard.doLayout(); } layoutCards(); diff --git a/Mage.Client/src/main/java/mage/client/cards/CardsList.form b/Mage.Client/src/main/java/mage/client/cards/CardsList.form index 2e3e1c73b1..e64f4ae04b 100644 --- a/Mage.Client/src/main/java/mage/client/cards/CardsList.form +++ b/Mage.Client/src/main/java/mage/client/cards/CardsList.form @@ -34,21 +34,16 @@ - - - - - - - + + - - - + + + @@ -81,15 +76,7 @@ - - - - - - - - - + @@ -97,7 +84,7 @@ - + @@ -109,11 +96,7 @@ - - - - @@ -177,60 +160,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -324,24 +253,6 @@ - - - - - - - - - - - - - - - - - - diff --git a/Mage.Client/src/main/java/mage/client/cards/CardsList.java b/Mage.Client/src/main/java/mage/client/cards/CardsList.java index 9d999ab6e4..e27eed4806 100644 --- a/Mage.Client/src/main/java/mage/client/cards/CardsList.java +++ b/Mage.Client/src/main/java/mage/client/cards/CardsList.java @@ -211,7 +211,7 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar } }); - mainModel.setUpdateCountsCallback(new UpdateCountsCallback(lblCount, lblCreatureCount, lblLandCount, lblSorceryCount, lblInstantCount, lblEnchantmentCount, lblArtifactCount)); + mainModel.setUpdateCountsCallback(new UpdateCountsCallback(lblCount, lblCreatureCount, lblLandCount, null, null, null, null)); } // if you use the deck ediot to build a free deck, numbers can be set directly in deck and sideboard @@ -418,10 +418,6 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar this.lblCount.setText(Integer.toString(count)); this.lblCreatureCount.setText(Integer.toString(creatureCount)); this.lblLandCount.setText(Integer.toString(landCount)); - this.lblSorceryCount.setText(Integer.toString(sorceryCount)); - this.lblInstantCount.setText(Integer.toString(instantCount)); - this.lblEnchantmentCount.setText(Integer.toString(enchantmentCount)); - this.lblArtifactCount.setText(Integer.toString(artifactCount)); } private MageCard addCard(CardView card, BigCard bigCard, UUID gameId) { @@ -482,14 +478,10 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar lblCount = new javax.swing.JLabel(); lblLandCount = new javax.swing.JLabel(); lblCreatureCount = new javax.swing.JLabel(); - lblSorceryCount = new javax.swing.JLabel(); - lblInstantCount = new javax.swing.JLabel(); - lblEnchantmentCount = new javax.swing.JLabel(); chkPiles = new javax.swing.JCheckBox(); cbSortBy = new javax.swing.JComboBox(); jToggleListView = new javax.swing.JToggleButton(); jToggleCardView = new javax.swing.JToggleButton(); - lblArtifactCount = new javax.swing.JLabel(); panelCardArea = new javax.swing.JScrollPane(); cardArea = new javax.swing.JLayeredPane(); @@ -537,39 +529,6 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar lblCreatureCount.setRequestFocusEnabled(false); lblCreatureCount.setVerifyInputWhenFocusTarget(false); - lblSorceryCount.setHorizontalAlignment(javax.swing.SwingConstants.LEFT); - lblSorceryCount.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/type_sorcery.png"))); // NOI18N - lblSorceryCount.setText("999"); - lblSorceryCount.setToolTipText("Number of sorceries."); - lblSorceryCount.setVerticalAlignment(javax.swing.SwingConstants.TOP); - lblSorceryCount.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); - lblSorceryCount.setFocusable(false); - lblSorceryCount.setInheritsPopupMenu(false); - lblSorceryCount.setRequestFocusEnabled(false); - lblSorceryCount.setVerifyInputWhenFocusTarget(false); - - lblInstantCount.setHorizontalAlignment(javax.swing.SwingConstants.LEFT); - lblInstantCount.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/type_instant.png"))); // NOI18N - lblInstantCount.setText("999"); - lblInstantCount.setToolTipText("Number of instants."); - lblInstantCount.setVerticalAlignment(javax.swing.SwingConstants.TOP); - lblInstantCount.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); - lblInstantCount.setFocusable(false); - lblInstantCount.setInheritsPopupMenu(false); - lblInstantCount.setRequestFocusEnabled(false); - lblInstantCount.setVerifyInputWhenFocusTarget(false); - - lblEnchantmentCount.setHorizontalAlignment(javax.swing.SwingConstants.LEFT); - lblEnchantmentCount.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/type_enchantment.png"))); // NOI18N - lblEnchantmentCount.setText("999"); - lblEnchantmentCount.setToolTipText("Number of enchantments."); - lblEnchantmentCount.setVerticalAlignment(javax.swing.SwingConstants.TOP); - lblEnchantmentCount.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); - lblEnchantmentCount.setFocusable(false); - lblEnchantmentCount.setInheritsPopupMenu(false); - lblEnchantmentCount.setRequestFocusEnabled(false); - lblEnchantmentCount.setVerifyInputWhenFocusTarget(false); - chkPiles.setText("Piles"); chkPiles.setHorizontalAlignment(javax.swing.SwingConstants.LEFT); chkPiles.setMargin(new java.awt.Insets(3, 2, 2, 2)); @@ -619,17 +578,6 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar } }); - lblArtifactCount.setHorizontalAlignment(javax.swing.SwingConstants.LEFT); - lblArtifactCount.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/type_artifact.png"))); // NOI18N - lblArtifactCount.setText("999"); - lblArtifactCount.setToolTipText("Number of artifacts"); - lblArtifactCount.setVerticalAlignment(javax.swing.SwingConstants.TOP); - lblArtifactCount.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); - lblArtifactCount.setFocusable(false); - lblArtifactCount.setInheritsPopupMenu(false); - lblArtifactCount.setRequestFocusEnabled(false); - lblArtifactCount.setVerifyInputWhenFocusTarget(false); - javax.swing.GroupLayout panelControlLayout = new javax.swing.GroupLayout(panelControl); panelControl.setLayout(panelControlLayout); panelControlLayout.setHorizontalGroup( @@ -641,14 +589,6 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(lblCreatureCount) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblSorceryCount) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblInstantCount) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblEnchantmentCount) - .addGap(4, 4, 4) - .addComponent(lblArtifactCount) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(chkPiles) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(cbSortBy, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) @@ -656,7 +596,7 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar .addComponent(jToggleListView, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jToggleCardView, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 62, Short.MAX_VALUE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); panelControlLayout.setVerticalGroup( panelControlLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -666,11 +606,7 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar .addComponent(lblCount) .addComponent(lblLandCount) .addComponent(lblCreatureCount) - .addComponent(lblSorceryCount) - .addComponent(lblInstantCount) - .addComponent(lblEnchantmentCount) - .addComponent(chkPiles) - .addComponent(lblArtifactCount)) + .addComponent(chkPiles)) .addComponent(cbSortBy, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jToggleListView, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jToggleCardView, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) @@ -686,21 +622,27 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(1, 1, 1) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(panelControl, javax.swing.GroupLayout.DEFAULT_SIZE, 703, Short.MAX_VALUE) - .addComponent(panelCardArea))) + .addComponent(panelControl, javax.swing.GroupLayout.PREFERRED_SIZE, 467, Short.MAX_VALUE) + .addComponent(panelCardArea) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addComponent(panelControl, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, 0) - .addComponent(panelCardArea, javax.swing.GroupLayout.DEFAULT_SIZE, 86, Short.MAX_VALUE)) + .addComponent(panelControl, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(2, 2, 2) + .addComponent(panelCardArea, javax.swing.GroupLayout.DEFAULT_SIZE, 179, Short.MAX_VALUE)) ); }// //GEN-END:initComponents + private void jToggleCardViewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleCardViewActionPerformed + currentView = this; + panelCardArea.setViewportView(cardArea); + cbSortBy.setEnabled(true); + chkPiles.setEnabled(true); + PreferencesDialog.saveValue(PreferencesDialog.KEY_DRAFT_VIEW, "cardView"); + redrawCards(); + }//GEN-LAST:event_jToggleCardViewActionPerformed + private void jToggleListViewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleListViewActionPerformed currentView = mainModel; panelCardArea.setViewportView(mainTable); @@ -720,15 +662,6 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar drawCards(sortSetting); }//GEN-LAST:event_chkPilesActionPerformed - private void jToggleCardViewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleCardViewActionPerformed - currentView = this; - panelCardArea.setViewportView(cardArea); - cbSortBy.setEnabled(true); - chkPiles.setEnabled(true); - PreferencesDialog.saveValue(PreferencesDialog.KEY_DRAFT_VIEW, "cardView"); - redrawCards(); - }//GEN-LAST:event_jToggleCardViewActionPerformed - // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.ButtonGroup bgView; private javax.swing.JLayeredPane cardArea; @@ -736,13 +669,9 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar private javax.swing.JCheckBox chkPiles; private javax.swing.JToggleButton jToggleCardView; private javax.swing.JToggleButton jToggleListView; - private javax.swing.JLabel lblArtifactCount; private javax.swing.JLabel lblCount; private javax.swing.JLabel lblCreatureCount; - private javax.swing.JLabel lblEnchantmentCount; - private javax.swing.JLabel lblInstantCount; private javax.swing.JLabel lblLandCount; - private javax.swing.JLabel lblSorceryCount; private javax.swing.JScrollPane panelCardArea; private javax.swing.JPanel panelControl; // End of variables declaration//GEN-END:variables diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckArea.form b/Mage.Client/src/main/java/mage/client/deckeditor/DeckArea.form index 625407e997..e3178a5df7 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckArea.form +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckArea.form @@ -16,31 +16,26 @@ - + - + - - + + + + - - - - - - - @@ -48,6 +43,13 @@ + + + + + + + diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckArea.java b/Mage.Client/src/main/java/mage/client/deckeditor/DeckArea.java index 35d501a8f0..d7a2dd1b02 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckArea.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckArea.java @@ -118,23 +118,23 @@ public class DeckArea extends javax.swing.JPanel { private void initComponents() { deckAreaSplitPane = new javax.swing.JSplitPane(); - deckList = new mage.client.cards.CardsList(); sideboardList = new mage.client.cards.CardsList(); + deckList = new mage.client.cards.CardsList(); - deckAreaSplitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); - deckAreaSplitPane.setResizeWeight(0.8); - deckAreaSplitPane.setLeftComponent(deckList); + deckAreaSplitPane.setBorder(null); + deckAreaSplitPane.setResizeWeight(0.6); deckAreaSplitPane.setRightComponent(sideboardList); + deckAreaSplitPane.setLeftComponent(deckList); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(deckAreaSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 740, Short.MAX_VALUE) + .addComponent(deckAreaSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 918, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(deckAreaSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 568, Short.MAX_VALUE) + .addComponent(deckAreaSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 377, Short.MAX_VALUE) ); }// //GEN-END:initComponents diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/table/UpdateCountsCallback.java b/Mage.Client/src/main/java/mage/client/deckeditor/table/UpdateCountsCallback.java index 64889c892d..8960035cfe 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/table/UpdateCountsCallback.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/table/UpdateCountsCallback.java @@ -11,7 +11,7 @@ public class UpdateCountsCallback { private final javax.swing.JLabel lblCount; private final javax.swing.JLabel lblCreatureCount; private final javax.swing.JLabel lblLandCount; - private final javax.swing.JLabel lblSoerceryCount; + private final javax.swing.JLabel lblSorceryCount; private final javax.swing.JLabel lblInstantCount; private final javax.swing.JLabel lblEnchantmentCount; private final javax.swing.JLabel lblArtifactCount; @@ -20,19 +20,26 @@ public class UpdateCountsCallback { this.lblCount = count; this.lblCreatureCount = creatures; this.lblLandCount = lands; - this.lblSoerceryCount = sorceries; + this.lblSorceryCount = sorceries; this.lblInstantCount = instants; this.lblEnchantmentCount = enchantments; this.lblArtifactCount = artifacts; } public void update(int count, int creatures, int lands, int sorceries, int instants, int enchantments, int artifacts) { - this.lblCount.setText(Integer.toString(count)); - this.lblCreatureCount.setText(Integer.toString(creatures)); - this.lblLandCount.setText(Integer.toString(lands)); - this.lblSoerceryCount.setText(Integer.toString(sorceries)); - this.lblInstantCount.setText(Integer.toString(instants)); - this.lblEnchantmentCount.setText(Integer.toString(enchantments)); - this.lblArtifactCount.setText(Integer.toString(artifacts)); + if (this.lblCount != null) + this.lblCount.setText(Integer.toString(count)); + if (this.lblCreatureCount != null) + this.lblCreatureCount.setText(Integer.toString(creatures)); + if (this.lblLandCount != null) + this.lblLandCount.setText(Integer.toString(lands)); + if (this.lblSorceryCount != null) + this.lblSorceryCount.setText(Integer.toString(sorceries)); + if (this.lblInstantCount != null) + this.lblInstantCount.setText(Integer.toString(instants)); + if (this.lblEnchantmentCount != null) + this.lblEnchantmentCount.setText(Integer.toString(enchantments)); + if (this.lblArtifactCount != null) + this.lblArtifactCount.setText(Integer.toString(artifacts)); } } diff --git a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form index 738a431c48..4cf0b3303c 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form @@ -31,7 +31,11 @@ - + + + + + @@ -146,7 +150,7 @@ - + @@ -3945,7 +3949,7 @@ - + @@ -4147,11 +4151,12 @@ - + - - + + + @@ -4160,11 +4165,13 @@ + + - + @@ -4189,36 +4196,41 @@ - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + + + + + + + + - - + - + @@ -4228,14 +4240,13 @@ - - + @@ -4249,7 +4260,6 @@ - @@ -4473,6 +4483,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -5579,7 +5655,7 @@ - + diff --git a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java index 2b5c14bbeb..74ba0968fa 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java @@ -118,6 +118,10 @@ public class PreferencesDialog extends javax.swing.JDialog { public static final String KEY_CARD_IMAGES_SAVE_TO_ZIP = "cardImagesSaveToZip"; public static final String KEY_CARD_IMAGES_PREF_LANGUAGE = "cardImagesPreferedImageLaguage"; + public static final String KEY_CARD_RENDERING_FALLBACK = "cardRenderingFallback"; + public static final String KEY_CARD_RENDERING_REMINDER_TEXT = "cardRenderingReminderText"; + public static final String KEY_CARD_RENDERING_SET_SYMBOL = "cardRenderingSetSymbol"; + public static final String KEY_BACKGROUND_IMAGE = "backgroundImage"; public static final String KEY_BATTLEFIELD_IMAGE = "battlefieldImage"; public static final String KEY_BACKGROUND_IMAGE_DEFAULT = "backgroundImagedDefault"; @@ -464,6 +468,10 @@ public class PreferencesDialog extends javax.swing.JDialog { cbUseRandomBattleImage = new javax.swing.JCheckBox(); jLabel14 = new javax.swing.JLabel(); jLabel15 = new javax.swing.JLabel(); + jPanel1 = new javax.swing.JPanel(); + cbCardRenderImageFallback = new javax.swing.JCheckBox(); + cbCardRenderShowReminderText = new javax.swing.JCheckBox(); + cbCardRenderHideSetSymbol = new javax.swing.JCheckBox(); tabSounds = new javax.swing.JPanel(); sounds_clips = new javax.swing.JPanel(); cbEnableGameSounds = new javax.swing.JCheckBox(); @@ -1385,7 +1393,7 @@ public class PreferencesDialog extends javax.swing.JDialog { .add(jLabelEndOfTurn) .add(checkBoxEndTurnOthers)) .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) - .add(phases_stopSettings, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 260, Short.MAX_VALUE) + .add(phases_stopSettings, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 266, Short.MAX_VALUE) .addContainerGap()) ); @@ -1439,41 +1447,43 @@ public class PreferencesDialog extends javax.swing.JDialog { .add(panelCardImagesLayout.createSequentialGroup() .add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(panelCardImagesLayout.createSequentialGroup() - .add(24, 24, 24) + .addContainerGap() .add(txtImageFolderPath) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(btnBrowseImageLocation)) .add(panelCardImagesLayout.createSequentialGroup() - .add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false) - .add(org.jdesktop.layout.GroupLayout.LEADING, panelCardImagesLayout.createSequentialGroup() - .addContainerGap() - .add(labelNumberOfDownloadThreads) - .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) - .add(cbNumberOfDownloadThreads, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 153, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) - .add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) - .add(cbUseDefaultImageFolder) - .add(cbCheckForNewImages) + .add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false) .add(panelCardImagesLayout.createSequentialGroup() - .add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false) - .add(org.jdesktop.layout.GroupLayout.LEADING, panelCardImagesLayout.createSequentialGroup() - .addContainerGap() - .add(labelPreferedImageLanguage)) - .add(org.jdesktop.layout.GroupLayout.LEADING, cbSaveToZipFiles)) - .add(40, 40, 40) - .add(cbPreferedImageLanguage, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 153, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))) - .add(0, 251, Short.MAX_VALUE))) + .add(cbCheckForNewImages) + .add(147, 147, 147)) + .add(org.jdesktop.layout.GroupLayout.LEADING, panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING) + .add(panelCardImagesLayout.createSequentialGroup() + .add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false) + .add(org.jdesktop.layout.GroupLayout.LEADING, panelCardImagesLayout.createSequentialGroup() + .addContainerGap() + .add(labelPreferedImageLanguage)) + .add(org.jdesktop.layout.GroupLayout.LEADING, cbSaveToZipFiles)) + .add(20, 20, 20) + .add(cbPreferedImageLanguage, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 153, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) + .add(panelCardImagesLayout.createSequentialGroup() + .addContainerGap() + .add(labelNumberOfDownloadThreads) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(cbNumberOfDownloadThreads, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 153, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))) + .add(cbUseDefaultImageFolder)) + .add(0, 231, Short.MAX_VALUE))) .addContainerGap()) ); panelCardImagesLayout.setVerticalGroup( panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(panelCardImagesLayout.createSequentialGroup() - .addContainerGap() .add(cbUseDefaultImageFolder) .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) .add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) .add(txtImageFolderPath, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .add(btnBrowseImageLocation)) - .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .add(cbCheckForNewImages) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(cbSaveToZipFiles) @@ -1484,8 +1494,7 @@ public class PreferencesDialog extends javax.swing.JDialog { .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) .add(cbPreferedImageLanguage, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) - .add(labelPreferedImageLanguage)) - .addContainerGap(48, Short.MAX_VALUE)) + .add(labelPreferedImageLanguage))) ); panelBackgroundImages.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Background images setting:")); @@ -1592,6 +1601,51 @@ public class PreferencesDialog extends javax.swing.JDialog { .add(jLabel15))) ); + jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Card rendering:")); + + cbCardRenderImageFallback.setText("Fall back to plain image based rendering"); + cbCardRenderImageFallback.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cbCardRenderImageFallbackActionPerformed(evt); + } + }); + + cbCardRenderShowReminderText.setText("Show reminder text in rendered card textboxes"); + cbCardRenderShowReminderText.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cbCardRenderShowReminderTextActionPerformed(evt); + } + }); + + cbCardRenderHideSetSymbol.setText("Hide set symbols on cards (more space on the type line for card types)"); + cbCardRenderHideSetSymbol.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cbCardRenderHideSetSymbolActionPerformed(evt); + } + }); + + org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(jPanel1Layout.createSequentialGroup() + .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(cbCardRenderImageFallback) + .add(cbCardRenderShowReminderText) + .add(cbCardRenderHideSetSymbol)) + .add(0, 0, Short.MAX_VALUE)) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(jPanel1Layout.createSequentialGroup() + .add(cbCardRenderImageFallback) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(cbCardRenderShowReminderText) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(cbCardRenderHideSetSymbol) + .add(0, 0, Short.MAX_VALUE)) + ); + org.jdesktop.layout.GroupLayout tabImagesLayout = new org.jdesktop.layout.GroupLayout(tabImages); tabImages.setLayout(tabImagesLayout); tabImagesLayout.setHorizontalGroup( @@ -1600,6 +1654,7 @@ public class PreferencesDialog extends javax.swing.JDialog { .addContainerGap() .add(tabImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(panelCardImages, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .add(panelBackgroundImages, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap()) ); @@ -1607,10 +1662,12 @@ public class PreferencesDialog extends javax.swing.JDialog { tabImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(tabImagesLayout.createSequentialGroup() .addContainerGap() + .add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(panelCardImages, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(panelBackgroundImages, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) - .addContainerGap(90, Short.MAX_VALUE)) + .addContainerGap(53, Short.MAX_VALUE)) ); tabsPanel.addTab("Images", tabImages); @@ -2220,7 +2277,7 @@ public class PreferencesDialog extends javax.swing.JDialog { .add(connection_serversLayout.createSequentialGroup() .add(141, 141, 141) .add(jLabel17))) - .addContainerGap(111, Short.MAX_VALUE)) + .addContainerGap(91, Short.MAX_VALUE)) ); connection_serversLayout.setVerticalGroup( connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) @@ -2406,7 +2463,10 @@ public class PreferencesDialog extends javax.swing.JDialog { .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(exitButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 100, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .add(6, 6, 6)) - .add(tabsPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .add(tabsPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) @@ -2534,6 +2594,11 @@ public class PreferencesDialog extends javax.swing.JDialog { save(prefs, dialog.cbUseDefaultBattleImage, KEY_BATTLEFIELD_IMAGE_DEFAULT, "true", "false", UPDATE_CACHE_POLICY); save(prefs, dialog.cbUseRandomBattleImage, KEY_BATTLEFIELD_IMAGE_RANDOM, "true", "false", UPDATE_CACHE_POLICY); + // rendering + save(prefs, dialog.cbCardRenderImageFallback, KEY_CARD_RENDERING_FALLBACK, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbCardRenderHideSetSymbol, KEY_CARD_RENDERING_SET_SYMBOL, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbCardRenderShowReminderText, KEY_CARD_RENDERING_REMINDER_TEXT, "true", "false", UPDATE_CACHE_POLICY); + // sounds save(prefs, dialog.cbEnableGameSounds, KEY_SOUNDS_GAME_ON, "true", "false", UPDATE_CACHE_POLICY); save(prefs, dialog.cbEnableDraftSounds, KEY_SOUNDS_DRAFT_ON, "true", "false", UPDATE_CACHE_POLICY); @@ -2806,6 +2871,14 @@ public class PreferencesDialog extends javax.swing.JDialog { // TODO add your handling code here: }//GEN-LAST:event_cbAutoOrderTriggerActionPerformed + private void cbCardRenderImageFallbackActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbCardRenderImageFallbackActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_cbCardRenderImageFallbackActionPerformed + + private void cbCardRenderShowReminderTextActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbCardRenderShowReminderTextActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_cbCardRenderShowReminderTextActionPerformed + private void cbSaveToZipFilesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbSaveToZipFilesActionPerformed // TODO add your handling code here: }//GEN-LAST:event_cbSaveToZipFilesActionPerformed @@ -2831,6 +2904,10 @@ public class PreferencesDialog extends javax.swing.JDialog { } }//GEN-LAST:event_cbUseDefaultImageFolderActionPerformed + private void cbCardRenderHideSetSymbolActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbCardRenderHideSetSymbolActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_cbCardRenderHideSetSymbolActionPerformed + private void showProxySettings() { Connection.ProxyType proxyType = (Connection.ProxyType) cbProxyType.getSelectedItem(); switch (proxyType) { @@ -3004,6 +3081,11 @@ public class PreferencesDialog extends javax.swing.JDialog { dialog.cbNumberOfDownloadThreads.setSelectedItem(MageFrame.getPreferences().get(KEY_CARD_IMAGES_THREADS, "10")); dialog.cbPreferedImageLanguage.setSelectedItem(MageFrame.getPreferences().get(KEY_CARD_IMAGES_PREF_LANGUAGE, "en")); + // rendering settings + load(prefs, dialog.cbCardRenderImageFallback, KEY_CARD_RENDERING_FALLBACK, "true"); + load(prefs, dialog.cbCardRenderHideSetSymbol, KEY_CARD_RENDERING_SET_SYMBOL, "true"); + load(prefs, dialog.cbCardRenderShowReminderText, KEY_CARD_RENDERING_REMINDER_TEXT, "true"); + //add background load precedure prop = prefs.get(KEY_BACKGROUND_IMAGE_DEFAULT, "true"); if (prop.equals("true")) { @@ -3384,6 +3466,9 @@ public class PreferencesDialog extends javax.swing.JDialog { private javax.swing.JCheckBox cbAllowRequestToShowHandCards; private javax.swing.JCheckBox cbAskMoveToGraveOrder; private javax.swing.JCheckBox cbAutoOrderTrigger; + private javax.swing.JCheckBox cbCardRenderHideSetSymbol; + private javax.swing.JCheckBox cbCardRenderImageFallback; + private javax.swing.JCheckBox cbCardRenderShowReminderText; private javax.swing.JCheckBox cbCheckForNewImages; private javax.swing.JCheckBox cbConfirmEmptyManaPool; private javax.swing.JCheckBox cbDraftLogAutoSave; @@ -3443,6 +3528,7 @@ public class PreferencesDialog extends javax.swing.JDialog { private javax.swing.JLabel jLabelOpponentsTurn; private javax.swing.JLabel jLabelUpkeep; private javax.swing.JLabel jLabelYourTurn; + private javax.swing.JPanel jPanel1; private javax.swing.JPanel jPanel10; private javax.swing.JPanel jPanel11; private javax.swing.JPanel jPanel12; diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/Animation.java b/Mage.Client/src/main/java/org/mage/card/arcane/Animation.java index 67e17540ea..ea69e5cc6e 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/Animation.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/Animation.java @@ -159,7 +159,7 @@ public abstract class Animation { public static void transformCard(final CardPanel panel, final MagePermanent parent, final boolean transformed) { - new Animation(1200) { + new Animation(600) { private boolean state = false; @Override @@ -256,7 +256,7 @@ public abstract class Animation { public void run() { if (placeholder != null) { placeholder.setDisplayEnabled(true); - placeholder.setImage(animationPanel); + placeholder.transferResources(animationPanel); } animationPanel.setVisible(false); animationPanel.repaint(); @@ -303,7 +303,7 @@ public abstract class Animation { public void run() { if (placeholder != null) { placeholder.setDisplayEnabled(true); - placeholder.setImage(animationPanel); + placeholder.transferResources(animationPanel); } animationPanel.setVisible(false); animationPanel.repaint(); diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanel.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanel.java index 94fd559cc5..23520e6a83 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanel.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanel.java @@ -1,17 +1,11 @@ package org.mage.card.arcane; -import com.google.common.base.Function; -import com.google.common.collect.MapMaker; -import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Dimension; -import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; -import java.awt.Image; import java.awt.Point; import java.awt.Rectangle; -import java.awt.RenderingHints; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentEvent; @@ -22,44 +16,27 @@ import java.awt.event.MouseMotionListener; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.awt.image.BufferedImage; -import java.io.File; import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.StringTokenizer; import java.util.UUID; -import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JButton; -import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JPopupMenu; import mage.cards.MagePermanent; import mage.cards.TextPopup; import mage.cards.action.ActionCallback; import mage.cards.action.TransferData; -import mage.client.dialog.PreferencesDialog; import mage.client.plugins.adapters.MageActionCallback; import mage.client.plugins.impl.Plugins; -import mage.client.util.ImageCaches; -import mage.client.util.ImageHelper; import mage.client.util.audio.AudioManager; -import mage.components.ImagePanel; -import mage.constants.AbilityType; import mage.constants.CardType; import mage.constants.EnlargeMode; -import mage.utils.CardUtil; import mage.view.AbilityView; import mage.view.CardView; -import mage.view.CounterView; import mage.view.PermanentView; import mage.view.StackAbilityView; -import net.java.truevfs.access.TFile; import org.apache.log4j.Logger; -import org.jdesktop.swingx.graphics.GraphicsUtilities; -import static org.mage.plugins.card.constants.Constants.THUMBNAIL_SIZE_FULL; -import org.mage.plugins.card.dl.sources.DirectLinksForDownload; -import org.mage.plugins.card.images.ImageCache; import org.mage.plugins.card.utils.impl.ImageManagerImpl; /** @@ -68,26 +45,19 @@ import org.mage.plugins.card.utils.impl.ImageManagerImpl; * @author arcane, nantuko, noxx */ @SuppressWarnings({"unchecked", "rawtypes"}) -public class CardPanel extends MagePermanent implements MouseListener, MouseMotionListener, MouseWheelListener, ComponentListener { +public abstract class CardPanel extends MagePermanent implements MouseListener, MouseMotionListener, MouseWheelListener, ComponentListener { private static final long serialVersionUID = -3272134219262184410L; private static final Logger LOGGER = Logger.getLogger(CardPanel.class); - private static final int WIDTH_LIMIT = 90; // card width limit to create smaller counter public static final double TAPPED_ANGLE = Math.PI / 2; public static final double FLIPPED_ANGLE = Math.PI; public static final float ASPECT_RATIO = 3.5f / 2.5f; public static final int POPUP_X_GAP = 1; // prevent tooltip window from blinking - public static CardPanel dragAnimationPanel; - public static final Rectangle CARD_SIZE_FULL = new Rectangle(101, 149); - private static final float ROUNDED_CORNER_SIZE = 0.1f; - private static final float BLACK_BORDER_SIZE = 0.03f; - private static final int TEXT_GLOW_SIZE = 6; - private static final float TEXT_GLOW_INTENSITY = 3f; private static final float ROT_CENTER_TO_TOP_CORNER = 1.0295630140987000315797369464196f; private static final float ROT_CENTER_TO_BOTTOM_CORNER = 0.7071067811865475244008443621048f; @@ -96,52 +66,30 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti // for two faced cards public CardView temporary; - private List links = new ArrayList<>(); public double tappedAngle = 0; public double flippedAngle = 0; - public final ScaledImagePanel imagePanel; - public ImagePanel overlayPanel; + + private final List links = new ArrayList<>(); public JPanel buttonPanel; private JButton dayNightButton; - - public JPanel copyIconPanel; private JButton showCopySourceButton; - public JPanel iconPanel; - private JButton typeButton; - - public JPanel counterPanel; - private JLabel loyaltyCounterLabel; - private JLabel plusCounterLabel; - private JLabel otherCounterLabel; - private JLabel minusCounterLabel; - private int loyaltyCounter; - private int plusCounter; - private int otherCounter; - private int minusCounter; - private int lastCardWidth; - - private GlowText titleText; - private GlowText ptText; private boolean displayEnabled = true; private boolean isAnimationPanel; - public int cardXOffset, cardYOffset, cardWidth, cardHeight; + private int cardXOffset, cardYOffset, cardWidth, cardHeight; private int symbolWidth; private boolean isSelected; - private boolean isPlayable; private boolean isChoosable; - private boolean canAttack; private boolean showCastingCost; - private boolean hasImage = false; private float alpha = 1.0f; private ActionCallback callback; protected boolean tooltipShowing; - protected TextPopup tooltipText = new TextPopup(); + protected TextPopup tooltipText; protected UUID gameId; private TransferData data = new TransferData(); @@ -154,8 +102,6 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti private boolean transformed; private boolean animationInProgress = false; - private boolean displayTitleAnyway; - private JPanel cardArea; private int yTextOffset = 10; @@ -163,142 +109,36 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti // if this is set, it's opened if the user right clicks on the card panel private JPopupMenu popupMenu; - private static Map IMAGE_CACHE; - - private final static class Key { - - final int width; - final int height; - final int cardWidth; - final int cardHeight; - final int cardXOffset; - final int cardYOffset; - final boolean hasImage; - final boolean isSelected; - final boolean isChoosable; - final boolean isPlayable; - final boolean canAttack; - - public Key(int width, int height, int cardWidth, int cardHeight, int cardXOffset, int cardYOffset, boolean hasImage, boolean isSelected, boolean isChoosable, boolean isPlayable, boolean canAttack) { - this.width = width; - this.height = height; - this.cardWidth = cardWidth; - this.cardHeight = cardHeight; - this.cardXOffset = cardXOffset; - this.cardYOffset = cardYOffset; - this.hasImage = hasImage; - this.isSelected = isSelected; - this.isChoosable = isChoosable; - this.isPlayable = isPlayable; - this.canAttack = canAttack; - } - - @Override - public int hashCode() { - int hash = 3; - hash = 19 * hash + this.width; - hash = 19 * hash + this.height; - hash = 19 * hash + this.cardWidth; - hash = 19 * hash + this.cardHeight; - hash = 19 * hash + this.cardXOffset; - hash = 19 * hash + this.cardYOffset; - hash = 19 * hash + (this.hasImage ? 1 : 0); - hash = 19 * hash + (this.isSelected ? 1 : 0); - hash = 19 * hash + (this.isChoosable ? 1 : 0); - hash = 19 * hash + (this.isPlayable ? 1 : 0); - hash = 19 * hash + (this.canAttack ? 1 : 0); - return hash; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Key other = (Key) obj; - if (this.width != other.width) { - return false; - } - if (this.height != other.height) { - return false; - } - if (this.cardWidth != other.cardWidth) { - return false; - } - if (this.cardHeight != other.cardHeight) { - return false; - } - if (this.cardXOffset != other.cardXOffset) { - return false; - } - if (this.cardYOffset != other.cardYOffset) { - return false; - } - if (this.hasImage != other.hasImage) { - return false; - } - if (this.isSelected != other.isSelected) { - return false; - } - if (this.isChoosable != other.isChoosable) { - return false; - } - if (this.isPlayable != other.isPlayable) { - return false; - } - if (this.canAttack != other.canAttack) { - return false; - } - return true; - } - } - - static { - IMAGE_CACHE = ImageCaches.register(new MapMaker().softValues().makeComputingMap(new Function() { - @Override - public BufferedImage apply(Key key) { - return createImage(key); - } - })); - } - public CardPanel(CardView newGameCard, UUID gameId, final boolean loadImage, ActionCallback callback, final boolean foil, Dimension dimension) { + // Store away params this.gameCard = newGameCard; this.callback = callback; this.gameId = gameId; + // Gather info about the card this.isPermanent = this.gameCard instanceof PermanentView; if (isPermanent) { this.hasSickness = ((PermanentView) this.gameCard).hasSummoningSickness(); } + // Set to requested size this.setCardBounds(0, 0, dimension.width, dimension.height); - //for container debug (don't remove) - //setBorder(BorderFactory.createLineBorder(Color.green)); + // Create button panel for Transform and Show Source (copied cards) + buttonPanel = new JPanel(); + buttonPanel.setLayout(null); + buttonPanel.setOpaque(false); + buttonPanel.setVisible(true); + add(buttonPanel); + + // Both card rendering implementations have a transform button if (this.gameCard.canTransform()) { - buttonPanel = new JPanel(); - buttonPanel.setLayout(null); - buttonPanel.setOpaque(false); - add(buttonPanel); - + // Create the day night button dayNightButton = new JButton(""); - dayNightButton.setLocation(2, 2); - dayNightButton.setSize(25, 25); - - buttonPanel.setVisible(true); - + dayNightButton.setSize(32, 32); + dayNightButton.setToolTipText("This permanent is a double faced card. To see the back face card, push this button or turn mouse wheel down while hovering with the mouse pointer over the permanent."); BufferedImage day = ImageManagerImpl.getInstance().getDayImage(); dayNightButton.setIcon(new ImageIcon(day)); - - buttonPanel.add(dayNightButton); - dayNightButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -311,60 +151,19 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti Animation.transformCard(CardPanel.this, CardPanel.this, true); } }); - } - if (!newGameCard.isAbility()) { - // panel to show counters on the card - counterPanel = new JPanel(); - counterPanel.setLayout(null); - counterPanel.setOpaque(false); - add(counterPanel); - plusCounterLabel = new JLabel(""); - plusCounterLabel.setToolTipText("+1/+1"); - counterPanel.add(plusCounterLabel); - - minusCounterLabel = new JLabel(""); - minusCounterLabel.setToolTipText("-1/-1"); - counterPanel.add(minusCounterLabel); - - loyaltyCounterLabel = new JLabel(""); - loyaltyCounterLabel.setToolTipText("loyalty"); - counterPanel.add(loyaltyCounterLabel); - - otherCounterLabel = new JLabel(""); - counterPanel.add(otherCounterLabel); - - counterPanel.setVisible(false); - } - if (newGameCard.isAbility()) { - if (AbilityType.TRIGGERED.equals(newGameCard.getAbilityType())) { - setTypeIcon(ImageManagerImpl.getInstance().getTriggeredAbilityImage(), "Triggered Ability"); - } else if (AbilityType.ACTIVATED.equals(newGameCard.getAbilityType())) { - setTypeIcon(ImageManagerImpl.getInstance().getActivatedAbilityImage(), "Activated Ability"); - } + // Add it + buttonPanel.add(dayNightButton); } - if (this.gameCard.isToken()) { - setTypeIcon(ImageManagerImpl.getInstance().getTokenIconImage(), "Token Permanent"); - } - - // icon to inform about permanent is copying something + // Both card rendering implementations have a view copy source button if (this.gameCard instanceof PermanentView) { - copyIconPanel = new JPanel(); - copyIconPanel.setLayout(null); - copyIconPanel.setOpaque(false); - add(copyIconPanel); - + // Create the show source button showCopySourceButton = new JButton(""); - showCopySourceButton.setLocation(2, 2); - showCopySourceButton.setSize(25, 25); - showCopySourceButton.setToolTipText("This permanent is copying a target. To see original image, push this button or turn mouse wheel down while hovering with the mouse pointer over the permanent."); - copyIconPanel.setVisible(((PermanentView) this.gameCard).isCopy()); - + showCopySourceButton.setSize(32, 32); + showCopySourceButton.setToolTipText("This permanent is copying a target. To see original card, push this button or turn mouse wheel down while hovering with the mouse pointer over the permanent."); + showCopySourceButton.setVisible(((PermanentView) this.gameCard).isCopy()); showCopySourceButton.setIcon(new ImageIcon(ImageManagerImpl.getInstance().getCopyInformIconImage())); - - copyIconPanel.add(showCopySourceButton); - showCopySourceButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -372,83 +171,58 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti ((MageActionCallback) callback).enlargeCard(EnlargeMode.COPY); } }); + + // Add it + buttonPanel.add(showCopySourceButton); } + // JPanel setup setBackground(Color.black); setOpaque(false); + // JPanel event listeners addMouseListener(this); addMouseMotionListener(this); addMouseWheelListener(this); addComponentListener(this); - displayTitleAnyway = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SHOW_CARD_NAMES, "true").equals("true"); - - titleText = new GlowText(); - setText(gameCard); -// int fontSize = (int) cardHeight / 11; -// titleText.setFont(getFont().deriveFont(Font.BOLD, fontSize)); - titleText.setForeground(Color.white); - titleText.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY); - titleText.setWrap(true); - add(titleText); - - ptText = new GlowText(); - if (CardUtil.isCreature(gameCard)) { - ptText.setText(gameCard.getPower() + "/" + gameCard.getToughness()); - } else if (CardUtil.isPlaneswalker(gameCard)) { - ptText.setText(gameCard.getLoyalty()); - } -// ptText.setFont(getFont().deriveFont(Font.BOLD, fontSize)); - ptText.setForeground(Color.white); - ptText.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY); - add(ptText); - - BufferedImage sickness = ImageManagerImpl.getInstance().getSicknessImage(); - overlayPanel = new ImagePanel(sickness, ImagePanel.SCALED); - overlayPanel.setOpaque(false); - add(overlayPanel); - - imagePanel = new ScaledImagePanel(); - imagePanel.setBorder(BorderFactory.createLineBorder(Color.white)); - add(imagePanel); - + // Tooltip for card details hover String cardType = getType(newGameCard); + tooltipText = new TextPopup(); tooltipText.setText(getText(cardType, newGameCard)); + // Animation setup tappedAngle = isTapped() ? CardPanel.TAPPED_ANGLE : 0; flippedAngle = isFlipped() ? CardPanel.FLIPPED_ANGLE : 0; + } - if (!loadImage) { - return; + @Override + public void doLayout() { + // Position transform and show source buttons + buttonPanel.setLocation(cardXOffset, cardYOffset); + buttonPanel.setSize(cardWidth, cardHeight); + int x = cardWidth / 20; + int y = cardHeight / 10; + if (dayNightButton != null) { + dayNightButton.setLocation(x, y); + y += 25; + y += 5; } + if (showCopySourceButton != null) { + showCopySourceButton.setLocation(x, y); + } + } + public final void initialDraw() { + // Kick off if (gameCard.isTransformed()) { // this calls updateImage toggleTransformed(); } else { - updateImage(); + updateArtImage(); } } - private void setTypeIcon(BufferedImage bufferedImage, String toolTipText) { - iconPanel = new JPanel(); - iconPanel.setLayout(null); - iconPanel.setOpaque(false); - add(iconPanel); - - typeButton = new JButton(""); - typeButton.setLocation(2, 2); - typeButton.setSize(25, 25); - - iconPanel.setVisible(true); - typeButton.setIcon(new ImageIcon(bufferedImage)); - if (toolTipText != null) { - typeButton.setToolTipText(toolTipText); - } - iconPanel.add(typeButton); - } - public void cleanUp() { if (dayNightButton != null) { for (ActionListener al : dayNightButton.getActionListeners()) { @@ -467,32 +241,12 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti // this holds reference to ActionCallback forever so set it to null to prevent this.callback = null; this.data = null; - this.counterPanel = null; } - private void setText(CardView card) { - titleText.setText(!displayTitleAnyway && hasImage ? "" : card.getName()); - } - - private void setImage(BufferedImage srcImage) { - synchronized (imagePanel) { - if (srcImage != null) { - imagePanel.setImage(srcImage); - } else { - imagePanel.clearImage(); - } - repaint(); - } - doLayout(); - } - - public void setImage(final CardPanel panel) { - synchronized (panel.imagePanel) { - if (panel.imagePanel.hasImage()) { - setImage(panel.imagePanel.getSrcImage()); - } - } - } + // Copy the graphical resources of another CardPanel over to this one, + // if possible (may not be possible if they have different implementations) + // Used when cards are moving between zones + public abstract void transferResources(CardPanel panel); @Override public void setZone(String zone) { @@ -516,16 +270,22 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti this.isAnimationPanel = isAnimationPanel; } + public boolean isAnimationPanel() { + return this.isAnimationPanel; + } + @Override public void setSelected(boolean isSelected) { this.isSelected = isSelected; - if (isSelected) { - this.titleText.setGlowColor(Color.green); - } else { - this.titleText.setGlowColor(Color.black); - } - // noxx: bad idea is to call repaint in setter method - ////repaint(); + } + + public boolean isSelected() { + return this.isSelected; + } + + @Override + public List getLinks() { + return links; } @Override @@ -533,19 +293,36 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti this.isChoosable = isChoosable; } + public boolean isChoosable() { + return this.isChoosable; + } + + public boolean hasSickness() { + return this.hasSickness; + } + + public boolean isPermanent() { + return this.isPermanent; + } + @Override public void setCardAreaRef(JPanel cardArea) { this.cardArea = cardArea; } - public boolean getSelected() { - return this.isSelected; - } - public void setShowCastingCost(boolean showCastingCost) { this.showCastingCost = showCastingCost; } + public boolean getShowCastingCost() { + return this.showCastingCost; + } + + /** + * Overridden by different card rendering styles + */ + protected abstract void paintCard(Graphics2D g); + @Override public void paint(Graphics g) { if (!displayEnabled) { @@ -573,164 +350,20 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti protected void paintComponent(Graphics g) { Graphics2D g2d = (Graphics2D) (g.create()); - if (alpha != 1.0f) { - AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha); - g2d.setComposite(composite); - } + // Deferr to subclasses + paintCard(g2d); - g2d.drawImage(IMAGE_CACHE.get(new Key(getWidth(), getHeight(), cardWidth, cardHeight, cardXOffset, cardYOffset, hasImage, isSelected, isChoosable, isPlayable, canAttack)), 0, 0, null); + // Done, dispose of the context g2d.dispose(); } - private static BufferedImage createImage(Key key) { - int cardWidth = key.cardWidth; - int cardHeight = key.cardHeight; - int cardXOffset = key.cardXOffset; - int cardYOffset = key.cardYOffset; - - BufferedImage image = GraphicsUtilities.createCompatibleTranslucentImage(key.width, key.height); - Graphics2D g2d = image.createGraphics(); - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - - if (!key.hasImage) { - g2d.setColor(new Color(30, 200, 200, 120)); - } else { - g2d.setColor(new Color(0, 0, 0, 0)); - } - - int cornerSize = Math.max(4, Math.round(cardWidth * ROUNDED_CORNER_SIZE)); - g2d.fillRoundRect(cardXOffset, cardYOffset, cardWidth, cardHeight, cornerSize, cornerSize); - - if (key.isSelected) { - g2d.setColor(Color.green); - g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize); - } else if (key.isChoosable) { - g2d.setColor(new Color(250, 250, 0, 230)); - g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize); - } else if (key.isPlayable) { - g2d.setColor(new Color(153, 102, 204, 200)); - //g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize); - g2d.fillRoundRect(cardXOffset, cardYOffset, cardWidth, cardHeight, cornerSize, cornerSize); - } - - if (key.canAttack) { - g2d.setColor(new Color(0, 0, 255, 230)); - g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize); - } - - //TODO:uncomment - /* - if (gameCard.isAttacking()) { - g2d.setColor(new Color(200,10,10,200)); - g2d.fillRoundRect(cardXOffset+1, cardYOffset+1, cardWidth-2, cardHeight-2, cornerSize, cornerSize); - }*/ - g2d.dispose(); - - return image; - } - - @Override - protected void paintChildren(Graphics g) { - super.paintChildren(g); - - if (showCastingCost && !isAnimationPanel && cardWidth < 200 && cardWidth > 60) { - String manaCost = ManaSymbols.getStringManaCost(gameCard.getManaCost()); - int width = getWidth(manaCost); - if (hasImage) { - ManaSymbols.draw(g, manaCost, cardXOffset + cardWidth - width - 5, cardYOffset + 5, symbolWidth); - } else { - ManaSymbols.draw(g, manaCost, cardXOffset + 8, cardHeight - 9, symbolWidth); - } - } - } - - private int getWidth(String manaCost) { - int width = 0; - manaCost = manaCost.replace("\\", ""); - StringTokenizer tok = new StringTokenizer(manaCost, " "); - while (tok.hasMoreTokens()) { - tok.nextToken(); - width += symbolWidth; - } - return width; - } - - @Override - public void doLayout() { - int borderSize = Math.round(cardWidth * BLACK_BORDER_SIZE); - imagePanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize); - imagePanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2); - - if (hasSickness && CardUtil.isCreature(gameCard) && isPermanent) { - overlayPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize); - overlayPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2); - } else { - overlayPanel.setVisible(false); - } - - if (buttonPanel != null) { - buttonPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize); - buttonPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2); - dayNightButton.setLocation(0, cardHeight - 30); - } - if (iconPanel != null) { - iconPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize); - iconPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2); - } - if (copyIconPanel != null) { - copyIconPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize); - copyIconPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2); - } - if (counterPanel != null) { - counterPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize); - counterPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2); - int size = cardWidth > WIDTH_LIMIT ? 40 : 20; - - minusCounterLabel.setLocation(counterPanel.getWidth() - size, counterPanel.getHeight() - size * 2); - minusCounterLabel.setSize(size, size); - - plusCounterLabel.setLocation(5, counterPanel.getHeight() - size * 2); - plusCounterLabel.setSize(size, size); - - loyaltyCounterLabel.setLocation(counterPanel.getWidth() - size, counterPanel.getHeight() - size); - loyaltyCounterLabel.setSize(size, size); - - otherCounterLabel.setLocation(5, counterPanel.getHeight() - size); - otherCounterLabel.setSize(size, size); - - } - int fontHeight = Math.round(cardHeight * (27f / 680)); - boolean showText = (!isAnimationPanel && fontHeight < 12); - titleText.setVisible(showText); - ptText.setVisible(showText); - - if (showText) { - int fontSize = (int) cardHeight / 11; - titleText.setFont(getFont().deriveFont(Font.BOLD, fontSize)); - - int titleX = Math.round(cardWidth * (20f / 480)); - int titleY = Math.round(cardHeight * (9f / 680)) + yTextOffset; - titleText.setBounds(cardXOffset + titleX, cardYOffset + titleY, cardWidth - titleX, cardHeight - titleY); - - ptText.setFont(getFont().deriveFont(Font.BOLD, fontSize)); - Dimension ptSize = ptText.getPreferredSize(); - ptText.setSize(ptSize.width, ptSize.height); - int ptX = Math.round(cardWidth * (420f / 480)) - ptSize.width / 2; - int ptY = Math.round(cardHeight * (675f / 680)) - ptSize.height; - - int offsetX = Math.round((CARD_SIZE_FULL.width - cardWidth) / 10.0f); - - ptText.setLocation(cardXOffset + ptX - TEXT_GLOW_SIZE / 2 - offsetX, cardYOffset + ptY - TEXT_GLOW_SIZE / 2); - } - } - @Override public String toString() { return gameCard.toString(); } @Override - public final void setCardBounds(int x, int y, int cardWidth, int cardHeight) { + public void setCardBounds(int x, int y, int cardWidth, int cardHeight) { if (cardWidth == this.cardWidth && cardHeight == this.cardHeight) { setBounds(x - cardXOffset, y - cardYOffset, getWidth(), getHeight()); return; @@ -752,15 +385,12 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti int height = -yOffset + rotCenterY + rotCenterToBottomCorner; setBounds(x + xOffset, y + yOffset, width, height); } else { - cardXOffset = 5; - cardYOffset = 5; + cardXOffset = 0; + cardYOffset = 0; int width = cardXOffset * 2 + cardWidth; int height = cardYOffset * 2 + cardHeight; setBounds(x - cardXOffset, y - cardYOffset, width, height); } - if (imagePanel != null && imagePanel.getSrcImage() != null) { - updateImage(); - } } public int getXOffset(int cardWidth) { @@ -774,7 +404,7 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti } } - public int getYOffset(int cardWidth, int cardHeight) { + public final int getYOffset(int cardWidth, int cardHeight) { if (this.isPermanent) { int rotCenterX = Math.round(cardWidth / 2f); int rotCenterY = cardHeight - rotCenterX; @@ -787,120 +417,57 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti } - public int getCardX() { + public final int getCardX() { return getX() + cardXOffset; } - public int getCardY() { + public final int getCardY() { return getY() + cardYOffset; } - public int getCardWidth() { + public final int getCardWidth() { return cardWidth; } - public int getCardHeight() { + public final int getCardHeight() { return cardHeight; } - public Point getCardLocation() { + public final int getSymbolWidth() { + return symbolWidth; + } + + public final Point getCardLocation() { Point p = getLocation(); p.x += cardXOffset; p.y += cardYOffset; return p; } - public CardView getCard() { + public final CardView getCard() { return this.gameCard; } @Override public void setAlpha(float alpha) { this.alpha = alpha; - if (alpha == 0) { - this.ptText.setVisible(false); - this.titleText.setVisible(false); - } else if (alpha == 1.0f) { - this.ptText.setVisible(true); - this.titleText.setVisible(true); - } } @Override - public float getAlpha() { + public final float getAlpha() { return alpha; } - public int getCardXOffset() { + public final int getCardXOffset() { return cardXOffset; } - public int getCardYOffset() { + public final int getCardYOffset() { return cardYOffset; } - private int updateImageStamp; - @Override - public void updateImage() { - tappedAngle = isTapped() ? CardPanel.TAPPED_ANGLE : 0; - flippedAngle = isFlipped() ? CardPanel.FLIPPED_ANGLE : 0; - - //final CardView gameCard = this.gameCard; - final int stamp = ++updateImageStamp; - - Util.threadPool.submit(new Runnable() { - @Override - public void run() { - try { - final BufferedImage srcImage; - if (gameCard.isFaceDown()) { - srcImage = getFaceDownImage(); - } else if (cardWidth > THUMBNAIL_SIZE_FULL.width) { - srcImage = ImageCache.getImage(gameCard, cardWidth, cardHeight); - } else { - srcImage = ImageCache.getThumbnail(gameCard); - } - UI.invokeLater(new Runnable() { - @Override - public void run() { - if (stamp == updateImageStamp) { - hasImage = srcImage != null; - setText(gameCard); - setImage(srcImage); - } - } - }); - } catch (Exception e) { - e.printStackTrace(); - } catch (Error err) { - err.printStackTrace(); - } - } - }); - } - - private BufferedImage getFaceDownImage() { - if (isPermanent) { - if (((PermanentView) gameCard).isMorphed()) { - return ImageCache.getMorphImage(); - } else { - return ImageCache.getManifestImage(); - } - } else if (this.gameCard instanceof StackAbilityView) { - return ImageCache.getMorphImage(); - } else { - return ImageCache.loadImage(new TFile(DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename)); - } - } - - @Override - public List getLinks() { - return links; - } - - @Override - public boolean isTapped() { + public final boolean isTapped() { if (isPermanent) { return ((PermanentView) gameCard).isTapped(); } @@ -908,7 +475,7 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti } @Override - public boolean isFlipped() { + public final boolean isFlipped() { if (isPermanent) { return ((PermanentView) gameCard).isFlipped(); } @@ -916,17 +483,16 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti } @Override - public boolean isTransformed() { + public final boolean isTransformed() { if (isPermanent) { - return gameCard.isTransformed(); + if (gameCard.isTransformed()) { + return !this.transformed; + } else { + return this.transformed; + } + } else { + return this.transformed; } - return false; - } - - @Override - public void showCardTitle() { - displayTitleAnyway = true; - setText(gameCard); } @Override @@ -939,9 +505,17 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti animationInProgress = false; } + /** + * Inheriting classes should implement update(CardView card) by using this. + * However, they should ALSO call repaint() after the superclass call to + * this function, that can't be done here as the overriders may need to do + * things both before and after this call before repainting. + */ @Override public void update(CardView card) { this.updateCard = card; + + // Animation update if (isPermanent && (card instanceof PermanentView)) { boolean needsTapping = isTapped() != ((PermanentView) card).isTapped(); boolean needsFlipping = isFlipped() != ((PermanentView) card).isFlipped(); @@ -956,140 +530,39 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti Animation.transformCard(this, this, card.isTransformed()); } } - if (card.canTransform()) { - dayNightButton.setVisible(!isPermanent); - } - if (CardUtil.isCreature(card) && CardUtil.isPlaneswalker(card)) { - ptText.setText(card.getPower() + "/" + card.getToughness() + " (" + card.getLoyalty() + ")"); - } else if (CardUtil.isCreature(card)) { - ptText.setText(card.getPower() + "/" + card.getToughness()); - } else if (CardUtil.isPlaneswalker(card)) { - ptText.setText(card.getLoyalty()); - } else { - ptText.setText(""); - } - setText(card); - - this.isPlayable = card.isPlayable(); + // Update panel attributes this.isChoosable = card.isChoosable(); - this.canAttack = card.isCanAttack(); this.isSelected = card.isSelected(); - boolean updateImage = !gameCard.getName().equals(card.getName()) || gameCard.isFaceDown() != card.isFaceDown(); // update after e.g. turning a night/day card - if (updateImage && gameCard.canTransform() && card.canTransform() && transformed) { - if (card.getSecondCardFace() != null && card.getSecondCardFace().getName().equals(gameCard.getName())) { - transformed = false; - } - } + // Update art? + boolean mustUpdateArt + = (!gameCard.getName().equals(card.getName())) + || (gameCard.isFaceDown() != card.isFaceDown()); + + // Set the new card this.gameCard = card; + // Update tooltip text String cardType = getType(card); tooltipText.setText(getText(cardType, card)); - if (hasSickness && CardUtil.isCreature(gameCard) && isPermanent) { - overlayPanel.setVisible(true); - } else { - overlayPanel.setVisible(false); + // Update the image + if (mustUpdateArt) { + updateArtImage(); } - if (updateImage) { - updateImage(); - if (card.canTransform()) { - BufferedImage transformIcon; - if (transformed || card.isTransformed()) { - transformIcon = ImageManagerImpl.getInstance().getNightImage(); - } else { - transformIcon = ImageManagerImpl.getInstance().getDayImage(); - } - dayNightButton.setIcon(new ImageIcon(transformIcon)); + + // Update transform circle + if (card.canTransform()) { + BufferedImage transformIcon; + if (isTransformed() || card.isTransformed()) { + transformIcon = ImageManagerImpl.getInstance().getNightImage(); + } else { + transformIcon = ImageManagerImpl.getInstance().getDayImage(); } + dayNightButton.setVisible(!isPermanent); + dayNightButton.setIcon(new ImageIcon(transformIcon)); } - - if (counterPanel != null) { - updateCounters(card); - } - - repaint(); - } - - private void updateCounters(CardView card) { - if (card.getCounters() != null && !card.getCounters().isEmpty()) { - String name = ""; - if (lastCardWidth != cardWidth) { - lastCardWidth = cardWidth; - plusCounter = 0; - minusCounter = 0; - otherCounter = 0; - loyaltyCounter = 0; - } - plusCounterLabel.setVisible(false); - minusCounterLabel.setVisible(false); - loyaltyCounterLabel.setVisible(false); - otherCounterLabel.setVisible(false); - for (CounterView counterView : card.getCounters()) { - if (counterView.getCount() == 0) { - continue; - } - switch (counterView.getName()) { - case "+1/+1": - if (counterView.getCount() != plusCounter) { - plusCounter = counterView.getCount(); - plusCounterLabel.setIcon(getCounterImageWithAmount(plusCounter, ImageManagerImpl.getInstance().getCounterImageGreen(), cardWidth)); - } - plusCounterLabel.setVisible(true); - break; - case "-1/-1": - if (counterView.getCount() != minusCounter) { - minusCounter = counterView.getCount(); - minusCounterLabel.setIcon(getCounterImageWithAmount(minusCounter, ImageManagerImpl.getInstance().getCounterImageRed(), cardWidth)); - } - minusCounterLabel.setVisible(true); - break; - case "loyalty": - if (counterView.getCount() != loyaltyCounter) { - loyaltyCounter = counterView.getCount(); - loyaltyCounterLabel.setIcon(getCounterImageWithAmount(loyaltyCounter, ImageManagerImpl.getInstance().getCounterImageViolet(), cardWidth)); - } - loyaltyCounterLabel.setVisible(true); - break; - default: - if (name.isEmpty()) { // only first other counter is shown - name = counterView.getName(); - otherCounter = counterView.getCount(); - otherCounterLabel.setToolTipText(name); - otherCounterLabel.setIcon(getCounterImageWithAmount(otherCounter, ImageManagerImpl.getInstance().getCounterImageGrey(), cardWidth)); - otherCounterLabel.setVisible(true); - } - } - } - - counterPanel.setVisible(true); - } else { - plusCounterLabel.setVisible(false); - minusCounterLabel.setVisible(false); - loyaltyCounterLabel.setVisible(false); - otherCounterLabel.setVisible(false); - counterPanel.setVisible(false); - } - - } - - private static ImageIcon getCounterImageWithAmount(int amount, BufferedImage image, int cardWidth) { - int factor = cardWidth > WIDTH_LIMIT ? 2 : 1; - int xOffset = amount > 9 ? 2 : 5; - int fontSize = factor == 1 ? amount < 10 ? 12 : amount < 100 ? 10 : amount < 1000 ? 7 : 6 - : amount < 10 ? 19 : amount < 100 ? 15 : amount < 1000 ? 12 : amount < 10000 ? 9 : 8; - BufferedImage newImage; - if (cardWidth > WIDTH_LIMIT) { - newImage = ImageManagerImpl.deepCopy(image); - } else { - newImage = ImageHelper.getResizedImage(image, 20, 20); - } - Graphics graphics = newImage.getGraphics(); - graphics.setColor(Color.BLACK); - graphics.setFont(new Font("Arial Black", amount > 100 ? Font.PLAIN : Font.BOLD, fontSize)); - graphics.drawString(Integer.toString(amount), xOffset * factor, 11 * factor); - return new ImageIcon(newImage); } @Override @@ -1118,18 +591,6 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti return this.gameCard; } - @Override - public Image getImage() { - if (this.hasImage) { - if (gameCard.isFaceDown()) { - return getFaceDownImage(); - } else { - return ImageCache.getImageOriginal(gameCard); - } - } - return null; - } - @Override public void mouseClicked(MouseEvent e) { } @@ -1276,7 +737,7 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti @Override public void update(PermanentView card) { this.hasSickness = card.hasSummoningSickness(); - this.copyIconPanel.setVisible(card.isCopy()); + this.showCopySourceButton.setVisible(card.isCopy()); update((CardView) card); } @@ -1327,7 +788,7 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti String temp = this.gameCard.getAlternateName(); this.gameCard.setAlternateName(this.gameCard.getOriginalName()); this.gameCard.setOriginalName(temp); - updateImage(); + updateArtImage(); } @Override @@ -1371,6 +832,10 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti yTextOffset = yOffset; } + public int getTextOffset() { + return yTextOffset; + } + @Override public JPopupMenu getPopupMenu() { return popupMenu; diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelAttributes.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelAttributes.java new file mode 100644 index 0000000000..9382cb9a52 --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelAttributes.java @@ -0,0 +1,25 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.mage.card.arcane; + +/** + * @author stravant@gmail.com + * Attributes of a card panel outside of the CardView itself that the renderer + * needs to know in order to render a card. + */ +public class CardPanelAttributes { + public final int cardWidth; + public final int cardHeight; + public final boolean isSelected; + public final boolean isChoosable; + + public CardPanelAttributes(int cardWidth, int cardHeight, boolean isChoosable, boolean isSelected) { + this.cardWidth = cardWidth; + this.cardHeight = cardHeight; + this.isChoosable = isChoosable; + this.isSelected = isSelected; + } +} diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelComponentImpl.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelComponentImpl.java new file mode 100644 index 0000000000..549242710c --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelComponentImpl.java @@ -0,0 +1,711 @@ +package org.mage.card.arcane; + +import com.google.common.base.Function; +import com.google.common.collect.MapMaker; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.io.File; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.UUID; +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import mage.cards.action.ActionCallback; +import mage.client.dialog.PreferencesDialog; +import mage.client.util.ImageCaches; +import mage.client.util.ImageHelper; +import mage.components.ImagePanel; +import mage.constants.AbilityType; +import mage.utils.CardUtil; +import mage.view.CardView; +import mage.view.CounterView; +import mage.view.PermanentView; +import mage.view.StackAbilityView; +import net.java.truevfs.access.TFile; +import org.apache.log4j.Logger; +import org.jdesktop.swingx.graphics.GraphicsUtilities; +import static org.mage.plugins.card.constants.Constants.THUMBNAIL_SIZE_FULL; +import org.mage.plugins.card.dl.sources.DirectLinksForDownload; +import org.mage.plugins.card.images.ImageCache; +import org.mage.plugins.card.utils.impl.ImageManagerImpl; + +/** + * Class for drawing the mage card object by using a form based JComponent approach + * + * @author arcane, nantuko, noxx, stravant + */ +@SuppressWarnings({"unchecked", "rawtypes"}) +public class CardPanelComponentImpl extends CardPanel { + + private static final long serialVersionUID = -3272134219262184411L; + + private static final Logger LOGGER = Logger.getLogger(CardPanelComponentImpl.class); + + private static final int WIDTH_LIMIT = 90; // card width limit to create smaller counter + + private static final float ROUNDED_CORNER_SIZE = 0.1f; + private static final float BLACK_BORDER_SIZE = 0.03f; + private static final int TEXT_GLOW_SIZE = 6; + private static final float TEXT_GLOW_INTENSITY = 3f; + + public final ScaledImagePanel imagePanel; + public ImagePanel overlayPanel; + + public JPanel iconPanel; + private JButton typeButton; + + public JPanel counterPanel; + private JLabel loyaltyCounterLabel; + private JLabel plusCounterLabel; + private JLabel otherCounterLabel; + private JLabel minusCounterLabel; + private int loyaltyCounter; + private int plusCounter; + private int otherCounter; + private int minusCounter; + private int lastCardWidth; + + private final GlowText titleText; + private final GlowText ptText; + + private boolean hasImage = false; + + private boolean displayTitleAnyway; + + private final static Map IMAGE_CACHE; + + class Key { + + final int width; + final int height; + final int cardWidth; + final int cardHeight; + final int cardXOffset; + final int cardYOffset; + final boolean hasImage; + final boolean isSelected; + final boolean isChoosable; + final boolean isPlayable; + final boolean canAttack; + + public Key(int width, int height, int cardWidth, int cardHeight, int cardXOffset, int cardYOffset, boolean hasImage, boolean isSelected, boolean isChoosable, boolean isPlayable, boolean canAttack) { + this.width = width; + this.height = height; + this.cardWidth = cardWidth; + this.cardHeight = cardHeight; + this.cardXOffset = cardXOffset; + this.cardYOffset = cardYOffset; + this.hasImage = hasImage; + this.isSelected = isSelected; + this.isChoosable = isChoosable; + this.isPlayable = isPlayable; + this.canAttack = canAttack; + } + + @Override + public int hashCode() { + int hash = 3; + hash = 19 * hash + this.width; + hash = 19 * hash + this.height; + hash = 19 * hash + this.cardWidth; + hash = 19 * hash + this.cardHeight; + hash = 19 * hash + this.cardXOffset; + hash = 19 * hash + this.cardYOffset; + hash = 19 * hash + (this.hasImage ? 1 : 0); + hash = 19 * hash + (this.isSelected ? 1 : 0); + hash = 19 * hash + (this.isChoosable ? 1 : 0); + hash = 19 * hash + (this.isPlayable ? 1 : 0); + hash = 19 * hash + (this.canAttack ? 1 : 0); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Key other = (Key) obj; + if (this.width != other.width) { + return false; + } + if (this.height != other.height) { + return false; + } + if (this.cardWidth != other.cardWidth) { + return false; + } + if (this.cardHeight != other.cardHeight) { + return false; + } + if (this.cardXOffset != other.cardXOffset) { + return false; + } + if (this.cardYOffset != other.cardYOffset) { + return false; + } + if (this.hasImage != other.hasImage) { + return false; + } + if (this.isSelected != other.isSelected) { + return false; + } + if (this.isChoosable != other.isChoosable) { + return false; + } + if (this.isPlayable != other.isPlayable) { + return false; + } + if (this.canAttack != other.canAttack) { + return false; + } + return true; + } + } + + static { + IMAGE_CACHE = ImageCaches.register(new MapMaker().softValues().makeComputingMap(new Function() { + @Override + public BufferedImage apply(Key key) { + return createImage(key); + } + })); + } + + public CardPanelComponentImpl(CardView newGameCard, UUID gameId, final boolean loadImage, ActionCallback callback, final boolean foil, Dimension dimension) { + // Call to super + super(newGameCard, gameId, loadImage, callback, foil, dimension); + + // Counter panel + if (!newGameCard.isAbility()) { + // panel to show counters on the card + counterPanel = new JPanel(); + counterPanel.setLayout(null); + counterPanel.setOpaque(false); + add(counterPanel); + + plusCounterLabel = new JLabel(""); + plusCounterLabel.setToolTipText("+1/+1"); + counterPanel.add(plusCounterLabel); + + minusCounterLabel = new JLabel(""); + minusCounterLabel.setToolTipText("-1/-1"); + counterPanel.add(minusCounterLabel); + + loyaltyCounterLabel = new JLabel(""); + loyaltyCounterLabel.setToolTipText("loyalty"); + counterPanel.add(loyaltyCounterLabel); + + otherCounterLabel = new JLabel(""); + counterPanel.add(otherCounterLabel); + + counterPanel.setVisible(false); + } + + // Ability icon + if (newGameCard.isAbility()) { + if (AbilityType.TRIGGERED.equals(newGameCard.getAbilityType())) { + setTypeIcon(ImageManagerImpl.getInstance().getTriggeredAbilityImage(), "Triggered Ability"); + } else if (AbilityType.ACTIVATED.equals(newGameCard.getAbilityType())) { + setTypeIcon(ImageManagerImpl.getInstance().getActivatedAbilityImage(), "Activated Ability"); + } + } + + // Token icon + if (this.gameCard.isToken()) { + setTypeIcon(ImageManagerImpl.getInstance().getTokenIconImage(), "Token Permanent"); + } + + displayTitleAnyway = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SHOW_CARD_NAMES, "true").equals("true"); + + // Title Text + titleText = new GlowText(); + setText(gameCard); +// int fontSize = (int) cardHeight / 11; +// titleText.setFont(getFont().deriveFont(Font.BOLD, fontSize)); + titleText.setForeground(Color.white); + titleText.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY); + titleText.setWrap(true); + add(titleText); + + // PT Text + ptText = new GlowText(); + if (CardUtil.isCreature(gameCard)) { + ptText.setText(gameCard.getPower() + "/" + gameCard.getToughness()); + } else if (CardUtil.isPlaneswalker(gameCard)) { + ptText.setText(gameCard.getLoyalty()); + } +// ptText.setFont(getFont().deriveFont(Font.BOLD, fontSize)); + ptText.setForeground(Color.white); + ptText.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY); + add(ptText); + + // Sickness overlay + BufferedImage sickness = ImageManagerImpl.getInstance().getSicknessImage(); + overlayPanel = new ImagePanel(sickness, ImagePanel.SCALED); + overlayPanel.setOpaque(false); + add(overlayPanel); + + // Imagel panel + imagePanel = new ScaledImagePanel(); + imagePanel.setBorder(BorderFactory.createLineBorder(Color.white)); + add(imagePanel); + + // Do we need to load? + if (loadImage) { + initialDraw(); + } else { + // Nothing to do + } + } + + private void setTypeIcon(BufferedImage bufferedImage, String toolTipText) { + iconPanel = new JPanel(); + iconPanel.setLayout(null); + iconPanel.setOpaque(false); + add(iconPanel); + + typeButton = new JButton(""); + typeButton.setLocation(2, 2); + typeButton.setSize(25, 25); + + iconPanel.setVisible(true); + typeButton.setIcon(new ImageIcon(bufferedImage)); + if (toolTipText != null) { + typeButton.setToolTipText(toolTipText); + } + iconPanel.add(typeButton); + } + + @Override + public void cleanUp() { + super.cleanUp(); + this.counterPanel = null; + } + + private void setText(CardView card) { + titleText.setText(!displayTitleAnyway && hasImage ? "" : card.getName()); + } + + private void setImage(BufferedImage srcImage) { + synchronized (imagePanel) { + if (srcImage != null) { + imagePanel.setImage(srcImage); + } else { + imagePanel.clearImage(); + } + repaint(); + } + doLayout(); + } + + @Override + public void transferResources(final CardPanel panelAbstract) { + if (panelAbstract instanceof CardPanelComponentImpl) { + CardPanelComponentImpl panel = (CardPanelComponentImpl)panelAbstract; + synchronized (panel.imagePanel) { + if (panel.imagePanel.hasImage()) { + setImage(panel.imagePanel.getSrcImage()); + } + } + } + } + + @Override + public void setSelected(boolean isSelected) { + super.setSelected(isSelected); + if (isSelected) { + this.titleText.setGlowColor(Color.green); + } else { + this.titleText.setGlowColor(Color.black); + } + } + + @Override + protected void paintCard(Graphics2D g2d) { + float alpha = getAlpha(); + if (alpha != 1.0f) { + AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha); + g2d.setComposite(composite); + } + + g2d.drawImage( + IMAGE_CACHE.get( + new Key(getWidth(), getHeight(), getCardWidth(), getCardHeight(), getCardXOffset(), getCardYOffset(), + hasImage, isSelected(), isChoosable(), gameCard.isPlayable(), gameCard.isCanAttack())), + 0, 0, null); + g2d.dispose(); + } + + private static BufferedImage createImage(Key key) { + int cardWidth = key.cardWidth; + int cardHeight = key.cardHeight; + int cardXOffset = key.cardXOffset; + int cardYOffset = key.cardYOffset; + + BufferedImage image = GraphicsUtilities.createCompatibleTranslucentImage(key.width, key.height); + Graphics2D g2d = image.createGraphics(); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + if (!key.hasImage) { + g2d.setColor(new Color(30, 200, 200, 120)); + } else { + g2d.setColor(new Color(0, 0, 0, 255)); + } + + int cornerSize = Math.max(4, Math.round(cardWidth * ROUNDED_CORNER_SIZE)); + g2d.fillRoundRect(cardXOffset, cardYOffset, cardWidth, cardHeight, cornerSize, cornerSize); + + if (key.isSelected) { + g2d.setColor(Color.green); + g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize); + } else if (key.isChoosable) { + g2d.setColor(new Color(250, 250, 0, 230)); + g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize); + } else if (key.isPlayable) { + g2d.setColor(new Color(153, 102, 204, 200)); + //g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize); + g2d.fillRoundRect(cardXOffset, cardYOffset, cardWidth, cardHeight, cornerSize, cornerSize); + } + + if (key.canAttack) { + g2d.setColor(new Color(0, 0, 255, 230)); + g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize); + } + + //TODO:uncomment + /* + if (gameCard.isAttacking()) { + g2d.setColor(new Color(200,10,10,200)); + g2d.fillRoundRect(cardXOffset+1, cardYOffset+1, cardWidth-2, cardHeight-2, cornerSize, cornerSize); + }*/ + g2d.dispose(); + + return image; + } + + @Override + protected void paintChildren(Graphics g) { + super.paintChildren(g); + + if (getShowCastingCost() && !isAnimationPanel() && getCardWidth() < 200 && getCardWidth() > 60) { + String manaCost = ManaSymbols.getStringManaCost(gameCard.getManaCost()); + int width = getWidth(manaCost); + if (hasImage) { + ManaSymbols.draw(g, manaCost, getCardXOffset() + getCardWidth() - width - 5, getCardYOffset() + 5, getSymbolWidth()); + } else { + ManaSymbols.draw(g, manaCost, getCardXOffset() + 8, getCardHeight() - 9, getSymbolWidth()); + } + } + } + + private int getWidth(String manaCost) { + int width = 0; + manaCost = manaCost.replace("\\", ""); + StringTokenizer tok = new StringTokenizer(manaCost, " "); + while (tok.hasMoreTokens()) { + tok.nextToken(); + width += getSymbolWidth(); + } + return width; + } + + @Override + public void doLayout() { + super.doLayout(); + + int cardWidth = getCardWidth(); + int cardHeight = getCardHeight(); + int cardXOffset = getCardXOffset(); + int cardYOffset = getCardYOffset(); + int borderSize = Math.round(cardWidth * BLACK_BORDER_SIZE); + imagePanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize); + imagePanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2); + + if (hasSickness() && CardUtil.isCreature(gameCard) && isPermanent()) { + overlayPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize); + overlayPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2); + } else { + overlayPanel.setVisible(false); + } + + if (iconPanel != null) { + iconPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize); + iconPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2); + } + if (counterPanel != null) { + counterPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize); + counterPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2); + int size = cardWidth > WIDTH_LIMIT ? 40 : 20; + + minusCounterLabel.setLocation(counterPanel.getWidth() - size, counterPanel.getHeight() - size * 2); + minusCounterLabel.setSize(size, size); + + plusCounterLabel.setLocation(5, counterPanel.getHeight() - size * 2); + plusCounterLabel.setSize(size, size); + + loyaltyCounterLabel.setLocation(counterPanel.getWidth() - size, counterPanel.getHeight() - size); + loyaltyCounterLabel.setSize(size, size); + + otherCounterLabel.setLocation(5, counterPanel.getHeight() - size); + otherCounterLabel.setSize(size, size); + + } + int fontHeight = Math.round(cardHeight * (27f / 680)); + boolean showText = (!isAnimationPanel() && fontHeight < 12); + titleText.setVisible(showText); + ptText.setVisible(showText); + + if (showText) { + int fontSize = (int) cardHeight / 11; + titleText.setFont(getFont().deriveFont(Font.BOLD, fontSize)); + + int titleX = Math.round(cardWidth * (20f / 480)); + int titleY = Math.round(cardHeight * (9f / 680)) + getTextOffset(); + titleText.setBounds(cardXOffset + titleX, cardYOffset + titleY, cardWidth - titleX, cardHeight - titleY); + + ptText.setFont(getFont().deriveFont(Font.BOLD, fontSize)); + Dimension ptSize = ptText.getPreferredSize(); + ptText.setSize(ptSize.width, ptSize.height); + int ptX = Math.round(cardWidth * (420f / 480)) - ptSize.width / 2; + int ptY = Math.round(cardHeight * (675f / 680)) - ptSize.height; + + int offsetX = Math.round((CARD_SIZE_FULL.width - cardWidth) / 10.0f); + + ptText.setLocation(cardXOffset + ptX - TEXT_GLOW_SIZE / 2 - offsetX, cardYOffset + ptY - TEXT_GLOW_SIZE / 2); + } + } + + @Override + public String toString() { + return gameCard.toString(); + } + + @Override + public void setCardBounds(int x, int y, int cardWidth, int cardHeight) { + // Call to super + super.setCardBounds(x, y, cardWidth, cardHeight); + + // Update image + if (imagePanel != null && imagePanel.getSrcImage() != null) { + updateArtImage(); + } + } + + @Override + public void setAlpha(float alpha) { + super.setAlpha(alpha); + + // Update components + if (alpha == 0) { + this.ptText.setVisible(false); + this.titleText.setVisible(false); + } else if (alpha == 1.0f) { + this.ptText.setVisible(true); + this.titleText.setVisible(true); + } + } + + /////////////////////////////////////////////////////////// + // Image updating code + private int updateArtImageStamp; + + @Override + public void updateArtImage() { + tappedAngle = isTapped() ? CardPanel.TAPPED_ANGLE : 0; + flippedAngle = isFlipped() ? CardPanel.FLIPPED_ANGLE : 0; + + //final CardView gameCard = this.gameCard; + final int stamp = ++updateArtImageStamp; + + Util.threadPool.submit(new Runnable() { + @Override + public void run() { + try { + final BufferedImage srcImage; + if (gameCard.isFaceDown()) { + srcImage = getFaceDownImage(); + } else if (getCardWidth() > THUMBNAIL_SIZE_FULL.width) { + srcImage = ImageCache.getImage(gameCard, getCardWidth(), getCardHeight()); + } else { + srcImage = ImageCache.getThumbnail(gameCard); + } + UI.invokeLater(new Runnable() { + @Override + public void run() { + if (stamp == updateArtImageStamp) { + hasImage = srcImage != null; + setText(gameCard); + setImage(srcImage); + } + } + }); + } catch (Exception e) { + e.printStackTrace(); + } catch (Error err) { + err.printStackTrace(); + } + } + }); + } + + private BufferedImage getFaceDownImage() { + if (isPermanent()) { + if (((PermanentView) gameCard).isMorphed()) { + return ImageCache.getMorphImage(); + } else { + return ImageCache.getManifestImage(); + } + } else if (this.gameCard instanceof StackAbilityView) { + return ImageCache.getMorphImage(); + } else { + return ImageCache.loadImage(new TFile(DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename)); + } + } + + @Override + public void showCardTitle() { + displayTitleAnyway = true; + setText(gameCard); + } + + @Override + public void update(CardView card) { + // Super + super.update(card); + + // Update card text + if (CardUtil.isCreature(card) && CardUtil.isPlaneswalker(card)) { + ptText.setText(card.getPower() + "/" + card.getToughness() + " (" + card.getLoyalty() + ")"); + } else if (CardUtil.isCreature(card)) { + ptText.setText(card.getPower() + "/" + card.getToughness()); + } else if (CardUtil.isPlaneswalker(card)) { + ptText.setText(card.getLoyalty()); + } else { + ptText.setText(""); + } + setText(card); + + // Summoning Sickness overlay + if (hasSickness() && CardUtil.isCreature(gameCard) && isPermanent()) { + overlayPanel.setVisible(true); + } else { + overlayPanel.setVisible(false); + } + + // Update counters panel + if (counterPanel != null) { + updateCounters(card); + } + + // Finally, queue a repaint + repaint(); + } + + private void updateCounters(CardView card) { + if (card.getCounters() != null && !card.getCounters().isEmpty()) { + String name = ""; + if (lastCardWidth != getCardWidth()) { + lastCardWidth = getCardWidth(); + plusCounter = 0; + minusCounter = 0; + otherCounter = 0; + loyaltyCounter = 0; + } + plusCounterLabel.setVisible(false); + minusCounterLabel.setVisible(false); + loyaltyCounterLabel.setVisible(false); + otherCounterLabel.setVisible(false); + for (CounterView counterView : card.getCounters()) { + if (counterView.getCount() == 0) { + continue; + } + switch (counterView.getName()) { + case "+1/+1": + if (counterView.getCount() != plusCounter) { + plusCounter = counterView.getCount(); + plusCounterLabel.setIcon(getCounterImageWithAmount(plusCounter, ImageManagerImpl.getInstance().getCounterImageGreen(), getCardWidth())); + } + plusCounterLabel.setVisible(true); + break; + case "-1/-1": + if (counterView.getCount() != minusCounter) { + minusCounter = counterView.getCount(); + minusCounterLabel.setIcon(getCounterImageWithAmount(minusCounter, ImageManagerImpl.getInstance().getCounterImageRed(), getCardWidth())); + } + minusCounterLabel.setVisible(true); + break; + case "loyalty": + if (counterView.getCount() != loyaltyCounter) { + loyaltyCounter = counterView.getCount(); + loyaltyCounterLabel.setIcon(getCounterImageWithAmount(loyaltyCounter, ImageManagerImpl.getInstance().getCounterImageViolet(), getCardWidth())); + } + loyaltyCounterLabel.setVisible(true); + break; + default: + if (name.isEmpty()) { // only first other counter is shown + name = counterView.getName(); + otherCounter = counterView.getCount(); + otherCounterLabel.setToolTipText(name); + otherCounterLabel.setIcon(getCounterImageWithAmount(otherCounter, ImageManagerImpl.getInstance().getCounterImageGrey(), getCardWidth())); + otherCounterLabel.setVisible(true); + } + } + } + + counterPanel.setVisible(true); + } else { + plusCounterLabel.setVisible(false); + minusCounterLabel.setVisible(false); + loyaltyCounterLabel.setVisible(false); + otherCounterLabel.setVisible(false); + counterPanel.setVisible(false); + } + + } + + private static ImageIcon getCounterImageWithAmount(int amount, BufferedImage image, int cardWidth) { + int factor = cardWidth > WIDTH_LIMIT ? 2 : 1; + int xOffset = amount > 9 ? 2 : 5; + int fontSize = factor == 1 ? amount < 10 ? 12 : amount < 100 ? 10 : amount < 1000 ? 7 : 6 + : amount < 10 ? 19 : amount < 100 ? 15 : amount < 1000 ? 12 : amount < 10000 ? 9 : 8; + BufferedImage newImage; + if (cardWidth > WIDTH_LIMIT) { + newImage = ImageManagerImpl.deepCopy(image); + } else { + newImage = ImageHelper.getResizedImage(image, 20, 20); + } + Graphics graphics = newImage.getGraphics(); + graphics.setColor(Color.BLACK); + graphics.setFont(new Font("Arial Black", amount > 100 ? Font.PLAIN : Font.BOLD, fontSize)); + graphics.drawString(Integer.toString(amount), xOffset * factor, 11 * factor); + return new ImageIcon(newImage); + } + + @Override + public Image getImage() { + if (this.hasImage) { + if (gameCard.isFaceDown()) { + return getFaceDownImage(); + } else { + return ImageCache.getImageOriginal(gameCard); + } + } + return null; + } +} diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java new file mode 100644 index 0000000000..e84d2aec7c --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java @@ -0,0 +1,397 @@ +package org.mage.card.arcane; + +import com.google.common.collect.MapMaker; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.io.File; +import java.util.Map; +import java.util.UUID; +import mage.cards.action.ActionCallback; +import mage.constants.CardType; +import mage.view.CardView; +import mage.view.CounterView; +import mage.view.PermanentView; +import mage.view.StackAbilityView; +import net.java.truevfs.access.TFile; +import org.apache.log4j.Logger; +import org.jdesktop.swingx.graphics.GraphicsUtilities; +import static org.mage.plugins.card.constants.Constants.THUMBNAIL_SIZE_FULL; +import org.mage.plugins.card.dl.sources.DirectLinksForDownload; +import org.mage.plugins.card.images.ImageCache; + +public class CardPanelRenderImpl extends CardPanel { + + private static final Logger LOGGER = Logger.getLogger(CardPanelRenderImpl.class); + + private static boolean cardViewEquals(CardView a, CardView b) { + if (a == b) { + return true; + } + if (a.getClass() != b.getClass()) { + return false; + } + if (!a.getName().equals(b.getName())) { + return false; + } + if (!a.getPower().equals(b.getPower())) { + return false; + } + if (!a.getToughness().equals(b.getToughness())) { + return false; + } + if (!a.getLoyalty().equals(b.getLoyalty())) { + return false; + } + if (0 != a.getColor().compareTo(b.getColor())) { + return false; + } + if (!a.getCardTypes().equals(b.getCardTypes())) { + return false; + } + if (!a.getSubTypes().equals(b.getSubTypes())) { + return false; + } + if (!a.getSuperTypes().equals(b.getSuperTypes())) { + return false; + } + if (!a.getManaCost().equals(b.getManaCost())) { + return false; + } + if (!a.getRules().equals(b.getRules())) { + return false; + } + if (!a.getExpansionSetCode().equals(b.getExpansionSetCode())) { + return false; + } + if (a.getCounters() == null) { + if (b.getCounters() != null) { + return false; + } + } else if (!a.getCounters().equals(b.getCounters())) { + return false; + } + if (a.isFaceDown() != b.isFaceDown()) { + return false; + } + if ((a instanceof PermanentView)) { + PermanentView aa = (PermanentView) a; + PermanentView bb = (PermanentView) b; + if (aa.hasSummoningSickness() != bb.hasSummoningSickness()) { + // Note: b must be a permanentview too as we aleady checked that classes + // are the same for a and b + return false; + } + if (aa.getDamage() != bb.getDamage()) { + return false; + } + } + return true; + } + + class ImageKey { + + final BufferedImage artImage; + final int width; + final int height; + final boolean isChoosable; + final boolean isSelected; + final CardView view; + final int hashCode; + + public ImageKey(CardView view, BufferedImage artImage, int width, int height, boolean isChoosable, boolean isSelected) { + this.view = view; + this.artImage = artImage; + this.width = width; + this.height = height; + this.isChoosable = isChoosable; + this.isSelected = isSelected; + this.hashCode = hashCodeImpl(); + } + + private int hashCodeImpl() { + StringBuilder sb = new StringBuilder(); + sb.append((char) (artImage != null ? 1 : 0)); + sb.append((char) width); + sb.append((char) height); + sb.append((char) (isSelected ? 1 : 0)); + sb.append((char) (isChoosable ? 1 : 0)); + sb.append((char) (this.view.isPlayable() ? 1 : 0)); + sb.append((char) (this.view.isCanAttack() ? 1 : 0)); + sb.append((char) (this.view.isFaceDown() ? 1 : 0)); + if (this.view instanceof PermanentView) { + sb.append((char) (((PermanentView) this.view).hasSummoningSickness() ? 1 : 0)); + sb.append((char) (((PermanentView) this.view).getDamage())); + } + sb.append(this.view.getName()); + sb.append(this.view.getPower()); + sb.append(this.view.getToughness()); + sb.append(this.view.getLoyalty()); + sb.append(this.view.getColor().toString()); + sb.append(this.view.getExpansionSetCode()); + for (CardType type : this.view.getCardTypes()) { + sb.append((char) type.ordinal()); + } + for (String s : this.view.getSuperTypes()) { + sb.append(s); + } + for (String s : this.view.getSubTypes()) { + sb.append(s); + } + for (String s : this.view.getManaCost()) { + sb.append(s); + } + for (String s : this.view.getRules()) { + sb.append(s); + } + if (this.view.getCounters() != null) { + for (CounterView v : this.view.getCounters()) { + sb.append(v.getName()).append(v.getCount()); + } + } + return sb.toString().hashCode(); + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + public boolean equals(Object object) { + // Initial checks + if (this == object) { + return true; + } + if (object == null) { + return false; + } + if (!(object instanceof ImageKey)) { + return false; + } + final ImageKey other = (ImageKey) object; + + // Compare + if ((artImage != null) != (other.artImage != null)) { + return false; + } + if (width != other.width) { + return false; + } + if (height != other.height) { + return false; + } + if (isChoosable != other.isChoosable) { + return false; + } + if (isSelected != other.isSelected) { + return false; + } + return cardViewEquals(view, other.view); + } + } + + // Map of generated images + private final static Map IMAGE_CACHE = new MapMaker().softValues().makeMap(); + + // The art image for the card, loaded in from the disk + private BufferedImage artImage; + + // The rendered card image, with or without the art image loaded yet + // = null while invalid + private BufferedImage cardImage; + private CardRenderer cardRenderer; + + public CardPanelRenderImpl(CardView newGameCard, UUID gameId, final boolean loadImage, ActionCallback callback, final boolean foil, Dimension dimension) { + // Call to super + super(newGameCard, gameId, loadImage, callback, foil, dimension); + + // Renderer + cardRenderer = new ModernCardRenderer(gameCard, isTransformed()); + + // Draw the parts + initialDraw(); + } + + @Override + public void transferResources(CardPanel panel) { + if (panel instanceof CardPanelRenderImpl) { + CardPanelRenderImpl impl = (CardPanelRenderImpl) panel; + + // Use the art image and current rendered image from the card + artImage = impl.artImage; + cardRenderer.setArtImage(artImage); + cardImage = impl.cardImage; + } + } + + @Override + protected void paintCard(Graphics2D g) { + // Render the card if we don't have an image ready to use + if (cardImage == null) { + // Try to get card image from cache based on our card characteristics + ImageKey key + = new ImageKey(gameCard, artImage, + getCardWidth(), getCardHeight(), + isChoosable(), isSelected()); + cardImage = IMAGE_CACHE.get(key); + + // No cached copy exists? Render one and cache it + if (cardImage == null) { + cardImage = renderCard(); + IMAGE_CACHE.put(key, cardImage); + } + } + + // And draw the image we now have + g.drawImage(cardImage, getCardXOffset(), getCardYOffset(), null); + } + + /** + * Render the card to a new BufferedImage at it's current dimensions + * + * @return + */ + private BufferedImage renderCard() { + int cardWidth = getCardWidth(); + int cardHeight = getCardHeight(); + + // Create image to render to + BufferedImage image + = GraphicsUtilities.createCompatibleTranslucentImage(cardWidth, cardHeight); + Graphics2D g2d = image.createGraphics(); + + // Render with Antialialsing + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + // Attributes + CardPanelAttributes attribs + = new CardPanelAttributes(cardWidth, cardHeight, isChoosable(), isSelected()); + + // Draw card itself + cardRenderer.draw(g2d, attribs); + + // Done + g2d.dispose(); + return image; + } + + private int updateArtImageStamp; + + @Override + public void updateArtImage() { + // Invalidate + artImage = null; + cardImage = null; + cardRenderer.setArtImage(null); + + // Stop animation + tappedAngle = isTapped() ? CardPanel.TAPPED_ANGLE : 0; + flippedAngle = isFlipped() ? CardPanel.FLIPPED_ANGLE : 0; + + // Schedule a repaint + repaint(); + + // See if the image is already loaded + //artImage = ImageCache.tryGetImage(gameCard, getCardWidth(), getCardHeight()); + //this.cardRenderer.setArtImage(artImage); + // Submit a task to draw with the card art when it arrives + if (artImage == null) { + final int stamp = ++updateArtImageStamp; + Util.threadPool.submit(new Runnable() { + @Override + public void run() { + try { + final BufferedImage srcImage; + if (gameCard.isFaceDown()) { + // Nothing to do + srcImage = null; + } else if (getCardWidth() > THUMBNAIL_SIZE_FULL.width) { + srcImage = ImageCache.getImage(gameCard, getCardWidth(), getCardHeight()); + } else { + srcImage = ImageCache.getThumbnail(gameCard); + } + UI.invokeLater(new Runnable() { + @Override + public void run() { + if (stamp == updateArtImageStamp) { + artImage = srcImage; + cardRenderer.setArtImage(srcImage); + if (srcImage != null) { + // Invalidate and repaint + cardImage = null; + repaint(); + } + } + } + }); + } catch (Exception e) { + e.printStackTrace(); + } catch (Error err) { + err.printStackTrace(); + } + } + }); + } + } + + @Override + public void update(CardView card) { + // Update super + super.update(card); + + // Update renderer + cardImage = null; + cardRenderer = new ModernCardRenderer(gameCard, isTransformed()); + cardRenderer.setArtImage(artImage); + + // Repaint + repaint(); + } + + @Override + public void setCardBounds(int x, int y, int cardWidth, int cardHeight) { + int oldCardWidth = getCardWidth(); + int oldCardHeight = getCardHeight(); + + super.setCardBounds(x, y, cardWidth, cardHeight); + + // Rerender if card size changed + if (getCardWidth() != oldCardWidth || getCardHeight() != oldCardHeight) { + cardImage = null; + } + } + + private BufferedImage getFaceDownImage() { + if (isPermanent()) { + if (((PermanentView) gameCard).isMorphed()) { + return ImageCache.getMorphImage(); + } else { + return ImageCache.getManifestImage(); + } + } else if (this.gameCard instanceof StackAbilityView) { + return ImageCache.getMorphImage(); + } else { + return ImageCache.loadImage(new TFile(DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename)); + } + } + + @Override + public Image getImage() { + if (artImage != null) { + if (gameCard.isFaceDown()) { + return getFaceDownImage(); + } else { + return ImageCache.getImageOriginal(gameCard); + } + } + return null; + } + + @Override + public void showCardTitle() { + // Nothing to do, rendered cards always have a title + } +} diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardRenderer.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardRenderer.java new file mode 100644 index 0000000000..53b6aa0741 --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardRenderer.java @@ -0,0 +1,374 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.mage.card.arcane; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Paint; +import java.awt.Polygon; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import mage.client.dialog.PreferencesDialog; +import mage.constants.AbilityType; +import mage.constants.CardType; +import mage.utils.CardUtil; +import mage.view.CardView; +import mage.view.CounterView; +import mage.view.PermanentView; +import org.apache.log4j.Logger; + +/** + * @author stravant@gmail.com + * + * Common base class for card renderers for each card frame / card type. + * + * Follows the template method pattern to implement a new renderer, implement + * the following methods (they are called in the following order): + * + * * drawBorder() Draws the outermost border of the card, white border or black + * border + * + * * drawBackground() Draws the background texture / color of the card + * + * * drawArt() Draws the card's art + * + * * drawFrame() Draws the card frame (over the art and background) + * + * * drawOverlays() Draws summoning sickness and possible other overlays + * + * * drawCounters() Draws counters on the card, such as +1/+1 and -1/-1 + * counters + * + * Predefined methods that the implementations can use: + * + * * drawRules(font, bounding box) + * + * * drawNameLine(font, bounding box) + * + * * drawTypeLine(font, bounding box) + * + */ +public abstract class CardRenderer { + + private static final Logger LOGGER = Logger.getLogger(CardPanel.class); + + /////////////////////////////////////////////////////////////////////////// + // Common layout metrics between all cards + // The card to be rendered + protected final CardView cardView; + + // Is the card transformed? + protected final boolean isTransformed; + + // The card image + protected BufferedImage artImage; + + /////////////////////////////////////////////////////////////////////////// + // Common layout metrics between all cards + // Polygons for counters + private static final Polygon PLUS_COUNTER_POLY = new Polygon(new int[]{ + 0, 5, 10, 10, 5, 0 + }, new int[]{ + 3, 0, 3, 10, 9, 10 + }, 6); + private static final Polygon MINUS_COUNTER_POLY = new Polygon(new int[]{ + 0, 5, 10, 10, 5, 0 + }, new int[]{ + 0, 1, 0, 7, 10, 7 + }, 6); + private static final Polygon TIME_COUNTER_POLY = new Polygon(new int[]{ + 0, 10, 8, 10, 0, 2 + }, new int[]{ + 0, 0, 5, 10, 10, 5 + }, 6); + private static final Polygon OTHER_COUNTER_POLY = new Polygon(new int[]{ + 1, 9, 9, 1 + }, new int[]{ + 1, 1, 9, 9 + }, 4); + + // Paint for a card back + public static Paint BG_TEXTURE_CARDBACK = new Color(153, 102, 51); + + // The size of the card + protected int cardWidth; + protected int cardHeight; + + // Is it selectable / selected + protected boolean isChoosable; + protected boolean isSelected; + + // Radius of the corners of the cards + protected static float CORNER_RADIUS_FRAC = 0.1f; //x cardWidth + protected static int CORNER_RADIUS_MIN = 3; + protected int cornerRadius; + + // The inset of the actual card from the black / white border around it + protected static float BORDER_WIDTH_FRAC = 0.03f; //x cardWidth + protected static float BORDER_WIDTH_MIN = 2; + protected int borderWidth; + + // The parsed text of the card + protected ArrayList textboxRules = new ArrayList<>(); + protected ArrayList textboxKeywords = new ArrayList<>(); + + // The Construtor + // The constructor should prepare all of the things that it can + // without knowing the dimensions that the card will be rendered at. + // Then, the CardRenderer can be called on multiple times to render the + // card at various sizes (for instance, during animation) + public CardRenderer(CardView card, boolean isTransformed) { + // Set base parameters + this.cardView = card; + this.isTransformed = isTransformed; + + // Translate the textbox text + for (String rule : card.getRules()) { + // Kill reminder text + if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_RENDERING_REMINDER_TEXT, "false").equals("false")) { + rule = CardRendererUtils.killReminderText(rule).trim(); + } + if (!rule.isEmpty()) { + TextboxRule tbRule = TextboxRuleParser.parse(card, rule); + if (tbRule.type == TextboxRuleType.SIMPLE_KEYWORD) { + textboxKeywords.add(tbRule); + } else if (tbRule.text.isEmpty()) { + // Nothing to do, rule is empty + } else { + textboxRules.add(tbRule); + } + } + } + } + + // Layout operation + // Calculate common layout metrics that will be used by several + // of the operations in the template method. + protected void layout(int cardWidth, int cardHeight) { + // Store the dimensions for the template methods to use + this.cardWidth = cardWidth; + this.cardHeight = cardHeight; + + // Corner radius and border width + cornerRadius = (int) Math.max( + CORNER_RADIUS_MIN, + CORNER_RADIUS_FRAC * cardWidth); + + borderWidth = (int) Math.max( + BORDER_WIDTH_MIN, + BORDER_WIDTH_FRAC * cardWidth); + } + + // The Draw Method + // The draw method takes the information caculated by the constructor + // and uses it to draw to a concrete size of card and graphics. + public void draw(Graphics2D g, CardPanelAttributes attribs) { + // Pre template method layout, to calculate shared layout info + layout(attribs.cardWidth, attribs.cardHeight); + isSelected = attribs.isSelected; + isChoosable = attribs.isChoosable; + + // Call the template methods + drawBorder(g); + drawBackground(g); + drawArt(g); + drawFrame(g); + if (!cardView.isAbility()) { + drawOverlays(g); + drawCounters(g); + } + } + + // Template methods to be implemented by sub classes + // For instance, for the Modern vs Old border card frames + protected abstract void drawBorder(Graphics2D g); + + protected abstract void drawBackground(Graphics2D g); + + protected abstract void drawArt(Graphics2D g); + + protected abstract void drawFrame(Graphics2D g); + + // Template methods that are possible to override, but unlikely to be + // overridden. + // Draw the card back + protected void drawCardBack(Graphics2D g) { + g.setPaint(BG_TEXTURE_CARDBACK); + g.fillRect(borderWidth, borderWidth, + cardWidth - 2 * borderWidth, cardHeight - 2 * borderWidth); + } + + // Draw summoning sickness overlay, and possibly other overlays + protected void drawOverlays(Graphics2D g) { + if (CardUtil.isCreature(cardView) && cardView instanceof PermanentView) { + if (((PermanentView) cardView).hasSummoningSickness()) { + int x1 = (int) (0.2 * cardWidth); + int x2 = (int) (0.8 * cardWidth); + int y1 = (int) (0.2 * cardHeight); + int y2 = (int) (0.8 * cardHeight); + int xPoints[] = { + x1, x2, x1, x2 + }; + int yPoints[] = { + y1, y1, y2, y2 + }; + g.setColor(new Color(255, 255, 255, 200)); + g.setStroke(new BasicStroke(7)); + g.drawPolygon(xPoints, yPoints, 4); + g.setColor(new Color(0, 0, 0, 200)); + g.setStroke(new BasicStroke(5)); + g.drawPolygon(xPoints, yPoints, 4); + g.setStroke(new BasicStroke(1)); + int[] xPoints2 = { + x1, x2, cardWidth / 2 + }; + int[] yPoints2 = { + y1, y1, cardHeight / 2 + }; + g.setColor(new Color(0, 0, 0, 100)); + g.fillPolygon(xPoints2, yPoints2, 3); + } + } + } + + // Draw +1/+1 and other counters + protected void drawCounters(Graphics2D g) { + int xPos = (int) (0.65 * cardWidth); + int yPos = (int) (0.15 * cardHeight); + if (cardView.getCounters() != null) { + for (CounterView v : cardView.getCounters()) { + // Don't render loyalty, we do that in the bottom corner + if (!v.getName().equals("loyalty")) { + Polygon p; + if (v.getName().equals("+1/+1")) { + p = PLUS_COUNTER_POLY; + } else if (v.getName().equals("-1/-1")) { + p = MINUS_COUNTER_POLY; + } else if (v.getName().equals("time")) { + p = TIME_COUNTER_POLY; + } else { + p = OTHER_COUNTER_POLY; + } + double scale = (0.1 * 0.25 * cardWidth); + Graphics2D g2 = (Graphics2D) g.create(); + g2.translate(xPos, yPos); + g2.scale(scale, scale); + g2.setColor(Color.white); + g2.fillPolygon(p); + g2.setColor(Color.black); + g2.drawPolygon(p); + g2.setFont(new Font("Arial", Font.BOLD, 7)); + String cstr = "" + v.getCount(); + int strW = g2.getFontMetrics().stringWidth(cstr); + g2.drawString(cstr, 5 - strW / 2, 8); + g2.dispose(); + yPos += ((int) (0.30 * cardWidth)); + } + } + } + } + + // Draw an expansion symbol, right justified, in a given region + // Return the width of the drawn symbol + protected int drawExpansionSymbol(Graphics2D g, int x, int y, int w, int h) { + // Draw the expansion symbol + Image setSymbol = ManaSymbols.getSetSymbolImage(cardView.getExpansionSetCode(), cardView.getRarity().getCode()); + int setSymbolWidth; + if (setSymbol == null) { + // Don't draw anything when we don't have a set symbol + return 0; + /* + // Just draw the as a code + String code = cardView.getExpansionSetCode(); + code = (code != null) ? code.toUpperCase() : ""; + FontMetrics metrics = g.getFontMetrics(); + setSymbolWidth = metrics.stringWidth(code); + if (cardView.getRarity() == Rarity.COMMON) { + g.setColor(Color.white); + } else { + g.setColor(Color.black); + } + g.fillRoundRect( + x + w - setSymbolWidth - 1, y + 2, + setSymbolWidth+2, h - 5, + 5, 5); + g.setColor(getRarityColor()); + g.drawString(code, x + w - setSymbolWidth, y + h - 3); + */ + } else { + // Draw the set symbol + int height = setSymbol.getHeight(null); + int scale = 1; + if (height != -1) { + while (height > h + 2) { + scale *= 2; + height /= 2; + } + } + setSymbolWidth = setSymbol.getWidth(null) / scale; + g.drawImage(setSymbol, + x + w - setSymbolWidth, y + (h - height) / 2, + setSymbolWidth, height, + null); + } + return setSymbolWidth; + } + + private Color getRarityColor() { + switch (cardView.getRarity()) { + case RARE: + return new Color(255, 191, 0); + case UNCOMMON: + return new Color(192, 192, 192); + case MYTHIC: + return new Color(213, 51, 11); + case SPECIAL: + return new Color(204, 0, 255); + case BONUS: + return new Color(129, 228, 228); + case COMMON: + default: + return Color.black; + } + } + + // Get a string representing the type line + protected String getCardTypeLine() { + if (cardView.isAbility()) { + if (AbilityType.TRIGGERED.equals(cardView.getAbilityType())) { + return "Triggered Ability"; + } else if (AbilityType.ACTIVATED.equals(cardView.getAbilityType())) { + return "Activated Ability"; + } else { + return "??? Ability"; + } + } else { + StringBuilder sbType = new StringBuilder(); + for (String superType : cardView.getSuperTypes()) { + sbType.append(superType).append(" "); + } + for (CardType cardType : cardView.getCardTypes()) { + sbType.append(cardType.toString()).append(" "); + } + if (cardView.getSubTypes().size() > 0) { + sbType.append("- "); + for (String subType : cardView.getSubTypes()) { + sbType.append(subType).append(" "); + } + } + return sbType.toString(); + } + } + + // Set the card art image (CardPanel will give it to us when it + // is loaded and ready) + public void setArtImage(Image image) { + artImage = CardRendererUtils.toBufferedImage(image); + } +} diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardRendererUtils.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardRendererUtils.java new file mode 100644 index 0000000000..bede760f80 --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardRendererUtils.java @@ -0,0 +1,124 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.mage.card.arcane; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Paint; +import java.awt.image.BufferedImage; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author stravant@gmail.com + * + * Various static utilities for use in the card renderer + */ +public class CardRendererUtils { + /** + * Convert an abstract image, whose underlying implementation may or may + * not be a BufferedImage into a BufferedImage by creating one and coping + * the contents if it is not, and simply up-casting if it is. + * @param img The image to convert + * @return The converted image + */ + public static BufferedImage toBufferedImage(Image img) { + // Null? No conversion to do + if (img == null) { + return null; + } + + // Already a buffered image? + if (img instanceof BufferedImage) { + return (BufferedImage) img; + } + + // Create a buffered image with transparency + BufferedImage bimage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB); + + // Draw the image on to the buffered image + Graphics2D bGr = bimage.createGraphics(); + bGr.drawImage(img, 0, 0, null); + bGr.dispose(); + + // Return the buffered image + return bimage; + } + + // Draw a rounded box with a 2-pixel border + // Used on various card parts. + public static void drawRoundedBox(Graphics2D g, int x, int y, int w, int h, int bevel, Paint border, Color fill) { + g.setColor(new Color(0, 0, 0, 150)); + g.drawOval(x-1, y-1, bevel*2, h); + g.setPaint(border); + g.drawOval(x, y, bevel*2-1, h-1); + g.drawOval(x + w - bevel*2, y, bevel*2-1, h-1); + g.drawOval(x+1, y+1, bevel*2-3, h-3); + g.drawOval(x+1 + w - bevel*2, y+1, bevel*2-3, h-3); + g.drawRect(x + bevel, y, w - 2*bevel, h-1); + g.drawRect(x+1 + bevel, y+1, w - 2*bevel-2, h-3); + g.setColor(fill); + g.fillOval(x+2, y+2, bevel*2-4, h-4); + g.fillOval(x+2 + w - bevel*2, y+2, bevel*2-4, h-4); + g.fillRect(x + bevel, y+2, w - 2*bevel, h-4); + } + + // Get the width of a mana cost rendered with ManaSymbols.draw + public static int getManaCostWidth(String manaCost, int symbolSize) { + int width = 0; + manaCost = manaCost.replace("\\", ""); + StringTokenizer tok = new StringTokenizer(manaCost, " "); + while (tok.hasMoreTokens()) { + tok.nextToken(); + width += symbolSize; + } + return width; + } + + // Abbreviate a piece of rules text, making substitutions to decrease its + // length. Also abbreviate reminder text. + private static Pattern abbreviationPattern; + private static Map abbreviations = new HashMap(); + private static Pattern killReminderTextPattern; + static { + // Available abbreviations + abbreviations.put("enters the battlefield", "ETB"); + abbreviations.put("less than", "<"); + abbreviations.put("greater than", ">"); + + // Compile into regex + String patternString = "("; + Iterator it = abbreviations.keySet().iterator(); + while (it.hasNext()) { + patternString += it.next(); + if (it.hasNext()) { + patternString += "|"; + } + } + patternString += ")"; + abbreviationPattern = Pattern.compile(patternString); + + // Reminder text killing + killReminderTextPattern = Pattern.compile("\\([^\\)]*\\)"); + } + public static String abbreviateRule(String rule) { + StringBuffer build = new StringBuffer(); + Matcher match = abbreviationPattern.matcher(rule); + while (match.find()) { + match.appendReplacement(build, abbreviations.get(match.group(1))); + } + match.appendTail(build); + return build.toString(); + } + public static String killReminderText(String rule) { + return killReminderTextPattern.matcher(rule).replaceAll(""); + } +} diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/GlowText.java b/Mage.Client/src/main/java/org/mage/card/arcane/GlowText.java index 5a32f6b872..526eec50cb 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/GlowText.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/GlowText.java @@ -2,20 +2,12 @@ package org.mage.card.arcane; import com.google.common.base.Function; import com.google.common.collect.MapMaker; -import javax.swing.*; import java.awt.*; import java.awt.font.FontRenderContext; import java.awt.font.LineBreakMeasurer; import java.awt.font.TextAttribute; import java.awt.font.TextLayout; import java.awt.image.BufferedImage; -import java.io.BufferedOutputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; import java.text.AttributedCharacterIterator; import java.text.AttributedString; @@ -23,10 +15,12 @@ import java.text.BreakIterator; import java.util.Locale; import java.util.Map; import java.util.Objects; +import javax.swing.*; import mage.client.util.ImageCaches; import org.jdesktop.swingx.graphics.GraphicsUtilities; public class GlowText extends JLabel { + private static final long serialVersionUID = 1827677946939348001L; private int glowSize; @SuppressWarnings("unused") @@ -36,12 +30,12 @@ public class GlowText extends JLabel { private int lineCount = 0; private static Map IMAGE_CACHE; - private final static class Key - { + private final static class Key { + final int width; final int height; final String text; - final Map fontAttributes; + final Map fontAttributes; final Color color; final int glowSize; final float glowIntensity; @@ -53,8 +47,9 @@ public class GlowText extends JLabel { Font getFont() { Font res = this.originalFont.get(); - if(res == null) + if (res == null) { res = Font.getFont(this.fontAttributes); + } return res; } @@ -138,18 +133,18 @@ public class GlowText extends JLabel { })); } - public void setGlow (Color glowColor, int size, float intensity) { + public void setGlow(Color glowColor, int size, float intensity) { this.glowColor = glowColor; this.glowSize = size; this.glowIntensity = intensity; } - public void setWrap (boolean wrap) { + public void setWrap(boolean wrap) { this.wrap = wrap; } @Override - public Dimension getPreferredSize () { + public Dimension getPreferredSize() { Dimension size = super.getPreferredSize(); size.width += glowSize; size.height += glowSize / 2; @@ -157,7 +152,7 @@ public class GlowText extends JLabel { } @Override - public void paint (Graphics g) { + public void paint(Graphics g) { if (getText().length() == 0) { return; } @@ -165,7 +160,7 @@ public class GlowText extends JLabel { g.drawImage(IMAGE_CACHE.get(new Key(getWidth(), getHeight(), getText(), getFont(), getForeground(), glowSize, glowIntensity, glowColor, wrap)), 0, 0, null); } - private static BufferedImage createImage (Key key) { + private static BufferedImage createImage(Key key) { Dimension size = new Dimension(key.width, key.height); BufferedImage image = GraphicsUtilities.createCompatibleTranslucentImage(size.width, size.height); Graphics2D g2d = image.createGraphics(); diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbols.java b/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbols.java index 7d133699f0..6b62e3f738 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbols.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbols.java @@ -37,7 +37,7 @@ public class ManaSymbols { private static boolean smallSymbolsFound = false; private static boolean mediumSymbolsFound = false; - private static final Map setImages = new HashMap<>(); + private static final Map> setImages = new HashMap<>(); private static final Map setImagesExist = new HashMap<>(); private static final Pattern REPLACE_SYMBOLS_PATTERN = Pattern.compile("\\{([^}/]*)/?([^}]*)\\}"); private static String cachedPath; @@ -57,25 +57,32 @@ public class ManaSymbols { return; } for (String set : setCodes) { - File file = new File(getSymbolsPath() + Constants.RESOURCE_PATH_SET + set + "-C.jpg"); - try { - Image image = UI.getImageIcon(file.getAbsolutePath()).getImage(); - int width = image.getWidth(null); - if (width > 21) { - int h = image.getHeight(null); - if (h > 0) { - Rectangle r = new Rectangle(21, (int) (h * 21.0f / width)); - BufferedImage resized = ImageHelper.getResizedImage(BufferedImageBuilder.bufferImage(image, BufferedImage.TYPE_INT_ARGB), r); - setImages.put(set, resized); - } - } else { - setImages.put(set, image); - } - } catch (Exception e) { - } String[] codes = new String[]{"C", "U", "R", "M"}; + + Map rarityImages = new HashMap<>(); + setImages.put(set, rarityImages); + + for (String rarityCode: codes) { + File file = new File(getSymbolsPath() + Constants.RESOURCE_PATH_SET + set + "-" + rarityCode + ".jpg"); + try { + Image image = UI.getImageIcon(file.getAbsolutePath()).getImage(); + int width = image.getWidth(null); + if (width > 21) { + int h = image.getHeight(null); + if (h > 0) { + Rectangle r = new Rectangle(21, (int) (h * 21.0f / width)); + BufferedImage resized = ImageHelper.getResizedImage(BufferedImageBuilder.bufferImage(image, BufferedImage.TYPE_INT_ARGB), r); + rarityImages.put(set, resized); + } + } else { + rarityImages.put(rarityCode, image); + } + } catch (Exception e) { + } + } + try { - file = new File(getSymbolsPath() + Constants.RESOURCE_PATH_SET_SMALL); + File file = new File(getSymbolsPath() + Constants.RESOURCE_PATH_SET_SMALL); if (!file.exists()) { file.mkdirs(); } @@ -298,14 +305,27 @@ public class ManaSymbols { } public static Image getSetSymbolImage(String set) { - return setImages.get(set); + return getSetSymbolImage(set, "C"); + } + + public static Image getSetSymbolImage(String set, String rarity) { + Map rarityImages = setImages.get(set); + if (rarityImages != null) { + return rarityImages.get(rarity); + } else { + return null; + } } public static BufferedImage getSizedManaSymbol(String symbol) { - if (!manaImages.containsKey(GUISizeHelper.symbolDialogSize)) { - loadSymbolsImages(GUISizeHelper.symbolDialogSize); + return getSizedManaSymbol(symbol, GUISizeHelper.symbolDialogSize); + } + + public static BufferedImage getSizedManaSymbol(String symbol, int size) { + if (!manaImages.containsKey(size)) { + loadSymbolsImages(size); } - Map sizedSymbols = manaImages.get(GUISizeHelper.symbolDialogSize); + Map sizedSymbols = manaImages.get(size); return sizedSymbols.get(symbol); } } diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java b/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java new file mode 100644 index 0000000000..7e0a1d9d27 --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java @@ -0,0 +1,1037 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.mage.card.arcane; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Font; +import java.awt.FontFormatException; +import java.awt.Graphics2D; +import java.awt.LinearGradientPaint; +import java.awt.Paint; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.TexturePaint; +import java.awt.font.FontRenderContext; +import java.awt.font.LineBreakMeasurer; +import java.awt.font.TextAttribute; +import java.awt.font.TextLayout; +import java.awt.font.TextMeasurer; +import java.awt.geom.RoundRectangle2D; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.net.URL; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; +import java.text.CharacterIterator; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import javax.swing.ImageIcon; +import mage.ObjectColor; +import mage.client.dialog.PreferencesDialog; +import mage.constants.CardType; +import mage.view.CardView; +import mage.view.PermanentView; +import org.apache.log4j.Logger; + + +/* + private void cardRendererBasedRender(Graphics2D g) { + // Prepare for draw + g.translate(cardXOffset, cardYOffset); + int cardWidth = this.cardWidth - cardXOffset; + int cardHeight = this.cardHeight - cardYOffset; + + // AA on + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + // Renderer + CardRenderer render = new ModernCardRenderer(gameCard, transformed); + Image img = imagePanel.getSrcImage(); + if (img != null) { + render.setArtImage(img); + } + render.draw(g, cardWidth, cardHeight); + } + */ +/** + * @author stravant@gmail.com + * + * Base rendering class for new border cards + */ +public class ModernCardRenderer extends CardRenderer { + + private final static Logger LOGGER = Logger.getLogger(ModernCardRenderer.class); + + /////////////////////////////////////////////////////////////////////////// + // Textures for modern frame cards + private static TexturePaint loadBackgroundTexture(String name) { + URL url = ModernCardRenderer.class.getResource("/cardrender/background_texture_" + name + ".png"); + ImageIcon icon = new ImageIcon(url); + BufferedImage img = CardRendererUtils.toBufferedImage(icon.getImage()); + return new TexturePaint(img, new Rectangle(0, 0, img.getWidth(), img.getHeight())); + } + + private static Font loadFont(String name) { + try { + return Font.createFont( + Font.TRUETYPE_FONT, + ModernCardRenderer.class.getResourceAsStream("/cardrender/" + name + ".ttf")); + } catch (IOException e) { + LOGGER.info("Failed to load font `" + name + "`, couldn't find resource."); + } catch (FontFormatException e) { + LOGGER.info("Failed to load font `" + name + "`, bad format."); + } + return new Font("Arial", Font.PLAIN, 1); + } + public static Font BASE_BELEREN_FONT = loadFont("beleren-bold"); + + public static Paint BG_TEXTURE_WHITE = loadBackgroundTexture("white"); + public static Paint BG_TEXTURE_BLUE = loadBackgroundTexture("blue"); + public static Paint BG_TEXTURE_BLACK = loadBackgroundTexture("black"); + public static Paint BG_TEXTURE_RED = loadBackgroundTexture("red"); + public static Paint BG_TEXTURE_GREEN = loadBackgroundTexture("green"); + public static Paint BG_TEXTURE_GOLD = loadBackgroundTexture("gold"); + public static Paint BG_TEXTURE_ARTIFACT = loadBackgroundTexture("artifact"); + public static Paint BG_TEXTURE_LAND = loadBackgroundTexture("land"); + + public static Color BORDER_WHITE = new Color(216, 203, 188); + public static Color BORDER_BLUE = new Color(20, 121, 175); + public static Color BORDER_BLACK = new Color(45, 45, 35); + public static Color BORDER_RED = new Color(201, 71, 58); + public static Color BORDER_GREEN = new Color(4, 136, 69); + public static Color BORDER_GOLD = new Color(255, 228, 124); + public static Color BORDER_COLORLESS = new Color(238, 242, 242); + public static Color BORDER_LAND = new Color(190, 173, 115); + + public static Color BOX_WHITE = new Color(244, 245, 239); + public static Color BOX_BLUE = new Color(201, 223, 237); + public static Color BOX_BLACK = new Color(204, 194, 192); + public static Color BOX_RED = new Color(246, 208, 185); + public static Color BOX_GREEN = new Color(205, 221, 213); + public static Color BOX_GOLD = new Color(223, 195, 136); + public static Color BOX_COLORLESS = new Color(220, 228, 232); + public static Color BOX_LAND = new Color(220, 215, 213); + + public static Color BOX_WHITE_NIGHT = new Color(169, 160, 145); + public static Color BOX_BLUE_NIGHT = new Color(46, 133, 176); + public static Color BOX_BLACK_NIGHT = new Color(95, 90, 89); + public static Color BOX_RED_NIGHT = new Color(188, 87, 57); + public static Color BOX_GREEN_NIGHT = new Color(31, 100, 44); + public static Color BOX_GOLD_NIGHT = new Color(171, 134, 70); + public static Color BOX_COLORLESS_NIGHT = new Color(118, 147, 158); + + public static Color TEXTBOX_WHITE = new Color(252, 249, 244, 244); + public static Color TEXTBOX_BLUE = new Color(229, 238, 247, 244); + public static Color TEXTBOX_BLACK = new Color(241, 241, 240, 244); + public static Color TEXTBOX_RED = new Color(243, 224, 217, 244); + public static Color TEXTBOX_GREEN = new Color(217, 232, 223, 244); + public static Color TEXTBOX_GOLD = new Color(240, 234, 209, 244); + public static Color TEXTBOX_COLORLESS = new Color(219, 229, 233, 244); + public static Color TEXTBOX_LAND = new Color(218, 214, 212, 244); + + public static Color ERROR_COLOR = new Color(255, 0, 255); + + /////////////////////////////////////////////////////////////////////////// + // Layout metrics for modern border cards + // How far the main box, art, and name / type line are inset from the + // card border. That is, the width of background texture that shows around + // the edge of the card. + protected int contentInset; + + // Helper: The total inset from card edge to rules box etc. + // = borderWidth + contentInset + protected int totalContentInset; + + // Width of the content region of the card + // = cardWidth - 2 x totalContentInset + protected int contentWidth; + + // How tall the name / type lines and P/T box are + protected static float BOX_HEIGHT_FRAC = 0.065f; // x cardHeight + protected static int BOX_HEIGHT_MIN = 16; + protected int boxHeight; + + // How far down the card is the type line placed? + protected static float TYPE_LINE_Y_FRAC = 0.57f; // x cardHeight + protected static float TYPE_LINE_Y_FRAC_TOKEN = 0.70f; + protected int typeLineY; + + // How large is the box text, and how far is it down the boxes + protected int boxTextHeight; + protected int boxTextOffset; + protected Font boxTextFont; + + // How large is the P/T text, and how far is it down the boxes + protected int ptTextHeight; + protected int ptTextOffset; + protected Font ptTextFont; + + // Processed mana cost string + protected String manaCostString; + + public ModernCardRenderer(CardView card, boolean isTransformed) { + // Pass off to parent + super(card, isTransformed); + + // Mana cost string + manaCostString = ManaSymbols.getStringManaCost(cardView.getManaCost()); + } + + @Override + protected void layout(int cardWidth, int cardHeight) { + // Pass to parent + super.layout(cardWidth, cardHeight); + + // Content inset, just equal to border width + contentInset = borderWidth; + + // Total content inset helper + totalContentInset = borderWidth + contentInset; + + // Content width + contentWidth = cardWidth - 2 * totalContentInset; + + // Box height + boxHeight = (int) Math.max( + BOX_HEIGHT_MIN, + BOX_HEIGHT_FRAC * cardHeight); + + // Type line at + if (cardView.isToken()) { + typeLineY = (int) (TYPE_LINE_Y_FRAC_TOKEN * cardHeight); + } else { + typeLineY = (int) (TYPE_LINE_Y_FRAC * cardHeight); + } + + // Box text height + boxTextHeight = getTextHeightForBoxHeight(boxHeight); + boxTextOffset = (boxHeight - boxTextHeight) / 2; + boxTextFont = BASE_BELEREN_FONT.deriveFont(Font.PLAIN, boxTextHeight); + + // Box text height + ptTextHeight = getPTTextHeightForLineHeight(boxHeight); + ptTextOffset = (boxHeight - ptTextHeight) / 2; + ptTextFont = BASE_BELEREN_FONT.deriveFont(Font.PLAIN, ptTextHeight); + } + + @Override + protected void drawBorder(Graphics2D g) { + // Draw border as one rounded rectangle + g.setColor(Color.black); + g.fillRoundRect(0, 0, cardWidth, cardHeight, cornerRadius, cornerRadius); + + // Selection Borders + Color borderColor; + if (isSelected) { + borderColor = Color.green; + } else if (isChoosable) { + borderColor = new Color(250, 250, 0, 230); + } else if (cardView.isPlayable()) { + borderColor = new Color(153, 102, 204, 200); + } else if (cardView instanceof PermanentView && ((PermanentView) cardView).isCanAttack()) { + borderColor = new Color(0, 0, 255, 230); + } else { + borderColor = null; + } + if (borderColor != null) { + float hwidth = borderWidth / 2.0f; + Graphics2D g2 = (Graphics2D) g.create(); + g2.setColor(borderColor); + g2.setStroke(new BasicStroke(borderWidth)); + RoundRectangle2D.Float rect + = new RoundRectangle2D.Float( + hwidth, hwidth, + cardWidth - borderWidth, cardHeight - borderWidth, + cornerRadius, cornerRadius); + g2.draw(rect); + g2.dispose(); + } + } + + @Override + protected void drawBackground(Graphics2D g) { + // Draw background, in 3 parts + + if (cardView.isFaceDown()) { + // Just draw a brown rectangle + drawCardBack(g); + } else { + // Set texture to paint with + g.setPaint(getBackgroundPaint(cardView.getColor(), cardView.getCardTypes())); + + // Draw main part (most of card) + g.fillRoundRect( + borderWidth, borderWidth, + cardWidth - borderWidth * 2, cardHeight - borderWidth * 4 - cornerRadius * 2, + cornerRadius - 1, cornerRadius - 1); + + // Draw the M15 rounded "swoosh" at the bottom + g.fillRoundRect( + borderWidth, cardHeight - borderWidth * 4 - cornerRadius * 4, + cardWidth - borderWidth * 2, cornerRadius * 4, + cornerRadius * 2, cornerRadius * 2); + + // Draw the cutout into the "swoosh" for the textbox to lie over + g.fillRect( + borderWidth + contentInset, cardHeight - borderWidth * 5, + cardWidth - borderWidth * 2 - contentInset * 2, borderWidth * 2); + } + } + + @Override + protected void drawArt(Graphics2D g) { + if (artImage != null && !cardView.isFaceDown()) { + int imgWidth = artImage.getWidth(); + int imgHeight = artImage.getHeight(); + BufferedImage subImg + = artImage.getSubimage( + (int) (.079 * imgWidth), (int) (.11 * imgHeight), + (int) (.84 * imgWidth), (int) (.42 * imgHeight)); + g.drawImage(subImg, + totalContentInset + 1, totalContentInset + boxHeight, + contentWidth - 2, typeLineY - totalContentInset - boxHeight, + null); + } + } + + @Override + protected void drawFrame(Graphics2D g) { + // Get the card colors to base the frame on + ObjectColor frameColors = getFrameObjectColor(); + + // Get the border paint + Color boxColor = getBoxColor(frameColors, cardView.getCardTypes(), isTransformed); + Paint textboxPaint = getTextboxPaint(frameColors, cardView.getCardTypes(), cardWidth); + Paint borderPaint = getBorderPaint(frameColors, cardView.getCardTypes(), cardWidth); + + // Draw the main card content border + g.setPaint(borderPaint); + g.drawRect( + totalContentInset, totalContentInset, + contentWidth - 1, cardHeight - borderWidth * 3 - totalContentInset - 1); + + // Draw the textbox fill + g.setPaint(textboxPaint); + g.fillRect( + totalContentInset + 1, typeLineY, + contentWidth - 2, cardHeight - borderWidth * 3 - typeLineY - 1); + + // If it's a planeswalker, extend the textbox left border by some + if (cardView.getCardTypes().contains(CardType.PLANESWALKER)) { + g.setPaint(borderPaint); + g.fillRect( + totalContentInset, typeLineY + boxHeight, + cardWidth / 16, cardHeight - typeLineY - boxHeight - borderWidth * 3); + } + + // Draw a shadow highlight at the right edge of the content frame + g.setColor(new Color(0, 0, 0, 100)); + g.fillRect( + totalContentInset - 1, totalContentInset, + 1, cardHeight - borderWidth * 3 - totalContentInset - 1); + + // Draw a shadow highlight separating the card art and rest of frame + g.drawRect( + totalContentInset + 1, totalContentInset + boxHeight, + contentWidth - 3, typeLineY - totalContentInset - boxHeight - 1); + + // Draw the name line box + CardRendererUtils.drawRoundedBox(g, + borderWidth, totalContentInset, + cardWidth - 2 * borderWidth, boxHeight, + contentInset, + borderPaint, boxColor); + + // Draw the type line box + CardRendererUtils.drawRoundedBox(g, + borderWidth, typeLineY, + cardWidth - 2 * borderWidth, boxHeight, + contentInset, + borderPaint, boxColor); + + // Draw a small separator between the type line and box, and shadow + // at the left of the texbox, and above the name line + g.setColor(new Color(0, 0, 0, 150)); + g.fillRect( + totalContentInset - 1, totalContentInset - 1, + contentWidth + 1, 1); + g.fillRect( + totalContentInset + 1, typeLineY + boxHeight, + contentWidth - 2, 1); + g.fillRect( + cardWidth - totalContentInset - 1, typeLineY + boxHeight, + 1, cardHeight - borderWidth * 3 - typeLineY - boxHeight); + + // Draw the transform circle + int nameOffset = drawTransformationCircle(g, borderPaint); + + // Draw the name line + drawNameLine(g, + totalContentInset + nameOffset, totalContentInset, + contentWidth - nameOffset, boxHeight); + + // Draw the type line + drawTypeLine(g, + totalContentInset, typeLineY, + contentWidth, boxHeight); + + // Draw the textbox rules + drawRulesText(g, + totalContentInset + 2, typeLineY + boxHeight + 2, + contentWidth - 4, cardHeight - typeLineY - boxHeight - 4 - borderWidth * 3); + + // Draw the bottom right stuff + drawBottomRight(g, borderPaint, boxColor); + } + + // Draw the name line + protected void drawNameLine(Graphics2D g, int x, int y, int w, int h) { + // Width of the mana symbols + int manaCostWidth; + if (cardView.isAbility()) { + manaCostWidth = 0; + } else { + manaCostWidth = CardRendererUtils.getManaCostWidth(manaCostString, boxTextHeight); + } + + // Available width for name. Add a little bit of slop so that one character + // can partially go underneath the mana cost + int availableWidth = w - manaCostWidth + 2; + + // Draw the name + String nameStr; + if (cardView.isFaceDown()) { + if (cardView instanceof PermanentView && ((PermanentView) cardView).isManifested()) { + nameStr = "Manifest: " + cardView.getName(); + } else { + nameStr = "Morph: " + cardView.getName(); + } + } else { + nameStr = cardView.getName(); + } + AttributedString str = new AttributedString(nameStr); + str.addAttribute(TextAttribute.FONT, boxTextFont); + TextMeasurer measure = new TextMeasurer(str.getIterator(), g.getFontRenderContext()); + TextLayout layout = measure.getLayout(0, measure.getLineBreakIndex(0, availableWidth)); + g.setColor(getBoxTextColor()); + layout.draw(g, x, y + boxTextOffset + boxTextHeight - 1); + + // Draw the mana symbols + if (!cardView.isAbility() && !cardView.isFaceDown()) { + ManaSymbols.draw(g, manaCostString, x + w - manaCostWidth, y + boxTextOffset, boxTextHeight); + } + } + + // Draw the type line (color indicator, types, and expansion symbol) + protected void drawTypeLine(Graphics2D g, int x, int y, int w, int h) { + // Draw expansion symbol + int expansionSymbolWidth; + if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_RENDERING_SET_SYMBOL, "false").equals("false")) { + if (cardView.isAbility()) { + expansionSymbolWidth = 0; + } else { + expansionSymbolWidth = drawExpansionSymbol(g, x, y, w, h); + } + } else { + expansionSymbolWidth = 0; + } + + // Draw type line text + int availableWidth = w - expansionSymbolWidth + 1; + String types = getCardTypeLine(); + g.setFont(boxTextFont); + + // Replace "Legendary" in type line if there's not enough space + if (g.getFontMetrics().stringWidth(types) > availableWidth) { + types = types.replace("Legendary", "L."); + } + + if (!types.isEmpty()) { + AttributedString str = new AttributedString(types); + str.addAttribute(TextAttribute.FONT, boxTextFont); + TextMeasurer measure = new TextMeasurer(str.getIterator(), g.getFontRenderContext()); + TextLayout layout = measure.getLayout(0, measure.getLineBreakIndex(0, availableWidth)); + g.setColor(getBoxTextColor()); + layout.draw(g, x, y + boxTextOffset + boxTextHeight - 1); + } + } + + // Draw the P/T and/or Loyalty boxes + protected void drawBottomRight(Graphics2D g, Paint borderPaint, Color fill) { + // No bottom right for abilities + if (cardView.isAbility()) { + return; + } + + // Where to start drawing the things + int curY = cardHeight - (int) (0.03f * cardHeight); + + // Width of the boxes + int partWidth = (int) Math.max(30, 0.20f * cardWidth); + + // Is it a creature? + if (cardView.getCardTypes().contains(CardType.CREATURE)) { + int x = cardWidth - borderWidth - partWidth; + + // Draw PT box + CardRendererUtils.drawRoundedBox(g, + x, curY - boxHeight, + partWidth, boxHeight, + contentInset, + borderPaint, + fill); + + // Draw shadow line top + g.setColor(new Color(0, 0, 0, 150)); + g.fillRect( + x + contentInset, curY - boxHeight - 1, + partWidth - 2 * contentInset, 1); + + // Draw text + g.setColor(getBoxTextColor()); + g.setFont(ptTextFont); + String ptText = cardView.getPower() + "/" + cardView.getToughness(); + int ptTextWidth = g.getFontMetrics().stringWidth(ptText); + g.drawString(ptText, + x + (partWidth - ptTextWidth) / 2, curY - ptTextOffset - 1); + + // Does it have damage on it? + if ((cardView instanceof PermanentView) && ((PermanentView) cardView).getDamage() > 0) { + // Show marked damage + + } + + curY -= boxHeight; + } + + // Is it a walker? (But don't draw the box if it's a non-permanent view + // of a walker without a starting loyalty (EG: Arlin Kord's flipped side). + if (cardView.getCardTypes().contains(CardType.PLANESWALKER) + && (cardView instanceof PermanentView || !cardView.getStartingLoyalty().equals("0"))) { + // Draw the PW loyalty box + int w = partWidth; + int h = partWidth / 2; + int x = cardWidth - partWidth - borderWidth; + int y = curY - h; + + Polygon symbol = new Polygon( + new int[]{ + x + w / 2, + (int) (x + w * 0.9), + x + w, + (int) (x + w * 0.6), + x + w / 2, + (int) (x + w * 0.4), + x, + (int) (x + w * 0.1),}, + new int[]{ + y + h, + (int) (y + 0.8 * h), + y, + (int) (y - 0.2 * h), + y, + (int) (y - 0.2 * h), + y, + (int) (y + 0.8 * h),}, + 8); + + // Draw + stroke + g.setColor(Color.black); + g.fillPolygon(symbol); + g.setColor(new Color(200, 200, 200)); + g.setStroke(new BasicStroke(2)); + g.drawPolygon(symbol); + g.setStroke(new BasicStroke(1)); + + // Loyalty number + String loyalty; + if (cardView instanceof PermanentView) { + loyalty = cardView.getLoyalty(); + } else { + loyalty = cardView.getStartingLoyalty(); + } + + g.setFont(ptTextFont); + g.setColor(Color.white); + int loyaltyWidth = g.getFontMetrics().stringWidth(loyalty); + g.drawString(loyalty, x + (w - loyaltyWidth) / 2, y + ptTextHeight + (h - ptTextHeight) / 2); + + // Advance + curY -= (int) (1.2 * y); + } + + // does it have damage on it? + if ((cardView instanceof PermanentView) && ((PermanentView) cardView).getDamage() > 0) { + int x = cardWidth - partWidth - borderWidth; + int y = curY - boxHeight; + String damage = "" + ((PermanentView) cardView).getDamage(); + g.setFont(ptTextFont); + int txWidth = g.getFontMetrics().stringWidth(damage); + g.setColor(Color.red); + g.fillRect(x, y, partWidth, boxHeight); + g.setColor(Color.white); + g.drawRect(x, y, partWidth, boxHeight); + g.drawString(damage, x + (partWidth - txWidth) / 2, curY - 1); + } + } + + // Draw the card's textbox in a given rect + protected boolean loyaltyAbilityColorToggle = false; + + protected void drawRulesText(Graphics2D g, int x, int y, int w, int h) { + // Initial font size to try to render at + Font font = new Font("Arial", Font.PLAIN, 12); + Font fontItalic = new Font("Arial", Font.ITALIC, 12); + + // Handle the keyword rules + boolean hasKeywords = !textboxKeywords.isEmpty(); + String keywordRulesString = getKeywordRulesString(); + AttributedString keywordRulesAttributed = new AttributedString(keywordRulesString); + if (hasKeywords) { + keywordRulesAttributed.addAttribute(TextAttribute.FONT, font); + } + + // Get the total height + List attributedRules = new ArrayList<>(); + boolean useSmallFont = false; + int remaining = h; + { + if (hasKeywords) { + remaining -= drawSingleRule(g, keywordRulesAttributed, null, 0, 0, w, remaining, false); + } + for (TextboxRule rule : textboxRules) { + AttributedString attributed = rule.generateAttributedString(font, fontItalic); + attributedRules.add(attributed); + remaining -= drawSingleRule(g, attributed, rule, 0, 0, w, remaining, false); + if (remaining < 0) { + useSmallFont = true; + break; + } + } + } + + // If there wasn't enough room, try using a smaller font + if (useSmallFont) { + font = new Font("Arial", Font.PLAIN, 9); + fontItalic = new Font("Arial", Font.ITALIC, 9); + if (hasKeywords) { + keywordRulesAttributed = new AttributedString(keywordRulesString); + keywordRulesAttributed.addAttribute(TextAttribute.FONT, font); + } + + // Clear out the attributed rules and reatribute them with the new font size + attributedRules.clear(); + for (TextboxRule rule : textboxRules) { + AttributedString attributed = rule.generateAttributedString(font, fontItalic); + attributedRules.add(attributed); + } + + // Get the new spacing for the small text + remaining = h; + if (hasKeywords) { + remaining -= drawSingleRule(g, keywordRulesAttributed, null, 0, 0, w, remaining, false); + } + for (TextboxRule rule : textboxRules) { + AttributedString attributed = rule.generateAttributedString(font, fontItalic); + attributedRules.add(attributed); + remaining -= drawSingleRule(g, attributed, rule, 0, 0, w, remaining, false); + if (remaining < 0) { + useSmallFont = true; + break; + } + } + } + + // Do we have room for additional spacing between the parts of text? + // If so, calculate the spacing based on how much space was left over + int spacing; + if (remaining <= 0) { + spacing = 0; + } else { + spacing = (int) (remaining / (hasKeywords + ? (textboxRules.size() + 2) + : (textboxRules.size() + 1))); + } + + // Do the actual draw + loyaltyAbilityColorToggle = false; + g.setColor(Color.black); + int curY = y + spacing; + if (hasKeywords) { + int adv = drawSingleRule(g, keywordRulesAttributed, null, x, curY, w, h, true); + curY += adv + spacing; + h -= adv; + } + for (int i = 0; i < textboxRules.size(); ++i) { + TextboxRule rule = textboxRules.get(i); + AttributedString attributedRule = attributedRules.get(i); + int adv = drawSingleRule(g, attributedRule, rule, x, curY, w, h, true); + curY += adv + spacing; + h -= adv; + if (h < 0) { + break; + } + } + } + + // Get the first line of the textbox, the keyword string + private String getKeywordRulesString() { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < textboxKeywords.size(); ++i) { + builder.append(textboxKeywords.get(i).text); + if (i != textboxKeywords.size() - 1) { + builder.append(", "); + } + } + return builder.toString(); + } + + // Draw a single rule and returns the amount vertically advanced by, but + // only if doDraw is true. If doDraw is false, just returns the vertical + // advance if the rule were to be drawn. + private int drawSingleRule(Graphics2D g, AttributedString text, TextboxRule rule, int x, int y, int w, int h, boolean doDraw) { + // Inset, in case we are a leveler or loyalty ability + int inset = 0; + if (rule != null && rule.type == TextboxRuleType.LOYALTY) { + inset = cardWidth / 12; + } + int availWidth = w - inset; + + FontRenderContext frc = g.getFontRenderContext(); + AttributedCharacterIterator textIter = text.getIterator(); + LineBreakMeasurer measure = new LineBreakMeasurer(textIter, frc); + float yPos = y; + float remain = h; + AttributedCharacterIterator newLineCheck = text.getIterator(); + while (measure.getPosition() < textIter.getEndIndex()) { + // Advance iterator to next line break + char ch = newLineCheck.setIndex(measure.getPosition()); + while ((ch = newLineCheck.next()) != CharacterIterator.DONE) { + if (ch == '\n') { + break; + } + } + + // Get the text layout + TextLayout layout = measure.nextLayout(availWidth, newLineCheck.getIndex(), false); + float ascent = layout.getAscent(); + yPos += ascent; + remain -= ascent; + if (remain < 0) { + break; + } + if (doDraw) { + g.setColor(Color.black); + layout.draw(g, x + inset, yPos); + } + yPos += layout.getDescent() + layout.getLeading() - 2; + } + + // Advance + int advance = ((int) Math.ceil(yPos)) - y; + + // Is it a loyalty ability? + if (rule != null && rule.type == TextboxRuleType.LOYALTY) { + TextboxLoyaltyRule loyaltyRule = (TextboxLoyaltyRule) rule; + Polygon symbol; + int symbolWidth = (x + inset) - borderWidth - 4; + int symbolHeight = (int) (0.7f * symbolWidth); + if (symbolHeight > advance) { + advance = symbolHeight; + } + int symbolX = x - borderWidth; + int symbolY = y + (advance - symbolHeight) / 2; + if (doDraw) { + if (loyaltyRule.loyaltyChange < 0 || loyaltyRule.loyaltyChange == TextboxLoyaltyRule.MINUS_X) { + symbol = new Polygon( + new int[]{ + symbolX, + symbolX + symbolWidth, + symbolX + symbolWidth, + symbolX + symbolWidth / 2, + symbolX,}, + new int[]{ + symbolY, + symbolY, + symbolY + symbolHeight - 3, + symbolY + symbolHeight + 3, + symbolY + symbolHeight - 3,}, + 5); + } else if (loyaltyRule.loyaltyChange > 0) { + symbol = new Polygon( + new int[]{ + symbolX, + symbolX + symbolWidth / 2, + symbolX + symbolWidth, + symbolX + symbolWidth, + symbolX,}, + new int[]{ + symbolY + 3, + symbolY - 3, + symbolY + 3, + symbolY + symbolHeight, + symbolY + symbolHeight,}, + 5); + } else { + symbol = new Polygon( + new int[]{ + symbolX, + symbolX + symbolWidth, + symbolX + symbolWidth, + symbolX,}, + new int[]{ + symbolY, + symbolY, + symbolY + symbolHeight, + symbolY + symbolHeight,}, + 4); + } + g.setColor(new Color(0, 0, 0, 128)); + g.fillRect(x + 2, y + advance + 1, w - 2, 1); + g.setColor(Color.black); + g.fillPolygon(symbol); + g.setColor(new Color(200, 200, 200)); + g.setStroke(new BasicStroke(2)); + g.drawPolygon(symbol); + g.setStroke(new BasicStroke(1)); + g.setColor(Color.white); + g.setFont(boxTextFont); + String loyaltyString = loyaltyRule.getChangeString(); + int textWidth = g.getFontMetrics().stringWidth(loyaltyString); + g.drawString(loyaltyString, + symbolX + (symbolWidth - textWidth) / 2, + symbolY + symbolHeight - (symbolHeight - boxTextHeight) / 2); + + advance += 3; + loyaltyAbilityColorToggle = !loyaltyAbilityColorToggle; + } + } + + return advance; + } + + // Draw the transformation circle if there is one, and return the + // horizontal width taken up into the content space by it. + protected boolean isNightCard() { + return isTransformed; + } + + protected boolean isTransformCard() { + return cardView.canTransform() || isTransformed; + } + + protected int drawTransformationCircle(Graphics2D g, Paint borderPaint) { + int transformCircleOffset = 0; + if (isTransformCard()) { + transformCircleOffset = boxHeight - contentInset; + g.setPaint(borderPaint); + g.drawOval(borderWidth, totalContentInset, boxHeight - 1, boxHeight - 1); + g.setColor(Color.black); + g.fillOval(borderWidth + 1, totalContentInset + 1, boxHeight - 2, boxHeight - 2); + g.setColor(Color.white); + if (isNightCard()) { + g.fillArc(borderWidth + 3, totalContentInset + 3, boxHeight - 6, boxHeight - 6, 90, 270); + g.setColor(Color.black); + g.fillArc(borderWidth + 3 + 3, totalContentInset + 3, boxHeight - 6 - 3, boxHeight - 6, 90, 270); + } else { + g.fillOval(borderWidth + 3, totalContentInset + 3, boxHeight - 6, boxHeight - 6); + } + } + return transformCircleOffset; + } + + // Get the text height for a given box height + protected static int getTextHeightForBoxHeight(int h) { + if (h < 15) { + return h - 3; + } else { + return (int) Math.ceil(.6 * h); + } + } + + protected static int getPTTextHeightForLineHeight(int h) { + return h - 4; + } + + // Determine the color of the name / type line text + protected Color getBoxTextColor() { + if (isNightCard()) { + return Color.white; + } else if (cardView.isAbility()) { + return Color.white; + } else { + return Color.black; + } + } + + // Determine the colors to base the frame on + protected ObjectColor getFrameObjectColor() { + // TODO: Take into account devoid, land frame colors, etc + return cardView.getColor().union(cardView.getFrameColor()); + } + + // Determine which background paint to use from a set of colors + // and the current card. + protected static Paint getBackgroundPaint(ObjectColor colors, Collection types) { + if (types.contains(CardType.LAND)) { + return BG_TEXTURE_LAND; + } else if (types.contains(CardType.ARTIFACT)) { + return BG_TEXTURE_ARTIFACT; + } else if (colors.isMulticolored()) { + return BG_TEXTURE_GOLD; + } else if (colors.isWhite()) { + return BG_TEXTURE_WHITE; + } else if (colors.isBlue()) { + return BG_TEXTURE_BLUE; + } else if (colors.isBlack()) { + return BG_TEXTURE_BLACK; + } else if (colors.isRed()) { + return BG_TEXTURE_RED; + } else if (colors.isGreen()) { + return BG_TEXTURE_GREEN; + } else { + // Colorless + return new Color(71, 86, 101); + } + } + + // Get the box color for the given colors + protected Color getBoxColor(ObjectColor colors, Collection types, boolean isNightCard) { + if (cardView.isAbility()) { + return Color.BLACK; + } else if (colors.getColorCount() == 2 && types.contains(CardType.LAND)) { + // Special case for two color lands. Boxes should be normal land colored + // rather than multicolor. Three or greater color lands use a multi-color + // box as normal. + return BOX_LAND; + } else if (colors.isMulticolored()) { + return isNightCard ? BOX_GOLD_NIGHT : BOX_GOLD; + } else if (colors.isColorless()) { + if (types.contains(CardType.LAND)) { + return BOX_LAND; + } else { + return isNightCard ? BOX_COLORLESS_NIGHT : BOX_COLORLESS; + } + } else if (colors.isWhite()) { + return isNightCard ? BOX_WHITE_NIGHT : BOX_WHITE; + } else if (colors.isBlue()) { + return isNightCard ? BOX_BLUE_NIGHT : BOX_BLUE; + } else if (colors.isBlack()) { + return isNightCard ? BOX_BLACK_NIGHT : BOX_BLACK; + } else if (colors.isRed()) { + return isNightCard ? BOX_RED_NIGHT : BOX_RED; + } else if (colors.isGreen()) { + return isNightCard ? BOX_GREEN_NIGHT : BOX_GREEN; + } else { + return ERROR_COLOR; + } + } + + // Get the border color for a single color + protected static Color getBorderColor(ObjectColor color) { + if (color.isWhite()) { + return BORDER_WHITE; + } else if (color.isBlue()) { + return BORDER_BLUE; + } else if (color.isBlack()) { + return BORDER_BLACK; + } else if (color.isRed()) { + return BORDER_RED; + } else if (color.isGreen()) { + return BORDER_GREEN; + } else { + return ERROR_COLOR; + } + } + + // Determine the border paint to use, based on an ObjectColors + protected static Paint getBorderPaint(ObjectColor colors, Collection types, int width) { + if (colors.isMulticolored()) { + if (colors.getColorCount() == 2) { + List twoColors = colors.getColors(); + + // Two-color frames look better if we use a whiter white + // than the normal white frame color for them, as the normal + // white border color is very close to the gold background + // color. + Color color1, color2; + if (twoColors.get(0).isWhite()) { + color1 = new Color(240, 240, 240); + } else { + color1 = getBorderColor(twoColors.get(0)); + } + if (twoColors.get(1).isWhite()) { + color2 = new Color(240, 240, 240); + } else { + color2 = getBorderColor(twoColors.get(1)); + } + + // Special case for two colors, gradient paint + return new LinearGradientPaint( + 0, 0, width, 0, + new float[]{0.4f, 0.6f}, + new Color[]{color1, color2}); + } else { + return BORDER_GOLD; + } + } else if (colors.isColorless()) { + if (types.contains(CardType.LAND)) { + return BORDER_LAND; + } else { + return BORDER_COLORLESS; + } + } else { + return getBorderColor(colors); + } + } + + // Determine the textbox color for a single color + protected static Color getTextboxColor(ObjectColor color) { + if (color.isWhite()) { + return TEXTBOX_WHITE; + } else if (color.isBlue()) { + return TEXTBOX_BLUE; + } else if (color.isBlack()) { + return TEXTBOX_BLACK; + } else if (color.isRed()) { + return TEXTBOX_RED; + } else if (color.isGreen()) { + return TEXTBOX_GREEN; + } else { + return ERROR_COLOR; + } + } + + // Determine the border paint to use, based on an ObjectColors + protected static Paint getTextboxPaint(ObjectColor colors, Collection types, int width) { + if (colors.isMulticolored()) { + if (colors.getColorCount() == 2) { + List twoColors = colors.getColors(); + + // Special case for two colors, gradient paint + return new LinearGradientPaint( + 0, 0, width, 0, + new float[]{0.4f, 0.6f}, + new Color[]{ + getTextboxColor(twoColors.get(0)), + getTextboxColor(twoColors.get(1)) + }); + } else { + return TEXTBOX_GOLD; + } + } else if (colors.isColorless()) { + if (types.contains(CardType.LAND)) { + return TEXTBOX_LAND; + } else { + return TEXTBOX_COLORLESS; + } + } else { + return getTextboxColor(colors); + } + } +} diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/TextboxKeywordRule.java b/Mage.Client/src/main/java/org/mage/card/arcane/TextboxKeywordRule.java new file mode 100644 index 0000000000..50e15b04aa --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/card/arcane/TextboxKeywordRule.java @@ -0,0 +1,17 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.mage.card.arcane; + +import java.util.List; + +/** + * @author stravant@gmail.com + */ +public class TextboxKeywordRule extends TextboxRule { + public TextboxKeywordRule(String text, List regions) { + super(text, regions, TextboxRuleType.SIMPLE_KEYWORD); + } +} diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/TextboxLevelRule.java b/Mage.Client/src/main/java/org/mage/card/arcane/TextboxLevelRule.java new file mode 100644 index 0000000000..207e2dee90 --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/card/arcane/TextboxLevelRule.java @@ -0,0 +1,28 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.mage.card.arcane; + +import java.util.List; + +/** + * @author StravantUser + * + * Level rule associated with leveler cards + */ +public class TextboxLevelRule extends TextboxRule { + + // The levels that this rule applies to + public int levelFrom; + public int levelTo; + + public static int AND_HIGHER = 100; + + public TextboxLevelRule(String text, List regions, int levelFrom, int levelTo) { + super(text, regions, TextboxRuleType.LEVEL); + this.levelFrom = levelFrom; + this.levelTo = levelTo; + } +} diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/TextboxLoyaltyRule.java b/Mage.Client/src/main/java/org/mage/card/arcane/TextboxLoyaltyRule.java new file mode 100644 index 0000000000..50d1ae633a --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/card/arcane/TextboxLoyaltyRule.java @@ -0,0 +1,33 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.mage.card.arcane; + +import java.util.List; + +/** + * @author StravantUser + */ +public class TextboxLoyaltyRule extends TextboxRule { + + public int loyaltyChange; + + public static int MINUS_X = 100; + + public String getChangeString() { + if (loyaltyChange == MINUS_X) { + return "-X"; + } else if (loyaltyChange > 0) { + return "+" + loyaltyChange; + } else { + return "" + loyaltyChange; + } + } + + public TextboxLoyaltyRule(String text, List regions, int loyaltyChange) { + super(text, regions, TextboxRuleType.LOYALTY); + this.loyaltyChange = loyaltyChange; + } +} diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/TextboxRule.java b/Mage.Client/src/main/java/org/mage/card/arcane/TextboxRule.java new file mode 100644 index 0000000000..063685782c --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/card/arcane/TextboxRule.java @@ -0,0 +1,98 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.mage.card.arcane; + +import java.awt.Font; +import java.awt.Image; +import java.awt.font.GraphicAttribute; +import java.awt.font.ImageGraphicAttribute; +import java.awt.font.TextAttribute; +import java.text.AttributedString; +import java.util.List; + +/** + * @author stravant@gmail.com + * + * Class describing parsed & translated rules in the text box of a card, ready + * to be rendered. + */ +public class TextboxRule { + + // An attributed region in the text, which can be applied to an + // attributed string. + public interface AttributeRegion { + + public void applyToAttributedString(AttributedString str, Font normal, Font italic); + } + + // A region of italics, or bold text in a + public static class ItalicRegion implements AttributeRegion { + + ItalicRegion(int start, int end) { + this.start = start; + this.end = end; + } + private final int start; + private final int end; + + @Override + public void applyToAttributedString(AttributedString str, Font normal, Font italic) { + if (end > start + 1) { + str.addAttribute(TextAttribute.FONT, italic, start, end); + } + } + } + + // A special symbol embedded at some point in a string + public static class EmbeddedSymbol implements AttributeRegion { + + EmbeddedSymbol(String symbol, int location) { + this.symbol = symbol; + this.location = location; + } + private final String symbol; + private final int location; + + @Override + public void applyToAttributedString(AttributedString str, Font normal, Font italic) { + Image symbolImage = ManaSymbols.getSizedManaSymbol(symbol.replace("/", ""), normal.getSize()); + if (symbolImage != null) { + ImageGraphicAttribute imgAttr + = new ImageGraphicAttribute(symbolImage, GraphicAttribute.BOTTOM_ALIGNMENT); + str.addAttribute(TextAttribute.CHAR_REPLACEMENT, imgAttr, location, location + 1); + } + } + } + + public String text; + public TextboxRuleType type; + + private List regions; + + protected TextboxRule(String text, List regions, TextboxRuleType type) { + this.text = text; + this.type = type; + this.regions = regions; + } + + public TextboxRule(String text, List regions) { + this(text, regions, TextboxRuleType.NORMAL); + } + + public AttributedString generateAttributedString(Font normal, Font italic) { + // Build the final attributed text using the regions + // Do it in reverse order for proper handling of regions where + // there are multiple attributes stacked (EG: bold + italic) + AttributedString attributedRule = new AttributedString(text); + if (text.length() != 0) { + attributedRule.addAttribute(TextAttribute.FONT, normal); + for (int i = regions.size() - 1; i >= 0; --i) { + regions.get(i).applyToAttributedString(attributedRule, normal, italic); + } + } + return attributedRule; + } +} diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/TextboxRuleParser.java b/Mage.Client/src/main/java/org/mage/card/arcane/TextboxRuleParser.java new file mode 100644 index 0000000000..021e150ad6 --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/card/arcane/TextboxRuleParser.java @@ -0,0 +1,251 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.mage.card.arcane; + +import java.awt.Image; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Deque; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import mage.view.CardView; +import org.apache.log4j.Logger; + +/** + * + * @author StravantUser + */ +public class TextboxRuleParser { + + private static final Logger LOGGER = Logger.getLogger(CardPanel.class); + + private static final Pattern LevelAbilityPattern = Pattern.compile("Level (\\d+)-?(\\d*)(\\+?)"); + private static final Pattern LoyaltyAbilityPattern = Pattern.compile("^(\\+|\\-)(\\d+|X): "); + private static final Pattern SimpleKeywordPattern = Pattern.compile("^(\\w+( \\w+)?)\\s*(\\([^\\)]*\\))?\\s*$"); + + // Parse a given rule (given as a string) into a TextboxRule, replacing + // symbol annotations, italics, etc, parsing out information such as + // if the ability is a loyalty ability, and returning an TextboxRule + // representing that information, which can be used to render the rule in + // the textbox of a card. + public static TextboxRule parse(CardView source, String rule) { + // List of regions to apply + ArrayList regions = new ArrayList<>(); + + // Leveler / loyalty + boolean isLeveler = false; + int levelFrom = 0; + int levelTo = 0; + + boolean isLoyalty = false; + int loyaltyChange = 0; + + // Parse the attributedString contents + int index = 0; + int outputIndex = 0; + + // Is it a simple keyword ability? + { + Matcher simpleKeywordMatch = SimpleKeywordPattern.matcher(rule); + if (simpleKeywordMatch.find()) { + return new TextboxKeywordRule(simpleKeywordMatch.group(1), regions); + } + } + + // Check if it's a loyalty ability. Must be right at the start of the rule + { + Matcher loyaltyMatch = LoyaltyAbilityPattern.matcher(rule); + if (loyaltyMatch.find()) { + // Get the loyalty change + if (loyaltyMatch.group(2).equals("X")) { + loyaltyChange = TextboxLoyaltyRule.MINUS_X; + } else { + loyaltyChange = Integer.parseInt(loyaltyMatch.group(2)); + if (loyaltyMatch.group(1).equals("-")) { + loyaltyChange = -loyaltyChange; + } + } + isLoyalty = true; + + // Go past the match + index = loyaltyMatch.group().length(); + } + } + + Deque openingStack = new ArrayDeque<>(); + StringBuilder build = new StringBuilder(); + while (index < rule.length()) { + int initialIndex = index; + char ch = rule.charAt(index); + switch (ch) { + case '{': { + // Handling for `{this}` + int closeIndex = rule.indexOf('}', index); + if (closeIndex == -1) { + // Malformed input, nothing to do + ++index; + ++outputIndex; + build.append(ch); + } else { + String contents = rule.substring(index + 1, closeIndex); + if (contents.equals("this") || contents.equals("source")) { + // Replace {this} with the card's name + String cardName = source.getName(); + build.append(cardName); + index += contents.length() + 2; + outputIndex += cardName.length(); + } else { + Image symbol = ManaSymbols.getSizedManaSymbol(contents.replace("/", ""), 10); + if (symbol != null) { + // Mana or other inline symbol + build.append('#'); + regions.add(new TextboxRule.EmbeddedSymbol(contents, outputIndex)); + ++outputIndex; + index = closeIndex + 1; + } else { + // Bad entry + build.append('{'); + build.append(contents); + build.append('}'); + index = closeIndex + 1; + outputIndex += (contents.length() + 2); + } + } + } + break; + } + case '&': + // Handling for `—` + if (rule.startsWith("—", index)) { + build.append('—'); + index += 7; + ++outputIndex; + } else if (rule.startsWith("&bull", index)) { + build.append('•'); + index += 5; + ++outputIndex; + } else { + LOGGER.error("Bad &...; sequence `" + rule.substring(index + 1, index + 10) + "` in rule."); + build.append('&'); + ++index; + ++outputIndex; + } + break; + case '<': { + // Handling for `` and `
` + int closeIndex = rule.indexOf('>', index); + if (closeIndex != -1) { + // Is a tag + String tag = rule.substring(index + 1, closeIndex); + if (tag.charAt(tag.length() - 1) == '/') { + // Pure closing tag (like
) + if (tag.equals("br/")) { + build.append('\n'); + ++outputIndex; + } else { + // Unknown + build.append('<').append(tag).append('>'); + outputIndex += (tag.length() + 2); + } + } else if (tag.charAt(0) == '/') { + // Opening index for the tag + int openingIndex; + if (openingStack.isEmpty()) { + // Malformed input, just make an empty interval + openingIndex = outputIndex; + } else { + openingIndex = openingStack.pop(); + } + + // What tag is it? + switch (tag) { + case "/i": + // Italics + regions.add(new TextboxRule.ItalicRegion(openingIndex, outputIndex)); + break; + case "/b": + // Bold, see if it's a level ability + String content = build.substring(openingIndex); + Matcher levelMatch = LevelAbilityPattern.matcher(content); + if (levelMatch.find()) { + try { + levelFrom = Integer.parseInt(levelMatch.group(1)); + if (!levelMatch.group(2).equals("")) { + levelTo = Integer.parseInt(levelMatch.group(2)); + } + if (!levelMatch.group(3).equals("")) { + levelTo = TextboxLevelRule.AND_HIGHER; + } + isLeveler = true; + } catch (Exception e) { + LOGGER.error("Bad leveler levels in rule `" + rule + "`."); + } + } + break; + default: + // Unknown + build.append('<').append(tag).append('>'); + outputIndex += (tag.length() + 2); + break; + } + } else // Is it a
tag special case? [Why can't it have a closing `/`... =( ] + { + if (tag.equals("br")) { + build.append('\n'); + ++outputIndex; + } else { + // Opening tag + openingStack.push(outputIndex); + } + } + // Skip characters + index = closeIndex + 1; + } else { + // Malformed tag + build.append('<'); + ++outputIndex; + ++index; + } + break; + } + default: + // Normal character + ++index; + ++outputIndex; + build.append(ch); + break; + } + if (outputIndex != build.length()) { + // Somehow our parsing code output symbols but didn't update the output index correspondingly + LOGGER.error("The human is dead; mismatch! Failed on rule: `" + rule + "` due to not updating outputIndex properly."); + + // Bail out + build = new StringBuilder(rule); + regions.clear(); + break; + } + if (index == initialIndex) { + // Somehow our parsing failed to consume the + LOGGER.error("Failed on rule `" + rule + "` due to not consuming a character."); + + // Bail out + build = new StringBuilder(rule); + regions.clear(); + break; + } + } + + // Build and return the rule + rule = build.toString(); + if (isLoyalty) { + return new TextboxLoyaltyRule(rule, regions, loyaltyChange); + } else if (isLeveler) { + return new TextboxLevelRule(rule, regions, levelFrom, levelTo); + } else { + return new TextboxRule(rule, regions); + } + } +} diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/TextboxRuleType.java b/Mage.Client/src/main/java/org/mage/card/arcane/TextboxRuleType.java new file mode 100644 index 0000000000..4903130db4 --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/card/arcane/TextboxRuleType.java @@ -0,0 +1,25 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.mage.card.arcane; + +/** + * @author stravant@gmail.com + */ +public enum TextboxRuleType { + /* Normal abilities, just rendered as lines of text with embedded symbols + * replaced to the relevant images. */ + NORMAL, + + /* Keyword ability. To be displayed in the comma separated list at the + * very top of the rules box */ + SIMPLE_KEYWORD, + + /* Loyalty abilities on planeswalkers */ + LOYALTY, + + /* Levelup creature - static ability at a given level */ + LEVEL +} diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java b/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java index 4be38a3456..3c53fa20f7 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java @@ -17,6 +17,7 @@ import javax.swing.JDialog; import javax.swing.JLayeredPane; import mage.cards.MagePermanent; import mage.cards.action.ActionCallback; +import mage.client.dialog.PreferencesDialog; import mage.client.util.GUISizeHelper; import mage.constants.Rarity; import mage.interfaces.plugin.CardPlugin; @@ -31,6 +32,7 @@ import net.xeoh.plugins.base.annotations.meta.Author; import org.apache.log4j.Logger; import org.mage.card.arcane.Animation; import org.mage.card.arcane.CardPanel; +import org.mage.card.arcane.CardPanelComponentImpl; import org.mage.card.arcane.ManaSymbols; import org.mage.plugins.card.dl.DownloadGui; import org.mage.plugins.card.dl.DownloadJob; @@ -41,6 +43,7 @@ import org.mage.plugins.card.dl.sources.GathererSets; import org.mage.plugins.card.dl.sources.GathererSymbols; import org.mage.plugins.card.images.ImageCache; import org.mage.plugins.card.info.CardInfoPaneImpl; +import org.mage.card.arcane.CardPanelRenderImpl; /** * {@link CardPlugin} implementation. @@ -105,10 +108,23 @@ public class CardPluginImpl implements CardPlugin { cardWidthMin = (int) GUISizeHelper.battlefieldCardMinDimension.getWidth(); cardWidthMax = (int) GUISizeHelper.battlefieldCardMaxDimension.getWidth(); } + + /** + * Temporary card rendering shim. Split card rendering isn't implemented yet, so + * use old component based rendering for the split cards. + */ + private CardPanel makePanel(CardView view, UUID gameId, boolean loadImage, ActionCallback callback, boolean isFoil, Dimension dimension) { + String fallback = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_RENDERING_FALLBACK, "false"); + if (view.isSplitCard() || fallback.equals("true")) { + return new CardPanelComponentImpl(view, gameId, loadImage, callback, isFoil, dimension); + } else { + return new CardPanelRenderImpl(view, gameId, loadImage, callback, isFoil, dimension); + } + } @Override public MagePermanent getMagePermanent(PermanentView permanent, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage) { - CardPanel cardPanel = new CardPanel(permanent, gameId, loadImage, callback, false, dimension); + CardPanel cardPanel = makePanel(permanent, gameId, loadImage, callback, false, dimension); boolean implemented = !permanent.getRarity().equals(Rarity.NA); cardPanel.setShowCastingCost(implemented); return cardPanel; @@ -116,7 +132,7 @@ public class CardPluginImpl implements CardPlugin { @Override public MagePermanent getMageCard(CardView cardView, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage) { - CardPanel cardPanel = new CardPanel(cardView, gameId, loadImage, callback, false, dimension); + CardPanel cardPanel = makePanel(cardView, gameId, loadImage, callback, false, dimension); boolean implemented = cardView.getRarity() != null && !cardView.getRarity().equals(Rarity.NA); cardPanel.setShowCastingCost(implemented); return cardPanel; diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/images/CardDownloadData.java b/Mage.Client/src/main/java/org/mage/plugins/card/images/CardDownloadData.java index 7155869366..49a780eec6 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/images/CardDownloadData.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/images/CardDownloadData.java @@ -12,6 +12,7 @@ public class CardDownloadData { private String downloadName; private String set; private String tokenSetCode; + private String tokenDescriptor; private String collectorId; private Integer type; private boolean token; @@ -23,15 +24,15 @@ public class CardDownloadData { private boolean usesVariousArt; private boolean isType2; - public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode) { - this(name, set, collectorId, usesVariousArt, type, tokenSetCode, false); + public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, String tokenDescriptor) { + this(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor, false); } - public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, boolean token) { - this(name, set, collectorId, usesVariousArt, type, tokenSetCode, token, false, false); + public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, String tokenDescriptor, boolean token) { + this(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor, token, false, false); } - public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, boolean token, boolean twoFacedCard, boolean secondSide) { + public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, String tokenDescriptor, boolean token, boolean twoFacedCard, boolean secondSide) { this.name = name; this.set = set; this.collectorId = collectorId; @@ -41,6 +42,7 @@ public class CardDownloadData { this.twoFacedCard = twoFacedCard; this.secondSide = secondSide; this.tokenSetCode = tokenSetCode; + this.tokenDescriptor = tokenDescriptor; } public CardDownloadData(final CardDownloadData card) { @@ -117,7 +119,7 @@ public class CardDownloadData { public String getSet() { return set; } - + public void setSet(String set) { this.set = set; } @@ -130,6 +132,13 @@ public class CardDownloadData { this.tokenSetCode = tokenSetCode; } + public String getTokenDescriptor() { + return tokenDescriptor; + } + + public void setTokenDescriptor(String tokenDescriptor) { + this.tokenDescriptor = tokenDescriptor; + } public boolean isToken() { return token; } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java index fd45594345..339db215fe 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java @@ -239,7 +239,8 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab TFile file; for (CardInfo card : allCards) { if (!card.getCardNumber().isEmpty() && !"0".equals(card.getCardNumber()) && !card.getSetCode().isEmpty()) { - CardDownloadData url = new CardDownloadData(card.getName(), card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", false, card.isDoubleFaced(), card.isNightCard()); + CardDownloadData url = new CardDownloadData(card.getName(), card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), + 0, "", "", false, card.isDoubleFaced(), card.isNightCard()); file = new TFile(CardImageUtils.generateImagePath(url)); if (!file.exists()) { return true; @@ -285,7 +286,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab && !ignoreUrls.contains(card.getSetCode())) { String cardName = card.getName(); boolean isType2 = type2SetsFilter.contains(card.getSetCode()); - CardDownloadData url = new CardDownloadData(cardName, card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", false, card.isDoubleFaced(), card.isNightCard()); + CardDownloadData url = new CardDownloadData(cardName, card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", "", false, card.isDoubleFaced(), card.isNightCard()); if (url.getUsesVariousArt()) { url.setDownloadName(createDownloadName(card)); } @@ -299,7 +300,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab if (card.getSecondSideName() == null || card.getSecondSideName().trim().isEmpty()) { throw new IllegalStateException("Second side card can't have empty name."); } - url = new CardDownloadData(card.getSecondSideName(), card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", false, card.isDoubleFaced(), true); + url = new CardDownloadData(card.getSecondSideName(), card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", "", false, card.isDoubleFaced(), true); url.setType2(isType2); allCardsUrls.add(url); } @@ -307,7 +308,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab if (card.getFlipCardName() == null || card.getFlipCardName().trim().isEmpty()) { throw new IllegalStateException("Flipped card can't have empty name."); } - url = new CardDownloadData(card.getFlipCardName(), card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", false, card.isDoubleFaced(), card.isNightCard()); + url = new CardDownloadData(card.getFlipCardName(), card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", "", false, card.isDoubleFaced(), card.isNightCard()); url.setFlipCard(true); url.setFlippedSide(true); url.setType2(isType2); @@ -385,19 +386,19 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab } if (params[1].toLowerCase().equals("generate") && params[2].startsWith("TOK:")) { String set = params[2].substring(4); - CardDownloadData card = new CardDownloadData(params[3], set, "0", false, type, "", true); + CardDownloadData card = new CardDownloadData(params[3], set, "0", false, type, "", "", true); list.add(card); } else if (params[1].toLowerCase().equals("generate") && params[2].startsWith("EMBLEM:")) { String set = params[2].substring(7); - CardDownloadData card = new CardDownloadData("Emblem " + params[3], set, "0", false, type, "", true); + CardDownloadData card = new CardDownloadData("Emblem " + params[3], set, "0", false, type, "", "", true); list.add(card); } else if (params[1].toLowerCase().equals("generate") && params[2].startsWith("EMBLEM-:")) { String set = params[2].substring(8); - CardDownloadData card = new CardDownloadData(params[3] + " Emblem", set, "0", false, type, "", true); + CardDownloadData card = new CardDownloadData(params[3] + " Emblem", set, "0", false, type, "", "", true); list.add(card); } else if (params[1].toLowerCase().equals("generate") && params[2].startsWith("EMBLEM!:")) { String set = params[2].substring(8); - CardDownloadData card = new CardDownloadData(params[3], set, "0", false, type, "", true); + CardDownloadData card = new CardDownloadData(params[3], set, "0", false, type, "", "", true); list.add(card); } } else { diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/images/ImageCache.java b/Mage.Client/src/main/java/org/mage/plugins/card/images/ImageCache.java index db0d9958ba..97a86655c2 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/images/ImageCache.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/images/ImageCache.java @@ -47,7 +47,7 @@ public class ImageCache { /** * Common pattern for keys. Format: "##" */ - private static final Pattern KEY_PATTERN = Pattern.compile("(.*)#(.*)#(.*)#(.*)#(.*)"); + private static final Pattern KEY_PATTERN = Pattern.compile("(.*)#(.*)#(.*)#(.*)#(.*)#(.*)"); static { IMAGE_CACHE = new MapMaker().softValues().makeComputingMap(new Function() { @@ -56,12 +56,12 @@ public class ImageCache { try { boolean usesVariousArt = false; - if (key.endsWith("#usesVariousArt")) { + if (key.matches(".*#usesVariousArt.*")) { usesVariousArt = true; key = key.replace("#usesVariousArt", ""); } boolean thumbnail = false; - if (key.endsWith("#thumb")) { + if (key.matches(".*#thumb.*")) { thumbnail = true; key = key.replace("#thumb", ""); } @@ -76,8 +76,9 @@ public class ImageCache { collectorId = "0"; } String tokenSetCode = m.group(5); + String tokenDescriptor = m.group(6); - CardDownloadData info = new CardDownloadData(name, set, collectorId, usesVariousArt, type, tokenSetCode); + CardDownloadData info = new CardDownloadData(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor); String path; if (collectorId.isEmpty() || "0".equals(collectorId)) { @@ -154,7 +155,7 @@ public class ImageCache { } public static BufferedImage getMorphImage() { - CardDownloadData info = new CardDownloadData("Morph", "KTK", "0", false, 0, "KTK"); + CardDownloadData info = new CardDownloadData("Morph", "KTK", "0", false, 0, "KTK", ""); info.setToken(true); String path = CardImageUtils.generateTokenImagePath(info); if (path == null) { @@ -165,7 +166,7 @@ public class ImageCache { } public static BufferedImage getManifestImage() { - CardDownloadData info = new CardDownloadData("Manifest", "FRF", "0", false, 0, "FRF"); + CardDownloadData info = new CardDownloadData("Manifest", "FRF", "0", false, 0, "FRF", ""); info.setToken(true); String path = CardImageUtils.generateTokenImagePath(info); if (path == null) { @@ -200,6 +201,10 @@ public class ImageCache { public static BufferedImage getThumbnail(CardView card) { return getImage(getKey(card, card.getName(), "#thumb")); } + + public static BufferedImage tryGetThumbnail(CardView card) { + return tryGetImage(getKey(card, card.getName(), "#thumb")); + } public static BufferedImage getImageOriginal(CardView card) { return getImage(getKey(card, card.getName(), "")); @@ -230,6 +235,18 @@ public class ImageCache { return null; } } + + /** + * Returns the Image corresponding to the key only if it already exists + * in the cache. + */ + private static BufferedImage tryGetImage(String key) { + if (IMAGE_CACHE.containsKey(key)) { + return IMAGE_CACHE.get(key); + } else { + return null; + } + } /** * Returns the map key for a card, without any suffixes for the image size. @@ -238,8 +255,8 @@ public class ImageCache { return name + "#" + card.getExpansionSetCode() + "#" + card.getType() + "#" + card.getCardNumber() + "#" + (card.getTokenSetCode() == null ? "" : card.getTokenSetCode()) + suffix - + (card.getUsesVariousArt() ? "#usesVariousArt" : ""); - + + (card.getUsesVariousArt() ? "#usesVariousArt" : "") + + (card.getTokenDescriptor() != null ? "#" + card.getTokenDescriptor() : "#"); } // /** @@ -343,6 +360,34 @@ public class ImageCache { return TransformedImageCache.getResizedImage(original, (int) (original.getWidth() * scale), (int) (original.getHeight() * scale)); } + + /** + * Returns the image appropriate to display for a card in a picture panel, but + * only it was ALREADY LOADED. That is, the call is immediate and will not block + * on file IO. + * @param card + * @param width + * @param height + * @return + */ + public static BufferedImage tryGetImage(CardView card, int width, int height) { + if (Constants.THUMBNAIL_SIZE_FULL.width + 10 > width) { + return tryGetThumbnail(card); + } + String key = getKey(card, card.getName(), Integer.toString(width)); + BufferedImage original = tryGetImage(key); + if (original == null) { + LOGGER.debug(key + " not found"); + return null; + } + + double scale = Math.min((double) width / original.getWidth(), (double) height / original.getHeight()); + if (scale >= 1) { + return original; + } + + return TransformedImageCache.getResizedImage(original, (int) (original.getWidth() * scale), (int) (original.getHeight() * scale)); + } public static TFile getTFile(String path) { try { diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java b/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java index 639c0590c9..8e69839c56 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java @@ -42,7 +42,7 @@ public class CardImageUtils { return filePath; } } - log.warn("Token image file not found: " + card.getTokenSetCode() + " - " + card.getName()); + log.warn("Token image file not found: " + card.getTokenSetCode() + " - " + card.getName()); return null; } @@ -50,6 +50,11 @@ public class CardImageUtils { String filename = generateImagePath(card); TFile file = new TFile(filename); + if (!file.exists()) { + filename = generateTokenDescriptorImagePath(card); + } + + file = new TFile(filename); if (!file.exists()) { CardDownloadData updated = new CardDownloadData(card); updated.setName(card.getName() + " 1"); @@ -86,7 +91,7 @@ public class CardImageUtils { // return path; // } // } - return ""; + return generateTokenDescriptorImagePath(card); } public static String updateSet(String cardSet, boolean forUrl) { @@ -102,17 +107,28 @@ public class CardImageUtils { private static String getImageDir(CardDownloadData card, String imagesPath) { if (card.getSet() == null) { - return ""; - } + return ""; + } String set = updateSet(card.getSet(), false).toUpperCase(); - String imagesDir = (imagesPath != null ? imagesPath : Constants.IO.imageBaseDir); + String imagesDir = (imagesPath != null ? imagesPath : Constants.IO.imageBaseDir); if (card.isToken()) { return buildTokenPath(imagesDir, set); } else { return buildPath(imagesDir, set); } } - + + private static String getTokenDescriptorImagePath(CardDownloadData card) { + String useDefault = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_USE_DEFAULT, "true"); + String imagesPath = useDefault.equals("true") ? null : PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PATH, null); + + if (PreferencesDialog.isSaveImagesToZip()) { + return imagesPath + TFile.separator + "TOK" + ".zip" + TFile.separator + card.getTokenDescriptor() + ".full.jpg"; + } else { + return imagesPath + TFile.separator + "TOK" + TFile.separator + card.getTokenDescriptor() + ".full.jpg"; + } + } + private static String buildTokenPath(String imagesDir, String set) { if (PreferencesDialog.isSaveImagesToZip()) { return imagesDir + TFile.separator + "TOK" + ".zip" + TFile.separator + set; @@ -156,7 +172,31 @@ public class CardImageUtils { return imageDir + TFile.separator + imageName; } - + + public static String generateTokenDescriptorImagePath(CardDownloadData card) { + String useDefault = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_USE_DEFAULT, "true"); + String imagesPath = useDefault.equals("true") ? null : PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PATH, null); + + String straightImageFile = getTokenDescriptorImagePath(card); + TFile file = new TFile(straightImageFile); + if (file.exists()) { + return straightImageFile; + } + + straightImageFile = straightImageFile.replaceFirst("\\.[0-9]+\\.[0-9]+", ".X.X"); + file = new TFile(straightImageFile); + if (file.exists()) { + return straightImageFile; + } + + straightImageFile = straightImageFile.replaceFirst("\\.X\\.X", ".S.S"); + file = new TFile(straightImageFile); + if (file.exists()) { + return straightImageFile; + } + return ""; + } + public static Proxy getProxyFromPreferences() { Preferences prefs = MageFrame.getPreferences(); Connection.ProxyType proxyType = Connection.ProxyType.valueByText(prefs.get("proxyType", "None")); diff --git a/Mage.Client/src/main/resources/cardrender/background_texture_artifact.png b/Mage.Client/src/main/resources/cardrender/background_texture_artifact.png new file mode 100644 index 0000000000..f34a1256d9 Binary files /dev/null and b/Mage.Client/src/main/resources/cardrender/background_texture_artifact.png differ diff --git a/Mage.Client/src/main/resources/cardrender/background_texture_black.png b/Mage.Client/src/main/resources/cardrender/background_texture_black.png new file mode 100644 index 0000000000..0237998b75 Binary files /dev/null and b/Mage.Client/src/main/resources/cardrender/background_texture_black.png differ diff --git a/Mage.Client/src/main/resources/cardrender/background_texture_blue.png b/Mage.Client/src/main/resources/cardrender/background_texture_blue.png new file mode 100644 index 0000000000..910d2f8760 Binary files /dev/null and b/Mage.Client/src/main/resources/cardrender/background_texture_blue.png differ diff --git a/Mage.Client/src/main/resources/cardrender/background_texture_gold.png b/Mage.Client/src/main/resources/cardrender/background_texture_gold.png new file mode 100644 index 0000000000..d325538a25 Binary files /dev/null and b/Mage.Client/src/main/resources/cardrender/background_texture_gold.png differ diff --git a/Mage.Client/src/main/resources/cardrender/background_texture_green.png b/Mage.Client/src/main/resources/cardrender/background_texture_green.png new file mode 100644 index 0000000000..08a3a1b386 Binary files /dev/null and b/Mage.Client/src/main/resources/cardrender/background_texture_green.png differ diff --git a/Mage.Client/src/main/resources/cardrender/background_texture_land.png b/Mage.Client/src/main/resources/cardrender/background_texture_land.png new file mode 100644 index 0000000000..3b7f3984cc Binary files /dev/null and b/Mage.Client/src/main/resources/cardrender/background_texture_land.png differ diff --git a/Mage.Client/src/main/resources/cardrender/background_texture_red.png b/Mage.Client/src/main/resources/cardrender/background_texture_red.png new file mode 100644 index 0000000000..1cd186adc5 Binary files /dev/null and b/Mage.Client/src/main/resources/cardrender/background_texture_red.png differ diff --git a/Mage.Client/src/main/resources/cardrender/background_texture_white.png b/Mage.Client/src/main/resources/cardrender/background_texture_white.png new file mode 100644 index 0000000000..44acb90961 Binary files /dev/null and b/Mage.Client/src/main/resources/cardrender/background_texture_white.png differ diff --git a/Mage.Client/src/main/resources/cardrender/beleren-bold.ttf b/Mage.Client/src/main/resources/cardrender/beleren-bold.ttf new file mode 100644 index 0000000000..7dd1bff6a7 Binary files /dev/null and b/Mage.Client/src/main/resources/cardrender/beleren-bold.ttf differ 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 dd09951d8d..16599a8379 100644 --- a/Mage.Client/src/test/java/mage/client/game/TokensMtgImageSourceTest.java +++ b/Mage.Client/src/test/java/mage/client/game/TokensMtgImageSourceTest.java @@ -18,15 +18,15 @@ public class TokensMtgImageSourceTest { public void generateTokenUrlTest() throws Exception { CardImageSource imageSource = TokensMtgImageSource.getInstance(); - String url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 1, "ORI")); + String url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 1, "ORI", "")); Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_010-Thopter.jpg", url); - url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 2, "ORI")); + url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 2, "ORI", "")); Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_011-Thopter.jpg", url); - url = imageSource.generateTokenUrl(new CardDownloadData("Ashaya, the Awoken World", "ORI", "0", false, 0, "ORI")); + 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); - url = imageSource.generateTokenUrl(new CardDownloadData("Emblem Gideon, Ally of Zendikar", "BFZ", "0", false, 0, null)); + 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); } } diff --git a/Mage.Common/src/mage/cards/CardBorder.java b/Mage.Common/src/mage/cards/CardBorder.java new file mode 100644 index 0000000000..17f6cd8c27 --- /dev/null +++ b/Mage.Common/src/mage/cards/CardBorder.java @@ -0,0 +1,28 @@ + +package mage.cards; + +/** + * @author stravant@gmail.com + * + * Enum listing the possible card faces for a card + * + * Because of Time Spiral block's shifted cards it is + * not sufficient to just look at a card's edition to + * determine what the card face should be. + */ +public enum CardBorder { + /* Old border card frames. ALPHA -> 8th ED */ + OLD, + + /* Future Sight frames. FUT futureshifted */ + FUT, + + /* Planar Chaos frames. PLC planeshifted */ + PLC, + + /* Modern card frames. 8th ED -> M15 */ + MOD, + + /* New border cards, M15 -> current */ + M15 +} diff --git a/Mage.Common/src/mage/cards/MageCard.java b/Mage.Common/src/mage/cards/MageCard.java index 8ee0ec61ed..61908d4dae 100644 --- a/Mage.Common/src/mage/cards/MageCard.java +++ b/Mage.Common/src/mage/cards/MageCard.java @@ -32,7 +32,7 @@ public abstract class MageCard extends JPanel { public abstract void update(CardView card); - public abstract void updateImage(); + public abstract void updateArtImage(); public abstract Image getImage(); diff --git a/Mage.Common/src/mage/utils/DeckBuilder.java b/Mage.Common/src/mage/utils/DeckBuilder.java index 9173994ea5..025a73bd37 100644 --- a/Mage.Common/src/mage/utils/DeckBuilder.java +++ b/Mage.Common/src/mage/utils/DeckBuilder.java @@ -247,9 +247,9 @@ public class DeckBuilder { int type; if (card.getCardType().contains(CardType.CREATURE)) { type = 10; - } else if (card.getSubtype().contains("Equipment")) { + } else if (card.getSubtype(null).contains("Equipment")) { type = 8; - } else if (card.getSubtype().contains("Aura")) { + } else if (card.getSubtype(null).contains("Aura")) { type = 5; } else if (card.getCardType().contains(CardType.INSTANT)) { type = 7; diff --git a/Mage.Common/src/mage/view/CardView.java b/Mage.Common/src/mage/view/CardView.java index e0f5ee9d84..ca3b6c48ee 100644 --- a/Mage.Common/src/mage/view/CardView.java +++ b/Mage.Common/src/mage/view/CardView.java @@ -68,14 +68,16 @@ public class CardView extends SimpleCardView { protected String power; protected String toughness; protected String loyalty; + protected String startingLoyalty; protected List cardTypes; protected List subTypes; protected List superTypes; protected ObjectColor color; + protected ObjectColor frameColor; protected List manaCost; protected int convertedManaCost; protected Rarity rarity; - + protected MageObjectType mageObjectType = MageObjectType.NULL; protected boolean isAbility; @@ -159,7 +161,7 @@ public class CardView extends SimpleCardView { * @param storeZone if true the card zone will be set in the zone attribute. */ public CardView(Card card, Game game, boolean controlled, boolean showFaceDownCard, boolean storeZone) { - super(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), card.getTokenSetCode(), game != null); + super(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), card.getTokenSetCode(), game != null, card.getTokenDescriptor()); // no information available for face down cards as long it's not a controlled face down morph card // TODO: Better handle this in Framework (but currently I'm not sure how to do it there) LevelX2 boolean showFaceUp = true; @@ -272,7 +274,7 @@ public class CardView extends SimpleCardView { this.power = Integer.toString(card.getPower().getValue()); this.toughness = Integer.toString(card.getToughness().getValue()); this.cardTypes = card.getCardType(); - this.subTypes = card.getSubtype(); + this.subTypes = card.getSubtype(game); this.superTypes = card.getSupertype(); this.color = card.getColor(game); this.canTransform = card.canTransform(); @@ -291,6 +293,7 @@ public class CardView extends SimpleCardView { } else { // a created token this.expansionSetCode = ((PermanentToken) card).getExpansionSetCode(); + this.tokenDescriptor = ((PermanentToken) card).getTokenDescriptor(); } // // set code und card number for token copies to get the image @@ -329,10 +332,16 @@ public class CardView extends SimpleCardView { } } } + + // Frame color + this.frameColor = card.getFrameColor(game); + + // Get starting loyalty + this.startingLoyalty = "" + card.getStartingLoyalty(); } public CardView(MageObject object) { - super(object.getId(), "", "0", false, "", true); + super(object.getId(), "", "0", false, "", true, ""); this.name = object.getName(); this.displayName = object.getName(); if (object instanceof Permanent) { @@ -346,7 +355,7 @@ public class CardView extends SimpleCardView { this.loyalty = ""; } this.cardTypes = object.getCardType(); - this.subTypes = object.getSubtype(); + this.subTypes = object.getSubtype(null); this.superTypes = object.getSupertype(); this.color = object.getColor(null); this.manaCost = object.getManaCost().getSymbols(); @@ -373,10 +382,14 @@ public class CardView extends SimpleCardView { this.expansionSetCode = stackAbility.getExpansionSetCode(); } } + // Frame color + this.frameColor = object.getFrameColor(null); + // Starting loyalty. Must be extracted from an ability + this.startingLoyalty = "" + object.getStartingLoyalty(); } protected CardView() { - super(null, "", "0", false, "", true); + super(null, "", "0", false, "", true, ""); } public CardView(EmblemView emblem) { @@ -393,7 +406,7 @@ public class CardView extends SimpleCardView { } public CardView(boolean empty) { - super(null, "", "0", false, ""); + super(null, "", "0", false, "", ""); if (!empty) { throw new IllegalArgumentException("Not supported."); } @@ -407,10 +420,12 @@ public class CardView extends SimpleCardView { this.power = ""; this.toughness = ""; this.loyalty = ""; + this.startingLoyalty = ""; this.cardTypes = new ArrayList<>(); this.subTypes = new ArrayList<>(); this.superTypes = new ArrayList<>(); this.color = new ObjectColor(); + this.frameColor = new ObjectColor(); this.manaCost = new ArrayList<>(); this.convertedManaCost = 0; @@ -442,7 +457,7 @@ public class CardView extends SimpleCardView { } CardView(Token token) { - super(token.getId(), "", "0", false, ""); + super(token.getId(), "", "0", false, "", ""); this.isToken = true; this.id = token.getId(); this.name = token.getName(); @@ -451,10 +466,12 @@ public class CardView extends SimpleCardView { this.power = token.getPower().toString(); this.toughness = token.getToughness().toString(); this.loyalty = ""; + this.startingLoyalty = ""; this.cardTypes = token.getCardType(); - this.subTypes = token.getSubtype(); + this.subTypes = token.getSubtype(null); this.superTypes = token.getSupertype(); this.color = token.getColor(null); + this.frameColor = token.getFrameColor(null); this.manaCost = token.getManaCost().getSymbols(); this.rarity = Rarity.NA; this.type = token.getTokenType(); @@ -517,6 +534,10 @@ public class CardView extends SimpleCardView { public String getLoyalty() { return loyalty; } + + public String getStartingLoyalty() { + return startingLoyalty; + } public List getCardTypes() { return cardTypes; @@ -533,6 +554,10 @@ public class CardView extends SimpleCardView { public ObjectColor getColor() { return color; } + + public ObjectColor getFrameColor() { + return frameColor; + } public List getManaCost() { return manaCost; @@ -765,3 +790,4 @@ public class CardView extends SimpleCardView { } } + diff --git a/Mage.Common/src/mage/view/CounterView.java b/Mage.Common/src/mage/view/CounterView.java index b15802c348..a9c2a61c4c 100644 --- a/Mage.Common/src/mage/view/CounterView.java +++ b/Mage.Common/src/mage/view/CounterView.java @@ -53,4 +53,21 @@ public class CounterView implements Serializable { public int getCount() { return count; } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if (other == null) { + return false; + } + if (!(other instanceof CounterView)) { + return false; + } + CounterView oth = (CounterView)other; + return + (count == oth.count) && + (name.equals(oth.name)); + } } diff --git a/Mage.Common/src/mage/view/LookedAtView.java b/Mage.Common/src/mage/view/LookedAtView.java index a7485e7120..ac965c6e31 100644 --- a/Mage.Common/src/mage/view/LookedAtView.java +++ b/Mage.Common/src/mage/view/LookedAtView.java @@ -46,7 +46,7 @@ public class LookedAtView implements Serializable { public LookedAtView(String name, Cards cards, Game game) { this.name = name; for (Card card: cards.getCards(game)) { - this.cards.put(card.getId(), new SimpleCardView(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), card.getTokenSetCode())); + this.cards.put(card.getId(), new SimpleCardView(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), card.getTokenSetCode(), card.getTokenDescriptor())); } } diff --git a/Mage.Common/src/mage/view/PermanentView.java b/Mage.Common/src/mage/view/PermanentView.java index 9ec311a269..e0b79cabe0 100644 --- a/Mage.Common/src/mage/view/PermanentView.java +++ b/Mage.Common/src/mage/view/PermanentView.java @@ -81,6 +81,7 @@ public class PermanentView extends CardView { original = new CardView(((PermanentToken) permanent).getToken()); original.expansionSetCode = permanent.getExpansionSetCode(); tokenSetCode = original.getTokenSetCode(); + tokenDescriptor = original.getTokenDescriptor(); } else { if (card != null) { // original may not be face down diff --git a/Mage.Common/src/mage/view/SimpleCardView.java b/Mage.Common/src/mage/view/SimpleCardView.java index 2a4c4d5e67..709e45ad83 100644 --- a/Mage.Common/src/mage/view/SimpleCardView.java +++ b/Mage.Common/src/mage/view/SimpleCardView.java @@ -39,16 +39,18 @@ public class SimpleCardView implements Serializable { protected UUID id; protected String expansionSetCode; protected String tokenSetCode; + protected String tokenDescriptor; protected String cardNumber; protected boolean usesVariousArt; protected boolean gameObject; - public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt, String tokenSetCode) { - this(id, expansionSetCode, cardNumber, usesVariousArt, tokenSetCode, false); + public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt, String tokenSetCode, String tokenDescriptor) { + this(id, expansionSetCode, cardNumber, usesVariousArt, tokenSetCode, false, tokenDescriptor); } - public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt, String tokenSetCode, boolean isGameObject) { + public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt, String tokenSetCode, boolean isGameObject, String tokenDescriptor) { this.id = id; this.expansionSetCode = expansionSetCode; + this.tokenDescriptor = tokenDescriptor; this.cardNumber = cardNumber; this.usesVariousArt = usesVariousArt; this.tokenSetCode = tokenSetCode; @@ -74,6 +76,10 @@ public class SimpleCardView implements Serializable { public String getTokenSetCode() { return tokenSetCode; } + + public String getTokenDescriptor() { + return tokenDescriptor; + } public boolean isGameObject() { return gameObject; diff --git a/Mage.Common/src/mage/view/SimpleCardsView.java b/Mage.Common/src/mage/view/SimpleCardsView.java index 909d0ee286..990d4b87b1 100644 --- a/Mage.Common/src/mage/view/SimpleCardsView.java +++ b/Mage.Common/src/mage/view/SimpleCardsView.java @@ -44,7 +44,8 @@ public class SimpleCardsView extends LinkedHashMap { public SimpleCardsView(Collection cards, boolean isGameObject) { for (Card card: cards) { - this.put(card.getId(), new SimpleCardView(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), card.getTokenSetCode(), isGameObject)); + this.put(card.getId(), new SimpleCardView(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), card.getTokenSetCode(), isGameObject, + card.getTokenDescriptor())); } } diff --git a/Mage.Common/src/mage/view/StackAbilityView.java b/Mage.Common/src/mage/view/StackAbilityView.java index 815c0ec13d..9b195d1b5b 100644 --- a/Mage.Common/src/mage/view/StackAbilityView.java +++ b/Mage.Common/src/mage/view/StackAbilityView.java @@ -64,12 +64,12 @@ public class StackAbilityView extends CardView { this.loyalty = ""; this.cardTypes = ability.getCardType(); - this.subTypes = ability.getSubtype(); + this.subTypes = ability.getSubtype(game); this.superTypes = ability.getSupertype(); this.color = ability.getColor(game); this.manaCost = ability.getManaCost().getSymbols(); this.cardTypes = ability.getCardType(); - this.subTypes = ability.getSubtype(); + this.subTypes = ability.getSubtype(game); this.superTypes = ability.getSupertype(); this.color = ability.getColor(game); this.manaCost = ability.getManaCost().getSymbols(); diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/ArtificialScoringSystem.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/ArtificialScoringSystem.java index 27e8cc0f06..9b0c017197 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/ArtificialScoringSystem.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/ArtificialScoringSystem.java @@ -55,7 +55,7 @@ public class ArtificialScoringSystem { //score + =cardDefinition.getActivations().size()*50; //score += cardDefinition.getManaActivations().size()*80; } else { - if (permanent.getSubtype().contains("Equipment")) { + if (permanent.getSubtype(game).contains("Equipment")) { score += 100; } } diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java index c485aa78f2..6264e60301 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java @@ -1340,9 +1340,9 @@ public class ComputerPlayer extends PlayerImpl implements Player { for (Permanent permanent : game.getBattlefield().getActivePermanents(this.getId(), game)) { if (game.getOpponents(this.getId()).contains(permanent.getControllerId()) && permanent.getCardType().contains(CardType.CREATURE) - && permanent.getSubtype().size() > 0) { - if (choice.getChoices().contains(permanent.getSubtype().get(0))) { - choice.setChoice(permanent.getSubtype().get(0)); + && permanent.getSubtype(game).size() > 0) { + if (choice.getChoices().contains(permanent.getSubtype(game).get(0))) { + choice.setChoice(permanent.getSubtype(game).get(0)); break; } } @@ -1352,9 +1352,9 @@ public class ComputerPlayer extends PlayerImpl implements Player { for (UUID opponentId : game.getOpponents(this.getId())) { Player opponent = game.getPlayer(opponentId); for (Card card : opponent.getGraveyard().getCards(game)) { - if (card != null && card.getCardType().contains(CardType.CREATURE) && card.getSubtype().size() > 0) { - if (choice.getChoices().contains(card.getSubtype().get(0))) { - choice.setChoice(card.getSubtype().get(0)); + if (card != null && card.getCardType().contains(CardType.CREATURE) && card.getSubtype(game).size() > 0) { + if (choice.getChoices().contains(card.getSubtype(game).get(0))) { + choice.setChoice(card.getSubtype(game).get(0)); break; } } @@ -1368,9 +1368,9 @@ public class ComputerPlayer extends PlayerImpl implements Player { // choose a creature type of hand or library for (UUID cardId : this.getHand()) { Card card = game.getCard(cardId); - if (card != null && card.getCardType().contains(CardType.CREATURE) && card.getSubtype().size() > 0) { - if (choice.getChoices().contains(card.getSubtype().get(0))) { - choice.setChoice(card.getSubtype().get(0)); + if (card != null && card.getCardType().contains(CardType.CREATURE) && card.getSubtype(game).size() > 0) { + if (choice.getChoices().contains(card.getSubtype(game).get(0))) { + choice.setChoice(card.getSubtype(game).get(0)); break; } } @@ -1378,9 +1378,9 @@ public class ComputerPlayer extends PlayerImpl implements Player { if (!choice.isChosen()) { for (UUID cardId : this.getLibrary().getCardList()) { Card card = game.getCard(cardId); - if (card != null && card.getCardType().contains(CardType.CREATURE) && card.getSubtype().size() > 0) { - if (choice.getChoices().contains(card.getSubtype().get(0))) { - choice.setChoice(card.getSubtype().get(0)); + if (card != null && card.getCardType().contains(CardType.CREATURE) && card.getSubtype(game).size() > 0) { + if (choice.getChoices().contains(card.getSubtype(game).get(0))) { + choice.setChoice(card.getSubtype(game).get(0)); break; } } diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/utils/RateCard.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/utils/RateCard.java index 1ea25df2e1..2bb13cb4a4 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/utils/RateCard.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/utils/RateCard.java @@ -16,7 +16,7 @@ import java.io.InputStream; import java.util.*; /** - * Class responsible for reading ratings from resources and rating gived cards. + * Class responsible for reading ratings from resources and rating given cards. * Based on card relative ratings from resources and card parameters. * * @author nantuko @@ -61,9 +61,9 @@ public class RateCard { type = 15; } else if (card.getCardType().contains(CardType.CREATURE)) { type = 10; - } else if (card.getSubtype().contains("Equipment")) { + } else if (card.getSubtype(null).contains("Equipment")) { type = 8; - } else if (card.getSubtype().contains("Aura")) { + } else if (card.getSubtype(null).contains("Aura")) { type = 5; } else if (card.getCardType().contains(CardType.INSTANT)) { type = 7; @@ -78,7 +78,7 @@ public class RateCard { } private static int isRemoval(Card card) { - if (card.getSubtype().contains("Aura") || card.getCardType().contains(CardType.INSTANT) + if (card.getSubtype(null).contains("Aura") || card.getCardType().contains(CardType.INSTANT) || card.getCardType().contains(CardType.SORCERY)) { for (Ability ability : card.getAbilities()) { diff --git a/Mage.Sets/src/mage/sets/alarareborn/LightningReaver.java b/Mage.Sets/src/mage/sets/alarareborn/LightningReaver.java index 0b42b2019e..b5dd1f7c0f 100644 --- a/Mage.Sets/src/mage/sets/alarareborn/LightningReaver.java +++ b/Mage.Sets/src/mage/sets/alarareborn/LightningReaver.java @@ -37,7 +37,7 @@ import mage.abilities.Ability; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.FearAbility; @@ -98,7 +98,7 @@ class DamageOpponentsEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - DynamicValue amount = new CountersCount(CounterType.CHARGE); + DynamicValue amount = new CountersSourceCount(CounterType.CHARGE); for (UUID playerId : game.getOpponents(source.getControllerId())) { Player player = game.getPlayer(playerId); if (player != null) { diff --git a/Mage.Sets/src/mage/sets/alliances/Tornado.java b/Mage.Sets/src/mage/sets/alliances/Tornado.java index dbce00b1e0..967ca123a9 100644 --- a/Mage.Sets/src/mage/sets/alliances/Tornado.java +++ b/Mage.Sets/src/mage/sets/alliances/Tornado.java @@ -34,7 +34,7 @@ import mage.abilities.costs.common.PayLifeCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.MultipliedValue; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -61,7 +61,7 @@ public class Tornado extends CardImpl { this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{G}"))); // {2}{G}, Pay 3 life for each velocity counter on Tornado: Destroy target permanent and put a velocity counter on Tornado. Activate this ability only once each turn. Ability ability = new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new ManaCostsImpl("{2}{G}")); - DynamicValue lifeToPayAmount = new MultipliedValue(new CountersCount(CounterType.VELOCITY), 3); + DynamicValue lifeToPayAmount = new MultipliedValue(new CountersSourceCount(CounterType.VELOCITY), 3); ability.addCost(new PayLifeCost(lifeToPayAmount, "3 life for each velocity counter on {source}")); ability.addTarget(new TargetPermanent()); Effect effect = new AddCountersSourceEffect(CounterType.VELOCITY.createInstance()); diff --git a/Mage.Sets/src/mage/sets/antiquities/Tetravus.java b/Mage.Sets/src/mage/sets/antiquities/Tetravus.java index 0a25fb5ff1..6992afa74f 100644 --- a/Mage.Sets/src/mage/sets/antiquities/Tetravus.java +++ b/Mage.Sets/src/mage/sets/antiquities/Tetravus.java @@ -120,7 +120,7 @@ class CantBeEnchantedAbility extends StaticAbility { public boolean canTarget(MageObject source, Game game) { if (source.getCardType().contains(CardType.ENCHANTMENT) && - source.hasSubtype("Aura")) { + source.hasSubtype("Aura", game)) { return false; } return true; diff --git a/Mage.Sets/src/mage/sets/arabiannights/DesertNomads.java b/Mage.Sets/src/mage/sets/arabiannights/DesertNomads.java index 99a006378c..22f9eb2590 100644 --- a/Mage.Sets/src/mage/sets/arabiannights/DesertNomads.java +++ b/Mage.Sets/src/mage/sets/arabiannights/DesertNomads.java @@ -96,7 +96,7 @@ class PreventDamageToSourceBySubtypeEffect extends PreventAllDamageToSourceEffec @Override public boolean applies(GameEvent event, Ability source, Game game) { if (super.applies(event, source, game)) { - if (game.getObject(event.getSourceId()).hasSubtype(subtype)){ + if (game.getObject(event.getSourceId()).hasSubtype(subtype, game)){ if (event.getTargetId().equals(source.getSourceId())) { return true; } diff --git a/Mage.Sets/src/mage/sets/arabiannights/GuardianBeast.java b/Mage.Sets/src/mage/sets/arabiannights/GuardianBeast.java index b357ed6dea..c33d7886ee 100644 --- a/Mage.Sets/src/mage/sets/arabiannights/GuardianBeast.java +++ b/Mage.Sets/src/mage/sets/arabiannights/GuardianBeast.java @@ -145,7 +145,7 @@ class GuardianBeastConditionalEffect extends ContinuousRuleModifyingEffectImpl { } StackObject spell = game.getStack().getStackObject(event.getSourceId()); - if (event.getType() == EventType.LOSE_CONTROL || event.getType() == EventType.ATTACH || event.getType() == EventType.TARGET && spell != null && spell.getCardType().contains(CardType.ENCHANTMENT) && spell.getSubtype().contains("Aura")) { + if (event.getType() == EventType.LOSE_CONTROL || event.getType() == EventType.ATTACH || event.getType() == EventType.TARGET && spell != null && spell.getCardType().contains(CardType.ENCHANTMENT) && spell.getSubtype(game).contains("Aura")) { for (Permanent perm : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { if (perm != null && perm.getId() == targetPermanent.getId() && !perm.getCardType().contains(CardType.CREATURE)) { return true; diff --git a/Mage.Sets/src/mage/sets/avacynrestored/CavernOfSouls.java b/Mage.Sets/src/mage/sets/avacynrestored/CavernOfSouls.java index 747c9bb6b9..168126031c 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/CavernOfSouls.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/CavernOfSouls.java @@ -142,7 +142,7 @@ class CavernOfSoulsManaCondition extends CreatureCastManaCondition { if (super.apply(game, source)) { // check: ... of the chosen type MageObject object = game.getObject(source.getSourceId()); - if (creatureType != null && object.hasSubtype(creatureType)) { + if (creatureType != null && object.hasSubtype(creatureType, game)) { return true; } } diff --git a/Mage.Sets/src/mage/sets/avacynrestored/DefyDeath.java b/Mage.Sets/src/mage/sets/avacynrestored/DefyDeath.java index 37c0c83d9a..f057639f9d 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/DefyDeath.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/DefyDeath.java @@ -87,7 +87,7 @@ class DefyDeathEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getFirstTarget()); - if (permanent != null && permanent.hasSubtype("Angel")) { + if (permanent != null && permanent.hasSubtype("Angel", game)) { permanent.addCounters(CounterType.P1P1.createInstance(2), game); return true; } diff --git a/Mage.Sets/src/mage/sets/avacynrestored/DescendantsPath.java b/Mage.Sets/src/mage/sets/avacynrestored/DescendantsPath.java index 0bb9524661..fb11b985ca 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/DescendantsPath.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/DescendantsPath.java @@ -103,7 +103,7 @@ class DescendantsPathEffect extends OneShotEffect { FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); boolean found = false; for (Permanent permanent: game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game)) { - if (CardUtil.shareSubtypes(card, permanent)) { + if (CardUtil.shareSubtypes(card, permanent, game)) { found = true; break; } diff --git a/Mage.Sets/src/mage/sets/avacynrestored/DreadSlaver.java b/Mage.Sets/src/mage/sets/avacynrestored/DreadSlaver.java index ff086a81a0..3d2af34277 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/DreadSlaver.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/DreadSlaver.java @@ -133,7 +133,7 @@ class DreadSlaverContiniousEffect extends ContinuousEffectImpl { switch (layer) { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { - creature.getSubtype().add("Zombie"); + creature.getSubtype(game).add("Zombie"); } break; case ColorChangingEffects_5: diff --git a/Mage.Sets/src/mage/sets/avacynrestored/EatenBySpiders.java b/Mage.Sets/src/mage/sets/avacynrestored/EatenBySpiders.java index 2165ed9c23..ccfd4e3b7d 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/EatenBySpiders.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/EatenBySpiders.java @@ -99,7 +99,7 @@ class EatenBySpidersEffect extends OneShotEffect { for (UUID attachmentId : attachments) { Permanent attachment = game.getPermanent(attachmentId); - if (attachment.hasSubtype("Equipment")) { + if (attachment.hasSubtype("Equipment", game)) { attachment.destroy(source.getSourceId(), game, false); } } diff --git a/Mage.Sets/src/mage/sets/avacynrestored/FalkenrathExterminator.java b/Mage.Sets/src/mage/sets/avacynrestored/FalkenrathExterminator.java index 1fc407f4fd..beb2977644 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/FalkenrathExterminator.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/FalkenrathExterminator.java @@ -36,7 +36,7 @@ import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -62,7 +62,7 @@ public class FalkenrathExterminator extends CardImpl { // Whenever Falkenrath Exterminator deals combat damage to a player, put a +1/+1 counter on it. this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false)); // {2}{R}: Falkenrath Exterminator deals damage to target creature equal to the number of +1/+1 counters on Falkenrath Exterminator. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new CountersCount(CounterType.P1P1)), new ManaCostsImpl("{2}{R}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new CountersSourceCount(CounterType.P1P1)), new ManaCostsImpl("{2}{R}")); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/avacynrestored/HeraldOfWar.java b/Mage.Sets/src/mage/sets/avacynrestored/HeraldOfWar.java index 30e25ad36b..ac3bc38035 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/HeraldOfWar.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/HeraldOfWar.java @@ -107,7 +107,7 @@ class HeraldOfWarCostReductionEffect extends CostModificationEffectImpl { public boolean applies(Ability abilityToModify, Ability source, Game game) { if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) { Card sourceCard = game.getCard(abilityToModify.getSourceId()); - if (sourceCard != null && abilityToModify.getControllerId().equals(source.getControllerId()) && (sourceCard.hasSubtype("Angel") || sourceCard.hasSubtype("Human"))) { + if (sourceCard != null && abilityToModify.getControllerId().equals(source.getControllerId()) && (sourceCard.hasSubtype("Angel", game) || sourceCard.hasSubtype("Human", game))) { return true; } } diff --git a/Mage.Sets/src/mage/sets/avacynrestored/HolyJusticiar.java b/Mage.Sets/src/mage/sets/avacynrestored/HolyJusticiar.java index 6d30460f2b..704f6251b3 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/HolyJusticiar.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/HolyJusticiar.java @@ -91,7 +91,7 @@ class HolyJusticiarEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent creature = game.getPermanent(source.getFirstTarget()); if (creature != null) { - if (creature.hasSubtype("Zombie")) { + if (creature.hasSubtype("Zombie", game)) { creature.tap(game); creature.moveToExile(source.getSourceId(), creature.getName(), source.getSourceId(), game); } else { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/AkoumHellkite.java b/Mage.Sets/src/mage/sets/battleforzendikar/AkoumHellkite.java index b1987a95f8..25a8dff3e5 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/AkoumHellkite.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/AkoumHellkite.java @@ -146,7 +146,7 @@ class AkoumHellkiteDamageEffect extends OneShotEffect { Permanent land = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source)); Player player = game.getPlayer(source.getFirstTarget()); if (land != null && player != null) { - if (land.hasSubtype("Mountain")) { + if (land.hasSubtype("Mountain", game)) { player.damage(2, source.getSourceId(), game, false, true); } else { player.damage(1, source.getSourceId(), game, false, true); @@ -155,7 +155,7 @@ class AkoumHellkiteDamageEffect extends OneShotEffect { } Permanent permanent = game.getPermanent(source.getFirstTarget()); if (land != null && permanent != null) { - if (land.hasSubtype("Mountain")) { + if (land.hasSubtype("Mountain", game)) { permanent.damage(2, source.getSourceId(), game, false, true); } else { permanent.damage(1, source.getSourceId(), game, false, true); diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/EmeriaShepherd.java b/Mage.Sets/src/mage/sets/battleforzendikar/EmeriaShepherd.java index 315406fcb0..c334f2516f 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/EmeriaShepherd.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/EmeriaShepherd.java @@ -109,7 +109,7 @@ class EmeriaShepherdReturnToHandTargetEffect extends OneShotEffect { return false; } Zone toZone = Zone.HAND; - if (triggeringLand.getSubtype().contains("Plains") + if (triggeringLand.getSubtype(game).contains("Plains") && controller.chooseUse(Outcome.PutCardInPlay, "Put the card to battlefield instead?", source, game)) { toZone = Zone.BATTLEFIELD; } diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/GuardianOfTazeem.java b/Mage.Sets/src/mage/sets/battleforzendikar/GuardianOfTazeem.java index 3df407ef19..776c768c47 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/GuardianOfTazeem.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/GuardianOfTazeem.java @@ -152,7 +152,7 @@ class GuardianOfTazeemEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent land = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source)); Permanent targetCreature = game.getPermanent(source.getFirstTarget()); - if (land != null && targetCreature != null && land.hasSubtype("Island")) { + if (land != null && targetCreature != null && land.hasSubtype("Island", game)) { ContinuousEffect effect = new DontUntapInControllersNextUntapStepTargetEffect("that creature"); effect.setTargetPointer(new FixedTarget(targetCreature, game)); game.addEffect(effect, source); diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/GuulDrazOverseer.java b/Mage.Sets/src/mage/sets/battleforzendikar/GuulDrazOverseer.java index 3260c68f2c..2e15699f02 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/GuulDrazOverseer.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/GuulDrazOverseer.java @@ -96,7 +96,7 @@ class GuulDrazOverseerEffect extends OneShotEffect { Permanent land = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source)); if (controller != null && land != null) { int boost = 1; - if (land.getSubtype().contains("Swamp")) { + if (land.getSubtype(game).contains("Swamp")) { boost = 2; } game.addEffect(new BoostControlledEffect(boost, 0, Duration.EndOfTurn, true), source); diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/OranRiefHydra.java b/Mage.Sets/src/mage/sets/battleforzendikar/OranRiefHydra.java index a997e01fd4..4773b8a0a5 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/OranRiefHydra.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/OranRiefHydra.java @@ -144,7 +144,7 @@ class OranRiefHydraEffect extends OneShotEffect { Permanent land = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source)); Permanent sourcePermanent = game.getPermanent(source.getSourceId()); if (land != null && sourcePermanent != null) { - if (land.hasSubtype("Forest")) { + if (land.hasSubtype("Forest", game)) { sourcePermanent.addCounters(CounterType.P1P1.createInstance(2), game); } else { sourcePermanent.addCounters(CounterType.P1P1.createInstance(), game); diff --git a/Mage.Sets/src/mage/sets/betrayersofkamigawa/PetalmaneBaku.java b/Mage.Sets/src/mage/sets/betrayersofkamigawa/PetalmaneBaku.java index 30e824dc0d..f74e76c3c2 100644 --- a/Mage.Sets/src/mage/sets/betrayersofkamigawa/PetalmaneBaku.java +++ b/Mage.Sets/src/mage/sets/betrayersofkamigawa/PetalmaneBaku.java @@ -34,7 +34,7 @@ import mage.abilities.Ability; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.costs.common.RemoveVariableCountersSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.mana.DynamicManaAbility; @@ -68,7 +68,7 @@ public class PetalmaneBaku extends CardImpl { new RemovedCountersForCostValue(), new ManaCostsImpl<>("{1}"), "Add X mana of any one color to your mana pool", - true, new CountersCount(CounterType.KI)); + true, new CountersSourceCount(CounterType.KI)); ability.addCost(new RemoveVariableCountersSourceCost(CounterType.KI.createInstance(), "Remove X ki counters from {this}")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/betrayersofkamigawa/Shuriken.java b/Mage.Sets/src/mage/sets/betrayersofkamigawa/Shuriken.java index 3ea7e2a5c7..19dbf6056a 100644 --- a/Mage.Sets/src/mage/sets/betrayersofkamigawa/Shuriken.java +++ b/Mage.Sets/src/mage/sets/betrayersofkamigawa/Shuriken.java @@ -208,7 +208,7 @@ class ShurikenControlEffect extends OneShotEffect { if (equipment != null) { Permanent creature = game.getPermanent(source.getSourceId()); if (creature != null) { - if (!creature.hasSubtype("Ninja")) { + if (!creature.hasSubtype("Ninja", game)) { Permanent damagedCreature = game.getPermanent(this.getTargetPointer().getFirst(game, source)); if (damagedCreature == null) { damagedCreature = (Permanent) game.getLastKnownInformation(this.getTargetPointer().getFirst(game, source), Zone.BATTLEFIELD); diff --git a/Mage.Sets/src/mage/sets/betrayersofkamigawa/SlumberingTora.java b/Mage.Sets/src/mage/sets/betrayersofkamigawa/SlumberingTora.java index a1c1da76e8..b4e170ad99 100644 --- a/Mage.Sets/src/mage/sets/betrayersofkamigawa/SlumberingTora.java +++ b/Mage.Sets/src/mage/sets/betrayersofkamigawa/SlumberingTora.java @@ -99,7 +99,7 @@ public class SlumberingTora extends CardImpl { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { permanent.getCardType().add(CardType.CREATURE); - permanent.getSubtype().add("Cat"); + permanent.getSubtype(game).add("Cat"); } break; case PTChangingEffects_7: diff --git a/Mage.Sets/src/mage/sets/betrayersofkamigawa/UncheckedGrowth.java b/Mage.Sets/src/mage/sets/betrayersofkamigawa/UncheckedGrowth.java index 82ec17eac9..f45695f5e3 100644 --- a/Mage.Sets/src/mage/sets/betrayersofkamigawa/UncheckedGrowth.java +++ b/Mage.Sets/src/mage/sets/betrayersofkamigawa/UncheckedGrowth.java @@ -93,7 +93,7 @@ public class UncheckedGrowth extends CardImpl { int affectedTargets = 0; for (UUID permanentId : targetPointer.getTargets(game, source)) { Permanent permanent = game.getPermanent(permanentId); - if (permanent != null && permanent.hasSubtype("Spirit")) { + if (permanent != null && permanent.hasSubtype("Spirit", game)) { permanent.addAbility(TrampleAbility.getInstance(), game); affectedTargets++; } diff --git a/Mage.Sets/src/mage/sets/bornofthegods/EverflameEidolon.java b/Mage.Sets/src/mage/sets/bornofthegods/EverflameEidolon.java index dc091c0b57..d3c5cc03a7 100644 --- a/Mage.Sets/src/mage/sets/bornofthegods/EverflameEidolon.java +++ b/Mage.Sets/src/mage/sets/bornofthegods/EverflameEidolon.java @@ -98,7 +98,7 @@ class EverflameEidolonEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent sourceObject = game.getPermanentOrLKIBattlefield(source.getSourceId()); if (sourceObject != null) { - if (sourceObject.getSubtype().contains("Aura")) { + if (sourceObject.getSubtype(game).contains("Aura")) { new BoostEnchantedEffect(1, 0, Duration.EndOfTurn).apply(game, source); } else { game.addEffect(new BoostSourceEffect(1, 0, Duration.EndOfTurn), source); diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/BloodthirstyOgre.java b/Mage.Sets/src/mage/sets/championsofkamigawa/BloodthirstyOgre.java index d1a0b5dda3..1cff910f58 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/BloodthirstyOgre.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/BloodthirstyOgre.java @@ -35,7 +35,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.SignInversionDynamicValue; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -75,7 +75,7 @@ public class BloodthirstyOgre extends CardImpl { this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.DEVOTION.createInstance()),new TapSourceCost())); // {T}: Target creature gets -X/-X until end of turn, where X is the number of devotion counters on Bloodthirsty Ogre. Activate this ability only if you control a Demon. - DynamicValue devotionCounters = new SignInversionDynamicValue(new CountersCount(CounterType.DEVOTION)); + DynamicValue devotionCounters = new SignInversionDynamicValue(new CountersSourceCount(CounterType.DEVOTION)); Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(devotionCounters,devotionCounters, Duration.EndOfTurn, true), new TapSourceCost(), diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/FloatingDreamZubera.java b/Mage.Sets/src/mage/sets/championsofkamigawa/FloatingDreamZubera.java index 37b726e474..7eba029563 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/FloatingDreamZubera.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/FloatingDreamZubera.java @@ -97,7 +97,7 @@ class ZuberasDiedWatcher extends Watcher { public void watch(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent) event).isDiesEvent()) { MageObject card = game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); - if (card != null && card.hasSubtype("Zubera")) { + if (card != null && card.hasSubtype("Zubera", game)) { zuberasDiedThisTurn++; } } diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/KondasBanner.java b/Mage.Sets/src/mage/sets/championsofkamigawa/KondasBanner.java index ede835d57b..6ba52f06c8 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/KondasBanner.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/KondasBanner.java @@ -1,5 +1,5 @@ /* - * + * * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -25,15 +25,15 @@ * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. - * + * */ package mage.sets.championsofkamigawa; import java.util.UUID; import mage.abilities.Ability; +import mage.abilities.common.AttachableToRestrictedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.continuous.BoostAllEffect; import mage.abilities.keyword.EquipAbility; import mage.cards.CardImpl; @@ -47,6 +47,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.SupertypePredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.Target; import mage.target.common.TargetControlledCreaturePermanent; import mage.util.CardUtil; @@ -56,7 +57,7 @@ import mage.util.CardUtil; */ public class KondasBanner extends CardImpl { - private static final FilterControlledCreaturePermanent legendaryFilter = new FilterControlledCreaturePermanent("Legendary creatures"); + private static final FilterControlledCreaturePermanent legendaryFilter = new FilterControlledCreaturePermanent("legendary creatures"); static { legendaryFilter.add(new SupertypePredicate("Legendary")); @@ -68,8 +69,9 @@ public class KondasBanner extends CardImpl { this.supertype.add("Legendary"); this.subtype.add("Equipment"); + Target target = new TargetControlledCreaturePermanent(1, 1, legendaryFilter, false); // Konda's Banner can be attached only to a legendary creature. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new InfoEffect("{this} can be attached only to a legendary creature"))); + this.addAbility(new AttachableToRestrictedAbility(target)); // Creatures that share a color with equipped creature get +1/+1. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new KondasBannerColorBoostEffect())); @@ -78,10 +80,7 @@ public class KondasBanner extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new KondasBannerTypeBoostEffect())); // Equip {2} - this.addAbility(new EquipAbility( - Outcome.AddAbility, - new GenericManaCost(2), - new TargetControlledCreaturePermanent(1, 1, legendaryFilter, false))); + this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2), target)); } @@ -116,7 +115,7 @@ class KondasBannerTypeBoostEffect extends BoostAllEffect { Permanent equipedCreature = game.getPermanent(equipment.getAttachedTo()); if (equipedCreature != null) { for (Permanent perm : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { - if (CardUtil.shareSubtypes(perm, equipedCreature)) { + if (CardUtil.shareSubtypes(perm, equipedCreature, game)) { perm.addPower(power.calculate(game, source, this)); perm.addToughness(toughness.calculate(game, source, this)); diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/OrochiHatchery.java b/Mage.Sets/src/mage/sets/championsofkamigawa/OrochiHatchery.java index beb1e74ea9..b5c002c111 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/OrochiHatchery.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/OrochiHatchery.java @@ -33,7 +33,7 @@ import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect; import mage.cards.CardImpl; @@ -56,7 +56,7 @@ public class OrochiHatchery extends CardImpl { this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.CHARGE.createInstance()))); // {5}, {T}: Put a 1/1 green Snake creature token onto the battlefield for each charge counter on Orochi Hatchery. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new SnakeToken(), new CountersCount(CounterType.CHARGE)), new GenericManaCost(5)); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new SnakeToken(), new CountersSourceCount(CounterType.CHARGE)), new GenericManaCost(5)); ability.addCost(new TapSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/RyuseiTheFallingStar.java b/Mage.Sets/src/mage/sets/championsofkamigawa/RyuseiTheFallingStar.java index 3992300e35..5c4905479d 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/RyuseiTheFallingStar.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/RyuseiTheFallingStar.java @@ -52,8 +52,8 @@ public class RyuseiTheFallingStar extends CardImpl { filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); } - public RyuseiTheFallingStar(UUID ownerID) { - super(ownerID, 185, "Ryusei, the Falling Star", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{5}{R}"); + public RyuseiTheFallingStar(UUID ownerId) { + super(ownerId, 185, "Ryusei, the Falling Star", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{5}{R}"); this.expansionSetCode = "CHK"; this.supertype.add("Legendary"); this.subtype.add("Dragon"); diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/SeshiroTheAnointed.java b/Mage.Sets/src/mage/sets/championsofkamigawa/SeshiroTheAnointed.java index 1f472f80a0..ba64bc4961 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/SeshiroTheAnointed.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/SeshiroTheAnointed.java @@ -106,7 +106,7 @@ class SeshiroTheAnointedAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { DamagedPlayerEvent damageEvent = (DamagedPlayerEvent)event; Permanent p = game.getPermanent(event.getSourceId()); - if (damageEvent.isCombatDamage() && p != null && p.hasSubtype("Snake") && p.getControllerId().equals(controllerId)) { + if (damageEvent.isCombatDamage() && p != null && p.hasSubtype("Snake", game) && p.getControllerId().equals(controllerId)) { return true; } return false; diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/SosukeSonOfSeshiro.java b/Mage.Sets/src/mage/sets/championsofkamigawa/SosukeSonOfSeshiro.java index 8cdf926c72..039cf7e2ff 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/SosukeSonOfSeshiro.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/SosukeSonOfSeshiro.java @@ -117,7 +117,7 @@ class SosukeSonOfSeshiroTriggeredAbility extends TriggeredAbilityImpl { Permanent sourceCreature = game.getPermanent(event.getSourceId()); Permanent targetCreature = game.getPermanent(event.getTargetId()); if (sourceCreature != null && sourceCreature.getControllerId().equals(this.getControllerId()) - && targetCreature != null && sourceCreature.hasSubtype("Warrior")) { + && targetCreature != null && sourceCreature.hasSubtype("Warrior", game)) { this.getEffects().get(0).setTargetPointer(new FixedTarget(targetCreature.getId())); return true; } diff --git a/Mage.Sets/src/mage/sets/coldsnap/HaakonStromgaldScourge.java b/Mage.Sets/src/mage/sets/coldsnap/HaakonStromgaldScourge.java index 3905fb266a..efdfee96f5 100644 --- a/Mage.Sets/src/mage/sets/coldsnap/HaakonStromgaldScourge.java +++ b/Mage.Sets/src/mage/sets/coldsnap/HaakonStromgaldScourge.java @@ -186,7 +186,7 @@ class HaakonPlayKnightsFromGraveyardEffect extends AsThoughEffectImpl { if (affectedControllerId.equals(source.getControllerId())) { Card knightToCast = game.getCard(objectId); if (knightToCast != null - && knightToCast.hasSubtype("Knight") + && knightToCast.hasSubtype("Knight", game) && knightToCast.getOwnerId().equals(source.getControllerId()) && game.getState().getZone(objectId) == Zone.GRAVEYARD) { return true; diff --git a/Mage.Sets/src/mage/sets/coldsnap/Jokulmorder.java b/Mage.Sets/src/mage/sets/coldsnap/Jokulmorder.java index f35509c7ac..1b0d645afe 100644 --- a/Mage.Sets/src/mage/sets/coldsnap/Jokulmorder.java +++ b/Mage.Sets/src/mage/sets/coldsnap/Jokulmorder.java @@ -110,7 +110,7 @@ class JokulmorderTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent land = game.getPermanent(event.getTargetId()); - return land.getSubtype().contains("Island") + return land.getSubtype(game).contains("Island") && land.getControllerId().equals(this.controllerId); } diff --git a/Mage.Sets/src/mage/sets/commander2014/MyriadLandscape.java b/Mage.Sets/src/mage/sets/commander2014/MyriadLandscape.java index 17c47b39b6..1549853659 100644 --- a/Mage.Sets/src/mage/sets/commander2014/MyriadLandscape.java +++ b/Mage.Sets/src/mage/sets/commander2014/MyriadLandscape.java @@ -110,11 +110,11 @@ class TargetCardInLibrarySharingLandType extends TargetCardInLibrary { if (landCard != null) { if (landTypes == null) { landTypes = new HashSet<>(); - landTypes.addAll(landCard.getSubtype()); + landTypes.addAll(landCard.getSubtype(game)); } else { for (Iterator iterator = landTypes.iterator(); iterator.hasNext();) { String next = iterator.next(); - if (!landCard.getSubtype().contains(next)) { + if (!landCard.getSubtype(game).contains(next)) { iterator.remove(); } } @@ -125,7 +125,7 @@ class TargetCardInLibrarySharingLandType extends TargetCardInLibrary { if (card != null && landTypes != null) { for (Iterator iterator = landTypes.iterator(); iterator.hasNext();) { String next = iterator.next(); - if (card.getSubtype().contains(next)) { + if (card.getSubtype(game).contains(next)) { return true; } } diff --git a/Mage.Sets/src/mage/sets/commander2014/NecromanticSelection.java b/Mage.Sets/src/mage/sets/commander2014/NecromanticSelection.java index 80547d636a..103d72ad18 100644 --- a/Mage.Sets/src/mage/sets/commander2014/NecromanticSelection.java +++ b/Mage.Sets/src/mage/sets/commander2014/NecromanticSelection.java @@ -158,8 +158,8 @@ class NecromanticSelectionContinuousEffect extends ContinuousEffectImpl { switch (layer) { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { - if (!creature.getSubtype().contains("Zombie")) { - creature.getSubtype().add("Zombie"); + if (!creature.getSubtype(game).contains("Zombie")) { + creature.getSubtype(game).add("Zombie"); } } break; diff --git a/Mage.Sets/src/mage/sets/commander2014/SongOfTheDryads.java b/Mage.Sets/src/mage/sets/commander2014/SongOfTheDryads.java index 41009ed74a..bc0eb63a6b 100644 --- a/Mage.Sets/src/mage/sets/commander2014/SongOfTheDryads.java +++ b/Mage.Sets/src/mage/sets/commander2014/SongOfTheDryads.java @@ -121,8 +121,8 @@ class BecomesColorlessForestLandEffect extends ContinuousEffectImpl { case TypeChangingEffects_4: permanent.getCardType().clear(); permanent.getCardType().add(CardType.LAND); - permanent.getSubtype().clear(); - permanent.getSubtype().add("Forest"); + permanent.getSubtype(game).clear(); + permanent.getSubtype(game).add("Forest"); break; } return true; diff --git a/Mage.Sets/src/mage/sets/commander2015/KasetoOrochiArchmage.java b/Mage.Sets/src/mage/sets/commander2015/KasetoOrochiArchmage.java index 02f9e11197..5651717c57 100644 --- a/Mage.Sets/src/mage/sets/commander2015/KasetoOrochiArchmage.java +++ b/Mage.Sets/src/mage/sets/commander2015/KasetoOrochiArchmage.java @@ -97,7 +97,7 @@ class KasetoEffect extends OneShotEffect { Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (permanent != null) { game.addEffect(new CantBeBlockedTargetEffect(Duration.EndOfTurn), source); - if (permanent.getSubtype().contains("Snake")) { + if (permanent.getSubtype(game).contains("Snake")) { game.addEffect(new BoostTargetEffect(2,2,Duration.EndOfTurn), source); } return true; diff --git a/Mage.Sets/src/mage/sets/conflux/DragonsoulKnight.java b/Mage.Sets/src/mage/sets/conflux/DragonsoulKnight.java index 81cb99049b..9bd4e2c888 100644 --- a/Mage.Sets/src/mage/sets/conflux/DragonsoulKnight.java +++ b/Mage.Sets/src/mage/sets/conflux/DragonsoulKnight.java @@ -117,8 +117,8 @@ public class DragonsoulKnight extends CardImpl { switch (layer) { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { - permanent.getSubtype().clear(); - permanent.getSubtype().add("Dragon"); + permanent.getSubtype(game).clear(); + permanent.getSubtype(game).add("Dragon"); } break; } diff --git a/Mage.Sets/src/mage/sets/conflux/GoblinRazerunners.java b/Mage.Sets/src/mage/sets/conflux/GoblinRazerunners.java index 2338470700..821ec58e72 100644 --- a/Mage.Sets/src/mage/sets/conflux/GoblinRazerunners.java +++ b/Mage.Sets/src/mage/sets/conflux/GoblinRazerunners.java @@ -38,7 +38,7 @@ import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -71,7 +71,7 @@ public class GoblinRazerunners extends CardImpl { this.addAbility(ability); // At the beginning of your end step, you may have Goblin Razerunners deal damage equal to the number of +1/+1 counters on it to target player. - ability = new BeginningOfYourEndStepTriggeredAbility(new DamageTargetEffect(new CountersCount(CounterType.P1P1)), true); + ability = new BeginningOfYourEndStepTriggeredAbility(new DamageTargetEffect(new CountersSourceCount(CounterType.P1P1)), true); ability.addTarget(new TargetPlayer()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/conflux/ParagonOfTheAmesha.java b/Mage.Sets/src/mage/sets/conflux/ParagonOfTheAmesha.java index 314a165e37..87a26e5434 100644 --- a/Mage.Sets/src/mage/sets/conflux/ParagonOfTheAmesha.java +++ b/Mage.Sets/src/mage/sets/conflux/ParagonOfTheAmesha.java @@ -117,8 +117,8 @@ public class ParagonOfTheAmesha extends CardImpl { switch (layer) { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { - permanent.getSubtype().clear(); - permanent.getSubtype().add("Angel"); + permanent.getSubtype(game).clear(); + permanent.getSubtype(game).add("Angel"); } break; } diff --git a/Mage.Sets/src/mage/sets/conspiracy/IgnitionTeam.java b/Mage.Sets/src/mage/sets/conspiracy/IgnitionTeam.java index b85f110fe1..ef9b702c64 100644 --- a/Mage.Sets/src/mage/sets/conspiracy/IgnitionTeam.java +++ b/Mage.Sets/src/mage/sets/conspiracy/IgnitionTeam.java @@ -121,7 +121,7 @@ class IgnitionTeamToken extends Token { public IgnitionTeamToken() { super("", "4/4 red Elemental creature"); this.cardType.add(CardType.CREATURE); - this.getSubtype().add("Elemental"); + this.getSubtype(null).add("Elemental"); this.color.setRed(true); this.power = new MageInt(4); diff --git a/Mage.Sets/src/mage/sets/darkascension/AvacynsCollar.java b/Mage.Sets/src/mage/sets/darkascension/AvacynsCollar.java index 209dd59ee2..5a54ce770e 100644 --- a/Mage.Sets/src/mage/sets/darkascension/AvacynsCollar.java +++ b/Mage.Sets/src/mage/sets/darkascension/AvacynsCollar.java @@ -103,7 +103,7 @@ class AvacynsCollarTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { if (((ZoneChangeEvent) event).isDiesEvent()) { Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); - if (permanent.getAttachments().contains(this.getSourceId()) && permanent.hasSubtype("Human")) { + if (permanent.getAttachments().contains(this.getSourceId()) && permanent.hasSubtype("Human", game)) { return true; } } diff --git a/Mage.Sets/src/mage/sets/darkascension/CallToTheKindred.java b/Mage.Sets/src/mage/sets/darkascension/CallToTheKindred.java index 391a2a3fa2..3be4ffa0d5 100644 --- a/Mage.Sets/src/mage/sets/darkascension/CallToTheKindred.java +++ b/Mage.Sets/src/mage/sets/darkascension/CallToTheKindred.java @@ -127,7 +127,7 @@ class CallToTheKindredEffect extends OneShotEffect { if (!creature.getAbilities().contains(ChangelingAbility.getInstance())) { StringBuilder sb = new StringBuilder("creature card with at least one subtype from: "); ArrayList> subtypes = new ArrayList<>(); - for (String subtype : creature.getSubtype()) { + for (String subtype : creature.getSubtype(game)) { subtypes.add(new SubtypePredicate(subtype)); sb.append(subtype).append(", "); } diff --git a/Mage.Sets/src/mage/sets/darkascension/CurseOfMisfortunes.java b/Mage.Sets/src/mage/sets/darkascension/CurseOfMisfortunes.java index 29dae5d38e..e0296f3570 100644 --- a/Mage.Sets/src/mage/sets/darkascension/CurseOfMisfortunes.java +++ b/Mage.Sets/src/mage/sets/darkascension/CurseOfMisfortunes.java @@ -108,7 +108,7 @@ class CurseOfMisfortunesEffect extends OneShotEffect { // get the names of attached Curses for (UUID attachmentId: targetPlayer.getAttachments()) { Permanent attachment = game.getPermanent(attachmentId); - if (attachment != null && attachment.getSubtype().contains("Curse")) { + if (attachment != null && attachment.getSubtype(game).contains("Curse")) { filter.add(Predicates.not(new NamePredicate(attachment.getName()))); } } diff --git a/Mage.Sets/src/mage/sets/darkascension/CurseOfThirst.java b/Mage.Sets/src/mage/sets/darkascension/CurseOfThirst.java index 9a5b75ad48..974ff0568e 100644 --- a/Mage.Sets/src/mage/sets/darkascension/CurseOfThirst.java +++ b/Mage.Sets/src/mage/sets/darkascension/CurseOfThirst.java @@ -136,7 +136,7 @@ class CursesAttachedCount implements DynamicValue { if (player != null) { for (UUID attachmentId: player.getAttachments()) { Permanent attachment = game.getPermanent(attachmentId); - if (attachment != null && attachment.getSubtype().contains("Curse")) + if (attachment != null && attachment.getSubtype(game).contains("Curse")) count++; } } diff --git a/Mage.Sets/src/mage/sets/darkascension/DeathsCaress.java b/Mage.Sets/src/mage/sets/darkascension/DeathsCaress.java index e3bc4a4706..5f665cc52d 100644 --- a/Mage.Sets/src/mage/sets/darkascension/DeathsCaress.java +++ b/Mage.Sets/src/mage/sets/darkascension/DeathsCaress.java @@ -89,7 +89,7 @@ class DeathsCaressEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); Permanent creature = (Permanent) game.getLastKnownInformation(source.getFirstTarget(), Zone.BATTLEFIELD); - if (player != null && creature != null && creature.hasSubtype("Human")) { + if (player != null && creature != null && creature.hasSubtype("Human", game)) { player.gainLife(creature.getToughness().getValue(), game); return true; } diff --git a/Mage.Sets/src/mage/sets/darkascension/FalkenrathAristocrat.java b/Mage.Sets/src/mage/sets/darkascension/FalkenrathAristocrat.java index 75e242e096..be9fb20d4c 100644 --- a/Mage.Sets/src/mage/sets/darkascension/FalkenrathAristocrat.java +++ b/Mage.Sets/src/mage/sets/darkascension/FalkenrathAristocrat.java @@ -106,7 +106,7 @@ class FalkenrathAristocratEffect extends OneShotEffect { if (cost instanceof SacrificeTargetCost) { Permanent sacrificedCreature = ((SacrificeTargetCost) cost).getPermanents().get(0); Permanent sourceCreature = game.getPermanent(source.getSourceId()); - if (sacrificedCreature.hasSubtype("Human") && sourceCreature != null) { + if (sacrificedCreature.hasSubtype("Human", game) && sourceCreature != null) { sourceCreature.addCounters(CounterType.P1P1.createInstance(), game); return true; } diff --git a/Mage.Sets/src/mage/sets/darkascension/FalkenrathTorturer.java b/Mage.Sets/src/mage/sets/darkascension/FalkenrathTorturer.java index 23c6d8e3d2..2fbd5451b1 100644 --- a/Mage.Sets/src/mage/sets/darkascension/FalkenrathTorturer.java +++ b/Mage.Sets/src/mage/sets/darkascension/FalkenrathTorturer.java @@ -102,7 +102,7 @@ class FalkenrathTorturerEffect extends OneShotEffect { if (cost instanceof SacrificeTargetCost) { Permanent sacrificedCreature = ((SacrificeTargetCost) cost).getPermanents().get(0); Permanent sourceCreature = game.getPermanent(source.getSourceId()); - if (sacrificedCreature.hasSubtype("Human") && sourceCreature != null) { + if (sacrificedCreature.hasSubtype("Human", game) && sourceCreature != null) { sourceCreature.addCounters(CounterType.P1P1.createInstance(), game); return true; } diff --git a/Mage.Sets/src/mage/sets/darkascension/LostInTheWoods.java b/Mage.Sets/src/mage/sets/darkascension/LostInTheWoods.java index fd593d07e7..66178ce6d2 100644 --- a/Mage.Sets/src/mage/sets/darkascension/LostInTheWoods.java +++ b/Mage.Sets/src/mage/sets/darkascension/LostInTheWoods.java @@ -96,7 +96,7 @@ class LostInTheWoodsEffect extends OneShotEffect { controller.revealCards(sourceObject.getName(), cards, game); if (card != null) { - if (card.getSubtype().contains("Forest")) { + if (card.getSubtype(game).contains("Forest")) { Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source)); if (permanent != null) { permanent.removeFromCombat(game); diff --git a/Mage.Sets/src/mage/sets/darkascension/MikaeusTheUnhallowed.java b/Mage.Sets/src/mage/sets/darkascension/MikaeusTheUnhallowed.java index b0df33eda0..3b1f5ef6de 100644 --- a/Mage.Sets/src/mage/sets/darkascension/MikaeusTheUnhallowed.java +++ b/Mage.Sets/src/mage/sets/darkascension/MikaeusTheUnhallowed.java @@ -114,7 +114,7 @@ class MikaeusTheUnhallowedAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { if (event.getTargetId().equals(this.controllerId)) { Permanent permanent = game.getPermanent(event.getSourceId()); - if (permanent != null && permanent.hasSubtype("Human")) { + if (permanent != null && permanent.hasSubtype("Human", game)) { this.getEffects().get(0).setTargetPointer(new FixedTarget(permanent.getId())); return true; } diff --git a/Mage.Sets/src/mage/sets/darksteel/MurderousSpoils.java b/Mage.Sets/src/mage/sets/darksteel/MurderousSpoils.java index 80c5130db5..c63973265c 100644 --- a/Mage.Sets/src/mage/sets/darksteel/MurderousSpoils.java +++ b/Mage.Sets/src/mage/sets/darksteel/MurderousSpoils.java @@ -100,7 +100,7 @@ class MurderousSpoilsEffect extends OneShotEffect { List attachments = new ArrayList(); for (UUID uuid : target.getAttachments()) { Permanent attached = game.getBattlefield().getPermanent(uuid); - if (attached.getSubtype().contains("Equipment")) { + if (attached.getSubtype(game).contains("Equipment")) { attachments.add(attached); } } diff --git a/Mage.Sets/src/mage/sets/darksteel/WireflyHive.java b/Mage.Sets/src/mage/sets/darksteel/WireflyHive.java index 0bdba0a96c..53040b5ea2 100644 --- a/Mage.Sets/src/mage/sets/darksteel/WireflyHive.java +++ b/Mage.Sets/src/mage/sets/darksteel/WireflyHive.java @@ -115,7 +115,7 @@ class WireflyToken extends Token { this.setOriginalExpansionSetCode("DST"); this.getPower().modifyBaseValue(2); this.getToughness().modifyBaseValue(2); - this.getSubtype().add("Insect"); + this.getSubtype(null).add("Insect"); this.getCardType().add(CardType.ARTIFACT); this.getCardType().add(CardType.CREATURE); } diff --git a/Mage.Sets/src/mage/sets/dissension/EvolutionVat.java b/Mage.Sets/src/mage/sets/dissension/EvolutionVat.java index 5d696c45d4..e07101f688 100644 --- a/Mage.Sets/src/mage/sets/dissension/EvolutionVat.java +++ b/Mage.Sets/src/mage/sets/dissension/EvolutionVat.java @@ -32,7 +32,7 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.Effect; import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; @@ -62,7 +62,7 @@ public class EvolutionVat extends CardImpl { Effect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance()); effect.setText("and put a +1/+1 counter on it"); ability.addEffect(effect); - effect = new AddCountersSourceEffect(CounterType.P1P1.createInstance(), new CountersCount(CounterType.P1P1), false); + effect = new AddCountersSourceEffect(CounterType.P1P1.createInstance(), new CountersSourceCount(CounterType.P1P1), false); effect.setText("Double the number of +1/+1 counters on this creature"); Ability gainedAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{2}{G}{U}")); ability.addEffect(new GainAbilityTargetEffect(gainedAbility, Duration.EndOfTurn, diff --git a/Mage.Sets/src/mage/sets/dissension/SimicGuildmage.java b/Mage.Sets/src/mage/sets/dissension/SimicGuildmage.java index 9cdc034680..742c1523ee 100644 --- a/Mage.Sets/src/mage/sets/dissension/SimicGuildmage.java +++ b/Mage.Sets/src/mage/sets/dissension/SimicGuildmage.java @@ -229,7 +229,7 @@ class MoveAuraEffect extends OneShotEffect { } // Check for protection MageObject auraObject = game.getObject(auraId); - if (permanentToAttachAuras.cantBeEnchantedBy(auraObject, game)) { + if (permanentToAttachAuras.cantBeAttachedBy(auraObject, game)) { passed = false; } } diff --git a/Mage.Sets/src/mage/sets/dissension/WalkingArchive.java b/Mage.Sets/src/mage/sets/dissension/WalkingArchive.java index 99157c353b..e98d11c696 100644 --- a/Mage.Sets/src/mage/sets/dissension/WalkingArchive.java +++ b/Mage.Sets/src/mage/sets/dissension/WalkingArchive.java @@ -36,7 +36,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.DrawCardTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.DefenderAbility; @@ -66,7 +66,7 @@ public class WalkingArchive extends CardImpl { this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), "Walking Archive enters the battlefield with a +1/+1 counter on it")); // At the beginning of each player's upkeep, that player draws a card for each +1/+1 counter on Walking Archive. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DrawCardTargetEffect(new CountersCount(CounterType.P1P1)), TargetController.ANY, false)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DrawCardTargetEffect(new CountersSourceCount(CounterType.P1P1)), TargetController.ANY, false)); // {2}{W}{U}: Put a +1/+1 counter on Walking Archive. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()), new ManaCostsImpl("{2}{W}{U}"))); diff --git a/Mage.Sets/src/mage/sets/dragonsmaze/MazesEnd.java b/Mage.Sets/src/mage/sets/dragonsmaze/MazesEnd.java index b8ff5248c0..da6ced7f42 100644 --- a/Mage.Sets/src/mage/sets/dragonsmaze/MazesEnd.java +++ b/Mage.Sets/src/mage/sets/dragonsmaze/MazesEnd.java @@ -114,7 +114,7 @@ class MazesEndEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { List names = new ArrayList(); for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) { - if (permanent.hasSubtype("Gate")) { + if (permanent.hasSubtype("Gate", game)) { if (!names.contains(permanent.getName())) { names.add(permanent.getName()); } diff --git a/Mage.Sets/src/mage/sets/dragonsoftarkir/GateSmasher.java b/Mage.Sets/src/mage/sets/dragonsoftarkir/GateSmasher.java index 30fe6e9229..075bd31f32 100644 --- a/Mage.Sets/src/mage/sets/dragonsoftarkir/GateSmasher.java +++ b/Mage.Sets/src/mage/sets/dragonsoftarkir/GateSmasher.java @@ -29,10 +29,10 @@ package mage.sets.dragonsoftarkir; import java.util.UUID; import mage.abilities.Ability; +import mage.abilities.common.AttachableToRestrictedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.Effect; -import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.keyword.EquipAbility; @@ -46,6 +46,7 @@ import mage.constants.Zone; import mage.filter.Filter; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.ToughnessPredicate; +import mage.target.Target; import mage.target.common.TargetControlledCreaturePermanent; /** @@ -65,9 +66,10 @@ public class GateSmasher extends CardImpl { this.expansionSetCode = "DTK"; this.subtype.add("Equipment"); + Target target = new TargetControlledCreaturePermanent(1, 1, filter, false); // Gate Smasher can be attached only to a creature with toughness 4 or greater. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new InfoEffect("{this} can be attached only to a creature with toughness 4 or greater"))); - + this.addAbility(new AttachableToRestrictedAbility(target)); + // Equipped creature gets +3/+0 and has trample. Effect effect = new BoostEquippedEffect(3, 0); effect.setText("Equipped creature gets +3/+0"); @@ -76,13 +78,10 @@ public class GateSmasher extends CardImpl { effect.setText("and has trample"); ability.addEffect(effect); this.addAbility(ability); - + // Equip {3} - this.addAbility(new EquipAbility( - Outcome.AddAbility, - new GenericManaCost(3), - new TargetControlledCreaturePermanent(1,1, filter, false))); - + this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(3), target)); + } public GateSmasher(final GateSmasher card) { diff --git a/Mage.Sets/src/mage/sets/dragonsoftarkir/HavenOfTheSpiritDragon.java b/Mage.Sets/src/mage/sets/dragonsoftarkir/HavenOfTheSpiritDragon.java index 8e7a0c3a87..30f30abf37 100644 --- a/Mage.Sets/src/mage/sets/dragonsoftarkir/HavenOfTheSpiritDragon.java +++ b/Mage.Sets/src/mage/sets/dragonsoftarkir/HavenOfTheSpiritDragon.java @@ -124,7 +124,7 @@ class HavenOfTheSpiritManaCondition extends CreatureCastManaCondition { public boolean apply(Game game, Ability source, UUID manaProducer, Cost costToPay) { if (super.apply(game, source)) { MageObject object = game.getObject(source.getSourceId()); - if (object.hasSubtype("Dragon") + if (object.hasSubtype("Dragon", game) && object.getCardType().contains(CardType.CREATURE)) { return true; } @@ -141,7 +141,7 @@ class DragonCreatureCardPredicate implements Predicate { @Override public boolean apply(Card input, Game game) { return input.getCardType().contains(CardType.CREATURE) - && input.getSubtype().contains("Dragon"); + && input.getSubtype(game).contains("Dragon"); } @Override diff --git a/Mage.Sets/src/mage/sets/eldritchmoon/CemeteryRecruitment.java b/Mage.Sets/src/mage/sets/eldritchmoon/CemeteryRecruitment.java index e4c7690482..162d6c4ea8 100644 --- a/Mage.Sets/src/mage/sets/eldritchmoon/CemeteryRecruitment.java +++ b/Mage.Sets/src/mage/sets/eldritchmoon/CemeteryRecruitment.java @@ -89,7 +89,7 @@ class CemeteryRecruitmentEffect extends OneShotEffect { Card card = game.getCard(targetPointer.getFirst(game, source)); if (card != null) { if (controller.moveCards(card, Zone.HAND, source, game) - && card.getSubtype().contains("Zombie")) { + && card.getSubtype(game).contains("Zombie")) { controller.drawCards(1, game); } } diff --git a/Mage.Sets/src/mage/sets/eldritchmoon/CoaxFromTheBlindEternities.java b/Mage.Sets/src/mage/sets/eldritchmoon/CoaxFromTheBlindEternities.java index b09d3e2917..38cc856af3 100644 --- a/Mage.Sets/src/mage/sets/eldritchmoon/CoaxFromTheBlindEternities.java +++ b/Mage.Sets/src/mage/sets/eldritchmoon/CoaxFromTheBlindEternities.java @@ -110,7 +110,7 @@ class CoaxFromTheBlindEternitiesEffect extends OneShotEffect { filteredCards.add(sideboardCard.getId()); } for (Card exileCard : exile) { - if (exileCard.getOwnerId().equals(source.getControllerId()) && exileCard.hasSubtype("Eldrazi")) { + if (exileCard.getOwnerId().equals(source.getControllerId()) && exileCard.hasSubtype("Eldrazi", game)) { filteredCards.add(exileCard); } } diff --git a/Mage.Sets/src/mage/sets/eldritchmoon/GisaAndGeralf.java b/Mage.Sets/src/mage/sets/eldritchmoon/GisaAndGeralf.java index 840dea6169..58a485db99 100644 --- a/Mage.Sets/src/mage/sets/eldritchmoon/GisaAndGeralf.java +++ b/Mage.Sets/src/mage/sets/eldritchmoon/GisaAndGeralf.java @@ -175,7 +175,7 @@ class GisaAndGeralfWatcher extends Watcher { public void watch(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.SPELL_CAST && event.getZone() == Zone.GRAVEYARD) { Spell spell = (Spell) game.getObject(event.getTargetId()); - if (spell.getCardType().contains(CardType.CREATURE) && spell.getSubtype().contains("Zombie")) { + if (spell.getCardType().contains(CardType.CREATURE) && spell.getSubtype(game).contains("Zombie")) { abilityUsed = true; } } diff --git a/Mage.Sets/src/mage/sets/eldritchmoon/ImprisonedInTheMoon.java b/Mage.Sets/src/mage/sets/eldritchmoon/ImprisonedInTheMoon.java index 194a3b54a3..d8d012752b 100644 --- a/Mage.Sets/src/mage/sets/eldritchmoon/ImprisonedInTheMoon.java +++ b/Mage.Sets/src/mage/sets/eldritchmoon/ImprisonedInTheMoon.java @@ -136,7 +136,7 @@ class BecomesColorlessLandEffect extends ContinuousEffectImpl { permanent.getCardType().clear(); permanent.getCardType().add(CardType.LAND); if (!isLand) { - permanent.getSubtype().clear(); + permanent.getSubtype(game).clear(); } break; } diff --git a/Mage.Sets/src/mage/sets/eldritchmoon/SlayersCleaver.java b/Mage.Sets/src/mage/sets/eldritchmoon/SlayersCleaver.java index b59fd670a7..b98dab2ec3 100644 --- a/Mage.Sets/src/mage/sets/eldritchmoon/SlayersCleaver.java +++ b/Mage.Sets/src/mage/sets/eldritchmoon/SlayersCleaver.java @@ -90,7 +90,7 @@ class SlayersCleaverEffect extends RequirementEffect { @Override public boolean applies(Permanent permanent, Ability source, Game game) { - return permanent.canBlock(source.getSourceId(), game) && permanent.hasSubtype("Eldrazi"); + return permanent.canBlock(source.getSourceId(), game) && permanent.hasSubtype("Eldrazi", game); } @Override diff --git a/Mage.Sets/src/mage/sets/fallenempires/BottomlessVault.java b/Mage.Sets/src/mage/sets/fallenempires/BottomlessVault.java index fc48a9218f..e833ae7cb8 100644 --- a/Mage.Sets/src/mage/sets/fallenempires/BottomlessVault.java +++ b/Mage.Sets/src/mage/sets/fallenempires/BottomlessVault.java @@ -37,7 +37,7 @@ import mage.abilities.condition.common.SourceTappedCondition; import mage.abilities.costs.common.RemoveVariableCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.decorator.ConditionalOneShotEffect; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; @@ -74,7 +74,7 @@ public class BottomlessVault extends CardImpl { new RemovedCountersForCostValue(), new TapSourceCost(), "Add {B} to your mana pool for each storage counter removed this way", - true, new CountersCount(CounterType.STORAGE)); + true, new CountersSourceCount(CounterType.STORAGE)); ability.addCost(new RemoveVariableCountersSourceCost(CounterType.STORAGE.createInstance(), "Remove any number of storage counters from {this}")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/fallenempires/HollowTrees.java b/Mage.Sets/src/mage/sets/fallenempires/HollowTrees.java index 390760d261..25cb0c208e 100644 --- a/Mage.Sets/src/mage/sets/fallenempires/HollowTrees.java +++ b/Mage.Sets/src/mage/sets/fallenempires/HollowTrees.java @@ -37,7 +37,7 @@ import mage.abilities.condition.common.SourceTappedCondition; import mage.abilities.costs.common.RemoveVariableCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.decorator.ConditionalOneShotEffect; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; @@ -74,7 +74,7 @@ public class HollowTrees extends CardImpl { new RemovedCountersForCostValue(), new TapSourceCost(), "Add {G} to your mana pool for each storage counter removed this way", - true, new CountersCount(CounterType.STORAGE)); + true, new CountersSourceCount(CounterType.STORAGE)); ability.addCost(new RemoveVariableCountersSourceCost(CounterType.STORAGE.createInstance(), "Remove any number of storage counters from {this}")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/fallenempires/Homarid1.java b/Mage.Sets/src/mage/sets/fallenempires/Homarid1.java index de26cfb3e9..18091e901c 100644 --- a/Mage.Sets/src/mage/sets/fallenempires/Homarid1.java +++ b/Mage.Sets/src/mage/sets/fallenempires/Homarid1.java @@ -35,7 +35,7 @@ import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.Effect; import mage.abilities.effects.common.RemoveAllCountersSourceEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; @@ -108,7 +108,7 @@ class HomaridTriggeredAbility extends StateTriggeredAbility { @Override public boolean checkTrigger(GameEvent event, Game game) { - return new CountersCount(CounterType.TIDE).calculate(game, this, null) == 4; + return new CountersSourceCount(CounterType.TIDE).calculate(game, this, null) == 4; } @Override diff --git a/Mage.Sets/src/mage/sets/fallenempires/HomaridSpawningBed.java b/Mage.Sets/src/mage/sets/fallenempires/HomaridSpawningBed.java index eac5d491f8..3f53f2733b 100644 --- a/Mage.Sets/src/mage/sets/fallenempires/HomaridSpawningBed.java +++ b/Mage.Sets/src/mage/sets/fallenempires/HomaridSpawningBed.java @@ -85,7 +85,7 @@ class CamaridToken extends Token { this.getPower().modifyBaseValue(1); this.getToughness().modifyBaseValue(1); this.color.setBlue(true); - this.getSubtype().add("Camarid"); + this.getSubtype(null).add("Camarid"); this.getCardType().add(CardType.CREATURE); } } \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/fallenempires/IcatianMoneychanger1.java b/Mage.Sets/src/mage/sets/fallenempires/IcatianMoneychanger1.java index f047aafece..88b7160e3b 100644 --- a/Mage.Sets/src/mage/sets/fallenempires/IcatianMoneychanger1.java +++ b/Mage.Sets/src/mage/sets/fallenempires/IcatianMoneychanger1.java @@ -35,7 +35,7 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.decorator.ConditionalActivatedAbility; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DamageControllerEffect; import mage.abilities.effects.common.GainLifeEffect; @@ -76,7 +76,7 @@ public class IcatianMoneychanger1 extends CardImpl { // Sacrifice Icatian Moneychanger: You gain 1 life for each credit counter on Icatian Moneychanger. Activate this ability only during your upkeep. this.addAbility(new ConditionalActivatedAbility(Zone.BATTLEFIELD, - new GainLifeEffect(new CountersCount(CounterType.CREDIT)), new SacrificeSourceCost(), new IsStepCondition(PhaseStep.UPKEEP), null)); + new GainLifeEffect(new CountersSourceCount(CounterType.CREDIT)), new SacrificeSourceCost(), new IsStepCondition(PhaseStep.UPKEEP), null)); } public IcatianMoneychanger1(final IcatianMoneychanger1 card) { diff --git a/Mage.Sets/src/mage/sets/fallenempires/IcatianStore.java b/Mage.Sets/src/mage/sets/fallenempires/IcatianStore.java index 7c055985df..946b584908 100644 --- a/Mage.Sets/src/mage/sets/fallenempires/IcatianStore.java +++ b/Mage.Sets/src/mage/sets/fallenempires/IcatianStore.java @@ -37,7 +37,7 @@ import mage.abilities.condition.common.SourceTappedCondition; import mage.abilities.costs.common.RemoveVariableCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.decorator.ConditionalOneShotEffect; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; @@ -74,7 +74,7 @@ public class IcatianStore extends CardImpl { new RemovedCountersForCostValue(), new TapSourceCost(), "Add {W} to your mana pool for each storage counter removed this way", - true, new CountersCount(CounterType.STORAGE)); + true, new CountersSourceCount(CounterType.STORAGE)); ability.addCost(new RemoveVariableCountersSourceCost(CounterType.STORAGE.createInstance(), "Remove any number of storage counters from {this}")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/fallenempires/TidalInfluence.java b/Mage.Sets/src/mage/sets/fallenempires/TidalInfluence.java index 5f92d4ced1..57ae2d23a6 100644 --- a/Mage.Sets/src/mage/sets/fallenempires/TidalInfluence.java +++ b/Mage.Sets/src/mage/sets/fallenempires/TidalInfluence.java @@ -38,7 +38,7 @@ import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.Cost; import mage.abilities.costs.CostImpl; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.Effect; import mage.abilities.effects.common.RemoveAllCountersSourceEffect; import mage.abilities.effects.common.continuous.BoostAllEffect; @@ -157,7 +157,7 @@ class TidalInfluenceTriggeredAbility extends StateTriggeredAbility { @Override public boolean checkTrigger(GameEvent event, Game game) { - return new CountersCount(CounterType.TIDE).calculate(game, this, null) == 4; + return new CountersSourceCount(CounterType.TIDE).calculate(game, this, null) == 4; } @Override diff --git a/Mage.Sets/src/mage/sets/fatereforged/CrucibleOfTheSpiritDragon.java b/Mage.Sets/src/mage/sets/fatereforged/CrucibleOfTheSpiritDragon.java index 3e7c8fe5cb..2781288eb5 100644 --- a/Mage.Sets/src/mage/sets/fatereforged/CrucibleOfTheSpiritDragon.java +++ b/Mage.Sets/src/mage/sets/fatereforged/CrucibleOfTheSpiritDragon.java @@ -115,7 +115,7 @@ class CrucibleOfTheSpiritDragonManaCondition implements Condition { @Override public boolean apply(Game game, Ability source) { MageObject object = game.getObject(source.getSourceId()); - if (object != null && object.hasSubtype("Dragon")) { + if (object != null && object.hasSubtype("Dragon", game)) { return true; } return false; diff --git a/Mage.Sets/src/mage/sets/fatereforged/FearsomeAwakening.java b/Mage.Sets/src/mage/sets/fatereforged/FearsomeAwakening.java index 671506b30a..f0da845556 100644 --- a/Mage.Sets/src/mage/sets/fatereforged/FearsomeAwakening.java +++ b/Mage.Sets/src/mage/sets/fatereforged/FearsomeAwakening.java @@ -86,7 +86,7 @@ class FearsomeAwakeningEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getFirstTarget()); - if (permanent != null && permanent.hasSubtype("Dragon")) { + if (permanent != null && permanent.hasSubtype("Dragon", game)) { permanent.addCounters(CounterType.P1P1.createInstance(2), game); return true; } diff --git a/Mage.Sets/src/mage/sets/fatereforged/MarduWoeReaper.java b/Mage.Sets/src/mage/sets/fatereforged/MarduWoeReaper.java index 77ef5b6b78..8679ee65ea 100644 --- a/Mage.Sets/src/mage/sets/fatereforged/MarduWoeReaper.java +++ b/Mage.Sets/src/mage/sets/fatereforged/MarduWoeReaper.java @@ -99,7 +99,7 @@ class MarduWoeReaperTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { if (event.getPlayerId().equals(this.getControllerId())) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && (permanent.getId().equals(this.getSourceId()) || permanent.hasSubtype("Warrior"))) { + if (permanent != null && (permanent.getId().equals(this.getSourceId()) || permanent.hasSubtype("Warrior", game))) { return true; } } diff --git a/Mage.Sets/src/mage/sets/fatereforged/ScrollOfTheMasters.java b/Mage.Sets/src/mage/sets/fatereforged/ScrollOfTheMasters.java index d4aca222bf..dfc2a8d139 100644 --- a/Mage.Sets/src/mage/sets/fatereforged/ScrollOfTheMasters.java +++ b/Mage.Sets/src/mage/sets/fatereforged/ScrollOfTheMasters.java @@ -34,7 +34,7 @@ import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -69,7 +69,7 @@ public class ScrollOfTheMasters extends CardImpl { this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.LORE.createInstance()), filterNonCreature, false)); // {3}, {T}: Target creature you control gets +1/+1 until end of turn for each lore counter on Scroll of the Masters. - DynamicValue xValue = new CountersCount(CounterType.LORE); + DynamicValue xValue = new CountersSourceCount(CounterType.LORE); Effect effect = new BoostTargetEffect(xValue, xValue, Duration.EndOfTurn); effect.setText("Target creature you control gets +1/+1 until end of turn for each lore counter on {this}"); Ability ability = new SimpleActivatedAbility( diff --git a/Mage.Sets/src/mage/sets/fifthdawn/AuriokWindwalker.java b/Mage.Sets/src/mage/sets/fifthdawn/AuriokWindwalker.java index d69f7e1fa3..1cb4da8d16 100644 --- a/Mage.Sets/src/mage/sets/fifthdawn/AuriokWindwalker.java +++ b/Mage.Sets/src/mage/sets/fifthdawn/AuriokWindwalker.java @@ -53,6 +53,7 @@ import mage.target.common.TargetControlledPermanent; public class AuriokWindwalker extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent("Equipment you control"); + static { filter.add(new SubtypePredicate("Equipment")); } @@ -67,7 +68,7 @@ public class AuriokWindwalker extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); - // {tap}: Attach target Equipment you control to target creature you control. + // {T}: Attach target Equipment you control to target creature you control. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AttachTargetEquipmentEffect(), new TapSourceCost()); ability.addTarget(new TargetControlledPermanent(filter)); ability.addTarget(new TargetControlledCreaturePermanent()); @@ -84,7 +85,6 @@ public class AuriokWindwalker extends CardImpl { } } - class AttachTargetEquipmentEffect extends OneShotEffect { public AttachTargetEquipmentEffect() { diff --git a/Mage.Sets/src/mage/sets/fifthdawn/ChimericCoils.java b/Mage.Sets/src/mage/sets/fifthdawn/ChimericCoils.java index 0f433f8637..7cbcffd78a 100644 --- a/Mage.Sets/src/mage/sets/fifthdawn/ChimericCoils.java +++ b/Mage.Sets/src/mage/sets/fifthdawn/ChimericCoils.java @@ -96,7 +96,7 @@ class ChimericCoilsEffect extends ContinuousEffectImpl { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { permanent.getCardType().add(CardType.CREATURE); - permanent.getSubtype().add("Construct"); + permanent.getSubtype(game).add("Construct"); } break; case PTChangingEffects_7: diff --git a/Mage.Sets/src/mage/sets/fifthdawn/ClearwaterGoblet.java b/Mage.Sets/src/mage/sets/fifthdawn/ClearwaterGoblet.java index 8872cc832b..5fea9f94e9 100644 --- a/Mage.Sets/src/mage/sets/fifthdawn/ClearwaterGoblet.java +++ b/Mage.Sets/src/mage/sets/fifthdawn/ClearwaterGoblet.java @@ -32,7 +32,7 @@ import java.util.UUID; import mage.constants.CardType; import mage.constants.Rarity; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.keyword.SunburstAbility; import mage.cards.CardImpl; @@ -53,7 +53,7 @@ public class ClearwaterGoblet extends CardImpl { // Sunburst this.addAbility(new SunburstAbility(this)); // At the beginning of your upkeep, you may gain life equal to the number of charge counters on Clearwater Goblet. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new GainLifeEffect(new CountersCount(CounterType.CHARGE)), TargetController.YOU, true)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new GainLifeEffect(new CountersSourceCount(CounterType.CHARGE)), TargetController.YOU, true)); } public ClearwaterGoblet(final ClearwaterGoblet card) { diff --git a/Mage.Sets/src/mage/sets/fifthdawn/GoblinBrawler.java b/Mage.Sets/src/mage/sets/fifthdawn/GoblinBrawler.java index 5851db6705..702bf3486d 100644 --- a/Mage.Sets/src/mage/sets/fifthdawn/GoblinBrawler.java +++ b/Mage.Sets/src/mage/sets/fifthdawn/GoblinBrawler.java @@ -99,7 +99,7 @@ class CantBeEquippedSourceEffect extends ContinuousRuleModifyingEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { if (event.getTargetId().equals(source.getSourceId())) { Permanent permanent = game.getPermanent(event.getSourceId()); - if (permanent != null && permanent.getSubtype().contains("Equipment")) { + if (permanent != null && permanent.getSubtype(game).contains("Equipment")) { return true; } } diff --git a/Mage.Sets/src/mage/sets/fifthdawn/Heliophial.java b/Mage.Sets/src/mage/sets/fifthdawn/Heliophial.java index af470f8467..343c12848c 100644 --- a/Mage.Sets/src/mage/sets/fifthdawn/Heliophial.java +++ b/Mage.Sets/src/mage/sets/fifthdawn/Heliophial.java @@ -32,7 +32,7 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.keyword.SunburstAbility; @@ -56,7 +56,7 @@ public class Heliophial extends CardImpl { // Sunburst this.addAbility(new SunburstAbility(this)); // {2}, Sacrifice Heliophial: Heliophial deals damage equal to the number of charge counters on it to target creature or player. - Effect effect = new DamageTargetEffect(new CountersCount(CounterType.CHARGE)); + Effect effect = new DamageTargetEffect(new CountersSourceCount(CounterType.CHARGE)); effect.setText("{this} deals damage equal to the number of charge counters on it to target creature or player"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{2}")); ability.addCost(new SacrificeSourceCost()); diff --git a/Mage.Sets/src/mage/sets/fifthdawn/MephidrossVampire.java b/Mage.Sets/src/mage/sets/fifthdawn/MephidrossVampire.java index 91ab6c921f..b39c3013eb 100644 --- a/Mage.Sets/src/mage/sets/fifthdawn/MephidrossVampire.java +++ b/Mage.Sets/src/mage/sets/fifthdawn/MephidrossVampire.java @@ -118,8 +118,8 @@ class MephidrossVampireEffect extends ContinuousEffectImpl { creature.addAbility(new DealsDamageToACreatureTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false, false, false), source.getSourceId(), game); break; case TypeChangingEffects_4: - if (!creature.getSubtype().contains("Vampire")) { - creature.getSubtype().add("Vampire"); + if (!creature.getSubtype(game).contains("Vampire")) { + creature.getSubtype(game).add("Vampire"); } break; } diff --git a/Mage.Sets/src/mage/sets/fifthdawn/OpalineBracers.java b/Mage.Sets/src/mage/sets/fifthdawn/OpalineBracers.java index bed42238c5..b5c4318ef5 100644 --- a/Mage.Sets/src/mage/sets/fifthdawn/OpalineBracers.java +++ b/Mage.Sets/src/mage/sets/fifthdawn/OpalineBracers.java @@ -30,7 +30,7 @@ package mage.sets.fifthdawn; import java.util.UUID; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.keyword.EquipAbility; import mage.abilities.keyword.SunburstAbility; @@ -55,7 +55,7 @@ public class OpalineBracers extends CardImpl { // Sunburst this.addAbility(new SunburstAbility(this)); // Equipped creature gets +X/+X, where X is the number of charge counters on Opaline Bracers. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(new CountersCount(CounterType.CHARGE), new CountersCount(CounterType.CHARGE)))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(new CountersSourceCount(CounterType.CHARGE), new CountersSourceCount(CounterType.CHARGE)))); // Equip {2} this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(2))); } diff --git a/Mage.Sets/src/mage/sets/fifthdawn/Solarion.java b/Mage.Sets/src/mage/sets/fifthdawn/Solarion.java index 7290ecd6ef..ce69a4b975 100644 --- a/Mage.Sets/src/mage/sets/fifthdawn/Solarion.java +++ b/Mage.Sets/src/mage/sets/fifthdawn/Solarion.java @@ -31,7 +31,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.Effect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.SunburstAbility; @@ -57,7 +57,7 @@ public class Solarion extends CardImpl { // Sunburst this.addAbility(new SunburstAbility(this)); // {tap}: Double the number of +1/+1 counters on Solarion. - Effect effect = new AddCountersSourceEffect(CounterType.P1P1.createInstance(1), new CountersCount(CounterType.P1P1), true); + Effect effect = new AddCountersSourceEffect(CounterType.P1P1.createInstance(1), new CountersSourceCount(CounterType.P1P1), true); effect.setText("Double the number of +1/+1 counters on {this}"); this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost())); } diff --git a/Mage.Sets/src/mage/sets/fifthedition/DwarvenHold.java b/Mage.Sets/src/mage/sets/fifthedition/DwarvenHold.java index 60ca440967..69c3277117 100644 --- a/Mage.Sets/src/mage/sets/fifthedition/DwarvenHold.java +++ b/Mage.Sets/src/mage/sets/fifthedition/DwarvenHold.java @@ -37,7 +37,7 @@ import mage.abilities.condition.common.SourceTappedCondition; import mage.abilities.costs.common.RemoveVariableCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.decorator.ConditionalOneShotEffect; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; @@ -74,7 +74,7 @@ public class DwarvenHold extends CardImpl { new RemovedCountersForCostValue(), new TapSourceCost(), "Add {R} to your mana pool for each storage counter removed this way", - true, new CountersCount(CounterType.STORAGE)); + true, new CountersSourceCount(CounterType.STORAGE)); ability.addCost(new RemoveVariableCountersSourceCost(CounterType.STORAGE.createInstance(), "Remove any number of storage counters from {this}")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/fifthedition/SandSilos.java b/Mage.Sets/src/mage/sets/fifthedition/SandSilos.java index 63700f3f9a..2d86fbb628 100644 --- a/Mage.Sets/src/mage/sets/fifthedition/SandSilos.java +++ b/Mage.Sets/src/mage/sets/fifthedition/SandSilos.java @@ -37,7 +37,7 @@ import mage.abilities.condition.common.SourceTappedCondition; import mage.abilities.costs.common.RemoveVariableCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.decorator.ConditionalOneShotEffect; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; @@ -74,7 +74,7 @@ public class SandSilos extends CardImpl { new RemovedCountersForCostValue(), new TapSourceCost(), "Add {U} to your mana pool for each storage counter removed this way", - true, new CountersCount(CounterType.STORAGE)); + true, new CountersSourceCount(CounterType.STORAGE)); ability.addCost(new RemoveVariableCountersSourceCost(CounterType.STORAGE.createInstance(), "Remove any number of storage counters from {this}")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/fourthedition/SirensCall.java b/Mage.Sets/src/mage/sets/fourthedition/SirensCall.java index 654864c4e3..e686777a4a 100644 --- a/Mage.Sets/src/mage/sets/fourthedition/SirensCall.java +++ b/Mage.Sets/src/mage/sets/fourthedition/SirensCall.java @@ -135,7 +135,7 @@ class SirensCallDestroyEffect extends OneShotEffect { if (player != null) { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(player.getId())) { // Walls are safe. - if (permanent.getSubtype().contains("Wall")) { + if (permanent.getSubtype(game).contains("Wall")) { continue; } // Creatures that attacked are safe. diff --git a/Mage.Sets/src/mage/sets/futuresight/DaybreakCoronet.java b/Mage.Sets/src/mage/sets/futuresight/DaybreakCoronet.java index fcb3ab20ff..d547809722 100644 --- a/Mage.Sets/src/mage/sets/futuresight/DaybreakCoronet.java +++ b/Mage.Sets/src/mage/sets/futuresight/DaybreakCoronet.java @@ -115,7 +115,7 @@ class AuraAttachedPredicate implements Predicate { if (!uuid.equals(ownId)) { Permanent attachment = game.getPermanent(uuid); if (attachment != null - && attachment.getSubtype().contains("Aura")) { + && attachment.getSubtype(game).contains("Aura")) { return true; } } diff --git a/Mage.Sets/src/mage/sets/futuresight/MagusOfTheMoon.java b/Mage.Sets/src/mage/sets/futuresight/MagusOfTheMoon.java index 75a6a5cb07..527d0afde7 100644 --- a/Mage.Sets/src/mage/sets/futuresight/MagusOfTheMoon.java +++ b/Mage.Sets/src/mage/sets/futuresight/MagusOfTheMoon.java @@ -113,8 +113,8 @@ public class MagusOfTheMoon extends CardImpl { // 305.7 Note that this doesn't remove any abilities that were granted to the land by other effects // So the ability removing has to be done before Layer 6 land.removeAllAbilities(source.getSourceId(), game); - land.getSubtype().removeAll(CardRepository.instance.getLandTypes()); - land.getSubtype().add("Mountain"); + land.getSubtype(game).removeAll(CardRepository.instance.getLandTypes()); + land.getSubtype(game).add("Mountain"); break; case AbilityAddingRemovingEffects_6: land.addAbility(new RedManaAbility(), source.getSourceId(), game); diff --git a/Mage.Sets/src/mage/sets/gatecrash/AssembleTheLegion.java b/Mage.Sets/src/mage/sets/gatecrash/AssembleTheLegion.java index 3184f889ca..73dc4861d9 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/AssembleTheLegion.java +++ b/Mage.Sets/src/mage/sets/gatecrash/AssembleTheLegion.java @@ -30,7 +30,7 @@ package mage.sets.gatecrash; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -52,7 +52,7 @@ public class AssembleTheLegion extends CardImpl { // At the beginning of your upkeep, put a muster counter on Assemble the Legion. Then put a 1/1 red and white Soldier creature token with haste onto the battlefield for each muster counter on Assemble the Legion. Ability ability = new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.MUSTER.createInstance()), TargetController.YOU, false); - ability.addEffect(new CreateTokenEffect(new SoldierTokenWithHaste(), new CountersCount(CounterType.MUSTER))); + ability.addEffect(new CreateTokenEffect(new SoldierTokenWithHaste(), new CountersSourceCount(CounterType.MUSTER))); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/gatecrash/DeathcultRogue.java b/Mage.Sets/src/mage/sets/gatecrash/DeathcultRogue.java index 3680ee5378..1ea9096b60 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/DeathcultRogue.java +++ b/Mage.Sets/src/mage/sets/gatecrash/DeathcultRogue.java @@ -92,7 +92,7 @@ class DeathcultRogueRestrictionEffect extends RestrictionEffect { @Override public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game) { - if (blocker.getSubtype().contains("Rogue")) { + if (blocker.getSubtype(game).contains("Rogue")) { return true; } return false; diff --git a/Mage.Sets/src/mage/sets/gatecrash/GideonChampionOfJustice.java b/Mage.Sets/src/mage/sets/gatecrash/GideonChampionOfJustice.java index ca21e65092..4194da7f2f 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/GideonChampionOfJustice.java +++ b/Mage.Sets/src/mage/sets/gatecrash/GideonChampionOfJustice.java @@ -33,7 +33,7 @@ import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; import mage.abilities.dynamicvalue.LockedInDynamicValue; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.PermanentsTargetOpponentControlsCount; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.PreventAllDamageToSourceEffect; @@ -72,7 +72,7 @@ public class GideonChampionOfJustice extends CardImpl { this.addAbility(ability1); // 0: Until end of turn, Gideon becomes an indestructible Human Soldier creature with power and toughness each equal to the number of loyalty counters on him. He's still a planeswalker. Prevent all damage that would be dealt to him this turn. - LockedInDynamicValue loyaltyCount = new LockedInDynamicValue(new CountersCount(CounterType.LOYALTY)); + LockedInDynamicValue loyaltyCount = new LockedInDynamicValue(new CountersSourceCount(CounterType.LOYALTY)); LoyaltyAbility ability2 = new LoyaltyAbility(new BecomesCreatureSourceEffect( new GideonChampionOfJusticeToken(), "planeswalker", Duration.EndOfTurn, false, false, loyaltyCount, loyaltyCount), 0); ability2.addEffect(new PreventAllDamageToSourceEffect(Duration.EndOfTurn)); diff --git a/Mage.Sets/src/mage/sets/gatecrash/GyreSage.java b/Mage.Sets/src/mage/sets/gatecrash/GyreSage.java index 514c46a159..66277f4c54 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/GyreSage.java +++ b/Mage.Sets/src/mage/sets/gatecrash/GyreSage.java @@ -33,7 +33,7 @@ import mage.constants.CardType; import mage.constants.Rarity; import mage.MageInt; import mage.Mana; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.keyword.EvolveAbility; import mage.abilities.mana.DynamicManaAbility; import mage.cards.CardImpl; @@ -59,7 +59,7 @@ public class GyreSage extends CardImpl { this.addAbility(new EvolveAbility()); //{T} : Add {G} to your mana pool for each +1/+1 counter on Gyre Sage. - this.addAbility(new DynamicManaAbility(Mana.GreenMana(1), new CountersCount(CounterType.P1P1))); + this.addAbility(new DynamicManaAbility(Mana.GreenMana(1), new CountersSourceCount(CounterType.P1P1))); } public GyreSage(final GyreSage card) { diff --git a/Mage.Sets/src/mage/sets/gatecrash/Hydroform.java b/Mage.Sets/src/mage/sets/gatecrash/Hydroform.java index 41f3e451aa..8987e73d15 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/Hydroform.java +++ b/Mage.Sets/src/mage/sets/gatecrash/Hydroform.java @@ -70,7 +70,7 @@ class HydroformToken extends Token { public HydroformToken() { super("", "3/3 Elemental creature with flying"); this.cardType.add(CardType.CREATURE); - this.getSubtype().add("Elemental"); + this.getSubtype(null).add("Elemental"); this.power = new MageInt(3); this.toughness = new MageInt(3); diff --git a/Mage.Sets/src/mage/sets/gatecrash/LazavDimirMastermind.java b/Mage.Sets/src/mage/sets/gatecrash/LazavDimirMastermind.java index de7f4c2013..c81084b010 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/LazavDimirMastermind.java +++ b/Mage.Sets/src/mage/sets/gatecrash/LazavDimirMastermind.java @@ -129,10 +129,10 @@ class LazavDimirEffect extends ContinuousEffectImpl { permanent.getCardType().add(type); } } - permanent.getSubtype().clear(); - for (String type : cardToCopy.getSubtype()) { - if (!permanent.getSubtype().contains(type)) { - permanent.getSubtype().add(type); + permanent.getSubtype(game).clear(); + for (String type : cardToCopy.getSubtype(game)) { + if (!permanent.getSubtype(game).contains(type)) { + permanent.getSubtype(game).add(type); } } permanent.getSupertype().clear(); diff --git a/Mage.Sets/src/mage/sets/gatecrash/OrzhovCharm.java b/Mage.Sets/src/mage/sets/gatecrash/OrzhovCharm.java index c30464641e..c28725d324 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/OrzhovCharm.java +++ b/Mage.Sets/src/mage/sets/gatecrash/OrzhovCharm.java @@ -119,7 +119,7 @@ class OrzhovCharmReturnToHandEffect extends OneShotEffect { for (UUID attachmentId : attachments) { Permanent attachment = game.getPermanent(attachmentId); if (attachment != null && attachment.getControllerId().equals(source.getControllerId()) - && attachment.getSubtype().contains("Aura")) { + && attachment.getSubtype(game).contains("Aura")) { attachment.moveToZone(Zone.HAND, source.getSourceId(), game, false); } } diff --git a/Mage.Sets/src/mage/sets/gatecrash/Realmwright.java b/Mage.Sets/src/mage/sets/gatecrash/Realmwright.java index 3b07a6c97c..c46dc8123e 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/Realmwright.java +++ b/Mage.Sets/src/mage/sets/gatecrash/Realmwright.java @@ -111,8 +111,8 @@ class RealmwrightEffect2 extends ContinuousEffectImpl { if (land != null) { switch (layer) { case TypeChangingEffects_4: - if (sublayer == SubLayer.NA && !land.getSubtype().contains(choice)) { - land.getSubtype().add(choice); + if (sublayer == SubLayer.NA && !land.getSubtype(game).contains(choice)) { + land.getSubtype(game).add(choice); } break; case AbilityAddingRemovingEffects_6: diff --git a/Mage.Sets/src/mage/sets/homelands/DrudgeSpell.java b/Mage.Sets/src/mage/sets/homelands/DrudgeSpell.java index 1600dac4b5..a26cfde7a2 100644 --- a/Mage.Sets/src/mage/sets/homelands/DrudgeSpell.java +++ b/Mage.Sets/src/mage/sets/homelands/DrudgeSpell.java @@ -94,7 +94,7 @@ class SkeletonToken extends Token { this.getPower().modifyBaseValue(1); this.getToughness().modifyBaseValue(1); this.color.setBlack(true); - this.getSubtype().add("Skeleton"); + this.getSubtype(null).add("Skeleton"); this.getCardType().add(CardType.CREATURE); this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl("{B}"))); diff --git a/Mage.Sets/src/mage/sets/iceage/NakedSingularity.java b/Mage.Sets/src/mage/sets/iceage/NakedSingularity.java index 1c086143d8..9ce0597bfc 100644 --- a/Mage.Sets/src/mage/sets/iceage/NakedSingularity.java +++ b/Mage.Sets/src/mage/sets/iceage/NakedSingularity.java @@ -103,19 +103,19 @@ class NakedSingularityEffect extends ReplacementEffectImpl { Permanent permanent = game.getPermanent(event.getSourceId()); Choice choice = new ChoiceImpl(true); choice.setMessage("Pick a color to produce"); - if (permanent.hasSubtype("Plains")) { + if (permanent.hasSubtype("Plains", game)) { choice.getChoices().add("Red"); } - if (permanent.hasSubtype("Island")) { + if (permanent.hasSubtype("Island", game)) { choice.getChoices().add("Green"); } - if (permanent.hasSubtype("Swamp")) { + if (permanent.hasSubtype("Swamp", game)) { choice.getChoices().add("White"); } - if (permanent.hasSubtype("Mountain")) { + if (permanent.hasSubtype("Mountain", game)) { choice.getChoices().add("Blue"); } - if (permanent.hasSubtype("Forest")) { + if (permanent.hasSubtype("Forest", game)) { choice.getChoices().add("Black"); } String chosenColor; @@ -159,10 +159,10 @@ class NakedSingularityEffect extends ReplacementEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { Permanent permanent = game.getPermanent(event.getSourceId()); return permanent != null - && (permanent.hasSubtype("Plains") - || permanent.hasSubtype("Island") - || permanent.hasSubtype("Swamp") - || permanent.hasSubtype("Mountain") - || permanent.hasSubtype("Forest")); + && (permanent.hasSubtype("Plains", game) + || permanent.hasSubtype("Island", game) + || permanent.hasSubtype("Swamp", game) + || permanent.hasSubtype("Mountain", game) + || permanent.hasSubtype("Forest", game)); } } diff --git a/Mage.Sets/src/mage/sets/innistrad/DearlyDeparted.java b/Mage.Sets/src/mage/sets/innistrad/DearlyDeparted.java index 1e67b099e0..a4439988c3 100644 --- a/Mage.Sets/src/mage/sets/innistrad/DearlyDeparted.java +++ b/Mage.Sets/src/mage/sets/innistrad/DearlyDeparted.java @@ -94,7 +94,7 @@ class DearlyDepartedEntersBattlefieldEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget(); - if (permanent != null && permanent.getControllerId().equals(source.getControllerId()) && permanent.hasSubtype("Human")) { + if (permanent != null && permanent.getControllerId().equals(source.getControllerId()) && permanent.hasSubtype("Human", game)) { return true; } return false; diff --git a/Mage.Sets/src/mage/sets/innistrad/ElderCathar.java b/Mage.Sets/src/mage/sets/innistrad/ElderCathar.java index 00f6d7b360..cb68160b04 100644 --- a/Mage.Sets/src/mage/sets/innistrad/ElderCathar.java +++ b/Mage.Sets/src/mage/sets/innistrad/ElderCathar.java @@ -96,7 +96,7 @@ class ElderCatharAddCountersTargetEffect extends OneShotEffect { Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source)); if (permanent != null) { if (counter != null) { - if (permanent.hasSubtype("Human")) { + if (permanent.hasSubtype("Human", game)) { permanent.addCounters(counter2.copy(), game); } else { permanent.addCounters(counter.copy(), game); diff --git a/Mage.Sets/src/mage/sets/innistrad/GrimoireOfTheDead.java b/Mage.Sets/src/mage/sets/innistrad/GrimoireOfTheDead.java index 32a9a853fe..566782c7ee 100644 --- a/Mage.Sets/src/mage/sets/innistrad/GrimoireOfTheDead.java +++ b/Mage.Sets/src/mage/sets/innistrad/GrimoireOfTheDead.java @@ -159,7 +159,7 @@ class GrimoireOfTheDeadEffect2 extends ContinuousEffectImpl { break; case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { - permanent.getSubtype().add("Zombie"); + permanent.getSubtype(game).add("Zombie"); } break; } diff --git a/Mage.Sets/src/mage/sets/innistrad/RakishHeir.java b/Mage.Sets/src/mage/sets/innistrad/RakishHeir.java index 5b243df62e..e29edc94c1 100644 --- a/Mage.Sets/src/mage/sets/innistrad/RakishHeir.java +++ b/Mage.Sets/src/mage/sets/innistrad/RakishHeir.java @@ -96,7 +96,7 @@ class RakishHeirTriggeredAbility extends TriggeredAbilityImpl { DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event; Permanent permanent = game.getPermanent(event.getSourceId()); if (damageEvent.isCombatDamage() && permanent != null - && permanent.hasSubtype("Vampire") && permanent.getControllerId().equals(controllerId)) { + && permanent.hasSubtype("Vampire", game) && permanent.getControllerId().equals(controllerId)) { this.getEffects().clear(); AddCountersTargetEffect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance()); effect.setTargetPointer(new FixedTarget(permanent.getId())); diff --git a/Mage.Sets/src/mage/sets/innistrad/RooftopStorm.java b/Mage.Sets/src/mage/sets/innistrad/RooftopStorm.java index 283ccafdad..db849adf88 100644 --- a/Mage.Sets/src/mage/sets/innistrad/RooftopStorm.java +++ b/Mage.Sets/src/mage/sets/innistrad/RooftopStorm.java @@ -95,7 +95,7 @@ class RooftopStormCostReductionEffect extends CostModificationEffectImpl { Ability spell = abilityToModify; if (spell.getControllerId().equals(source.getControllerId())) { Card sourceCard = game.getCard(spell.getSourceId()); - if (sourceCard != null && sourceCard.hasSubtype("Zombie")) { + if (sourceCard != null && sourceCard.hasSubtype("Zombie", game)) { Player player = game.getPlayer(spell.getControllerId()); if (player != null && (CardUtil.isCheckPlayableMode(spell) || player.chooseUse(Outcome.Benefit, "Pay {0} rather than pay the mana cost for Zombie creature", source, game))) { diff --git a/Mage.Sets/src/mage/sets/innistrad/UndeadAlchemist.java b/Mage.Sets/src/mage/sets/innistrad/UndeadAlchemist.java index 4bc0fd520e..e94afbc38e 100644 --- a/Mage.Sets/src/mage/sets/innistrad/UndeadAlchemist.java +++ b/Mage.Sets/src/mage/sets/innistrad/UndeadAlchemist.java @@ -152,7 +152,7 @@ class UndeadAlchemistEffect extends ReplacementEffectImpl { DamagePlayerEvent damageEvent = (DamagePlayerEvent) event; if (damageEvent.isCombatDamage()) { Permanent permanent = game.getPermanent(event.getSourceId()); - if (permanent != null && permanent.hasSubtype("Zombie")) { + if (permanent != null && permanent.hasSubtype("Zombie", game)) { return true; } } diff --git a/Mage.Sets/src/mage/sets/innistrad/VillageCannibals.java b/Mage.Sets/src/mage/sets/innistrad/VillageCannibals.java index 5bceae86f7..5391761e43 100644 --- a/Mage.Sets/src/mage/sets/innistrad/VillageCannibals.java +++ b/Mage.Sets/src/mage/sets/innistrad/VillageCannibals.java @@ -95,7 +95,7 @@ class VillageCannibalsTriggeredAbility extends TriggeredAbilityImpl { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() == Zone.GRAVEYARD) { Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); - if (permanent != null && permanent.getCardType().contains(CardType.CREATURE) && permanent.hasSubtype("Human") + if (permanent != null && permanent.getCardType().contains(CardType.CREATURE) && permanent.hasSubtype("Human", game) && !permanent.getId().equals(this.getSourceId())) { return true; } diff --git a/Mage.Sets/src/mage/sets/innistrad/WitchbaneOrb.java b/Mage.Sets/src/mage/sets/innistrad/WitchbaneOrb.java index bbfc2c0f8d..a051baa2d3 100644 --- a/Mage.Sets/src/mage/sets/innistrad/WitchbaneOrb.java +++ b/Mage.Sets/src/mage/sets/innistrad/WitchbaneOrb.java @@ -88,7 +88,7 @@ class WitchbaneOrbEffect extends OneShotEffect { if (player != null) { for (UUID attachmentId: player.getAttachments()) { Permanent attachment = game.getPermanent(attachmentId); - if (attachment != null && attachment.getSubtype().contains("Curse")) { + if (attachment != null && attachment.getSubtype(game).contains("Curse")) { attachment.destroy(source.getSourceId(), game, false); } } diff --git a/Mage.Sets/src/mage/sets/innistrad/WoodenStake.java b/Mage.Sets/src/mage/sets/innistrad/WoodenStake.java index 27f6025512..0addb69bb3 100644 --- a/Mage.Sets/src/mage/sets/innistrad/WoodenStake.java +++ b/Mage.Sets/src/mage/sets/innistrad/WoodenStake.java @@ -97,7 +97,7 @@ class WoodenStakeBlocksOrBecomesBlockedTriggeredAbility extends TriggeredAbility if (equipment != null && equipment.getAttachedTo() != null) { if (event.getSourceId().equals(equipment.getAttachedTo())) { Permanent blocks = game.getPermanent(event.getTargetId()); - if (blocks != null && blocks.hasSubtype("Vampire")) { + if (blocks != null && blocks.hasSubtype("Vampire", game)) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getTargetId())); } @@ -107,7 +107,7 @@ class WoodenStakeBlocksOrBecomesBlockedTriggeredAbility extends TriggeredAbility } if (event.getTargetId().equals(equipment.getAttachedTo())) { Permanent blockedBy = game.getPermanent(event.getSourceId()); - if (blockedBy != null && blockedBy.hasSubtype("Vampire")) { + if (blockedBy != null && blockedBy.hasSubtype("Vampire", game)) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getSourceId())); } diff --git a/Mage.Sets/src/mage/sets/invasion/KangeeAerieKeeper.java b/Mage.Sets/src/mage/sets/invasion/KangeeAerieKeeper.java index 7022870199..ccb6dda72f 100644 --- a/Mage.Sets/src/mage/sets/invasion/KangeeAerieKeeper.java +++ b/Mage.Sets/src/mage/sets/invasion/KangeeAerieKeeper.java @@ -36,7 +36,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.KickedCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostAllEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -88,7 +88,7 @@ public class KangeeAerieKeeper extends CardImpl { this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.getInstance(), "When {this} enters the battlefield, if it was kicked, put X feather counters on it.")); // Other Bird creatures get +1/+1 for each feather counter on Kangee, Aerie Keeper. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(new CountersCount(CounterType.FEATHER), new CountersCount(CounterType.FEATHER), Duration.WhileOnBattlefield, filter, true, "Other Bird creatures get +1/+1 for each feather counter on {this}."))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(new CountersSourceCount(CounterType.FEATHER), new CountersSourceCount(CounterType.FEATHER), Duration.WhileOnBattlefield, filter, true, "Other Bird creatures get +1/+1 for each feather counter on {this}."))); } public KangeeAerieKeeper(final KangeeAerieKeeper card) { diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/Deicide.java b/Mage.Sets/src/mage/sets/journeyintonyx/Deicide.java index 1789731045..983920adea 100644 --- a/Mage.Sets/src/mage/sets/journeyintonyx/Deicide.java +++ b/Mage.Sets/src/mage/sets/journeyintonyx/Deicide.java @@ -92,7 +92,7 @@ class DeicideExileEffect extends SearchTargetGraveyardHandLibraryForCardNameAndE // if it is a God. For each of the Gods in the Theros block, it won’t matter what your // devotion to its color(s) was. The card is a God card when not on the battlefield. Card cardInExile = game.getExile().getCard(targetEnchantment.getId(), game); - if (cardInExile != null && cardInExile.hasSubtype("God")) { + if (cardInExile != null && cardInExile.hasSubtype("God", game)) { Player enchantmentController = game.getPlayer(targetEnchantment.getControllerId()); return super.applySearchAndExile(game, source, cardInExile.getName(), enchantmentController.getId()); } diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/SilenceTheBelievers.java b/Mage.Sets/src/mage/sets/journeyintonyx/SilenceTheBelievers.java index f576b3dfcf..7cd3e09593 100644 --- a/Mage.Sets/src/mage/sets/journeyintonyx/SilenceTheBelievers.java +++ b/Mage.Sets/src/mage/sets/journeyintonyx/SilenceTheBelievers.java @@ -99,7 +99,7 @@ class SilenceTheBelieversExileEffect extends OneShotEffect { ArrayList attachments = new ArrayList<>(creature.getAttachments()); for (UUID attachmentId: attachments) { Permanent attachment = game.getPermanent(attachmentId); - if (attachment != null && attachment.getSubtype().contains("Aura")) { + if (attachment != null && attachment.getSubtype(game).contains("Aura")) { controller.moveCardToExileWithInfo(attachment, null, null, source.getSourceId(), game, Zone.BATTLEFIELD, true); } } diff --git a/Mage.Sets/src/mage/sets/judgment/NomadMythmaker.java b/Mage.Sets/src/mage/sets/judgment/NomadMythmaker.java index 1219e79422..1eb06dbd47 100644 --- a/Mage.Sets/src/mage/sets/judgment/NomadMythmaker.java +++ b/Mage.Sets/src/mage/sets/judgment/NomadMythmaker.java @@ -121,7 +121,7 @@ class NomadMythmakerEffect extends OneShotEffect { && controller.choose(Outcome.PutCardInPlay, target, source.getSourceId(), game)) { Permanent permanent = game.getPermanent(target.getFirstTarget()); if (permanent != null - && !permanent.cantBeEnchantedBy(aura, game)) { + && !permanent.cantBeAttachedBy(aura, game)) { game.getState().setValue("attachTo:" + aura.getId(), permanent); controller.moveCards(aura, Zone.BATTLEFIELD, source, game); return permanent.addAttachment(aura.getId(), game); diff --git a/Mage.Sets/src/mage/sets/judgment/SoulcatchersAerie.java b/Mage.Sets/src/mage/sets/judgment/SoulcatchersAerie.java index 6640eb8fc4..4c7e0f8b2c 100644 --- a/Mage.Sets/src/mage/sets/judgment/SoulcatchersAerie.java +++ b/Mage.Sets/src/mage/sets/judgment/SoulcatchersAerie.java @@ -30,7 +30,7 @@ package mage.sets.judgment; import java.util.UUID; import mage.abilities.common.PutIntoGraveFromBattlefieldAllTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.continuous.BoostAllEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -65,8 +65,8 @@ public class SoulcatchersAerie extends CardImpl { this.addAbility(new PutIntoGraveFromBattlefieldAllTriggeredAbility(new AddCountersSourceEffect(CounterType.FEATHER.createInstance()), false, filter, false, true)); // Bird creatures get +1/+1 for each feather counter on Soulcatchers' Aerie. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(new CountersCount(CounterType.FEATHER), - new CountersCount(CounterType.FEATHER), Duration.WhileOnBattlefield, filter2, false, + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(new CountersSourceCount(CounterType.FEATHER), + new CountersSourceCount(CounterType.FEATHER), Duration.WhileOnBattlefield, filter2, false, "Bird creatures get +1/+1 for each feather counter on {this}."))); } diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/HoodedHydra.java b/Mage.Sets/src/mage/sets/khansoftarkir/HoodedHydra.java index c44f476180..de1c3a19e4 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/HoodedHydra.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/HoodedHydra.java @@ -34,7 +34,7 @@ import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.AsTurnedFaceUpEffect; import mage.abilities.effects.Effect; import mage.abilities.effects.common.CreateTokenEffect; @@ -67,7 +67,7 @@ public class HoodedHydra extends CardImpl { this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.P1P1.createInstance()))); // When Hooded Hydra dies, put a 1/1 green Snake creature token onto the battlefield for each +1/+1 counter on it. - this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new SnakeToken("KTK"), new CountersCount(CounterType.P1P1)), false)); + this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new SnakeToken("KTK"), new CountersSourceCount(CounterType.P1P1)), false)); // Morph {3}{G}{G} this.addAbility(new MorphAbility(this, new ManaCostsImpl("{3}{G}{G}"))); diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/RaidersSpoils.java b/Mage.Sets/src/mage/sets/khansoftarkir/RaidersSpoils.java index 6ef96c8ac1..31e5ce888e 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/RaidersSpoils.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/RaidersSpoils.java @@ -96,7 +96,7 @@ class RaidersSpoilsTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event; Permanent permanent = game.getPermanent(event.getSourceId()); - if (damageEvent.isCombatDamage() && permanent != null && permanent.hasSubtype("Warrior") && permanent.getControllerId().equals(controllerId)) { + if (damageEvent.isCombatDamage() && permanent != null && permanent.hasSubtype("Warrior", game) && permanent.getControllerId().equals(controllerId)) { return true; } return false; diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/SarkhanTheDragonspeaker.java b/Mage.Sets/src/mage/sets/khansoftarkir/SarkhanTheDragonspeaker.java index 2b79450a3f..a34bf6882d 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/SarkhanTheDragonspeaker.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/SarkhanTheDragonspeaker.java @@ -126,8 +126,8 @@ class SarkhanTheDragonspeakerEffect extends ContinuousEffectImpl { if (sublayer == SubLayer.NA) { permanent.getCardType().clear(); permanent.getCardType().add(CardType.CREATURE); - permanent.getSubtype().clear(); - permanent.getSubtype().add("Dragon"); + permanent.getSubtype(game).clear(); + permanent.getSubtype(game).add("Dragon"); permanent.getSupertype().clear(); permanent.getSupertype().add("Legendary"); } diff --git a/Mage.Sets/src/mage/sets/knightsvsdragons/KilnmouthDragon.java b/Mage.Sets/src/mage/sets/knightsvsdragons/KilnmouthDragon.java index e5f54a40dd..417f8ff095 100644 --- a/Mage.Sets/src/mage/sets/knightsvsdragons/KilnmouthDragon.java +++ b/Mage.Sets/src/mage/sets/knightsvsdragons/KilnmouthDragon.java @@ -32,7 +32,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.AmplifyEffect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.keyword.AmplifyAbility; @@ -65,7 +65,7 @@ public class KilnmouthDragon extends CardImpl { // {tap}: Kilnmouth Dragon deals damage equal to the number of +1/+1 counters on it to target creature or player. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, - new DamageTargetEffect(new CountersCount(CounterType.P1P1)), new TapSourceCost()); + new DamageTargetEffect(new CountersSourceCount(CounterType.P1P1)), new TapSourceCost()); ability.addTarget(new TargetCreatureOrPlayer()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/legends/BartelRuneaxe.java b/Mage.Sets/src/mage/sets/legends/BartelRuneaxe.java index d4e3d3d89c..98bf1734c3 100644 --- a/Mage.Sets/src/mage/sets/legends/BartelRuneaxe.java +++ b/Mage.Sets/src/mage/sets/legends/BartelRuneaxe.java @@ -114,7 +114,7 @@ class BartelRuneaxeEffect extends ContinuousRuleModifyingEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { StackObject stackObject = (StackObject) game.getStack().getStackObject(event.getSourceId()); if (stackObject != null && event.getTargetId().equals(source.getSourceId())) { - if (stackObject.getSubtype().contains("Aura")) { + if (stackObject.getSubtype(game).contains("Aura")) { return true; } } diff --git a/Mage.Sets/src/mage/sets/legends/TetsuoUmezawa.java b/Mage.Sets/src/mage/sets/legends/TetsuoUmezawa.java index 1391bd8139..631d63b31c 100644 --- a/Mage.Sets/src/mage/sets/legends/TetsuoUmezawa.java +++ b/Mage.Sets/src/mage/sets/legends/TetsuoUmezawa.java @@ -135,7 +135,7 @@ class TetsuoUmezawaEffect extends ContinuousRuleModifyingEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { StackObject stackObject = (StackObject) game.getStack().getStackObject(event.getSourceId()); if (stackObject != null && event.getTargetId().equals(source.getSourceId())) { - if (stackObject.getSubtype().contains("Aura")) { + if (stackObject.getSubtype(game).contains("Aura")) { return true; } } diff --git a/Mage.Sets/src/mage/sets/legions/CanopyCrawler.java b/Mage.Sets/src/mage/sets/legions/CanopyCrawler.java index a4a7c2fc1d..2704321bfc 100644 --- a/Mage.Sets/src/mage/sets/legions/CanopyCrawler.java +++ b/Mage.Sets/src/mage/sets/legions/CanopyCrawler.java @@ -32,7 +32,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.AmplifyEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.keyword.AmplifyAbility; @@ -60,7 +60,7 @@ public class CanopyCrawler extends CardImpl { // Amplify 1 this.addAbility(new AmplifyAbility(AmplifyEffect.AmplifyFactor.Amplify1)); // {tap}: Target creature gets +1/+1 until end of turn for each +1/+1 counter on Canopy Crawler. - CountersCount count = new CountersCount(CounterType.P1P1); + CountersSourceCount count = new CountersSourceCount(CounterType.P1P1); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(count, count, Duration.EndOfTurn, true), new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/legions/DaruStinger.java b/Mage.Sets/src/mage/sets/legions/DaruStinger.java index 323dbc9732..8e02e0245c 100644 --- a/Mage.Sets/src/mage/sets/legions/DaruStinger.java +++ b/Mage.Sets/src/mage/sets/legions/DaruStinger.java @@ -32,7 +32,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.AmplifyEffect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.keyword.AmplifyAbility; @@ -59,7 +59,7 @@ public class DaruStinger extends CardImpl { // Amplify 1 this.addAbility(new AmplifyAbility(AmplifyEffect.AmplifyFactor.Amplify1)); // {tap}: Daru Stinger deals damage equal to the number of +1/+1 counters on it to target attacking or blocking creature. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new CountersCount(CounterType.P1P1)), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new CountersSourceCount(CounterType.P1P1)), new TapSourceCost()); ability.addTarget(new TargetAttackingOrBlockingCreature()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/legions/EmbalmedBrawler.java b/Mage.Sets/src/mage/sets/legions/EmbalmedBrawler.java index 4038cfe0b1..1088d65f20 100644 --- a/Mage.Sets/src/mage/sets/legions/EmbalmedBrawler.java +++ b/Mage.Sets/src/mage/sets/legions/EmbalmedBrawler.java @@ -30,7 +30,7 @@ package mage.sets.legions; import java.util.UUID; import mage.MageInt; import mage.abilities.common.AttacksOrBlocksTriggeredAbility; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.AmplifyEffect; import mage.abilities.effects.common.LoseLifeSourceControllerEffect; import mage.abilities.keyword.AmplifyAbility; @@ -55,7 +55,7 @@ public class EmbalmedBrawler extends CardImpl { // Amplify 1 this.addAbility(new AmplifyAbility(AmplifyEffect.AmplifyFactor.Amplify1)); // Whenever Embalmed Brawler attacks or blocks, you lose 1 life for each +1/+1 counter on it. - this.addAbility(new AttacksOrBlocksTriggeredAbility(new LoseLifeSourceControllerEffect(new CountersCount(CounterType.P1P1)), false)); + this.addAbility(new AttacksOrBlocksTriggeredAbility(new LoseLifeSourceControllerEffect(new CountersSourceCount(CounterType.P1P1)), false)); } public EmbalmedBrawler(final EmbalmedBrawler card) { diff --git a/Mage.Sets/src/mage/sets/legions/GoblinAssassin.java b/Mage.Sets/src/mage/sets/legions/GoblinAssassin.java index 35866b1d30..29667964e1 100644 --- a/Mage.Sets/src/mage/sets/legions/GoblinAssassin.java +++ b/Mage.Sets/src/mage/sets/legions/GoblinAssassin.java @@ -97,7 +97,7 @@ class GoblinAssassinTriggeredAbiliy extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { UUID targetId = event.getTargetId(); Permanent permanent = game.getPermanent(targetId); - if ((targetId.equals(this.getSourceId())) || (permanent.hasSubtype("Goblin") && !targetId.equals(this.getSourceId()))) { + if ((targetId.equals(this.getSourceId())) || (permanent.hasSubtype("Goblin", game) && !targetId.equals(this.getSourceId()))) { return true; } return false; diff --git a/Mage.Sets/src/mage/sets/legions/ToxinSliver.java b/Mage.Sets/src/mage/sets/legions/ToxinSliver.java index be0a4e660a..4641e0d1ba 100644 --- a/Mage.Sets/src/mage/sets/legions/ToxinSliver.java +++ b/Mage.Sets/src/mage/sets/legions/ToxinSliver.java @@ -97,7 +97,7 @@ class DealsDamageTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (game.getPermanent(event.getSourceId()).hasSubtype("Sliver")) { + if (game.getPermanent(event.getSourceId()).hasSubtype("Sliver", game)) { if (setTargetPointer) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(game.getControllerId(event.getTargetId()))); diff --git a/Mage.Sets/src/mage/sets/limitedalpha/Conversion.java b/Mage.Sets/src/mage/sets/limitedalpha/Conversion.java index ebd5524d65..38ad356aa2 100644 --- a/Mage.Sets/src/mage/sets/limitedalpha/Conversion.java +++ b/Mage.Sets/src/mage/sets/limitedalpha/Conversion.java @@ -112,8 +112,8 @@ public class Conversion extends CardImpl { land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); break; case TypeChangingEffects_4: - land.getSubtype().clear(); - land.getSubtype().add("Plains"); + land.getSubtype(game).clear(); + land.getSubtype(game).add("Plains"); break; } } diff --git a/Mage.Sets/src/mage/sets/limitedalpha/Invisibility.java b/Mage.Sets/src/mage/sets/limitedalpha/Invisibility.java index 7c2b83ec59..18d294fd41 100644 --- a/Mage.Sets/src/mage/sets/limitedalpha/Invisibility.java +++ b/Mage.Sets/src/mage/sets/limitedalpha/Invisibility.java @@ -101,7 +101,7 @@ class CantBeBlockedByWallsEffect extends RestrictionEffect { @Override public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game) { - if (!blocker.hasSubtype("Wall")) { + if (!blocker.hasSubtype("Wall", game)) { return false; } return true; diff --git a/Mage.Sets/src/mage/sets/limitedalpha/PhantasmalTerrain.java b/Mage.Sets/src/mage/sets/limitedalpha/PhantasmalTerrain.java index d7de486907..6397f9ec79 100644 --- a/Mage.Sets/src/mage/sets/limitedalpha/PhantasmalTerrain.java +++ b/Mage.Sets/src/mage/sets/limitedalpha/PhantasmalTerrain.java @@ -113,8 +113,8 @@ class PhantasmalTerrainContinuousEffect extends ContinuousEffectImpl { switch (layer) { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { - land.getSubtype().clear(); - land.getSubtype().add(choice); + land.getSubtype(game).clear(); + land.getSubtype(game).add(choice); } break; case AbilityAddingRemovingEffects_6: diff --git a/Mage.Sets/src/mage/sets/lorwyn/EgoErasure.java b/Mage.Sets/src/mage/sets/lorwyn/EgoErasure.java index 3eaebdac2a..838e36688d 100644 --- a/Mage.Sets/src/mage/sets/lorwyn/EgoErasure.java +++ b/Mage.Sets/src/mage/sets/lorwyn/EgoErasure.java @@ -110,7 +110,7 @@ class EgoErasureLoseEffect extends ContinuousEffectImpl { for (Iterator it = affectedObjectList.iterator(); it.hasNext();) { Permanent permanent = it.next().getPermanent(game); if (permanent != null) { - permanent.getSubtype().retainAll(CardRepository.instance.getLandTypes()); + permanent.getSubtype(game).retainAll(CardRepository.instance.getLandTypes()); } else { it.remove(); } diff --git a/Mage.Sets/src/mage/sets/lorwyn/MistbindClique.java b/Mage.Sets/src/mage/sets/lorwyn/MistbindClique.java index 33f9ef6803..e56b7b808c 100644 --- a/Mage.Sets/src/mage/sets/lorwyn/MistbindClique.java +++ b/Mage.Sets/src/mage/sets/lorwyn/MistbindClique.java @@ -108,7 +108,7 @@ class MistbindCliqueAbility extends ZoneChangeTriggeredAbility { && event.getSourceId().equals(getSourceId()) && !event.getSourceId().equals(event.getTargetId())) { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.getTarget() != null && zEvent.getTarget().hasSubtype("Faerie")) { + if (zEvent.getTarget() != null && zEvent.getTarget().hasSubtype("Faerie", game)) { return true; } } diff --git a/Mage.Sets/src/mage/sets/magic2010/CoatOfArms.java b/Mage.Sets/src/mage/sets/magic2010/CoatOfArms.java index 6641c9bb58..b88db65e9a 100644 --- a/Mage.Sets/src/mage/sets/magic2010/CoatOfArms.java +++ b/Mage.Sets/src/mage/sets/magic2010/CoatOfArms.java @@ -92,16 +92,16 @@ class CoatOfArmsEffect extends ContinuousEffectImpl { public boolean apply(Game game, Ability source) { List permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game); for (Permanent permanent : permanents) { - int amount = getAmount(permanents, permanent); + int amount = getAmount(permanents, permanent, game); permanent.addPower(amount); permanent.addToughness(amount); } return true; } - private int getAmount(List permanents, Permanent target) { + private int getAmount(List permanents, Permanent target, Game game) { int amount = 0; - List targetSubtype = target.getSubtype(); + List targetSubtype = target.getSubtype(game); if (target.getAbilities().contains(ChangelingAbility.getInstance())) { return permanents.size() - 1; } @@ -109,7 +109,7 @@ class CoatOfArmsEffect extends ContinuousEffectImpl { if (!permanent.getId().equals(target.getId())) { for (String subtype : targetSubtype) { if (!CardUtil.isNonCreatureSubtype(subtype)) { - if (permanent.hasSubtype(subtype)) { + if (permanent.hasSubtype(subtype, game)) { amount++; break; } diff --git a/Mage.Sets/src/mage/sets/magic2010/ConvincingMirage.java b/Mage.Sets/src/mage/sets/magic2010/ConvincingMirage.java index 97bf8288a2..57d7babaac 100644 --- a/Mage.Sets/src/mage/sets/magic2010/ConvincingMirage.java +++ b/Mage.Sets/src/mage/sets/magic2010/ConvincingMirage.java @@ -112,8 +112,8 @@ class ConvincingMirageContinousEffect extends ContinuousEffectImpl { switch (layer) { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { - land.getSubtype().clear(); - land.getSubtype().add(choice); + land.getSubtype(game).clear(); + land.getSubtype(game).add(choice); } break; case AbilityAddingRemovingEffects_6: diff --git a/Mage.Sets/src/mage/sets/magic2010/RiseFromTheGrave.java b/Mage.Sets/src/mage/sets/magic2010/RiseFromTheGrave.java index 7a6ca7f349..7406b70e14 100644 --- a/Mage.Sets/src/mage/sets/magic2010/RiseFromTheGrave.java +++ b/Mage.Sets/src/mage/sets/magic2010/RiseFromTheGrave.java @@ -93,7 +93,7 @@ class RiseFromTheGraveEffect extends ContinuousEffectImpl { switch (layer) { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { - creature.getSubtype().add("Zombie"); + creature.getSubtype(game).add("Zombie"); } break; case ColorChangingEffects_5: diff --git a/Mage.Sets/src/mage/sets/magic2011/CaptivatingVampire.java b/Mage.Sets/src/mage/sets/magic2011/CaptivatingVampire.java index c64555e37d..95fff54b8e 100644 --- a/Mage.Sets/src/mage/sets/magic2011/CaptivatingVampire.java +++ b/Mage.Sets/src/mage/sets/magic2011/CaptivatingVampire.java @@ -124,8 +124,8 @@ class CaptivatingVampireEffect extends ContinuousEffectImpl { break; case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { - if (!permanent.getSubtype().contains("Vampire")) { - permanent.getSubtype().add("Vampire"); + if (!permanent.getSubtype(game).contains("Vampire")) { + permanent.getSubtype(game).add("Vampire"); } } break; diff --git a/Mage.Sets/src/mage/sets/magic2011/StormtideLeviathan.java b/Mage.Sets/src/mage/sets/magic2011/StormtideLeviathan.java index b1b6d5c116..d15216983a 100644 --- a/Mage.Sets/src/mage/sets/magic2011/StormtideLeviathan.java +++ b/Mage.Sets/src/mage/sets/magic2011/StormtideLeviathan.java @@ -114,8 +114,8 @@ class StormtideLeviathanEffect extends ContinuousEffectImpl { for (Permanent land : game.getBattlefield().getActivePermanents(new FilterLandPermanent(), source.getControllerId(), game)) { switch (layer) { case TypeChangingEffects_4: - if (!land.getSubtype().contains("Island")) { - land.getSubtype().add("Island"); + if (!land.getSubtype(game).contains("Island")) { + land.getSubtype(game).add("Island"); } break; case AbilityAddingRemovingEffects_6: diff --git a/Mage.Sets/src/mage/sets/magic2012/AdaptiveAutomaton.java b/Mage.Sets/src/mage/sets/magic2012/AdaptiveAutomaton.java index 60b4ad65cd..48293fa30d 100644 --- a/Mage.Sets/src/mage/sets/magic2012/AdaptiveAutomaton.java +++ b/Mage.Sets/src/mage/sets/magic2012/AdaptiveAutomaton.java @@ -102,8 +102,8 @@ class AdaptiveAutomatonAddSubtypeEffect extends ContinuousEffectImpl { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { String subtype = (String) game.getState().getValue(permanent.getId() + "_type"); - if (subtype != null && !permanent.getSubtype().contains(subtype)) { - permanent.getSubtype().add(subtype); + if (subtype != null && !permanent.getSubtype(game).contains(subtype)) { + permanent.getSubtype(game).add(subtype); } } return true; diff --git a/Mage.Sets/src/mage/sets/magic2012/MindUnbound.java b/Mage.Sets/src/mage/sets/magic2012/MindUnbound.java index f56cb2941a..417e266af5 100644 --- a/Mage.Sets/src/mage/sets/magic2012/MindUnbound.java +++ b/Mage.Sets/src/mage/sets/magic2012/MindUnbound.java @@ -33,7 +33,7 @@ import mage.constants.CardType; import mage.constants.Rarity; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -53,7 +53,7 @@ public class MindUnbound extends CardImpl { // At the beginning of your upkeep, put a lore counter on Mind Unbound, then draw a card for each lore counter on Mind Unbound. Ability ability = new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.LORE.createInstance()), TargetController.YOU, false); - ability.addEffect(new DrawCardSourceControllerEffect(new CountersCount(CounterType.LORE))); + ability.addEffect(new DrawCardSourceControllerEffect(new CountersSourceCount(CounterType.LORE))); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/magic2012/PhantasmalImage.java b/Mage.Sets/src/mage/sets/magic2012/PhantasmalImage.java index 09011fd34c..f05106b8f6 100644 --- a/Mage.Sets/src/mage/sets/magic2012/PhantasmalImage.java +++ b/Mage.Sets/src/mage/sets/magic2012/PhantasmalImage.java @@ -54,8 +54,8 @@ public class PhantasmalImage extends CardImpl { ApplyToPermanent phantasmalImageApplier = new ApplyToPermanent() { @Override public Boolean apply(Game game, Permanent permanent) { - if (!permanent.getSubtype().contains("Illusion")) { - permanent.getSubtype().add("Illusion"); + if (!permanent.getSubtype(game).contains("Illusion")) { + permanent.getSubtype(game).add("Illusion"); } // Add directly because the created permanent is only used to copy from, so there is no need to add the ability to e.g. TriggeredAbilities permanent.getAbilities().add(new BecomesTargetTriggeredAbility(new SacrificeSourceEffect())); @@ -65,8 +65,8 @@ public class PhantasmalImage extends CardImpl { @Override public Boolean apply(Game game, MageObject mageObject) { - if (!mageObject.getSubtype().contains("Illusion")) { - mageObject.getSubtype().add("Illusion"); + if (!mageObject.getSubtype(game).contains("Illusion")) { + mageObject.getSubtype(game).add("Illusion"); } // Add directly because the created permanent is only used to copy from, so there is no need to add the ability to e.g. TriggeredAbilities mageObject.getAbilities().add(new BecomesTargetTriggeredAbility(new SacrificeSourceEffect())); diff --git a/Mage.Sets/src/mage/sets/magic2014/AjanisChosen.java b/Mage.Sets/src/mage/sets/magic2014/AjanisChosen.java index 762b3646b0..4363d0dc30 100644 --- a/Mage.Sets/src/mage/sets/magic2014/AjanisChosen.java +++ b/Mage.Sets/src/mage/sets/magic2014/AjanisChosen.java @@ -99,7 +99,7 @@ class AjanisChosenEffect extends OneShotEffect { Token token = new CatToken(); if (token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId())) { Permanent enchantment = game.getPermanent(this.getTargetPointer().getFirst(game, source)); - if (enchantment != null && enchantment.getSubtype().contains("Aura")) { + if (enchantment != null && enchantment.getSubtype(game).contains("Aura")) { for (UUID tokenId : token.getLastAddedTokenIds()) { Permanent tokenPermanent = game.getPermanent(tokenId); if (tokenPermanent != null) { diff --git a/Mage.Sets/src/mage/sets/magic2014/DismissIntoDream.java b/Mage.Sets/src/mage/sets/magic2014/DismissIntoDream.java index 407a60a232..2d09c50da5 100644 --- a/Mage.Sets/src/mage/sets/magic2014/DismissIntoDream.java +++ b/Mage.Sets/src/mage/sets/magic2014/DismissIntoDream.java @@ -107,8 +107,8 @@ class DismissIntoDreamEffect extends ContinuousEffectImpl { object.addAbility(new BecomesTargetTriggeredAbility(new SacrificeSourceEffect()), source.getSourceId(), game); break; case TypeChangingEffects_4: - if (!object.getSubtype().contains("Illusion")) { - object.getSubtype().add("Illusion"); + if (!object.getSubtype(game).contains("Illusion")) { + object.getSubtype(game).add("Illusion"); } break; } diff --git a/Mage.Sets/src/mage/sets/magic2014/DoorOfDestinies.java b/Mage.Sets/src/mage/sets/magic2014/DoorOfDestinies.java index 335d18e3d1..5a342a704b 100644 --- a/Mage.Sets/src/mage/sets/magic2014/DoorOfDestinies.java +++ b/Mage.Sets/src/mage/sets/magic2014/DoorOfDestinies.java @@ -153,7 +153,7 @@ class BoostCreatureEffectEffect extends ContinuousEffectImpl { String subtype = (String) game.getState().getValue(permanent.getId() + "_type"); if (subtype != null) { for (Permanent perm : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { - if (perm.hasSubtype(subtype)) { + if (perm.hasSubtype(subtype, game)) { int boost = permanent.getCounters().getCount(CounterType.CHARGE); perm.addPower(boost); perm.addToughness(boost); diff --git a/Mage.Sets/src/mage/sets/magic2014/VastwoodHydra.java b/Mage.Sets/src/mage/sets/magic2014/VastwoodHydra.java index 980669dc6f..993da9e720 100644 --- a/Mage.Sets/src/mage/sets/magic2014/VastwoodHydra.java +++ b/Mage.Sets/src/mage/sets/magic2014/VastwoodHydra.java @@ -32,7 +32,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect; import mage.cards.CardImpl; @@ -73,7 +73,7 @@ public class VastwoodHydra extends CardImpl { // When Vastwood Hydra dies, you may distribute a number of +1/+1 counters equal to the number of +1/+1 counters on Vastwood Hydra among any number of creatures you control. Ability ability = new DiesTriggeredAbility(new VastwoodHydraDistributeEffect(), true); - ability.addTarget(new TargetCreaturePermanentAmount(new CountersCount(CounterType.P1P1), filter)); + ability.addTarget(new TargetCreaturePermanentAmount(new CountersSourceCount(CounterType.P1P1), filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/magic2015/BlastfireBolt.java b/Mage.Sets/src/mage/sets/magic2015/BlastfireBolt.java index b6e8253013..b8c08cd48e 100644 --- a/Mage.Sets/src/mage/sets/magic2015/BlastfireBolt.java +++ b/Mage.Sets/src/mage/sets/magic2015/BlastfireBolt.java @@ -93,7 +93,7 @@ class DestroyAllAttachedEquipmentEffect extends OneShotEffect { ArrayList attachments = new ArrayList<>(target.getAttachments()); for (UUID attachmentId : attachments) { Permanent attachment = game.getPermanent(attachmentId); - if (attachment != null && attachment.getSubtype().contains("Equipment")) { + if (attachment != null && attachment.getSubtype(game).contains("Equipment")) { attachment.destroy(source.getSourceId(), game, false); } } diff --git a/Mage.Sets/src/mage/sets/magic2015/NecromancersStockpile.java b/Mage.Sets/src/mage/sets/magic2015/NecromancersStockpile.java index 575766661b..41f52d14c7 100644 --- a/Mage.Sets/src/mage/sets/magic2015/NecromancersStockpile.java +++ b/Mage.Sets/src/mage/sets/magic2015/NecromancersStockpile.java @@ -101,7 +101,7 @@ class NecromancersStockpileDiscardTargetCost extends CostImpl { if (card == null) { return false; } - isZombieCard = card.getSubtype().contains("Zombie"); + isZombieCard = card.getSubtype(game).contains("Zombie"); paid |= player.discard(card, null, game); } diff --git a/Mage.Sets/src/mage/sets/magic2015/ObeliskOfUrd.java b/Mage.Sets/src/mage/sets/magic2015/ObeliskOfUrd.java index 40eb7eb157..e8f7304b59 100644 --- a/Mage.Sets/src/mage/sets/magic2015/ObeliskOfUrd.java +++ b/Mage.Sets/src/mage/sets/magic2015/ObeliskOfUrd.java @@ -101,7 +101,7 @@ class ObeliskOfUrdBoostEffect extends ContinuousEffectImpl { String subtype = (String) game.getState().getValue(permanent.getId() + "_type"); if (subtype != null) { for (Permanent perm : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { - if (perm.hasSubtype(subtype)) { + if (perm.hasSubtype(subtype, game)) { perm.addPower(2); perm.addToughness(2); } diff --git a/Mage.Sets/src/mage/sets/magic2015/PolymorphistsJest.java b/Mage.Sets/src/mage/sets/magic2015/PolymorphistsJest.java index ac4a410861..142fbd5b8b 100644 --- a/Mage.Sets/src/mage/sets/magic2015/PolymorphistsJest.java +++ b/Mage.Sets/src/mage/sets/magic2015/PolymorphistsJest.java @@ -108,8 +108,8 @@ class PolymorphistsJestEffect extends ContinuousEffectImpl { switch (layer) { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { - permanent.getSubtype().clear(); - permanent.getSubtype().add("Frog"); + permanent.getSubtype(game).clear(); + permanent.getSubtype(game).add("Frog"); } break; diff --git a/Mage.Sets/src/mage/sets/magic2015/SliverHive.java b/Mage.Sets/src/mage/sets/magic2015/SliverHive.java index 1e3e3f9028..ef90a404ea 100644 --- a/Mage.Sets/src/mage/sets/magic2015/SliverHive.java +++ b/Mage.Sets/src/mage/sets/magic2015/SliverHive.java @@ -127,7 +127,7 @@ class SliverHiveManaCondition extends CreatureCastManaCondition { public boolean apply(Game game, Ability source, UUID manaProducer, Cost costToPay) { if (super.apply(game, source)) { MageObject object = game.getObject(source.getSourceId()); - if (object.hasSubtype("Sliver")) { + if (object.hasSubtype("Sliver", game)) { return true; } } diff --git a/Mage.Sets/src/mage/sets/magicorigins/GnarlrootTrapper.java b/Mage.Sets/src/mage/sets/magicorigins/GnarlrootTrapper.java index 70ba66c9f4..107210049b 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/GnarlrootTrapper.java +++ b/Mage.Sets/src/mage/sets/magicorigins/GnarlrootTrapper.java @@ -117,7 +117,7 @@ class GnarlrootTrapperManaCondition extends CreatureCastManaCondition { public boolean apply(Game game, Ability source) { if (super.apply(game, source)) { MageObject object = game.getObject(source.getSourceId()); - if (object.hasSubtype("Elf") + if (object.hasSubtype("Elf", game) && object.getCardType().contains(CardType.CREATURE)) { return true; } diff --git a/Mage.Sets/src/mage/sets/magicorigins/HangarbackWalker.java b/Mage.Sets/src/mage/sets/magicorigins/HangarbackWalker.java index 652cbf4a8c..b82c6a5788 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/HangarbackWalker.java +++ b/Mage.Sets/src/mage/sets/magicorigins/HangarbackWalker.java @@ -35,7 +35,7 @@ import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -63,7 +63,7 @@ public class HangarbackWalker extends CardImpl { this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.P1P1.createInstance()))); // When Hangarback Walker dies, put a 1/1 colorless Thopter artifact creature token with flying onto the battlefield for each +1/+1 counter on Hangarback Walker. - this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new ThopterColorlessToken(), new CountersCount(CounterType.P1P1)), false)); + this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new ThopterColorlessToken(), new CountersSourceCount(CounterType.P1P1)), false)); // {1}, {t}: Put a +1/+1 counter on Hangarback Walker. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()), new GenericManaCost(1)); diff --git a/Mage.Sets/src/mage/sets/magicorigins/MageRingNetwork.java b/Mage.Sets/src/mage/sets/magicorigins/MageRingNetwork.java index f901d201cd..0c9ebd06b8 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/MageRingNetwork.java +++ b/Mage.Sets/src/mage/sets/magicorigins/MageRingNetwork.java @@ -34,7 +34,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.RemoveVariableCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.mana.ColorlessManaAbility; @@ -69,7 +69,7 @@ public class MageRingNetwork extends CardImpl { new RemovedCountersForCostValue(), new TapSourceCost(), "Add {C} to your mana pool for each storage counter removed this way", - true, new CountersCount(CounterType.STORAGE)); + true, new CountersSourceCount(CounterType.STORAGE)); ability.addCost(new RemoveVariableCountersSourceCost(CounterType.STORAGE.createInstance(), "Remove X storage counters from {this}")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/magicorigins/NissaSageAnimist.java b/Mage.Sets/src/mage/sets/magicorigins/NissaSageAnimist.java index a0c75b4138..269229d548 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/NissaSageAnimist.java +++ b/Mage.Sets/src/mage/sets/magicorigins/NissaSageAnimist.java @@ -137,7 +137,7 @@ class NissaSageAnimistToken extends Token { this.getPower().modifyBaseValue(4); this.getToughness().modifyBaseValue(4); this.color.setGreen(true); - this.getSubtype().add("Elemental"); + this.getSubtype(null).add("Elemental"); this.getCardType().add(CardType.CREATURE); } } @@ -168,8 +168,8 @@ class NissaSageAnimistMinusSevenEffect extends ContinuousEffectImpl { if (!permanent.getCardType().contains(CardType.CREATURE)) { permanent.getCardType().add(CardType.CREATURE); } - if (!permanent.getSubtype().contains("Elemental")) { - permanent.getSubtype().add("Elemental"); + if (!permanent.getSubtype(game).contains("Elemental")) { + permanent.getSubtype(game).add("Elemental"); } break; case PTChangingEffects_7: diff --git a/Mage.Sets/src/mage/sets/masterseditionii/EbonPraetor.java b/Mage.Sets/src/mage/sets/masterseditionii/EbonPraetor.java index 04ed4d15c0..729729b1be 100644 --- a/Mage.Sets/src/mage/sets/masterseditionii/EbonPraetor.java +++ b/Mage.Sets/src/mage/sets/masterseditionii/EbonPraetor.java @@ -115,7 +115,7 @@ class EbonPraetorEffect extends OneShotEffect { if (cost instanceof SacrificeTargetCost) { Permanent sacrificedCreature = ((SacrificeTargetCost) cost).getPermanents().get(0); Permanent sourceCreature = game.getPermanent(source.getSourceId()); - if (sacrificedCreature.hasSubtype("Thrull") && sourceCreature != null) { + if (sacrificedCreature.hasSubtype("Thrull", game) && sourceCreature != null) { sourceCreature.addCounters(CounterType.P1P0.createInstance(), game); return true; } diff --git a/Mage.Sets/src/mage/sets/masterseditionii/SoulExchange.java b/Mage.Sets/src/mage/sets/masterseditionii/SoulExchange.java index 215fec4f80..b95517356a 100644 --- a/Mage.Sets/src/mage/sets/masterseditionii/SoulExchange.java +++ b/Mage.Sets/src/mage/sets/masterseditionii/SoulExchange.java @@ -102,7 +102,7 @@ class SoulExchangeEffect extends OneShotEffect{ if (c.isPaid() && c instanceof ExileTargetCost) { for (Permanent exiled : ((ExileTargetCost) c).getPermanents()) { if (exiled != null){ - if(exiled.getSubtype().contains("Thrull")){ + if(exiled.getSubtype(game).contains("Thrull")){ game.getPermanent(source.getFirstTarget()).addCounters(CounterType.P2P2.createInstance(), game); return true; } diff --git a/Mage.Sets/src/mage/sets/masterseditionii/TimeBomb.java b/Mage.Sets/src/mage/sets/masterseditionii/TimeBomb.java index 1777a4ad54..23c5a0267d 100644 --- a/Mage.Sets/src/mage/sets/masterseditionii/TimeBomb.java +++ b/Mage.Sets/src/mage/sets/masterseditionii/TimeBomb.java @@ -34,7 +34,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DamageEverythingEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -60,7 +60,7 @@ public class TimeBomb extends CardImpl { this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.TIME.createInstance(), true), TargetController.YOU, false)); // {1}, {tap}, Sacrifice Time Bomb: Time Bomb deals damage equal to the number of time counters on it to each creature and each player. - Effect effect = new DamageEverythingEffect(new CountersCount(CounterType.TIME), new FilterCreaturePermanent()); + Effect effect = new DamageEverythingEffect(new CountersSourceCount(CounterType.TIME), new FilterCreaturePermanent()); effect.setText("{this} deals damage equal to the number of time counters on it to each creature and each player"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new GenericManaCost(1)); ability.addCost(new TapSourceCost()); diff --git a/Mage.Sets/src/mage/sets/masterseditioniv/ArmageddonClock.java b/Mage.Sets/src/mage/sets/masterseditioniv/ArmageddonClock.java index 66aecc516c..4f19c3c08a 100644 --- a/Mage.Sets/src/mage/sets/masterseditioniv/ArmageddonClock.java +++ b/Mage.Sets/src/mage/sets/masterseditioniv/ArmageddonClock.java @@ -34,7 +34,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.decorator.ConditionalActivatedAbility; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.common.DamagePlayersEffect; import mage.cards.CardImpl; @@ -62,7 +62,7 @@ public class ArmageddonClock extends CardImpl { // At the beginning of your upkeep, put a doom counter on Armageddon Clock. this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.DOOM.createInstance(), new StaticValue(1), true, true), TargetController.YOU, false)); // At the beginning of your draw step, Armageddon Clock deals damage equal to the number of doom counters on it to each player. - this.addAbility(new BeginningOfDrawTriggeredAbility(new DamagePlayersEffect(Outcome.Damage, new CountersCount(CounterType.DOOM)), TargetController.YOU, false)); + this.addAbility(new BeginningOfDrawTriggeredAbility(new DamagePlayersEffect(Outcome.Damage, new CountersSourceCount(CounterType.DOOM)), TargetController.YOU, false)); // {4}: Remove a doom counter from Armageddon Clock. Any player may activate this ability but only during any upkeep step. ActivatedAbilityImpl ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new RemoveCounterSourceEffect(CounterType.DOOM.createInstance()), new ManaCostsImpl("{4}"), new IsStepCondition(PhaseStep.UPKEEP, false), null); diff --git a/Mage.Sets/src/mage/sets/masterseditioniv/SerendibDjinn.java b/Mage.Sets/src/mage/sets/masterseditioniv/SerendibDjinn.java index e3cf9ec727..a1c030851e 100644 --- a/Mage.Sets/src/mage/sets/masterseditioniv/SerendibDjinn.java +++ b/Mage.Sets/src/mage/sets/masterseditioniv/SerendibDjinn.java @@ -108,7 +108,7 @@ class SerendibDjinnEffect extends OneShotEffect { Permanent permanent = game.getPermanent(target.getFirstTarget()); if (permanent != null) { permanent.sacrifice(source.getSourceId(), game); - if (permanent.hasSubtype("Island")) { + if (permanent.hasSubtype("Island", game)) { controller.damage(3, source.getSourceId(), game, false, true); } } diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/Conspiracy.java b/Mage.Sets/src/mage/sets/mercadianmasques/Conspiracy.java new file mode 100644 index 0000000000..6e36dda613 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mercadianmasques/Conspiracy.java @@ -0,0 +1,54 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.mercadianmasques; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author anonymous + */ +public class Conspiracy extends mage.sets.timeshifted.Conspiracy { + + public Conspiracy(UUID ownerId) { + super(ownerId); + this.cardNumber = "127"; + this.expansionSetCode = "MMQ"; + this.rarity = Rarity.RARE; + } + + public Conspiracy(final Conspiracy card) { + super(card); + } + + @Override + public Conspiracy copy() { + return new Conspiracy(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/FountainOfCho.java b/Mage.Sets/src/mage/sets/mercadianmasques/FountainOfCho.java index 9af8db5aa5..7d03197daf 100644 --- a/Mage.Sets/src/mage/sets/mercadianmasques/FountainOfCho.java +++ b/Mage.Sets/src/mage/sets/mercadianmasques/FountainOfCho.java @@ -34,7 +34,7 @@ import mage.abilities.common.EntersBattlefieldTappedAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.RemoveVariableCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.mana.DynamicManaAbility; @@ -64,7 +64,7 @@ public class FountainOfCho extends CardImpl { new RemovedCountersForCostValue(), new TapSourceCost(), "Add {W} to your mana pool for each storage counter removed this way", - true, new CountersCount(CounterType.STORAGE)); + true, new CountersSourceCount(CounterType.STORAGE)); ability.addCost(new RemoveVariableCountersSourceCost(CounterType.STORAGE.createInstance(), "Remove any number of storage counters from {this}")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/MercadianBazaar.java b/Mage.Sets/src/mage/sets/mercadianmasques/MercadianBazaar.java index 78689e23c9..3e63c4a195 100644 --- a/Mage.Sets/src/mage/sets/mercadianmasques/MercadianBazaar.java +++ b/Mage.Sets/src/mage/sets/mercadianmasques/MercadianBazaar.java @@ -34,7 +34,7 @@ import mage.abilities.common.EntersBattlefieldTappedAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.RemoveVariableCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.mana.DynamicManaAbility; @@ -64,7 +64,7 @@ public class MercadianBazaar extends CardImpl { new RemovedCountersForCostValue(), new TapSourceCost(), "Add {R} to your mana pool for each storage counter removed this way", - true, new CountersCount(CounterType.STORAGE)); + true, new CountersSourceCount(CounterType.STORAGE)); ability.addCost(new RemoveVariableCountersSourceCost(CounterType.STORAGE.createInstance(), "Remove any number of storage counters from {this}")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/RushwoodGrove.java b/Mage.Sets/src/mage/sets/mercadianmasques/RushwoodGrove.java index 8465cb3378..5da740d525 100644 --- a/Mage.Sets/src/mage/sets/mercadianmasques/RushwoodGrove.java +++ b/Mage.Sets/src/mage/sets/mercadianmasques/RushwoodGrove.java @@ -34,7 +34,7 @@ import mage.abilities.common.EntersBattlefieldTappedAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.RemoveVariableCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.mana.DynamicManaAbility; @@ -64,7 +64,7 @@ public class RushwoodGrove extends CardImpl { new RemovedCountersForCostValue(), new TapSourceCost(), "Add {G} to your mana pool for each storage counter removed this way", - true, new CountersCount(CounterType.STORAGE)); + true, new CountersSourceCount(CounterType.STORAGE)); ability.addCost(new RemoveVariableCountersSourceCost(CounterType.STORAGE.createInstance(), "Remove any number of storage counters from {this}")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/SaprazzanCove.java b/Mage.Sets/src/mage/sets/mercadianmasques/SaprazzanCove.java index 97da1092ab..f2fc04b29a 100644 --- a/Mage.Sets/src/mage/sets/mercadianmasques/SaprazzanCove.java +++ b/Mage.Sets/src/mage/sets/mercadianmasques/SaprazzanCove.java @@ -34,7 +34,7 @@ import mage.abilities.common.EntersBattlefieldTappedAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.RemoveVariableCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.mana.DynamicManaAbility; @@ -64,7 +64,7 @@ public class SaprazzanCove extends CardImpl { new RemovedCountersForCostValue(), new TapSourceCost(), "Add {U} to your mana pool for each storage counter removed this way", - true, new CountersCount(CounterType.STORAGE)); + true, new CountersSourceCount(CounterType.STORAGE)); ability.addCost(new RemoveVariableCountersSourceCost(CounterType.STORAGE.createInstance(), "Remove any number of storage counters from {this}")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/SubterraneanHangar.java b/Mage.Sets/src/mage/sets/mercadianmasques/SubterraneanHangar.java index 3beaec2710..2668cc2746 100644 --- a/Mage.Sets/src/mage/sets/mercadianmasques/SubterraneanHangar.java +++ b/Mage.Sets/src/mage/sets/mercadianmasques/SubterraneanHangar.java @@ -34,7 +34,7 @@ import mage.abilities.common.EntersBattlefieldTappedAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.RemoveVariableCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.mana.DynamicManaAbility; @@ -64,7 +64,7 @@ public class SubterraneanHangar extends CardImpl { new RemovedCountersForCostValue(), new TapSourceCost(), "Add {B} to your mana pool for each storage counter removed this way", - true, new CountersCount(CounterType.STORAGE)); + true, new CountersSourceCount(CounterType.STORAGE)); ability.addCost(new RemoveVariableCountersSourceCost(CounterType.STORAGE.createInstance(), "Remove any number of storage counters from {this}")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/mirage/CloakOfInvisibility.java b/Mage.Sets/src/mage/sets/mirage/CloakOfInvisibility.java index 1e9f7b1c96..62851f72d7 100644 --- a/Mage.Sets/src/mage/sets/mirage/CloakOfInvisibility.java +++ b/Mage.Sets/src/mage/sets/mirage/CloakOfInvisibility.java @@ -105,7 +105,7 @@ class CantBeBlockedByWallsEffect extends RestrictionEffect { @Override public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game) { - if (!blocker.hasSubtype("Wall")) { + if (!blocker.hasSubtype("Wall", game)) { return false; } return true; diff --git a/Mage.Sets/src/mage/sets/mirrodin/BansheesBlade.java b/Mage.Sets/src/mage/sets/mirrodin/BansheesBlade.java index 284ef1c979..59b46dce8f 100644 --- a/Mage.Sets/src/mage/sets/mirrodin/BansheesBlade.java +++ b/Mage.Sets/src/mage/sets/mirrodin/BansheesBlade.java @@ -31,7 +31,7 @@ import java.util.UUID; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.EquipAbility; @@ -59,7 +59,7 @@ public class BansheesBlade extends CardImpl { this.subtype.add("Equipment"); // Equipped creature gets +1/+1 for each charge counter on Banshee's Blade. - CountersCount chargeCountersCount = new CountersCount(CounterType.CHARGE); + CountersSourceCount chargeCountersCount = new CountersSourceCount(CounterType.CHARGE); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(chargeCountersCount, chargeCountersCount))); // Whenever equipped creature deals combat damage, put a charge counter on Banshee's Blade. this.addAbility(new BansheesBladeAbility()); diff --git a/Mage.Sets/src/mage/sets/mirrodin/Duplicant.java b/Mage.Sets/src/mage/sets/mirrodin/Duplicant.java index 26d33de22e..6f3def7a34 100644 --- a/Mage.Sets/src/mage/sets/mirrodin/Duplicant.java +++ b/Mage.Sets/src/mage/sets/mirrodin/Duplicant.java @@ -151,7 +151,7 @@ class DuplicantContinuousEffect extends ContinuousEffectImpl { switch (layer) { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { - permanent.getSubtype().addAll(card.getSubtype()); + permanent.getSubtype(game).addAll(card.getSubtype(game)); } break; diff --git a/Mage.Sets/src/mage/sets/mirrodin/GoblinCharbelcher.java b/Mage.Sets/src/mage/sets/mirrodin/GoblinCharbelcher.java index 6729cd5d16..42cde37c64 100644 --- a/Mage.Sets/src/mage/sets/mirrodin/GoblinCharbelcher.java +++ b/Mage.Sets/src/mage/sets/mirrodin/GoblinCharbelcher.java @@ -106,7 +106,7 @@ class GoblinCharbelcherEffect extends OneShotEffect { cards.add(card); if (card.getCardType().contains(CardType.LAND)){ landFound = true; - if(card.getSubtype().contains("Mountain")){ + if(card.getSubtype(game).contains("Mountain")){ isMountain = true; } break; diff --git a/Mage.Sets/src/mage/sets/mirrodin/GolemSkinGauntlets.java b/Mage.Sets/src/mage/sets/mirrodin/GolemSkinGauntlets.java index d9109c627f..0ab5bcc40b 100644 --- a/Mage.Sets/src/mage/sets/mirrodin/GolemSkinGauntlets.java +++ b/Mage.Sets/src/mage/sets/mirrodin/GolemSkinGauntlets.java @@ -88,7 +88,7 @@ class GolemSkinGauntletsAttachedCount implements DynamicValue { List attachments = permanent.getAttachments(); for (UUID attachmentId : attachments) { Permanent attached = game.getPermanent(attachmentId); - if (attached != null && attached.getSubtype().contains("Equipment")) { + if (attached != null && attached.getSubtype(game).contains("Equipment")) { count++; } } diff --git a/Mage.Sets/src/mage/sets/mirrodinbesieged/KembasLegion.java b/Mage.Sets/src/mage/sets/mirrodinbesieged/KembasLegion.java index 8d497edf85..74825c9ebb 100644 --- a/Mage.Sets/src/mage/sets/mirrodinbesieged/KembasLegion.java +++ b/Mage.Sets/src/mage/sets/mirrodinbesieged/KembasLegion.java @@ -102,7 +102,7 @@ class KembasLegionEffect extends ContinuousEffectImpl { int count = 0; for (UUID attachmentId : attachments) { Permanent attachment = game.getPermanent(attachmentId); - if (attachment != null && attachment.hasSubtype("Equipment")) { + if (attachment != null && attachment.hasSubtype("Equipment", game)) { count++; } } diff --git a/Mage.Sets/src/mage/sets/mirrodinbesieged/TrainingDrone.java b/Mage.Sets/src/mage/sets/mirrodinbesieged/TrainingDrone.java index 1c386f9dd4..74309d6619 100644 --- a/Mage.Sets/src/mage/sets/mirrodinbesieged/TrainingDrone.java +++ b/Mage.Sets/src/mage/sets/mirrodinbesieged/TrainingDrone.java @@ -86,7 +86,7 @@ class TrainingDroneEffect extends RestrictionEffect { List attachments = permanent.getAttachments(); for (UUID uuid : attachments) { Permanent attached = game.getBattlefield().getPermanent(uuid); - if (attached.getSubtype().contains("Equipment")) { + if (attached.getSubtype(game).contains("Equipment")) { return false; } } diff --git a/Mage.Sets/src/mage/sets/modernmasters/WarrenPilferers.java b/Mage.Sets/src/mage/sets/modernmasters/WarrenPilferers.java index a6b93a5abf..f50ec5b53d 100644 --- a/Mage.Sets/src/mage/sets/modernmasters/WarrenPilferers.java +++ b/Mage.Sets/src/mage/sets/modernmasters/WarrenPilferers.java @@ -97,7 +97,7 @@ class WarrenPilferersReturnEffect extends OneShotEffect { Card card = game.getCard(source.getFirstTarget()); if (card != null) { card.moveToZone(Zone.HAND, source.getSourceId(), game, false); - if (card.getSubtype().contains("Goblin")) { + if (card.getSubtype(game).contains("Goblin")) { game.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.EndOfTurn), source); } return true; diff --git a/Mage.Sets/src/mage/sets/morningtide/BoldwyrIntimidator.java b/Mage.Sets/src/mage/sets/morningtide/BoldwyrIntimidator.java index e7a229c1b2..d67b6d66cf 100644 --- a/Mage.Sets/src/mage/sets/morningtide/BoldwyrIntimidator.java +++ b/Mage.Sets/src/mage/sets/morningtide/BoldwyrIntimidator.java @@ -113,8 +113,8 @@ class BoldwyrIntimidatorEffect extends RestrictionEffect { public boolean canBlock(Permanent attacker, Permanent blocker, Ability source, Game game) { if (attacker != null && blocker != null) { Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (sourcePermanent != null && attacker.getSubtype().contains("Warrior")) { - return !blocker.getSubtype().contains("Coward"); + if (sourcePermanent != null && attacker.getSubtype(game).contains("Warrior")) { + return !blocker.getSubtype(game).contains("Coward"); } } return true; diff --git a/Mage.Sets/src/mage/sets/morningtide/BramblewoodParagon.java b/Mage.Sets/src/mage/sets/morningtide/BramblewoodParagon.java index 14d5283152..3b338deb77 100644 --- a/Mage.Sets/src/mage/sets/morningtide/BramblewoodParagon.java +++ b/Mage.Sets/src/mage/sets/morningtide/BramblewoodParagon.java @@ -112,7 +112,7 @@ class BramblewoodParagonReplacementEffect extends ReplacementEffectImpl { Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget(); return creature != null && creature.getControllerId().equals(source.getControllerId()) && creature.getCardType().contains(CardType.CREATURE) - && creature.hasSubtype("Warrior") + && creature.hasSubtype("Warrior", game) && !event.getTargetId().equals(source.getSourceId()); } diff --git a/Mage.Sets/src/mage/sets/morningtide/GreatbowDoyen.java b/Mage.Sets/src/mage/sets/morningtide/GreatbowDoyen.java index 42398310d1..145d525c60 100644 --- a/Mage.Sets/src/mage/sets/morningtide/GreatbowDoyen.java +++ b/Mage.Sets/src/mage/sets/morningtide/GreatbowDoyen.java @@ -115,7 +115,7 @@ class GreatbowDoyenTriggeredAbility extends TriggeredAbilityImpl { Permanent damagedCreature = game.getPermanent(event.getTargetId()); if (creature != null && damagedCreature != null && creature.getCardType().contains(CardType.CREATURE) - && creature.hasSubtype("Archer") + && creature.hasSubtype("Archer", game) && creature.getControllerId().equals(controllerId)) { this.getEffects().get(0).setValue("damageAmount", event.getAmount()); this.getEffects().get(0).setValue("controller", damagedCreature.getControllerId()); diff --git a/Mage.Sets/src/mage/sets/morningtide/OonasBlackguard.java b/Mage.Sets/src/mage/sets/morningtide/OonasBlackguard.java index e652196c9d..085cd722d3 100644 --- a/Mage.Sets/src/mage/sets/morningtide/OonasBlackguard.java +++ b/Mage.Sets/src/mage/sets/morningtide/OonasBlackguard.java @@ -106,7 +106,7 @@ class OonasBlackguardReplacementEffect extends ReplacementEffectImpl { Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget(); if (creature != null && creature.getControllerId().equals(source.getControllerId()) && creature.getCardType().contains(CardType.CREATURE) - && creature.hasSubtype("Rogue") + && creature.hasSubtype("Rogue", game) && !event.getTargetId().equals(source.getSourceId())) { return true; } diff --git a/Mage.Sets/src/mage/sets/morningtide/PrimalBeyond.java b/Mage.Sets/src/mage/sets/morningtide/PrimalBeyond.java index 77b9ec0548..858408fea6 100644 --- a/Mage.Sets/src/mage/sets/morningtide/PrimalBeyond.java +++ b/Mage.Sets/src/mage/sets/morningtide/PrimalBeyond.java @@ -110,6 +110,6 @@ class PrimalBeyondManaCondition implements Condition { @Override public boolean apply(Game game, Ability source) { MageObject object = game.getObject(source.getSourceId()); - return object != null && object.hasSubtype("Elemental"); + return object != null && object.hasSubtype("Elemental", game); } } diff --git a/Mage.Sets/src/mage/sets/morningtide/ReinsOfTheVinesteed.java b/Mage.Sets/src/mage/sets/morningtide/ReinsOfTheVinesteed.java index 91540d9e81..447367dfcc 100644 --- a/Mage.Sets/src/mage/sets/morningtide/ReinsOfTheVinesteed.java +++ b/Mage.Sets/src/mage/sets/morningtide/ReinsOfTheVinesteed.java @@ -115,7 +115,7 @@ class ReinsOfTheVinesteedEffect extends OneShotEffect { FilterCreaturePermanent FILTER = new FilterCreaturePermanent(); StringBuilder sb = new StringBuilder("creature that shares a creature type with the formerly attached creature: "); ArrayList> subtypes = new ArrayList<>(); - for (String subtype : lastStateCreature.getSubtype()) { + for (String subtype : lastStateCreature.getSubtype(game)) { subtypes.add(new SubtypePredicate(subtype)); sb.append(subtype).append(", "); } @@ -127,7 +127,7 @@ class ReinsOfTheVinesteedEffect extends OneShotEffect { if (controller != null && controller.choose(Outcome.PutCardInPlay, target, source.getSourceId(), game)) { Permanent targetPermanent = game.getPermanent(target.getFirstTarget()); - if (!targetPermanent.cantBeEnchantedBy(aura, game)) { + if (!targetPermanent.cantBeAttachedBy(aura, game)) { game.getState().setValue("attachTo:" + aura.getId(), targetPermanent); aura.putOntoBattlefield(game, Zone.GRAVEYARD, source.getSourceId(), controller.getId()); return targetPermanent.addAttachment(aura.getId(), game); diff --git a/Mage.Sets/src/mage/sets/morningtide/SageOfFables.java b/Mage.Sets/src/mage/sets/morningtide/SageOfFables.java index ee007b91f5..e3f57e7d0d 100644 --- a/Mage.Sets/src/mage/sets/morningtide/SageOfFables.java +++ b/Mage.Sets/src/mage/sets/morningtide/SageOfFables.java @@ -103,7 +103,7 @@ class SageOfFablesReplacementEffect extends ReplacementEffectImpl { Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget(); return creature != null && creature.getControllerId().equals(source.getControllerId()) && creature.getCardType().contains(CardType.CREATURE) - && creature.getSubtype().contains("Wizard") + && creature.getSubtype(game).contains("Wizard") && !event.getTargetId().equals(source.getSourceId()); } diff --git a/Mage.Sets/src/mage/sets/morningtide/SharedAnimosity.java b/Mage.Sets/src/mage/sets/morningtide/SharedAnimosity.java index ac628391e2..8c68b316cd 100644 --- a/Mage.Sets/src/mage/sets/morningtide/SharedAnimosity.java +++ b/Mage.Sets/src/mage/sets/morningtide/SharedAnimosity.java @@ -105,7 +105,7 @@ class SharedAnimosityEffect extends ContinuousEffectImpl { filter.add(Predicates.not(new PermanentIdPredicate(this.targetPointer.getFirst(game, source)))); filter.add(new AttackingPredicate()); boolean allCreatureTypes = false; - if (permanent.getSubtype().contains(ChangelingAbility.ALL_CREATURE_TYPE)) { + if (permanent.getSubtype(game).contains(ChangelingAbility.ALL_CREATURE_TYPE)) { allCreatureTypes = true; } else { for(Ability ability : permanent.getAbilities()){ @@ -116,7 +116,7 @@ class SharedAnimosityEffect extends ContinuousEffectImpl { } if(!allCreatureTypes){ ArrayList> predicateList = new ArrayList<>(); - for(String subtype : permanent.getSubtype()){ + for(String subtype : permanent.getSubtype(game)){ predicateList.add(new SubtypePredicate(subtype)); } filter.add(Predicates.or(predicateList)); diff --git a/Mage.Sets/src/mage/sets/morningtide/WeightOfConscience.java b/Mage.Sets/src/mage/sets/morningtide/WeightOfConscience.java index 674c38b324..b39f2163db 100644 --- a/Mage.Sets/src/mage/sets/morningtide/WeightOfConscience.java +++ b/Mage.Sets/src/mage/sets/morningtide/WeightOfConscience.java @@ -143,7 +143,7 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent { // Choosing first target if (this.getTargets().isEmpty()) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) { - for (String subtype : permanent.getSubtype()) { + for (String subtype : permanent.getSubtype(game)) { if (!CardUtil.isNonCreatureSubtype(subtype)) { if (game.getBattlefield().contains(new FilterControlledCreaturePermanent(subtype, subtype), sourceControllerId, game, 2)) { possibleTargets.add(permanent.getId()); @@ -158,7 +158,7 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent { Permanent firstTargetCreature = game.getPermanent(firstTargetId); if (firstTargetCreature != null) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) { - if (!permanent.getId().equals(firstTargetId) && CardUtil.shareSubtypes(firstTargetCreature, permanent)) { + if (!permanent.getId().equals(firstTargetId) && CardUtil.shareSubtypes(firstTargetCreature, permanent, game)) { possibleTargets.add(permanent.getId()); } } @@ -172,7 +172,7 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent { public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { for (Permanent permanent1 : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) { for (Permanent permanent2 : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) { - if (permanent1 != permanent2 && CardUtil.shareSubtypes(permanent1, permanent2)) { + if (permanent1 != permanent2 && CardUtil.shareSubtypes(permanent1, permanent2, game)) { return true; } } @@ -187,7 +187,7 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent { if (targetPermanent != null) { if (this.getTargets().isEmpty()) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, source.getControllerId(), game)) { - for (String subtype : permanent.getSubtype()) { + for (String subtype : permanent.getSubtype(game)) { if (!CardUtil.isNonCreatureSubtype(subtype)) { if (game.getBattlefield().contains(new FilterControlledCreaturePermanent(subtype, subtype), source.getControllerId(), game, 2)) { return true; @@ -198,7 +198,7 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent { } else { Permanent firstTarget = game.getPermanent(this.getTargets().get(0)); - if (firstTarget != null && CardUtil.shareSubtypes(firstTarget, targetPermanent)) { + if (firstTarget != null && CardUtil.shareSubtypes(firstTarget, targetPermanent, game)) { return true; } } diff --git a/Mage.Sets/src/mage/sets/nemesis/RustingGolem.java b/Mage.Sets/src/mage/sets/nemesis/RustingGolem.java index e2dfb525d6..46ff1d7269 100644 --- a/Mage.Sets/src/mage/sets/nemesis/RustingGolem.java +++ b/Mage.Sets/src/mage/sets/nemesis/RustingGolem.java @@ -30,7 +30,7 @@ package mage.sets.nemesis; import java.util.UUID; import mage.MageInt; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect; import mage.abilities.keyword.FadingAbility; import mage.cards.CardImpl; @@ -57,7 +57,7 @@ public class RustingGolem extends CardImpl { this.addAbility(new FadingAbility(5, this)); // Rusting Golem's power and toughness are each equal to the number of fade counters on it. this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect( - new CountersCount(CounterType.FADE), Duration.EndOfGame))); + new CountersSourceCount(CounterType.FADE), Duration.EndOfGame))); } public RustingGolem(final RustingGolem card) { diff --git a/Mage.Sets/src/mage/sets/newphyrexia/BludgeonBrawl.java b/Mage.Sets/src/mage/sets/newphyrexia/BludgeonBrawl.java index 96d15473a7..6c03057173 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/BludgeonBrawl.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/BludgeonBrawl.java @@ -119,7 +119,7 @@ class BludgeonBrawlAddSubtypeEffect extends ContinuousEffectImpl { List permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game); for (Permanent permanent : permanents) { if (permanent != null) { - permanent.getSubtype().add("Equipment"); + permanent.getSubtype(game).add("Equipment"); affectedPermanents.add(permanent.getId()); } } diff --git a/Mage.Sets/src/mage/sets/newphyrexia/KarnLiberated.java b/Mage.Sets/src/mage/sets/newphyrexia/KarnLiberated.java index 70e5258ad9..45c585dae9 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/KarnLiberated.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/KarnLiberated.java @@ -121,7 +121,7 @@ class KarnLiberatedEffect extends OneShotEffect { for (ExileZone zone : game.getExile().getExileZones()) { if (zone.getId().equals(exileId)) { for (Card card : zone.getCards(game)) { - if (!card.getSubtype().contains("Aura") && CardUtil.isPermanentCard(card)) { + if (!card.getSubtype(game).contains("Aura") && CardUtil.isPermanentCard(card)) { cards.add(card); } } @@ -150,7 +150,7 @@ class KarnLiberatedEffect extends OneShotEffect { } for (Card card : cards) { game.getState().setZone(card.getId(), Zone.EXILED); - if (CardUtil.isPermanentCard(card) && !card.getSubtype().contains("Aura")) { + if (CardUtil.isPermanentCard(card) && !card.getSubtype(game).contains("Aura")) { game.getExile().add(exileId, sourceObject.getIdName(), card); } } diff --git a/Mage.Sets/src/mage/sets/newphyrexia/ShrineOfBoundlessGrowth.java b/Mage.Sets/src/mage/sets/newphyrexia/ShrineOfBoundlessGrowth.java index a8a5d7cb79..6bef468ea1 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/ShrineOfBoundlessGrowth.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/ShrineOfBoundlessGrowth.java @@ -39,7 +39,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.mana.DynamicManaAbility; import mage.cards.CardImpl; @@ -68,7 +68,7 @@ public class ShrineOfBoundlessGrowth extends CardImpl { this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), filter, false)); // {T}, Sacrifice Shrine of Boundless Growth: Add {C} to your mana pool for each charge counter on Shrine of Boundless Growth. - Ability ability = new DynamicManaAbility(Mana.ColorlessMana(1), new CountersCount(CounterType.CHARGE), new TapSourceCost()); + Ability ability = new DynamicManaAbility(Mana.ColorlessMana(1), new CountersSourceCount(CounterType.CHARGE), new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/newphyrexia/ShrineOfBurningRage.java b/Mage.Sets/src/mage/sets/newphyrexia/ShrineOfBurningRage.java index f56bf199a9..acebc38c4e 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/ShrineOfBurningRage.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/ShrineOfBurningRage.java @@ -40,7 +40,7 @@ import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -67,7 +67,7 @@ public class ShrineOfBurningRage extends CardImpl { this.expansionSetCode = "NPH"; this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), TargetController.YOU, false)); this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), filter, false)); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new CountersCount(CounterType.CHARGE)), new GenericManaCost(3)); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new CountersSourceCount(CounterType.CHARGE)), new GenericManaCost(3)); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); ability.addTarget(new TargetCreatureOrPlayer()); diff --git a/Mage.Sets/src/mage/sets/newphyrexia/ShrineOfLimitlessPower.java b/Mage.Sets/src/mage/sets/newphyrexia/ShrineOfLimitlessPower.java index 5406c7c93d..919cd5fae1 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/ShrineOfLimitlessPower.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/ShrineOfLimitlessPower.java @@ -40,7 +40,7 @@ import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -68,7 +68,7 @@ public class ShrineOfLimitlessPower extends CardImpl { this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), TargetController.YOU, false)); this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), filter, false)); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DiscardTargetEffect(new CountersCount(CounterType.CHARGE)), new GenericManaCost(4)); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DiscardTargetEffect(new CountersSourceCount(CounterType.CHARGE)), new GenericManaCost(4)); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); ability.addTarget(new TargetPlayer()); diff --git a/Mage.Sets/src/mage/sets/newphyrexia/ShrineOfLoyalLegions.java b/Mage.Sets/src/mage/sets/newphyrexia/ShrineOfLoyalLegions.java index a4f732fa0a..11b2d39e5f 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/ShrineOfLoyalLegions.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/ShrineOfLoyalLegions.java @@ -40,7 +40,7 @@ import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -69,7 +69,7 @@ public class ShrineOfLoyalLegions extends CardImpl { this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), filter, false)); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, - new CreateTokenEffect(new MyrToken("NPH"), new CountersCount(CounterType.CHARGE)), + new CreateTokenEffect(new MyrToken("NPH"), new CountersSourceCount(CounterType.CHARGE)), new GenericManaCost(3)); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); diff --git a/Mage.Sets/src/mage/sets/newphyrexia/Xenograft.java b/Mage.Sets/src/mage/sets/newphyrexia/Xenograft.java index 2d33de50f5..110c56dd4d 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/Xenograft.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/Xenograft.java @@ -89,8 +89,8 @@ class XenograftAddSubtypeEffect extends ContinuousEffectImpl { if (subtype != null) { List permanents = game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), game); for (Permanent permanent : permanents) { - if (permanent != null && !permanent.getSubtype().contains(subtype)) { - permanent.getSubtype().add(subtype); + if (permanent != null && !permanent.getSubtype(game).contains(subtype)) { + permanent.getSubtype(game).add(subtype); } } return true; diff --git a/Mage.Sets/src/mage/sets/ninthedition/BloodMoon.java b/Mage.Sets/src/mage/sets/ninthedition/BloodMoon.java index 6fbd5ff4f7..60f5a0fad5 100644 --- a/Mage.Sets/src/mage/sets/ninthedition/BloodMoon.java +++ b/Mage.Sets/src/mage/sets/ninthedition/BloodMoon.java @@ -106,8 +106,8 @@ class BloodMoonEffect extends ContinuousEffectImpl { // 305.7 Note that this doesn't remove any abilities that were granted to the land by other effects // So the ability removing has to be done before Layer 6 land.removeAllAbilities(source.getSourceId(), game); - land.getSubtype().removeAll(CardRepository.instance.getLandTypes()); - land.getSubtype().add("Mountain"); + land.getSubtype(game).removeAll(CardRepository.instance.getLandTypes()); + land.getSubtype(game).add("Mountain"); break; case AbilityAddingRemovingEffects_6: land.addAbility(new RedManaAbility(), source.getSourceId(), game); diff --git a/Mage.Sets/src/mage/sets/oathofthegatewatch/DeceiverOfForm.java b/Mage.Sets/src/mage/sets/oathofthegatewatch/DeceiverOfForm.java index 6b1019e768..320d242267 100644 --- a/Mage.Sets/src/mage/sets/oathofthegatewatch/DeceiverOfForm.java +++ b/Mage.Sets/src/mage/sets/oathofthegatewatch/DeceiverOfForm.java @@ -168,10 +168,10 @@ class DeceiverOfFormCopyEffect extends ContinuousEffectImpl { permanent.getCardType().add(type); } } - permanent.getSubtype().clear(); - for (String type : card.getSubtype()) { - if (!permanent.getSubtype().contains(type)) { - permanent.getSubtype().add(type); + permanent.getSubtype(game).clear(); + for (String type : card.getSubtype(game)) { + if (!permanent.getSubtype(game).contains(type)) { + permanent.getSubtype(game).add(type); } } permanent.getSupertype().clear(); diff --git a/Mage.Sets/src/mage/sets/oathofthegatewatch/StoneforgeMasterwork.java b/Mage.Sets/src/mage/sets/oathofthegatewatch/StoneforgeMasterwork.java index 85203c9392..fe01e28ea7 100644 --- a/Mage.Sets/src/mage/sets/oathofthegatewatch/StoneforgeMasterwork.java +++ b/Mage.Sets/src/mage/sets/oathofthegatewatch/StoneforgeMasterwork.java @@ -86,7 +86,7 @@ class StoneforgeMasterworkDynamicValue implements DynamicValue { if (equipped != null) { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), sourceAbility.getControllerId(), game)) { if (!permanent.getId().equals(equipped.getId())) { - if (CardUtil.shareSubtypes(equipped, permanent)) { + if (CardUtil.shareSubtypes(equipped, permanent, game)) { xValue++; } } diff --git a/Mage.Sets/src/mage/sets/odyssey/TestamentOfFaith.java b/Mage.Sets/src/mage/sets/odyssey/TestamentOfFaith.java index 233dddfdd5..706811649d 100644 --- a/Mage.Sets/src/mage/sets/odyssey/TestamentOfFaith.java +++ b/Mage.Sets/src/mage/sets/odyssey/TestamentOfFaith.java @@ -118,10 +118,10 @@ class TestamentOfFaithBecomesCreatureSourceEffect extends ContinuousEffectImpl i } } if ("".equals(type) || type == null) { - permanent.getSubtype().clear(); + permanent.getSubtype(game).clear(); } - if (token.getSubtype().size() > 0) { - permanent.getSubtype().addAll(token.getSubtype()); + if (token.getSubtype(game).size() > 0) { + permanent.getSubtype(game).addAll(token.getSubtype(game)); } } break; diff --git a/Mage.Sets/src/mage/sets/onslaught/AEtherCharge.java b/Mage.Sets/src/mage/sets/onslaught/AEtherCharge.java index 5c22f29cea..22c324da72 100644 --- a/Mage.Sets/src/mage/sets/onslaught/AEtherCharge.java +++ b/Mage.Sets/src/mage/sets/onslaught/AEtherCharge.java @@ -97,7 +97,7 @@ class AEtherChargeTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent.getCardType().contains(CardType.CREATURE) && permanent.getSubtype().contains("Beast") + if (permanent.getCardType().contains(CardType.CREATURE) && permanent.getSubtype(game).contains("Beast") && permanent.getControllerId().equals(this.controllerId)) { Effect effect = this.getEffects().get(0); effect.setValue("damageSource", event.getTargetId()); diff --git a/Mage.Sets/src/mage/sets/onslaught/AnimalMagnetism.java b/Mage.Sets/src/mage/sets/onslaught/AnimalMagnetism.java index 4716ca3275..8cbe76565a 100644 --- a/Mage.Sets/src/mage/sets/onslaught/AnimalMagnetism.java +++ b/Mage.Sets/src/mage/sets/onslaught/AnimalMagnetism.java @@ -53,8 +53,8 @@ import mage.target.common.TargetOpponent; */ public class AnimalMagnetism extends CardImpl { - public AnimalMagnetism(UUID ownerID) { - super(ownerID, 245, "Animal Magnetism", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{4}{G}"); + public AnimalMagnetism(UUID ownerId) { + super(ownerId, 245, "Animal Magnetism", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{4}{G}"); this.expansionSetCode = "ONS"; // Reveal the top five cards of your library. An opponent chooses a creature card from among them. Put that card onto the battlefield and the rest into your graveyard. diff --git a/Mage.Sets/src/mage/sets/onslaught/BloodstainedMire.java b/Mage.Sets/src/mage/sets/onslaught/BloodstainedMire.java index be712d48cd..c0ace42443 100644 --- a/Mage.Sets/src/mage/sets/onslaught/BloodstainedMire.java +++ b/Mage.Sets/src/mage/sets/onslaught/BloodstainedMire.java @@ -28,6 +28,7 @@ package mage.sets.onslaught; import java.util.UUID; +import mage.ObjectColor; import mage.constants.CardType; import mage.constants.Rarity; import mage.abilities.common.FetchLandActivatedAbility; @@ -42,6 +43,7 @@ public class BloodstainedMire extends CardImpl { public BloodstainedMire(UUID ownerId) { super(ownerId, 313, "Bloodstained Mire", Rarity.RARE, new CardType[]{CardType.LAND}, ""); this.expansionSetCode = "ONS"; + this.frameColor = new ObjectColor("RB"); // {tap}, Pay 1 life, Sacrifice Bloodstained Mire: Search your library for a Swamp or Mountain card and put it onto the battlefield. Then shuffle your library. this.addAbility(new FetchLandActivatedAbility(new String[]{"Swamp", "Mountain"})); diff --git a/Mage.Sets/src/mage/sets/onslaught/CoverOfDarkness.java b/Mage.Sets/src/mage/sets/onslaught/CoverOfDarkness.java index 2bdbcb6977..da0e5f2187 100644 --- a/Mage.Sets/src/mage/sets/onslaught/CoverOfDarkness.java +++ b/Mage.Sets/src/mage/sets/onslaught/CoverOfDarkness.java @@ -89,7 +89,7 @@ class FilterCoverOfDarkness extends FilterCreaturePermanent { public boolean match(Permanent permanent, UUID sourceId, UUID playerId, Game game) { if (super.match(permanent, sourceId, playerId, game)) { String subtype = (String) game.getState().getValue(sourceId + "_type"); - if (subtype != null && !subtype.equals("") && permanent.hasSubtype(subtype)) { + if (subtype != null && !subtype.equals("") && permanent.hasSubtype(subtype, game)) { return true; } } diff --git a/Mage.Sets/src/mage/sets/onslaught/CrypticGateway.java b/Mage.Sets/src/mage/sets/onslaught/CrypticGateway.java index 0334234694..a1a8b64e78 100644 --- a/Mage.Sets/src/mage/sets/onslaught/CrypticGateway.java +++ b/Mage.Sets/src/mage/sets/onslaught/CrypticGateway.java @@ -192,24 +192,24 @@ class CrypticGatewayEffect extends OneShotEffect { boolean commonSubType = false; boolean changeling = false; boolean changeling2 = false; - if (creature.getAbilities().containsKey(ChangelingAbility.getInstance().getId()) || creature.getSubtype().contains(ChangelingAbility.ALL_CREATURE_TYPE)) { + if (creature.getAbilities().containsKey(ChangelingAbility.getInstance().getId()) || creature.getSubtype(game).contains(ChangelingAbility.ALL_CREATURE_TYPE)) { changeling = true; } - if (creature2.getAbilities().containsKey(ChangelingAbility.getInstance().getId()) || creature2.getSubtype().contains(ChangelingAbility.ALL_CREATURE_TYPE)) { + if (creature2.getAbilities().containsKey(ChangelingAbility.getInstance().getId()) || creature2.getSubtype(game).contains(ChangelingAbility.ALL_CREATURE_TYPE)) { changeling2 = true; } ArrayList subtypes = new ArrayList<>(); - for (String subtype : creature.getSubtype()) { - if (creature2.getSubtype().contains(subtype) || changeling2) { + for (String subtype : creature.getSubtype(game)) { + if (creature2.getSubtype(game).contains(subtype) || changeling2) { subtypes.add(new SubtypePredicate(subtype)); commonSubType = true; } } - for (String subtype : creature2.getSubtype()) { - if (creature.getSubtype().contains(subtype) || changeling) { + for (String subtype : creature2.getSubtype(game)) { + if (creature.getSubtype(game).contains(subtype) || changeling) { subtypes.add(new SubtypePredicate(subtype)); commonSubType = true; } diff --git a/Mage.Sets/src/mage/sets/onslaught/FloodedStrand.java b/Mage.Sets/src/mage/sets/onslaught/FloodedStrand.java index e6116d56d8..97f542dee6 100644 --- a/Mage.Sets/src/mage/sets/onslaught/FloodedStrand.java +++ b/Mage.Sets/src/mage/sets/onslaught/FloodedStrand.java @@ -28,6 +28,7 @@ package mage.sets.onslaught; import java.util.UUID; +import mage.ObjectColor; import mage.constants.CardType; import mage.constants.Rarity; import mage.abilities.common.FetchLandActivatedAbility; @@ -42,6 +43,7 @@ public class FloodedStrand extends CardImpl { public FloodedStrand(UUID ownerId) { super(ownerId, 316, "Flooded Strand", Rarity.RARE, new CardType[]{CardType.LAND}, ""); this.expansionSetCode = "ONS"; + this.frameColor = new ObjectColor("UW"); // {tap}, Pay 1 life, Sacrifice Flooded Strand: Search your library for a Plains or Island card and put it onto the battlefield. Then shuffle your library. this.addAbility(new FetchLandActivatedAbility(new String[]{"Plains", "Island"})); diff --git a/Mage.Sets/src/mage/sets/onslaught/GrandMelee.java b/Mage.Sets/src/mage/sets/onslaught/GrandMelee.java index 4af0c6fedc..c53189a57d 100644 --- a/Mage.Sets/src/mage/sets/onslaught/GrandMelee.java +++ b/Mage.Sets/src/mage/sets/onslaught/GrandMelee.java @@ -45,8 +45,8 @@ import mage.watchers.common.AttackedThisTurnWatcher; */ public class GrandMelee extends CardImpl { - public GrandMelee(UUID ownerID) { - super(ownerID, 211, "Grand Melee", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}"); + public GrandMelee(UUID ownerId) { + super(ownerId, 211, "Grand Melee", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}"); this.expansionSetCode = "ONS"; // All creatures attack each turn if able. diff --git a/Mage.Sets/src/mage/sets/onslaught/ManaEchoes.java b/Mage.Sets/src/mage/sets/onslaught/ManaEchoes.java index a213593f1c..5fc662911b 100644 --- a/Mage.Sets/src/mage/sets/onslaught/ManaEchoes.java +++ b/Mage.Sets/src/mage/sets/onslaught/ManaEchoes.java @@ -92,7 +92,7 @@ class ManaEchoesEffect extends OneShotEffect { if (controller != null && permanent != null) { int foundCreatures = 0; for (Permanent perm : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), game)) { - if (CardUtil.shareSubtypes(permanent, perm)) { + if (CardUtil.shareSubtypes(permanent, perm, game)) { foundCreatures++; } } diff --git a/Mage.Sets/src/mage/sets/onslaught/PollutedDelta.java b/Mage.Sets/src/mage/sets/onslaught/PollutedDelta.java index 19ee047bb0..44d229431d 100644 --- a/Mage.Sets/src/mage/sets/onslaught/PollutedDelta.java +++ b/Mage.Sets/src/mage/sets/onslaught/PollutedDelta.java @@ -28,6 +28,7 @@ package mage.sets.onslaught; import java.util.UUID; +import mage.ObjectColor; import mage.constants.CardType; import mage.constants.Rarity; import mage.abilities.common.FetchLandActivatedAbility; @@ -42,6 +43,7 @@ public class PollutedDelta extends CardImpl { public PollutedDelta(UUID ownerId) { super(ownerId, 321, "Polluted Delta", Rarity.RARE, new CardType[]{CardType.LAND}, ""); this.expansionSetCode = "ONS"; + this.frameColor = new ObjectColor("UB"); // {tap}, Pay 1 life, Sacrifice Polluted Delta: Search your library for an Island or Swamp card and put it onto the battlefield. Then shuffle your library. this.addAbility(new FetchLandActivatedAbility(new String[]{"Island", "Swamp"})); diff --git a/Mage.Sets/src/mage/sets/onslaught/RiptideShapeshifter.java b/Mage.Sets/src/mage/sets/onslaught/RiptideShapeshifter.java index e88838cc37..bd3dcddb45 100644 --- a/Mage.Sets/src/mage/sets/onslaught/RiptideShapeshifter.java +++ b/Mage.Sets/src/mage/sets/onslaught/RiptideShapeshifter.java @@ -111,7 +111,7 @@ class RiptideShapeshifterEffect extends OneShotEffect { Cards revealedCards = new CardsImpl(); while (controller.getLibrary().size() > 0) { Card card = controller.getLibrary().removeFromTop(game); - if (card.getCardType().contains(CardType.CREATURE) && card.getSubtype().contains(choice.getChoice())) { + if (card.getCardType().contains(CardType.CREATURE) && card.getSubtype(game).contains(choice.getChoice())) { controller.moveCards(card, Zone.BATTLEFIELD, source, game); break; } diff --git a/Mage.Sets/src/mage/sets/onslaught/SteelyResolve.java b/Mage.Sets/src/mage/sets/onslaught/SteelyResolve.java index e7718d04e2..23154151bf 100644 --- a/Mage.Sets/src/mage/sets/onslaught/SteelyResolve.java +++ b/Mage.Sets/src/mage/sets/onslaught/SteelyResolve.java @@ -87,7 +87,7 @@ class FilterSteelyResolve extends FilterCreaturePermanent { public boolean match(Permanent permanent, UUID sourceId, UUID playerId, Game game) { if (super.match(permanent, sourceId, playerId, game)) { String subtype = (String) game.getState().getValue(sourceId + "_type"); - if (subtype != null && !subtype.equals("") && permanent.hasSubtype(subtype)) { + if (subtype != null && !subtype.equals("") && permanent.hasSubtype(subtype, game)) { return true; } } diff --git a/Mage.Sets/src/mage/sets/onslaught/WindsweptHeath.java b/Mage.Sets/src/mage/sets/onslaught/WindsweptHeath.java index cef77f0815..78b8ecd6d1 100644 --- a/Mage.Sets/src/mage/sets/onslaught/WindsweptHeath.java +++ b/Mage.Sets/src/mage/sets/onslaught/WindsweptHeath.java @@ -28,6 +28,7 @@ package mage.sets.onslaught; import java.util.UUID; +import mage.ObjectColor; import mage.constants.CardType; import mage.constants.Rarity; import mage.abilities.common.FetchLandActivatedAbility; @@ -42,6 +43,7 @@ public class WindsweptHeath extends CardImpl { public WindsweptHeath(UUID ownerId) { super(ownerId, 328, "Windswept Heath", Rarity.RARE, new CardType[]{CardType.LAND}, ""); this.expansionSetCode = "ONS"; + this.frameColor = new ObjectColor("GW"); // {tap}, Pay 1 life, Sacrifice Windswept Heath: Search your library for a Forest or Plains card and put it onto the battlefield. Then shuffle your library. this.addAbility(new FetchLandActivatedAbility(new String[]{"Forest", "Plains"})); diff --git a/Mage.Sets/src/mage/sets/onslaught/WoodedFoothills.java b/Mage.Sets/src/mage/sets/onslaught/WoodedFoothills.java index 5c13350cfe..7cce2364af 100644 --- a/Mage.Sets/src/mage/sets/onslaught/WoodedFoothills.java +++ b/Mage.Sets/src/mage/sets/onslaught/WoodedFoothills.java @@ -28,6 +28,7 @@ package mage.sets.onslaught; import java.util.UUID; +import mage.ObjectColor; import mage.constants.CardType; import mage.constants.Rarity; import mage.abilities.common.FetchLandActivatedAbility; @@ -42,6 +43,7 @@ public class WoodedFoothills extends CardImpl { public WoodedFoothills(UUID ownerId) { super(ownerId, 330, "Wooded Foothills", Rarity.RARE, new CardType[]{CardType.LAND}, ""); this.expansionSetCode = "ONS"; + this.frameColor = new ObjectColor("RG"); // {tap}, Pay 1 life, Sacrifice Wooded Foothills: Search your library for a Mountain or Forest card and put it onto the battlefield. Then shuffle your library. this.addAbility(new FetchLandActivatedAbility(new String[]{"Mountain", "Forest"})); diff --git a/Mage.Sets/src/mage/sets/planarchaos/JeditOjanenOfEfrava.java b/Mage.Sets/src/mage/sets/planarchaos/JeditOjanenOfEfrava.java index f798f676eb..03e6bbcd7b 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/JeditOjanenOfEfrava.java +++ b/Mage.Sets/src/mage/sets/planarchaos/JeditOjanenOfEfrava.java @@ -77,8 +77,8 @@ class CatWarriorToken extends Token { this.getPower().modifyBaseValue(2); this.getToughness().modifyBaseValue(2); this.color.setGreen(true); - this.getSubtype().add("Cat"); - this.getSubtype().add("Warrior"); + this.getSubtype(null).add("Cat"); + this.getSubtype(null).add("Warrior"); this.getCardType().add(CardType.CREATURE); this.addAbility(new ForestwalkAbility()); } diff --git a/Mage.Sets/src/mage/sets/planarchaos/LifeAndLimb.java b/Mage.Sets/src/mage/sets/planarchaos/LifeAndLimb.java index c072b39034..5bd13ed5d4 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/LifeAndLimb.java +++ b/Mage.Sets/src/mage/sets/planarchaos/LifeAndLimb.java @@ -103,14 +103,14 @@ class LifeAndLimbEffect extends ContinuousEffectImpl { if (!permanent.getCardType().contains(CardType.CREATURE)) { permanent.getCardType().add(CardType.CREATURE); } - if (!permanent.getSubtype().contains("Saproling")) { - permanent.getSubtype().add("Saproling"); + if (!permanent.getSubtype(game).contains("Saproling")) { + permanent.getSubtype(game).add("Saproling"); } if (!permanent.getCardType().contains(CardType.LAND)) { permanent.getCardType().add(CardType.LAND); } - if (!permanent.getSubtype().contains("Forest")) { - permanent.getSubtype().add("Forest"); + if (!permanent.getSubtype(game).contains("Forest")) { + permanent.getSubtype(game).add("Forest"); } break; case ColorChangingEffects_5: diff --git a/Mage.Sets/src/mage/sets/planarchaos/Tidewalker.java b/Mage.Sets/src/mage/sets/planarchaos/Tidewalker.java index 3c55beed82..b0178dea79 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/Tidewalker.java +++ b/Mage.Sets/src/mage/sets/planarchaos/Tidewalker.java @@ -31,7 +31,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -71,7 +71,7 @@ public class Tidewalker extends CardImpl { this.addAbility(new VanishingUpkeepAbility(0)); this.addAbility(new VanishingSacrificeAbility()); // Tidewalker's power and toughness are each equal to the number of time counters on it. - this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(new CountersCount(CounterType.TIME), Duration.EndOfGame))); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(new CountersSourceCount(CounterType.TIME), Duration.EndOfGame))); } public Tidewalker(final Tidewalker card) { diff --git a/Mage.Sets/src/mage/sets/planarchaos/UrborgTombOfYawgmoth.java b/Mage.Sets/src/mage/sets/planarchaos/UrborgTombOfYawgmoth.java index a81e54f99c..afd9f45028 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/UrborgTombOfYawgmoth.java +++ b/Mage.Sets/src/mage/sets/planarchaos/UrborgTombOfYawgmoth.java @@ -87,8 +87,8 @@ class AddCardSubtypeAllEffect extends ContinuousEffectImpl { @Override public boolean apply(Game game, Ability source) { for (Permanent perm : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { - if (perm != null && !perm.getSubtype().contains(addedSubtype)) { - perm.getSubtype().add(addedSubtype); + if (perm != null && !perm.getSubtype(game).contains(addedSubtype)) { + perm.getSubtype(game).add(addedSubtype); } } return true; diff --git a/Mage.Sets/src/mage/sets/planarchaos/WildPair.java b/Mage.Sets/src/mage/sets/planarchaos/WildPair.java index 8d4ce274ec..8db3fc523c 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/WildPair.java +++ b/Mage.Sets/src/mage/sets/planarchaos/WildPair.java @@ -58,8 +58,8 @@ import mage.watchers.common.CastFromHandWatcher; */ public class WildPair extends CardImpl { - public WildPair(UUID ownerID) { - super(ownerID, 144, "Wild Pair", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{4}{G}{G}"); + public WildPair(UUID ownerId) { + super(ownerId, 144, "Wild Pair", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{4}{G}{G}"); this.expansionSetCode = "PLC"; // Whenever a creature enters the battlefield, if you cast it from your hand, you may search your library for a creature card with the same total power and toughness and put it onto the battlefield. If you do, shuffle your library. diff --git a/Mage.Sets/src/mage/sets/planechase/Smokebraider.java b/Mage.Sets/src/mage/sets/planechase/Smokebraider.java index 19cc167aed..d8b1331ba7 100644 --- a/Mage.Sets/src/mage/sets/planechase/Smokebraider.java +++ b/Mage.Sets/src/mage/sets/planechase/Smokebraider.java @@ -97,7 +97,7 @@ class SmokebraiderManaCondition implements Condition { @Override public boolean apply(Game game, Ability source) { MageObject object = game.getObject(source.getSourceId()); - if (object != null && object.hasSubtype("Elemental")) { + if (object != null && object.hasSubtype("Elemental", game)) { return true; } return false; diff --git a/Mage.Sets/src/mage/sets/planechase2012/PreyseizerDragon.java b/Mage.Sets/src/mage/sets/planechase2012/PreyseizerDragon.java index d3934a8b61..7926ad91bf 100644 --- a/Mage.Sets/src/mage/sets/planechase2012/PreyseizerDragon.java +++ b/Mage.Sets/src/mage/sets/planechase2012/PreyseizerDragon.java @@ -33,7 +33,7 @@ import mage.constants.Rarity; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.DevourEffect.DevourFactor; import mage.abilities.keyword.DevourAbility; @@ -63,7 +63,7 @@ public class PreyseizerDragon extends CardImpl { this.addAbility(new DevourAbility(DevourFactor.Devour2)); // Whenever Preyseizer Dragon attacks, it deals damage to target creature or player equal to the number of +1/+1 counters on Preyseizer Dragon. - Ability ability = new AttacksTriggeredAbility(new DamageTargetEffect(new CountersCount(CounterType.P1P1)), false); + Ability ability = new AttacksTriggeredAbility(new DamageTargetEffect(new CountersSourceCount(CounterType.P1P1)), false); ability.addTarget(new TargetCreatureOrPlayer()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/planechase2012/RivalsDuel.java b/Mage.Sets/src/mage/sets/planechase2012/RivalsDuel.java index 748b282442..aeb60f1527 100644 --- a/Mage.Sets/src/mage/sets/planechase2012/RivalsDuel.java +++ b/Mage.Sets/src/mage/sets/planechase2012/RivalsDuel.java @@ -88,7 +88,7 @@ class TargetCreaturePermanentWithDifferentTypes extends TargetCreaturePermanent for (Object object : getTargets()) { UUID targetId = (UUID) object; Permanent selectedCreature = game.getPermanent(targetId); - if (CardUtil.shareSubtypes(creature, selectedCreature)) { + if (CardUtil.shareSubtypes(creature, selectedCreature, game)) { return false; } } diff --git a/Mage.Sets/src/mage/sets/ravnica/CopyEnchantment.java b/Mage.Sets/src/mage/sets/ravnica/CopyEnchantment.java index 55f158921c..7564f012ad 100644 --- a/Mage.Sets/src/mage/sets/ravnica/CopyEnchantment.java +++ b/Mage.Sets/src/mage/sets/ravnica/CopyEnchantment.java @@ -88,7 +88,7 @@ class CopyEnchantmentEffect extends CopyPermanentEffect { if (super.apply(game, source)) { Permanent permanentToCopy = getBluePrintPermanent(); if (permanentToCopy != null) { - if (permanentToCopy.getSubtype().contains("Aura")) { + if (permanentToCopy.getSubtype(game).contains("Aura")) { Target target = getBluePrintPermanent().getSpellAbility().getTargets().get(0); Outcome auraOutcome = Outcome.BoostCreature; Ability: diff --git a/Mage.Sets/src/mage/sets/ravnica/DimirDoppelganger.java b/Mage.Sets/src/mage/sets/ravnica/DimirDoppelganger.java index 56ae353e31..adcbb401cb 100644 --- a/Mage.Sets/src/mage/sets/ravnica/DimirDoppelganger.java +++ b/Mage.Sets/src/mage/sets/ravnica/DimirDoppelganger.java @@ -116,10 +116,10 @@ class DimirDoppelgangerEffect extends ContinuousEffectImpl { permanent.getCardType().add(type); } } - permanent.getSubtype().clear(); - for (String type : cardToCopy.getSubtype()) { - if (!permanent.getSubtype().contains(type)) { - permanent.getSubtype().add(type); + permanent.getSubtype(game).clear(); + for (String type : cardToCopy.getSubtype(game)) { + if (!permanent.getSubtype(game).contains(type)) { + permanent.getSubtype(game).add(type); } } permanent.getSupertype().clear(); diff --git a/Mage.Sets/src/mage/sets/ravnica/Terraformer.java b/Mage.Sets/src/mage/sets/ravnica/Terraformer.java index 6817e2f14a..5979753a32 100644 --- a/Mage.Sets/src/mage/sets/ravnica/Terraformer.java +++ b/Mage.Sets/src/mage/sets/ravnica/Terraformer.java @@ -140,8 +140,8 @@ class TerraformerContinuousEffect extends ContinuousEffectImpl { switch (layer) { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { - land.getSubtype().clear(); - land.getSubtype().add(choice); + land.getSubtype(game).clear(); + land.getSubtype(game).add(choice); } break; case AbilityAddingRemovingEffects_6: diff --git a/Mage.Sets/src/mage/sets/returntoravnica/GraveBetrayal.java b/Mage.Sets/src/mage/sets/returntoravnica/GraveBetrayal.java index f791793386..067e540d2b 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/GraveBetrayal.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/GraveBetrayal.java @@ -182,7 +182,7 @@ class GraveBetrayalContiniousEffect extends ContinuousEffectImpl { switch (layer) { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { - creature.getSubtype().add("Zombie"); + creature.getSubtype(game).add("Zombie"); } break; case ColorChangingEffects_5: diff --git a/Mage.Sets/src/mage/sets/returntoravnica/StreetSweeper.java b/Mage.Sets/src/mage/sets/returntoravnica/StreetSweeper.java index bb56267821..c9ea4c4c43 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/StreetSweeper.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/StreetSweeper.java @@ -109,7 +109,7 @@ class StreetSweeperDestroyEffect extends OneShotEffect { for(UUID uuid : attachments) { Permanent aura = game.getPermanent(uuid); - if(aura != null && aura.getSubtype().contains("Aura")) + if(aura != null && aura.getSubtype(game).contains("Aura")) { aura.destroy(source.getSourceId(), game, false); } diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/EldraziTemple.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/EldraziTemple.java index 70959b92df..04496d743f 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/EldraziTemple.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/EldraziTemple.java @@ -96,6 +96,6 @@ class EldraziTempleCondition implements Condition { @Override public boolean apply(Game game, Ability source) { MageObject object = game.getObject(source.getSourceId()); - return object != null && object.hasSubtype("Eldrazi") && object.getColor(game).isColorless(); + return object != null && object.hasSubtype("Eldrazi", game) && object.getColor(game).isColorless(); } } diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/SurrakarSpellblade.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/SurrakarSpellblade.java index a7aec7dfa6..a4208a1ba1 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/SurrakarSpellblade.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/SurrakarSpellblade.java @@ -33,7 +33,7 @@ import mage.constants.Rarity; import mage.MageInt; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -68,7 +68,7 @@ public class SurrakarSpellblade extends CardImpl { this.addAbility(new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), filter, true)); // Whenever Surrakar Spellblade deals combat damage to a player, you may draw X cards, where X is the number of charge counters on it. - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DrawCardSourceControllerEffect(new CountersCount(CounterType.CHARGE)), true)); + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DrawCardSourceControllerEffect(new CountersSourceCount(CounterType.CHARGE)), true)); } public SurrakarSpellblade(final SurrakarSpellblade card) { diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/AshesOfTheFallen.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/AshesOfTheFallen.java index 368893a6ce..4c63a6bd83 100644 --- a/Mage.Sets/src/mage/sets/saviorsofkamigawa/AshesOfTheFallen.java +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/AshesOfTheFallen.java @@ -92,8 +92,8 @@ class AshesOfTheFallenEffect extends ContinuousEffectImpl { String subtype = (String) game.getState().getValue(permanent.getId() + "_type"); for (UUID cardId : controller.getGraveyard()) { Card card = game.getCard(cardId); - if (card != null && card.getCardType().contains(CardType.CREATURE) && !card.getSubtype().contains(subtype)) { - card.getSubtype().add(subtype); + if (card != null && card.getCardType().contains(CardType.CREATURE) && !card.getSubtype(game).contains(subtype)) { + game.getState().getCreateCardAttribute(card).getSubtype().add(subtype); } } return true; diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/MagaTraitorToMortals.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/MagaTraitorToMortals.java index 53bda1d2e3..2cbf2014a5 100644 --- a/Mage.Sets/src/mage/sets/saviorsofkamigawa/MagaTraitorToMortals.java +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/MagaTraitorToMortals.java @@ -32,7 +32,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect; import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.cards.CardImpl; @@ -62,7 +62,7 @@ public class MagaTraitorToMortals extends CardImpl { // When Maga enters the battlefield, target player loses life equal to the number of +1/+1 counters on it. Ability ability = new EntersBattlefieldTriggeredAbility( - new LoseLifeTargetEffect(new CountersCount(CounterType.P1P1)), false); + new LoseLifeTargetEffect(new CountersSourceCount(CounterType.P1P1)), false); ability.addTarget(new TargetPlayer()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/ONaginata.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/ONaginata.java index 409d3ded75..2231dfc03d 100644 --- a/Mage.Sets/src/mage/sets/saviorsofkamigawa/ONaginata.java +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/ONaginata.java @@ -29,10 +29,10 @@ package mage.sets.saviorsofkamigawa; import java.util.UUID; import mage.abilities.Ability; +import mage.abilities.common.AttachableToRestrictedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.Effect; -import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.keyword.EquipAbility; @@ -46,6 +46,7 @@ import mage.constants.Zone; import mage.filter.Filter; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.Target; import mage.target.common.TargetControlledCreaturePermanent; /** @@ -65,9 +66,10 @@ public class ONaginata extends CardImpl { this.expansionSetCode = "SOK"; this.subtype.add("Equipment"); + Target target = new TargetControlledCreaturePermanent(1, 1, filter, false); // O-Naginata can be attached only to a creature with 3 or more power. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new InfoEffect("{this} can be attached only to a creature with 3 or more power"))); - + this.addAbility(new AttachableToRestrictedAbility(target)); + // Equipped creature gets +3/+0 and has trample. Effect effect = new BoostEquippedEffect(3, 0); effect.setText("Equipped creature gets +3/+0"); @@ -76,12 +78,9 @@ public class ONaginata extends CardImpl { effect.setText("and has trample"); ability.addEffect(effect); this.addAbility(ability); - + // Equip {2} - this.addAbility(new EquipAbility( - Outcome.AddAbility, - new GenericManaCost(2), - new TargetControlledCreaturePermanent(1,1, filter, false))); + this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2), target)); } public ONaginata(final ONaginata card) { diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/SakashimaTheImpostor.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/SakashimaTheImpostor.java index c6fa592d4f..9d8a4ef4a7 100644 --- a/Mage.Sets/src/mage/sets/saviorsofkamigawa/SakashimaTheImpostor.java +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/SakashimaTheImpostor.java @@ -83,7 +83,7 @@ class SakashimaTheImpostorApplier extends ApplyToPermanent { @Override public Boolean apply(Game game, Permanent permanent) { if (!permanent.getSupertype().contains("Legendary")) { - permanent.getSubtype().add("Legendary"); + permanent.getSupertype().add("Legendary"); } permanent.setName("Sakashima the Impostor"); // {2}{U}{U}: Return Sakashima the Impostor to its owner's hand at the beginning of the next end step @@ -97,7 +97,7 @@ class SakashimaTheImpostorApplier extends ApplyToPermanent { @Override public Boolean apply(Game game, MageObject mageObject) { if (!mageObject.getSupertype().contains("Legendary")) { - mageObject.getSubtype().add("Legendary"); + mageObject.getSupertype().add("Legendary"); } mageObject.setName("Sakashima the Impostor"); // {2}{U}{U}: Return Sakashima the Impostor to its owner's hand at the beginning of the next end step diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/ChimericMass.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/ChimericMass.java index 6fef0b8fcd..a3db567c13 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/ChimericMass.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/ChimericMass.java @@ -33,7 +33,7 @@ import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect; @@ -81,6 +81,6 @@ class ChimericMassToken extends Token { subtype.add("Construct"); power = new MageInt(0); toughness = new MageInt(0); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SetPowerToughnessSourceEffect(new CountersCount(CounterType.CHARGE), Duration.WhileOnBattlefield))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SetPowerToughnessSourceEffect(new CountersSourceCount(CounterType.CHARGE), Duration.WhileOnBattlefield))); } } diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/GoldenUrn.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/GoldenUrn.java index 49c1a2257c..ae6446a468 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/GoldenUrn.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/GoldenUrn.java @@ -35,7 +35,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -55,7 +55,7 @@ public class GoldenUrn extends CardImpl { super(ownerId, 158, "Golden Urn", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{1}"); this.expansionSetCode = "SOM"; this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), TargetController.YOU, true)); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainLifeEffect(new CountersCount(CounterType.CHARGE)), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainLifeEffect(new CountersSourceCount(CounterType.CHARGE)), new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/LiegeOfTheTangle.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/LiegeOfTheTangle.java index 8f38fa706a..6f46999fee 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/LiegeOfTheTangle.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/LiegeOfTheTangle.java @@ -140,7 +140,7 @@ class LiegeOfTheTangleEffect extends ContinuousEffectImpl { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { perm.getCardType().addAll(token.getCardType()); - perm.getSubtype().addAll(token.getSubtype()); + perm.getSubtype(game).addAll(token.getSubtype(game)); } break; case ColorChangingEffects_5: diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/MyrReservoir.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/MyrReservoir.java index b9a1eb76f3..c72891194b 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/MyrReservoir.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/MyrReservoir.java @@ -114,7 +114,7 @@ class MyrManaCondition implements Condition { @Override public boolean apply(Game game, Ability source) { MageObject object = game.getObject(source.getSourceId()); - if (object != null && object.hasSubtype("Myr")) { + if (object != null && object.hasSubtype("Myr", game)) { return true; } return false; diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/PrecursorGolem.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/PrecursorGolem.java index fe658b91e2..404a6bc624 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/PrecursorGolem.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/PrecursorGolem.java @@ -114,7 +114,7 @@ class PrecursorGolemCopyTriggeredAbility extends TriggeredAbilityImpl { Target targetInstance = addr.getTarget(spell); for (UUID target : targetInstance.getTargets()) { Permanent permanent = game.getPermanent(target); - if (permanent == null || !permanent.hasSubtype("Golem")) { + if (permanent == null || !permanent.hasSubtype("Golem", game)) { return false; } if (targetGolem == null) { diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/TurnToSlag.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/TurnToSlag.java index 9d95d5f385..1828424c00 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/TurnToSlag.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/TurnToSlag.java @@ -84,7 +84,7 @@ class TurnToSlagEffect extends OneShotEffect { List attachments = new ArrayList(); for (UUID uuid : target.getAttachments()) { Permanent attached = game.getBattlefield().getPermanent(uuid); - if (attached.getSubtype().contains("Equipment")) { + if (attached.getSubtype(game).contains("Equipment")) { attachments.add(attached); } } diff --git a/Mage.Sets/src/mage/sets/shadowmoor/DuskUrchins.java b/Mage.Sets/src/mage/sets/shadowmoor/DuskUrchins.java index 559b62cc89..93552d1720 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/DuskUrchins.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/DuskUrchins.java @@ -31,7 +31,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.AttacksOrBlocksTriggeredAbility; import mage.abilities.common.DiesTriggeredAbility; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -57,7 +57,7 @@ public class DuskUrchins extends CardImpl { this.addAbility(new AttacksOrBlocksTriggeredAbility(new AddCountersSourceEffect(CounterType.M1M1.createInstance()), false)); // When Dusk Urchins dies, draw a card for each -1/-1 counter on it. - this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(new CountersCount(CounterType.M1M1)))); + this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(new CountersSourceCount(CounterType.M1M1)))); } diff --git a/Mage.Sets/src/mage/sets/shadowmoor/ElsewhereFlask.java b/Mage.Sets/src/mage/sets/shadowmoor/ElsewhereFlask.java index 933ce3485e..6634c38180 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/ElsewhereFlask.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/ElsewhereFlask.java @@ -140,8 +140,8 @@ class ElsewhereFlaskContinuousEffect extends ContinuousEffectImpl { switch (layer) { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { - land.getSubtype().clear(); - land.getSubtype().add(choice); + land.getSubtype(game).clear(); + land.getSubtype(game).add(choice); } break; case AbilityAddingRemovingEffects_6: diff --git a/Mage.Sets/src/mage/sets/shadowmoor/GlamerSpinners.java b/Mage.Sets/src/mage/sets/shadowmoor/GlamerSpinners.java index b9b73fdc71..dd7b370a0a 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/GlamerSpinners.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/GlamerSpinners.java @@ -143,7 +143,7 @@ class GlamerSpinnersEffect extends OneShotEffect { } // Check for protection MageObject auraObject = game.getObject(auraId); - if (permanentToAttachAuras.cantBeEnchantedBy(auraObject, game)) { + if (permanentToAttachAuras.cantBeAttachedBy(auraObject, game)) { passed = false; } } diff --git a/Mage.Sets/src/mage/sets/shadowmoor/PrismaticOmen.java b/Mage.Sets/src/mage/sets/shadowmoor/PrismaticOmen.java index 1893f7162f..eea89b65f2 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/PrismaticOmen.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/PrismaticOmen.java @@ -133,8 +133,8 @@ class BecomesBasicLandTypeAllEffect extends ContinuousEffectImpl { break; case TypeChangingEffects_4: for (String subtype : landTypes) { - if (!land.getSubtype().contains(subtype)) { - land.getSubtype().add(subtype); + if (!land.getSubtype(game).contains(subtype)) { + land.getSubtype(game).add(subtype); } } break; diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/BriarbridgePatrol.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/BriarbridgePatrol.java index 6197e3a86c..c1879ed9c1 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/BriarbridgePatrol.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/BriarbridgePatrol.java @@ -94,7 +94,7 @@ class BriarbridgePatrolCondition implements Condition { if (sacrificedPermanents != null && !sacrificedPermanents.isEmpty()) { int amountOfClues = 0; for (Permanent permanent : sacrificedPermanents) { - if (permanent.getSubtype().contains("Clue")) { + if (permanent.getSubtype(game).contains("Clue")) { amountOfClues++; } } diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/DaringSleuth.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/DaringSleuth.java index f87e984175..9eed604232 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/DaringSleuth.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/DaringSleuth.java @@ -95,7 +95,7 @@ class DaringSleuthTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { return event.getPlayerId().equals(this.getControllerId()) - && game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD).getSubtype().contains("Clue"); + && game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD).getSubtype(game).contains("Clue"); } @Override diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/EssenceFlux.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/EssenceFlux.java index 56f29a50c6..2be742d283 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/EssenceFlux.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/EssenceFlux.java @@ -129,7 +129,7 @@ class EssenceFluxEffect extends OneShotEffect { controller.moveCards(cardsToBattlefield.getCards(game), Zone.BATTLEFIELD, source, game, false, false, true, null); for (UUID cardId : cardsToBattlefield) { Permanent permanent = game.getPermanent(cardId); - if (permanent != null && permanent.getSubtype().contains("Spirit")) { + if (permanent != null && permanent.getSubtype(game).contains("Spirit")) { Effect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance()); effect.setTargetPointer(new FixedTarget(permanent, game)); return effect.apply(game, source); diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/EverAfter.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/EverAfter.java index e112d582f0..05e9789561 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/EverAfter.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/EverAfter.java @@ -98,7 +98,7 @@ class EverAfterEffect extends ContinuousEffectImpl { switch (layer) { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { - card.getSubtype().add("Zombie"); + card.getSubtype(game).add("Zombie"); } break; case ColorChangingEffects_5: diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/FleetingMemories.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/FleetingMemories.java index 39ca92a5dc..9d654204ea 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/FleetingMemories.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/FleetingMemories.java @@ -103,7 +103,7 @@ class FleetingMemoriesTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { return event.getPlayerId().equals(this.getControllerId()) - && game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD).getSubtype().contains("Clue"); + && game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD).getSubtype(game).contains("Clue"); } @Override diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/GrafMole.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/GrafMole.java index 85d78240d7..b410e642e3 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/GrafMole.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/GrafMole.java @@ -91,7 +91,7 @@ class GrafMoleTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { return event.getPlayerId().equals(this.getControllerId()) - && game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD).getSubtype().contains("Clue"); + && game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD).getSubtype(game).contains("Clue"); } @Override diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/GryffsBoon.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/GryffsBoon.java index 848941da59..bf41ce2400 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/GryffsBoon.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/GryffsBoon.java @@ -110,7 +110,7 @@ class GryffsBoonEffect extends OneShotEffect { if (aura != null && game.getState().getZone(aura.getId()).equals(Zone.GRAVEYARD)) { Permanent targetPermanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (!targetPermanent.cantBeEnchantedBy(aura, game)) { + if (!targetPermanent.cantBeAttachedBy(aura, game)) { game.getState().setValue("attachTo:" + aura.getId(), targetPermanent); aura.putOntoBattlefield(game, Zone.GRAVEYARD, source.getSourceId(), source.getControllerId()); return targetPermanent.addAttachment(aura.getId(), game); diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/SilverfurPartisan.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/SilverfurPartisan.java index 095ca138a7..9d1ec2862e 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/SilverfurPartisan.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/SilverfurPartisan.java @@ -100,7 +100,7 @@ class CreaturesYouControlBecomesTargetTriggeredAbility extends TriggeredAbilityI @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && permanent.getControllerId().equals(this.controllerId) && (permanent.getSubtype().contains("Wolf") || permanent.getSubtype().contains("Werewolf"))) { + if (permanent != null && permanent.getControllerId().equals(this.controllerId) && (permanent.getSubtype(game).contains("Wolf") || permanent.getSubtype(game).contains("Werewolf"))) { MageObject object = game.getObject(event.getSourceId()); if (object != null && object instanceof Spell) { Card c = (Spell) object; diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/SlayersPlate.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/SlayersPlate.java index da45995fcb..bc5f77a8f3 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/SlayersPlate.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/SlayersPlate.java @@ -101,7 +101,7 @@ class SlayersPlateTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { if (((ZoneChangeEvent) event).isDiesEvent()) { Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); - if (permanent.getAttachments().contains(this.getSourceId()) && permanent.hasSubtype("Human")) { + if (permanent.getAttachments().contains(this.getSourceId()) && permanent.hasSubtype("Human", game)) { return true; } } diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/StensiaMasquerade.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/StensiaMasquerade.java index e3578968b7..dbcf9746b4 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/StensiaMasquerade.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/StensiaMasquerade.java @@ -114,7 +114,7 @@ class StensiaMasqueradeTriggeredAbility extends TriggeredAbilityImpl { DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event; Permanent permanent = game.getPermanent(event.getSourceId()); if (damageEvent.isCombatDamage() && permanent != null - && permanent.hasSubtype("Vampire") && permanent.getControllerId().equals(controllerId)) { + && permanent.hasSubtype("Vampire", game) && permanent.getControllerId().equals(controllerId)) { this.getEffects().clear(); AddCountersTargetEffect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance()); effect.setTargetPointer(new FixedTarget(permanent.getId())); diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/TirelessTracker.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/TirelessTracker.java index 027303b6e1..8cd8d7d936 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/TirelessTracker.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/TirelessTracker.java @@ -106,7 +106,7 @@ class TirelessTrackerTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { return event.getPlayerId().equals(this.getControllerId()) - && game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD).getSubtype().contains("Clue"); + && game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD).getSubtype(game).contains("Clue"); } @Override diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/UlvenwaldMysteries.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/UlvenwaldMysteries.java index 92f2aa9c73..749b214c31 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/UlvenwaldMysteries.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/UlvenwaldMysteries.java @@ -107,7 +107,7 @@ class UlvenwaldMysteriesTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { return event.getPlayerId().equals(this.getControllerId()) - && game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD).getSubtype().contains("Clue"); + && game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD).getSubtype(game).contains("Clue"); } @Override diff --git a/Mage.Sets/src/mage/sets/shardsofalara/Mycoloth.java b/Mage.Sets/src/mage/sets/shardsofalara/Mycoloth.java index a3a280dcee..bda4a95831 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/Mycoloth.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/Mycoloth.java @@ -33,7 +33,7 @@ import mage.constants.Rarity; import mage.constants.TargetController; import mage.MageInt; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.DevourEffect.DevourFactor; import mage.abilities.keyword.DevourAbility; @@ -60,7 +60,7 @@ public class Mycoloth extends CardImpl { // At the beginning of your upkeep, put a 1/1 green Saproling creature token onto the battlefield for each +1/+1 counter on Mycoloth. this.addAbility(new BeginningOfUpkeepTriggeredAbility( - new CreateTokenEffect(new SaprolingToken(),new CountersCount(CounterType.P1P1)), + new CreateTokenEffect(new SaprolingToken(),new CountersSourceCount(CounterType.P1P1)), TargetController.YOU, false )); diff --git a/Mage.Sets/src/mage/sets/shardsofalara/SigilOfDistinction.java b/Mage.Sets/src/mage/sets/shardsofalara/SigilOfDistinction.java index c3f9fbb88e..aa75086b14 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/SigilOfDistinction.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/SigilOfDistinction.java @@ -31,7 +31,7 @@ import java.util.UUID; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.common.RemoveCountersSourceCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.keyword.EquipAbility; @@ -56,7 +56,7 @@ public class SigilOfDistinction extends CardImpl { this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.CHARGE.createInstance()))); // Equipped creature gets +1/+1 for each charge counter on Sigil of Distinction. - BoostEquippedEffect effect = new BoostEquippedEffect(new CountersCount(CounterType.CHARGE), new CountersCount(CounterType.CHARGE)); + BoostEquippedEffect effect = new BoostEquippedEffect(new CountersSourceCount(CounterType.CHARGE), new CountersSourceCount(CounterType.CHARGE)); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); // Equip—Remove a charge counter from Sigil of Distinction. diff --git a/Mage.Sets/src/mage/sets/shardsofalara/TezzeretTheSeeker.java b/Mage.Sets/src/mage/sets/shardsofalara/TezzeretTheSeeker.java index a0aae51402..b95982960a 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/TezzeretTheSeeker.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/TezzeretTheSeeker.java @@ -166,7 +166,7 @@ class TezzeretTheSeekerEffect3 extends ContinuousEffectImpl { if (!permanent.getCardType().contains(CardType.CREATURE)) { permanent.getCardType().add(CardType.CREATURE); } - permanent.getSubtype().clear(); + permanent.getSubtype(game).clear(); } break; case PTChangingEffects_7: diff --git a/Mage.Sets/src/mage/sets/tempest/EndlessScream.java b/Mage.Sets/src/mage/sets/tempest/EndlessScream.java index 58c3755d0f..cacdf670df 100644 --- a/Mage.Sets/src/mage/sets/tempest/EndlessScream.java +++ b/Mage.Sets/src/mage/sets/tempest/EndlessScream.java @@ -31,7 +31,7 @@ import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect; @@ -67,7 +67,7 @@ public class EndlessScream extends CardImpl { // Endless Scream enters the battlefield with X scream counters on it. this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.SCREAM.createInstance()))); // Enchanted creature gets +1/+0 for each scream counter on Endless Scream. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(new CountersCount(CounterType.SCREAM), new StaticValue(0), Duration.WhileOnBattlefield))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(new CountersSourceCount(CounterType.SCREAM), new StaticValue(0), Duration.WhileOnBattlefield))); } public EndlessScream(final EndlessScream card) { diff --git a/Mage.Sets/src/mage/sets/tempest/Excavator.java b/Mage.Sets/src/mage/sets/tempest/Excavator.java index 9b9918a9fb..b1d90e6acd 100644 --- a/Mage.Sets/src/mage/sets/tempest/Excavator.java +++ b/Mage.Sets/src/mage/sets/tempest/Excavator.java @@ -116,23 +116,23 @@ class ExcavatorEffect extends ContinuousEffectImpl implements SourceEffect { if(cost instanceof SacrificeTargetCost) { SacrificeTargetCost sacrificeCost = (SacrificeTargetCost) cost; for(Permanent permanent : sacrificeCost.getPermanents()) { - if(permanent.hasSubtype("Forest")) + if(permanent.hasSubtype("Forest", game)) { abilities.add(new ForestwalkAbility()); } - if(permanent.hasSubtype("Plains")) + if(permanent.hasSubtype("Plains", game)) { abilities.add(new PlainswalkAbility()); } - if(permanent.hasSubtype("Island")) + if(permanent.hasSubtype("Island", game)) { abilities.add(new IslandwalkAbility()); } - if(permanent.hasSubtype("Mountain")) + if(permanent.hasSubtype("Mountain", game)) { abilities.add(new MountainwalkAbility()); } - if(permanent.hasSubtype("Swamp")) + if(permanent.hasSubtype("Swamp", game)) { abilities.add(new SwampwalkAbility()); } diff --git a/Mage.Sets/src/mage/sets/thedark/CityOfShadows.java b/Mage.Sets/src/mage/sets/thedark/CityOfShadows.java index 66e4b455d5..1bdc21a93f 100644 --- a/Mage.Sets/src/mage/sets/thedark/CityOfShadows.java +++ b/Mage.Sets/src/mage/sets/thedark/CityOfShadows.java @@ -33,7 +33,7 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.ExileTargetCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.mana.DynamicManaAbility; import mage.cards.CardImpl; @@ -59,7 +59,7 @@ public class CityOfShadows extends CardImpl { this.addAbility(ability); // {T}: Add X mana of {C} to your mana pool, where X is the number of storage counters on City of Shadows. - ability = new DynamicManaAbility(Mana.ColorlessMana(1), new CountersCount(CounterType.STORAGE), + ability = new DynamicManaAbility(Mana.ColorlessMana(1), new CountersSourceCount(CounterType.STORAGE), "Add X mana of {C} to your mana pool, where X is the number of storage counters on {this}"); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/thedark/GoblinCaves.java b/Mage.Sets/src/mage/sets/thedark/GoblinCaves.java index 641d77f9a0..79f48dfeda 100644 --- a/Mage.Sets/src/mage/sets/thedark/GoblinCaves.java +++ b/Mage.Sets/src/mage/sets/thedark/GoblinCaves.java @@ -92,7 +92,7 @@ class AttachedToBasicMountainCondition implements Condition { if (enchantment != null) { Permanent enchanted = game.getPermanent(enchantment.getAttachedTo()); if (enchanted != null) { - if (enchanted.hasSubtype("Mountain") && enchanted.getSupertype().contains("Basic")) { + if (enchanted.hasSubtype("Mountain", game) && enchanted.getSupertype().contains("Basic")) { return true; } } diff --git a/Mage.Sets/src/mage/sets/thedark/Venom.java b/Mage.Sets/src/mage/sets/thedark/Venom.java index 5c736ca71e..4bae921bea 100644 --- a/Mage.Sets/src/mage/sets/thedark/Venom.java +++ b/Mage.Sets/src/mage/sets/thedark/Venom.java @@ -112,13 +112,13 @@ class VenomTriggeredAbility extends TriggeredAbilityImpl { Permanent enchantedCreature = game.getPermanent(enchantment.getAttachedTo()); if (enchantedCreature != null) { if (blocker != null && blocker != enchantedCreature - && !blocker.getSubtype().contains("Wall") + && !blocker.getSubtype(game).contains("Wall") && blocked == enchantedCreature) { this.getEffects().get(0).setTargetPointer(new FixedTarget(blocker.getId())); return true; } if (blocker != null && blocker == enchantedCreature - && !blocked.getSubtype().contains("Wall")) { + && !blocked.getSubtype(game).contains("Wall")) { this.getEffects().get(0).setTargetPointer(new FixedTarget(blocked.getId())); return true; } diff --git a/Mage.Sets/src/mage/sets/theros/AshiokNightmareWeaver.java b/Mage.Sets/src/mage/sets/theros/AshiokNightmareWeaver.java index a87905e2fd..2a44f49eb1 100644 --- a/Mage.Sets/src/mage/sets/theros/AshiokNightmareWeaver.java +++ b/Mage.Sets/src/mage/sets/theros/AshiokNightmareWeaver.java @@ -206,7 +206,7 @@ class AshiokNightmareWeaverAddTypeEffect extends ContinuousEffectImpl { switch (layer) { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { - creature.getSubtype().add("Nightmare"); + creature.getSubtype(game).add("Nightmare"); } break; } diff --git a/Mage.Sets/src/mage/sets/theros/NyleasPresence.java b/Mage.Sets/src/mage/sets/theros/NyleasPresence.java index cafe4bbf2b..27884eeb6b 100644 --- a/Mage.Sets/src/mage/sets/theros/NyleasPresence.java +++ b/Mage.Sets/src/mage/sets/theros/NyleasPresence.java @@ -151,8 +151,8 @@ class NyleasPresenceLandTypeEffect extends ContinuousEffectImpl { break; case TypeChangingEffects_4: for (String subtype : landTypes) { - if (!land.getSubtype().contains(subtype)) { - land.getSubtype().add(subtype); + if (!land.getSubtype(game).contains(subtype)) { + land.getSubtype(game).add(subtype); } } break; diff --git a/Mage.Sets/src/mage/sets/theros/ProwlersHelm.java b/Mage.Sets/src/mage/sets/theros/ProwlersHelm.java index ed0f8f890d..dbb4683ce9 100644 --- a/Mage.Sets/src/mage/sets/theros/ProwlersHelm.java +++ b/Mage.Sets/src/mage/sets/theros/ProwlersHelm.java @@ -94,7 +94,7 @@ class CantBeBlockedByWallsEffect extends RestrictionEffect { @Override public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game) { - if (!blocker.hasSubtype("Wall")) { + if (!blocker.hasSubtype("Wall", game)) { return false; } return true; diff --git a/Mage.Sets/src/mage/sets/theros/SealockMonster.java b/Mage.Sets/src/mage/sets/theros/SealockMonster.java index 04a68fad77..dbeb753766 100644 --- a/Mage.Sets/src/mage/sets/theros/SealockMonster.java +++ b/Mage.Sets/src/mage/sets/theros/SealockMonster.java @@ -122,8 +122,8 @@ class SealockMonsterBecomesIslandTargetEffect extends ContinuousEffectImpl { } break; case TypeChangingEffects_4: - if (!land.getSubtype().contains("Island")) { - land.getSubtype().add("Island"); + if (!land.getSubtype(game).contains("Island")) { + land.getSubtype(game).add("Island"); } break; } diff --git a/Mage.Sets/src/mage/sets/timeshifted/CelestialDawn.java b/Mage.Sets/src/mage/sets/timeshifted/CelestialDawn.java index ce72b1a20d..0d50506149 100644 --- a/Mage.Sets/src/mage/sets/timeshifted/CelestialDawn.java +++ b/Mage.Sets/src/mage/sets/timeshifted/CelestialDawn.java @@ -123,8 +123,8 @@ class CelestialDawnToPlainsEffect extends ContinuousEffectImpl { land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); break; case TypeChangingEffects_4: - land.getSubtype().clear(); - land.getSubtype().add("Plains"); + land.getSubtype(game).clear(); + land.getSubtype(game).add("Plains"); break; } } diff --git a/Mage.Sets/src/mage/sets/timeshifted/Conspiracy.java b/Mage.Sets/src/mage/sets/timeshifted/Conspiracy.java new file mode 100644 index 0000000000..c6d9ae9edb --- /dev/null +++ b/Mage.Sets/src/mage/sets/timeshifted/Conspiracy.java @@ -0,0 +1,187 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.timeshifted; + +import java.util.Iterator; +import java.util.List; +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.ChooseCreatureTypeEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.repository.CardRepository; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.SubLayer; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.stack.Spell; +import mage.game.stack.StackObject; +import mage.players.Player; + +/** + * + * @author anonymous + */ +public class Conspiracy extends CardImpl { + + public Conspiracy(UUID ownerId) { + super(ownerId, 39, "Conspiracy", Rarity.SPECIAL, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}{B}"); + this.expansionSetCode = "TSB"; + + // As Conspiracy enters the battlefield, choose a creature type. + this.addAbility(new EntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.Neutral))); + // Creature cards you own that aren't on the battlefield, creature spells you control, and creatures you control are the chosen type. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConspiracyEffect())); + } + + public Conspiracy(final Conspiracy card) { + super(card); + } + + @Override + public Conspiracy copy() { + return new Conspiracy(this); + } +} + +class ConspiracyEffect extends ContinuousEffectImpl { + + public ConspiracyEffect() { + super(Duration.WhileOnBattlefield, Outcome.Neutral); + staticText = "Creature cards you own that aren't on the battlefield, creature spells you control, and creatures you control are the chosen type"; + } + + public ConspiracyEffect(final ConspiracyEffect effect) { + super(effect); + } + + @Override + public ConspiracyEffect copy() { + return new ConspiracyEffect(this); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + String choice = (String) game.getState().getValue(source.getSourceId().toString() + "_type"); + if (controller != null && choice != null) { + // Creature cards you own that aren't on the battlefield + // in graveyard + for (UUID cardId : controller.getGraveyard()) { + Card card = game.getCard(cardId); + if (card.getCardType().contains(CardType.CREATURE)) { + setCreatureSubtype(card, choice, game); + } + } + // on Hand + for (UUID cardId : controller.getHand()) { + Card card = game.getCard(cardId); + if (card.getCardType().contains(CardType.CREATURE)) { + setCreatureSubtype(card, choice, game); + } + } + // in Exile + for (Card card : game.getState().getExile().getAllCards(game)) { + if (card.getOwnerId().equals(controller.getId()) && card.getCardType().contains(CardType.CREATURE)) { + setCreatureSubtype(card, choice, game); + } + } + // in Library (e.g. for Mystical Teachings) + for (Card card : controller.getLibrary().getCards(game)) { + if (card.getOwnerId().equals(controller.getId()) && card.getCardType().contains(CardType.CREATURE)) { + setCreatureSubtype(card, choice, game); + } + } + // commander in command zone + if (controller.getCommanderId() != null && game.getState().getZone(controller.getCommanderId()).equals(Zone.COMMAND)) { + Card card = game.getCard(controller.getCommanderId()); + if (card.getCardType().contains(CardType.CREATURE)) { + setCreatureSubtype(card, choice, game); + } + } + // creature spells you control + for (Iterator iterator = game.getStack().iterator(); iterator.hasNext();) { + StackObject stackObject = iterator.next(); + if (stackObject instanceof Spell && + stackObject.getControllerId().equals(source.getControllerId()) && + stackObject.getCardType().contains(CardType.CREATURE)) { + Card card = ((Spell) stackObject).getCard(); + setCreatureSubtype(card, choice, game); + } + } + // creatures you control + List creatures = game.getBattlefield().getAllActivePermanents( + new FilterControlledCreaturePermanent(), source.getControllerId(), game); + for (Permanent creature : creatures) { + setCreatureSubtype(creature, choice, game); + } + return true; + } + return false; + } + + private void setCreatureSubtype(MageObject object, String subtype, Game game) { + if (object != null) { + if (object instanceof Card) { + Card card = (Card) object; + setChosenSubtype( + game.getState().getCreateCardAttribute(card).getSubtype(), + subtype); + } else { + setChosenSubtype(object.getSubtype(game), subtype); + } + } + } + + private void setChosenSubtype(List subtype, String choice) { + if (subtype.size() != 1 || !subtype.contains(choice)) { + subtype.removeAll(CardRepository.instance.getCreatureTypes()); + subtype.add(choice); + } + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean hasLayer(Layer layer) { + return layer == Layer.TypeChangingEffects_4; + } +} diff --git a/Mage.Sets/src/mage/sets/timeshifted/EssenceSliver.java b/Mage.Sets/src/mage/sets/timeshifted/EssenceSliver.java index 3afdd8d5ce..cc0393e1e8 100644 --- a/Mage.Sets/src/mage/sets/timeshifted/EssenceSliver.java +++ b/Mage.Sets/src/mage/sets/timeshifted/EssenceSliver.java @@ -98,7 +98,7 @@ class DealsDamageAllTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent creature = game.getPermanent(event.getSourceId()); - if (creature != null && creature.hasSubtype("Sliver")) { + if (creature != null && creature.hasSubtype("Sliver", game)) { for (Effect effect : this.getEffects()) { effect.setValue("damage", event.getAmount()); } diff --git a/Mage.Sets/src/mage/sets/urzaslegacy/TreefolkMystic.java b/Mage.Sets/src/mage/sets/urzaslegacy/TreefolkMystic.java index 49a574c82d..95de672810 100644 --- a/Mage.Sets/src/mage/sets/urzaslegacy/TreefolkMystic.java +++ b/Mage.Sets/src/mage/sets/urzaslegacy/TreefolkMystic.java @@ -97,7 +97,7 @@ class TreefolkMysticEffect extends OneShotEffect { for(UUID uuid : attachments) { Permanent aura = game.getPermanent(uuid); - if(aura != null && aura.getSubtype().contains("Aura")) + if(aura != null && aura.getSubtype(game).contains("Aura")) { aura.destroy(source.getSourceId(), game, false); } diff --git a/Mage.Sets/src/mage/sets/urzassaga/BarrinsCodex.java b/Mage.Sets/src/mage/sets/urzassaga/BarrinsCodex.java index 1407efba1c..165be605d1 100644 --- a/Mage.Sets/src/mage/sets/urzassaga/BarrinsCodex.java +++ b/Mage.Sets/src/mage/sets/urzassaga/BarrinsCodex.java @@ -40,7 +40,7 @@ import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.cards.CardImpl; import mage.constants.TargetController; import mage.counters.CounterType; @@ -59,7 +59,7 @@ public class BarrinsCodex extends CardImpl { this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.PAGE.createInstance()), TargetController.YOU, true)); //{4}, {T}, Sacrifice Barrin's Codex: Draw X cards, where X is the number of page counters on Barrin's Codex. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(new CountersCount(CounterType.PAGE)), new ManaCostsImpl("{4}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(new CountersSourceCount(CounterType.PAGE)), new ManaCostsImpl("{4}")); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/urzassaga/ChimericStaff.java b/Mage.Sets/src/mage/sets/urzassaga/ChimericStaff.java index e15593ea94..51a65f3a0e 100644 --- a/Mage.Sets/src/mage/sets/urzassaga/ChimericStaff.java +++ b/Mage.Sets/src/mage/sets/urzassaga/ChimericStaff.java @@ -91,7 +91,7 @@ class ChimericStaffEffect extends ContinuousEffectImpl { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { permanent.getCardType().add(CardType.CREATURE); - permanent.getSubtype().add("Construct"); + permanent.getSubtype(game).add("Construct"); } break; case PTChangingEffects_7: diff --git a/Mage.Sets/src/mage/sets/urzassaga/LiltingRefrain.java b/Mage.Sets/src/mage/sets/urzassaga/LiltingRefrain.java index e4cfe2d382..e3041826f0 100644 --- a/Mage.Sets/src/mage/sets/urzassaga/LiltingRefrain.java +++ b/Mage.Sets/src/mage/sets/urzassaga/LiltingRefrain.java @@ -32,7 +32,7 @@ import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.CounterUnlessPaysEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -57,7 +57,7 @@ public class LiltingRefrain extends CardImpl { this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.VERSE.createInstance()), TargetController.YOU, true)); // Sacrifice Lilting Refrain: Counter target spell unless its controller pays {X}, where X is the number of verse counters on Lilting Refrain. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterUnlessPaysEffect(new CountersCount(CounterType.VERSE)), new SacrificeSourceCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterUnlessPaysEffect(new CountersSourceCount(CounterType.VERSE)), new SacrificeSourceCost()); ability.addTarget(new TargetSpell()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/urzassaga/MidsummerRevel.java b/Mage.Sets/src/mage/sets/urzassaga/MidsummerRevel.java index 4197bea226..741bce973c 100644 --- a/Mage.Sets/src/mage/sets/urzassaga/MidsummerRevel.java +++ b/Mage.Sets/src/mage/sets/urzassaga/MidsummerRevel.java @@ -33,7 +33,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -59,7 +59,7 @@ public class MidsummerRevel extends CardImpl { new AddCountersSourceEffect(CounterType.VERSE.createInstance(), true), TargetController.YOU, true)); // {G}, Sacrifice Midsummer Revel: Put X 3/3 green Beast creature tokens onto the battlefield, where X is the number of verse counters on Midsummer Revel. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new BeastToken(), - new CountersCount(CounterType.VERSE)), new ManaCostsImpl("{G}")); + new CountersSourceCount(CounterType.VERSE)), new ManaCostsImpl("{G}")); ability.addCost(new SacrificeSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/urzassaga/TorchSong.java b/Mage.Sets/src/mage/sets/urzassaga/TorchSong.java index edd10ecd56..1ca643773f 100644 --- a/Mage.Sets/src/mage/sets/urzassaga/TorchSong.java +++ b/Mage.Sets/src/mage/sets/urzassaga/TorchSong.java @@ -33,7 +33,7 @@ import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -58,7 +58,7 @@ public class TorchSong extends CardImpl { this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.VERSE.createInstance(), true), TargetController.YOU, true)); // {2}{R}, Sacrifice Torch Song: Torch Song deals X damage to target creature or player, where X is the number of verse counters on Torch Song. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new CountersCount(CounterType.VERSE)), new ManaCostsImpl("{2}{R}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new CountersSourceCount(CounterType.VERSE)), new ManaCostsImpl("{2}{R}")); ability.addCost(new SacrificeSourceCost()); ability.addTarget(new TargetCreatureOrPlayer()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/vintagemasters/CrescendoOfWar.java b/Mage.Sets/src/mage/sets/vintagemasters/CrescendoOfWar.java index 45773d8f0a..03474c83f3 100644 --- a/Mage.Sets/src/mage/sets/vintagemasters/CrescendoOfWar.java +++ b/Mage.Sets/src/mage/sets/vintagemasters/CrescendoOfWar.java @@ -30,7 +30,7 @@ package mage.sets.vintagemasters; import java.util.UUID; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.common.continuous.BoostAllEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -58,11 +58,11 @@ public class CrescendoOfWar extends CardImpl { this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.STRIFE.createInstance(1), true), TargetController.ANY, false)); // Attacking creatures get +1/+0 for each strife counter on Crescendo of War. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(new CountersCount(CounterType.STRIFE), new StaticValue(0), + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(new CountersSourceCount(CounterType.STRIFE), new StaticValue(0), Duration.WhileOnBattlefield, new FilterAttackingCreature(), false))); // Blocking creatures you control get +1/+0 for each strife counter on Crescendo of War. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(new CountersCount(CounterType.STRIFE), new StaticValue(0), + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(new CountersSourceCount(CounterType.STRIFE), new StaticValue(0), Duration.WhileOnBattlefield, new FilterBlockingCreature(), false))); } diff --git a/Mage.Sets/src/mage/sets/vintagemasters/VolrathsShapeshifter.java b/Mage.Sets/src/mage/sets/vintagemasters/VolrathsShapeshifter.java index 98aeac7b4a..4130f7d831 100644 --- a/Mage.Sets/src/mage/sets/vintagemasters/VolrathsShapeshifter.java +++ b/Mage.Sets/src/mage/sets/vintagemasters/VolrathsShapeshifter.java @@ -117,10 +117,10 @@ class VolrathsShapeshifterEffect extends ContinuousEffectImpl { } } - permanent.getSubtype().clear(); - for (String type : card.getSubtype()) { - if (!permanent.getSubtype().contains(type)) { - permanent.getSubtype().add(type); + permanent.getSubtype(game).clear(); + for (String type : card.getSubtype(game)) { + if (!permanent.getSubtype(game).contains(type)) { + permanent.getSubtype(game).add(type); } } diff --git a/Mage.Sets/src/mage/sets/visions/MagmaMine.java b/Mage.Sets/src/mage/sets/visions/MagmaMine.java index aac5b04b73..e9bed6541d 100644 --- a/Mage.Sets/src/mage/sets/visions/MagmaMine.java +++ b/Mage.Sets/src/mage/sets/visions/MagmaMine.java @@ -33,7 +33,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -59,7 +59,7 @@ public class MagmaMine extends CardImpl { new GenericManaCost(4))); // {tap}, Sacrifice Magma Mine: Magma Mine deals damage equal to the number of pressure counters on it to target creature or player. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new CountersCount(CounterType.PRESSURE)), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new CountersSourceCount(CounterType.PRESSURE)), new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); ability.addTarget(new TargetCreatureOrPlayer()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/visions/Necromancy.java b/Mage.Sets/src/mage/sets/visions/Necromancy.java index 034abf3031..7444758609 100644 --- a/Mage.Sets/src/mage/sets/visions/Necromancy.java +++ b/Mage.Sets/src/mage/sets/visions/Necromancy.java @@ -211,8 +211,8 @@ class NecromancyChangeAbilityEffect extends ContinuousEffectImpl implements Sour switch (layer) { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { - if (!permanent.getSubtype().contains("Aura")) { - permanent.getSubtype().add("Aura"); + if (!permanent.getSubtype(game).contains("Aura")) { + permanent.getSubtype(game).add("Aura"); } } break; diff --git a/Mage.Sets/src/mage/sets/visions/VisionCharm.java b/Mage.Sets/src/mage/sets/visions/VisionCharm.java index 9a218243d3..8207443087 100644 --- a/Mage.Sets/src/mage/sets/visions/VisionCharm.java +++ b/Mage.Sets/src/mage/sets/visions/VisionCharm.java @@ -135,8 +135,8 @@ class VisionCharmEffect extends ContinuousEffectImpl { filter.add(new SubtypePredicate(targetLandType)); for (Permanent land : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) { //Remove all existing subtypes and replace them with the selected Basic Land Type - land.getSubtype().removeAll(land.getSubtype()); - land.getSubtype().add(targetBasicLandType); + land.getSubtype(game).removeAll(land.getSubtype(game)); + land.getSubtype(game).add(targetBasicLandType); /* Remove the existing abilities and replace them with the ability of the chosen basic land */ diff --git a/Mage.Sets/src/mage/sets/weatherlight/MwonvuliOoze.java b/Mage.Sets/src/mage/sets/weatherlight/MwonvuliOoze.java index e9ff59f123..4de794792b 100644 --- a/Mage.Sets/src/mage/sets/weatherlight/MwonvuliOoze.java +++ b/Mage.Sets/src/mage/sets/weatherlight/MwonvuliOoze.java @@ -32,7 +32,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect; import mage.abilities.keyword.CumulativeUpkeepAbility; @@ -74,7 +74,7 @@ public class MwonvuliOoze extends CardImpl { } -class MwonvuliOozePTValue extends CountersCount { +class MwonvuliOozePTValue extends CountersSourceCount { public MwonvuliOozePTValue() { super(CounterType.AGE); diff --git a/Mage.Sets/src/mage/sets/weatherlight/ReveredUnicorn.java b/Mage.Sets/src/mage/sets/weatherlight/ReveredUnicorn.java index 2897ba0ec6..d4ee8c7e52 100644 --- a/Mage.Sets/src/mage/sets/weatherlight/ReveredUnicorn.java +++ b/Mage.Sets/src/mage/sets/weatherlight/ReveredUnicorn.java @@ -31,7 +31,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.common.LeavesBattlefieldTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.keyword.CumulativeUpkeepAbility; import mage.cards.CardImpl; @@ -55,7 +55,7 @@ public class ReveredUnicorn extends CardImpl { // Cumulative upkeep {1} this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{1}"))); // When Revered Unicorn leaves the battlefield, you gain life equal to the number of age counters on it. - this.addAbility(new LeavesBattlefieldTriggeredAbility(new GainLifeEffect(new CountersCount(CounterType.AGE)), false)); + this.addAbility(new LeavesBattlefieldTriggeredAbility(new GainLifeEffect(new CountersSourceCount(CounterType.AGE)), false)); } public ReveredUnicorn(final ReveredUnicorn card) { diff --git a/Mage.Sets/src/mage/sets/worldwake/AgadeemOccultist.java b/Mage.Sets/src/mage/sets/worldwake/AgadeemOccultist.java index 1991164395..6973d85b0a 100644 --- a/Mage.Sets/src/mage/sets/worldwake/AgadeemOccultist.java +++ b/Mage.Sets/src/mage/sets/worldwake/AgadeemOccultist.java @@ -98,7 +98,7 @@ class AgadeemOccultistEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); int allycount = 0; for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) { - if (permanent.hasSubtype("Ally")) { + if (permanent.hasSubtype("Ally", game)) { allycount++; } } diff --git a/Mage.Sets/src/mage/sets/worldwake/EverflowingChalice.java b/Mage.Sets/src/mage/sets/worldwake/EverflowingChalice.java index ec35340333..5c3cb7942c 100644 --- a/Mage.Sets/src/mage/sets/worldwake/EverflowingChalice.java +++ b/Mage.Sets/src/mage/sets/worldwake/EverflowingChalice.java @@ -33,7 +33,7 @@ import mage.constants.CardType; import mage.constants.Rarity; import mage.Mana; import mage.abilities.common.EntersBattlefieldAbility; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.MultikickerCount; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.MultikickerAbility; @@ -64,7 +64,7 @@ public class EverflowingChalice extends CardImpl { "with a charge counter on it for each time it was kicked")); // {T}: Add {C} to your mana pool for each charge counter on Everflowing Chalice. - this.addAbility(new DynamicManaAbility(Mana.ColorlessMana(1), new CountersCount(CounterType.CHARGE))); + this.addAbility(new DynamicManaAbility(Mana.ColorlessMana(1), new CountersSourceCount(CounterType.CHARGE))); } public EverflowingChalice(final EverflowingChalice card) { diff --git a/Mage.Sets/src/mage/sets/worldwake/JoragaWarcaller.java b/Mage.Sets/src/mage/sets/worldwake/JoragaWarcaller.java index 5d2bf1eeac..4827b669dd 100644 --- a/Mage.Sets/src/mage/sets/worldwake/JoragaWarcaller.java +++ b/Mage.Sets/src/mage/sets/worldwake/JoragaWarcaller.java @@ -33,7 +33,7 @@ import mage.constants.*; import mage.MageInt; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.MultikickerCount; import mage.abilities.effects.common.continuous.BoostAllEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -81,7 +81,7 @@ public class JoragaWarcaller extends CardImpl { // Other Elf creatures you control get +1/+1 for each +1/+1 counter on Joraga Warcaller. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, - new BoostAllEffect( new CountersCount(CounterType.P1P1), new CountersCount(CounterType.P1P1), Duration.WhileOnBattlefield, filter, true, rule))); + new BoostAllEffect( new CountersSourceCount(CounterType.P1P1), new CountersSourceCount(CounterType.P1P1), Duration.WhileOnBattlefield, filter, true, rule))); } diff --git a/Mage.Sets/src/mage/sets/worldwake/KalastriaHighborn.java b/Mage.Sets/src/mage/sets/worldwake/KalastriaHighborn.java index 7b2bd15a0f..ea58815665 100644 --- a/Mage.Sets/src/mage/sets/worldwake/KalastriaHighborn.java +++ b/Mage.Sets/src/mage/sets/worldwake/KalastriaHighborn.java @@ -111,7 +111,7 @@ class KalastriaHighbornTriggeredAbility extends TriggeredAbilityImpl { zEvent.getToZone() == Zone.GRAVEYARD && zEvent.getFromZone() == Zone.BATTLEFIELD && (permanent.getControllerId().equals(this.getControllerId()) && - permanent.hasSubtype("Vampire") || permanent.getId().equals(this.getSourceId())); + permanent.hasSubtype("Vampire", game) || permanent.getId().equals(this.getSourceId())); } @Override diff --git a/Mage.Sets/src/mage/sets/worldwake/TalusPaladin.java b/Mage.Sets/src/mage/sets/worldwake/TalusPaladin.java index bfd0764de8..8da95e4aa5 100644 --- a/Mage.Sets/src/mage/sets/worldwake/TalusPaladin.java +++ b/Mage.Sets/src/mage/sets/worldwake/TalusPaladin.java @@ -111,7 +111,7 @@ class TalusPaladinTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent ally = game.getPermanent(event.getTargetId()); if (ally != null) { - if (ally.hasSubtype("Ally") + if (ally.hasSubtype("Ally", game) && ally.getControllerId().equals(this.getControllerId())) { if (event.getTargetId().equals(this.getSourceId()) || event.getTargetId().equals(ally.getId())) { diff --git a/Mage.Sets/src/mage/sets/worldwake/TuktukScrapper.java b/Mage.Sets/src/mage/sets/worldwake/TuktukScrapper.java index ea14edc842..cac12c44db 100644 --- a/Mage.Sets/src/mage/sets/worldwake/TuktukScrapper.java +++ b/Mage.Sets/src/mage/sets/worldwake/TuktukScrapper.java @@ -103,7 +103,7 @@ class TuktukScrapperTriggeredAbility extends TriggeredAbilityImpl { if (permanent.getId().equals(this.getSourceId())) { return true; } - if (permanent.hasSubtype("Ally") + if (permanent.hasSubtype("Ally", game) && permanent.getControllerId().equals(this.getControllerId())) { return true; } diff --git a/Mage.Sets/src/mage/sets/zendikar/AridMesa.java b/Mage.Sets/src/mage/sets/zendikar/AridMesa.java index d9a0567366..f7c0c63646 100644 --- a/Mage.Sets/src/mage/sets/zendikar/AridMesa.java +++ b/Mage.Sets/src/mage/sets/zendikar/AridMesa.java @@ -29,6 +29,7 @@ package mage.sets.zendikar; import java.util.UUID; +import mage.ObjectColor; import mage.constants.CardType; import mage.constants.Rarity; import mage.abilities.common.FetchLandActivatedAbility; @@ -43,6 +44,7 @@ public class AridMesa extends CardImpl { public AridMesa(UUID ownerId) { super(ownerId, 211, "Arid Mesa", Rarity.RARE, new CardType[]{CardType.LAND}, null); this.expansionSetCode = "ZEN"; + this.frameColor = new ObjectColor("WR"); this.addAbility(new FetchLandActivatedAbility(new String[] {"Mountain", "Plains"})); } diff --git a/Mage.Sets/src/mage/sets/zendikar/ArmamentMaster.java b/Mage.Sets/src/mage/sets/zendikar/ArmamentMaster.java index 98ec453898..7c4c8aade0 100644 --- a/Mage.Sets/src/mage/sets/zendikar/ArmamentMaster.java +++ b/Mage.Sets/src/mage/sets/zendikar/ArmamentMaster.java @@ -123,7 +123,7 @@ class ArmamentMasterEffect extends ContinuousEffectImpl { List attachments = p.getAttachments(); for (UUID attachmentId : attachments) { Permanent attached = game.getPermanent(attachmentId); - if (attached != null && attached.getSubtype().contains("Equipment")) { + if (attached != null && attached.getSubtype(game).contains("Equipment")) { count++; } } diff --git a/Mage.Sets/src/mage/sets/zendikar/BladeOfTheBloodchief.java b/Mage.Sets/src/mage/sets/zendikar/BladeOfTheBloodchief.java index 1d58f3eca4..9bc2a6711b 100644 --- a/Mage.Sets/src/mage/sets/zendikar/BladeOfTheBloodchief.java +++ b/Mage.Sets/src/mage/sets/zendikar/BladeOfTheBloodchief.java @@ -54,7 +54,7 @@ public class BladeOfTheBloodchief extends CardImpl { public BladeOfTheBloodchief(UUID ownerId) { super(ownerId, 196, "Blade of the Bloodchief", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{1}"); this.expansionSetCode = "ZEN"; - this.getSubtype().add("Equipment"); + this.getSubtype(null).add("Equipment"); this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(1))); this.addAbility(new BladeOfTheBloodChiefTriggeredAbility()); @@ -130,7 +130,7 @@ class BladeOfTheBloodchiefEffect extends OneShotEffect { if (enchantment != null && enchantment.getAttachedTo() != null) { Permanent creature = game.getPermanent(enchantment.getAttachedTo()); if (creature != null) { - if (creature.hasSubtype("Vampire")) { + if (creature.hasSubtype("Vampire", game)) { creature.addCounters(CounterType.P1P1.createInstance(2), game); } else { creature.addCounters(CounterType.P1P1.createInstance(), game); diff --git a/Mage.Sets/src/mage/sets/zendikar/BlazingTorch.java b/Mage.Sets/src/mage/sets/zendikar/BlazingTorch.java index b86ce40889..f52b3c56ed 100644 --- a/Mage.Sets/src/mage/sets/zendikar/BlazingTorch.java +++ b/Mage.Sets/src/mage/sets/zendikar/BlazingTorch.java @@ -109,7 +109,7 @@ class BlazingTorchEvasionEffect extends RestrictionEffect { @Override public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game) { - return !blocker.hasSubtype("Vampire") && !blocker.hasSubtype("Zombie"); + return !blocker.hasSubtype("Vampire", game) && !blocker.hasSubtype("Zombie", game); } @Override diff --git a/Mage.Sets/src/mage/sets/zendikar/KorDuelist.java b/Mage.Sets/src/mage/sets/zendikar/KorDuelist.java index a9a2d1e76d..a7e11ce554 100644 --- a/Mage.Sets/src/mage/sets/zendikar/KorDuelist.java +++ b/Mage.Sets/src/mage/sets/zendikar/KorDuelist.java @@ -84,7 +84,7 @@ class SourceIsEquiped implements Condition { for (UUID attachmentUUID : attachments) { Permanent attachment = game.getPermanent(attachmentUUID); if (attachment != null) { - if (attachment.getSubtype().contains("Equipment")) { + if (attachment.getSubtype(game).contains("Equipment")) { return true; } } diff --git a/Mage.Sets/src/mage/sets/zendikar/MarshFlats.java b/Mage.Sets/src/mage/sets/zendikar/MarshFlats.java index 31c872f597..edaf14fd4d 100644 --- a/Mage.Sets/src/mage/sets/zendikar/MarshFlats.java +++ b/Mage.Sets/src/mage/sets/zendikar/MarshFlats.java @@ -29,6 +29,7 @@ package mage.sets.zendikar; import java.util.UUID; +import mage.ObjectColor; import mage.constants.CardType; import mage.constants.Rarity; import mage.abilities.common.FetchLandActivatedAbility; @@ -43,6 +44,7 @@ public class MarshFlats extends CardImpl { public MarshFlats(UUID ownerId) { super(ownerId, 219, "Marsh Flats", Rarity.RARE, new CardType[]{CardType.LAND}, null); this.expansionSetCode = "ZEN"; + this.frameColor = new ObjectColor("WB"); this.addAbility(new FetchLandActivatedAbility(new String[] {"Swamp", "Plains"})); } diff --git a/Mage.Sets/src/mage/sets/zendikar/MerfolkWayfinder.java b/Mage.Sets/src/mage/sets/zendikar/MerfolkWayfinder.java index 84efa542d4..93bc0b7f45 100644 --- a/Mage.Sets/src/mage/sets/zendikar/MerfolkWayfinder.java +++ b/Mage.Sets/src/mage/sets/zendikar/MerfolkWayfinder.java @@ -103,7 +103,7 @@ class MerfolkWayfinderEffect extends OneShotEffect { Card card = player.getLibrary().removeFromTop(game); if (card != null) { cardsToReveal.add(card); - if (card.hasSubtype("Island")) { + if (card.hasSubtype("Island", game)) { card.moveToZone(Zone.HAND, source.getSourceId(), game, false); } else { cards.add(card); diff --git a/Mage.Sets/src/mage/sets/zendikar/MistyRainforest.java b/Mage.Sets/src/mage/sets/zendikar/MistyRainforest.java index c49c4847ed..c9a80d3b70 100644 --- a/Mage.Sets/src/mage/sets/zendikar/MistyRainforest.java +++ b/Mage.Sets/src/mage/sets/zendikar/MistyRainforest.java @@ -29,6 +29,7 @@ package mage.sets.zendikar; import java.util.UUID; +import mage.ObjectColor; import mage.constants.CardType; import mage.constants.Rarity; import mage.abilities.common.FetchLandActivatedAbility; @@ -43,6 +44,7 @@ public class MistyRainforest extends CardImpl { public MistyRainforest(UUID ownerId) { super(ownerId, 220, "Misty Rainforest", Rarity.RARE, new CardType[]{CardType.LAND}, null); this.expansionSetCode = "ZEN"; + this.frameColor = new ObjectColor("UG"); this.addAbility(new FetchLandActivatedAbility(new String[] {"Forest", "Island"})); } diff --git a/Mage.Sets/src/mage/sets/zendikar/ScaldingTarn.java b/Mage.Sets/src/mage/sets/zendikar/ScaldingTarn.java index b3a9ecf96c..8c02ba8624 100644 --- a/Mage.Sets/src/mage/sets/zendikar/ScaldingTarn.java +++ b/Mage.Sets/src/mage/sets/zendikar/ScaldingTarn.java @@ -29,6 +29,7 @@ package mage.sets.zendikar; import java.util.UUID; +import mage.ObjectColor; import mage.constants.CardType; import mage.constants.Rarity; import mage.abilities.common.FetchLandActivatedAbility; @@ -43,6 +44,7 @@ public class ScaldingTarn extends CardImpl { public ScaldingTarn(UUID ownerId) { super(ownerId, 223, "Scalding Tarn", Rarity.RARE, new CardType[]{CardType.LAND}, null); this.expansionSetCode = "ZEN"; + this.frameColor = new ObjectColor("UR"); this.addAbility(new FetchLandActivatedAbility(new String[] {"Island", "Mountain"})); } diff --git a/Mage.Sets/src/mage/sets/zendikar/TrapfindersTrick.java b/Mage.Sets/src/mage/sets/zendikar/TrapfindersTrick.java index 15a7088590..93c5e7a1c3 100644 --- a/Mage.Sets/src/mage/sets/zendikar/TrapfindersTrick.java +++ b/Mage.Sets/src/mage/sets/zendikar/TrapfindersTrick.java @@ -91,7 +91,7 @@ class TrapfindersTrickEffect extends OneShotEffect { player.revealCards("Trapfinder's Trick", hand, game); Set cards = hand.getCards(game); for (Card card : cards) { - if (card != null && card.hasSubtype("Trap")) { + if (card != null && card.hasSubtype("Trap", game)) { player.discard(card, source, game); } } diff --git a/Mage.Sets/src/mage/sets/zendikar/ValakutTheMoltenPinnacle.java b/Mage.Sets/src/mage/sets/zendikar/ValakutTheMoltenPinnacle.java index 952d1512c1..61739f0009 100644 --- a/Mage.Sets/src/mage/sets/zendikar/ValakutTheMoltenPinnacle.java +++ b/Mage.Sets/src/mage/sets/zendikar/ValakutTheMoltenPinnacle.java @@ -107,7 +107,7 @@ class ValakutTheMoltenPinnacleTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && permanent.getCardType().contains(CardType.LAND) && permanent.getControllerId().equals(this.getControllerId())) { - if (permanent.hasSubtype("Mountain")) { + if (permanent.hasSubtype("Mountain", game)) { return true; } } diff --git a/Mage.Sets/src/mage/sets/zendikar/VerdantCatacombs.java b/Mage.Sets/src/mage/sets/zendikar/VerdantCatacombs.java index c3776aa3c9..753ce8a6d3 100644 --- a/Mage.Sets/src/mage/sets/zendikar/VerdantCatacombs.java +++ b/Mage.Sets/src/mage/sets/zendikar/VerdantCatacombs.java @@ -29,6 +29,7 @@ package mage.sets.zendikar; import java.util.UUID; +import mage.ObjectColor; import mage.constants.CardType; import mage.constants.Rarity; import mage.abilities.common.FetchLandActivatedAbility; @@ -43,6 +44,7 @@ public class VerdantCatacombs extends CardImpl { public VerdantCatacombs(UUID ownerId) { super(ownerId, 229, "Verdant Catacombs", Rarity.RARE, new CardType[]{CardType.LAND}, null); this.expansionSetCode = "ZEN"; + this.frameColor = new ObjectColor("BG"); this.addAbility(new FetchLandActivatedAbility(new String[] {"Forest", "Swamp"})); } diff --git a/Mage.Tests/replay_pid4548.log b/Mage.Tests/replay_pid4548.log new file mode 100644 index 0000000000..42adf46b25 --- /dev/null +++ b/Mage.Tests/replay_pid4548.log @@ -0,0 +1,2127 @@ +JvmtiExport can_access_local_variables 0 +JvmtiExport can_hotswap_or_post_breakpoint 0 +JvmtiExport can_post_on_exceptions 0 +# 108 ciObject found +ciMethod java/lang/ref/ReferenceQueue reallyPoll ()Ljava/lang/ref/Reference; 9 1 8004 0 256 +ciMethod java/lang/ref/ReferenceQueue poll ()Ljava/lang/ref/Reference; 2081 1 6409 0 -1 +ciMethod sun/misc/VM addFinalRefCount (I)V 4097 1 15988 0 -1 +ciMethodData java/lang/ref/ReferenceQueue poll ()Ljava/lang/ref/Reference; 2 6410 orig 264 72 34 174 107 0 0 0 0 184 251 220 22 0 0 0 0 80 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 77 68 79 32 101 120 116 114 97 32 100 97 116 97 32 108 111 99 107 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 1 0 0 49 192 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 9 0 2 0 0 0 48 0 0 0 255 255 255 255 7 0 4 0 0 0 0 0 data 6 0x40007 0x7 0x20 0x17ff 0x110002 0x7 oops 0 +ciMethodData java/lang/ref/ReferenceQueue reallyPoll ()Ljava/lang/ref/Reference; 2 8004 orig 264 72 34 174 107 0 0 0 0 240 250 220 22 0 0 0 0 0 2 0 0 64 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 77 68 79 32 101 120 116 114 97 32 100 97 116 97 32 108 111 99 107 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 25 250 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 14 0 2 0 0 0 184 0 0 0 255 255 255 255 7 0 6 0 0 0 0 0 data 23 0x60007 0x6 0xb8 0x1f3d 0xf0007 0x1f35 0x38 0x8 0x130003 0x8 0x18 0x340004 0xfffffffffffffffd 0x297ae60 0x1f3a 0x19890300 0x1 0x370007 0x3 0x30 0x1f3a 0x3b0002 0x1f3a oops 2 13 java/lang/ref/Finalizer 15 java/util/WeakHashMap$Entry +instanceKlass org/apache/maven/surefire/common/junit4/JUnit4StackTraceWriter +instanceKlass org/junit/runner/notification/Failure +instanceKlass mage/sets/mirrodin/GolemSkinGauntletsAttachedCount +instanceKlass mage/sets/mirrodin/ElectrostaticBoltDamageValue +instanceKlass mage/sets/mirrodin/DuplicantContinuousEffect$1 +instanceKlass mage/sets/mirrodin/CantBeBlockedByMoreThanOneAttachedEffect$1 +instanceKlass mage/filter/predicate/permanent/AttachedToPredicate +instanceKlass mage/sets/mirage/AsmiraHolyAvengerDynamicValue +instanceKlass mage/sets/mercadianmasques/NetherSpiritCondition +instanceKlass mage/sets/mercadianmasques/LandGrantCondition +instanceKlass mage/sets/masterseditioniv/XenicPoltergeistEffect$1 +instanceKlass mage/sets/mastersedition/TargetPlayerCardsInHandCount +instanceKlass mage/sets/magicorigins/StarfieldOfNyxEffect$1 +instanceKlass mage/sets/magicorigins/SigilOfValorCount +instanceKlass mage/sets/magicorigins/PsychicRebuttalPredicate +instanceKlass mage/sets/magicorigins/NissaSageAnimistMinusSevenEffect$1 +instanceKlass mage/sets/magicorigins/KytheonHeroOfAkrosCondition +instanceKlass mage/sets/magicorigins/PowerToughnessNotEqualPredicate +instanceKlass mage/sets/magicorigins/EmbermawHellionEffect$1 +instanceKlass mage/sets/magic2015/TheChainVeilCondition +instanceKlass mage/sets/magic2015/PolymorphistsJestEffect$1 +instanceKlass mage/sets/magic2015/OpponentOwnsCardInExileCondition +instanceKlass mage/sets/magic2015/FeastOnTheFallenCondition +instanceKlass mage/sets/magic2015/ControlsEachCreatureWithGreatestPowerCondition +instanceKlass mage/sets/magic2015/ControllerLifeLowerThanStrtingLife +instanceKlass mage/sets/magic2014/LifeCondition +instanceKlass mage/sets/magic2014/DismissIntoDreamEffect$1 +instanceKlass mage/sets/magic2014/CreatureCardsInControllerGraveCondition +instanceKlass mage/sets/magic2013/IsBeingCastFromHandCondition +instanceKlass mage/sets/magic2012/SuturedGhoulToughnessCount +instanceKlass mage/sets/magic2012/SuturedGhoulPowerCount +instanceKlass mage/sets/magic2012/GrandAbolisherEffect$1 +instanceKlass mage/sets/magic2011/VolcanicStrengthEffect$1 +instanceKlass mage/sets/magic2011/StormtideLeviathanEffect$1 +instanceKlass mage/sets/magic2011/SerraAscendantEffect$1 +instanceKlass mage/sets/magic2011/GargoyleSentinelEffect$1 +instanceKlass mage/sets/magic2011/DryadsFavorEffect$1 +instanceKlass mage/sets/magic2011/CaptivatingVampireEffect$1 +instanceKlass mage/sets/magic2010/VampireNocturnusCondition +instanceKlass mage/sets/magic2010/RiseFromTheGraveEffect$1 +instanceKlass mage/sets/magic2010/OakenformEffect$1 +instanceKlass mage/sets/magic2010/FaceUpPredicate +instanceKlass mage/sets/magic2010/ConvincingMirageContinousEffect$1 +instanceKlass mage/sets/magic2010/ChandraNalaarXValue +instanceKlass mage/sets/lorwyn/WindbriskHeightsAttackersCondition +instanceKlass mage/sets/lorwyn/SoulbrightFlamekinEffect$ActivationInfo +instanceKlass mage/sets/lorwyn/InnerFlameIgniterEffect$ActivationInfo +instanceKlass mage/sets/lorwyn/DamagedThisTurnPredicate +instanceKlass mage/sets/lorwyn/AshlingThePilgrimEffect$ActivationInfo +instanceKlass mage/sets/limitedalpha/PhantasmalTerrainContinuousEffect$1 +instanceKlass mage/sets/limitedalpha/HalfForestsUpCount +instanceKlass mage/sets/limitedalpha/HalfForestsDownCount +instanceKlass mage/sets/limitedalpha/Conversion$1 +instanceKlass mage/sets/limitedalpha/BurrowingEffect$1 +instanceKlass mage/sets/legions/CallerOfTheClawDynamicValue +instanceKlass mage/sets/legends/BeforeCombatDamageCondition +instanceKlass mage/sets/knightsvsdragons/PaladinOfPrahvTriggeredAbility$1 +instanceKlass mage/sets/khansoftarkir/TargetHasCounterCondition +instanceKlass mage/sets/khansoftarkir/SarkhanTheDragonspeakerEffect$1 +instanceKlass mage/sets/judgment/FiftyOrMoreLifeCondition +instanceKlass mage/sets/journeyintonyx/DictateOfTheTwinGodsEffect$1 +instanceKlass mage/sets/jacevschandra/HostilityEffect$1 +instanceKlass mage/sets/invasion/SpiritOfResistanceCondition +instanceKlass mage/sets/invasion/KangeeAerieKeeperGetKickerXValue +instanceKlass mage/sets/invasion/GetKickerXValue +instanceKlass mage/sets/invasion/DivinePresenceEffect$1 +instanceKlass mage/sets/innistrad/RunechantersPikeValue +instanceKlass mage/sets/innistrad/HasDefenderCondition +instanceKlass mage/sets/innistrad/HalfZombiesCount +instanceKlass mage/sets/innistrad/GutterGrimeCounters +instanceKlass mage/sets/innistrad/GrimoireOfTheDeadEffect2$1 +instanceKlass mage/sets/innistrad/GarrukTheVeilCursedValue +instanceKlass mage/sets/innistrad/EvilTwinPredicate +instanceKlass mage/sets/heroesvsmonsters/OpponentWasDealtDamageCondition +instanceKlass mage/filter/predicate/permanent/EnchantedPredicate +instanceKlass mage/sets/gatecrash/TargetPermanentPowerPlusToughnessCount +instanceKlass mage/sets/gatecrash/SameControllerPredicate +instanceKlass mage/sets/gatecrash/RealmwrightEffect2$1 +instanceKlass mage/sets/gatecrash/greatestPowerCountCreatureYouControl +instanceKlass mage/sets/gatecrash/greatestPowerCount +instanceKlass mage/filter/predicate/mageobject/VariableManaCostPredicate +instanceKlass mage/sets/gatecrash/DyingWishAttachedPermanentPowerCount +instanceKlass mage/sets/gatecrash/CardsInOpponentsGraveyardsCount +instanceKlass mage/sets/gatecrash/CardsInOpponentGraveyardsCount +instanceKlass mage/sets/gatecrash/CardsInEnchantedCreaturesControllerGraveyardCount +instanceKlass mage/sets/gatecrash/CardsInControllerLibraryCount +instanceKlass mage/sets/gatecrash/CantBeBlockedByMoreThanOneAttachedEffect$1 +instanceKlass mage/sets/gatecrash/AttachedPermanentPowerCount +instanceKlass mage/sets/gameday/ScaleguardSentinelsCondition +instanceKlass mage/sets/futuresight/OtherSpellsCastThisTurnCount +instanceKlass mage/sets/futuresight/MagusOfTheMoon$1 +instanceKlass mage/sets/futuresight/MadnessPaidCondition +instanceKlass mage/sets/futuresight/CastWhiteSpellThisTurnCondition +instanceKlass mage/sets/futuresight/AuraAttachedPredicate +instanceKlass mage/sets/shadowmoor/BeseechTheQueenPredicate +instanceKlass mage/sets/fourthedition/TitaniasSongEffect$1 +instanceKlass mage/sets/fourthedition/TargetPermanentToughnessMinus1Value +instanceKlass mage/sets/fourthedition/TargetMatchesFilterCondition +instanceKlass mage/sets/fourthedition/ErgRaidersCondition +instanceKlass mage/sets/fifthedition/CardIdPredicate +instanceKlass mage/sets/modernmasters/PowerIslandPredicate +instanceKlass mage/filter/predicate/permanent/DamagedPlayerThisTurnPredicate +instanceKlass mage/target/targetpointer/FirstTargetPointer +instanceKlass mage/abilities/costs/AdjustingSourceCosts +instanceKlass mage/sets/fifthdawn/MephidrossVampireEffect$1 +instanceKlass mage/sets/fifthdawn/HelmOfKaldraCondition +instanceKlass mage/sets/fifthdawn/GetXValue +instanceKlass mage/abilities/costs/mana/ManaCostImpl$1 +instanceKlass mage/Mana$1 +instanceKlass mage/sets/fifthdawn/ChimericCoilsEffect$1 +instanceKlass mage/sets/fatereforged/YasovaDragonclawPowerLessThanSourcePredicate +instanceKlass mage/abilities/effects/common/continuous/SourceEffect +instanceKlass mage/sets/fatereforged/SagesReveriePredicate +instanceKlass mage/sets/fatereforged/RenownedWeaponsmithCondition +instanceKlass mage/sets/fatereforged/CrucibleOfTheSpiritDragonManaCondition +instanceKlass mage/sets/fatereforged/BloodfireEnforcersCondition +instanceKlass mage/sets/fallenempires/AttachmentByUUIDPredicate +instanceKlass mage/sets/exodus/OathOfLiegesPredicate +instanceKlass mage/sets/exodus/OathOfDruidsPredicate +instanceKlass mage/abilities/effects/PayCostToAttackBlockEffect +instanceKlass mage/sets/exodus/CardsInTargetPlayerHandCount +instanceKlass mage/sets/eventide/OpponentHasNoCardsInHandCondition +instanceKlass mage/sets/eventide/TargetYouPredicate +instanceKlass mage/sets/eventide/DivinityOfPrideCondition +instanceKlass mage/sets/eventide/ChromaUmbraStalkerCount +instanceKlass mage/sets/eventide/ChromaSpringjackShepherdCount +instanceKlass mage/sets/eventide/ChromaSanityGrindingCount +instanceKlass mage/sets/eventide/ChromaPrimalcruxCount +instanceKlass mage/sets/eventide/ChromaOutrageShamanCount +instanceKlass mage/sets/eventide/ChromaLightFromWithinCount +instanceKlass mage/sets/eventide/ChromaHeartlashCinderCount +instanceKlass mage/sets/eventide/CastRedSpellThisTurnCondition +instanceKlass mage/sets/eventide/CastGreenSpellThisTurnCondition +instanceKlass mage/sets/eventide/CastBlueSpellThisTurnCondition +instanceKlass mage/sets/eventide/CastBlackSpellThisTurnCondition +instanceKlass mage/sets/eldritchmoon/ZombiesControlledByTargetPlayerCount +instanceKlass mage/filter/predicate/other/TargetsPermanentPredicate +instanceKlass mage/sets/eldritchmoon/OathOfLilianaCondition +instanceKlass mage/sets/eldritchmoon/LilianaZombiesCount +instanceKlass mage/sets/eldritchmoon/IsBeingCastFromHandCondition +instanceKlass mage/sets/eldritchmoon/InstantOrSorceryCardsInControllerGraveCondition +instanceKlass mage/sets/eldritchmoon/GalvanicBombardmentCardsInControllerGraveyardCount +instanceKlass mage/sets/eldritchmoon/EquippedDealtCombatDamageToCreatureCondition +instanceKlass mage/filter/predicate/other/PlayerPredicate +instanceKlass mage/sets/eldritchmoon/BecomesColorlessLandEffect$1 +instanceKlass mage/sets/dragonsoftarkir/VolcanicVisionReturnToHandTargetEffect$1 +instanceKlass mage/sets/dragonsoftarkir/ShamanOfForgottenWaysManaCondition +instanceKlass mage/sets/dragonsoftarkir/QarsiDeceiverManaCondition +instanceKlass mage/sets/dragonsoftarkir/PlayerCastNonCreatureSpellCondition +instanceKlass mage/sets/dragonsoftarkir/UginPlaneswalkerCardPredicate +instanceKlass mage/sets/dragonsoftarkir/DragonlordsPrerogativeCondition +instanceKlass mage/sets/dragonsoftarkir/DragonCreatureCardPredicate +instanceKlass mage/sets/dragonsoftarkir/DeathbringerRegentCondition +instanceKlass mage/sets/dragonsoftarkir/CountersOnControlledCount +instanceKlass mage/sets/dragonsmaze/TurnBurn$1 +instanceKlass mage/sets/dragonsmaze/TargetPlayerCardsInHandCount +instanceKlass mage/sets/dragonsmaze/MasterOfCrueltiesNoDamageEffect$1 +instanceKlass mage/filter/predicate/other/PlayerIdPredicate +instanceKlass mage/sets/dragonsmaze/BloodBaronOfVizkopaEffect$1 +instanceKlass mage/sets/dissension/SameControllerPredicate +instanceKlass mage/sets/dissension/SacrificedWasCondition +instanceKlass mage/sets/dissension/MightOfTheNephilimValue +instanceKlass mage/sets/dissension/HasAbilityWithTapSymbolPredicate +instanceKlass mage/filter/predicate/mageobject/MonocoloredPredicate +instanceKlass mage/sets/dissension/EnchantedCreatureColorsCount +instanceKlass mage/sets/darksteel/SwordOfLightAndShadowReturnToHandTargetEffect$1 +instanceKlass mage/sets/darksteel/SourceUntappedCondition +instanceKlass mage/abilities/effects/AsThoughManaEffect +instanceKlass mage/sets/darksteel/EmissaryOfDespairCount +instanceKlass mage/sets/darksteel/BurdenOfGreedCount +instanceKlass mage/sets/darkascension/SpellZonePredicate +instanceKlass mage/sets/darkascension/DungeonGeistsEffect$1 +instanceKlass mage/sets/darkascension/CursesAttachedCount +instanceKlass mage/sets/darkascension/AltarOfTheLostManaCondition +instanceKlass mage/sets/conspiracy/TappedLandsCount +instanceKlass mage/sets/conflux/TwiceDevouredGoblins +instanceKlass mage/sets/conflux/testCondition +instanceKlass mage/sets/conflux/ParagonOfTheAmesha$1 +instanceKlass mage/sets/conflux/DragonsoulKnight$1 +instanceKlass mage/sets/conflux/ControlsAnotherArtifactCondition +instanceKlass mage/sets/conflux/CardsInChosenPlayerHandCount +instanceKlass mage/sets/commander2015/SourceControllerExperienceCountersCount +instanceKlass mage/sets/commander2015/MizzixOfTheIzmagnusPredicate +instanceKlass mage/filter/predicate/permanent/CommanderPredicate +instanceKlass mage/sets/commander2015/ArachnogenesisCount +instanceKlass mage/sets/commander2015/AnyaMercilessAngelDynamicValue +instanceKlass mage/sets/commander2015/AnyaMercilessAngelCondition +instanceKlass mage/sets/commander2014/NecromanticSelectionContinuousEffect$1 +instanceKlass mage/filter/predicate/other/FaceDownPredicate +instanceKlass mage/sets/commander2014/GreatestAmountOfDamageWatcher$1 +instanceKlass mage/sets/commander2014/GreatestAmountOfDamageDealtValue +instanceKlass mage/sets/commander2014/BitterFeudEffect$1 +instanceKlass mage/sets/commander2014/BecomesColorlessForestLandEffect$1 +instanceKlass mage/sets/commander2013/TerraRavagerLandCount +instanceKlass mage/counters/CounterType$1 +instanceKlass mage/sets/commander2013/SydriGalvanicGeniusEffect$1 +instanceKlass mage/sets/commander2013/RubiniaSoulsingerCondition +instanceKlass mage/choices/ChoiceImpl +instanceKlass mage/sets/commander2013/MosswortBridgeTotalPowerCondition +instanceKlass mage/sets/commander2013/ChangeMaxAttackedBySourceEffect$1 +instanceKlass mage/sets/commander/VishKalBloodArbiterDynamicValue +instanceKlass mage/filter/predicate/mageobject/AnotherCardPredicate +instanceKlass mage/sets/commander/CardsInTargetOpponentsGraveyardCount +instanceKlass mage/abilities/costs/VariableCostImpl +instanceKlass mage/sets/coldsnap/LightningStormCountCondition +instanceKlass mage/sets/championsofkamigawa/ZuberasDiedDynamicValue +instanceKlass mage/sets/championsofkamigawa/WickedAkubaPredicate +instanceKlass mage/sets/championsofkamigawa/SilentChantZuberaDynamicValue +instanceKlass mage/sets/championsofkamigawa/SiftThroughSandsCondition +instanceKlass mage/sets/championsofkamigawa/TargetYouPredicate +instanceKlass mage/sets/championsofkamigawa/OathkeeperEquippedMatchesFilterCondition +instanceKlass mage/sets/championsofkamigawa/CardsInTargetOpponentHandCondition +instanceKlass mage/sets/championsofkamigawa/CardsInTargetOpponentHandCondition$1 +instanceKlass mage/filter/predicate/permanent/WasDealtDamageThisTurnPredicate +instanceKlass mage/sets/championsofkamigawa/AttachmentAttachedToCardTypePredicate +instanceKlass mage/sets/bornofthegods/MindreaverNamePredicate +instanceKlass mage/sets/bornofthegods/HeroesPodiumLegendaryCount +instanceKlass mage/sets/bornofthegods/HadAnotherCreatureEnterTheBattlefieldCondition +instanceKlass mage/sets/betrayersofkamigawa/UmezawasJitteAbility$1 +instanceKlass mage/filter/predicate/permanent/CounterPredicate +instanceKlass mage/sets/betrayersofkamigawa/TallowispAbilityPredicate +instanceKlass mage/sets/betrayersofkamigawa/SlumberingTora$1 +instanceKlass mage/filter/predicate/permanent/UnblockedPredicate +instanceKlass mage/abilities/condition/common/SourceIsSpellCondition +instanceKlass mage/abilities/costs/AlternativeCost2 +instanceKlass mage/abilities/costs/AlternativeSourceCosts +instanceKlass mage/sets/betrayersofkamigawa/ColorlessConvertedManaCost +instanceKlass mage/abilities/costs/DynamicCost +instanceKlass mage/filter/predicate/permanent/CounterAnyPredicate +instanceKlass mage/sets/betrayersofkamigawa/CallForBloodDynamicValue +instanceKlass mage/sets/battleforzendikar/FirstCastCreatureSpellPredicate +instanceKlass mage/filter/predicate/mageobject/ColorlessPredicate +instanceKlass mage/sets/avacynrestored/VanguardsShieldEffect$1 +instanceKlass mage/sets/avacynrestored/TappedCreaturesControlledByTargetCount +instanceKlass mage/game/command/Emblem +instanceKlass mage/game/command/CommandObject +instanceKlass mage/sets/avacynrestored/SecondSpellPredicate +instanceKlass mage/util/functions/ApplyToMageObject +instanceKlass mage/sets/avacynrestored/HighestLifeTotalAmongOpponentsCount +instanceKlass mage/sets/avacynrestored/GiselaBladeOfGoldnightDoubleDamageEffect$1 +instanceKlass mage/sets/avacynrestored/DreadSlaverContiniousEffect$1 +instanceKlass mage/abilities/mana/conditional/ManaCondition +instanceKlass mage/sets/avacynrestored/CardsInTargetHandCount +instanceKlass mage/sets/arabiannights/SourcePowerGreaterEqualTargetCondition +instanceKlass mage/sets/arabiannights/PyramidsPredicate +instanceKlass mage/sets/arabiannights/PowerLowerEqualSourcePredicate +instanceKlass mage/sets/arabiannights/NoColoredPermanentOpponentCondition +instanceKlass mage/Mana +instanceKlass mage/sets/arabiannights/MagneticMountainEffect$MagneticMountainPredicate +instanceKlass mage/abilities/condition/IntCompareCondition +instanceKlass mage/abilities/effects/PreventionEffect +instanceKlass mage/abilities/effects/CostModificationEffect +instanceKlass mage/filter/predicate/other/OwnerPredicate +instanceKlass mage/abilities/mana/builder/ConditionalManaBuilder +instanceKlass mage/abilities/mana/builder/Builder +instanceKlass mage/filter/predicate/other/ExpansionSetPredicate +instanceKlass mage/filter/predicate/mageobject/NumberOfTargetsPredicate +instanceKlass mage/MageInt +instanceKlass sun/nio/fs/BasicFileAttributesHolder +instanceKlass sun/nio/fs/WindowsDirectoryStream$WindowsDirectoryIterator +instanceKlass sun/nio/fs/WindowsFileAttributes +instanceKlass java/nio/file/attribute/DosFileAttributes +instanceKlass java/nio/file/attribute/BasicFileAttributes +instanceKlass sun/nio/fs/NativeBuffer$Deallocator +instanceKlass sun/nio/fs/NativeBuffer +instanceKlass sun/nio/fs/NativeBuffers +instanceKlass sun/nio/fs/WindowsNativeDispatcher$BackupResult +instanceKlass sun/nio/fs/WindowsNativeDispatcher$CompletionStatus +instanceKlass sun/nio/fs/WindowsNativeDispatcher$AclInformation +instanceKlass sun/nio/fs/WindowsNativeDispatcher$Account +instanceKlass sun/nio/fs/WindowsNativeDispatcher$DiskFreeSpace +instanceKlass sun/nio/fs/WindowsNativeDispatcher$VolumeInformation +instanceKlass sun/nio/fs/WindowsNativeDispatcher$FirstStream +instanceKlass sun/nio/fs/WindowsNativeDispatcher$FirstFile +instanceKlass sun/nio/fs/WindowsNativeDispatcher$1 +instanceKlass sun/nio/fs/WindowsNativeDispatcher +instanceKlass sun/nio/fs/WindowsDirectoryStream +instanceKlass java/nio/file/DirectoryStream +instanceKlass java/nio/file/Files$AcceptAllFilter +instanceKlass java/nio/file/DirectoryStream$Filter +instanceKlass java/nio/file/Files +instanceKlass sun/nio/fs/AbstractPath +instanceKlass sun/nio/fs/Util +instanceKlass sun/nio/fs/WindowsPathParser$Result +instanceKlass sun/nio/fs/WindowsPathParser +instanceKlass java/nio/file/FileSystem +instanceKlass java/nio/file/spi/FileSystemProvider +instanceKlass sun/nio/fs/DefaultFileSystemProvider +instanceKlass java/nio/file/FileSystems$DefaultFileSystemHolder$1 +instanceKlass java/nio/file/FileSystems$DefaultFileSystemHolder +instanceKlass java/nio/file/FileSystems +instanceKlass java/net/NetworkInterface$2 +instanceKlass java/net/DefaultInterface +instanceKlass java/net/InterfaceAddress +instanceKlass java/net/NetworkInterface$1 +instanceKlass java/net/NetworkInterface +instanceKlass sun/security/provider/SeedGenerator$1 +instanceKlass sun/security/provider/SecureRandom$SeederHolder +instanceKlass java/util/UUID$Holder +instanceKlass mage/filter/predicate/Predicates$AndPredicate +instanceKlass mage/filter/FilterMana +instanceKlass mage/filter/predicate/mageobject/NamePredicate +instanceKlass mage/abilities/dynamicvalue/common/ManacostVariableValue +instanceKlass mage/abilities/costs/CostImpl +instanceKlass mage/sets/alarareborn/XPaid +instanceKlass mage/filter/predicate/permanent/TokenPredicate +instanceKlass mage/abilities/effects/AsThoughEffect +instanceKlass mage/abilities/effects/ReplacementEffect +instanceKlass mage/abilities/effects/ContinuousRuleModifyingEffect +instanceKlass mage/sets/alarareborn/LordOfExtinctionDynamicCount +instanceKlass mage/filter/predicate/permanent/TappedPredicate +instanceKlass mage/filter/predicate/IntComparePredicate +instanceKlass mage/filter/predicate/permanent/AttackingPredicate +instanceKlass mage/filter/predicate/permanent/BlockedPredicate +instanceKlass mage/filter/predicate/permanent/BlockingPredicate +instanceKlass mage/sets/alarareborn/DidNotCastCreatureCondition +instanceKlass mage/abilities/MageSingleton +instanceKlass mage/filter/predicate/mageobject/AbilityPredicate +instanceKlass mage/filter/predicate/mageobject/MulticoloredPredicate +instanceKlass mage/sets/alarareborn/AnathemancerCount +instanceKlass org/h2/mvstore/WriteBuffer +instanceKlass mage/sets/alarareborn/AllPlayersLostLifeCount +instanceKlass org/h2/mvstore/Chunk +instanceKlass mage/filter/predicate/mageobject/SupertypePredicate +instanceKlass mage/abilities/dynamicvalue/DynamicValue +instanceKlass mage/watchers/Watcher +instanceKlass mage/filter/predicate/mageobject/SubtypePredicate +instanceKlass mage/abilities/effects/ContinuousEffect +instanceKlass mage/filter/predicate/Predicates$OrPredicate +instanceKlass mage/filter/predicate/permanent/ControllerPredicate +instanceKlass mage/abilities/condition/Condition +instanceKlass mage/filter/predicate/permanent/AnotherPredicate +instanceKlass mage/filter/predicate/ObjectSourcePlayerPredicate +instanceKlass mage/filter/predicate/ObjectPlayerPredicate +instanceKlass mage/filter/predicate/Predicates$NotPredicate +instanceKlass mage/filter/predicate/Predicates +instanceKlass mage/ObjectColor +instanceKlass mage/filter/predicate/mageobject/ColorPredicate +instanceKlass mage/filter/predicate/mageobject/CardTypePredicate +instanceKlass mage/target/targetpointer/TargetPointer +instanceKlass mage/abilities/effects/EffectImpl +instanceKlass mage/abilities/effects/Effect +instanceKlass mage/game/stack/StackObject +instanceKlass mage/game/events/GameEvent +instanceKlass mage/MageObjectImpl +instanceKlass org/h2/mvstore/DataUtils$MapEntry +instanceKlass org/h2/mvstore/Page$PageReference +instanceKlass org/h2/mvstore/db/TransactionStore$TransactionMap$1 +instanceKlass org/h2/util/DateTimeUtils +instanceKlass org/h2/mvstore/db/MVTable$1 +instanceKlass org/h2/index/SpatialIndex +instanceKlass org/h2/engine/Constants +instanceKlass java/text/FieldPosition$Delegate +instanceKlass mage/cards/repository/ExpansionInfo +instanceKlass com/j256/ormlite/support/GeneratedKeyHolder +instanceKlass com/j256/ormlite/misc/BaseDaoEnabled +instanceKlass java/sql/Array +instanceKlass org/h2/result/ResultExternal +instanceKlass org/h2/result/LocalResult +instanceKlass com/j256/ormlite/jdbc/JdbcDatabaseResults +instanceKlass com/j256/ormlite/stmt/SelectIterator +instanceKlass com/j256/ormlite/jdbc/TypeValMapper$1 +instanceKlass com/j256/ormlite/jdbc/TypeValMapper +instanceKlass org/h2/table/Plan$1 +instanceKlass org/h2/table/Plan +instanceKlass org/h2/command/dml/Optimizer +instanceKlass com/j256/ormlite/stmt/mapped/BaseMappedStatement +instanceKlass com/j256/ormlite/stmt/PreparedUpdate +instanceKlass com/j256/ormlite/stmt/PreparedDelete +instanceKlass com/j256/ormlite/stmt/ColumnArg +instanceKlass com/j256/ormlite/stmt/query/ManyClause +instanceKlass com/j256/ormlite/stmt/query/BaseComparison +instanceKlass com/j256/ormlite/stmt/query/Comparison +instanceKlass com/j256/ormlite/stmt/BaseArgumentHolder +instanceKlass com/j256/ormlite/stmt/ArgumentHolder +instanceKlass com/j256/ormlite/stmt/query/NeedsFutureClause +instanceKlass com/j256/ormlite/stmt/query/Clause +instanceKlass com/j256/ormlite/stmt/Where +instanceKlass com/j256/ormlite/stmt/PreparedQuery +instanceKlass com/j256/ormlite/stmt/StatementBuilder +instanceKlass com/j256/ormlite/jdbc/JdbcCompiledStatement +instanceKlass java/nio/DirectByteBuffer$Deallocator +instanceKlass sun/nio/ch/Util$BufferCache +instanceKlass sun/nio/ch/Util$2 +instanceKlass sun/nio/ch/Util +instanceKlass sun/nio/ch/IOStatus +instanceKlass java/nio/channels/spi/AbstractInterruptibleChannel$1 +instanceKlass sun/nio/ch/FileKey +instanceKlass sun/nio/ch/FileLockTable +instanceKlass sun/nio/ch/NativeThread +instanceKlass java/nio/channels/FileLock +instanceKlass sun/nio/ch/FileDispatcherImpl$1 +instanceKlass sun/nio/ch/NativeDispatcher +instanceKlass sun/nio/ch/NativeThreadSet +instanceKlass sun/nio/ch/IOUtil$1 +instanceKlass sun/nio/ch/IOUtil +instanceKlass java/io/RandomAccessFile +instanceKlass java/nio/file/attribute/FileAttribute +instanceKlass org/h2/mvstore/cache/CacheLongKeyLIRS$Entry +instanceKlass org/h2/mvstore/cache/CacheLongKeyLIRS$Segment +instanceKlass org/h2/mvstore/cache/CacheLongKeyLIRS +instanceKlass org/h2/mvstore/FreeSpaceBitSet +instanceKlass org/h2/mvstore/FileStore +instanceKlass org/h2/mvstore/db/MVTableEngine$1 +instanceKlass org/h2/mvstore/MVStoreTool +instanceKlass sun/net/ResourceManager +instanceKlass java/lang/Throwable$PrintStreamOrWriter +instanceKlass java/net/Socket$3 +instanceKlass java/net/Socket$2 +instanceKlass org/h2/value/Transfer +instanceKlass org/h2/util/SmallMap +instanceKlass org/h2/server/TcpServerThread +instanceKlass java/net/Proxy +instanceKlass sun/net/spi/DefaultProxySelector$3 +instanceKlass sun/net/spi/DefaultProxySelector$NonProxyInfo +instanceKlass sun/net/NetProperties$1 +instanceKlass sun/net/NetProperties +instanceKlass sun/net/spi/DefaultProxySelector$1 +instanceKlass java/net/ProxySelector +instanceKlass java/net/SocksSocketImpl$3 +instanceKlass sun/net/util/IPAddressUtil +instanceKlass java/net/Socket +instanceKlass java/net/InetAddress$CacheEntry +instanceKlass sun/net/InetAddressCachePolicy$2 +instanceKlass sun/net/InetAddressCachePolicy$1 +instanceKlass sun/net/InetAddressCachePolicy +instanceKlass org/h2/table/PlanItem +instanceKlass org/h2/index/IndexCondition +instanceKlass org/h2/index/IndexCursor +instanceKlass org/h2/table/TableFilter +instanceKlass org/h2/result/ResultInterface +instanceKlass java/sql/ParameterMetaData +instanceKlass java/sql/ResultSetMetaData +instanceKlass org/h2/expression/ExpressionVisitor +instanceKlass org/h2/engine/FunctionAlias$JavaMethod +instanceKlass org/h2/engine/Session$Savepoint +instanceKlass org/h2/expression/FunctionInfo +instanceKlass java/util/concurrent/atomic/AtomicReference +instanceKlass org/h2/mvstore/StreamStore +instanceKlass org/h2/value/Value$ValueBlob +instanceKlass org/h2/value/Value$ValueClob +instanceKlass org/h2/store/LobStorageMap +instanceKlass org/h2/mvstore/rtree/SpatialKey +instanceKlass org/h2/mvstore/db/TransactionStore$VersionedValue +instanceKlass org/h2/engine/MetaRecord +instanceKlass org/h2/result/Row +instanceKlass org/h2/mvstore/db/TransactionStore$TransactionMap$2 +instanceKlass org/h2/mvstore/db/MVPrimaryIndex$MVStoreCursor +instanceKlass org/h2/util/StatementBuilder +instanceKlass org/h2/table/TableFilter$TableFilterVisitor +instanceKlass org/h2/command/Command +instanceKlass org/h2/expression/ParameterInterface +instanceKlass org/h2/expression/FunctionCall +instanceKlass org/h2/result/ResultTarget +instanceKlass org/h2/command/Prepared +instanceKlass org/h2/command/Parser +instanceKlass org/h2/mvstore/db/TransactionStore$TransactionMap +instanceKlass org/h2/mvstore/db/TransactionStore$Transaction +instanceKlass org/h2/index/IndexType +instanceKlass org/h2/table/IndexColumn +instanceKlass org/h2/index/Cursor +instanceKlass org/h2/mvstore/db/MVIndex +instanceKlass org/h2/index/Index +instanceKlass org/h2/api/ErrorCode +instanceKlass org/h2/util/JdbcUtils +instanceKlass org/h2/value/DataType +instanceKlass org/h2/table/ColumnResolver +instanceKlass org/h2/expression/Expression +instanceKlass org/h2/table/Column +instanceKlass org/h2/command/ddl/CreateTableData +instanceKlass org/h2/engine/UndoLog +instanceKlass org/h2/mvstore/CursorPos +instanceKlass org/h2/mvstore/Cursor +instanceKlass org/h2/mvstore/db/TransactionStore$ArrayType +instanceKlass org/h2/mvstore/db/TransactionStore$VersionedValueType +instanceKlass org/h2/mvstore/type/ObjectDataType$AutoDetectDataType +instanceKlass org/h2/mvstore/type/ObjectDataType +instanceKlass org/h2/mvstore/MVMap$Builder +instanceKlass org/h2/mvstore/db/ValueDataType +instanceKlass org/h2/mvstore/db/TransactionStore +instanceKlass org/h2/mvstore/DataUtils +instanceKlass org/h2/mvstore/Page +instanceKlass org/h2/mvstore/ConcurrentArrayList +instanceKlass org/h2/mvstore/type/StringDataType +instanceKlass org/h2/mvstore/MVMap$MapBuilder +instanceKlass org/h2/mvstore/MVStore +instanceKlass org/h2/mvstore/type/DataType +instanceKlass org/h2/mvstore/db/MVTableEngine$Store +instanceKlass org/h2/mvstore/MVStore$Builder +instanceKlass org/h2/engine/DbObjectBase +instanceKlass org/h2/mvstore/db/MVTableEngine +instanceKlass org/h2/api/TableEngine +instanceKlass java/net/Inet6Address$Inet6AddressHolder +instanceKlass sun/net/NetHooks +instanceKlass java/net/Inet4AddressImpl +instanceKlass java/net/InetAddress$2 +instanceKlass sun/net/spi/nameservice/NameService +instanceKlass java/net/Inet6AddressImpl +instanceKlass java/net/InetAddressImpl +instanceKlass java/net/InetAddressImplFactory +instanceKlass java/net/InetAddress$Cache +instanceKlass java/net/InetAddress$InetAddressHolder +instanceKlass java/net/InetAddress$1 +instanceKlass java/net/InetSocketAddress$InetSocketAddressHolder +instanceKlass java/net/InetAddress +instanceKlass sun/misc/FloatingDecimal$ASCIIToBinaryBuffer +instanceKlass java/net/PlainSocketImpl$1 +instanceKlass java/net/AbstractPlainSocketImpl$1 +instanceKlass java/net/SocketImpl +instanceKlass java/net/SocketOptions +instanceKlass java/net/SocksConsts +instanceKlass java/net/ServerSocket +instanceKlass java/net/SocketAddress +instanceKlass org/h2/util/NetUtils +instanceKlass org/h2/server/TcpServer +instanceKlass org/h2/server/Service +instanceKlass org/h2/util/Tool +instanceKlass org/h2/server/ShutdownHandler +instanceKlass sun/util/locale/provider/TimeZoneNameUtility$TimeZoneNameGetter +instanceKlass sun/util/locale/provider/TimeZoneNameUtility +instanceKlass sun/nio/cs/Surrogate +instanceKlass sun/nio/cs/Surrogate$Parser +instanceKlass org/h2/util/IOUtils +instanceKlass sun/security/provider/ByteArrayAccess +instanceKlass sun/security/provider/SeedGenerator +instanceKlass org/h2/util/MathUtils$1 +instanceKlass sun/security/jca/GetInstance$Instance +instanceKlass java/security/MessageDigestSpi +instanceKlass java/security/Provider$UString +instanceKlass java/security/Provider$Service +instanceKlass sun/security/provider/NativePRNG$NonBlocking +instanceKlass sun/security/provider/NativePRNG$Blocking +instanceKlass sun/security/provider/NativePRNG +instanceKlass sun/security/provider/SunEntries$1 +instanceKlass sun/security/provider/SunEntries +instanceKlass sun/security/jca/ProviderConfig$2 +instanceKlass java/security/Security$1 +instanceKlass java/security/Security +instanceKlass sun/security/jca/ProviderList$2 +instanceKlass sun/misc/FDBigInteger +instanceKlass sun/misc/FloatingDecimal$PreparedASCIIToBinaryBuffer +instanceKlass sun/misc/FloatingDecimal$ASCIIToBinaryConverter +instanceKlass sun/misc/FloatingDecimal$BinaryToASCIIBuffer +instanceKlass sun/misc/FloatingDecimal$ExceptionalBinaryToASCIIBuffer +instanceKlass sun/misc/FloatingDecimal$BinaryToASCIIConverter +instanceKlass sun/misc/FloatingDecimal +instanceKlass java/security/Provider$EngineDescription +instanceKlass java/security/Provider$ServiceKey +instanceKlass sun/security/jca/ProviderConfig +instanceKlass sun/security/jca/ProviderList +instanceKlass sun/security/jca/Providers +instanceKlass sun/security/jca/GetInstance +instanceKlass java/security/SecureRandomSpi +instanceKlass org/h2/message/Trace +instanceKlass org/h2/message/TraceSystem +instanceKlass org/h2/message/TraceWriter +instanceKlass org/h2/util/TempFileDeleter +instanceKlass org/h2/engine/Mode +instanceKlass org/h2/util/BitField +instanceKlass org/h2/schema/SchemaObject +instanceKlass org/h2/engine/DbObject +instanceKlass org/h2/result/SearchRow +instanceKlass org/h2/engine/Database +instanceKlass org/h2/compress/CompressLZF +instanceKlass org/h2/compress/Compressor +instanceKlass org/h2/store/fs/FileMemData +instanceKlass java/nio/channels/spi/AbstractInterruptibleChannel +instanceKlass java/nio/channels/InterruptibleChannel +instanceKlass java/nio/channels/ScatteringByteChannel +instanceKlass java/nio/channels/GatheringByteChannel +instanceKlass java/nio/channels/SeekableByteChannel +instanceKlass java/nio/channels/ByteChannel +instanceKlass java/nio/channels/WritableByteChannel +instanceKlass java/nio/channels/ReadableByteChannel +instanceKlass java/nio/channels/Channel +instanceKlass org/h2/store/fs/FilePath +instanceKlass org/h2/store/fs/FileUtils +instanceKlass org/h2/store/FileLock +instanceKlass org/h2/engine/Engine +instanceKlass org/h2/engine/SessionFactory +instanceKlass org/h2/command/CommandInterface +instanceKlass org/h2/store/LobStorageInterface +instanceKlass org/h2/engine/SessionWithState +instanceKlass org/h2/engine/SessionInterface +instanceKlass org/h2/store/DataHandler +instanceKlass org/h2/value/CompareMode +instanceKlass org/h2/util/StringUtils +instanceKlass org/h2/engine/SettingsBase +instanceKlass org/h2/util/MathUtils +instanceKlass org/h2/engine/SysProperties +instanceKlass org/h2/command/dml/SetTypes +instanceKlass org/h2/engine/ConnectionInfo +instanceKlass java/sql/CallableStatement +instanceKlass java/sql/NClob +instanceKlass java/sql/Clob +instanceKlass java/sql/Blob +instanceKlass org/h2/value/Value +instanceKlass java/sql/ResultSet +instanceKlass java/sql/DatabaseMetaData +instanceKlass java/sql/PreparedStatement +instanceKlass java/sql/Statement +instanceKlass org/h2/message/TraceObject +instanceKlass org/h2/util/New +instanceKlass org/h2/util/Utils +instanceKlass org/h2/upgrade/DbUpgrade +instanceKlass com/j256/ormlite/misc/VersionUtils +instanceKlass com/j256/ormlite/jdbc/JdbcDatabaseConnection$OneLongWrapper +instanceKlass com/j256/ormlite/support/DatabaseResults +instanceKlass java/sql/Savepoint +instanceKlass com/j256/ormlite/support/CompiledStatement +instanceKlass com/j256/ormlite/db/BaseDatabaseType$1 +instanceKlass com/j256/ormlite/dao/RawRowMapper +instanceKlass com/j256/ormlite/dao/GenericRawResults +instanceKlass com/j256/ormlite/stmt/StatementExecutor +instanceKlass com/j256/ormlite/field/DataPersisterManager +instanceKlass com/j256/ormlite/field/DatabaseField +instanceKlass com/j256/ormlite/field/types/BaseDateType$DateStringFormatConfig +instanceKlass com/j256/ormlite/field/DataPersister +instanceKlass com/j256/ormlite/field/DatabaseFieldConfig +instanceKlass com/j256/ormlite/dao/BaseForeignCollection +instanceKlass com/j256/ormlite/table/DatabaseTableConfig +instanceKlass com/j256/ormlite/table/TableInfo +instanceKlass com/j256/ormlite/dao/CloseableIterator +instanceKlass com/j256/ormlite/stmt/PreparedStmt +instanceKlass com/j256/ormlite/stmt/GenericRowMapper +instanceKlass com/j256/ormlite/dao/ObjectCache +instanceKlass com/j256/ormlite/dao/ForeignCollection +instanceKlass com/j256/ormlite/dao/CloseableWrappedIterable +instanceKlass com/j256/ormlite/dao/BaseDaoImpl +instanceKlass com/j256/ormlite/table/DatabaseTable +instanceKlass com/j256/ormlite/dao/DaoManager$ClassConnectionSource +instanceKlass com/j256/ormlite/dao/Dao +instanceKlass com/j256/ormlite/dao/CloseableIterable +instanceKlass com/j256/ormlite/dao/DaoManager +instanceKlass com/j256/ormlite/field/FieldType +instanceKlass com/j256/ormlite/table/TableUtils +instanceKlass mage/cards/repository/DatabaseVersion +instanceKlass mage/cards/repository/RepositoryUtil +instanceKlass java/sql/DriverInfo +instanceKlass java/sql/DriverManager$2 +instanceKlass java/sql/DriverManager$1 +instanceKlass java/sql/DriverManager +instanceKlass java/sql/Connection +instanceKlass java/sql/Wrapper +instanceKlass org/h2/Driver +instanceKlass java/sql/Driver +instanceKlass com/j256/ormlite/field/BaseFieldConverter +instanceKlass com/j256/ormlite/field/FieldConverter +instanceKlass com/j256/ormlite/db/BaseDatabaseType +instanceKlass com/j256/ormlite/db/DatabaseType +instanceKlass com/j256/ormlite/db/DatabaseTypeUtils +instanceKlass com/j256/ormlite/logger/Logger +instanceKlass com/j256/ormlite/logger/Slf4jLoggingLog$1 +instanceKlass java/util/concurrent/ConcurrentHashMap$Traverser +instanceKlass org/slf4j/helpers/NamedLoggerBase +instanceKlass org/slf4j/spi/LocationAwareLogger +instanceKlass org/slf4j/impl/Log4jLoggerFactory +instanceKlass org/slf4j/impl/StaticLoggerBinder +instanceKlass org/slf4j/spi/LoggerFactoryBinder +instanceKlass com/j256/ormlite/logger/Slf4jLoggingLog +instanceKlass org/slf4j/helpers/NOPLoggerFactory +instanceKlass org/slf4j/Logger +instanceKlass org/slf4j/helpers/SubstituteLoggerFactory +instanceKlass org/slf4j/ILoggerFactory +instanceKlass org/slf4j/LoggerFactory +instanceKlass com/j256/ormlite/logger/LocalLog +instanceKlass com/j256/ormlite/logger/Log +instanceKlass com/j256/ormlite/logger/LoggerFactory +instanceKlass com/j256/ormlite/jdbc/JdbcDatabaseConnection +instanceKlass com/j256/ormlite/support/DatabaseConnection +instanceKlass com/j256/ormlite/support/BaseConnectionSource +instanceKlass com/j256/ormlite/support/ConnectionSource +instanceKlass java/util/EnumMap$1 +instanceKlass java/util/Random +instanceKlass java/util/zip/ZipUtils +instanceKlass java/net/URLEncoder +instanceKlass java/net/URLDecoder +instanceKlass mage/util/ClassScanner +instanceKlass mage/cards/ExpansionSet +instanceKlass mage/cards/repository/CardScanner +instanceKlass mage/util/Copier +instanceKlass mage/game/match/MatchImpl +instanceKlass org/apache/log4j/spi/LocationInfo +instanceKlass java/text/DontCareFieldPosition$1 +instanceKlass java/text/Format$FieldDelegate +instanceKlass java/net/URI$Parser +instanceKlass mage/server/game/GameFactory +instanceKlass com/sun/org/apache/xerces/internal/impl/Constants$ArrayEnumeration +instanceKlass java/util/ArrayList$SubList$1 +instanceKlass com/sun/org/apache/xerces/internal/impl/Constants +instanceKlass com/sun/org/apache/xerces/internal/parsers/AbstractSAXParser$LocatorProxy +instanceKlass org/xml/sax/ext/Locator2 +instanceKlass com/sun/org/apache/xerces/internal/util/XMLSymbols +instanceKlass com/sun/org/apache/xerces/internal/util/XMLChar +instanceKlass com/sun/xml/internal/stream/Entity +instanceKlass com/sun/xml/internal/stream/util/BufferAllocator +instanceKlass com/sun/xml/internal/stream/util/ThreadLocalBufferAllocator +instanceKlass com/sun/org/apache/xerces/internal/util/URI +instanceKlass com/sun/org/apache/xerces/internal/utils/XMLLimitAnalyzer +instanceKlass com/sun/org/apache/xerces/internal/xni/parser/XMLInputSource +instanceKlass com/sun/org/apache/xerces/internal/util/ErrorHandlerWrapper +instanceKlass com/sun/org/apache/xerces/internal/xni/parser/XMLErrorHandler +instanceKlass com/sun/xml/bind/v2/runtime/unmarshaller/TagName +instanceKlass com/sun/xml/bind/v2/runtime/unmarshaller/SAXConnector +instanceKlass com/sun/org/apache/xerces/internal/parsers/AbstractSAXParser$AttributesProxy +instanceKlass org/xml/sax/ext/Attributes2 +instanceKlass org/xml/sax/Attributes +instanceKlass org/xml/sax/AttributeList +instanceKlass com/sun/org/apache/xerces/internal/util/PropertyState +instanceKlass com/sun/org/apache/xerces/internal/util/FeatureState +instanceKlass com/sun/org/apache/xerces/internal/impl/msg/XMLMessageFormatter +instanceKlass com/sun/org/apache/xerces/internal/util/MessageFormatter +instanceKlass com/sun/org/apache/xerces/internal/impl/XMLVersionDetector +instanceKlass com/sun/org/apache/xerces/internal/impl/validation/ValidationManager +instanceKlass com/sun/org/apache/xerces/internal/impl/dv/dtd/NMTOKENDatatypeValidator +instanceKlass com/sun/org/apache/xerces/internal/impl/dv/dtd/NOTATIONDatatypeValidator +instanceKlass com/sun/org/apache/xerces/internal/impl/dv/dtd/ENTITYDatatypeValidator +instanceKlass com/sun/org/apache/xerces/internal/impl/dv/dtd/ListDatatypeValidator +instanceKlass com/sun/org/apache/xerces/internal/impl/dv/dtd/IDREFDatatypeValidator +instanceKlass com/sun/org/apache/xerces/internal/impl/dv/dtd/IDDatatypeValidator +instanceKlass com/sun/org/apache/xerces/internal/impl/dv/dtd/StringDatatypeValidator +instanceKlass com/sun/org/apache/xerces/internal/impl/dv/DatatypeValidator +instanceKlass com/sun/org/apache/xerces/internal/impl/dv/DTDDVFactory +instanceKlass com/sun/org/apache/xerces/internal/impl/dtd/DTDGrammarBucket +instanceKlass com/sun/org/apache/xerces/internal/impl/dtd/XMLAttributeDecl +instanceKlass com/sun/org/apache/xerces/internal/impl/dtd/XMLSimpleType +instanceKlass com/sun/org/apache/xerces/internal/impl/dtd/XMLElementDecl +instanceKlass com/sun/org/apache/xerces/internal/impl/validation/ValidationState +instanceKlass com/sun/org/apache/xerces/internal/impl/dv/ValidationContext +instanceKlass com/sun/org/apache/xerces/internal/impl/dtd/XMLDTDValidator +instanceKlass com/sun/org/apache/xerces/internal/impl/RevalidationHandler +instanceKlass com/sun/org/apache/xerces/internal/impl/dtd/XMLDTDValidatorFilter +instanceKlass com/sun/org/apache/xerces/internal/xni/parser/XMLDocumentFilter +instanceKlass com/sun/org/apache/xerces/internal/impl/dtd/XMLEntityDecl +instanceKlass com/sun/org/apache/xerces/internal/impl/dtd/XMLDTDProcessor +instanceKlass com/sun/org/apache/xerces/internal/xni/parser/XMLDTDContentModelFilter +instanceKlass com/sun/org/apache/xerces/internal/xni/parser/XMLDTDFilter +instanceKlass com/sun/org/apache/xerces/internal/xni/parser/XMLDTDScanner +instanceKlass com/sun/org/apache/xerces/internal/xni/parser/XMLDTDContentModelSource +instanceKlass com/sun/org/apache/xerces/internal/xni/parser/XMLDTDSource +instanceKlass com/sun/org/apache/xerces/internal/xni/grammars/XMLDTDDescription +instanceKlass com/sun/org/apache/xerces/internal/xni/grammars/XMLGrammarDescription +instanceKlass com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl$TrailingMiscDriver +instanceKlass com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl$PrologDriver +instanceKlass com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl$XMLDeclDriver +instanceKlass com/sun/org/apache/xerces/internal/util/NamespaceSupport +instanceKlass com/sun/org/apache/xerces/internal/xni/NamespaceContext +instanceKlass com/sun/org/apache/xerces/internal/util/XMLAttributesImpl$Attribute +instanceKlass com/sun/org/apache/xerces/internal/util/XMLAttributesImpl +instanceKlass com/sun/org/apache/xerces/internal/xni/XMLAttributes +instanceKlass com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl$FragmentContentDriver +instanceKlass com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl$Driver +instanceKlass com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl$ElementStack2 +instanceKlass com/sun/org/apache/xerces/internal/xni/QName +instanceKlass com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl$ElementStack +instanceKlass com/sun/org/apache/xerces/internal/xni/XMLString +instanceKlass com/sun/org/apache/xerces/internal/impl/XMLScanner +instanceKlass com/sun/xml/internal/stream/XMLBufferListener +instanceKlass com/sun/org/apache/xerces/internal/impl/XMLEntityHandler +instanceKlass com/sun/org/apache/xerces/internal/xni/parser/XMLDocumentScanner +instanceKlass com/sun/org/apache/xerces/internal/xni/parser/XMLDocumentSource +instanceKlass com/sun/org/apache/xerces/internal/impl/XMLErrorReporter +instanceKlass com/sun/org/apache/xerces/internal/impl/XMLEntityScanner +instanceKlass com/sun/org/apache/xerces/internal/xni/XMLLocator +instanceKlass com/sun/xml/internal/stream/XMLEntityStorage +instanceKlass com/sun/org/apache/xerces/internal/impl/XMLEntityManager$CharacterBuffer +instanceKlass com/sun/org/apache/xerces/internal/impl/XMLEntityManager$CharacterBufferPool +instanceKlass com/sun/org/apache/xerces/internal/util/AugmentationsImpl$AugmentationsItemsContainer +instanceKlass com/sun/org/apache/xerces/internal/util/AugmentationsImpl +instanceKlass com/sun/org/apache/xerces/internal/xni/Augmentations +instanceKlass com/sun/org/apache/xerces/internal/util/XMLResourceIdentifierImpl +instanceKlass com/sun/org/apache/xerces/internal/xni/XMLResourceIdentifier +instanceKlass com/sun/org/apache/xerces/internal/impl/XMLEntityManager +instanceKlass com/sun/org/apache/xerces/internal/xni/parser/XMLEntityResolver +instanceKlass com/sun/org/apache/xerces/internal/xni/parser/XMLComponent +instanceKlass com/sun/org/apache/xerces/internal/util/SymbolTable$Entry +instanceKlass com/sun/org/apache/xerces/internal/util/SymbolTable +instanceKlass com/sun/org/apache/xerces/internal/util/ParserConfigurationSettings +instanceKlass com/sun/org/apache/xerces/internal/parsers/XML11Configurable +instanceKlass com/sun/org/apache/xerces/internal/xni/parser/XMLPullParserConfiguration +instanceKlass com/sun/org/apache/xerces/internal/xni/parser/XMLParserConfiguration +instanceKlass com/sun/org/apache/xerces/internal/xni/parser/XMLComponentManager +instanceKlass com/sun/org/apache/xerces/internal/parsers/XMLParser +instanceKlass com/sun/org/apache/xerces/internal/xni/XMLDTDContentModelHandler +instanceKlass com/sun/org/apache/xerces/internal/xni/XMLDTDHandler +instanceKlass com/sun/org/apache/xerces/internal/xni/XMLDocumentHandler +instanceKlass org/xml/sax/XMLReader +instanceKlass org/xml/sax/Parser +instanceKlass com/sun/org/apache/xerces/internal/utils/XMLSecurityPropertyManager +instanceKlass com/sun/org/apache/xerces/internal/utils/SecuritySupport$8 +instanceKlass com/sun/org/apache/xerces/internal/utils/SecuritySupport$4 +instanceKlass com/sun/org/apache/xerces/internal/utils/SecuritySupport +instanceKlass com/sun/org/apache/xerces/internal/utils/XMLSecurityManager +instanceKlass javax/xml/parsers/SAXParser +instanceKlass com/sun/org/apache/xerces/internal/xs/PSVIProvider +instanceKlass com/sun/org/apache/xerces/internal/jaxp/JAXPConstants +instanceKlass javax/xml/parsers/SecuritySupport$1 +instanceKlass javax/xml/parsers/FactoryFinder$1 +instanceKlass javax/xml/parsers/SecuritySupport$5 +instanceKlass javax/xml/parsers/SecuritySupport$2 +instanceKlass javax/xml/parsers/SecuritySupport +instanceKlass javax/xml/parsers/FactoryFinder +instanceKlass javax/xml/parsers/SAXParserFactory +instanceKlass org/xml/sax/InputSource +instanceKlass com/sun/xml/bind/v2/runtime/unmarshaller/UnmarshallingContext$State +instanceKlass com/sun/xml/bind/v2/runtime/unmarshaller/Scope +instanceKlass com/sun/xml/bind/v2/runtime/unmarshaller/LocatorExWrapper +instanceKlass org/xml/sax/helpers/LocatorImpl +instanceKlass java/util/concurrent/Callable +instanceKlass javax/xml/bind/helpers/DefaultValidationEventHandler +instanceKlass org/xml/sax/helpers/DefaultHandler +instanceKlass org/xml/sax/DTDHandler +instanceKlass org/xml/sax/EntityResolver +instanceKlass com/sun/xml/bind/IDResolver +instanceKlass javax/xml/bind/UnmarshallerHandler +instanceKlass com/sun/xml/bind/v2/runtime/unmarshaller/ValidatingUnmarshaller +instanceKlass com/sun/xml/bind/v2/runtime/Coordinator +instanceKlass com/sun/xml/bind/v2/runtime/unmarshaller/XmlVisitor$TextPredictor +instanceKlass com/sun/xml/bind/v2/runtime/unmarshaller/LocatorEx +instanceKlass com/sun/xml/bind/v2/runtime/unmarshaller/XmlVisitor +instanceKlass org/xml/sax/ContentHandler +instanceKlass javax/xml/bind/helpers/AbstractUnmarshallerImpl +instanceKlass javax/xml/bind/ValidationEventHandler +instanceKlass com/sun/xml/bind/v2/runtime/NameList +instanceKlass com/sun/xml/bind/v2/runtime/unmarshaller/ChildLoader +instanceKlass com/sun/xml/bind/v2/runtime/property/ArrayERProperty$ReceiverImpl +instanceKlass com/sun/xml/bind/v2/runtime/unmarshaller/StructureLoader$1 +instanceKlass com/sun/xml/bind/v2/runtime/property/UnmarshallerChain +instanceKlass javax/xml/bind/annotation/W3CDomHandler +instanceKlass javax/xml/bind/annotation/DomHandler +instanceKlass com/sun/xml/bind/v2/runtime/ElementBeanInfoImpl$1 +instanceKlass com/sun/xml/bind/v2/runtime/unmarshaller/Intercepter +instanceKlass javax/xml/bind/JAXBElement +instanceKlass com/sun/xml/bind/v2/runtime/property/TagAndType +instanceKlass com/sun/xml/bind/v2/runtime/LifecycleMethods +instanceKlass com/sun/xml/bind/v2/runtime/reflect/opt/OptimizedTransducedAccessorFactory +instanceKlass com/sun/xml/bind/v2/runtime/reflect/TransducedAccessor +instanceKlass com/sun/xml/bind/v2/runtime/Name +instanceKlass com/sun/xml/bind/v2/runtime/reflect/opt/Injector$1 +instanceKlass java/util/concurrent/locks/ReentrantReadWriteLock$WriteLock +instanceKlass java/util/concurrent/locks/ReentrantReadWriteLock$ReadLock +instanceKlass sun/nio/ch/Interruptible +instanceKlass java/util/concurrent/locks/ReentrantReadWriteLock +instanceKlass java/util/concurrent/locks/ReadWriteLock +instanceKlass com/sun/xml/bind/v2/runtime/reflect/opt/Injector +instanceKlass com/sun/xml/bind/v2/runtime/reflect/opt/AccessorInjector +instanceKlass com/sun/xml/bind/v2/runtime/reflect/opt/Ref +instanceKlass com/sun/xml/bind/v2/runtime/reflect/opt/Bean +instanceKlass com/sun/xml/bind/v2/bytecode/ClassTailor +instanceKlass com/sun/xml/bind/v2/runtime/reflect/opt/OptimizedAccessorFactory +instanceKlass com/sun/xml/bind/v2/ClassFactory +instanceKlass com/sun/xml/bind/v2/runtime/reflect/Lister$2 +instanceKlass java/util/Collections$SynchronizedMap +instanceKlass com/sun/xml/bind/v2/runtime/reflect/ListIterator +instanceKlass com/sun/xml/bind/v2/runtime/reflect/Lister +instanceKlass com/sun/xml/bind/v2/runtime/property/PropertyFactory$1 +instanceKlass com/sun/xml/bind/v2/runtime/property/PropertyFactory +instanceKlass com/sun/xml/bind/v2/runtime/property/PropertyImpl +instanceKlass org/xml/sax/Locator +instanceKlass com/sun/xml/bind/v2/runtime/property/Property +instanceKlass com/sun/xml/bind/v2/runtime/property/StructureLoaderBuilder +instanceKlass com/sun/xml/bind/v2/runtime/unmarshaller/Loader +instanceKlass com/sun/xml/bind/v2/runtime/FilterTransducer +instanceKlass com/sun/xml/bind/v2/util/FlattenIterator +instanceKlass javax/xml/bind/annotation/XmlSchemaType$DEFAULT +instanceKlass com/sun/xml/bind/v2/TODO +instanceKlass java/util/NavigableSet +instanceKlass java/util/SortedSet +instanceKlass com/sun/xml/bind/annotation/XmlLocation +instanceKlass javax/xml/bind/annotation/XmlSchemaTypes +instanceKlass javax/xml/bind/annotation/XmlSeeAlso +instanceKlass com/sun/xml/bind/v2/model/nav/ParameterizedTypeImpl +instanceKlass com/sun/xml/bind/v2/model/nav/ReflectionNavigator$BinderArg +instanceKlass javax/xml/bind/annotation/adapters/XmlJavaTypeAdapters +instanceKlass sun/reflect/generics/tree/TypeVariableSignature +instanceKlass com/sun/xml/bind/v2/model/impl/Util +instanceKlass com/sun/xml/bind/v2/model/runtime/RuntimeTypeRef +instanceKlass com/sun/xml/bind/v2/model/impl/TypeRefImpl +instanceKlass com/sun/xml/bind/v2/model/core/TypeRef +instanceKlass com/sun/xml/bind/v2/model/impl/ClassInfoImpl$1 +instanceKlass com/sun/xml/bind/v2/model/impl/FieldPropertySeed +instanceKlass com/sun/xml/bind/v2/model/impl/RuntimeClassInfoImpl$RuntimePropertySeed +instanceKlass java/lang/Short$ShortCache +instanceKlass java/lang/Character$CharacterCache +instanceKlass java/lang/Byte$ByteCache +instanceKlass javax/xml/bind/annotation/XmlElement$DEFAULT +instanceKlass com/sun/xml/bind/AccessorFactoryImpl +instanceKlass com/sun/xml/bind/InternalAccessorFactory +instanceKlass javax/xml/bind/annotation/XmlAccessorOrder +instanceKlass java/lang/Package$1PackageInfoProxy +instanceKlass com/sun/xml/bind/annotation/OverrideAnnotationOf +instanceKlass javax/xml/bind/annotation/XmlMixed +instanceKlass javax/xml/bind/annotation/XmlAnyElement +instanceKlass javax/xml/bind/annotation/XmlElements +instanceKlass javax/xml/bind/annotation/XmlAnyAttribute +instanceKlass javax/xml/bind/annotation/XmlList +instanceKlass javax/xml/bind/annotation/XmlElementWrapper +instanceKlass javax/xml/bind/annotation/XmlAttachmentRef +instanceKlass javax/xml/bind/annotation/XmlMimeType +instanceKlass javax/xml/bind/annotation/XmlInlineBinaryData +instanceKlass javax/xml/bind/annotation/XmlIDREF +instanceKlass javax/xml/bind/annotation/XmlID +instanceKlass javax/xml/bind/annotation/adapters/XmlJavaTypeAdapter +instanceKlass com/sun/xml/bind/AccessorFactory +instanceKlass com/sun/xml/bind/v2/model/runtime/RuntimeReferencePropertyInfo +instanceKlass com/sun/xml/bind/v2/model/runtime/RuntimeAttributePropertyInfo +instanceKlass com/sun/xml/bind/v2/model/core/AttributePropertyInfo +instanceKlass com/sun/xml/bind/v2/model/runtime/RuntimeElementPropertyInfo +instanceKlass com/sun/xml/bind/v2/model/core/ElementPropertyInfo +instanceKlass com/sun/xml/bind/v2/model/runtime/RuntimeMapPropertyInfo +instanceKlass com/sun/xml/bind/v2/model/core/MapPropertyInfo +instanceKlass com/sun/xml/bind/v2/runtime/reflect/Accessor +instanceKlass com/sun/xml/bind/v2/runtime/unmarshaller/Receiver +instanceKlass com/sun/xml/bind/v2/model/runtime/RuntimeValuePropertyInfo +instanceKlass com/sun/xml/bind/v2/model/runtime/RuntimeNonElementRef +instanceKlass com/sun/xml/bind/v2/model/runtime/RuntimePropertyInfo +instanceKlass com/sun/xml/bind/v2/model/core/ValuePropertyInfo +instanceKlass com/sun/xml/bind/v2/model/core/NonElementRef +instanceKlass com/sun/xml/bind/v2/model/impl/PropertySeed +instanceKlass com/sun/xml/bind/v2/model/impl/DummyPropertyInfo +instanceKlass com/sun/xml/bind/v2/model/core/ReferencePropertyInfo +instanceKlass com/sun/xml/bind/v2/model/impl/PropertyInfoImpl +instanceKlass com/sun/xml/bind/v2/model/core/PropertyInfo +instanceKlass com/sun/xml/bind/v2/model/annotation/AnnotationSource +instanceKlass javax/xml/bind/annotation/XmlType$DEFAULT +instanceKlass javax/xml/bind/annotation/XmlAccessorType +instanceKlass com/sun/xml/bind/v2/model/annotation/MethodLocatable +instanceKlass mage/server/util/config/Server +instanceKlass mage/server/util/config/Config +instanceKlass mage/server/util/config/DeckTypes +instanceKlass mage/server/util/config/GameTypes +instanceKlass mage/server/util/config/DraftCubes +instanceKlass mage/server/util/config/TournamentTypes +instanceKlass mage/server/util/config/PlayerTypes +instanceKlass com/sun/xml/bind/v2/model/impl/RegistryInfoImpl +instanceKlass javax/xml/bind/annotation/XmlValue +instanceKlass javax/xml/bind/annotation/XmlType +instanceKlass javax/xml/bind/annotation/XmlTransient +instanceKlass javax/xml/bind/annotation/XmlSchemaType +instanceKlass javax/xml/bind/annotation/XmlRootElement +instanceKlass javax/xml/bind/annotation/XmlEnum +instanceKlass javax/xml/bind/annotation/XmlElementRefs +instanceKlass javax/xml/bind/annotation/XmlElementRef +instanceKlass javax/xml/bind/annotation/XmlElementDecl +instanceKlass javax/xml/bind/annotation/XmlElement +instanceKlass javax/xml/bind/annotation/XmlAttribute +instanceKlass com/sun/xml/bind/v2/model/annotation/Quick +instanceKlass com/sun/xml/bind/v2/model/annotation/Init +instanceKlass com/sun/xml/bind/v2/model/annotation/LocatableAnnotation +instanceKlass javax/xml/bind/annotation/XmlRegistry +instanceKlass com/sun/xml/bind/v2/model/core/Ref +instanceKlass com/sun/xml/bind/api/CompositeStructure +instanceKlass com/sun/xml/bind/v2/runtime/IllegalAnnotationsException$Builder +instanceKlass java/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$UnmodifiableEntry +instanceKlass java/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$1 +instanceKlass javax/xml/bind/ValidationEventLocator +instanceKlass com/sun/xml/bind/v2/runtime/RuntimeUtil +instanceKlass com/sun/xml/bind/v2/model/impl/AnyTypeImpl +instanceKlass com/sun/xml/bind/v2/model/impl/TypeInfoSetImpl$1 +instanceKlass javax/xml/datatype/Duration +instanceKlass javax/xml/namespace/NamespaceContext +instanceKlass javax/xml/datatype/XMLGregorianCalendar +instanceKlass javax/xml/transform/Result +instanceKlass javax/xml/transform/Source +instanceKlass javax/activation/DataHandler +instanceKlass java/awt/datatransfer/Transferable +instanceKlass javax/activation/DataSource +instanceKlass javax/xml/bind/ValidationEvent +instanceKlass com/sun/xml/bind/v2/runtime/output/Pcdata +instanceKlass java/awt/Transparency +instanceKlass java/awt/image/WritableRenderedImage +instanceKlass java/awt/image/RenderedImage +instanceKlass java/awt/Image +instanceKlass java/awt/Graphics +instanceKlass java/awt/Component +instanceKlass java/awt/MenuContainer +instanceKlass java/awt/image/ImageObserver +instanceKlass java/net/URI +instanceKlass javax/xml/datatype/DatatypeConstants$Field +instanceKlass javax/xml/datatype/DatatypeConstants +instanceKlass javax/xml/namespace/QName$1 +instanceKlass javax/xml/namespace/QName +instanceKlass com/sun/xml/bind/v2/model/impl/LeafInfoImpl +instanceKlass com/sun/xml/bind/v2/model/impl/ModelBuilder$1 +instanceKlass com/sun/xml/bind/v2/model/nav/TypeVisitor +instanceKlass com/sun/xml/bind/v2/model/nav/ReflectionNavigator +instanceKlass com/sun/xml/bind/WhiteSpaceProcessor +instanceKlass javax/xml/bind/annotation/XmlSchema +instanceKlass com/sun/xml/bind/v2/model/runtime/RuntimeClassInfo +instanceKlass com/sun/xml/bind/v2/model/core/ClassInfo +instanceKlass com/sun/xml/bind/v2/model/runtime/RuntimeArrayInfo +instanceKlass com/sun/xml/bind/v2/runtime/Location +instanceKlass com/sun/xml/bind/v2/model/core/ArrayInfo +instanceKlass com/sun/xml/bind/v2/model/runtime/RuntimeTypeInfoSet +instanceKlass com/sun/xml/bind/v2/model/impl/TypeInfoSetImpl +instanceKlass com/sun/xml/bind/v2/model/runtime/RuntimeElementInfo +instanceKlass com/sun/xml/bind/v2/model/runtime/RuntimeElement +instanceKlass com/sun/xml/bind/v2/model/core/ElementInfo +instanceKlass com/sun/xml/bind/v2/runtime/Transducer +instanceKlass com/sun/xml/bind/v2/model/runtime/RuntimeEnumLeafInfo +instanceKlass com/sun/xml/bind/v2/model/core/RegistryInfo +instanceKlass com/sun/xml/bind/v2/model/impl/TypeInfoImpl +instanceKlass com/sun/xml/bind/v2/model/core/Element +instanceKlass com/sun/xml/bind/v2/model/core/EnumLeafInfo +instanceKlass com/sun/xml/bind/v2/model/impl/ModelBuilder +instanceKlass javax/xml/bind/DatatypeConverter +instanceKlass javax/xml/datatype/SecuritySupport$1 +instanceKlass javax/xml/datatype/FactoryFinder$1 +instanceKlass javax/xml/datatype/SecuritySupport$5 +instanceKlass javax/xml/datatype/SecuritySupport$2 +instanceKlass javax/xml/datatype/SecuritySupport +instanceKlass javax/xml/datatype/FactoryFinder +instanceKlass javax/xml/datatype/DatatypeFactory +instanceKlass com/sun/xml/bind/DatatypeConverterImpl +instanceKlass javax/xml/bind/DatatypeConverterInterface +instanceKlass com/sun/xml/bind/v2/runtime/JAXBContextImpl$3 +instanceKlass com/sun/xml/bind/v2/runtime/NameBuilder +instanceKlass com/sun/istack/Pool$Impl +instanceKlass com/sun/xml/bind/v2/util/QNameMap$Entry +instanceKlass com/sun/xml/bind/v2/util/QNameMap +instanceKlass com/sun/xml/bind/v2/runtime/JAXBContextImpl$8 +instanceKlass com/sun/xml/bind/api/Bridge +instanceKlass com/sun/xml/bind/v2/model/runtime/RuntimeBuiltinLeafInfo +instanceKlass com/sun/xml/bind/v2/model/core/BuiltinLeafInfo +instanceKlass com/sun/istack/Pool +instanceKlass javax/xml/bind/Unmarshaller +instanceKlass com/sun/xml/bind/api/BridgeContext +instanceKlass com/sun/xml/bind/v2/model/core/TypeInfoSet +instanceKlass com/sun/xml/bind/api/RawAccessor +instanceKlass javax/xml/bind/SchemaOutputResolver +instanceKlass com/sun/xml/bind/v2/model/core/ErrorHandler +instanceKlass com/sun/xml/bind/v2/model/runtime/RuntimeLeafInfo +instanceKlass com/sun/xml/bind/v2/model/runtime/RuntimeNonElement +instanceKlass com/sun/xml/bind/v2/model/runtime/RuntimeTypeInfo +instanceKlass com/sun/xml/bind/v2/model/core/LeafInfo +instanceKlass com/sun/xml/bind/v2/model/core/MaybeElement +instanceKlass com/sun/xml/bind/v2/model/core/NonElement +instanceKlass com/sun/xml/bind/v2/model/core/TypeInfo +instanceKlass com/sun/xml/bind/v2/model/annotation/Locatable +instanceKlass com/sun/xml/bind/v2/runtime/AttributeAccessor +instanceKlass com/sun/xml/bind/v2/runtime/JaxBeanInfo +instanceKlass com/sun/xml/bind/v2/model/nav/Navigator +instanceKlass javax/xml/bind/Binder +instanceKlass com/sun/xml/bind/unmarshaller/InfosetScanner +instanceKlass javax/xml/bind/JAXBIntrospector +instanceKlass javax/xml/bind/Marshaller +instanceKlass com/sun/xml/bind/api/ErrorListener +instanceKlass org/xml/sax/ErrorHandler +instanceKlass com/sun/xml/bind/v2/model/annotation/AbstractInlineAnnotationReaderImpl +instanceKlass com/sun/xml/bind/v2/runtime/JAXBContextImpl$JAXBContextBuilder +instanceKlass com/sun/xml/bind/v2/util/TypeCast +instanceKlass com/sun/xml/bind/Util +instanceKlass mage/server/util/config/ObjectFactory +instanceKlass com/sun/xml/bind/v2/model/annotation/RuntimeAnnotationReader +instanceKlass com/sun/xml/bind/v2/model/annotation/AnnotationReader +instanceKlass com/sun/xml/bind/v2/ContextFactory +instanceKlass sun/net/www/protocol/jar/JarFileFactory +instanceKlass sun/net/www/protocol/jar/URLJarFile$URLJarFileCloseController +instanceKlass javax/xml/bind/GetPropertyAction +instanceKlass java/util/logging/LogManager$5 +instanceKlass java/util/logging/LoggingProxyImpl +instanceKlass sun/util/logging/LoggingProxy +instanceKlass sun/util/logging/LoggingSupport$1 +instanceKlass sun/util/logging/LoggingSupport +instanceKlass sun/util/logging/PlatformLogger$LoggerProxy +instanceKlass sun/util/logging/PlatformLogger$1 +instanceKlass sun/util/logging/PlatformLogger +instanceKlass java/util/logging/LogManager$LoggerContext$1 +instanceKlass java/util/logging/LogManager$3 +instanceKlass java/util/logging/LogManager$2 +instanceKlass java/lang/Shutdown$Lock +instanceKlass java/lang/Shutdown +instanceKlass java/lang/ApplicationShutdownHooks$1 +instanceKlass java/lang/ApplicationShutdownHooks +instanceKlass java/util/logging/LogManager$LogNode +instanceKlass java/util/logging/LogManager$LoggerContext +instanceKlass java/util/logging/LogManager$1 +instanceKlass java/util/logging/LogManager +instanceKlass java/util/logging/Logger$LoggerBundle +instanceKlass java/util/logging/Level$KnownLevel +instanceKlass java/util/logging/Level +instanceKlass java/util/logging/Handler +instanceKlass java/util/logging/Logger +instanceKlass javax/xml/bind/ContextFinder +instanceKlass javax/xml/bind/JAXBContext +instanceKlass mage/server/util/ConfigSettings +instanceKlass org/mage/test/serverside/base/MageTestPlayerBase$1 +instanceKlass org/apache/log4j/CategoryKey +instanceKlass org/apache/log4j/helpers/AppenderAttachableImpl +instanceKlass java/util/Vector$1 +instanceKlass java/util/Collections$EmptyEnumeration +instanceKlass org/apache/log4j/SortedKeyEnumeration +instanceKlass org/apache/log4j/spi/Filter +instanceKlass java/util/Date +instanceKlass java/text/DigitList +instanceKlass java/text/FieldPosition +instanceKlass java/text/DateFormatSymbols +instanceKlass sun/util/calendar/CalendarUtils +instanceKlass sun/util/calendar/CalendarDate +instanceKlass sun/util/locale/provider/CalendarDataUtility$CalendarWeekParameterGetter +instanceKlass sun/util/locale/provider/CalendarDataUtility +instanceKlass java/util/Calendar$Builder +instanceKlass java/util/Calendar +instanceKlass java/util/TimeZone$1 +instanceKlass java/util/zip/CRC32 +instanceKlass java/util/zip/Checksum +instanceKlass sun/util/calendar/ZoneInfoFile$ZoneOffsetTransitionRule +instanceKlass sun/util/calendar/ZoneInfoFile$1 +instanceKlass sun/util/calendar/ZoneInfoFile +instanceKlass sun/util/calendar/CalendarSystem +instanceKlass java/util/TimeZone +instanceKlass java/text/AttributedCharacterIterator$Attribute +instanceKlass org/apache/log4j/spi/LoggingEvent +instanceKlass java/beans/SimpleBeanInfo +instanceKlass java/util/TreeMap$PrivateEntryIterator +instanceKlass java/beans/Transient +instanceKlass com/sun/beans/WildcardTypeImpl +instanceKlass sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl +instanceKlass java/lang/reflect/ParameterizedType +instanceKlass sun/reflect/generics/reflectiveObjects/LazyReflectiveObjectGenerator +instanceKlass java/lang/reflect/WildcardType +instanceKlass sun/reflect/generics/tree/MethodTypeSignature +instanceKlass sun/reflect/generics/tree/Wildcard +instanceKlass sun/reflect/generics/tree/BottomSignature +instanceKlass java/lang/reflect/TypeVariable +instanceKlass sun/reflect/generics/tree/ClassSignature +instanceKlass sun/reflect/generics/tree/Signature +instanceKlass sun/reflect/generics/tree/FormalTypeParameter +instanceKlass com/sun/beans/TypeResolver +instanceKlass java/beans/MethodRef +instanceKlass com/sun/beans/util/Cache$CacheEntry +instanceKlass com/sun/beans/util/Cache +instanceKlass com/sun/beans/finder/AbstractFinder +instanceKlass com/sun/beans/finder/ClassFinder +instanceKlass com/sun/beans/finder/InstanceFinder +instanceKlass java/beans/WeakIdentityMap +instanceKlass java/beans/ThreadGroupContext +instanceKlass java/beans/FeatureDescriptor +instanceKlass java/util/EventListener +instanceKlass com/sun/beans/WeakCache +instanceKlass java/beans/Introspector +instanceKlass java/beans/BeanInfo +instanceKlass org/apache/log4j/config/PropertySetter +instanceKlass org/apache/log4j/helpers/FormattingInfo +instanceKlass java/text/Format +instanceKlass org/apache/log4j/helpers/PatternConverter +instanceKlass org/apache/log4j/helpers/PatternParser +instanceKlass org/apache/log4j/helpers/OnlyOnceErrorHandler +instanceKlass org/apache/log4j/Layout +instanceKlass org/apache/log4j/spi/ErrorHandler +instanceKlass org/apache/log4j/AppenderSkeleton +instanceKlass org/apache/log4j/spi/OptionHandler +instanceKlass org/apache/log4j/Appender +instanceKlass sun/net/DefaultProgressMeteringPolicy +instanceKlass sun/net/ProgressMeteringPolicy +instanceKlass sun/net/ProgressMonitor +instanceKlass org/apache/log4j/PropertyConfigurator +instanceKlass java/net/URLClassLoader$2 +instanceKlass org/apache/log4j/helpers/LogLog +instanceKlass org/apache/log4j/helpers/Loader +instanceKlass org/apache/log4j/spi/Configurator +instanceKlass org/apache/log4j/helpers/OptionConverter +instanceKlass org/apache/log4j/spi/DefaultRepositorySelector +instanceKlass org/apache/log4j/DefaultCategoryFactory +instanceKlass org/apache/log4j/or/DefaultRenderer +instanceKlass org/apache/log4j/or/ObjectRenderer +instanceKlass org/apache/log4j/or/RendererMap +instanceKlass org/apache/log4j/spi/LoggerFactory +instanceKlass org/apache/log4j/Hierarchy +instanceKlass org/apache/log4j/spi/ThrowableRendererSupport +instanceKlass org/apache/log4j/spi/RendererSupport +instanceKlass org/apache/log4j/spi/RepositorySelector +instanceKlass org/apache/log4j/spi/LoggerRepository +instanceKlass org/apache/log4j/LogManager +instanceKlass org/apache/log4j/Priority +instanceKlass org/junit/internal/runners/model/ReflectiveCallable +instanceKlass org/junit/rules/TestRule +instanceKlass org/junit/runners/ParentRunner$3 +instanceKlass java/util/Formattable +instanceKlass java/util/Formatter$FixedString +instanceKlass java/util/Formatter$Conversion +instanceKlass java/util/Formatter$Flags +instanceKlass java/util/Formatter$FormatSpecifier +instanceKlass java/util/Formatter$FormatString +instanceKlass java/util/regex/ASCII +instanceKlass java/util/regex/Matcher +instanceKlass java/util/regex/MatchResult +instanceKlass java/util/Currency$CurrencyNameGetter +instanceKlass sun/util/locale/provider/LocaleServiceProviderPool$LocalizedObjectGetter +instanceKlass sun/util/locale/provider/SPILocaleProviderAdapter$1 +instanceKlass sun/util/locale/provider/LocaleServiceProviderPool +instanceKlass java/util/Currency$1 +instanceKlass java/util/Currency +instanceKlass java/util/concurrent/atomic/AtomicMarkableReference$Pair +instanceKlass java/util/concurrent/atomic/AtomicMarkableReference +instanceKlass java/util/ResourceBundle$CacheKeyReference +instanceKlass java/util/ResourceBundle$CacheKey +instanceKlass java/util/ResourceBundle$RBClassLoader$1 +instanceKlass java/net/URLClassLoader$3$1 +instanceKlass sun/misc/CompoundEnumeration +instanceKlass java/net/URLClassLoader$3 +instanceKlass sun/misc/URLClassPath$1 +instanceKlass java/lang/ClassLoader$2 +instanceKlass sun/misc/URLClassPath$2 +instanceKlass sun/misc/Launcher$BootClassPathHolder$1 +instanceKlass sun/misc/Launcher$BootClassPathHolder +instanceKlass java/util/ServiceLoader$1 +instanceKlass java/util/ServiceLoader$LazyIterator +instanceKlass java/util/ServiceLoader +instanceKlass java/util/spi/ResourceBundleControlProvider +instanceKlass java/util/ResourceBundle +instanceKlass java/util/ResourceBundle$Control +instanceKlass sun/util/resources/LocaleData$1 +instanceKlass sun/util/resources/LocaleData +instanceKlass sun/util/locale/provider/LocaleResources +instanceKlass sun/util/locale/LanguageTag +instanceKlass sun/util/locale/provider/JRELocaleProviderAdapter$1 +instanceKlass sun/util/locale/provider/LocaleDataMetaInfo +instanceKlass sun/util/locale/provider/AvailableLanguageTags +instanceKlass sun/util/locale/provider/LocaleProviderAdapter$1 +instanceKlass sun/util/locale/provider/ResourceBundleBasedAdapter +instanceKlass sun/util/locale/provider/LocaleProviderAdapter +instanceKlass java/util/spi/LocaleServiceProvider +instanceKlass java/text/DecimalFormatSymbols +instanceKlass java/util/Locale$1 +instanceKlass java/util/Formatter +instanceKlass java/util/concurrent/ConcurrentLinkedQueue$Node +instanceKlass java/util/regex/Pattern$TreeInfo +instanceKlass org/junit/runner/Description +instanceKlass org/junit/internal/runners/model/EachTestNotifier +instanceKlass org/junit/After +instanceKlass org/junit/Assert +instanceKlass org/junit/validator/ValidateWith +instanceKlass java/util/Collections$1 +instanceKlass org/junit/internal/runners/rules/RuleMemberValidator$MethodMustBeARule +instanceKlass org/junit/internal/runners/rules/RuleMemberValidator$MethodMustBeATestRule +instanceKlass org/junit/internal/runners/rules/RuleMemberValidator$FieldMustBeARule +instanceKlass org/junit/internal/runners/rules/RuleMemberValidator$MemberMustBeNonStaticOrAlsoClassRule +instanceKlass org/junit/Rule +instanceKlass org/junit/internal/runners/rules/RuleMemberValidator$FieldMustBeATestRule +instanceKlass org/junit/internal/runners/rules/RuleMemberValidator$MemberMustBePublic +instanceKlass org/junit/internal/runners/rules/RuleMemberValidator$MemberMustBeStatic +instanceKlass org/junit/internal/runners/rules/RuleMemberValidator$DeclaringClassMustBePublic +instanceKlass org/junit/ClassRule +instanceKlass org/junit/internal/runners/rules/RuleMemberValidator$Builder +instanceKlass org/junit/internal/runners/rules/RuleMemberValidator$RuleValidator +instanceKlass org/junit/internal/runners/rules/RuleMemberValidator +instanceKlass org/junit/AfterClass +instanceKlass java/util/Collections$UnmodifiableCollection$1 +instanceKlass org/apache/log4j/Category +instanceKlass org/apache/log4j/spi/AppenderAttachable +instanceKlass mage/game/GameOptions +instanceKlass java/util/TimSort +instanceKlass org/junit/FixMethodOrder +instanceKlass org/junit/internal/MethodSorter$2 +instanceKlass org/junit/internal/MethodSorter$1 +instanceKlass org/junit/internal/MethodSorter +instanceKlass org/junit/runners/model/TestClass$MethodComparator +instanceKlass org/junit/runners/model/TestClass$FieldComparator +instanceKlass org/junit/runners/model/FrameworkMember +instanceKlass org/junit/runners/model/TestClass +instanceKlass org/junit/runners/model/Annotatable +instanceKlass org/junit/runners/ParentRunner$1 +instanceKlass org/junit/validator/PublicClassValidator +instanceKlass org/junit/validator/AnnotationValidatorFactory +instanceKlass org/junit/validator/AnnotationsValidator$AnnotatableValidator +instanceKlass org/junit/validator/AnnotationsValidator +instanceKlass org/junit/validator/TestClassValidator +instanceKlass org/junit/runners/model/RunnerScheduler +instanceKlass org/hamcrest/SelfDescribing +instanceKlass org/junit/runners/model/Statement +instanceKlass junit/framework/Assert +instanceKlass java/util/AbstractList$Itr +instanceKlass org/junit/runner/manipulation/Sortable +instanceKlass org/junit/runner/manipulation/Filterable +instanceKlass org/junit/runners/model/RunnerBuilder +instanceKlass org/junit/runner/Runner +instanceKlass org/junit/runner/Describable +instanceKlass org/junit/runner/Request +instanceKlass org/apache/maven/surefire/junit4/JUnit4TestSet +instanceKlass org/apache/maven/surefire/report/SimpleReportEntry +instanceKlass java/util/concurrent/CopyOnWriteArrayList$COWIterator +instanceKlass org/junit/runner/notification/RunNotifier$SafeNotifier +instanceKlass java/util/LinkedList$ListItr +instanceKlass java/util/ListIterator +instanceKlass org/junit/runner/notification/RunListener$ThreadSafe +instanceKlass org/junit/runner/notification/RunNotifier +instanceKlass java/util/concurrent/locks/AbstractQueuedSynchronizer$Node +instanceKlass java/util/concurrent/locks/AbstractOwnableSynchronizer +instanceKlass java/util/concurrent/CopyOnWriteArrayList +instanceKlass java/io/ObjectStreamClass$FieldReflector +instanceKlass java/io/ObjectInput +instanceKlass java/io/DataInput +instanceKlass java/io/ObjectStreamConstants +instanceKlass java/io/ObjectOutput +instanceKlass java/util/ComparableTimSort +instanceKlass java/util/Arrays$LegacyMergeSort +instanceKlass sun/reflect/UnsafeFieldAccessorFactory +instanceKlass java/io/ObjectStreamClass$2 +instanceKlass java/io/Externalizable +instanceKlass java/io/ObjectStreamClass$EntryFuture +instanceKlass java/io/ObjectStreamClass$Caches +instanceKlass java/io/ObjectStreamClass +instanceKlass org/junit/runner/Result$SerializedForm +instanceKlass org/junit/runner/Result +instanceKlass java/util/regex/Pattern$Node +instanceKlass java/util/regex/Pattern +instanceKlass org/apache/maven/surefire/report/ConsoleOutputCapture +instanceKlass org/apache/maven/surefire/util/internal/StringUtils +instanceKlass org/apache/maven/surefire/booter/ForkingRunListener +instanceKlass org/apache/maven/surefire/report/ConsoleOutputReceiver +instanceKlass org/apache/maven/surefire/util/TestsToRun +instanceKlass mage/interfaces/rate/RateCallback +instanceKlass org/mage/test/utils/DeckBuilderTest +instanceKlass mage/game/tournament/TournamentPlayer +instanceKlass org/mage/test/serverside/tournament/SwissPairingMinimalWeightMatchingTest +instanceKlass org/mage/test/serverside/rating/GlickoRatingSystemTest +instanceKlass org/mage/test/serverside/base/MageTestBase +instanceKlass mage/cards/decks/DeckValidator +instanceKlass java/lang/annotation/Documented +instanceKlass java/lang/Deprecated +instanceKlass mage/game/combat/CombatGroup +instanceKlass mage/abilities/costs/mana/ManaCosts +instanceKlass mage/abilities/costs/Costs +instanceKlass mage/game/match/Match +instanceKlass mage/game/Table +instanceKlass mage/abilities/Mode +instanceKlass mage/choices/Choice +instanceKlass mage/game/draft/Draft +instanceKlass mage/util/MessageToClient +instanceKlass mage/abilities/costs/VariableCost +instanceKlass mage/game/match/MatchPlayer +instanceKlass mage/game/tournament/Tournament +instanceKlass mage/players/ManaPool +instanceKlass mage/abilities/TriggeredAbility +instanceKlass mage/target/TargetImpl +instanceKlass mage/target/Target +instanceKlass mage/players/net/UserData +instanceKlass mage/counters/Counter +instanceKlass mage/players/Library +instanceKlass mage/cards/Cards +instanceKlass mage/abilities/AbilityImpl +instanceKlass mage/abilities/ActivatedAbility +instanceKlass mage/remote/Connection +instanceKlass mage/cards/decks/Deck +instanceKlass mage/game/match/MatchOptions +instanceKlass mage/view/GameTypeView +instanceKlass mage/cards/decks/DeckCardLists +instanceKlass mage/remote/Session +instanceKlass mage/remote/interfaces/Testable +instanceKlass mage/remote/interfaces/Replays +instanceKlass mage/remote/interfaces/PlayerActions +instanceKlass mage/remote/interfaces/Feedback +instanceKlass mage/remote/interfaces/ChatSession +instanceKlass mage/remote/interfaces/ServerState +instanceKlass mage/remote/interfaces/GameTypes +instanceKlass mage/remote/interfaces/GamePlay +instanceKlass mage/remote/interfaces/Connect +instanceKlass mage/remote/interfaces/ClientData +instanceKlass mage/interfaces/MageClient +instanceKlass mage/interfaces/callback/CallbackClient +instanceKlass org/mage/test/load/LoadTest +instanceKlass org/mage/test/decks/importer/TxtDeckImporterTest +instanceKlass mage/abilities/Abilities +instanceKlass sun/reflect/ClassDefiner$1 +instanceKlass sun/reflect/ClassDefiner +instanceKlass sun/reflect/MethodAccessorGenerator$1 +instanceKlass sun/reflect/Label$PatchInfo +instanceKlass sun/reflect/Label +instanceKlass sun/reflect/UTF8 +instanceKlass sun/reflect/ClassFileAssembler +instanceKlass sun/reflect/ByteVectorImpl +instanceKlass sun/reflect/ByteVector +instanceKlass sun/reflect/ByteVectorFactory +instanceKlass sun/reflect/AccessorGenerator +instanceKlass sun/reflect/ClassFileConstants +instanceKlass mage/abilities/costs/mana/ManaCost +instanceKlass mage/abilities/costs/Cost +instanceKlass mage/filter/FilterImpl +instanceKlass mage/filter/FilterInPlay +instanceKlass mage/filter/Filter +instanceKlass org/junit/BeforeClass +instanceKlass mage/game/tournament/TournamentType +instanceKlass mage/game/match/MatchType +instanceKlass org/junit/Before +instanceKlass java/util/LinkedHashMap$LinkedHashIterator +instanceKlass org/junit/Ignore +instanceKlass java/lang/annotation/Target +instanceKlass java/lang/reflect/WeakCache$Value +instanceKlass sun/misc/ProxyGenerator$ExceptionTableEntry +instanceKlass sun/misc/ProxyGenerator$PrimitiveTypeInfo +instanceKlass sun/misc/ProxyGenerator$FieldInfo +instanceKlass java/io/DataOutput +instanceKlass sun/misc/ProxyGenerator$ConstantPool$Entry +instanceKlass sun/misc/ProxyGenerator$MethodInfo +instanceKlass sun/misc/ProxyGenerator$ProxyMethod +instanceKlass sun/misc/ProxyGenerator$ConstantPool +instanceKlass sun/security/action/GetBooleanAction +instanceKlass sun/misc/ProxyGenerator +instanceKlass java/lang/reflect/WeakCache$Factory +instanceKlass java/util/function/Supplier +instanceKlass java/lang/reflect/Proxy$ProxyClassFactory +instanceKlass java/lang/reflect/Proxy$KeyFactory +instanceKlass java/util/function/BiFunction +instanceKlass java/lang/reflect/WeakCache +instanceKlass java/lang/reflect/Proxy +instanceKlass sun/reflect/annotation/AnnotationInvocationHandler +instanceKlass java/lang/reflect/InvocationHandler +instanceKlass sun/reflect/annotation/AnnotationParser$1 +instanceKlass java/lang/Class$4 +instanceKlass java/lang/annotation/Inherited +instanceKlass java/lang/annotation/Retention +instanceKlass sun/reflect/annotation/ExceptionProxy +instanceKlass java/lang/Long$LongCache +instanceKlass sun/reflect/annotation/AnnotationType$1 +instanceKlass java/lang/reflect/GenericArrayType +instanceKlass org/junit/Test +instanceKlass sun/reflect/generics/visitor/Reifier +instanceKlass sun/reflect/generics/visitor/TypeTreeVisitor +instanceKlass sun/reflect/generics/factory/CoreReflectionFactory +instanceKlass sun/reflect/generics/factory/GenericsFactory +instanceKlass sun/reflect/generics/scope/AbstractScope +instanceKlass sun/reflect/generics/scope/Scope +instanceKlass sun/reflect/generics/tree/ClassTypeSignature +instanceKlass sun/reflect/generics/tree/SimpleClassTypeSignature +instanceKlass sun/reflect/generics/tree/FieldTypeSignature +instanceKlass sun/reflect/generics/tree/BaseType +instanceKlass sun/reflect/generics/tree/TypeSignature +instanceKlass sun/reflect/generics/tree/ReturnType +instanceKlass sun/reflect/generics/tree/TypeArgument +instanceKlass sun/reflect/generics/tree/TypeTree +instanceKlass sun/reflect/generics/tree/Tree +instanceKlass sun/reflect/generics/parser/SignatureParser +instanceKlass java/util/Collections$EmptyIterator +instanceKlass sun/reflect/annotation/AnnotationParser +instanceKlass mage/game/permanent/Permanent +instanceKlass mage/cards/Card +instanceKlass mage/MageObject +instanceKlass java/util/UUID +instanceKlass mage/abilities/Ability +instanceKlass mage/game/Controllable +instanceKlass org/mage/test/player/TestPlayer +instanceKlass mage/players/PlayerImpl +instanceKlass mage/game/Game +instanceKlass mage/filter/predicate/Predicate +instanceKlass mage/players/Player +instanceKlass mage/util/Copyable +instanceKlass mage/MageItem +instanceKlass java/io/FilenameFilter +instanceKlass mage/server/util/config/Plugin +instanceKlass org/mage/test/serverside/base/MageTestPlayerBase +instanceKlass org/mage/test/serverside/base/CardTestAPI +instanceKlass org/apache/maven/surefire/shade/org/codehaus/plexus/util/SelectorUtils +instanceKlass org/apache/maven/surefire/shade/org/codehaus/plexus/util/AbstractScanner +instanceKlass org/apache/maven/surefire/shade/org/codehaus/plexus/util/Scanner +instanceKlass org/apache/maven/surefire/booter/ProviderFactory$ProviderProxy +instanceKlass org/junit/runner/RunWith +instanceKlass junit/framework/Test +instanceKlass org/apache/maven/surefire/NonAbstractClassFilter +instanceKlass org/apache/maven/surefire/common/junit3/JUnit3TestChecker +instanceKlass org/apache/maven/surefire/common/junit4/JUnit4TestChecker +instanceKlass org/apache/maven/surefire/common/junit4/JUnit4RunListenerFactory +instanceKlass org/apache/maven/surefire/util/DefaultDirectoryScanner +instanceKlass org/junit/runner/notification/RunListener +instanceKlass org/apache/maven/surefire/report/StackTraceWriter +instanceKlass org/apache/maven/surefire/report/ReportEntry +instanceKlass org/apache/maven/surefire/util/ScannerFilter +instanceKlass org/apache/maven/surefire/providerapi/AbstractProvider +instanceKlass java/util/LinkedList$Node +instanceKlass org/apache/maven/surefire/util/DirectoryScanner +instanceKlass org/apache/maven/surefire/report/ConsoleLogger +instanceKlass org/apache/maven/surefire/booter/BaseProviderFactory +instanceKlass org/apache/maven/surefire/providerapi/SurefireProvider +instanceKlass org/apache/maven/surefire/booter/ProviderFactory +instanceKlass org/apache/maven/surefire/util/ReflectionUtils +instanceKlass org/apache/maven/surefire/report/RunListener +instanceKlass org/apache/maven/surefire/booter/ForkingReporterFactory +instanceKlass org/apache/maven/surefire/providerapi/ProviderParameters +instanceKlass org/apache/maven/surefire/suite/RunResult +instanceKlass org/apache/maven/surefire/report/ReporterFactory +instanceKlass org/apache/maven/surefire/booter/ProviderPropertiesAware +instanceKlass org/apache/maven/surefire/booter/ReporterConfigurationAware +instanceKlass org/apache/maven/surefire/booter/SurefireClassLoadersAware +instanceKlass org/apache/maven/surefire/booter/TestRequestAware +instanceKlass org/apache/maven/surefire/booter/DirectoryScannerParametersAware +instanceKlass org/apache/maven/surefire/booter/TestArtifactInfoAware +instanceKlass org/apache/maven/surefire/report/AbstractReporter +instanceKlass org/apache/maven/surefire/report/Reporter +instanceKlass org/apache/maven/surefire/booter/StartupReportConfiguration +instanceKlass org/apache/maven/surefire/booter/SurefireReflector +instanceKlass java/lang/AssertionStatusDirectives +instanceKlass org/apache/maven/surefire/util/UrlUtils +instanceKlass org/apache/maven/surefire/booter/SurefireStarter +instanceKlass org/apache/maven/surefire/booter/StartupConfiguration +instanceKlass java/util/ArrayList$Itr +instanceKlass org/apache/maven/surefire/booter/Classpath +instanceKlass org/apache/maven/surefire/booter/ClasspathConfiguration +instanceKlass org/apache/maven/surefire/booter/ClassLoaderConfiguration +instanceKlass org/apache/maven/surefire/booter/ProviderConfiguration +instanceKlass org/apache/maven/surefire/report/ReporterConfiguration +instanceKlass org/apache/maven/surefire/testset/TestRequest +instanceKlass org/apache/maven/surefire/testset/TestArtifactInfo +instanceKlass org/apache/maven/surefire/util/RunOrder +instanceKlass org/apache/maven/surefire/testset/DirectoryScannerParameters +instanceKlass org/apache/maven/surefire/booter/TypeEncodedValue +instanceKlass org/apache/maven/surefire/booter/BooterDeserializer +instanceKlass org/apache/maven/surefire/booter/BooterConstants +instanceKlass org/apache/maven/surefire/booter/PropertiesWrapper +instanceKlass java/util/Properties$LineReader +instanceKlass org/apache/maven/surefire/booter/SystemPropertyManager +instanceKlass java/lang/Void +instanceKlass java/lang/Class$MethodArray +instanceKlass sun/launcher/LauncherHelper$FXHelper +instanceKlass org/apache/maven/surefire/booter/ForkedBooter +instanceKlass java/io/FilePermission$1 +instanceKlass sun/net/www/MessageHeader +instanceKlass java/net/URLConnection +instanceKlass java/security/PermissionCollection +instanceKlass sun/nio/ByteBuffered +instanceKlass sun/security/util/ManifestEntryVerifier +instanceKlass sun/security/util/SignatureFileVerifier +instanceKlass java/lang/Package +instanceKlass sun/misc/Resource +instanceKlass sun/misc/ExtensionDependency +instanceKlass sun/misc/JarIndex +instanceKlass sun/misc/FileURLMapper +instanceKlass sun/misc/URLClassPath$JarLoader$1 +instanceKlass sun/nio/cs/ThreadLocalCoders$Cache +instanceKlass sun/nio/cs/ThreadLocalCoders +instanceKlass sun/misc/URLClassPath$Loader +instanceKlass sun/misc/URLClassPath$3 +instanceKlass sun/net/util/URLUtil +instanceKlass java/net/URLClassLoader$1 +instanceKlass java/util/jar/JarVerifier$3 +instanceKlass java/security/CodeSigner +instanceKlass java/util/jar/JarVerifier +instanceKlass sun/misc/ASCIICaseInsensitiveComparator +instanceKlass java/util/jar/Attributes$Name +instanceKlass java/util/jar/Attributes +instanceKlass sun/misc/IOUtils +instanceKlass java/util/zip/ZStreamRef +instanceKlass java/util/zip/Inflater +instanceKlass java/util/zip/ZipEntry +instanceKlass sun/nio/ch/DirectBuffer +instanceKlass sun/misc/PerfCounter$CoreCounters +instanceKlass sun/misc/Perf +instanceKlass sun/misc/Perf$GetPerfAction +instanceKlass sun/misc/PerfCounter +instanceKlass java/util/zip/ZipCoder +instanceKlass java/util/Deque +instanceKlass java/util/Queue +instanceKlass java/nio/charset/StandardCharsets +instanceKlass java/util/jar/JavaUtilJarAccessImpl +instanceKlass sun/misc/JavaUtilJarAccess +instanceKlass java/util/zip/ZipFile$1 +instanceKlass sun/misc/JavaUtilZipFileAccess +instanceKlass java/util/zip/ZipFile +instanceKlass java/util/zip/ZipConstants +instanceKlass java/lang/StringCoding$StringDecoder +instanceKlass sun/nio/cs/SingleByte +instanceKlass java/io/FileOutputStream$1 +instanceKlass java/lang/StringCoding$StringEncoder +instanceKlass java/lang/ThreadLocal$ThreadLocalMap +instanceKlass java/lang/StringCoding +instanceKlass sun/usagetracker/UsageTrackerClient$3 +instanceKlass java/util/TreeMap$Entry +instanceKlass java/lang/ProcessEnvironment$CheckedEntry +instanceKlass java/util/HashMap$HashIterator +instanceKlass java/lang/ProcessEnvironment$CheckedEntrySet$1 +instanceKlass java/util/NavigableMap +instanceKlass java/util/SortedMap +instanceKlass java/util/Collections$UnmodifiableMap +instanceKlass java/lang/ProcessEnvironment$EntryComparator +instanceKlass java/lang/ProcessEnvironment$NameComparator +instanceKlass sun/usagetracker/UsageTrackerClient$2 +instanceKlass sun/usagetracker/UsageTrackerClient$4 +instanceKlass sun/usagetracker/UsageTrackerClient$1 +instanceKlass java/util/concurrent/atomic/AtomicBoolean +instanceKlass sun/usagetracker/UsageTrackerClient +instanceKlass sun/misc/PostVMInitHook +instanceKlass java/lang/invoke/MethodHandleStatics$1 +instanceKlass java/lang/invoke/MethodHandleStatics +instanceKlass java/lang/invoke/MemberName$Factory +instanceKlass java/lang/ClassValue$Version +instanceKlass java/lang/ClassValue$Identity +instanceKlass java/lang/ClassValue +instanceKlass java/lang/invoke/MethodHandleImpl$3 +instanceKlass java/lang/invoke/MethodHandleImpl$2 +instanceKlass java/util/function/Function +instanceKlass java/lang/invoke/MethodHandleImpl$1 +instanceKlass java/lang/invoke/MethodHandleImpl +instanceKlass java/lang/SystemClassLoaderAction +instanceKlass sun/misc/Launcher$AppClassLoader$1 +instanceKlass sun/misc/URLClassPath +instanceKlass java/security/Principal +instanceKlass java/security/ProtectionDomain$Key +instanceKlass java/security/ProtectionDomain$2 +instanceKlass sun/misc/JavaSecurityProtectionDomainAccess +instanceKlass java/security/ProtectionDomain$JavaSecurityAccessImpl +instanceKlass sun/misc/JavaSecurityAccess +instanceKlass java/net/URLStreamHandler +instanceKlass java/net/Parts +instanceKlass java/util/BitSet +instanceKlass sun/net/www/ParseUtil +instanceKlass java/io/FileInputStream$1 +instanceKlass java/lang/CharacterData +instanceKlass sun/util/locale/LocaleUtils +instanceKlass java/util/Locale$LocaleKey +instanceKlass sun/util/locale/BaseLocale$Key +instanceKlass sun/util/locale/BaseLocale +instanceKlass java/util/concurrent/ConcurrentHashMap$CollectionView +instanceKlass java/util/concurrent/ConcurrentHashMap$CounterCell +instanceKlass java/util/concurrent/ConcurrentHashMap$Node +instanceKlass java/util/concurrent/locks/ReentrantLock +instanceKlass java/util/concurrent/locks/Lock +instanceKlass java/util/concurrent/ConcurrentMap +instanceKlass sun/util/locale/LocaleObjectCache +instanceKlass java/util/Locale +instanceKlass java/lang/reflect/Array +instanceKlass java/nio/charset/CoderResult$Cache +instanceKlass java/nio/charset/CoderResult +instanceKlass java/nio/charset/CharsetDecoder +instanceKlass sun/nio/cs/ArrayDecoder +instanceKlass java/io/Reader +instanceKlass java/lang/Readable +instanceKlass sun/misc/MetaIndex +instanceKlass sun/misc/Launcher$ExtClassLoader$1 +instanceKlass java/util/StringTokenizer +instanceKlass java/net/URLClassLoader$7 +instanceKlass sun/misc/JavaNetAccess +instanceKlass java/lang/ClassLoader$ParallelLoaders +instanceKlass sun/security/util/Debug +instanceKlass sun/misc/Launcher$Factory +instanceKlass java/net/URLStreamHandlerFactory +instanceKlass java/lang/Compiler$1 +instanceKlass java/lang/Compiler +instanceKlass java/lang/System$2 +instanceKlass sun/misc/JavaLangAccess +instanceKlass sun/io/Win32ErrorMode +instanceKlass sun/misc/OSEnvironment +instanceKlass java/lang/Integer$IntegerCache +instanceKlass sun/misc/NativeSignalHandler +instanceKlass sun/misc/Signal +instanceKlass java/lang/Terminator$1 +instanceKlass sun/misc/SignalHandler +instanceKlass java/lang/Terminator +instanceKlass java/lang/ClassLoader$NativeLibrary +instanceKlass java/io/ExpiringCache$Entry +instanceKlass java/lang/ClassLoader$3 +instanceKlass java/nio/file/Path +instanceKlass java/nio/file/Watchable +instanceKlass java/lang/Enum +instanceKlass java/io/ExpiringCache +instanceKlass java/io/FileSystem +instanceKlass java/io/DefaultFileSystem +instanceKlass java/nio/Bits$1 +instanceKlass sun/misc/JavaNioAccess +instanceKlass java/nio/ByteOrder +instanceKlass java/nio/Bits +instanceKlass java/nio/charset/CodingErrorAction +instanceKlass java/nio/charset/CharsetEncoder +instanceKlass sun/nio/cs/ArrayEncoder +instanceKlass sun/reflect/ReflectionFactory$1 +instanceKlass java/lang/Class$1 +instanceKlass sun/nio/cs/HistoricallyNamedCharset +instanceKlass java/util/Arrays +instanceKlass sun/security/action/GetPropertyAction +instanceKlass java/lang/ThreadLocal +instanceKlass java/nio/charset/spi/CharsetProvider +instanceKlass java/nio/charset/Charset +instanceKlass java/io/Writer +instanceKlass sun/reflect/misc/ReflectUtil +instanceKlass java/lang/reflect/ReflectAccess +instanceKlass sun/reflect/LangReflectAccess +instanceKlass java/lang/reflect/Modifier +instanceKlass sun/reflect/annotation/AnnotationType +instanceKlass java/lang/Class$AnnotationData +instanceKlass sun/reflect/generics/repository/AbstractRepository +instanceKlass java/lang/Class$Atomic +instanceKlass java/lang/Class$ReflectionData +instanceKlass java/lang/Class$3 +instanceKlass java/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl$1 +instanceKlass java/security/PrivilegedExceptionAction +instanceKlass java/util/concurrent/atomic/AtomicReferenceFieldUpdater +instanceKlass java/io/OutputStream +instanceKlass java/io/Flushable +instanceKlass java/io/FileDescriptor$1 +instanceKlass sun/misc/JavaIOFileDescriptorAccess +instanceKlass java/io/FileDescriptor +instanceKlass sun/misc/Version +instanceKlass java/lang/Runtime +instanceKlass java/util/Hashtable$Enumerator +instanceKlass java/util/Iterator +instanceKlass java/util/Enumeration +instanceKlass java/util/Objects +instanceKlass java/util/Collections$SynchronizedCollection +instanceKlass java/lang/Math +instanceKlass java/util/Hashtable$Entry +instanceKlass sun/misc/VM +instanceKlass java/util/HashMap$Node +instanceKlass java/util/Map$Entry +instanceKlass sun/reflect/Reflection +instanceKlass sun/misc/SharedSecrets +instanceKlass java/lang/ref/Reference$1 +instanceKlass sun/misc/JavaLangRefAccess +instanceKlass java/lang/ref/ReferenceQueue$Lock +instanceKlass java/lang/ref/ReferenceQueue +instanceKlass java/util/Collections$UnmodifiableCollection +instanceKlass java/util/AbstractMap +instanceKlass java/util/Set +instanceKlass java/util/Collections +instanceKlass java/lang/ref/Reference$Lock +instanceKlass sun/reflect/ReflectionFactory +instanceKlass java/util/AbstractCollection +instanceKlass java/util/RandomAccess +instanceKlass java/util/List +instanceKlass java/util/Collection +instanceKlass java/lang/Iterable +instanceKlass java/security/cert/Certificate +instanceKlass sun/reflect/ReflectionFactory$GetReflectionFactoryAction +instanceKlass java/security/PrivilegedAction +instanceKlass java/security/AccessController +instanceKlass java/security/Permission +instanceKlass java/security/Guard +instanceKlass java/lang/String$CaseInsensitiveComparator +instanceKlass java/util/Comparator +instanceKlass java/io/ObjectStreamField +instanceKlass java/lang/Number +instanceKlass java/lang/Character +instanceKlass java/lang/Boolean +instanceKlass java/nio/Buffer +instanceKlass java/lang/StackTraceElement +instanceKlass java/security/CodeSource +instanceKlass sun/misc/Launcher +instanceKlass java/util/jar/Manifest +instanceKlass java/net/URL +instanceKlass java/io/File +instanceKlass java/io/InputStream +instanceKlass java/io/Closeable +instanceKlass java/lang/AutoCloseable +instanceKlass sun/misc/Unsafe +instanceKlass java/lang/AbstractStringBuilder +instanceKlass java/lang/Appendable +instanceKlass java/lang/invoke/CallSite +instanceKlass java/lang/invoke/MethodType +instanceKlass java/lang/invoke/LambdaForm +instanceKlass java/lang/invoke/MethodHandleNatives +instanceKlass java/lang/invoke/MemberName +instanceKlass java/lang/invoke/MethodHandle +instanceKlass sun/reflect/CallerSensitive +instanceKlass java/lang/annotation/Annotation +instanceKlass sun/reflect/FieldAccessor +instanceKlass sun/reflect/ConstantPool +instanceKlass sun/reflect/ConstructorAccessor +instanceKlass sun/reflect/MethodAccessor +instanceKlass sun/reflect/MagicAccessorImpl +instanceKlass java/lang/reflect/Parameter +instanceKlass java/lang/reflect/Member +instanceKlass java/lang/reflect/AccessibleObject +instanceKlass java/util/Dictionary +instanceKlass java/util/Map +instanceKlass java/lang/ThreadGroup +instanceKlass java/lang/Thread$UncaughtExceptionHandler +instanceKlass java/lang/Thread +instanceKlass java/lang/Runnable +instanceKlass java/lang/ref/Reference +instanceKlass java/security/AccessControlContext +instanceKlass java/security/ProtectionDomain +instanceKlass java/lang/SecurityManager +instanceKlass java/lang/Throwable +instanceKlass java/lang/System +instanceKlass java/lang/ClassLoader +instanceKlass java/lang/Cloneable +instanceKlass java/lang/Class +instanceKlass java/lang/reflect/Type +instanceKlass java/lang/reflect/GenericDeclaration +instanceKlass java/lang/reflect/AnnotatedElement +instanceKlass java/lang/String +instanceKlass java/lang/CharSequence +instanceKlass java/lang/Comparable +instanceKlass java/io/Serializable +ciInstanceKlass java/lang/Object 1 1 78 3 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 7 7 100 7 7 7 7 7 1 1 1 12 12 12 12 12 12 12 12 12 12 10 10 10 10 10 10 10 10 10 10 1 +ciInstanceKlass java/io/Serializable 1 0 7 1 1 1 100 100 1 +ciInstanceKlass java/lang/String 1 1 540 3 3 3 3 8 8 8 8 8 8 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 0 100 100 100 100 7 7 100 100 100 7 7 100 100 7 100 100 100 7 100 100 7 100 7 7 100 7 100 100 7 100 7 100 100 7 7 7 7 100 7 7 100 100 7 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 11 11 11 11 11 11 1 1 +staticfield java/lang/String serialPersistentFields [Ljava/io/ObjectStreamField; 0 [Ljava/io/ObjectStreamField; +staticfield java/lang/String CASE_INSENSITIVE_ORDER Ljava/util/Comparator; java/lang/String$CaseInsensitiveComparator +ciInstanceKlass java/lang/Class 1 1 1190 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 5 0 8 8 8 8 8 7 7 7 100 100 100 7 7 100 7 100 7 7 7 7 100 7 7 100 7 100 100 100 7 100 100 100 100 100 100 7 7 7 7 100 100 100 7 7 7 100 100 100 7 100 100 7 7 100 7 100 7 7 100 100 7 7 100 100 100 100 7 100 7 7 100 7 7 7 7 100 100 7 7 7 7 100 7 100 7 7 100 100 7 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 1 1 1 1 1 1 1 1 +staticfield java/lang/Class serialPersistentFields [Ljava/io/ObjectStreamField; 0 [Ljava/io/ObjectStreamField; +ciInstanceKlass java/lang/Cloneable 1 0 7 1 1 1 100 100 1 +instanceKlass java/util/ResourceBundle$RBClassLoader +instanceKlass sun/reflect/DelegatingClassLoader +instanceKlass java/security/SecureClassLoader +ciInstanceKlass java/lang/ClassLoader 1 1 842 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 100 7 7 7 7 100 7 100 7 7 100 7 7 7 7 100 7 100 7 100 100 7 7 100 100 7 100 7 7 100 100 100 100 7 100 100 7 7 100 7 7 100 7 7 7 7 7 7 7 7 7 7 7 7 7 100 7 7 7 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 11 11 11 11 1 1 +staticfield java/lang/ClassLoader nocerts [Ljava/security/cert/Certificate; 0 [Ljava/security/cert/Certificate; +ciInstanceKlass java/lang/System 1 1 369 8 8 8 8 8 8 8 8 8 8 8 8 8 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 7 7 7 7 7 100 7 100 100 100 100 100 100 7 7 100 100 7 100 100 7 7 7 7 100 100 100 7 100 100 7 7 7 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 1 +staticfield java/lang/System in Ljava/io/InputStream; java/io/BufferedInputStream +staticfield java/lang/System out Ljava/io/PrintStream; org/apache/maven/surefire/report/ConsoleOutputCapture$ForwardingPrintStream +staticfield java/lang/System err Ljava/io/PrintStream; org/apache/maven/surefire/report/ConsoleOutputCapture$ForwardingPrintStream +instanceKlass org/junit/Test$None +instanceKlass java/lang/Exception +instanceKlass java/lang/Error +ciInstanceKlass java/lang/Throwable 1 1 327 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 0 7 100 100 100 100 100 100 7 100 100 100 100 7 7 100 7 100 100 100 7 100 100 7 7 7 7 100 100 100 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 11 11 11 11 11 11 1 1 1 1 1 +staticfield java/lang/Throwable UNASSIGNED_STACK [Ljava/lang/StackTraceElement; 0 [Ljava/lang/StackTraceElement; +staticfield java/lang/Throwable SUPPRESSED_SENTINEL Ljava/util/List; java/util/Collections$UnmodifiableRandomAccessList +staticfield java/lang/Throwable EMPTY_THROWABLE_ARRAY [Ljava/lang/Throwable; 0 [Ljava/lang/Throwable; +staticfield java/lang/Throwable $assertionsDisabled Z 1 +instanceKlass javax/xml/parsers/FactoryConfigurationError +instanceKlass java/lang/AssertionError +instanceKlass java/lang/VirtualMachineError +instanceKlass java/lang/LinkageError +instanceKlass java/lang/ThreadDeath +ciInstanceKlass java/lang/Error 1 1 30 1 1 1 1 1 1 1 1 1 1 1 1 5 0 100 7 1 1 12 12 12 12 12 10 10 10 10 10 1 +ciInstanceKlass java/lang/ThreadDeath 0 0 18 1 1 1 1 1 1 1 1 1 1 5 0 100 100 12 10 1 +instanceKlass org/junit/runners/model/MultipleFailureException +instanceKlass java/text/ParseException +instanceKlass java/sql/SQLException +instanceKlass javax/xml/stream/XMLStreamException +instanceKlass com/sun/xml/bind/v2/model/impl/ClassInfoImpl$ConflictException +instanceKlass com/sun/xml/bind/v2/model/impl/ClassInfoImpl$DuplicateException +instanceKlass javax/activation/MimeTypeParseException +instanceKlass java/net/URISyntaxException +instanceKlass javax/xml/datatype/DatatypeConfigurationException +instanceKlass com/sun/xml/bind/api/AccessorException +instanceKlass javax/xml/transform/TransformerException +instanceKlass javax/xml/parsers/ParserConfigurationException +instanceKlass org/xml/sax/SAXException +instanceKlass javax/xml/bind/JAXBException +instanceKlass java/beans/PropertyVetoException +instanceKlass org/apache/log4j/config/PropertySetterException +instanceKlass java/beans/IntrospectionException +instanceKlass org/junit/runner/manipulation/NoTestsRemainException +instanceKlass org/junit/runners/model/InitializationError +instanceKlass java/lang/CloneNotSupportedException +instanceKlass mage/MageException +instanceKlass java/security/PrivilegedActionException +instanceKlass org/apache/maven/surefire/util/NestedCheckedException +instanceKlass java/io/IOException +instanceKlass java/lang/InterruptedException +instanceKlass java/lang/ReflectiveOperationException +instanceKlass java/lang/RuntimeException +ciInstanceKlass java/lang/Exception 1 1 30 1 1 1 1 1 1 1 1 1 1 1 1 5 0 100 7 1 1 12 12 12 12 12 10 10 10 10 10 1 +instanceKlass org/h2/message/DbException +instanceKlass java/util/NoSuchElementException +instanceKlass java/lang/reflect/MalformedParameterizedTypeException +instanceKlass java/lang/SecurityException +instanceKlass java/lang/IndexOutOfBoundsException +instanceKlass java/util/MissingResourceException +instanceKlass org/junit/internal/AssumptionViolatedException +instanceKlass org/junit/runner/notification/StoppedByUserException +instanceKlass java/lang/reflect/UndeclaredThrowableException +instanceKlass java/lang/UnsupportedOperationException +instanceKlass org/apache/maven/surefire/util/NestedRuntimeException +instanceKlass java/lang/IllegalStateException +instanceKlass java/lang/IllegalArgumentException +instanceKlass java/lang/ArithmeticException +instanceKlass java/lang/NullPointerException +instanceKlass java/lang/IllegalMonitorStateException +instanceKlass java/lang/ArrayStoreException +instanceKlass java/lang/ClassCastException +ciInstanceKlass java/lang/RuntimeException 1 1 30 1 1 1 1 1 1 1 1 1 1 1 1 5 0 7 100 1 1 12 12 12 12 12 10 10 10 10 10 1 +ciInstanceKlass java/lang/SecurityManager 0 0 375 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 1 +ciInstanceKlass java/security/ProtectionDomain 1 1 272 8 8 8 8 8 8 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 100 7 100 100 100 100 100 100 100 100 100 7 7 100 7 7 100 7 7 7 100 100 100 7 7 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 11 11 11 11 11 1 1 +staticfield java/security/ProtectionDomain debug Lsun/security/util/Debug; null +ciInstanceKlass java/security/AccessControlContext 1 1 305 8 8 8 8 8 8 8 8 8 8 8 8 8 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 100 100 7 100 100 100 100 100 7 100 100 7 100 100 100 100 7 100 100 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 11 11 11 11 1 +instanceKlass java/net/URLClassLoader +ciInstanceKlass java/security/SecureClassLoader 1 1 130 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 7 100 100 100 100 7 100 7 7 7 7 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 1 +staticfield java/security/SecureClassLoader debug Lsun/security/util/Debug; null +instanceKlass java/lang/NoSuchFieldException +instanceKlass java/lang/InstantiationException +instanceKlass java/lang/NoSuchMethodException +instanceKlass java/lang/IllegalAccessException +instanceKlass java/lang/reflect/InvocationTargetException +instanceKlass java/lang/ClassNotFoundException +ciInstanceKlass java/lang/ReflectiveOperationException 1 1 27 1 1 1 1 1 1 1 1 1 1 1 1 5 0 7 100 1 12 12 12 12 10 10 10 10 1 +ciInstanceKlass java/lang/ClassNotFoundException 1 1 32 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 0 100 7 100 1 1 1 12 12 12 9 10 10 1 +instanceKlass java/lang/ClassFormatError +instanceKlass java/lang/ExceptionInInitializerError +instanceKlass java/lang/IncompatibleClassChangeError +instanceKlass java/lang/BootstrapMethodError +instanceKlass java/lang/NoClassDefFoundError +ciInstanceKlass java/lang/LinkageError 1 1 24 1 1 1 1 1 1 1 1 1 1 1 5 0 7 100 1 12 12 12 10 10 10 1 +ciInstanceKlass java/lang/NoClassDefFoundError 1 1 21 1 1 1 1 1 1 1 1 1 1 1 5 0 7 100 12 12 10 10 1 +ciInstanceKlass java/lang/ClassCastException 1 1 21 1 1 1 1 1 1 1 1 1 1 1 5 0 100 100 12 12 10 10 1 +ciInstanceKlass java/lang/ArrayStoreException 1 1 21 1 1 1 1 1 1 1 1 1 1 1 5 0 100 100 12 12 10 10 1 +instanceKlass java/lang/InternalError +instanceKlass java/lang/StackOverflowError +instanceKlass java/lang/OutOfMemoryError +ciInstanceKlass java/lang/VirtualMachineError 1 1 27 1 1 1 1 1 1 1 1 1 1 1 1 5 0 100 100 1 12 12 12 12 10 10 10 10 1 +ciInstanceKlass java/lang/OutOfMemoryError 1 1 21 1 1 1 1 1 1 1 1 1 1 1 5 0 100 100 12 12 10 10 1 +ciInstanceKlass java/lang/StackOverflowError 1 1 21 1 1 1 1 1 1 1 1 1 1 1 5 0 100 100 12 12 10 10 1 +ciInstanceKlass java/lang/IllegalMonitorStateException 1 1 21 1 1 1 1 1 1 1 1 1 1 1 5 0 100 100 12 12 10 10 1 +instanceKlass java/lang/ref/PhantomReference +instanceKlass java/lang/ref/FinalReference +instanceKlass java/lang/ref/WeakReference +instanceKlass java/lang/ref/SoftReference +ciInstanceKlass java/lang/ref/Reference 1 1 134 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 7 100 7 7 100 7 7 7 7 7 7 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 1 1 1 +instanceKlass sun/util/locale/provider/LocaleResources$ResourceReference +instanceKlass java/util/ResourceBundle$BundleReference +instanceKlass sun/util/locale/LocaleObjectCache$CacheEntry +ciInstanceKlass java/lang/ref/SoftReference 1 1 35 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 7 7 1 1 1 1 12 12 12 12 12 9 9 10 10 10 1 +instanceKlass sun/nio/ch/SharedFileLockTable$FileLockReference +instanceKlass java/lang/reflect/Proxy$Key2 +instanceKlass java/util/logging/LogManager$LoggerWeakRef +instanceKlass java/beans/WeakIdentityMap$Entry +instanceKlass java/util/ResourceBundle$LoaderReference +instanceKlass java/io/ObjectStreamClass$FieldReflectorKey +instanceKlass java/io/ObjectStreamClass$WeakClassKey +instanceKlass java/lang/reflect/WeakCache$CacheValue +instanceKlass java/lang/reflect/Proxy$Key1 +instanceKlass java/lang/reflect/WeakCache$CacheKey +instanceKlass java/lang/ThreadLocal$ThreadLocalMap$Entry +instanceKlass java/lang/ClassValue$Entry +instanceKlass java/util/WeakHashMap$Entry +ciInstanceKlass java/lang/ref/WeakReference 1 1 20 1 1 1 1 1 1 1 1 7 100 1 1 1 1 12 12 10 10 1 +instanceKlass java/lang/ref/Finalizer +ciInstanceKlass java/lang/ref/FinalReference 1 1 16 1 1 1 1 1 1 1 100 7 1 1 1 12 10 1 +instanceKlass org/h2/util/CloseWatcher +instanceKlass sun/misc/Cleaner +ciInstanceKlass java/lang/ref/PhantomReference 1 1 19 1 1 1 1 1 1 1 1 1 1 100 7 1 1 1 12 10 1 +ciInstanceKlass sun/misc/Cleaner 1 1 74 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 7 7 100 7 100 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 10 10 10 10 10 10 10 11 1 +staticfield sun/misc/Cleaner dummyQueue Ljava/lang/ref/ReferenceQueue; java/lang/ref/ReferenceQueue +ciInstanceKlass java/lang/ref/Finalizer 1 1 148 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 7 7 7 7 100 7 7 100 100 100 7 7 100 7 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 1 1 +staticfield java/lang/ref/Finalizer lock Ljava/lang/Object; java/lang/Object +instanceKlass org/h2/mvstore/MVStore$BackgroundWriterThread +instanceKlass org/h2/engine/DatabaseCloser +instanceKlass java/util/logging/LogManager$Cleaner +instanceKlass java/lang/ref/Finalizer$FinalizerThread +instanceKlass java/lang/ref/Reference$ReferenceHandler +ciInstanceKlass java/lang/Thread 1 1 539 3 3 8 8 8 8 8 8 8 8 8 8 8 8 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 100 100 100 100 100 100 100 100 100 7 100 100 7 7 7 100 7 100 7 7 100 100 100 100 100 100 7 100 100 100 100 100 100 100 7 100 100 100 100 100 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 11 11 11 11 11 1 1 1 1 1 +staticfield java/lang/Thread EMPTY_STACK_TRACE [Ljava/lang/StackTraceElement; 0 [Ljava/lang/StackTraceElement; +staticfield java/lang/Thread SUBCLASS_IMPLEMENTATION_PERMISSION Ljava/lang/RuntimePermission; java/lang/RuntimePermission +ciInstanceKlass java/lang/ThreadGroup 1 1 268 8 8 8 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 100 100 100 100 7 100 100 7 7 100 100 7 100 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 1 1 +instanceKlass java/util/Hashtable +ciInstanceKlass java/util/Dictionary 1 1 31 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 7 100 1 1 1 1 1 1 12 10 1 +instanceKlass java/util/Properties +ciInstanceKlass java/util/Hashtable 1 1 402 3 3 4 4 8 8 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 5 0 100 100 100 100 100 100 100 100 100 100 7 100 100 7 100 7 100 100 100 7 100 7 7 100 7 7 7 7 100 7 7 7 7 7 100 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 11 11 11 11 11 11 11 11 11 11 1 1 1 1 1 +instanceKlass java/security/Provider +instanceKlass org/h2/util/SortedProperties +ciInstanceKlass java/util/Properties 1 1 263 3 8 8 8 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 0 100 7 100 100 100 7 100 100 100 100 100 7 7 7 100 7 7 7 100 100 7 7 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 1 1 1 +staticfield java/util/Properties hexDigit [C 16 +instanceKlass java/lang/reflect/Executable +instanceKlass java/lang/reflect/Field +ciInstanceKlass java/lang/reflect/AccessibleObject 1 1 144 8 8 8 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 100 7 100 100 7 7 7 7 100 7 7 7 7 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 1 1 +staticfield java/lang/reflect/AccessibleObject ACCESS_PERMISSION Ljava/security/Permission; java/lang/reflect/ReflectPermission +staticfield java/lang/reflect/AccessibleObject reflectionFactory Lsun/reflect/ReflectionFactory; sun/reflect/ReflectionFactory +ciInstanceKlass java/lang/reflect/Field 1 1 362 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 7 100 100 100 100 7 7 7 100 100 100 7 7 7 7 7 100 7 7 100 100 100 100 7 7 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 1 1 +ciInstanceKlass java/lang/reflect/Parameter 0 0 210 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 11 11 1 +instanceKlass java/lang/reflect/Constructor +instanceKlass java/lang/reflect/Method +ciInstanceKlass java/lang/reflect/Executable 1 1 378 3 8 8 8 8 8 8 8 8 8 8 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 100 100 100 100 7 100 100 100 100 7 7 7 7 100 100 100 7 100 7 100 7 7 7 7 7 100 100 100 100 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 11 1 1 +ciInstanceKlass java/lang/reflect/Method 1 1 346 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 7 7 7 100 100 7 7 7 100 7 100 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 11 1 +ciInstanceKlass java/lang/reflect/Constructor 1 1 330 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 7 100 7 100 100 100 100 100 100 7 7 100 100 100 100 100 7 7 7 100 100 100 100 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 1 1 +instanceKlass sun/reflect/FieldAccessorImpl +instanceKlass sun/reflect/ConstructorAccessorImpl +instanceKlass sun/reflect/MethodAccessorImpl +ciInstanceKlass sun/reflect/MagicAccessorImpl 1 1 13 1 1 1 1 1 1 1 7 100 12 10 1 +instanceKlass sun/reflect/GeneratedMethodAccessor8 +instanceKlass sun/reflect/GeneratedMethodAccessor7 +instanceKlass sun/reflect/GeneratedMethodAccessor6 +instanceKlass sun/reflect/GeneratedMethodAccessor5 +instanceKlass sun/reflect/GeneratedMethodAccessor4 +instanceKlass sun/reflect/GeneratedMethodAccessor3 +instanceKlass sun/reflect/GeneratedMethodAccessor2 +instanceKlass sun/reflect/GeneratedMethodAccessor1 +instanceKlass sun/reflect/DelegatingMethodAccessorImpl +instanceKlass sun/reflect/NativeMethodAccessorImpl +ciInstanceKlass sun/reflect/MethodAccessorImpl 1 1 22 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 7 100 100 12 10 1 +instanceKlass sun/reflect/GeneratedConstructorAccessor4 +instanceKlass sun/reflect/SerializationConstructorAccessorImpl +instanceKlass sun/reflect/BootstrapConstructorAccessorImpl +instanceKlass sun/reflect/DelegatingConstructorAccessorImpl +instanceKlass sun/reflect/NativeConstructorAccessorImpl +ciInstanceKlass sun/reflect/ConstructorAccessorImpl 1 1 24 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 100 100 100 7 12 10 1 +ciInstanceKlass sun/reflect/DelegatingClassLoader 1 1 13 1 1 1 1 1 1 1 7 100 1 12 10 +ciInstanceKlass sun/reflect/ConstantPool 1 1 106 8 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 7 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 1 +instanceKlass sun/reflect/UnsafeFieldAccessorImpl +ciInstanceKlass sun/reflect/FieldAccessorImpl 1 1 56 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 100 100 7 1 1 1 1 1 1 1 1 1 1 1 1 1 12 10 1 +instanceKlass sun/reflect/UnsafeBooleanFieldAccessorImpl +instanceKlass sun/reflect/UnsafeObjectFieldAccessorImpl +instanceKlass sun/reflect/UnsafeStaticFieldAccessorImpl +ciInstanceKlass sun/reflect/UnsafeFieldAccessorImpl 1 1 229 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 100 7 100 100 100 100 100 100 7 100 100 100 7 7 7 7 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 1 +staticfield sun/reflect/UnsafeFieldAccessorImpl unsafe Lsun/misc/Unsafe; sun/misc/Unsafe +instanceKlass sun/reflect/UnsafeQualifiedStaticFieldAccessorImpl +ciInstanceKlass sun/reflect/UnsafeStaticFieldAccessorImpl 1 1 38 8 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 7 7 7 7 1 1 1 1 12 12 12 12 12 9 9 10 10 10 1 +ciInstanceKlass sun/reflect/CallerSensitive 0 0 17 1 1 1 1 1 1 1 1 100 100 100 1 1 1 1 1 +instanceKlass java/lang/invoke/DirectMethodHandle +ciInstanceKlass java/lang/invoke/MethodHandle 1 1 438 8 8 8 8 8 8 8 8 8 8 8 8 8 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 7 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 7 100 7 100 100 100 100 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 1 1 1 +staticfield java/lang/invoke/MethodHandle FORM_OFFSET J 20 +staticfield java/lang/invoke/MethodHandle $assertionsDisabled Z 1 +ciInstanceKlass java/lang/invoke/DirectMethodHandle 0 0 692 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 100 100 100 100 100 100 100 100 100 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 1 1 1 1 1 1 1 1 1 +ciInstanceKlass java/lang/invoke/MemberName 1 1 642 3 3 3 3 3 3 3 3 3 3 3 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 100 100 7 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 3 3 100 100 100 100 100 100 7 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 1 1 1 1 +staticfield java/lang/invoke/MemberName $assertionsDisabled Z 1 +ciInstanceKlass java/lang/invoke/MethodHandleNatives 1 1 427 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 100 100 100 7 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 100 100 7 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 7 100 100 100 100 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 1 1 1 +staticfield java/lang/invoke/MethodHandleNatives COUNT_GWT Z 1 +staticfield java/lang/invoke/MethodHandleNatives $assertionsDisabled Z 1 +ciInstanceKlass java/lang/invoke/LambdaForm 0 0 967 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 100 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 8 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 11 11 11 1 1 1 1 1 1 +ciInstanceKlass java/lang/invoke/MethodType 0 0 591 8 8 8 8 8 8 8 8 8 8 8 8 100 100 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 5 0 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 11 11 1 1 +ciInstanceKlass java/lang/BootstrapMethodError 0 0 38 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 0 100 100 100 100 1 1 12 12 12 12 12 10 10 10 10 10 1 +instanceKlass java/lang/invoke/VolatileCallSite +instanceKlass java/lang/invoke/MutableCallSite +instanceKlass java/lang/invoke/ConstantCallSite +ciInstanceKlass java/lang/invoke/CallSite 0 0 311 8 8 8 8 8 8 8 8 100 100 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 1 1 +ciInstanceKlass java/lang/invoke/ConstantCallSite 0 0 42 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 100 100 100 1 1 12 12 12 12 12 12 9 9 10 10 10 10 10 1 +ciInstanceKlass java/lang/invoke/MutableCallSite 0 0 57 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 100 100 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 9 9 10 10 10 10 10 10 10 10 1 +ciInstanceKlass java/lang/invoke/VolatileCallSite 0 0 33 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 1 1 1 12 12 12 12 12 12 10 10 10 10 10 10 1 +instanceKlass java/lang/StringBuilder +instanceKlass java/lang/StringBuffer +ciInstanceKlass java/lang/AbstractStringBuilder 1 1 318 3 3 3 8 8 8 8 8 8 8 8 8 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 0 100 7 100 7 100 100 100 7 7 7 100 7 100 100 100 7 7 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 1 +ciInstanceKlass java/lang/StringBuffer 1 1 371 8 8 8 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 0 100 100 100 100 100 7 100 7 7 100 100 7 7 7 100 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 1 1 1 +staticfield java/lang/StringBuffer serialPersistentFields [Ljava/io/ObjectStreamField; 3 [Ljava/io/ObjectStreamField; +ciInstanceKlass java/lang/StringBuilder 1 1 326 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 0 100 100 100 100 100 7 100 100 7 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 1 +ciInstanceKlass sun/misc/Unsafe 1 1 389 8 8 7 7 7 7 7 7 7 7 7 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 100 7 100 100 7 100 7 100 100 7 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 1 +staticfield sun/misc/Unsafe theUnsafe Lsun/misc/Unsafe; sun/misc/Unsafe +staticfield sun/misc/Unsafe ARRAY_BOOLEAN_BASE_OFFSET I 16 +staticfield sun/misc/Unsafe ARRAY_BYTE_BASE_OFFSET I 16 +staticfield sun/misc/Unsafe ARRAY_SHORT_BASE_OFFSET I 16 +staticfield sun/misc/Unsafe ARRAY_CHAR_BASE_OFFSET I 16 +staticfield sun/misc/Unsafe ARRAY_INT_BASE_OFFSET I 16 +staticfield sun/misc/Unsafe ARRAY_LONG_BASE_OFFSET I 16 +staticfield sun/misc/Unsafe ARRAY_FLOAT_BASE_OFFSET I 16 +staticfield sun/misc/Unsafe ARRAY_DOUBLE_BASE_OFFSET I 16 +staticfield sun/misc/Unsafe ARRAY_OBJECT_BASE_OFFSET I 16 +staticfield sun/misc/Unsafe ARRAY_BOOLEAN_INDEX_SCALE I 1 +staticfield sun/misc/Unsafe ARRAY_BYTE_INDEX_SCALE I 1 +staticfield sun/misc/Unsafe ARRAY_SHORT_INDEX_SCALE I 2 +staticfield sun/misc/Unsafe ARRAY_CHAR_INDEX_SCALE I 2 +staticfield sun/misc/Unsafe ARRAY_INT_INDEX_SCALE I 4 +staticfield sun/misc/Unsafe ARRAY_LONG_INDEX_SCALE I 8 +staticfield sun/misc/Unsafe ARRAY_FLOAT_INDEX_SCALE I 4 +staticfield sun/misc/Unsafe ARRAY_DOUBLE_INDEX_SCALE I 8 +staticfield sun/misc/Unsafe ARRAY_OBJECT_INDEX_SCALE I 4 +staticfield sun/misc/Unsafe ADDRESS_SIZE I 8 +instanceKlass org/h2/util/AutoCloseInputStream +instanceKlass org/h2/mvstore/StreamStore$Stream +instanceKlass org/h2/store/CountingReaderInputStream +instanceKlass java/io/SequenceInputStream +instanceKlass org/h2/store/fs/FileChannelInputStream +instanceKlass com/sun/org/apache/xerces/internal/impl/XMLEntityManager$RewindableInputStream +instanceKlass java/io/ObjectInputStream +instanceKlass java/util/zip/ZipFile$ZipFileInputStream +instanceKlass java/io/FilterInputStream +instanceKlass java/io/FileInputStream +instanceKlass java/io/ByteArrayInputStream +ciInstanceKlass java/io/InputStream 1 1 61 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 5 0 100 100 100 7 100 100 100 7 12 12 12 12 12 10 10 10 10 10 10 10 1 +ciInstanceKlass java/io/ByteArrayInputStream 1 1 62 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 7 100 7 100 100 100 7 1 12 12 12 12 12 12 12 9 9 9 9 10 10 10 10 10 1 +ciInstanceKlass java/io/File 1 1 578 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 0 7 100 7 100 7 100 100 7 100 100 100 100 100 100 100 7 100 100 100 100 100 7 100 100 100 100 7 7 7 100 100 7 100 7 7 7 100 7 100 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 11 11 11 1 1 1 1 +staticfield java/io/File fs Ljava/io/FileSystem; java/io/WinNTFileSystem +staticfield java/io/File separatorChar C 92 +staticfield java/io/File separator Ljava/lang/String; "\" +staticfield java/io/File pathSeparatorChar C 59 +staticfield java/io/File pathSeparator Ljava/lang/String; ";" +staticfield java/io/File PATH_OFFSET J 16 +staticfield java/io/File PREFIX_LENGTH_OFFSET J 12 +staticfield java/io/File UNSAFE Lsun/misc/Unsafe; sun/misc/Unsafe +staticfield java/io/File $assertionsDisabled Z 1 +instanceKlass mage/server/util/PluginClassLoader +instanceKlass org/apache/maven/surefire/booter/IsolatedClassLoader +instanceKlass sun/misc/Launcher$ExtClassLoader +instanceKlass sun/misc/Launcher$AppClassLoader +ciInstanceKlass java/net/URLClassLoader 1 1 522 8 8 8 8 8 8 8 8 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 7 7 100 100 100 7 7 7 100 100 7 100 100 100 7 7 7 100 7 100 7 7 7 7 7 100 100 100 7 7 100 100 100 7 7 7 7 7 7 100 100 100 7 7 7 100 7 7 7 7 7 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 11 11 11 11 11 11 +ciInstanceKlass java/net/URL 1 1 550 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 0 100 100 100 100 100 100 7 100 7 7 100 100 100 100 100 7 7 100 7 7 100 100 100 100 7 100 100 100 100 7 7 7 100 100 7 7 7 100 7 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 1 +staticfield java/net/URL serialPersistentFields [Ljava/io/ObjectStreamField; 7 [Ljava/io/ObjectStreamField; +ciInstanceKlass java/util/jar/Manifest 1 1 230 8 8 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 100 100 100 100 7 7 7 100 100 7 100 7 100 100 7 7 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 11 11 11 11 11 11 11 11 11 11 1 1 +ciInstanceKlass sun/misc/Launcher 1 1 218 8 8 8 8 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 7 100 100 100 100 100 100 100 100 7 100 7 100 7 7 100 7 7 100 7 7 7 7 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 1 1 1 1 +ciInstanceKlass sun/misc/Launcher$AppClassLoader 1 1 201 8 8 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 100 100 100 7 7 100 7 100 7 7 100 100 7 100 7 100 7 100 7 7 7 100 7 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 1 +staticfield sun/misc/Launcher$AppClassLoader $assertionsDisabled Z 1 +ciInstanceKlass sun/misc/Launcher$ExtClassLoader 1 1 209 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 100 100 7 100 7 7 7 7 7 100 7 100 100 100 7 7 7 7 7 7 100 7 7 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 1 +ciInstanceKlass java/security/CodeSource 1 1 322 8 8 8 8 8 8 8 8 8 8 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 0 100 100 100 100 100 100 100 100 100 7 100 100 100 100 7 100 7 100 100 100 100 100 100 100 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 11 11 1 +ciInstanceKlass java/lang/StackTraceElement 1 1 98 8 8 8 8 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 0 100 100 7 7 7 7 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 1 +instanceKlass java/nio/LongBuffer +instanceKlass java/nio/CharBuffer +instanceKlass java/nio/ByteBuffer +ciInstanceKlass java/nio/Buffer 1 1 103 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 100 100 7 100 7 100 100 100 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 1 +ciInstanceKlass java/lang/Boolean 1 1 110 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 0 100 7 7 100 100 100 7 100 7 7 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 10 10 10 10 10 10 10 10 10 10 1 +staticfield java/lang/Boolean TRUE Ljava/lang/Boolean; java/lang/Boolean +staticfield java/lang/Boolean FALSE Ljava/lang/Boolean; java/lang/Boolean +staticfield java/lang/Boolean TYPE Ljava/lang/Class; java/lang/Class +ciInstanceKlass java/lang/Character 1 1 459 3 3 3 3 3 3 3 3 8 8 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 5 0 5 0 100 100 7 7 100 100 100 7 100 7 100 100 100 100 7 100 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 1 1 1 1 1 +staticfield java/lang/Character TYPE Ljava/lang/Class; java/lang/Class +staticfield java/lang/Character $assertionsDisabled Z 1 +instanceKlass java/math/BigDecimal +instanceKlass java/math/BigInteger +instanceKlass java/util/concurrent/atomic/AtomicLong +instanceKlass java/util/concurrent/atomic/AtomicInteger +instanceKlass java/lang/Long +instanceKlass java/lang/Integer +instanceKlass java/lang/Short +instanceKlass java/lang/Byte +instanceKlass java/lang/Double +instanceKlass java/lang/Float +ciInstanceKlass java/lang/Number 1 1 34 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 0 100 100 7 12 12 10 10 1 +ciInstanceKlass java/lang/Float 1 1 169 3 3 3 4 4 4 4 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 4 4 5 0 7 100 100 7 100 7 100 100 7 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 1 +staticfield java/lang/Float TYPE Ljava/lang/Class; java/lang/Class +ciInstanceKlass java/lang/Double 1 1 223 8 8 8 8 8 8 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 5 0 5 0 5 0 5 0 5 0 6 0 6 0 6 0 6 0 6 0 6 0 6 0 7 100 7 100 100 7 100 100 100 7 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 1 +staticfield java/lang/Double TYPE Ljava/lang/Class; java/lang/Class +ciInstanceKlass java/lang/Byte 1 1 153 8 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 5 0 5 0 7 7 7 100 100 7 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 1 1 +staticfield java/lang/Byte TYPE Ljava/lang/Class; java/lang/Class +ciInstanceKlass java/lang/Short 1 1 159 3 3 8 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 5 0 5 0 7 100 100 7 100 7 7 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 1 1 +staticfield java/lang/Short TYPE Ljava/lang/Class; java/lang/Class +ciInstanceKlass java/lang/Integer 1 1 309 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 5 0 5 0 5 0 100 7 7 100 100 7 7 100 7 100 7 100 100 100 7 100 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 1 1 +staticfield java/lang/Integer TYPE Ljava/lang/Class; java/lang/Class +staticfield java/lang/Integer digits [C 36 +staticfield java/lang/Integer DigitTens [C 100 +staticfield java/lang/Integer DigitOnes [C 100 +staticfield java/lang/Integer sizeTable [I 10 +ciInstanceKlass java/lang/Long 1 1 356 3 3 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 100 100 7 100 100 7 7 7 7 100 7 100 100 100 7 100 100 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 1 1 +staticfield java/lang/Long TYPE Ljava/lang/Class; java/lang/Class +ciInstanceKlass java/lang/NullPointerException 1 1 21 1 1 1 1 1 1 1 1 1 1 1 5 0 100 7 12 12 10 10 1 +ciInstanceKlass java/lang/ArithmeticException 1 1 21 1 1 1 1 1 1 1 1 1 1 1 5 0 100 100 12 12 10 10 1 +instanceKlass java/lang/ref/ReferenceQueue$Null +ciInstanceKlass java/lang/ref/ReferenceQueue 1 1 121 8 7 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 5 0 100 7 100 100 7 100 100 7 7 100 7 7 7 1 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 1 1 +staticfield java/lang/ref/ReferenceQueue $assertionsDisabled Z 1 +ciInstanceKlass java/lang/ref/ReferenceQueue$Lock 1 1 21 1 1 1 1 1 1 1 1 1 1 7 100 100 7 1 12 10 10 1 1 +ciInstanceKlass sun/misc/VM 1 1 226 8 8 8 8 8 8 8 8 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 3 5 0 5 0 100 100 100 100 7 7 7 100 100 100 100 7 7 7 1 1 1 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 1 +staticfield sun/misc/VM lock Ljava/lang/Object; java/lang/Object +staticfield sun/misc/VM savedProps Ljava/util/Properties; java/util/Properties +ciInstanceKlass java/util/WeakHashMap$Entry 1 1 91 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100 100 7 100 100 100 100 7 1 1 1 1 1 1 1 1 1 12 12 12 12 12 12 12 12 12 12 12 12 12 12 9 9 9 10 10 10 10 10 10 10 10 10 10 10 11 11 1 +compile java/lang/ref/ReferenceQueue poll ()Ljava/lang/ref/Reference; -1 4 inline 1 0 -1 java/lang/ref/ReferenceQueue poll ()Ljava/lang/ref/Reference; diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/equipped/EquipRestrictedTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/equipped/EquipRestrictedTest.java new file mode 100644 index 0000000000..facac264dd --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/equipped/EquipRestrictedTest.java @@ -0,0 +1,122 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package org.mage.test.cards.abilities.equipped; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.game.permanent.Permanent; +import org.junit.Assert; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class EquipRestrictedTest extends CardTestPlayerBase { + + @Test + public void testEquipLeoninScimitarToNonLegendary() { + addCard(Zone.BATTLEFIELD, playerB, "Auriok Windwalker"); + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); + addCard(Zone.BATTLEFIELD, playerB, "Leonin Scimitar"); + + activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{T}: Attach target Equipment you control to target creature you control.", "Leonin Scimitar"); + addTarget(playerB, "Silvercout Lion"); + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + + Permanent equipment = getPermanent("Leonin Scimitar", playerB); + Assert.assertTrue("Leonin Scimitar has to be attached", equipment.getAttachedTo() != null); + } + + /** + * Konda's Banner, Gate Smasher, and O-Naginata can all be attached to + * creatures that they should not be able to be attached to. The filter is + * only applied to the EquipAbility and does not check other methods (such + * as Auriok Windwaker) + */ + @Test + public void testEquipKondasBannerToNonLegendary() { + addCard(Zone.BATTLEFIELD, playerB, "Auriok Windwalker"); + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); + addCard(Zone.BATTLEFIELD, playerB, "Konda's Banner"); + + activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{T}: Attach target Equipment you control to target creature you control.", "Konda's Banner"); + addTarget(playerB, "Silvercout Lion"); + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + + Permanent equipment = getPermanent("Konda's Banner", playerB); + Assert.assertTrue("Konda's Banner may not be attached", equipment.getAttachedTo() == null); + } + + @Test + public void testEquipGateSmasher() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 5); + // {1}{W}: Kranioceros gets +0/+3 until end of turn. + addCard(Zone.BATTLEFIELD, playerA, "Kranioceros");// 5/2 + // Gate Smasher can be attached only to a creature with toughness 4 or greater. + // Equipped creature gets +3/+0 and has trample. + // Equip {3} + addCard(Zone.BATTLEFIELD, playerA, "Gate Smasher"); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{W}:"); + activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Equip", "Kranioceros"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPowerToughness(playerA, "Kranioceros", 8, 5); + Permanent equipment = getPermanent("Gate Smasher", playerA); + Assert.assertTrue("Gate Smasher may no longer be attached", equipment.getAttachedTo() != null); + } + + @Test + public void testEquipGateSmasherAndUnattached() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 5); + // {1}{W}: Kranioceros gets +0/+3 until end of turn. + addCard(Zone.BATTLEFIELD, playerA, "Kranioceros");// 5/2 + // Gate Smasher can be attached only to a creature with toughness 4 or greater. + // Equipped creature gets +3/+0 and has trample. + // Equip {3} + addCard(Zone.BATTLEFIELD, playerA, "Gate Smasher"); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{W}:"); + activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Equip", "Kranioceros"); + + setStopAt(2, PhaseStep.PRECOMBAT_MAIN); + execute(); + + assertPowerToughness(playerA, "Kranioceros", 5, 2); + Permanent equipment = getPermanent("Gate Smasher", playerA); + Assert.assertTrue("Gate Smasher may no longer be attached", equipment.getAttachedTo() == null); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/LazavDimirMastermindTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/LazavDimirMastermindTest.java index 0614fbfb55..bba2800208 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/LazavDimirMastermindTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/LazavDimirMastermindTest.java @@ -48,7 +48,7 @@ public class LazavDimirMastermindTest extends CardTestPlayerBase { assertPowerToughness(playerA, "Lazav, Dimir Mastermind", 3, 2); Permanent lazav = getPermanent("Lazav, Dimir Mastermind", playerA.getId()); - Assert.assertTrue(lazav.getSubtype().contains("Griffin")); + Assert.assertTrue(lazav.getSubtype(currentGame).contains("Griffin")); Assert.assertTrue("Lazav, Dimir Mastermind must have flying",lazav.getAbilities().contains(FlyingAbility.getInstance())); } @@ -74,8 +74,8 @@ public class LazavDimirMastermindTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Lazav, Dimir Mastermind", 1); assertPowerToughness(playerA, "Lazav, Dimir Mastermind", 3, 3); Permanent lazav = getPermanent("Lazav, Dimir Mastermind", playerA.getId()); - Assert.assertTrue(lazav.getSubtype().contains("Ogre")); - Assert.assertTrue(lazav.getSubtype().contains("Rogue")); + Assert.assertTrue(lazav.getSubtype(currentGame).contains("Ogre")); + Assert.assertTrue(lazav.getSubtype(currentGame).contains("Rogue")); Permanent gutterSkulk = getPermanent("Gutter Skulk", playerA.getId()); Assert.assertTrue("Gutter Skulk should have deathtouch but hasn't", gutterSkulk.getAbilities().contains(DeathtouchAbility.getInstance())); @@ -116,7 +116,7 @@ public class LazavDimirMastermindTest extends CardTestPlayerBase { Permanent lazav = getPermanent("Lazav, Dimir Mastermind", playerA.getId()); Assert.assertTrue(lazav.getAbilities().contains(FlyingAbility.getInstance())); - Assert.assertTrue(lazav.getSubtype().contains("Specter")); + Assert.assertTrue(lazav.getSubtype(currentGame).contains("Specter")); Assert.assertTrue(lazav.getSupertype().contains("Legendary")); assertPermanentCount(playerA, "Silvercoat Lion", 1); @@ -146,7 +146,7 @@ public class LazavDimirMastermindTest extends CardTestPlayerBase { assertPowerToughness(playerA, "Lazav, Dimir Mastermind", 2, 2); Permanent lazav = getPermanent("Lazav, Dimir Mastermind", playerA.getId()); - Assert.assertTrue(lazav.getSubtype().contains("Cat")); + Assert.assertTrue(lazav.getSubtype(currentGame).contains("Cat")); Assert.assertTrue(lazav.getSupertype().contains("Legendary")); } @@ -190,7 +190,7 @@ public class LazavDimirMastermindTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Lazav, Dimir Mastermind", 1); assertPowerToughness(playerA, "Lazav, Dimir Mastermind", 3, 3); Permanent lazav = getPermanent("Lazav, Dimir Mastermind", playerA.getId()); - Assert.assertFalse(lazav.getSubtype().contains("Griffin")); // no Griffin type + Assert.assertFalse(lazav.getSubtype(currentGame).contains("Griffin")); // no Griffin type Assert.assertFalse("Lazav, Dimir Mastermind must have flying",lazav.getAbilities().contains(FlyingAbility.getInstance())); @@ -226,7 +226,7 @@ public class LazavDimirMastermindTest extends CardTestPlayerBase { assertPowerToughness(playerA, "Lazav, Dimir Mastermind", 3, 2); Permanent lazav = getPermanent("Lazav, Dimir Mastermind", playerA.getId()); - Assert.assertTrue(lazav.getSubtype().contains("Griffin")); + Assert.assertTrue(lazav.getSubtype(currentGame).contains("Griffin")); Assert.assertTrue("Lazav, Dimir Mastermind must have flying",lazav.getAbilities().contains(FlyingAbility.getInstance())); } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/PhantasmalImageTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/PhantasmalImageTest.java index d677381ae8..5e69551e6e 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/PhantasmalImageTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/PhantasmalImageTest.java @@ -11,6 +11,9 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; /** * @author noxx diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/VolrathsShapshifterTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/VolrathsShapshifterTest.java index 2e6bdca969..72e517ed03 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/VolrathsShapshifterTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/VolrathsShapshifterTest.java @@ -43,7 +43,7 @@ public class VolrathsShapshifterTest extends CardTestPlayerBase { assertPowerToughness(playerA, "Assault Griffin", 3, 2); Permanent shapeshifter = getPermanent("Assault Griffin", playerA.getId()); - Assert.assertTrue(shapeshifter.getSubtype().contains("Griffin")); + Assert.assertTrue(shapeshifter.getSubtype(currentGame).contains("Griffin")); Assert.assertTrue("Volrath's Shapeshifter must have flying", shapeshifter.getAbilities().contains(FlyingAbility.getInstance())); Assert.assertTrue("Volrath's Shapeshifter must have {2} : Discard a card", hasShapeshiftersOriginalAbility(shapeshifter)); } @@ -73,7 +73,7 @@ public class VolrathsShapshifterTest extends CardTestPlayerBase { assertPowerToughness(playerA, "Volrath's Shapeshifter", 0, 1); Permanent shapeshifter = getPermanent("Volrath's Shapeshifter", playerA.getId()); - Assert.assertTrue(shapeshifter.getSubtype().contains("Shapeshifter")); + Assert.assertTrue(shapeshifter.getSubtype(currentGame).contains("Shapeshifter")); Assert.assertTrue("Volrath's Shapeshifter must have {2} : Discard a card", hasShapeshiftersOriginalAbility(shapeshifter)); } @@ -100,7 +100,7 @@ public class VolrathsShapshifterTest extends CardTestPlayerBase { assertPowerToughness(playerA, "Dutiful Thrull", 1, 1); Permanent shapeshifter = getPermanent("Dutiful Thrull", playerA.getId()); - Assert.assertTrue(shapeshifter.getSubtype().contains("Thrull")); + Assert.assertTrue(shapeshifter.getSubtype(currentGame).contains("Thrull")); Assert.assertTrue("Volrath's Shapeshifter must have {2} : Discard a card", hasShapeshiftersOriginalAbility(shapeshifter)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/LignifyTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/LignifyTest.java index 19b7c61c5e..483c3a6bc0 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/LignifyTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/LignifyTest.java @@ -70,7 +70,7 @@ public class LignifyTest extends CardTestPlayerBase { Permanent hivelord = getPermanent("Sliver Hivelord", playerB); - Assert.assertFalse("Sliver Hivelord may not be of subtype Sliver", hivelord.getSubtype().contains("Sliver")); + Assert.assertFalse("Sliver Hivelord may not be of subtype Sliver", hivelord.getSubtype(currentGame).contains("Sliver")); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/emn/SoulSeparatorTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/emn/SoulSeparatorTest.java index a9920940d3..933223c0d4 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/emn/SoulSeparatorTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/emn/SoulSeparatorTest.java @@ -40,7 +40,7 @@ public class SoulSeparatorTest extends CardTestPlayerBase { Permanent saToken = getPermanent("Sylvan Advocate", playerA); Assert.assertTrue(saToken.getAbilities().contains(FlyingAbility.getInstance())); - Assert.assertTrue(saToken.getSubtype().contains("Spirit")); + Assert.assertTrue(saToken.getSubtype(currentGame).contains("Spirit")); Assert.assertTrue(saToken.getAbilities().contains(VigilanceAbility.getInstance())); assertPowerToughness(playerA, "Sylvan Advocate", 1, 1); } @@ -76,7 +76,7 @@ public class SoulSeparatorTest extends CardTestPlayerBase { Permanent treeToken = getPermanent("Tree of Perdition", playerA); Assert.assertTrue(treeToken.getAbilities().contains(FlyingAbility.getInstance())); - Assert.assertTrue(treeToken.getSubtype().contains("Spirit")); + Assert.assertTrue(treeToken.getSubtype(currentGame).contains("Spirit")); Assert.assertTrue(treeToken.getAbilities().contains(DefenderAbility.getInstance())); assertLife(playerA, 20); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/FathomMageTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/FathomMageTest.java index bfb822c895..c9191ff255 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/FathomMageTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/FathomMageTest.java @@ -60,7 +60,7 @@ public class FathomMageTest extends CardTestPlayerBase { assertPowerToughness(playerA, "Fathom Mage", 3, 3); Permanent fathomMage = getPermanent("Fathom Mage", playerA); - Assert.assertEquals("Fathom Mage has to be a Mutant", true, fathomMage.getSubtype().contains("Mutant")); + Assert.assertEquals("Fathom Mage has to be a Mutant", true, fathomMage.getSubtype(currentGame).contains("Mutant")); assertHandCount(playerA, 2); } diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java index 37fdf374e9..e4177371fc 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java @@ -716,7 +716,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement Assert.assertTrue("(Battlefield) card type not found (" + cardName + ":" + type + ")", found.getCardType().contains(type)); - Assert.assertTrue("(Battlefield) card sub-type not equal (" + cardName + ":" + subType + ")", found.getSubtype().contains(subType)); + Assert.assertTrue("(Battlefield) card sub-type not equal (" + cardName + ":" + subType + ")", found.getSubtype(currentGame).contains(subType)); } /** diff --git a/Mage/src/main/java/mage/MageObject.java b/Mage/src/main/java/mage/MageObject.java index 545ba0dd15..db9ed97dee 100644 --- a/Mage/src/main/java/mage/MageObject.java +++ b/Mage/src/main/java/mage/MageObject.java @@ -24,9 +24,9 @@ public interface MageObject extends MageItem, Serializable { List getCardType(); - List getSubtype(); + List getSubtype(Game game); - boolean hasSubtype(String subtype); + boolean hasSubtype(String subtype, Game game); List getSupertype(); @@ -35,6 +35,8 @@ public interface MageObject extends MageItem, Serializable { boolean hasAbility(UUID abilityId, Game game); ObjectColor getColor(Game game); + + ObjectColor getFrameColor(Game game); ManaCosts getManaCost(); @@ -43,6 +45,10 @@ public interface MageObject extends MageItem, Serializable { MageInt getPower(); MageInt getToughness(); + + int getStartingLoyalty(); + + void adjustCosts(Ability ability, Game game); diff --git a/Mage/src/main/java/mage/MageObjectImpl.java b/Mage/src/main/java/mage/MageObjectImpl.java index ebb8fc674f..80b3d7fd8d 100644 --- a/Mage/src/main/java/mage/MageObjectImpl.java +++ b/Mage/src/main/java/mage/MageObjectImpl.java @@ -33,10 +33,12 @@ import java.util.UUID; import mage.abilities.Abilities; import mage.abilities.AbilitiesImpl; import mage.abilities.Ability; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.keyword.ChangelingAbility; +import mage.abilities.mana.ManaAbility; import mage.constants.CardType; import mage.game.Game; import mage.util.CardUtil; @@ -49,6 +51,7 @@ public abstract class MageObjectImpl implements MageObject { protected String name; protected ManaCosts manaCost; protected ObjectColor color; + protected ObjectColor frameColor; protected List cardType = new ArrayList<>(); protected List subtype = new ArrayList<>(); protected List supertype = new ArrayList<>(); @@ -67,6 +70,7 @@ public abstract class MageObjectImpl implements MageObject { power = new MageInt(0); toughness = new MageInt(0); color = new ObjectColor(); + frameColor = new ObjectColor(); manaCost = new ManaCostsImpl<>(""); abilities = new AbilitiesImpl<>(); } @@ -77,6 +81,7 @@ public abstract class MageObjectImpl implements MageObject { manaCost = object.manaCost.copy(); text = object.text; color = object.color.copy(); + frameColor = object.frameColor.copy(); power = object.power.copy(); toughness = object.toughness.copy(); abilities = object.abilities.copy(); @@ -122,7 +127,7 @@ public abstract class MageObjectImpl implements MageObject { } @Override - public List getSubtype() { + public List getSubtype(Game game) { return subtype; } @@ -154,11 +159,67 @@ public abstract class MageObjectImpl implements MageObject { public MageInt getToughness() { return toughness; } + + @Override + public int getStartingLoyalty() { + for (Ability ab: getAbilities()) { + if (ab instanceof PlanswalkerEntersWithLoyalityCountersAbility) { + return ((PlanswalkerEntersWithLoyalityCountersAbility)ab).getStartingLoyalty(); + } + } + return 0; + } @Override public ObjectColor getColor(Game game) { return color; } + + @Override + public ObjectColor getFrameColor(Game game) { + // For lands, add any colors of mana the land can produce to + // its frame colors. + if (getCardType().contains(CardType.LAND)) { + ObjectColor cl = frameColor.copy(); + for (Ability ab: getAbilities()) { + if (ab instanceof ManaAbility) { + ManaAbility mana = (ManaAbility)ab; + try { + List manaAdded = mana.getNetMana(game); + for (Mana m: manaAdded) { + if (m.getAny() > 0) { + return new ObjectColor("WUBRG"); + } + if (m.getWhite() > 0) { + cl.setWhite(true); + } + if (m.getBlue() > 0) { + cl.setBlue(true); + } + if (m.getBlack() > 0) { + cl.setBlack(true); + } + if (m.getRed() > 0) { + cl.setRed(true); + } + if (m.getGreen() > 0) { + cl.setGreen(true); + } + } + } catch (NullPointerException e) { + // Ability depends on game + // but no game passed + // All such abilities are 5-color ones + return new ObjectColor("WUBRG"); + } + } + } + return cl; + } else { + // For everything else, just return the frame colors + return frameColor; + } + } @Override public ManaCosts getManaCost() { @@ -182,11 +243,12 @@ public abstract class MageObjectImpl implements MageObject { } @Override - public boolean hasSubtype(String value) { + public boolean hasSubtype(String value, Game game) { if (value == null) { return false; } - if (this.subtype.contains(value)) { + List subtypes = this.getSubtype(game); + if (subtypes.contains(value)) { return true; } else { // checking for Changeling @@ -196,7 +258,7 @@ public abstract class MageObjectImpl implements MageObject { return false; } // as it is creature subtype, then check the existence of Changeling - return abilities.contains(ChangelingAbility.getInstance()) || this.subtype.contains(ChangelingAbility.ALL_CREATURE_TYPE); + return abilities.contains(ChangelingAbility.getInstance()) || subtypes.contains(ChangelingAbility.ALL_CREATURE_TYPE); } } diff --git a/Mage/src/main/java/mage/ObjectColor.java b/Mage/src/main/java/mage/ObjectColor.java index 91a3001584..60827481e6 100644 --- a/Mage/src/main/java/mage/ObjectColor.java +++ b/Mage/src/main/java/mage/ObjectColor.java @@ -81,6 +81,22 @@ public class ObjectColor implements Serializable, Copyable, Compara red = color.red; green = color.green; } + + /** + * Returns a new color which contains all of the colors of this ObjectColor + * in addition to all of the colors of the other ObjectColor. + * @param other The other ObjectColor to union with + * @return A new color which is the union of this and other + */ + public ObjectColor union(ObjectColor other) { + ObjectColor newColor = new ObjectColor(); + newColor.white = white | other.white; + newColor.blue = blue | other.blue; + newColor.black = black | other.black; + newColor.red = red | other.red; + newColor.green = green | other.green; + return newColor; + } public int getColorCount() { int count = 0; diff --git a/Mage/src/main/java/mage/abilities/abilityword/KinshipAbility.java b/Mage/src/main/java/mage/abilities/abilityword/KinshipAbility.java index fa645b0f60..201b23fca8 100644 --- a/Mage/src/main/java/mage/abilities/abilityword/KinshipAbility.java +++ b/Mage/src/main/java/mage/abilities/abilityword/KinshipAbility.java @@ -126,7 +126,7 @@ class KinshipBaseEffect extends OneShotEffect { if (card != null) { Cards cards = new CardsImpl(card); controller.lookAtCards(sourcePermanent.getName(), cards, game); - if (CardUtil.shareSubtypes(sourcePermanent, card)) { + if (CardUtil.shareSubtypes(sourcePermanent, card, game)) { if (controller.chooseUse(outcome,new StringBuilder("Kinship - Reveal ").append(card.getLogName()).append("?").toString(), source, game)) { controller.revealCards(sourcePermanent.getName(), cards, game); for (Effect effect: kinshipEffects) { diff --git a/Mage/src/main/java/mage/abilities/common/AllyEntersBattlefieldTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/AllyEntersBattlefieldTriggeredAbility.java index 9252d5d9e0..512b881b52 100644 --- a/Mage/src/main/java/mage/abilities/common/AllyEntersBattlefieldTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/AllyEntersBattlefieldTriggeredAbility.java @@ -58,7 +58,7 @@ public class AllyEntersBattlefieldTriggeredAbility extends TriggeredAbilityImpl EntersTheBattlefieldEvent ebe = (EntersTheBattlefieldEvent) event; if (ebe.getTarget().getControllerId().equals(this.controllerId) && (event.getTargetId().equals(this.getSourceId()) - || (ebe.getTarget().hasSubtype("Ally") && !event.getTargetId().equals(this.getSourceId())))) { + || (ebe.getTarget().hasSubtype("Ally", game) && !event.getTargetId().equals(this.getSourceId())))) { return true; } return false; diff --git a/Mage/src/main/java/mage/abilities/common/AttachableToRestrictedAbility.java b/Mage/src/main/java/mage/abilities/common/AttachableToRestrictedAbility.java new file mode 100644 index 0000000000..3cc732e8c3 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/common/AttachableToRestrictedAbility.java @@ -0,0 +1,47 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.abilities.common; + +import mage.abilities.Ability; +import mage.abilities.effects.common.InfoEffect; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.Target; + +/** + * + * @author LevelX2 + */ +public class AttachableToRestrictedAbility extends SimpleStaticAbility { + + public AttachableToRestrictedAbility(Target target) { + super(Zone.BATTLEFIELD, new InfoEffect("{this} can be attached only to a " + target.getTargetName())); + addTarget(target); + } + + private AttachableToRestrictedAbility(AttachableToRestrictedAbility ability) { + super(ability); + } + + public boolean canEquip(Permanent toEquip, Ability source, Game game) { + for (Target target : getTargets()) { + if (source == null) { + if (!target.canTarget(toEquip.getId(), game)) { + return false; + } + } else if (!target.canTarget(toEquip.getId(), source, game)) { + return false; + } + } + return true; + } + + @Override + public AttachableToRestrictedAbility copy() { + return new AttachableToRestrictedAbility(this); + } +} diff --git a/Mage/src/main/java/mage/abilities/common/AuraAttachedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/AuraAttachedTriggeredAbility.java index cb4dca44cc..4ab0f259ef 100644 --- a/Mage/src/main/java/mage/abilities/common/AuraAttachedTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/AuraAttachedTriggeredAbility.java @@ -57,7 +57,7 @@ public class AuraAttachedTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { if (event.getTargetId().equals(this.getSourceId())) { Permanent attachment = game.getPermanent(event.getSourceId()); - if (attachment != null && attachment.getSubtype().contains("Aura")) { + if (attachment != null && attachment.getSubtype(game).contains("Aura")) { return true; } } diff --git a/Mage/src/main/java/mage/abilities/common/BecomesMonstrousTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BecomesMonstrousTriggeredAbility.java new file mode 100644 index 0000000000..452adbba58 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/common/BecomesMonstrousTriggeredAbility.java @@ -0,0 +1,60 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.abilities.common; + +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author Styxo + */ +public class BecomesMonstrousTriggeredAbility extends TriggeredAbilityImpl { + + protected FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + public BecomesMonstrousTriggeredAbility(Effect effect) { + super(Zone.BATTLEFIELD, effect, false); + } + + public BecomesMonstrousTriggeredAbility(final BecomesMonstrousTriggeredAbility ability) { + super(ability); + } + + @Override + public BecomesMonstrousTriggeredAbility copy() { + return new BecomesMonstrousTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.BECOMES_MONSTROUS; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent permanent = game.getPermanent(event.getTargetId()); + if (filter.match(permanent, sourceId, controllerId, game) + && (permanent.getControllerId().equals(this.controllerId))) { + for (Effect effect : this.getEffects()) { + effect.setTargetPointer(new FixedTarget(event.getTargetId())); + } + return true; + } + return false; + } + + @Override + public String getRule() { + return "Whenever " + filter.getMessage() + " becomes monstrous, " + super.getRule(); + } +} diff --git a/Mage/src/main/java/mage/abilities/common/LicidAbility.java b/Mage/src/main/java/mage/abilities/common/LicidAbility.java index 1c5a3e4232..1b8381c8bb 100644 --- a/Mage/src/main/java/mage/abilities/common/LicidAbility.java +++ b/Mage/src/main/java/mage/abilities/common/LicidAbility.java @@ -140,8 +140,8 @@ class LicidContinuousEffect extends ContinuousEffectImpl { case TypeChangingEffects_4: licid.getCardType().clear(); licid.getCardType().add(CardType.ENCHANTMENT); - licid.getSubtype().clear(); - licid.getSubtype().add("Aura"); + licid.getSubtype(game).clear(); + licid.getSubtype(game).add("Aura"); break; case AbilityAddingRemovingEffects_6: for (Ability ability : licid.getAbilities(game)) { diff --git a/Mage/src/main/java/mage/abilities/common/PlanswalkerEntersWithLoyalityCountersAbility.java b/Mage/src/main/java/mage/abilities/common/PlanswalkerEntersWithLoyalityCountersAbility.java index 963f5168d4..d47119c7f8 100644 --- a/Mage/src/main/java/mage/abilities/common/PlanswalkerEntersWithLoyalityCountersAbility.java +++ b/Mage/src/main/java/mage/abilities/common/PlanswalkerEntersWithLoyalityCountersAbility.java @@ -14,13 +14,21 @@ import mage.counters.CounterType; */ public class PlanswalkerEntersWithLoyalityCountersAbility extends EntersBattlefieldAbility { - public PlanswalkerEntersWithLoyalityCountersAbility(int loyality) { - super(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(loyality))); + private final int startingLoyalty; + + public PlanswalkerEntersWithLoyalityCountersAbility(int loyalty) { + super(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(loyalty))); + startingLoyalty = loyalty; setRuleVisible(false); } public PlanswalkerEntersWithLoyalityCountersAbility(final PlanswalkerEntersWithLoyalityCountersAbility ability) { super(ability); + startingLoyalty = ability.startingLoyalty; + } + + public int getStartingLoyalty() { + return startingLoyalty; } @Override diff --git a/Mage/src/main/java/mage/abilities/condition/common/EquippedHasSubtypeCondition.java b/Mage/src/main/java/mage/abilities/condition/common/EquippedHasSubtypeCondition.java index 4a06baeb86..3f2bf3cdc0 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/EquippedHasSubtypeCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/EquippedHasSubtypeCondition.java @@ -61,12 +61,12 @@ public class EquippedHasSubtypeCondition implements Condition { } if (attachedTo != null) { if (subType != null) { - if (attachedTo.hasSubtype(this.subType)) { + if (attachedTo.hasSubtype(this.subType, game)) { return true; } } else { for (String s : subTypes) { - if (attachedTo.hasSubtype(s)) { + if (attachedTo.hasSubtype(s, game)) { return true; } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/EquippedSourceCondition.java b/Mage/src/main/java/mage/abilities/condition/common/EquippedSourceCondition.java index 304c893087..22badda22c 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/EquippedSourceCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/EquippedSourceCondition.java @@ -52,7 +52,7 @@ public class EquippedSourceCondition implements Condition { if (permanent != null) { for (UUID uuid : permanent.getAttachments()) { Permanent attached = game.getBattlefield().getPermanent(uuid); - if (attached != null && attached.getSubtype().contains("Equipment")) { + if (attached != null && attached.getSubtype(game).contains("Equipment")) { return true; } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/SourceHasSubtypeCondition.java b/Mage/src/main/java/mage/abilities/condition/common/SourceHasSubtypeCondition.java index bcd187e2c0..3d246b2417 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/SourceHasSubtypeCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/SourceHasSubtypeCondition.java @@ -1,7 +1,6 @@ package mage.abilities.condition.common; import java.util.List; -import java.util.Set; import mage.abilities.Ability; import mage.abilities.condition.Condition; import mage.game.Game; @@ -24,7 +23,7 @@ public class SourceHasSubtypeCondition implements Condition { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { for (String subtype : subtypes) { - if (permanent.hasSubtype(subtype)) { + if (permanent.hasSubtype(subtype, game)) { return true; } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/TargetHasSubtypeCondition.java b/Mage/src/main/java/mage/abilities/condition/common/TargetHasSubtypeCondition.java index 97541140a9..cecd3593e9 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/TargetHasSubtypeCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/TargetHasSubtypeCondition.java @@ -50,7 +50,7 @@ public class TargetHasSubtypeCondition implements Condition { if (!source.getTargets().isEmpty()) { Permanent permanent = game.getPermanent(source.getFirstTarget()); if (permanent != null) { - return permanent.hasSubtype(subtype); + return permanent.hasSubtype(subtype, game); } } return false; diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/AuraAttachedCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/AuraAttachedCount.java index be484456be..0f6daf2562 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/AuraAttachedCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/AuraAttachedCount.java @@ -63,7 +63,7 @@ public class AuraAttachedCount implements DynamicValue { List attachments = p.getAttachments(); for (UUID attachmentId : attachments) { Permanent attached = game.getPermanent(attachmentId); - if (attached != null && attached.getSubtype().contains("Aura")) { + if (attached != null && attached.getSubtype(game).contains("Aura")) { count++; } } diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/CountersCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CountersCount.java index 7bad2ad6af..eb317e6101 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/CountersCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CountersCount.java @@ -1,45 +1,84 @@ -package mage.abilities.dynamicvalue.common; - -import mage.abilities.Ability; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; -import mage.counters.CounterType; -import mage.game.Game; -import mage.game.permanent.Permanent; - -public class CountersCount implements DynamicValue { - - private final CounterType counter; - - public CountersCount(CounterType counter) { - this.counter = counter; - } - - public CountersCount(final CountersCount countersCount) { - this.counter = countersCount.counter; - } - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - Permanent permanent = game.getPermanentOrLKIBattlefield(sourceAbility.getSourceId()); - if (permanent != null) { - return permanent.getCounters().getCount(counter); - } - return 0; - } - - @Override - public CountersCount copy() { - return new CountersCount(this); - } - - @Override - public String toString() { - return "1"; - } - - @Override - public String getMessage() { - return counter.getName() + " counter on {this}"; - } -} +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.abilities.dynamicvalue.common; + +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author Styxo + */ +public class CountersCount implements DynamicValue { + + private CounterType counter; + private FilterPermanent filter; + + public CountersCount(CounterType counterType) { + this(counterType, new FilterPermanent()); + } + + public CountersCount(CounterType counter, FilterPermanent filter) { + this.counter = counter; + this.filter = filter; + } + + public CountersCount(final CountersCount countersCount) { + this.counter = countersCount.counter; + this.filter = countersCount.filter; + } + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + int count = 0; + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, game)) { + count += permanent.getCounters().getCount(counter); + } + return count; + } + + @Override + public CountersCount copy() { + return new CountersCount(this); + } + + @Override + public String toString() { + return "1"; + } + + @Override + public String getMessage() { + return counter.getName() + " counter on " + filter.getMessage(); + } +} diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/CountersSourceCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CountersSourceCount.java new file mode 100644 index 0000000000..d132ed29a6 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CountersSourceCount.java @@ -0,0 +1,45 @@ +package mage.abilities.dynamicvalue.common; + +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.permanent.Permanent; + +public class CountersSourceCount implements DynamicValue { + + private final CounterType counter; + + public CountersSourceCount(CounterType counter) { + this.counter = counter; + } + + public CountersSourceCount(final CountersSourceCount countersCount) { + this.counter = countersCount.counter; + } + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + Permanent permanent = game.getPermanentOrLKIBattlefield(sourceAbility.getSourceId()); + if (permanent != null) { + return permanent.getCounters().getCount(counter); + } + return 0; + } + + @Override + public CountersSourceCount copy() { + return new CountersSourceCount(this); + } + + @Override + public String toString() { + return "1"; + } + + @Override + public String getMessage() { + return counter.getName() + " counter on {this}"; + } +} diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/DomainValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/DomainValue.java index 5b4f6da09b..75311da6f6 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/DomainValue.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/DomainValue.java @@ -62,19 +62,19 @@ public class DomainValue implements DynamicValue { } for (Permanent p : game.getBattlefield().getAllActivePermanents(targetPlayer)) { if (p.getCardType().contains(CardType.LAND)) { - if (havePlains == 0 && p.getSubtype().contains("Plains")) { + if (havePlains == 0 && p.getSubtype(game).contains("Plains")) { havePlains = 1; } - if (haveIslands == 0 && p.getSubtype().contains("Island")) { + if (haveIslands == 0 && p.getSubtype(game).contains("Island")) { haveIslands = 1; } - if (haveMountains == 0 && p.getSubtype().contains("Mountain")) { + if (haveMountains == 0 && p.getSubtype(game).contains("Mountain")) { haveMountains = 1; } - if (haveSwamps == 0 && p.getSubtype().contains("Swamp")) { + if (haveSwamps == 0 && p.getSubtype(game).contains("Swamp")) { haveSwamps = 1; } - if (haveForests == 0 && p.getSubtype().contains("Forest")) { + if (haveForests == 0 && p.getSubtype(game).contains("Forest")) { haveForests = 1; } } diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/EquipmentAttachedCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/EquipmentAttachedCount.java index 6bc0e8c51c..c7881cdc35 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/EquipmentAttachedCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/EquipmentAttachedCount.java @@ -63,7 +63,7 @@ public class EquipmentAttachedCount implements DynamicValue { List attachments = permanent.getAttachments(); for (UUID attachmentId : attachments) { Permanent attached = game.getPermanent(attachmentId); - if (attached != null && attached.getSubtype().contains("Equipment")) { + if (attached != null && attached.getSubtype(game).contains("Equipment")) { count++; } } diff --git a/Mage/src/main/java/mage/abilities/effects/AuraReplacementEffect.java b/Mage/src/main/java/mage/abilities/effects/AuraReplacementEffect.java index 13b3c5e5fd..d63917d5f5 100644 --- a/Mage/src/main/java/mage/abilities/effects/AuraReplacementEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/AuraReplacementEffect.java @@ -206,12 +206,12 @@ public class AuraReplacementEffect extends ReplacementEffectImpl { if (((ZoneChangeEvent) event).getToZone().equals(Zone.BATTLEFIELD) && !(((ZoneChangeEvent) event).getFromZone().equals(Zone.STACK))) { Card card = game.getCard(event.getTargetId()); - if (card != null && (card.getCardType().contains(CardType.ENCHANTMENT) && card.hasSubtype("Aura") + if (card != null && (card.getCardType().contains(CardType.ENCHANTMENT) && card.hasSubtype("Aura", game) || // in case of transformable enchantments (game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId()) != null && card.getSecondCardFace() != null && card.getSecondCardFace().getCardType().contains(CardType.ENCHANTMENT) - && card.getSecondCardFace().hasSubtype("Aura")))) { + && card.getSecondCardFace().hasSubtype("Aura", game)))) { return true; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/AmplifyEffect.java b/Mage/src/main/java/mage/abilities/effects/common/AmplifyEffect.java index b05ddd626c..1a210a2ce6 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/AmplifyEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/AmplifyEffect.java @@ -100,7 +100,7 @@ public class AmplifyEffect extends ReplacementEffectImpl { if (controller != null && sourceCreature != null) { FilterCreatureCard filter = new FilterCreatureCard("creatures cards to reveal"); List filterSubtypes = new ArrayList<>(); - for (String subtype : sourceCreature.getSubtype()) { + for (String subtype : sourceCreature.getSubtype(game)) { filterSubtypes.add(new SubtypePredicate((subtype))); } if (filterSubtypes.size() > 1) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/CopyEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CopyEffect.java index 5c83a3ccf6..7b472f6566 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CopyEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CopyEffect.java @@ -126,9 +126,9 @@ public class CopyEffect extends ContinuousEffectImpl { for (CardType type : copyFromObject.getCardType()) { permanent.getCardType().add(type); } - permanent.getSubtype().clear(); - for (String type : copyFromObject.getSubtype()) { - permanent.getSubtype().add(type); + permanent.getSubtype(game).clear(); + for (String type : copyFromObject.getSubtype(game)) { + permanent.getSubtype(game).add(type); } permanent.getSupertype().clear(); for (String type : copyFromObject.getSupertype()) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java index bf909df626..60f09fb7d1 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CopyTokenEffect.java @@ -34,9 +34,9 @@ public class CopyTokenEffect extends ContinuousEffectImpl { for (CardType type: token.getCardType()) { permanent.getCardType().add(type); } - permanent.getSubtype().clear(); - for (String type: token.getSubtype()) { - permanent.getSubtype().add(type); + permanent.getSubtype(game).clear(); + for (String type: token.getSubtype(game)) { + permanent.getSubtype(game).add(type); } permanent.getSupertype().clear(); for (String type: token.getSupertype()) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/DevourEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DevourEffect.java index 42b8294aeb..e7b40e0e74 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DevourEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DevourEffect.java @@ -150,7 +150,7 @@ public class DevourEffect extends ReplacementEffectImpl { for (UUID targetId : target.getTargets()) { Permanent targetCreature = game.getPermanent(targetId); if (targetCreature != null) { - cardSubtypes.add((ArrayList) targetCreature.getSubtype()); + cardSubtypes.add((ArrayList) targetCreature.getSubtype(game)); } if (targetCreature == null || !targetCreature.sacrifice(source.getSourceId(), game)) { return false; diff --git a/Mage/src/main/java/mage/abilities/effects/common/FightTargetsEffect.java b/Mage/src/main/java/mage/abilities/effects/common/FightTargetsEffect.java index ba94bdd73f..b955cb2eba 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/FightTargetsEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/FightTargetsEffect.java @@ -46,6 +46,11 @@ public class FightTargetsEffect extends OneShotEffect { super(Outcome.Damage); } + public FightTargetsEffect(String effectText) { + this(); + this.staticText = effectText; + } + public FightTargetsEffect(final FightTargetsEffect effect) { super(effect); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/PutTokenOntoBattlefieldCopyTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PutTokenOntoBattlefieldCopyTargetEffect.java index 69af814f09..43d7439afb 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/PutTokenOntoBattlefieldCopyTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/PutTokenOntoBattlefieldCopyTargetEffect.java @@ -198,8 +198,8 @@ public class PutTokenOntoBattlefieldCopyTargetEffect extends OneShotEffect { if (tokenToughness != Integer.MIN_VALUE) { token.setToughness(tokenToughness); } - if (additionalSubType != null && !token.getSubtype().contains(additionalSubType)) { - token.getSubtype().add(additionalSubType); + if (additionalSubType != null && !token.getSubtype(game).contains(additionalSubType)) { + token.getSubtype(game).add(additionalSubType); } token.putOntoBattlefield(number, game, source.getSourceId(), playerId == null ? source.getControllerId() : playerId, tapped, attacking, attackedPlayer); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubTypeTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubTypeTargetEffect.java index 908fe8f140..7a988a5bbc 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubTypeTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubTypeTargetEffect.java @@ -58,8 +58,8 @@ public class AddCardSubTypeTargetEffect extends ContinuousEffectImpl { public boolean apply(Game game, Ability source) { Permanent target = game.getPermanent(targetPointer.getFirst(game, source)); if (target != null) { - if (!target.hasSubtype(addedSubType)) { - target.getSubtype().add(addedSubType); + if (!target.hasSubtype(addedSubType, game)) { + target.getSubtype(game).add(addedSubType); } } else { if (Duration.Custom.equals(duration)) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAttachedEffect.java index a93ce7b819..8811d631cc 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAttachedEffect.java @@ -59,8 +59,8 @@ public class AddCardSubtypeAttachedEffect extends ContinuousEffectImpl { Permanent equipment = game.getPermanent(source.getSourceId()); if (equipment != null && equipment.getAttachedTo() != null) { Permanent target = game.getPermanent(equipment.getAttachedTo()); - if (target != null && !target.getSubtype().contains(addedSubtype)) - target.getSubtype().add(addedSubtype); + if (target != null && !target.getSubtype(game).contains(addedSubtype)) + target.getSubtype(game).add(addedSubtype); } return true; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAuraSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAuraSourceEffect.java index ff4f1a1c67..dc731efe9e 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAuraSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAuraSourceEffect.java @@ -83,8 +83,8 @@ public class BecomesAuraSourceEffect extends ContinuousEffectImpl implements Sou switch (layer) { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { - if (!permanent.getSubtype().contains("Aura")) { - permanent.getSubtype().add("Aura"); + if (!permanent.getSubtype(game).contains("Aura")) { + permanent.getSubtype(game).add("Aura"); } } break; diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandEnchantedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandEnchantedEffect.java index a340937034..a34d51a734 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandEnchantedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandEnchantedEffect.java @@ -98,27 +98,27 @@ public class BecomesBasicLandEnchantedEffect extends ContinuousEffectImpl { for (String landType : landTypes) { switch (landType) { case "Swamp": - if (permanent.getSubtype().contains("Swamp")) { // type can be removed by other effect with newer timestamp, so no ability adding + if (permanent.getSubtype(game).contains("Swamp")) { // type can be removed by other effect with newer timestamp, so no ability adding permanent.addAbility(new BlackManaAbility(), source.getSourceId(), game); } break; case "Mountain": - if (permanent.getSubtype().contains("Mountain")) { + if (permanent.getSubtype(game).contains("Mountain")) { permanent.addAbility(new RedManaAbility(), source.getSourceId(), game); } break; case "Forest": - if (permanent.getSubtype().contains("Forest")) { + if (permanent.getSubtype(game).contains("Forest")) { permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game); } break; case "Island": - if (permanent.getSubtype().contains("Island")) { + if (permanent.getSubtype(game).contains("Island")) { permanent.addAbility(new BlueManaAbility(), source.getSourceId(), game); } break; case "Plains": - if (permanent.getSubtype().contains("Plains")) { + if (permanent.getSubtype(game).contains("Plains")) { permanent.addAbility(new WhiteManaAbility(), source.getSourceId(), game); } break; @@ -127,8 +127,8 @@ public class BecomesBasicLandEnchantedEffect extends ContinuousEffectImpl { break; case TypeChangingEffects_4: // subtypes are all removed by changing the subtype to a land type. - permanent.getSubtype().removeAll(allLandTypes); - permanent.getSubtype().addAll(landTypes); + permanent.getSubtype(game).removeAll(allLandTypes); + permanent.getSubtype(game).addAll(landTypes); break; } return true; diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandTargetEffect.java index a5c61a9b47..7f6ad973d0 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesBasicLandTargetEffect.java @@ -132,7 +132,7 @@ public class BecomesBasicLandTargetEffect extends ContinuousEffectImpl { for (UUID targetPermanent : targetPointer.getTargets(game, source)) { Permanent land = game.getPermanent(targetPermanent); if (land != null) { - for (String type : land.getSubtype()) { + for (String type : land.getSubtype(game)) { if (!landTypes.contains(type)) { landTypes.add(type); } @@ -157,8 +157,8 @@ public class BecomesBasicLandTargetEffect extends ContinuousEffectImpl { // So the ability removing has to be done before Layer 6 land.removeAllAbilities(source.getSourceId(), game); // 305.7 - land.getSubtype().removeAll(CardRepository.instance.getLandTypes()); - land.getSubtype().addAll(landTypes); + land.getSubtype(game).removeAll(CardRepository.instance.getLandTypes()); + land.getSubtype(game).addAll(landTypes); break; case AbilityAddingRemovingEffects_6: for (String landType : landTypes) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAllEffect.java index 775fe1e918..f146091597 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAllEffect.java @@ -84,10 +84,10 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl { } } if (type == null) { - permanent.getSubtype().clear(); + permanent.getSubtype(game).clear(); } - if (token.getSubtype().size() > 0) { - permanent.getSubtype().addAll(token.getSubtype()); + if (token.getSubtype(game).size() > 0) { + permanent.getSubtype(game).addAll(token.getSubtype(game)); } } break; diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedEffect.java index b8e69a3278..454f0000e6 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAttachedEffect.java @@ -112,13 +112,13 @@ public class BecomesCreatureAttachedEffect extends ContinuousEffectImpl { case ALL: case ALL_BUT_COLOR: case ABILITIES_SUBTYPE_AND_PT: - permanent.getSubtype().retainAll(CardRepository.instance.getLandTypes()); + permanent.getSubtype(game).retainAll(CardRepository.instance.getLandTypes()); break; } - if (token.getSubtype().size() > 0) { - for (String t : token.getSubtype()) { - if (!permanent.getSubtype().contains(t)) { - permanent.getSubtype().add(t); + if (token.getSubtype(game).size() > 0) { + for (String t : token.getSubtype(game)) { + if (!permanent.getSubtype(game).contains(t)) { + permanent.getSubtype(game).add(t); } } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java index 99399d7c27..23c90cd686 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureSourceEffect.java @@ -121,10 +121,10 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements } } if ("".equals(type) || type == null && permanent.getCardType().contains(CardType.LAND)) { - permanent.getSubtype().retainAll(CardRepository.instance.getLandTypes()); + permanent.getSubtype(game).retainAll(CardRepository.instance.getLandTypes()); } - if (token.getSubtype().size() > 0) { - permanent.getSubtype().addAll(token.getSubtype()); + if (token.getSubtype(game).size() > 0) { + permanent.getSubtype(game).addAll(token.getSubtype(game)); } } break; diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTargetEffect.java index 25181520e2..00475d4f93 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTargetEffect.java @@ -88,13 +88,13 @@ public class BecomesCreatureTargetEffect extends ContinuousEffectImpl { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { if (loseAllAbilities) { - permanent.getSubtype().retainAll(CardRepository.instance.getLandTypes()); - permanent.getSubtype().addAll(token.getSubtype()); + permanent.getSubtype(game).retainAll(CardRepository.instance.getLandTypes()); + permanent.getSubtype(game).addAll(token.getSubtype(game)); } else { - if (token.getSubtype().size() > 0) { - for (String subtype : token.getSubtype()) { - if (!permanent.getSubtype().contains(subtype)) { - permanent.getSubtype().add(subtype); + if (token.getSubtype(game).size() > 0) { + for (String subtype : token.getSubtype(game)) { + if (!permanent.getSubtype(game).contains(subtype)) { + permanent.getSubtype(game).add(subtype); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTypeTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTypeTargetEffect.java index 7360ea3205..4837e258e1 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTypeTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTypeTargetEffect.java @@ -72,12 +72,12 @@ public class BecomesCreatureTypeTargetEffect extends ContinuousEffectImpl { switch (layer) { case TypeChangingEffects_4: if (loseOther) { - permanent.getSubtype().retainAll(CardRepository.instance.getLandTypes()); - permanent.getSubtype().addAll(subtypes); + permanent.getSubtype(game).retainAll(CardRepository.instance.getLandTypes()); + permanent.getSubtype(game).addAll(subtypes); } else { for (String subtype : subtypes) { - if (!permanent.getSubtype().contains(subtype)) { - permanent.getSubtype().add(subtype); + if (!permanent.getSubtype(game).contains(subtype)) { + permanent.getSubtype(game).add(subtype); } } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureAllEffect.java index 5c151f364a..ab16ec1f15 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureAllEffect.java @@ -110,7 +110,7 @@ public class BecomesFaceDownCreatureAllEffect extends ContinuousEffectImpl imple permanent.getSupertype().clear(); permanent.getCardType().clear(); permanent.getCardType().add(CardType.CREATURE); - permanent.getSubtype().clear(); + permanent.getSubtype(game).clear(); permanent.getManaCost().clear(); break; case ColorChangingEffects_5: diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureEffect.java index 4e80d92298..0afee43a10 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesFaceDownCreatureEffect.java @@ -166,7 +166,7 @@ public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implemen permanent.getSupertype().clear(); permanent.getCardType().clear(); permanent.getCardType().add(CardType.CREATURE); - permanent.getSubtype().clear(); + permanent.getSubtype(game).clear(); break; case ColorChangingEffects_5: permanent.getColor(game).setColor(new ObjectColor()); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesSubtypeAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesSubtypeAllEffect.java index 5b126ac4b5..e1967e797a 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesSubtypeAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesSubtypeAllEffect.java @@ -75,12 +75,12 @@ public class BecomesSubtypeAllEffect extends ContinuousEffectImpl { switch (layer) { case TypeChangingEffects_4: if (loseOther) { - permanent.getSubtype().retainAll(CardRepository.instance.getLandTypes()); - permanent.getSubtype().addAll(subtypes); + permanent.getSubtype(game).retainAll(CardRepository.instance.getLandTypes()); + permanent.getSubtype(game).addAll(subtypes); } else { for (String subtype : subtypes) { - if (!permanent.getSubtype().contains(subtype)) { - permanent.getSubtype().add(subtype); + if (!permanent.getSubtype(game).contains(subtype)) { + permanent.getSubtype(game).add(subtype); } } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostAllOfChosenSubtypeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostAllOfChosenSubtypeEffect.java index 57282f413e..5fd13d97e0 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostAllOfChosenSubtypeEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostAllOfChosenSubtypeEffect.java @@ -40,7 +40,7 @@ public class BoostAllOfChosenSubtypeEffect extends BoostAllEffect { @Override protected boolean selectedByRuntimeData(Permanent permanent, Ability source, Game game) { if (subtype != null) { - return permanent.hasSubtype(subtype); + return permanent.hasSubtype(subtype, game); } return false; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityAllOfChosenSubtypeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityAllOfChosenSubtypeEffect.java index 66d8367dd7..9d6030bfd3 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityAllOfChosenSubtypeEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityAllOfChosenSubtypeEffect.java @@ -36,7 +36,7 @@ public class GainAbilityAllOfChosenSubtypeEffect extends GainAbilityAllEffect { @Override protected boolean selectedByRuntimeData(Permanent permanent, Ability source, Game game) { if (subtype != null) { - return permanent.hasSubtype(subtype); + return permanent.hasSubtype(subtype, game); } return false; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseAllCreatureTypesTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseAllCreatureTypesTargetEffect.java index 508b89b17f..26181be4d3 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseAllCreatureTypesTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseAllCreatureTypesTargetEffect.java @@ -61,7 +61,7 @@ public class LoseAllCreatureTypesTargetEffect extends ContinuousEffectImpl { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (permanent != null) { - return permanent.getSubtype().retainAll(CardRepository.instance.getLandTypes()); + return permanent.getSubtype(game).retainAll(CardRepository.instance.getLandTypes()); } return false; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseCreatureTypeSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseCreatureTypeSourceEffect.java index 50bc86f6a9..533b2f8393 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseCreatureTypeSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/LoseCreatureTypeSourceEffect.java @@ -85,7 +85,7 @@ public class LoseCreatureTypeSourceEffect extends ContinuousEffectImpl implement case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { permanent.getCardType().remove(CardType.CREATURE); - permanent.getSubtype().retainAll(CardRepository.instance.getLandTypes()); + permanent.getSubtype(game).retainAll(CardRepository.instance.getLandTypes()); if (permanent.isAttacking() || permanent.getBlocking() > 0) { permanent.removeFromCombat(game); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/SetCardSubtypeAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/SetCardSubtypeAttachedEffect.java index 55d47b6a05..f6636df1e2 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/SetCardSubtypeAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/SetCardSubtypeAttachedEffect.java @@ -74,8 +74,8 @@ public class SetCardSubtypeAttachedEffect extends ContinuousEffectImpl { if (equipment != null && equipment.getAttachedTo() != null) { Permanent target = game.getPermanent(equipment.getAttachedTo()); if (target != null) { - target.getSubtype().retainAll(CardRepository.instance.getLandTypes()); - target.getSubtype().addAll(setSubtypes); + target.getSubtype(game).retainAll(CardRepository.instance.getLandTypes()); + target.getSubtype(game).addAll(setSubtypes); } } return true; diff --git a/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostReductionAllOfChosenSubtypeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostReductionAllOfChosenSubtypeEffect.java index 7799747779..83731edbf5 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostReductionAllOfChosenSubtypeEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostReductionAllOfChosenSubtypeEffect.java @@ -33,7 +33,7 @@ public class SpellsCostReductionAllOfChosenSubtypeEffect extends SpellsCostReduc protected boolean selectedByRuntimeData(Card card, Ability source, Game game) { String subtype = (String) game.getState().getValue(source.getSourceId() + "_type"); if (subtype != null) { - return card.hasSubtype(subtype); + return card.hasSubtype(subtype, game); } return false; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersTargetEffect.java index f8efacad7e..a19cd3cd21 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/counter/AddCountersTargetEffect.java @@ -41,6 +41,7 @@ import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.Target; import mage.util.CardUtil; /** @@ -144,17 +145,21 @@ public class AddCountersTargetEffect extends OneShotEffect { sb.append("s"); } sb.append(" on "); + + Target target = mode.getTargets().get(0); + if (target.getNumberOfTargets() == 0) { + sb.append("up to "); + } - // TODO: add normal text infrastructure for target pointers - if (mode.getTargets().size() > 0) { - String targetName = mode.getTargets().get(0).getTargetName(); - if (!targetName.startsWith("another")) { + if (target.getMaxNumberOfTargets() > 1 || target.getNumberOfTargets() == 0) { + sb.append(target.getMaxNumberOfTargets()).append(" target ").append(target.getTargetName()); + } else { + if (!target.getTargetName().startsWith("another")) { sb.append("target "); } - sb.append(targetName); - } else { - sb.append("it"); + sb.append(target.getTargetName()); } + if (amount.getMessage().length() > 0) { sb.append(" for each ").append(amount.getMessage()); } diff --git a/Mage/src/main/java/mage/abilities/keyword/AuraSwapAbility.java b/Mage/src/main/java/mage/abilities/keyword/AuraSwapAbility.java index cf98578791..c1ede4ef17 100644 --- a/Mage/src/main/java/mage/abilities/keyword/AuraSwapAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/AuraSwapAbility.java @@ -93,7 +93,7 @@ class AuraSwapEffect extends OneShotEffect { if (controller != null) { Permanent auraSourcePermanent = game.getPermanent(source.getSourceId()); if (auraSourcePermanent != null - && auraSourcePermanent.getSubtype().contains("Aura") + && auraSourcePermanent.getSubtype(game).contains("Aura") && auraSourcePermanent.getOwnerId().equals(source.getControllerId())) { Permanent enchantedPermanent = game.getPermanent(auraSourcePermanent.getAttachedTo()); filterCardToCheck.add(new AuraCardCanAttachToPermanentId(enchantedPermanent.getId())); diff --git a/Mage/src/main/java/mage/abilities/keyword/BestowAbility.java b/Mage/src/main/java/mage/abilities/keyword/BestowAbility.java index 16b440e2e6..fffff63fb2 100644 --- a/Mage/src/main/java/mage/abilities/keyword/BestowAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/BestowAbility.java @@ -175,15 +175,15 @@ public class BestowAbility extends SpellAbility { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { if (permanent.getAttachedTo() == null) { - if (wasAttached && permanent.getSubtype().contains("Aura")) { - permanent.getSubtype().remove("Aura"); + if (wasAttached && permanent.getSubtype(game).contains("Aura")) { + permanent.getSubtype(game).remove("Aura"); wasAttached = false; } } else { permanent.getCardType().remove(CardType.CREATURE); - permanent.getSubtype().retainAll(CardRepository.instance.getLandTypes()); - if (!permanent.getSubtype().contains("Aura")) { - permanent.getSubtype().add("Aura"); + permanent.getSubtype(game).retainAll(CardRepository.instance.getLandTypes()); + if (!permanent.getSubtype(game).contains("Aura")) { + permanent.getSubtype(game).add("Aura"); } wasAttached = true; } diff --git a/Mage/src/main/java/mage/abilities/keyword/EquipAbility.java b/Mage/src/main/java/mage/abilities/keyword/EquipAbility.java index 7e6ff39582..c6fa5c0810 100644 --- a/Mage/src/main/java/mage/abilities/keyword/EquipAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/EquipAbility.java @@ -1,16 +1,16 @@ /* * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR @@ -20,12 +20,11 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.abilities.keyword; import java.util.UUID; @@ -57,17 +56,15 @@ public class EquipAbility extends ActivatedAbilityImpl { @Override public boolean canActivate(UUID playerId, Game game) { - if(super.canActivate(playerId, game)){ + if (super.canActivate(playerId, game)) { Permanent permanent = game.getPermanent(sourceId); - if(permanent != null && permanent.hasSubtype("Equipment")){ + if (permanent != null && permanent.hasSubtype("Equipment", game)) { return true; } } return false; } - - public EquipAbility(final EquipAbility ability) { super(ability); } @@ -79,9 +76,7 @@ public class EquipAbility extends ActivatedAbilityImpl { @Override public String getRule() { - StringBuilder sb = new StringBuilder("Equip ").append(costs.getText()).append(manaCosts.getText()); - sb.append(" (").append(manaCosts.getText()).append(": Attach to target creature you control. Equip only as a sorcery.)"); - return sb.toString(); + return "Equip " + costs.getText() + manaCosts.getText() + " (" + manaCosts.getText() + ": Attach to target creature you control. Equip only as a sorcery.)"; } } diff --git a/Mage/src/main/java/mage/abilities/keyword/FlyingAbility.java b/Mage/src/main/java/mage/abilities/keyword/FlyingAbility.java index 0cc5d45fac..9b9422c20f 100644 --- a/Mage/src/main/java/mage/abilities/keyword/FlyingAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/FlyingAbility.java @@ -90,7 +90,7 @@ class FlyingEffect extends RestrictionEffect implements MageSingleton { public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game) { return blocker.getAbilities().containsKey(FlyingAbility.getInstance().getId()) || blocker.getAbilities().containsKey(ReachAbility.getInstance().getId()) - || (game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_DRAGON, source, blocker.getControllerId(), game) && attacker.hasSubtype("Dragon")) ; + || (game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_DRAGON, source, blocker.getControllerId(), game) && attacker.hasSubtype("Dragon", game)) ; } @Override diff --git a/Mage/src/main/java/mage/abilities/keyword/MorphAbility.java b/Mage/src/main/java/mage/abilities/keyword/MorphAbility.java index c77fa4c893..9369b1bb8a 100644 --- a/Mage/src/main/java/mage/abilities/keyword/MorphAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/MorphAbility.java @@ -302,7 +302,7 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost mageObject.setName(""); mageObject.getCardType().clear(); mageObject.getCardType().add(CardType.CREATURE); - mageObject.getSubtype().clear(); + mageObject.getSubtype(null).clear(); mageObject.getSupertype().clear(); mageObject.getManaCost().clear(); if (mageObject instanceof Permanent) { diff --git a/Mage/src/main/java/mage/abilities/keyword/ProwlAbility.java b/Mage/src/main/java/mage/abilities/keyword/ProwlAbility.java index 6b84f8b42e..b61921457f 100644 --- a/Mage/src/main/java/mage/abilities/keyword/ProwlAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/ProwlAbility.java @@ -123,7 +123,7 @@ public class ProwlAbility extends StaticAbility implements AlternativeSourceCost throw new IllegalArgumentException("Params can't be null"); } boolean canProwl = false; - for (String subtype : card.getSubtype()) { + for (String subtype : card.getSubtype(game)) { if (prowlWatcher.hasSubtypeMadeCombatDamage(ability.getControllerId(), subtype)) { canProwl = true; break; @@ -187,18 +187,8 @@ public class ProwlAbility extends StaticAbility implements AlternativeSourceCost } private void setReminderText(Card card) { - StringBuilder sb = new StringBuilder("(You may cast this for its prowl cost if you dealt combat damage to a player this turn with a "); - int i = 0; - for (String subtype : card.getSubtype()) { - i++; - sb.append(subtype); - if (card.getSubtype().size() > 1 && i < card.getSubtype().size()) { - sb.append(" or "); - } - } - sb.append(".)"); - - reminderText = sb.toString(); + reminderText = + "(You may cast this for its prowl cost if you dealt combat damage to a player this turn with a creature that shared a creature type with {this}"; } @Override diff --git a/Mage/src/main/java/mage/abilities/keyword/SpliceOntoArcaneAbility.java b/Mage/src/main/java/mage/abilities/keyword/SpliceOntoArcaneAbility.java index 2efde5b235..e0d1475826 100644 --- a/Mage/src/main/java/mage/abilities/keyword/SpliceOntoArcaneAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/SpliceOntoArcaneAbility.java @@ -182,7 +182,7 @@ class SpliceOntoArcaneEffect extends SpliceCardEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { MageObject object = game.getObject(abilityToModify.getSourceId()); - if (object != null && object.getSubtype().contains("Arcane")) { + if (object != null && object.getSubtype(game).contains("Arcane")) { return spliceSpellCanBeActivated(source, game); } return false; diff --git a/Mage/src/main/java/mage/abilities/keyword/TransformAbility.java b/Mage/src/main/java/mage/abilities/keyword/TransformAbility.java index 643623d4ef..a46b8fe347 100644 --- a/Mage/src/main/java/mage/abilities/keyword/TransformAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/TransformAbility.java @@ -79,9 +79,9 @@ public class TransformAbility extends SimpleStaticAbility { for (CardType type : sourceCard.getCardType()) { permanent.getCardType().add(type); } - permanent.getSubtype().clear(); - for (String type : sourceCard.getSubtype()) { - permanent.getSubtype().add(type); + permanent.getSubtype(game).clear(); + for (String type : sourceCard.getSubtype(game)) { + permanent.getSubtype(game).add(type); } permanent.getSupertype().clear(); for (String type : sourceCard.getSupertype()) { diff --git a/Mage/src/main/java/mage/cards/Card.java b/Mage/src/main/java/mage/cards/Card.java index 8d39c817c3..3befec124b 100644 --- a/Mage/src/main/java/mage/cards/Card.java +++ b/Mage/src/main/java/mage/cards/Card.java @@ -65,6 +65,8 @@ public interface Card extends MageObject { String getExpansionSetCode(); String getTokenSetCode(); + + String getTokenDescriptor(); void checkForCountersToAdd(Permanent permanent, Game game); diff --git a/Mage/src/main/java/mage/cards/CardImpl.java b/Mage/src/main/java/mage/cards/CardImpl.java index bcfd75c2db..050e5d5ee0 100644 --- a/Mage/src/main/java/mage/cards/CardImpl.java +++ b/Mage/src/main/java/mage/cards/CardImpl.java @@ -74,6 +74,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card { protected String cardNumber; public String expansionSetCode; protected String tokenSetCode; + protected String tokenDescriptor; protected Rarity rarity; protected boolean canTransform; protected Card secondSideCard; @@ -316,6 +317,11 @@ public abstract class CardImpl extends MageObjectImpl implements Card { public String getTokenSetCode() { return tokenSetCode; } + + @Override + public String getTokenDescriptor() { + return tokenDescriptor; + } @Override public List getMana() { @@ -756,6 +762,17 @@ public abstract class CardImpl extends MageObjectImpl implements Card { return cardAttribute.getColor(); } } - return super.getColor(game); //To change body of generated methods, choose Tools | Templates. + return super.getColor(game); + } + + @Override + public List getSubtype(Game game) { + if (game != null) { + CardAttribute cardAttribute = game.getState().getCardAttribute(getId()); + if (cardAttribute != null) { + return cardAttribute.getSubtype(); + } + } + return super.getSubtype(game); } } diff --git a/Mage/src/main/java/mage/cards/basiclands/Forest.java b/Mage/src/main/java/mage/cards/basiclands/Forest.java index abecdb2a85..46aa777d13 100644 --- a/Mage/src/main/java/mage/cards/basiclands/Forest.java +++ b/Mage/src/main/java/mage/cards/basiclands/Forest.java @@ -29,6 +29,7 @@ package mage.cards.basiclands; import java.util.UUID; +import mage.ObjectColor; import mage.abilities.mana.GreenManaAbility; /** @@ -43,6 +44,7 @@ public abstract class Forest extends BasicLand { public Forest(UUID ownerId, String cardNumber) { super(ownerId, cardNumber, "Forest", new GreenManaAbility()); + this.frameColor = ObjectColor.GREEN; } public Forest(final Forest land) { diff --git a/Mage/src/main/java/mage/cards/basiclands/Island.java b/Mage/src/main/java/mage/cards/basiclands/Island.java index 74d53377ea..569d7c9bc6 100644 --- a/Mage/src/main/java/mage/cards/basiclands/Island.java +++ b/Mage/src/main/java/mage/cards/basiclands/Island.java @@ -29,6 +29,7 @@ package mage.cards.basiclands; import java.util.UUID; +import mage.ObjectColor; import mage.abilities.mana.BlueManaAbility; /** @@ -43,6 +44,7 @@ public abstract class Island extends BasicLand { public Island(UUID ownerId, String cardNumber) { super(ownerId, cardNumber, "Island", new BlueManaAbility()); + this.frameColor = ObjectColor.BLUE; } public Island(Island land) { diff --git a/Mage/src/main/java/mage/cards/basiclands/Mountain.java b/Mage/src/main/java/mage/cards/basiclands/Mountain.java index 3616be6cb7..dc38fcc2b8 100644 --- a/Mage/src/main/java/mage/cards/basiclands/Mountain.java +++ b/Mage/src/main/java/mage/cards/basiclands/Mountain.java @@ -29,6 +29,7 @@ package mage.cards.basiclands; import java.util.UUID; +import mage.ObjectColor; import mage.abilities.mana.RedManaAbility; /** @@ -43,6 +44,7 @@ public abstract class Mountain extends BasicLand { public Mountain(UUID ownerId, String cardNumber) { super(ownerId, cardNumber, "Mountain", new RedManaAbility()); + this.frameColor = ObjectColor.RED; } public Mountain(Mountain land) { diff --git a/Mage/src/main/java/mage/cards/basiclands/Plains.java b/Mage/src/main/java/mage/cards/basiclands/Plains.java index a69f349656..5063735228 100644 --- a/Mage/src/main/java/mage/cards/basiclands/Plains.java +++ b/Mage/src/main/java/mage/cards/basiclands/Plains.java @@ -29,6 +29,7 @@ package mage.cards.basiclands; import java.util.UUID; +import mage.ObjectColor; import mage.abilities.mana.WhiteManaAbility; /** @@ -43,6 +44,7 @@ public abstract class Plains extends BasicLand { public Plains(UUID ownerId, String cardNumber) { super(ownerId, cardNumber, "Plains", new WhiteManaAbility()); + this.frameColor = ObjectColor.WHITE; } public Plains(Plains land) { diff --git a/Mage/src/main/java/mage/cards/basiclands/Swamp.java b/Mage/src/main/java/mage/cards/basiclands/Swamp.java index d6df027b69..d262d5510f 100644 --- a/Mage/src/main/java/mage/cards/basiclands/Swamp.java +++ b/Mage/src/main/java/mage/cards/basiclands/Swamp.java @@ -29,6 +29,7 @@ package mage.cards.basiclands; import java.util.UUID; +import mage.ObjectColor; import mage.abilities.mana.BlackManaAbility; /** @@ -43,6 +44,7 @@ public abstract class Swamp extends BasicLand { public Swamp(UUID ownerId, String cardNumber) { super(ownerId, cardNumber, "Swamp", new BlackManaAbility()); + this.frameColor = ObjectColor.BLACK; } public Swamp(Swamp land) { diff --git a/Mage/src/main/java/mage/cards/mock/MockCard.java b/Mage/src/main/java/mage/cards/mock/MockCard.java index 2225476567..7a0d375d97 100644 --- a/Mage/src/main/java/mage/cards/mock/MockCard.java +++ b/Mage/src/main/java/mage/cards/mock/MockCard.java @@ -7,11 +7,18 @@ import mage.abilities.costs.mana.ManaCostsImpl; import mage.cards.CardImpl; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; +import mage.constants.CardType; +import org.apache.log4j.Logger; /** * @author North */ public class MockCard extends CardImpl { + // Needs to be here, as it is normally calculated from the + // PlaneswalkerEntersWithLoyaltyAbility of the card... but the MockCard + // only has MockAbilities. + private int startingLoyalty; + public MockCard(CardInfo card) { super(null, card.getName()); this.cardNumber = card.getCardNumber(); @@ -28,6 +35,9 @@ public class MockCard extends CardImpl { this.manaCost = new ManaCostsImpl(join(card.getManaCosts())); this.color = card.getColor(); + + this.frameColor = card.getFrameColor(); + this.splitCard = card.isSplitCard(); this.flipCard = card.isFlipCard(); @@ -36,9 +46,21 @@ public class MockCard extends CardImpl { if (card.getSecondSideName() != null && !card.getSecondSideName().isEmpty()) { this.secondSideCard = new MockCard(CardRepository.instance.findCard(card.getSecondSideName())); } + + if (this.cardType.contains(CardType.PLANESWALKER)) { + String startingLoyaltyString = card.getStartingLoyalty(); + if (startingLoyaltyString.isEmpty()) { + //Logger.getLogger(MockCard.class).warn("Planeswalker `" + this.name + "` has empty starting loyalty."); + } else { + try { + this.startingLoyalty = Integer.parseInt(startingLoyaltyString); + } catch (NumberFormatException e) { + Logger.getLogger(MockCard.class).warn("Planeswalker `" + this.name + "` starting loyalty in bad format: `" + startingLoyaltyString + "`."); + } + } + } this.flipCardName = card.getFlipCardName(); - for(String ruleText: card.getRules()) { this.addAbility(textAbilityFromString(ruleText)); } @@ -47,6 +69,11 @@ public class MockCard extends CardImpl { public MockCard(final MockCard card) { super(card); } + + @Override + public int getStartingLoyalty() { + return startingLoyalty; + } @Override public MockCard copy() { diff --git a/Mage/src/main/java/mage/cards/repository/CardInfo.java b/Mage/src/main/java/mage/cards/repository/CardInfo.java index 6b2e157642..a9ead5ffcc 100644 --- a/Mage/src/main/java/mage/cards/repository/CardInfo.java +++ b/Mage/src/main/java/mage/cards/repository/CardInfo.java @@ -39,7 +39,9 @@ import java.util.List; import mage.constants.CardType; import mage.constants.Rarity; import mage.ObjectColor; +import mage.abilities.Ability; import mage.abilities.SpellAbility; +import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.mock.MockCard; @@ -70,6 +72,8 @@ public class CardInfo { @DatabaseField protected String toughness; @DatabaseField + protected String startingLoyalty; + @DatabaseField protected int convertedManaCost; @DatabaseField(dataType = DataType.ENUM_STRING) protected Rarity rarity; @@ -94,6 +98,8 @@ public class CardInfo { @DatabaseField protected boolean white; @DatabaseField + protected String frameColor; + @DatabaseField protected boolean splitCard; @DatabaseField protected boolean splitCardHalf; @@ -132,6 +138,7 @@ public class CardInfo { this.secondSideName = secondSide.getName(); } + this.frameColor = card.getFrameColor(null).toString(); this.blue = card.getColor(null).isBlue(); this.black = card.getColor(null).isBlack(); this.green = card.getColor(null).isGreen(); @@ -139,18 +146,18 @@ public class CardInfo { this.white = card.getColor(null).isWhite(); this.setTypes(card.getCardType()); - this.setSubtypes(card.getSubtype()); + this.setSubtypes(card.getSubtype(null)); this.setSuperTypes(card.getSupertype()); this.setManaCosts(card.getManaCost().getSymbols()); int length = 0; - for (String rule :card.getRules()) { + for (String rule: card.getRules()) { length += rule.length(); } if (length > MAX_RULE_LENGTH) { length = 0; ArrayList shortRules = new ArrayList<>(); - for (String rule :card.getRules()) { + for (String rule: card.getRules()) { if (length + rule.length() + 3 <= MAX_RULE_LENGTH) { shortRules.add(rule); length += rule.length() + 3; @@ -173,6 +180,21 @@ public class CardInfo { this.splitCardHalf = true; } } + + // Starting loyalty + if (card.getCardType().contains(CardType.PLANESWALKER)) { + for (Ability ab: card.getAbilities()) { + if (ab instanceof PlanswalkerEntersWithLoyalityCountersAbility) { + this.startingLoyalty = "" + ((PlanswalkerEntersWithLoyalityCountersAbility) ab).getStartingLoyalty(); + } + } + if (this.startingLoyalty == null) { + //Logger.getLogger(CardInfo.class).warn("Planeswalker `" + card.getName() + "` missing starting loyalty"); + this.startingLoyalty = ""; + } + } else { + this.startingLoyalty = ""; + } } public Card getCard() { @@ -200,6 +222,10 @@ public class CardInfo { color.setWhite(white); return color; } + + public ObjectColor getFrameColor() { + return new ObjectColor(frameColor); + } private String joinList(List items) { StringBuilder sb = new StringBuilder(); @@ -286,6 +312,10 @@ public class CardInfo { public String getToughness() { return toughness; } + + public String getStartingLoyalty() { + return startingLoyalty; + } public String getSetCode() { return setCode; diff --git a/Mage/src/main/java/mage/cards/repository/CardRepository.java b/Mage/src/main/java/mage/cards/repository/CardRepository.java index 6f0b2e7885..448771998b 100644 --- a/Mage/src/main/java/mage/cards/repository/CardRepository.java +++ b/Mage/src/main/java/mage/cards/repository/CardRepository.java @@ -61,9 +61,9 @@ public enum CardRepository { private static final String JDBC_URL = "jdbc:h2:file:./db/cards.h2;AUTO_SERVER=TRUE"; private static final String VERSION_ENTITY_NAME = "card"; // raise this if db structure was changed - private static final long CARD_DB_VERSION = 44; + private static final long CARD_DB_VERSION = 46; // raise this if new cards were added to the server - private static final long CARD_CONTENT_VERSION = 55; + private static final long CARD_CONTENT_VERSION = 57; private final Random random = new Random(); private Dao cardDao; diff --git a/Mage/src/main/java/mage/filter/common/FilterOpponentsCreaturePermanent.java b/Mage/src/main/java/mage/filter/common/FilterOpponentsCreaturePermanent.java new file mode 100644 index 0000000000..c3de7cc215 --- /dev/null +++ b/Mage/src/main/java/mage/filter/common/FilterOpponentsCreaturePermanent.java @@ -0,0 +1,40 @@ +package mage.filter.common; + +import mage.constants.TargetController; +import mage.filter.predicate.permanent.ControllerPredicate; + +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +/** + * + * @author Styxo + */ +public class FilterOpponentsCreaturePermanent extends FilterCreaturePermanent { + + public FilterOpponentsCreaturePermanent() { + this("creature an opponent controls"); + } + + public FilterOpponentsCreaturePermanent(String name) { + super(name); + this.add(new ControllerPredicate(TargetController.OPPONENT)); + + } + + public FilterOpponentsCreaturePermanent(String subtype, String name) { + super(subtype, name); + this.add(new ControllerPredicate(TargetController.OPPONENT)); + } + + public FilterOpponentsCreaturePermanent(final FilterOpponentsCreaturePermanent filter) { + super(filter); + } + + @Override + public FilterOpponentsCreaturePermanent copy() { + return new FilterOpponentsCreaturePermanent(this); + } +} diff --git a/Mage/src/main/java/mage/filter/predicate/mageobject/ChosenSubtypePredicate.java b/Mage/src/main/java/mage/filter/predicate/mageobject/ChosenSubtypePredicate.java index ca732ec3f9..3b8e30b0c9 100644 --- a/Mage/src/main/java/mage/filter/predicate/mageobject/ChosenSubtypePredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/ChosenSubtypePredicate.java @@ -47,7 +47,7 @@ public class ChosenSubtypePredicate implements Predicate { @Override public boolean apply(MageObject input, Game game) { String subtype = (String) game.getState().getValue(cardID + "_type"); - return input.hasSubtype(subtype); + return input.hasSubtype(subtype, game); } @Override diff --git a/Mage/src/main/java/mage/filter/predicate/mageobject/SubtypePredicate.java b/Mage/src/main/java/mage/filter/predicate/mageobject/SubtypePredicate.java index fc6fd26957..0bf0755905 100644 --- a/Mage/src/main/java/mage/filter/predicate/mageobject/SubtypePredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/SubtypePredicate.java @@ -45,7 +45,7 @@ public class SubtypePredicate implements Predicate { @Override public boolean apply(MageObject input, Game game) { - return input.hasSubtype(subtype); + return input.hasSubtype(subtype, game); } @Override diff --git a/Mage/src/main/java/mage/filter/predicate/other/CardTextPredicate.java b/Mage/src/main/java/mage/filter/predicate/other/CardTextPredicate.java index 7522494175..0456fdfc95 100644 --- a/Mage/src/main/java/mage/filter/predicate/other/CardTextPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/other/CardTextPredicate.java @@ -66,7 +66,7 @@ public class CardTextPredicate implements Predicate { } } - for (String subType : input.getSubtype()) { + for (String subType : input.getSubtype(game)) { if (subType.equalsIgnoreCase(token)) { found = true; break; diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/CanBeEnchantedByPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/CanBeEnchantedByPredicate.java index 6d876299e2..f9441f84d0 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/CanBeEnchantedByPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/CanBeEnchantedByPredicate.java @@ -45,7 +45,7 @@ public class CanBeEnchantedByPredicate implements Predicate { @Override public boolean apply(Permanent input, Game game) { - return !input.cantBeEnchantedBy(auraEnchantment, game); + return !input.cantBeAttachedBy(auraEnchantment, game); } @Override diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/EquippedPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/EquippedPredicate.java index 9e69dd0030..a6c2abbee1 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/EquippedPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/EquippedPredicate.java @@ -20,7 +20,7 @@ public class EquippedPredicate implements Predicate { public boolean apply(Permanent input, Game game) { for (UUID attachmentId : input.getAttachments()) { Permanent attachment = game.getPermanent(attachmentId); - if (attachment != null && attachment.getSubtype().contains("Equipment")) { + if (attachment != null && attachment.getSubtype(game).contains("Equipment")) { return true; } } diff --git a/Mage/src/main/java/mage/game/CardAttribute.java b/Mage/src/main/java/mage/game/CardAttribute.java index ec3b6fb965..6ed2cd7326 100644 --- a/Mage/src/main/java/mage/game/CardAttribute.java +++ b/Mage/src/main/java/mage/game/CardAttribute.java @@ -6,6 +6,8 @@ package mage.game; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; import mage.ObjectColor; import mage.cards.Card; @@ -17,13 +19,16 @@ import mage.cards.Card; public class CardAttribute implements Serializable { protected ObjectColor color; + protected List subtype; public CardAttribute(Card card) { color = card.getColor(null).copy(); + subtype = new ArrayList(card.getSubtype(null)); } public CardAttribute(CardAttribute cardAttribute) { this.color = cardAttribute.color; + this.subtype = cardAttribute.subtype; } public CardAttribute copy() { @@ -34,4 +39,8 @@ public class CardAttribute implements Serializable { return color; } + public List getSubtype() { + return subtype; + } + } diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 2617e3ff0a..ee2365a731 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -51,6 +51,7 @@ import mage.abilities.ActivatedAbility; import mage.abilities.DelayedTriggeredAbility; import mage.abilities.SpellAbility; import mage.abilities.TriggeredAbility; +import mage.abilities.common.AttachableToRestrictedAbility; import mage.abilities.common.ChancellorAbility; import mage.abilities.common.GemstoneCavernsAbility; import mage.abilities.effects.ContinuousEffect; @@ -1775,12 +1776,12 @@ public abstract class GameImpl implements Game, Serializable { Filter auraFilter = spellAbility.getTargets().get(0).getFilter(); if (auraFilter instanceof FilterControlledCreaturePermanent) { if (!((FilterControlledCreaturePermanent) auraFilter).match(attachedTo, perm.getId(), perm.getControllerId(), this) - || attachedTo.cantBeEnchantedBy(perm, this)) { + || attachedTo.cantBeAttachedBy(perm, this)) { if (movePermanentToGraveyardWithInfo(perm)) { somethingHappened = true; } } - } else if (!auraFilter.match(attachedTo, this) || attachedTo.cantBeEnchantedBy(perm, this)) { + } else if (!auraFilter.match(attachedTo, this) || attachedTo.cantBeAttachedBy(perm, this)) { // handle bestow unattachment Card card = this.getCard(perm.getId()); if (card != null && card.getCardType().contains(CardType.CREATURE)) { @@ -1816,13 +1817,23 @@ public abstract class GameImpl implements Game, Serializable { if (FILTER_EQUIPMENT.match(perm, this)) { //20091005 - 704.5p, 702.14d if (perm.getAttachedTo() != null) { - Permanent creature = getPermanent(perm.getAttachedTo()); - if (creature == null || !creature.getAttachments().contains(perm.getId())) { + Permanent attachedTo = getPermanent(perm.getAttachedTo()); + if (attachedTo != null) { + for (Ability ability : perm.getAbilities(this)) { + if (ability instanceof AttachableToRestrictedAbility) { + if (!((AttachableToRestrictedAbility) ability).canEquip(attachedTo, null, this)) { + attachedTo = null; + break; + } + } + } + } + if (attachedTo == null || !attachedTo.getAttachments().contains(perm.getId())) { UUID wasAttachedTo = perm.getAttachedTo(); perm.attachTo(null, this); fireEvent(new GameEvent(GameEvent.EventType.UNATTACHED, wasAttachedTo, perm.getId(), perm.getControllerId())); - } else if (!creature.getCardType().contains(CardType.CREATURE) || creature.hasProtectionFrom(perm, this)) { - if (creature.removeAttachment(perm.getId(), this)) { + } else if (!attachedTo.getCardType().contains(CardType.CREATURE) || attachedTo.hasProtectionFrom(perm, this)) { + if (attachedTo.removeAttachment(perm.getId(), this)) { somethingHappened = true; } } @@ -1848,9 +1859,9 @@ public abstract class GameImpl implements Game, Serializable { Permanent attachment = getPermanent(attachmentId); if (attachment != null && (attachment.getCardType().contains(CardType.CREATURE) - || !(attachment.getSubtype().contains("Aura") - || attachment.getSubtype().contains("Equipment") - || attachment.getSubtype().contains("Fortification")))) { + || !(attachment.getSubtype(this).contains("Aura") + || attachment.getSubtype(this).contains("Equipment") + || attachment.getSubtype(this).contains("Fortification")))) { if (perm.removeAttachment(attachment.getId(), this)) { somethingHappened = true; break; @@ -1875,7 +1886,7 @@ public abstract class GameImpl implements Game, Serializable { // This is called the "planeswalker uniqueness rule." if (planeswalkers.size() > 1) { //don't bother checking if less than 2 planeswalkers in play for (Permanent planeswalker : planeswalkers) { - for (String planeswalkertype : planeswalker.getSubtype()) { + for (String planeswalkertype : planeswalker.getSubtype(this)) { FilterPlaneswalkerPermanent filterPlaneswalker = new FilterPlaneswalkerPermanent(); filterPlaneswalker.add(new SubtypePredicate(planeswalkertype)); filterPlaneswalker.add(new ControllerIdPredicate(planeswalker.getControllerId())); diff --git a/Mage/src/main/java/mage/game/command/Commander.java b/Mage/src/main/java/mage/game/command/Commander.java index 0f6c5e3183..2805caeb80 100644 --- a/Mage/src/main/java/mage/game/command/Commander.java +++ b/Mage/src/main/java/mage/game/command/Commander.java @@ -112,18 +112,18 @@ public class Commander implements CommandObject { } @Override - public List getSubtype() { - return card.getSubtype(); + public List getSubtype(Game game) { + return card.getSubtype(game); } @Override - public boolean hasSubtype(String subtype) { - return card.hasSubtype(subtype); + public boolean hasSubtype(String subtype, Game game) { + return card.hasSubtype(subtype, game); } @Override public List getSupertype() { - return card.getSubtype(); + return card.getSupertype(); } @Override @@ -144,6 +144,11 @@ public class Commander implements CommandObject { public ObjectColor getColor(Game game) { return card.getColor(game); } + + @Override + public ObjectColor getFrameColor(Game game) { + return card.getFrameColor(game); + } @Override public ManaCosts getManaCost() { @@ -164,6 +169,11 @@ public class Commander implements CommandObject { public MageInt getToughness() { return card.getToughness(); } + + @Override + public int getStartingLoyalty() { + return card.getStartingLoyalty(); + } @Override public void adjustCosts(Ability ability, Game game) { diff --git a/Mage/src/main/java/mage/game/command/Emblem.java b/Mage/src/main/java/mage/game/command/Emblem.java index e7d3044495..6f9f10a864 100644 --- a/Mage/src/main/java/mage/game/command/Emblem.java +++ b/Mage/src/main/java/mage/game/command/Emblem.java @@ -125,12 +125,12 @@ public class Emblem implements CommandObject { } @Override - public List getSubtype() { + public List getSubtype(Game game) { return emptyList; } @Override - public boolean hasSubtype(String subtype) { + public boolean hasSubtype(String subtype, Game game) { return false; } @@ -153,6 +153,11 @@ public class Emblem implements CommandObject { public ObjectColor getColor(Game game) { return emptyColor; } + + @Override + public ObjectColor getFrameColor(Game game) { + return emptyColor; + } @Override public ManaCosts getManaCost() { @@ -173,6 +178,11 @@ public class Emblem implements CommandObject { public MageInt getToughness() { return MageInt.EmptyMageInt; } + + @Override + public int getStartingLoyalty() { + return 0; + } @Override public void adjustCosts(Ability ability, Game game) { diff --git a/Mage/src/main/java/mage/game/permanent/Permanent.java b/Mage/src/main/java/mage/game/permanent/Permanent.java index 7319a51a11..1d20fa0516 100644 --- a/Mage/src/main/java/mage/game/permanent/Permanent.java +++ b/Mage/src/main/java/mage/game/permanent/Permanent.java @@ -121,7 +121,7 @@ public interface Permanent extends Card, Controllable { boolean hasProtectionFrom(MageObject source, Game game); - boolean cantBeEnchantedBy(MageObject source, Game game); + boolean cantBeAttachedBy(MageObject source, Game game); boolean wasControlledFromStartOfControllerTurn(); diff --git a/Mage/src/main/java/mage/game/permanent/PermanentCard.java b/Mage/src/main/java/mage/game/permanent/PermanentCard.java index 6fd8f34574..bb583cd292 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentCard.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentCard.java @@ -63,7 +63,7 @@ public class PermanentCard extends PermanentImpl { private void init(Card card, Game game) { power = card.getPower().copy(); toughness = card.getToughness().copy(); - copyFromCard(card); + copyFromCard(card, game); // if temporary added abilities to the spell/card exist, you need to add it to the permanent derived from that card Abilities otherAbilities = game.getState().getAllOtherAbilities(card.getId()); if (otherAbilities != null) { @@ -95,13 +95,13 @@ public class PermanentCard extends PermanentImpl { public void reset(Game game) { // when the permanent is reset, copy all original values from the card // must copy card each reset so that the original values don't get modified - copyFromCard(card); + copyFromCard(card, game); power.resetToBaseValue(); toughness.resetToBaseValue(); super.reset(game); } - protected void copyFromCard(final Card card) { + protected void copyFromCard(final Card card, final Game game) { this.name = card.getName(); this.abilities.clear(); if (this.faceDown) { @@ -118,12 +118,13 @@ public class PermanentCard extends PermanentImpl { this.cardType.clear(); this.cardType.addAll(card.getCardType()); this.color = card.getColor(null).copy(); + this.frameColor = card.getFrameColor(null).copy(); this.manaCost = card.getManaCost().copy(); if (card instanceof PermanentCard) { this.maxLevelCounters = ((PermanentCard) card).maxLevelCounters; } this.subtype.clear(); - this.subtype.addAll(card.getSubtype()); + this.subtype.addAll(card.getSubtype(game)); this.supertype.clear(); this.supertype.addAll(card.getSupertype()); this.expansionSetCode = card.getExpansionSetCode(); diff --git a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java index 72dd7ad03c..84aeff54b6 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java @@ -625,13 +625,13 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { @Override public boolean changeControllerId(UUID controllerId, Game game) { Player newController = game.getPlayer(controllerId); - + GameEvent loseControlEvent = GameEvent.getEvent(GameEvent.EventType.LOSE_CONTROL, this.getId(), null, controllerId); if (game.replaceEvent(loseControlEvent)) { return false; } - + if (newController != null && (!newController.hasLeft() || !newController.hasLost())) { this.controllerId = controllerId; return true; @@ -981,7 +981,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { @Override public boolean hasProtectionFrom(MageObject source, Game game) { - for (ProtectionAbility ability : abilities.getProtectionAbilities()) { + for (ProtectionAbility ability : this.getAbilities(game).getProtectionAbilities()) { if (!ability.canTarget(source, game)) { return true; } @@ -990,9 +990,9 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { } @Override - public boolean cantBeEnchantedBy(MageObject source, Game game) { - for (ProtectionAbility ability : abilities.getProtectionAbilities()) { - if (!(source.getSubtype().contains("Aura") + public boolean cantBeAttachedBy(MageObject source, Game game) { + for (ProtectionAbility ability : this.getAbilities(game).getProtectionAbilities()) { + if (!(source.getSubtype(game).contains("Aura") && !ability.removesAuras()) && !source.getId().equals(ability.getAuraIdNotToBeRemoved()) && !ability.canTarget(source, game)) { diff --git a/Mage/src/main/java/mage/game/permanent/PermanentToken.java b/Mage/src/main/java/mage/game/permanent/PermanentToken.java index 2c649bf5f8..e95fc3c0ca 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentToken.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentToken.java @@ -82,10 +82,12 @@ public class PermanentToken extends PermanentImpl { } this.cardType = token.getCardType(); this.color = token.getColor(game).copy(); + this.frameColor = token.getFrameColor(game); this.power.modifyBaseValue(token.getPower().getBaseValueModified()); this.toughness.modifyBaseValue(token.getToughness().getBaseValueModified()); this.supertype = token.getSupertype(); - this.subtype = token.getSubtype(); + this.subtype = token.getSubtype(game); + this.tokenDescriptor = token.getTokenDescriptor(); } @Override diff --git a/Mage/src/main/java/mage/game/permanent/token/Token.java b/Mage/src/main/java/mage/game/permanent/token/Token.java index 91e719ce57..84dfc61367 100644 --- a/Mage/src/main/java/mage/game/permanent/token/Token.java +++ b/Mage/src/main/java/mage/game/permanent/token/Token.java @@ -55,6 +55,7 @@ public class Token extends MageObjectImpl { private int tokenType; private String originalCardNumber; private String originalExpansionSetCode; + private String tokenDescriptor; private boolean expansionSetCodeChecked; private Card copySourceCard; // the card the Token is a copy from @@ -113,6 +114,26 @@ public class Token extends MageObjectImpl { this.copySourceCard = token.copySourceCard; // will never be changed this.availableImageSetCodes = token.availableImageSetCodes; } + + private void setTokenDescriptor() { + this.tokenDescriptor = tokenDescriptor(); + } + + public String getTokenDescriptor() { + this.tokenDescriptor = tokenDescriptor(); + return tokenDescriptor; + } + + private String tokenDescriptor() { + String name = this.name.replaceAll("[^a-zA-Z0-9]", ""); + String color = this.color.toString().replaceAll("[^a-zA-Z0-9]", ""); + String subtype = this.subtype.toString().replaceAll("[^a-zA-Z0-9]", ""); + String cardType = this.cardType.toString().replaceAll("[^a-zA-Z0-9]", ""); + String originalset = this.getOriginalExpansionSetCode(); + String descriptor = name + "." + color + "." + subtype + "." + cardType + "." + this.power + "." + this.toughness ; + descriptor = descriptor.toUpperCase(); + return descriptor; + } public String getDescription() { return description; @@ -166,7 +187,7 @@ public class Token extends MageObjectImpl { } else { MageObject object = game.getObject(sourceId); if (object instanceof PermanentToken) { - ((PermanentToken) object).getExpansionSetCode(); + setCode = ((PermanentToken) object).getExpansionSetCode(); } } } @@ -241,13 +262,14 @@ public class Token extends MageObjectImpl { public void setOriginalCardNumber(String originalCardNumber) { this.originalCardNumber = originalCardNumber; } - - public String getOriginalExpansionSetCode() { + + public String getOriginalExpansionSetCode() { return originalExpansionSetCode; } public void setOriginalExpansionSetCode(String originalExpansionSetCode) { this.originalExpansionSetCode = originalExpansionSetCode; + setTokenDescriptor(); } public Card getCopySourceCard() { @@ -264,15 +286,20 @@ public class Token extends MageObjectImpl { if (availableImageSetCodes.size() > 0) { if (availableImageSetCodes.contains(code)) { setOriginalExpansionSetCode(code); - } else // we should not set random set if appropriate set is already used - if (getOriginalExpansionSetCode() == null || getOriginalExpansionSetCode().isEmpty() - || !availableImageSetCodes.contains(getOriginalExpansionSetCode())) { - setOriginalExpansionSetCode(availableImageSetCodes.get(new Random().nextInt(availableImageSetCodes.size()))); + } else { + // we should not set random set if appropriate set is already used + if (getOriginalExpansionSetCode() == null || getOriginalExpansionSetCode().isEmpty() + || !availableImageSetCodes.contains(getOriginalExpansionSetCode())) { + setOriginalExpansionSetCode(availableImageSetCodes.get(new Random().nextInt(availableImageSetCodes.size()))); + } + } + } else { + if (getOriginalExpansionSetCode() == null || getOriginalExpansionSetCode().isEmpty()) { + setOriginalExpansionSetCode(code); } - } else if (getOriginalExpansionSetCode() == null || getOriginalExpansionSetCode().isEmpty()) { - setOriginalExpansionSetCode(code); } - } + setTokenDescriptor(); + } public boolean updateExpansionSetCode(String setCode) { if (setCode == null || setCode.isEmpty()) { diff --git a/Mage/src/main/java/mage/game/stack/Spell.java b/Mage/src/main/java/mage/game/stack/Spell.java index aec4b126e0..6ce48963fa 100644 --- a/Mage/src/main/java/mage/game/stack/Spell.java +++ b/Mage/src/main/java/mage/game/stack/Spell.java @@ -75,6 +75,7 @@ public class Spell extends StackObjImpl implements Card { private final Card card; private final ObjectColor color; + private final ObjectColor frameColor; private final SpellAbility ability; private final Zone fromZone; private final UUID id; @@ -87,6 +88,7 @@ public class Spell extends StackObjImpl implements Card { public Spell(Card card, SpellAbility ability, UUID controllerId, Zone fromZone) { this.card = card; this.color = card.getColor(null).copy(); + this.frameColor = card.getFrameColor(null).copy(); id = ability.getId(); this.ability = ability; this.ability.setControllerId(controllerId); @@ -127,6 +129,7 @@ public class Spell extends StackObjImpl implements Card { this.copiedSpell = spell.copiedSpell; this.faceDown = spell.faceDown; this.color = spell.color.copy(); + this.frameColor = spell.color.copy(); } public boolean activate(Game game, boolean noMana) { @@ -223,7 +226,7 @@ public class Spell extends StackObjImpl implements Card { } counter(null, game); return false; - } else if (this.getCardType().contains(CardType.ENCHANTMENT) && this.getSubtype().contains("Aura")) { + } else if (this.getCardType().contains(CardType.ENCHANTMENT) && this.getSubtype(game).contains("Aura")) { if (ability.getTargets().stillLegal(ability, game)) { updateOptionalCosts(0); boolean bestow = ability instanceof BestowAbility; @@ -231,7 +234,7 @@ public class Spell extends StackObjImpl implements Card { // Must be removed first time, after that will be removed by continous effect // Otherwise effects like evolve trigger from creature comes into play event card.getCardType().remove(CardType.CREATURE); - card.getSubtype().add("Aura"); + card.getSubtype(game).add("Aura"); } if (controller.moveCards(card, Zone.BATTLEFIELD, ability, game, false, faceDown, false, null)) { if (bestow) { @@ -241,7 +244,7 @@ public class Spell extends StackObjImpl implements Card { if (permanent != null && permanent instanceof PermanentCard) { permanent.setSpellAbility(ability); // otherwise spell ability without bestow will be set ((PermanentCard) permanent).getCard().getCardType().add(CardType.CREATURE); - ((PermanentCard) permanent).getCard().getSubtype().remove("Aura"); + ((PermanentCard) permanent).getCard().getSubtype(game).remove("Aura"); } } return ability.resolve(game); @@ -431,27 +434,27 @@ public class Spell extends StackObjImpl implements Card { } @Override - public List getSubtype() { + public List getSubtype(Game game) { if (this.getSpellAbility() instanceof BestowAbility) { List subtypes = new ArrayList<>(); - subtypes.addAll(card.getSubtype()); + subtypes.addAll(card.getSubtype(game)); subtypes.add("Aura"); return subtypes; } - return card.getSubtype(); + return card.getSubtype(game); } @Override - public boolean hasSubtype(String subtype) { + public boolean hasSubtype(String subtype, Game game) { if (this.getSpellAbility() instanceof BestowAbility) { // workaround for Bestow (don't like it) List subtypes = new ArrayList<>(); - subtypes.addAll(card.getSubtype()); + subtypes.addAll(card.getSubtype(game)); subtypes.add("Aura"); if (subtypes.contains(subtype)) { return true; } } - return card.hasSubtype(subtype); + return card.hasSubtype(subtype, game); } @Override @@ -482,6 +485,11 @@ public class Spell extends StackObjImpl implements Card { public ObjectColor getColor(Game game) { return color; } + + @Override + public ObjectColor getFrameColor(Game game) { + return frameColor; + } @Override public ManaCosts getManaCost() { @@ -518,6 +526,11 @@ public class Spell extends StackObjImpl implements Card { public MageInt getToughness() { return card.getToughness(); } + + @Override + public int getStartingLoyalty() { + return card.getStartingLoyalty(); + } @Override public UUID getId() { @@ -572,6 +585,11 @@ public class Spell extends StackObjImpl implements Card { public String getTokenSetCode() { return card.getTokenSetCode(); } + + @Override + public String getTokenDescriptor() { + return card.getTokenDescriptor(); + } @Override public void setFaceDown(boolean value, Game game) { diff --git a/Mage/src/main/java/mage/game/stack/StackAbility.java b/Mage/src/main/java/mage/game/stack/StackAbility.java index 46e0a94458..824787d22a 100644 --- a/Mage/src/main/java/mage/game/stack/StackAbility.java +++ b/Mage/src/main/java/mage/game/stack/StackAbility.java @@ -162,12 +162,12 @@ public class StackAbility extends StackObjImpl implements Ability { } @Override - public List getSubtype() { + public List getSubtype(Game game) { return emptyString; } @Override - public boolean hasSubtype(String subtype) { + public boolean hasSubtype(String subtype, Game game) { return false; } @@ -192,6 +192,11 @@ public class StackAbility extends StackObjImpl implements Ability { public ObjectColor getColor(Game game) { return emptyColor; } + + @Override + public ObjectColor getFrameColor(Game game) { + return ability.getSourceObject(game).getFrameColor(game); + } @Override public ManaCosts getManaCost() { @@ -207,6 +212,11 @@ public class StackAbility extends StackObjImpl implements Ability { public MageInt getToughness() { return MageInt.EmptyMageInt; } + + @Override + public int getStartingLoyalty() { + return 0; + } @Override public Zone getZone() { diff --git a/Mage/src/main/java/mage/target/common/TargetCreatureOrPlayer.java b/Mage/src/main/java/mage/target/common/TargetCreatureOrPlayer.java index 3b55514126..8d0aa4f767 100644 --- a/Mage/src/main/java/mage/target/common/TargetCreatureOrPlayer.java +++ b/Mage/src/main/java/mage/target/common/TargetCreatureOrPlayer.java @@ -24,8 +24,7 @@ * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. -*/ - + */ package mage.target.common; import mage.constants.Zone; @@ -57,7 +56,11 @@ public class TargetCreatureOrPlayer extends TargetImpl { public TargetCreatureOrPlayer(int numTargets) { this(numTargets, numTargets, new FilterCreatureOrPlayer()); } - + + public TargetCreatureOrPlayer(FilterCreatureOrPlayer filter) { + this(1, 1, filter); + } + public TargetCreatureOrPlayer(int numTargets, int maxNumTargets) { this(numTargets, maxNumTargets, new FilterCreatureOrPlayer()); } @@ -123,8 +126,9 @@ public class TargetCreatureOrPlayer extends TargetImpl { } /** - * Checks if there are enough {@link Permanent} or {@link Player} that can be chosen. Should only be used - * for Ability targets since this checks for protection, shroud etc. + * Checks if there are enough {@link Permanent} or {@link Player} that can + * be chosen. Should only be used for Ability targets since this checks for + * protection, shroud etc. * * @param sourceId - the target event source * @param sourceControllerId - controller of the target event source @@ -135,7 +139,7 @@ public class TargetCreatureOrPlayer extends TargetImpl { public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { int count = 0; MageObject targetSource = game.getObject(sourceId); - for (UUID playerId: game.getState().getPlayersInRange(sourceControllerId, game)) { + for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { Player player = game.getPlayer(playerId); if (player != null && player.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(player, game)) { count++; @@ -144,7 +148,7 @@ public class TargetCreatureOrPlayer extends TargetImpl { } } } - for (Permanent permanent: game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) { if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(permanent, sourceId, sourceControllerId, game)) { count++; if (count >= this.minNumberOfTargets) { @@ -156,8 +160,9 @@ public class TargetCreatureOrPlayer extends TargetImpl { } /** - * Checks if there are enough {@link Permanent} or {@link Player} that can be selected. Should not be used - * for Ability targets since this does not check for protection, shroud etc. + * Checks if there are enough {@link Permanent} or {@link Player} that can + * be selected. Should not be used for Ability targets since this does not + * check for protection, shroud etc. * * @param sourceControllerId - controller of the select event * @param game @@ -166,7 +171,7 @@ public class TargetCreatureOrPlayer extends TargetImpl { @Override public boolean canChoose(UUID sourceControllerId, Game game) { int count = 0; - for (UUID playerId: game.getState().getPlayersInRange(sourceControllerId, game)) { + for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { Player player = game.getPlayer(playerId); if (player != null && filter.match(player, game)) { count++; @@ -175,7 +180,7 @@ public class TargetCreatureOrPlayer extends TargetImpl { } } } - for (Permanent permanent: game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) { if (filter.match(permanent, null, sourceControllerId, game)) { count++; if (count >= this.minNumberOfTargets) { @@ -190,7 +195,7 @@ public class TargetCreatureOrPlayer extends TargetImpl { public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { Set possibleTargets = new HashSet<>(); MageObject targetSource = game.getObject(sourceId); - for (UUID playerId: game.getState().getPlayersInRange(sourceControllerId, game)) { + for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { Player player = game.getPlayer(playerId); if (player != null && player.canBeTargetedBy(targetSource, sourceControllerId, game) @@ -198,7 +203,7 @@ public class TargetCreatureOrPlayer extends TargetImpl { possibleTargets.add(playerId); } } - for (Permanent permanent: game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) { if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.getCreatureFilter().match(permanent, sourceId, sourceControllerId, game)) { possibleTargets.add(permanent.getId()); @@ -210,13 +215,13 @@ public class TargetCreatureOrPlayer extends TargetImpl { @Override public Set possibleTargets(UUID sourceControllerId, Game game) { Set possibleTargets = new HashSet<>(); - for (UUID playerId: game.getState().getPlayersInRange(sourceControllerId, game)) { + for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { Player player = game.getPlayer(playerId); if (player != null && filter.getPlayerFilter().match(player, game)) { possibleTargets.add(playerId); } } - for (Permanent permanent: game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) { if (filter.getCreatureFilter().match(permanent, null, sourceControllerId, game)) { possibleTargets.add(permanent.getId()); } @@ -227,12 +232,11 @@ public class TargetCreatureOrPlayer extends TargetImpl { @Override public String getTargetedName(Game game) { StringBuilder sb = new StringBuilder(); - for (UUID targetId: getTargets()) { + for (UUID targetId : getTargets()) { Permanent permanent = game.getPermanent(targetId); if (permanent != null) { sb.append(permanent.getLogName()).append(" "); - } - else { + } else { Player player = game.getPlayer(targetId); if (player != null) { sb.append(player.getLogName()).append(" "); diff --git a/Mage/src/main/java/mage/target/common/TargetOpponentsCreaturePermanent.java b/Mage/src/main/java/mage/target/common/TargetOpponentsCreaturePermanent.java new file mode 100644 index 0000000000..9a17a690a3 --- /dev/null +++ b/Mage/src/main/java/mage/target/common/TargetOpponentsCreaturePermanent.java @@ -0,0 +1,45 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.target.common; + +import mage.filter.common.FilterOpponentsCreaturePermanent; + +/** + * + * @author Styxo + */ +public class TargetOpponentsCreaturePermanent extends TargetCreaturePermanent { + + public TargetOpponentsCreaturePermanent() { + this(1, 1, new FilterOpponentsCreaturePermanent(), false); + } + + public TargetOpponentsCreaturePermanent(int numTargets) { + this(numTargets, numTargets, new FilterOpponentsCreaturePermanent(), false); + } + + public TargetOpponentsCreaturePermanent(int minNumTargets, int maxNumTargets) { + this(minNumTargets, maxNumTargets, new FilterOpponentsCreaturePermanent(), false); + } + + public TargetOpponentsCreaturePermanent(FilterOpponentsCreaturePermanent filter) { + super(1, 1, filter, false); + } + + public TargetOpponentsCreaturePermanent(int minNumTargets, int maxNumTargets, FilterOpponentsCreaturePermanent filter, boolean notTarget) { + super(minNumTargets, maxNumTargets, filter, notTarget); + this.targetName = filter.getMessage(); + } + + public TargetOpponentsCreaturePermanent(final TargetOpponentsCreaturePermanent target) { + super(target); + } + + @Override + public TargetOpponentsCreaturePermanent copy() { + return new TargetOpponentsCreaturePermanent(this); + } +} diff --git a/Mage/src/main/java/mage/util/CardUtil.java b/Mage/src/main/java/mage/util/CardUtil.java index aa1f9751fa..7c665b64cb 100644 --- a/Mage/src/main/java/mage/util/CardUtil.java +++ b/Mage/src/main/java/mage/util/CardUtil.java @@ -118,7 +118,7 @@ public class CardUtil { * @param card2 * @return */ - public static boolean shareSubtypes(Card card1, Card card2) { + public static boolean shareSubtypes(Card card1, Card card2, Game game) { if (card1 == null || card2 == null) { throw new IllegalArgumentException("Params can't be null"); @@ -126,14 +126,14 @@ public class CardUtil { if (card1.getCardType().contains(CardType.CREATURE) && card2.getCardType().contains(CardType.CREATURE)) { if (card1.getAbilities().contains(ChangelingAbility.getInstance()) - || card1.getSubtype().contains(ChangelingAbility.ALL_CREATURE_TYPE) + || card1.getSubtype(game).contains(ChangelingAbility.ALL_CREATURE_TYPE) || card2.getAbilities().contains(ChangelingAbility.getInstance()) - || card2.getSubtype().contains(ChangelingAbility.ALL_CREATURE_TYPE)) { + || card2.getSubtype(game).contains(ChangelingAbility.ALL_CREATURE_TYPE)) { return true; } } - for (String subtype : card1.getSubtype()) { - if (card2.getSubtype().contains(subtype)) { + for (String subtype : card1.getSubtype(game)) { + if (card2.getSubtype(game).contains(subtype)) { return true; } } diff --git a/Mage/src/main/java/mage/util/functions/AddSubtypeApplier.java b/Mage/src/main/java/mage/util/functions/AddSubtypeApplier.java index 4c15691045..e0bacd0564 100644 --- a/Mage/src/main/java/mage/util/functions/AddSubtypeApplier.java +++ b/Mage/src/main/java/mage/util/functions/AddSubtypeApplier.java @@ -23,16 +23,16 @@ public class AddSubtypeApplier extends ApplyToPermanent { @Override public Boolean apply(Game game, Permanent permanent) { - if (!permanent.getSubtype().contains(subtype)) { - permanent.getSubtype().add(subtype); + if (!permanent.getSubtype(game).contains(subtype)) { + permanent.getSubtype(game).add(subtype); } return true; } @Override public Boolean apply(Game game, MageObject mageObject) { - if (!mageObject.getSubtype().contains(subtype)) { - mageObject.getSubtype().add(subtype); + if (!mageObject.getSubtype(game).contains(subtype)) { + mageObject.getSubtype(game).add(subtype); } return true; } diff --git a/Mage/src/main/java/mage/util/functions/CopyTokenFunction.java b/Mage/src/main/java/mage/util/functions/CopyTokenFunction.java index f10e9bd2c4..28be2fb7b9 100644 --- a/Mage/src/main/java/mage/util/functions/CopyTokenFunction.java +++ b/Mage/src/main/java/mage/util/functions/CopyTokenFunction.java @@ -96,9 +96,9 @@ public class CopyTokenFunction implements Function { for (CardType type : sourceObj.getCardType()) { target.getCardType().add(type); } - target.getSubtype().clear(); - for (String type : sourceObj.getSubtype()) { - target.getSubtype().add(type); + target.getSubtype(null).clear(); + for (String type : sourceObj.getSubtype(null)) { + target.getSubtype(null).add(type); } target.getSupertype().clear(); for (String type : sourceObj.getSupertype()) { diff --git a/Mage/src/main/java/mage/watchers/common/ProwlWatcher.java b/Mage/src/main/java/mage/watchers/common/ProwlWatcher.java index b7f7f96c6c..40469145d1 100644 --- a/Mage/src/main/java/mage/watchers/common/ProwlWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/ProwlWatcher.java @@ -77,14 +77,14 @@ public class ProwlWatcher extends Watcher { if (dEvent.isCombatDamage()) { Permanent creature = game.getPermanent(dEvent.getSourceId()); if (creature != null && !allSubtypes.contains(creature.getControllerId())) { - if (creature.getAbilities().containsKey(ChangelingAbility.getInstance().getId()) || creature.getSubtype().contains(ChangelingAbility.ALL_CREATURE_TYPE)) { + if (creature.getAbilities().containsKey(ChangelingAbility.getInstance().getId()) || creature.getSubtype(game).contains(ChangelingAbility.ALL_CREATURE_TYPE)) { allSubtypes.add(creature.getControllerId()); } else { Set subtypes = damagingSubtypes.get(creature.getControllerId()); if (subtypes == null) { subtypes = new LinkedHashSet<>(); } - subtypes.addAll(creature.getSubtype()); + subtypes.addAll(creature.getSubtype(game)); damagingSubtypes.put(creature.getControllerId(), subtypes); } }