mirror of
https://github.com/correl/mage.git
synced 2024-11-15 03:00:16 +00:00
Merge branch 'master' into additional-mulligan-support-5600
This commit is contained in:
commit
47c9aab877
39 changed files with 546 additions and 320 deletions
|
@ -56,7 +56,6 @@
|
|||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>20.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.swinglabs</groupId>
|
||||
|
|
|
@ -1,53 +1,46 @@
|
|||
|
||||
package mage.client.deck.generator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public enum DeckGeneratorCMC {
|
||||
|
||||
Low(
|
||||
new ArrayList<CMC>() {{
|
||||
add(new CMC(0, 2, 0.60f));
|
||||
add(new CMC(3, 4, 0.30f));
|
||||
add(new CMC(5, 6, 0.10f));
|
||||
}},
|
||||
new ArrayList<CMC>() {{
|
||||
add(new CMC(0, 2, 0.65f));
|
||||
add(new CMC(3, 4, 0.30f));
|
||||
add(new CMC(5, 5, 0.05f));
|
||||
}}),
|
||||
Default(
|
||||
new ArrayList<CMC>() {{
|
||||
add(new CMC(0, 2, 0.20f));
|
||||
add(new CMC(3, 5, 0.50f));
|
||||
add(new CMC(6, 7, 0.25f));
|
||||
add(new CMC(8, 100, 0.05f));
|
||||
}},
|
||||
new ArrayList<CMC>() {{
|
||||
add(new CMC(0, 2, 0.30f));
|
||||
add(new CMC(3, 4, 0.45f));
|
||||
add(new CMC(5, 6, 0.20f));
|
||||
add(new CMC(7, 100, 0.05f));
|
||||
}}),
|
||||
High(
|
||||
new ArrayList<CMC>() {{
|
||||
add(new CMC(0, 2, 0.05f));
|
||||
add(new CMC(3, 5, 0.35f));
|
||||
add(new CMC(6, 7, 0.40f));
|
||||
add(new CMC(8, 100, 0.15f));
|
||||
}},
|
||||
new ArrayList<CMC>() {{
|
||||
add(new CMC(0, 2, 0.10f));
|
||||
add(new CMC(3, 4, 0.30f));
|
||||
add(new CMC(5, 6, 0.45f));
|
||||
add(new CMC(7, 100, 0.15f));
|
||||
}});
|
||||
Low(ImmutableList.<CMC>builder()
|
||||
.add(new CMC(0, 2, 0.60f))
|
||||
.add(new CMC(3, 4, 0.30f))
|
||||
.add(new CMC(5, 6, 0.10f)).build(),
|
||||
ImmutableList.<CMC>builder()
|
||||
.add(new CMC(0, 2, 0.65f))
|
||||
.add(new CMC(3, 4, 0.30f))
|
||||
.add(new CMC(5, 5, 0.05f)).build()),
|
||||
Default(ImmutableList.<CMC>builder()
|
||||
.add(new CMC(0, 2, 0.20f))
|
||||
.add(new CMC(3, 5, 0.50f))
|
||||
.add(new CMC(6, 7, 0.25f))
|
||||
.add(new CMC(8, 100, 0.05f)).build(),
|
||||
ImmutableList.<CMC>builder()
|
||||
.add(new CMC(0, 2, 0.30f))
|
||||
.add(new CMC(3, 4, 0.45f))
|
||||
.add(new CMC(5, 6, 0.20f))
|
||||
.add(new CMC(7, 100, 0.05f)).build()),
|
||||
|
||||
private final ArrayList<CMC> poolCMCs60;
|
||||
private final ArrayList<CMC> poolCMCs40;
|
||||
High(ImmutableList.<CMC>builder().
|
||||
add(new CMC(0, 2, 0.05f))
|
||||
.add(new CMC(3, 5, 0.35f))
|
||||
.add(new CMC(6, 7, 0.40f))
|
||||
.add(new CMC(8, 100, 0.15f)).build(),
|
||||
ImmutableList.<CMC>builder().
|
||||
add(new CMC(0, 2, 0.10f))
|
||||
.add(new CMC(3, 4, 0.30f))
|
||||
.add(new CMC(5, 6, 0.45f))
|
||||
.add(new CMC(7, 100, 0.15f)).build());
|
||||
|
||||
DeckGeneratorCMC(ArrayList<CMC> CMCs60, ArrayList<CMC> CMCs40) {
|
||||
private final List<CMC> poolCMCs60;
|
||||
private final List<CMC> poolCMCs40;
|
||||
|
||||
DeckGeneratorCMC(List<CMC> CMCs60, List<CMC> CMCs40) {
|
||||
this.poolCMCs60 = CMCs60;
|
||||
this.poolCMCs40 = CMCs40;
|
||||
}
|
||||
|
@ -60,8 +53,7 @@ public enum DeckGeneratorCMC {
|
|||
return this.poolCMCs60;
|
||||
}
|
||||
|
||||
static class CMC
|
||||
{
|
||||
static class CMC {
|
||||
public final int min;
|
||||
public final int max;
|
||||
public final float percentage;
|
||||
|
@ -69,12 +61,12 @@ public enum DeckGeneratorCMC {
|
|||
|
||||
/**
|
||||
* Constructs a CMC range given a minimum and maximum, and the percentage of cards that are in this range.
|
||||
* @param min the minimum CMC a card in this range can be.
|
||||
* @param max the maximum CMC a card in this range can be.
|
||||
*
|
||||
* @param min the minimum CMC a card in this range can be.
|
||||
* @param max the maximum CMC a card in this range can be.
|
||||
* @param percentage the percentage of cards in the range (min, max)
|
||||
*/
|
||||
CMC(int min, int max, float percentage)
|
||||
{
|
||||
CMC(int min, int max, float percentage) {
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
this.percentage = percentage;
|
||||
|
@ -82,19 +74,19 @@ public enum DeckGeneratorCMC {
|
|||
|
||||
/**
|
||||
* Sets the amount of cards needed in this CMC range.
|
||||
*
|
||||
* @param amount the number of cards needed.
|
||||
*/
|
||||
public void setAmount(int amount)
|
||||
{
|
||||
public void setAmount(int amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of cards needed in this CMC range.
|
||||
*
|
||||
* @return the number of cards needed in this CMC range.
|
||||
*/
|
||||
public int getAmount()
|
||||
{
|
||||
public int getAmount() {
|
||||
return this.amount;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import javax.swing.*;
|
|||
import javax.swing.border.CompoundBorder;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.border.EtchedBorder;
|
||||
import mage.cards.Sets;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.client.MageFrame;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
|
@ -19,6 +18,8 @@ import mage.client.util.gui.ColorsChooser;
|
|||
import mage.client.util.gui.FastSearchUtil;
|
||||
import mage.client.util.sets.ConstructedFormats;
|
||||
|
||||
import static mage.cards.decks.DeckFormats.DCK;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Simown
|
||||
|
@ -328,7 +329,7 @@ public class DeckGeneratorDialog {
|
|||
tmp.getParentFile().mkdirs();
|
||||
tmp.createNewFile();
|
||||
deck.setName(deckName);
|
||||
Sets.saveDeck(tmp.getAbsolutePath(), deck.getDeckCardLists());
|
||||
DCK.getExporter().writeDeck(tmp.getAbsolutePath(), deck.getDeckCardLists());
|
||||
cleanUp();
|
||||
return tmp.getAbsolutePath();
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package mage.client.deckeditor;
|
||||
|
||||
import mage.cards.Card;
|
||||
import mage.cards.Sets;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.cards.decks.DeckCardLists;
|
||||
import mage.cards.decks.DnDDeckTargetListener;
|
||||
|
@ -35,12 +34,13 @@ import java.awt.*;
|
|||
import java.awt.dnd.DropTarget;
|
||||
import java.awt.event.*;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import static mage.cards.decks.DeckFormats.DCK;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
|
@ -965,8 +965,8 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
DeckCardLists cardLists = deck.getDeckCardLists();
|
||||
cardLists.setCardLayout(deckArea.getCardLayout());
|
||||
cardLists.setSideboardLayout(deckArea.getSideboardLayout());
|
||||
Sets.saveDeck(fileName, cardLists);
|
||||
} catch (FileNotFoundException ex) {
|
||||
DCK.getExporter().writeDeck(fileName, cardLists);
|
||||
} catch (IOException ex) {
|
||||
JOptionPane.showMessageDialog(MageFrame.getDesktop(), ex.getMessage() + "\nTry ensuring that the selected directory is writable.", "Error saving deck", JOptionPane.ERROR_MESSAGE);
|
||||
} finally {
|
||||
MageFrame.getDesktop().setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
|
||||
|
|
|
@ -1,22 +1,15 @@
|
|||
|
||||
/*
|
||||
* ErrorDialog.java
|
||||
*
|
||||
* Created on Dec 23, 2009, 11:01:32 AM
|
||||
*/
|
||||
package mage.client.dialog;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.plaf.basic.BasicInternalFrameUI;
|
||||
import mage.client.MageFrame;
|
||||
import mage.client.util.GUISizeHelper;
|
||||
import mage.constants.PlayerAction;
|
||||
import mage.view.UserRequestMessage;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.plaf.basic.BasicInternalFrameUI;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class UserRequestDialog extends MageDialog {
|
||||
|
@ -34,7 +27,7 @@ public class UserRequestDialog extends MageDialog {
|
|||
private void setGUISize() {
|
||||
Font font = GUISizeHelper.gameRequestsFont;
|
||||
lblText.setFont(font);
|
||||
lblText.setMaximumSize(new Dimension(300 + font.getSize() * 15, 20 + font.getSize() * 5));
|
||||
lblText.setMaximumSize(new Dimension(300 + font.getSize() * 15, 200 + font.getSize() * 5));
|
||||
lblText.setMinimumSize(new Dimension(300 + font.getSize() * 15, 20 + font.getSize() * 5));
|
||||
lblText.setPreferredSize(new Dimension(300 + font.getSize() * 15, 20 + font.getSize() * 5));
|
||||
btn1.setFont(font);
|
||||
|
@ -58,7 +51,7 @@ public class UserRequestDialog extends MageDialog {
|
|||
|
||||
public void showDialog(UserRequestMessage userRequestMessage) {
|
||||
this.userRequestMessage = userRequestMessage;
|
||||
this.setTitle(userRequestMessage.getTitel());
|
||||
this.setTitle(userRequestMessage.getTitle());
|
||||
String text = "<html><p style=\"text-align:center; margin-left:10px; margin-right:10px\">" + userRequestMessage.getMessage() + "</p></html>";
|
||||
this.lblText.setText(text);
|
||||
if (userRequestMessage.getButton1Text() != null) {
|
||||
|
@ -128,30 +121,30 @@ public class UserRequestDialog extends MageDialog {
|
|||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||
getContentPane().setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(lblText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(btn3, javax.swing.GroupLayout.PREFERRED_SIZE, 1, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btn2, javax.swing.GroupLayout.PREFERRED_SIZE, 1, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btn1, javax.swing.GroupLayout.PREFERRED_SIZE, 1, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(lblText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(btn3, javax.swing.GroupLayout.PREFERRED_SIZE, 1, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btn2, javax.swing.GroupLayout.PREFERRED_SIZE, 1, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btn1, javax.swing.GroupLayout.PREFERRED_SIZE, 1, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(lblText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(btn1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(btn2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(btn3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addGap(12, 12, 12))
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(lblText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(btn1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(btn2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(btn3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addGap(12, 12, 12))
|
||||
);
|
||||
|
||||
pack();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.mage.plugins.card.dl.sources;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.tritonus.share.ArraySet;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -12,22 +13,19 @@ import java.util.Set;
|
|||
*/
|
||||
public class ScryfallImageSupportCards {
|
||||
|
||||
private static final Map<String, String> xmageSetsToScryfall = new HashMap<String, String>() {
|
||||
{
|
||||
// xmage -> scryfall
|
||||
put("DD3GVL", "gvl");
|
||||
put("DD3JVC", "jvc");
|
||||
put("DD3DVD", "dvd");
|
||||
put("DD3EVG", "evg");
|
||||
put("MPS-AKH", "mp2");
|
||||
put("MBP", "pmei");
|
||||
put("WMCQ", "pwcq");
|
||||
put("EURO", "pelp");
|
||||
put("GPX", "pgpx");
|
||||
put("MED", "me1");
|
||||
put("MEDM", "med");
|
||||
}
|
||||
};
|
||||
private static final Map<String, String> xmageSetsToScryfall = ImmutableMap.<String, String>builder().put("DD3GVL", "gvl").
|
||||
put("DD3JVC", "jvc").
|
||||
put("DD3DVD", "dvd").
|
||||
put("DD3EVG", "evg").
|
||||
put("MPS-AKH", "mp2").
|
||||
put("MBP", "pmei").
|
||||
put("WMCQ", "pwcq").
|
||||
put("EURO", "pelp").
|
||||
put("GPX", "pgpx").
|
||||
put("MED", "me1").
|
||||
put("MEDM", "med").build();
|
||||
|
||||
|
||||
|
||||
private static final Set<String> supportedSets = new ArraySet<String>() {
|
||||
{
|
||||
|
|
|
@ -89,7 +89,7 @@ public enum TokensMtgImageSource implements CardImageSource {
|
|||
}
|
||||
|
||||
// Image URL contains token number
|
||||
// e.g. http://tokens.mtg.onl/tokens/ORI_010-Thopter.jpg -- token number 010
|
||||
// e.g. https://tokens.mtg.onl/tokens/ORI_010-Thopter.jpg -- token number 010
|
||||
// We don't know these numbers, but we can take them from a file
|
||||
// with tokens information that can be downloaded from the site.
|
||||
if (tokensData.isEmpty()) {
|
||||
|
@ -115,7 +115,7 @@ public enum TokensMtgImageSource implements CardImageSource {
|
|||
tokenData = list.get(card.getType() - 1);
|
||||
}
|
||||
|
||||
String url = "http://tokens.mtg.onl/tokens/" + tokenData.getExpansionSetCode().trim() + '_'
|
||||
String url = "https://tokens.mtg.onl/tokens/" + tokenData.getExpansionSetCode().trim() + '_'
|
||||
+ tokenData.getNumber().trim() + '-' + tokenData.getName().trim() + ".jpg";
|
||||
url = url.replace(' ', '-');
|
||||
return new CardImageUrls(url);
|
||||
|
|
|
@ -19,15 +19,15 @@ public class TokensMtgImageSourceTest {
|
|||
CardImageSource imageSource = TokensMtgImageSource.instance;
|
||||
|
||||
CardImageUrls url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 1, "ORI", ""));
|
||||
Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_010-Thopter.jpg", url.baseUrl);
|
||||
Assert.assertEquals("https://tokens.mtg.onl/tokens/ORI_010-Thopter.jpg", url.baseUrl);
|
||||
|
||||
url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 2, "ORI", ""));
|
||||
Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_011-Thopter.jpg", url.baseUrl);
|
||||
Assert.assertEquals("https://tokens.mtg.onl/tokens/ORI_011-Thopter.jpg", url.baseUrl);
|
||||
|
||||
url = imageSource.generateTokenUrl(new CardDownloadData("Ashaya, the Awoken World", "ORI", "0", false, 0, "ORI", ""));
|
||||
Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_007-Ashaya,-the-Awoken-World.jpg", url.baseUrl);
|
||||
Assert.assertEquals("https://tokens.mtg.onl/tokens/ORI_007-Ashaya,-the-Awoken-World.jpg", url.baseUrl);
|
||||
|
||||
url = imageSource.generateTokenUrl(new CardDownloadData("Emblem Gideon, Ally of Zendikar", "BFZ", "0", false, 0, null, ""));
|
||||
Assert.assertEquals("http://tokens.mtg.onl/tokens/BFZ_012-Gideon-Emblem.jpg", url.baseUrl);
|
||||
Assert.assertEquals("https://tokens.mtg.onl/tokens/BFZ_012-Gideon-Emblem.jpg", url.baseUrl);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
|
||||
package mage.remote;
|
||||
|
||||
import mage.MageException;
|
||||
import mage.utils.MageVersion;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class MageVersionException extends MageException {
|
||||
|
@ -13,7 +11,11 @@ public class MageVersionException extends MageException {
|
|||
private final MageVersion serverVersion;
|
||||
|
||||
public MageVersionException(MageVersion clientVersion, MageVersion serverVersion) {
|
||||
super("Wrong client version " + clientVersion + ", expecting version " + serverVersion + ". \r\n\r\nPlease download needed version from http://XMage.de or http://www.slightlymagic.net/forum/viewforum.php?f=70");
|
||||
super("Wrong client version."
|
||||
+ "<br/>Your version: " + clientVersion
|
||||
+ "<br/>Server version: " + serverVersion
|
||||
+ "<br/>Release app download: http://xmage.de"
|
||||
+ "<br/>BETA app download: http://xmage.today");
|
||||
this.serverVersion = serverVersion;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
|
||||
package mage.view;
|
||||
|
||||
import mage.constants.PlayerAction;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.UUID;
|
||||
import mage.constants.PlayerAction;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class UserRequestMessage implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final String titel;
|
||||
private final String title;
|
||||
private final String message;
|
||||
private UUID relatedUserId;
|
||||
private String relatedUserName;
|
||||
|
@ -32,8 +31,8 @@ public class UserRequestMessage implements Serializable {
|
|||
private String button3Text;
|
||||
private PlayerAction button3Action;
|
||||
|
||||
public UserRequestMessage(String titel, String message) {
|
||||
this.titel = titel;
|
||||
public UserRequestMessage(String title, String message) {
|
||||
this.title = title;
|
||||
this.message = message;
|
||||
this.button1Action = null;
|
||||
this.button2Action = null;
|
||||
|
@ -68,8 +67,8 @@ public class UserRequestMessage implements Serializable {
|
|||
this.button3Action = buttonAction;
|
||||
}
|
||||
|
||||
public String getTitel() {
|
||||
return titel;
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public static long getSerialVersionUID() {
|
||||
|
|
|
@ -15,6 +15,7 @@ import mage.cards.CardSetInfo;
|
|||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.TargetController;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
|
@ -34,6 +35,7 @@ public final class AurraSingBaneOfJedi extends CardImpl {
|
|||
|
||||
public AurraSingBaneOfJedi(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{B}{R}");
|
||||
this.addSuperType(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.AURRA);
|
||||
|
||||
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3));
|
||||
|
|
|
@ -9,6 +9,7 @@ import mage.abilities.decorator.ConditionalContinuousEffect;
|
|||
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
|
||||
import mage.abilities.keyword.MenaceAbility;
|
||||
import mage.abilities.keyword.MonstrosityAbility;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
@ -28,6 +29,9 @@ public final class BullRancor extends CardImpl {
|
|||
this.power = new MageInt(7);
|
||||
this.toughness = new MageInt(7);
|
||||
|
||||
// Trample
|
||||
this.addAbility(TrampleAbility.getInstance());
|
||||
|
||||
// {3}{R}{G}{G}{W}: Monstrosity 3.
|
||||
this.addAbility(new MonstrosityAbility("{3}{R}{G}{G}{W}", 3));
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.Duration;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
|
@ -36,6 +37,7 @@ public final class DarthSidiousSithLord extends CardImpl {
|
|||
|
||||
public DarthSidiousSithLord(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.PLANESWALKER},"{4}{U}{B}{B}{R}");
|
||||
this.addSuperType(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.SIDIOUS);
|
||||
|
||||
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5));
|
||||
|
|
|
@ -14,6 +14,7 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
|
@ -35,6 +36,7 @@ public final class DarthTyranusCountOfSerenno extends CardImpl {
|
|||
|
||||
public DarthTyranusCountOfSerenno(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.PLANESWALKER},"{1}{W}{U}{B}");
|
||||
this.addSuperType(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.DOOKU);
|
||||
|
||||
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3));
|
||||
|
|
|
@ -91,7 +91,7 @@ class GrimFeastEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent creature = game.getPermanentOrLKIBattlefield(source.getFirstTarget());
|
||||
Permanent creature = game.getPermanentOrLKIBattlefield(targetPointer.getFirst(game, source));
|
||||
if (creature == null) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,37 +1,30 @@
|
|||
|
||||
package mage.cards.j;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.AttacksTriggeredAbility;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.continuous.BoostSourceEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.abilities.keyword.MenaceAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.*;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||
import mage.filter.predicate.permanent.CounterPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetOpponentsCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Styxo/spjspj
|
||||
*/
|
||||
public final class JangoFett extends CardImpl {
|
||||
|
@ -55,7 +48,7 @@ public final class JangoFett extends CardImpl {
|
|||
ability.addTarget(new TargetOpponentsCreaturePermanent());
|
||||
this.addAbility(ability);
|
||||
|
||||
// Whenever Jango Fett attacks, it deals X damage to defending player and target creature he or she controls, where X is the number of creatures defending player controls with a bounty counter on them.
|
||||
// Whenever Jango Fett attacks, it gets +X/+0, where X is the number of creatures defending player controls with a bounty counter on them
|
||||
this.addAbility(new JangoFettTriggeredAbility(new JangoFettEffect(), false));
|
||||
}
|
||||
|
||||
|
@ -97,11 +90,6 @@ class JangoFettTriggeredAbility extends TriggeredAbilityImpl {
|
|||
if (event.getSourceId().equals(this.getSourceId())) {
|
||||
UUID defenderId = game.getCombat().getDefendingPlayerId(getSourceId(), game);
|
||||
if (defenderId != null) {
|
||||
this.getTargets().clear();
|
||||
FilterCreaturePermanent filter = new FilterCreaturePermanent("target creature defending player controls");
|
||||
filter.add(new ControllerIdPredicate(defenderId));
|
||||
TargetPermanent target = new TargetPermanent(filter);
|
||||
this.addTarget(target);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -125,8 +113,8 @@ class JangoFettTriggeredAbility extends TriggeredAbilityImpl {
|
|||
class JangoFettEffect extends OneShotEffect {
|
||||
|
||||
public JangoFettEffect() {
|
||||
super(Outcome.Damage);
|
||||
this.staticText = "it deals X damage to defending player and target creature he or she controls, where X is the number of creatures defending player controls with a bounty counter on them";
|
||||
super(Outcome.BoostCreature);
|
||||
this.staticText = "it gets +X/+0, where X is the number of creatures defending player controls with a bounty counter on them";
|
||||
}
|
||||
|
||||
public JangoFettEffect(final JangoFettEffect ability) {
|
||||
|
@ -158,14 +146,7 @@ class JangoFettEffect extends OneShotEffect {
|
|||
return false;
|
||||
}
|
||||
|
||||
Permanent targetCreature = game.getPermanent(source.getFirstTarget());
|
||||
if (targetCreature != null) {
|
||||
targetCreature.damage(count, source.getSourceId(), game, false, true);
|
||||
}
|
||||
Player defender = game.getPlayer(defenderId);
|
||||
defender.damage(count, source.getSourceId(), game, false, true);
|
||||
|
||||
game.addEffect(new BoostSourceEffect(count, 0, Duration.WhileOnBattlefield), source);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ public final class KrovikanVampire extends CardImpl {
|
|||
Zone.BATTLEFIELD,
|
||||
new KrovikanVampireEffect(),
|
||||
TargetController.ANY,
|
||||
KrovikanVampireInterveningIfCondition.instance,
|
||||
new KrovikanVampireInterveningIfCondition(),
|
||||
false);
|
||||
ability.addWatcher(new KrovikanVampireCreaturesDamagedWatcher());
|
||||
ability.addWatcher(new KrovikanVampireCreaturesDiedWatcher());
|
||||
|
@ -85,14 +85,17 @@ class KrovikanVampireEffect extends OneShotEffect {
|
|||
if (creaturesAffected != null
|
||||
&& controller != null
|
||||
&& krovikanVampire != null) {
|
||||
for (UUID creatureId : creaturesAffected) {
|
||||
creaturesAffected.stream().map((creatureId) -> {
|
||||
controller.moveCards(game.getCard(creatureId), Zone.BATTLEFIELD, source, game, false, false, false, null);
|
||||
return creatureId;
|
||||
}).map((creatureId) -> {
|
||||
OneShotEffect effect = new SacrificeTargetEffect();
|
||||
effect.setText("Sacrifice this if Krovikan Vampire leaves the battlefield or its current controller loses control of it.");
|
||||
effect.setTargetPointer(new FixedTarget(creatureId));
|
||||
KrovikanVampireDelayedTriggeredAbility dTA = new KrovikanVampireDelayedTriggeredAbility(effect, krovikanVampire.getId());
|
||||
return effect;
|
||||
}).map((effect) -> new KrovikanVampireDelayedTriggeredAbility(effect, krovikanVampire.getId())).forEachOrdered((dTA) -> {
|
||||
game.addDelayedTriggeredAbility(dTA, source);
|
||||
}
|
||||
});
|
||||
creaturesAffected.clear();
|
||||
return true;
|
||||
}
|
||||
|
@ -105,9 +108,8 @@ class KrovikanVampireEffect extends OneShotEffect {
|
|||
}
|
||||
}
|
||||
|
||||
enum KrovikanVampireInterveningIfCondition implements Condition {
|
||||
class KrovikanVampireInterveningIfCondition implements Condition {
|
||||
|
||||
instance;
|
||||
Set<UUID> creaturesAffected = new HashSet<>();
|
||||
|
||||
@Override
|
||||
|
@ -116,16 +118,12 @@ enum KrovikanVampireInterveningIfCondition implements Condition {
|
|||
KrovikanVampireCreaturesDamagedWatcher watcherDamaged = game.getState().getWatcher(KrovikanVampireCreaturesDamagedWatcher.class);
|
||||
if (watcherDied != null) {
|
||||
Set<UUID> creaturesThatDiedThisTurn = watcherDied.getDiedThisTurn();
|
||||
for (UUID mor : creaturesThatDiedThisTurn) {
|
||||
if (watcherDamaged != null) {
|
||||
for (UUID mor2 : watcherDamaged.getDamagedBySource()) {
|
||||
if (mor2 != null
|
||||
&& mor == mor2) {
|
||||
creaturesAffected.add(mor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
creaturesThatDiedThisTurn.stream().filter((mor) -> (watcherDamaged != null)).forEachOrdered((mor) -> {
|
||||
watcherDamaged.getDamagedBySource().stream().filter((mor2) -> (mor2 != null
|
||||
&& mor == mor2)).forEachOrdered((_item) -> {
|
||||
creaturesAffected.add(mor);
|
||||
});
|
||||
});
|
||||
if (creaturesAffected != null
|
||||
&& creaturesAffected.size() > 0) {
|
||||
game.getState().setValue(source.getSourceId() + "creatureToGainControl", creaturesAffected);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.cards.m;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -11,15 +10,14 @@ import mage.abilities.effects.OneShotEffect;
|
|||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.Cards;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterNonlandCard;
|
||||
import mage.game.ExileZone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.PermanentToken;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetOpponent;
|
||||
|
@ -32,7 +30,7 @@ import mage.util.CardUtil;
|
|||
public final class MesmericFiend extends CardImpl {
|
||||
|
||||
public MesmericFiend(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
|
||||
this.subtype.add(SubType.NIGHTMARE);
|
||||
this.subtype.add(SubType.HORROR);
|
||||
|
||||
|
@ -79,14 +77,16 @@ class MesmericFiendExileEffect extends OneShotEffect {
|
|||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Player opponent = game.getPlayer(source.getFirstTarget());
|
||||
Permanent sourcePermanent = (Permanent) source.getSourceObject(game);
|
||||
if (controller != null && opponent != null && sourcePermanent != null) {
|
||||
if (controller != null
|
||||
&& opponent != null
|
||||
&& sourcePermanent != null) {
|
||||
opponent.revealCards(sourcePermanent.getName(), opponent.getHand(), game);
|
||||
|
||||
TargetCard target = new TargetCard(Zone.HAND, new FilterNonlandCard("nonland card to exile"));
|
||||
if (controller.choose(Outcome.Exile, opponent.getHand(), target, game)) {
|
||||
Card card = opponent.getHand().get(target.getFirstTarget(), game);
|
||||
if (card != null) {
|
||||
controller.moveCardToExileWithInfo(card, CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.HAND, true);
|
||||
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
|
||||
controller.moveCardsToExile(card, source, game, true, exileId, sourcePermanent.getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,11 +117,14 @@ class MesmericFiendLeaveEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (controller != null && sourceObject != null) {
|
||||
int zoneChangeCounter = (sourceObject instanceof PermanentToken) ? source.getSourceObjectZoneChangeCounter() : source.getSourceObjectZoneChangeCounter() - 1;
|
||||
ExileZone exZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(), zoneChangeCounter));
|
||||
if (exZone != null) {
|
||||
return controller.moveCards(exZone, Zone.HAND, source, game);
|
||||
if (controller != null
|
||||
&& sourceObject != null) {
|
||||
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter() - 1);
|
||||
if (exileId != null) {
|
||||
Cards cards = game.getExile().getExileZone(exileId);
|
||||
if (!cards.isEmpty()) {
|
||||
return controller.moveCards(cards, Zone.HAND, source, game);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -15,6 +15,7 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.Duration;
|
||||
import mage.game.command.emblems.ObiWanKenobiEmblem;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
@ -27,6 +28,7 @@ public final class ObiWanKenobi extends CardImpl {
|
|||
|
||||
public ObiWanKenobi(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{3}{W}{U}");
|
||||
this.addSuperType(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.OBI_WAN);
|
||||
|
||||
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5));
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.cards.p;
|
||||
|
||||
import java.util.Optional;
|
||||
|
@ -9,6 +8,7 @@ import mage.abilities.common.AsEntersBattlefieldAbility;
|
|||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
||||
import mage.abilities.effects.common.ChooseACardNameEffect;
|
||||
import mage.abilities.mana.ActivatedManaAbilityImpl;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
|
@ -71,9 +71,10 @@ class PithingNeedleEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
MageObject object = game.getObject(event.getSourceId());
|
||||
Optional<Ability> ability = game.getAbility(event.getTargetId(), event.getSourceId());
|
||||
if (ability.isPresent() && object != null) {
|
||||
if (ability.isPresent()
|
||||
&& object != null) {
|
||||
if (game.getState().getPlayersInRange(source.getControllerId(), game).contains(event.getPlayerId()) // controller in range
|
||||
&& ability.get().getAbilityType() != AbilityType.MANA
|
||||
&& !(ability.get() instanceof ActivatedManaAbilityImpl) // not an activated mana ability
|
||||
&& object.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY))) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
|
||||
package mage.cards.p;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||
|
@ -17,6 +15,7 @@ import mage.constants.Outcome;
|
|||
import mage.constants.Zone;
|
||||
import mage.game.ExileZone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
|
@ -27,12 +26,19 @@ import mage.util.CardUtil;
|
|||
public final class PyxisOfPandemonium extends CardImpl {
|
||||
|
||||
public PyxisOfPandemonium(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{1}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}");
|
||||
|
||||
// {T}: Each player exiles the top card of their library face down.
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new PyxisOfPandemoniumExileEffect(), new TapSourceCost()));
|
||||
this.addAbility(new SimpleActivatedAbility(
|
||||
Zone.BATTLEFIELD,
|
||||
new PyxisOfPandemoniumExileEffect(),
|
||||
new TapSourceCost()));
|
||||
|
||||
// {7}, {T}, Sacrifice Pyxis of Pandemonium: Each player turns face up all cards he or she owns exiled with Pyxis of Pandemonium, then puts all permanent cards among them onto the battlefield.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PyxisOfPandemoniumPutOntoBattlefieldEffect(), new GenericManaCost(7));
|
||||
Ability ability = new SimpleActivatedAbility(
|
||||
Zone.BATTLEFIELD,
|
||||
new PyxisOfPandemoniumPutOntoBattlefieldEffect(),
|
||||
new GenericManaCost(7));
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addCost(new SacrificeSourceCost());
|
||||
this.addAbility(ability);
|
||||
|
@ -68,10 +74,11 @@ class PyxisOfPandemoniumExileEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (sourceObject != null && controller != null) {
|
||||
Permanent pyxis = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
||||
if (pyxis != null
|
||||
&& controller != null) {
|
||||
Map<String, UUID> exileIds;
|
||||
String valueKey = CardUtil.getObjectZoneString("exileIds", sourceObject, game);
|
||||
String valueKey = CardUtil.getObjectZoneString("exileIds", pyxis, game);
|
||||
Object object = game.getState().getValue(valueKey);
|
||||
if (object instanceof Map) {
|
||||
exileIds = (Map<String, UUID>) object;
|
||||
|
@ -79,20 +86,22 @@ class PyxisOfPandemoniumExileEffect extends OneShotEffect {
|
|||
exileIds = new HashMap<>();
|
||||
game.getState().setValue(valueKey, exileIds);
|
||||
}
|
||||
|
||||
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
|
||||
|
||||
game.getState().getPlayersInRange(controller.getId(), game).forEach((playerId) -> {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
if (player.getLibrary().hasCards()) {
|
||||
Card card = player.getLibrary().getFromTop(game);
|
||||
String exileKey = playerId.toString() + CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()).toString();
|
||||
String exileKey = playerId.toString()
|
||||
+ CardUtil.getExileZoneId(game,
|
||||
source.getSourceId(),
|
||||
pyxis.getZoneChangeCounter(game));
|
||||
UUID exileId = exileIds.computeIfAbsent(exileKey, k -> UUID.randomUUID());
|
||||
player.moveCardsToExile(card, source, game, false, exileId, sourceObject.getIdName() + " (" + player.getName() + ')');
|
||||
player.moveCardsToExile(card, source, game, false,
|
||||
exileId, pyxis.getIdName() + " (" + player.getName() + ')');
|
||||
card.setFaceDown(true, game);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -103,7 +112,8 @@ class PyxisOfPandemoniumPutOntoBattlefieldEffect extends OneShotEffect {
|
|||
|
||||
public PyxisOfPandemoniumPutOntoBattlefieldEffect() {
|
||||
super(Outcome.PutCardInPlay);
|
||||
this.staticText = "Each player turns face up all cards he or she owns exiled with {this}, then puts all permanent cards among them onto the battlefield";
|
||||
this.staticText = "Each player turns face up all cards he or she owns exiled with {this}, "
|
||||
+ "then puts all permanent cards among them onto the battlefield";
|
||||
}
|
||||
|
||||
public PyxisOfPandemoniumPutOntoBattlefieldEffect(final PyxisOfPandemoniumPutOntoBattlefieldEffect effect) {
|
||||
|
@ -118,10 +128,11 @@ class PyxisOfPandemoniumPutOntoBattlefieldEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (controller != null && sourceObject != null) {
|
||||
Permanent pyxis = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
||||
if (controller != null
|
||||
&& pyxis != null) {
|
||||
Map<String, UUID> exileIds;
|
||||
String valueKey = CardUtil.getObjectZoneString("exileIds", sourceObject, game);
|
||||
String valueKey = CardUtil.getObjectZoneString("exileIds", pyxis, game);
|
||||
Object object = game.getState().getValue(valueKey);
|
||||
if (object instanceof Map) {
|
||||
exileIds = (Map<String, UUID>) object;
|
||||
|
@ -129,24 +140,26 @@ class PyxisOfPandemoniumPutOntoBattlefieldEffect extends OneShotEffect {
|
|||
return true;
|
||||
}
|
||||
Cards cardsToBringIntoPlay = new CardsImpl();
|
||||
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
|
||||
game.getState().getPlayersInRange(controller.getId(), game).forEach((playerId) -> {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
String exileKey = playerId.toString() + CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()).toString();
|
||||
String exileKey = playerId.toString() + CardUtil.getExileZoneId(game,
|
||||
source.getSourceId(),
|
||||
pyxis.getZoneChangeCounter(game));
|
||||
UUID exileId = exileIds.get(exileKey);
|
||||
if (exileId != null) {
|
||||
ExileZone exileZone = game.getState().getExile().getExileZone(exileId);
|
||||
if (exileZone != null) {
|
||||
for (Card card : exileZone.getCards(game)) {
|
||||
exileZone.getCards(game).stream().map((card) -> {
|
||||
card.setFaceDown(false, game);
|
||||
if (card.isPermanent()) {
|
||||
cardsToBringIntoPlay.add(card);
|
||||
}
|
||||
}
|
||||
return card;
|
||||
}).filter((card) -> (card.isPermanent())).forEachOrdered((card) -> {
|
||||
cardsToBringIntoPlay.add(card);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
controller.moveCards(cardsToBringIntoPlay.getCards(game), Zone.BATTLEFIELD, source, game, false, false, true, null);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import mage.constants.SubType;
|
|||
*/
|
||||
public final class ScreechingSilcaw extends CardImpl {
|
||||
|
||||
private static final String text = "<i>Metalcraft</i> — Whenever Screeching Silcaw deals combat damage to a player, if you control three or more artifacts, that player puts the top four cards of their library into their graveyard.";
|
||||
private static final String rule = "<i>Metalcraft</i> — Whenever Screeching Silcaw deals combat damage to a player, if you control three or more artifacts, that player puts the top four cards of their library into their graveyard.";
|
||||
|
||||
public ScreechingSilcaw(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}");
|
||||
|
@ -34,7 +34,7 @@ public final class ScreechingSilcaw extends CardImpl {
|
|||
//"<i>Metalcraft</i> — Whenever Screeching Silcaw deals combat damage to a player, if you control three or more artifacts, that player puts the top four cards of their library into their graveyard.
|
||||
TriggeredAbility conditional = new ConditionalInterveningIfTriggeredAbility(
|
||||
new DealsCombatDamageToAPlayerTriggeredAbility(new PutLibraryIntoGraveTargetEffect(4), false, true),
|
||||
MetalcraftCondition.instance, text);
|
||||
MetalcraftCondition.instance, rule);
|
||||
this.addAbility(conditional);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.Zone;
|
||||
|
@ -44,6 +45,7 @@ public final class YodaJediMaster extends CardImpl {
|
|||
|
||||
public YodaJediMaster(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{1}{G}{U}");
|
||||
this.addSuperType(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.YODA);
|
||||
|
||||
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3));
|
||||
|
|
|
@ -383,6 +383,19 @@ public class VerifyCardDataTest {
|
|||
}
|
||||
}
|
||||
|
||||
// 2. all planeswalkers must be legendary
|
||||
for (ExpansionSet set : sets) {
|
||||
for (ExpansionSet.SetCardInfo cardInfo : set.getSetCardInfo()) {
|
||||
Card card = CardImpl.createCard(cardInfo.getCardClass(), new CardSetInfo(cardInfo.getName(), set.getCode(),
|
||||
cardInfo.getCardNumber(), cardInfo.getRarity(), cardInfo.getGraphicInfo()));
|
||||
Assert.assertNotNull(card);
|
||||
|
||||
if (card.getCardType().contains(CardType.PLANESWALKER) && !card.getSuperType().contains(SuperType.LEGENDARY)) {
|
||||
errorsList.add("error, planeswalker must have legendary type: " + set.getCode() + " - " + set.getName() + " - " + card.getName() + " - " + card.getCardNumber());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printMessages(warningsList);
|
||||
printMessages(errorsList);
|
||||
if (errorsList.size() > 0) {
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
<version>1.4.197</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.j256.ormlite</groupId>
|
||||
<artifactId>ormlite-jdbc</artifactId>
|
||||
|
|
|
@ -325,15 +325,9 @@ public abstract class AbilityImpl implements Ability {
|
|||
}
|
||||
if (!getTargets().isEmpty()) {
|
||||
Outcome outcome = getEffects().isEmpty() ? Outcome.Detriment : getEffects().get(0).getOutcome();
|
||||
// can be cancel by user
|
||||
if (getTargets().chooseTargets(outcome, this.controllerId, this, noMana, game, true) == false) {
|
||||
/*
|
||||
if ((variableManaCost != null) || (announceString != null && !announceString.isEmpty())) {
|
||||
// ?debug message?
|
||||
game.informPlayer(controller, (sourceObject != null ? sourceObject.getIdName() : "") + ": no valid targets");
|
||||
}
|
||||
*/
|
||||
// when activation of ability is canceled during target selection
|
||||
// only activated abilities can be canceled by user (not triggered)
|
||||
if (!getTargets().chooseTargets(outcome, this.controllerId, this, noMana, game, this instanceof ActivatedAbility)) {
|
||||
// was canceled during targer selection
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,8 @@ public class CanAttackAsThoughItDidntHaveDefenderAllEffect extends AsThoughEffec
|
|||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
Permanent permanent = game.getPermanent(objectId);
|
||||
return permanent != null && filter.match(permanent, source.getSourceId(), affectedControllerId, game);
|
||||
return permanent != null
|
||||
&& filter.match(permanent, source.getSourceId(), source.getControllerId(), game);
|
||||
}
|
||||
|
||||
private String getText() {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package mage.cards;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectImpl;
|
||||
import mage.Mana;
|
||||
|
@ -224,11 +225,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
game.getState().getCardState(objectId).addInfo(key, value);
|
||||
}
|
||||
|
||||
protected static final ArrayList<String> rulesError = new ArrayList<String>() {
|
||||
{
|
||||
add("Exception occurred in rules generation");
|
||||
}
|
||||
};
|
||||
protected static final List<String> rulesError = ImmutableList.of("Exception occurred in rules generation");
|
||||
|
||||
@Override
|
||||
public List<String> getRules() {
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
package mage.cards;
|
||||
|
||||
import mage.Mana;
|
||||
import mage.cards.decks.DeckCardInfo;
|
||||
import mage.cards.decks.DeckCardLayout;
|
||||
import mage.cards.decks.DeckCardLists;
|
||||
import mage.cards.repository.CardCriteria;
|
||||
import mage.cards.repository.CardInfo;
|
||||
import mage.cards.repository.CardRepository;
|
||||
|
@ -16,8 +13,6 @@ import mage.util.RandomUtil;
|
|||
import org.apache.log4j.Logger;
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
|
@ -205,73 +200,4 @@ public class Sets extends HashMap<String, ExpansionSet> {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static void saveDeck(String file, DeckCardLists deck) throws FileNotFoundException {
|
||||
Map<String, DeckCardInfo> deckCards = new HashMap<>();
|
||||
Map<String, DeckCardInfo> sideboard = new HashMap<>();
|
||||
try (PrintWriter out = new PrintWriter(file)) {
|
||||
if (deck.getName() != null && !deck.getName().isEmpty()) {
|
||||
out.println("NAME:" + deck.getName());
|
||||
}
|
||||
if (deck.getAuthor() != null && !deck.getAuthor().isEmpty()) {
|
||||
out.println("AUTHOR:" + deck.getAuthor());
|
||||
}
|
||||
for (DeckCardInfo deckCardInfo : deck.getCards()) {
|
||||
if (deckCards.containsKey(deckCardInfo.getCardKey())) {
|
||||
deckCards.put(deckCardInfo.getCardKey(), deckCards.get(deckCardInfo.getCardKey()).increaseQuantity());
|
||||
} else {
|
||||
deckCards.put(deckCardInfo.getCardKey(), deckCardInfo);
|
||||
}
|
||||
}
|
||||
|
||||
for (DeckCardInfo deckCardInfo : deck.getSideboard()) {
|
||||
if (sideboard.containsKey(deckCardInfo.getCardKey())) {
|
||||
sideboard.put(deckCardInfo.getCardKey(), sideboard.get(deckCardInfo.getCardKey()).increaseQuantity());
|
||||
} else {
|
||||
sideboard.put(deckCardInfo.getCardKey(), deckCardInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// Write out all of the cards
|
||||
for (Entry<String, DeckCardInfo> entry : deckCards.entrySet()) {
|
||||
out.printf("%d [%s:%s] %s%n", entry.getValue().getQuantity(), entry.getValue().getSetCode(), entry.getValue().getCardNum(), entry.getValue().getCardName());
|
||||
}
|
||||
for (Entry<String, DeckCardInfo> entry : sideboard.entrySet()) {
|
||||
out.printf("SB: %d [%s:%s] %s%n", entry.getValue().getQuantity(), entry.getValue().getSetCode(), entry.getValue().getCardNum(), entry.getValue().getCardName());
|
||||
}
|
||||
|
||||
// Write out the layout
|
||||
out.print("LAYOUT MAIN:");
|
||||
writeCardLayout(out, deck.getCardLayout());
|
||||
out.print("\n");
|
||||
out.print("LAYOUT SIDEBOARD:");
|
||||
writeCardLayout(out, deck.getSideboardLayout());
|
||||
out.print("\n");
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeCardLayout(PrintWriter out, DeckCardLayout layout) {
|
||||
if (layout == null) {
|
||||
return;
|
||||
}
|
||||
List<List<List<DeckCardInfo>>> cardGrid = layout.getCards();
|
||||
int height = cardGrid.size();
|
||||
int width = (height > 0) ? cardGrid.get(0).size() : 0;
|
||||
out.print("(" + height + ',' + width + ')');
|
||||
out.print(layout.getSettings());
|
||||
out.print("|");
|
||||
for (List<List<DeckCardInfo>> row : cardGrid) {
|
||||
for (List<DeckCardInfo> stack : row) {
|
||||
out.print("(");
|
||||
for (int i = 0; i < stack.size(); ++i) {
|
||||
DeckCardInfo info = stack.get(i);
|
||||
out.printf("[%s:%s]", info.getSetCode(), info.getCardNum());
|
||||
if (i != stack.size() - 1) {
|
||||
out.print(",");
|
||||
}
|
||||
}
|
||||
out.print(")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
90
Mage/src/main/java/mage/cards/decks/DeckFormats.java
Normal file
90
Mage/src/main/java/mage/cards/decks/DeckFormats.java
Normal file
|
@ -0,0 +1,90 @@
|
|||
package mage.cards.decks;
|
||||
|
||||
import mage.cards.decks.exporter.DckExporter;
|
||||
import mage.cards.decks.exporter.DeckExporter;
|
||||
import mage.cards.decks.exporter.MtgoExporter;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Optional;
|
||||
|
||||
public enum DeckFormats {
|
||||
|
||||
DCK(new DckExporter()),
|
||||
MTGO(new MtgoExporter());
|
||||
|
||||
private final DeckExporter exporter;
|
||||
|
||||
DeckFormats(DeckExporter exporter) {
|
||||
this.exporter = exporter;
|
||||
}
|
||||
|
||||
public DeckExporter getExporter() {
|
||||
return exporter;
|
||||
}
|
||||
|
||||
public static Optional<DeckFormats> getFormatForExtension(String filename) {
|
||||
return getExtension(filename).map(c -> {
|
||||
try {
|
||||
return DeckFormats.valueOf(c);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Optional<String> getExtension(String filename) {
|
||||
int i = filename.lastIndexOf('.');
|
||||
if (i > 0) {
|
||||
return Optional.of(filename.substring(i+1).toUpperCase());
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeDeck(String file, DeckCardLists deck) throws IOException {
|
||||
writeDeck(new File(file), deck);
|
||||
}
|
||||
|
||||
public static void writeDeck(String file, DeckCardLists deck, DeckFormats format) throws IOException {
|
||||
writeDeck(new File(file), deck, format);
|
||||
}
|
||||
|
||||
public static void writeDeck(String file, DeckCardLists deck, DeckExporter exporter) throws IOException {
|
||||
writeDeck(new File(file), deck, exporter);
|
||||
}
|
||||
|
||||
public static void writeDeck(File file, DeckCardLists deck) throws IOException {
|
||||
DeckFormats format = DeckFormats.getFormatForExtension(file.getName()).orElseGet(() -> {
|
||||
throw new IllegalArgumentException("Could not determine deck export format.");
|
||||
});
|
||||
writeDeck(file, deck, format);
|
||||
}
|
||||
|
||||
public static void writeDeck(File file, DeckCardLists deck, DeckFormats format) throws IOException {
|
||||
writeDeck(file, deck, format.getExporter());
|
||||
}
|
||||
|
||||
public static void writeDeck(File file, DeckCardLists deck, DeckExporter exporter) throws IOException {
|
||||
try (FileOutputStream out = new FileOutputStream(file)){
|
||||
writeDeck(out, deck, exporter);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeDeck(OutputStream out, DeckCardLists deck, DeckFormats format) {
|
||||
writeDeck(new PrintWriter(out), deck, format);
|
||||
}
|
||||
|
||||
public static void writeDeck(OutputStream out, DeckCardLists deck, DeckExporter exporter) {
|
||||
writeDeck(new PrintWriter(out), deck, exporter);
|
||||
}
|
||||
|
||||
public static void writeDeck(PrintWriter out, DeckCardLists deck, DeckFormats format) {
|
||||
writeDeck(out, deck, format.getExporter());
|
||||
}
|
||||
|
||||
public static void writeDeck(PrintWriter out, DeckCardLists deck, DeckExporter exporter) {
|
||||
exporter.writeDeck(out, deck);
|
||||
out.flush();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package mage.cards.decks.exporter;
|
||||
|
||||
import mage.cards.decks.DeckCardInfo;
|
||||
import mage.cards.decks.DeckCardLayout;
|
||||
import mage.cards.decks.DeckCardLists;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class DckExporter extends DeckExporter {
|
||||
|
||||
public void writeDeck(PrintWriter out, DeckCardLists deck) {
|
||||
Map<String, DeckCardInfo> deckCards = new HashMap<>();
|
||||
Map<String, DeckCardInfo> sideboard = new HashMap<>();
|
||||
|
||||
if (deck.getName() != null && !deck.getName().isEmpty()) {
|
||||
out.println("NAME:" + deck.getName());
|
||||
}
|
||||
if (deck.getAuthor() != null && !deck.getAuthor().isEmpty()) {
|
||||
out.println("AUTHOR:" + deck.getAuthor());
|
||||
}
|
||||
for (DeckCardInfo deckCardInfo : deck.getCards()) {
|
||||
if (deckCards.containsKey(deckCardInfo.getCardKey())) {
|
||||
deckCards.put(deckCardInfo.getCardKey(), deckCards.get(deckCardInfo.getCardKey()).increaseQuantity());
|
||||
} else {
|
||||
deckCards.put(deckCardInfo.getCardKey(), deckCardInfo);
|
||||
}
|
||||
}
|
||||
|
||||
for (DeckCardInfo deckCardInfo : deck.getSideboard()) {
|
||||
if (sideboard.containsKey(deckCardInfo.getCardKey())) {
|
||||
sideboard.put(deckCardInfo.getCardKey(), sideboard.get(deckCardInfo.getCardKey()).increaseQuantity());
|
||||
} else {
|
||||
sideboard.put(deckCardInfo.getCardKey(), deckCardInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// Write out all of the cards
|
||||
for (Map.Entry<String, DeckCardInfo> entry : deckCards.entrySet()) {
|
||||
out.printf("%d [%s:%s] %s%n", entry.getValue().getQuantity(), entry.getValue().getSetCode(), entry.getValue().getCardNum(), entry.getValue().getCardName());
|
||||
}
|
||||
for (Map.Entry<String, DeckCardInfo> entry : sideboard.entrySet()) {
|
||||
out.printf("SB: %d [%s:%s] %s%n", entry.getValue().getQuantity(), entry.getValue().getSetCode(), entry.getValue().getCardNum(), entry.getValue().getCardName());
|
||||
}
|
||||
|
||||
// Write out the layout
|
||||
out.print("LAYOUT MAIN:");
|
||||
writeCardLayout(out, deck.getCardLayout());
|
||||
out.println("");
|
||||
out.print("LAYOUT SIDEBOARD:");
|
||||
writeCardLayout(out, deck.getSideboardLayout());
|
||||
out.println("");
|
||||
}
|
||||
|
||||
private static void writeCardLayout(PrintWriter out, DeckCardLayout layout) {
|
||||
if (layout == null) {
|
||||
return;
|
||||
}
|
||||
List<List<List<DeckCardInfo>>> cardGrid = layout.getCards();
|
||||
int height = cardGrid.size();
|
||||
int width = (height > 0) ? cardGrid.get(0).size() : 0;
|
||||
out.print("(" + height + ',' + width + ')');
|
||||
out.print(layout.getSettings());
|
||||
out.print("|");
|
||||
for (List<List<DeckCardInfo>> row : cardGrid) {
|
||||
for (List<DeckCardInfo> stack : row) {
|
||||
out.print("(");
|
||||
for (int i = 0; i < stack.size(); ++i) {
|
||||
DeckCardInfo info = stack.get(i);
|
||||
out.printf("[%s:%s]", info.getSetCode(), info.getCardNum());
|
||||
if (i != stack.size() - 1) {
|
||||
out.print(",");
|
||||
}
|
||||
}
|
||||
out.print(")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package mage.cards.decks.exporter;
|
||||
|
||||
import mage.cards.decks.DeckCardLists;
|
||||
import mage.cards.decks.DeckFormats;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public abstract class DeckExporter {
|
||||
|
||||
public void writeDeck(String file, DeckCardLists deck) throws IOException {
|
||||
DeckFormats.writeDeck(file, deck, this);
|
||||
}
|
||||
|
||||
public void writeDeck(File file, DeckCardLists deck) throws IOException {
|
||||
DeckFormats.writeDeck(file, deck, this);
|
||||
}
|
||||
|
||||
public void writeDeck(OutputStream out, DeckCardLists deck) {
|
||||
DeckFormats.writeDeck(out, deck, this);
|
||||
}
|
||||
|
||||
public abstract void writeDeck(PrintWriter out, DeckCardLists deck);
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package mage.cards.decks.exporter;
|
||||
|
||||
import mage.cards.decks.DeckCardInfo;
|
||||
import mage.cards.decks.DeckCardLists;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.List;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class MtgoExporter extends DeckExporter {
|
||||
|
||||
@Override
|
||||
public void writeDeck(PrintWriter out, DeckCardLists deck) {
|
||||
TreeMap<String, Integer> deckCards = toCardMap(deck.getCards());
|
||||
TreeMap<String, Integer> sideboard = toCardMap(deck.getSideboard());
|
||||
deckCards.forEach((name, count) -> {
|
||||
out.print(count);
|
||||
out.print(' ');
|
||||
out.println(name);
|
||||
});
|
||||
|
||||
out.println();
|
||||
out.println();
|
||||
|
||||
sideboard.forEach((name, count) -> {
|
||||
out.print(count);
|
||||
out.print(' ');
|
||||
out.println(name);
|
||||
});
|
||||
|
||||
out.println();
|
||||
}
|
||||
|
||||
private TreeMap<String, Integer> toCardMap(List<DeckCardInfo> cards) {
|
||||
TreeMap<String, Integer> counts = new TreeMap<>();
|
||||
for (DeckCardInfo card : cards) {
|
||||
int count = counts.getOrDefault(card.getCardName(), 0) + card.getQuantity();
|
||||
counts.put(card.getCardName(), count);
|
||||
}
|
||||
return counts;
|
||||
}
|
||||
|
||||
}
|
|
@ -116,9 +116,6 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
protected GameOptions gameOptions;
|
||||
protected String startMessage;
|
||||
|
||||
public static volatile int copyCount = 0;
|
||||
public static volatile long copyTime = 0;
|
||||
|
||||
// private final transient LinkedList<MageAction> actions;
|
||||
private Player scorePlayer;
|
||||
// private int score = 0;
|
||||
|
@ -156,10 +153,6 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
|
||||
public GameImpl(final GameImpl game) {
|
||||
long t1 = 0;
|
||||
if (logger.isDebugEnabled()) {
|
||||
t1 = System.currentTimeMillis();
|
||||
}
|
||||
this.id = game.id;
|
||||
this.ready = game.ready;
|
||||
this.startingPlayerId = game.startingPlayerId;
|
||||
|
@ -175,10 +168,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
this.lkiExtended.putAll(game.lkiExtended);
|
||||
this.shortLivingLKI.putAll(game.shortLivingLKI);
|
||||
this.permanentsEntering.putAll(game.permanentsEntering);
|
||||
if (logger.isDebugEnabled()) {
|
||||
copyCount++;
|
||||
copyTime += (System.currentTimeMillis() - t1);
|
||||
}
|
||||
|
||||
this.stateCheckRequired = game.stateCheckRequired;
|
||||
this.scorePlayer = game.scorePlayer;
|
||||
this.scopeRelevant = game.scopeRelevant;
|
||||
|
|
|
@ -24,8 +24,8 @@ public final class GarrukApexPredatorEmblem extends Emblem {
|
|||
public GarrukApexPredatorEmblem() {
|
||||
setName("Emblem Garruk");
|
||||
|
||||
Effect effect = new BoostTargetEffect(-1, 0, Duration.EndOfTurn);
|
||||
effect.setText("it gets -1/-0");
|
||||
Effect effect = new BoostTargetEffect(5, 5, Duration.EndOfTurn);
|
||||
effect.setText("it gets +5/+5");
|
||||
Ability ability = new AttackedByCreatureTriggeredAbility(Zone.COMMAND, effect, false, SetTargetPointer.PERMANENT);
|
||||
effect = new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn);
|
||||
ability.addEffect(effect.concatBy("and"));
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package mage.players;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import mage.ConditionalMana;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
|
@ -178,11 +179,10 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
/**
|
||||
* During some steps we can't play anything
|
||||
*/
|
||||
protected final Map<PhaseStep, Step.StepPart> silentPhaseSteps = new EnumMap<PhaseStep, Step.StepPart>(PhaseStep.class) {
|
||||
{
|
||||
put(PhaseStep.DECLARE_ATTACKERS, Step.StepPart.PRE);
|
||||
}
|
||||
};
|
||||
protected final Map<PhaseStep, Step.StepPart> silentPhaseSteps = ImmutableMap.<PhaseStep, Step.StepPart>builder().
|
||||
put(PhaseStep.DECLARE_ATTACKERS, Step.StepPart.PRE).build();
|
||||
|
||||
|
||||
|
||||
public PlayerImpl(String name, RangeOfInfluence range) {
|
||||
this(UUID.randomUUID());
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package mage.cards.decks.exporter;
|
||||
|
||||
import mage.cards.decks.DeckCardInfo;
|
||||
import mage.cards.decks.DeckCardLists;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class DckExporterTest {
|
||||
|
||||
@Test
|
||||
public void writeDeck() throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DeckCardLists deck = new DeckCardLists();
|
||||
deck.getCards().add(new DeckCardInfo("Forest", "RNA", "1", 2));
|
||||
deck.getCards().add(new DeckCardInfo("Plains", "RNA", "2", 3));
|
||||
deck.getSideboard().add(new DeckCardInfo("Island", "RNA", "3", 2));
|
||||
DckExporter exporter = new DckExporter();
|
||||
exporter.writeDeck(baos, deck);
|
||||
assertEquals("2 [1:RNA] Forest" + System.lineSeparator() +
|
||||
"3 [2:RNA] Plains" + System.lineSeparator() +
|
||||
"SB: 2 [3:RNA] Island" + System.lineSeparator() +
|
||||
"LAYOUT MAIN:" + System.lineSeparator() +
|
||||
"LAYOUT SIDEBOARD:" + System.lineSeparator(),
|
||||
baos.toString());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package mage.cards.decks.exporter;
|
||||
|
||||
import mage.cards.decks.DeckCardInfo;
|
||||
import mage.cards.decks.DeckCardLists;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class MtgoExporterTest {
|
||||
|
||||
@Test
|
||||
public void writeDeck() throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DeckCardLists deck = new DeckCardLists();
|
||||
deck.getCards().add(new DeckCardInfo("Forest", "RNA", "1", 2));
|
||||
deck.getCards().add(new DeckCardInfo("Plains", "RNA", "2", 3));
|
||||
deck.getSideboard().add(new DeckCardInfo("Island", "RNA", "3", 2));
|
||||
MtgoExporter exporter = new MtgoExporter();
|
||||
exporter.writeDeck(baos, deck);
|
||||
assertEquals("2 Forest" + System.lineSeparator() +
|
||||
"3 Plains" + System.lineSeparator() +
|
||||
System.lineSeparator() +
|
||||
System.lineSeparator() +
|
||||
"2 Island" + System.lineSeparator() +
|
||||
System.lineSeparator(),
|
||||
baos.toString());
|
||||
}
|
||||
|
||||
}
|
5
pom.xml
5
pom.xml
|
@ -109,6 +109,11 @@
|
|||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>1.8.0-beta2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>20.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
</project>
|
||||
|
|
Loading…
Reference in a new issue