diff --git a/Mage.Client/pom.xml b/Mage.Client/pom.xml
index d67a18f2cc0..01067104565 100644
--- a/Mage.Client/pom.xml
+++ b/Mage.Client/pom.xml
@@ -62,6 +62,7 @@
jetlang
0.2.4
+
diff --git a/Mage.Client/src/main/java/mage/client/MageFrame.java b/Mage.Client/src/main/java/mage/client/MageFrame.java
index 2c24f9734dc..37a8d0d6eed 100644
--- a/Mage.Client/src/main/java/mage/client/MageFrame.java
+++ b/Mage.Client/src/main/java/mage/client/MageFrame.java
@@ -46,8 +46,6 @@ import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
-import java.util.LinkedHashSet;
-import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -58,7 +56,6 @@ import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
-import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JOptionPane;
@@ -67,8 +64,7 @@ import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.JToolBar.Separator;
-import mage.cards.Card;
-import mage.cards.ExpansionSet;
+import mage.client.cards.CardsStorage;
import mage.client.components.MageComponents;
import mage.client.dialog.AboutDialog;
import mage.client.dialog.CombatDialog;
@@ -79,7 +75,6 @@ import mage.client.remote.Session;
import mage.client.util.EDTExceptionHandler;
import mage.client.util.gui.ArrowBuilder;
import mage.client.util.gui.ImagePanel;
-import mage.sets.Sets;
import mage.util.Logging;
/**
@@ -138,7 +133,7 @@ public class MageFrame extends javax.swing.JFrame {
initComponents();
setSize(1024,768);
- this.setExtendedState(JFrame.MAXIMIZED_BOTH);
+ //this.setExtendedState(JFrame.MAXIMIZED_BOTH);
session = new Session(this);
connectDialog = new ConnectDialog();
@@ -223,11 +218,7 @@ public class MageFrame extends javax.swing.JFrame {
}
private void btnImagesActionPerformed(java.awt.event.ActionEvent evt) {
- Set allCards = new LinkedHashSet();
- for (ExpansionSet set: Sets.getInstance().values()) {
- allCards.addAll(set.createCards());
- }
- Plugins.getInstance().downloadImage(allCards);
+ Plugins.getInstance().downloadImage(CardsStorage.getAllCards());
}
private void btnSymbolsActionPerformed(java.awt.event.ActionEvent evt) {
@@ -544,10 +535,10 @@ public class MageFrame extends javax.swing.JFrame {
private mage.client.table.TablesPane tablesPane;
// End of variables declaration//GEN-END:variables
+ private static final long serialVersionUID = -9104885239063142218L;
private ImagePanel backgroundPane;
public void setStatusText(String status) {
this.lblStatus.setText(status);
}
-
}
diff --git a/Mage.Client/src/main/java/mage/client/cards/CardsStorage.java b/Mage.Client/src/main/java/mage/client/cards/CardsStorage.java
new file mode 100644
index 00000000000..2562da57c6d
--- /dev/null
+++ b/Mage.Client/src/main/java/mage/client/cards/CardsStorage.java
@@ -0,0 +1,22 @@
+package mage.client.cards;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import mage.cards.Card;
+import mage.cards.ExpansionSet;
+import mage.sets.Sets;
+
+public class CardsStorage {
+ private static Set allCards = new LinkedHashSet();
+
+ static {
+ for (ExpansionSet set: Sets.getInstance().values()) {
+ allCards.addAll(set.createCards());
+ }
+ }
+
+ public static Set getAllCards() {
+ return allCards;
+ }
+}
diff --git a/Mage.Client/src/main/java/mage/client/deck/generator/DeckGenerator.java b/Mage.Client/src/main/java/mage/client/deck/generator/DeckGenerator.java
new file mode 100644
index 00000000000..5ecdea65a91
--- /dev/null
+++ b/Mage.Client/src/main/java/mage/client/deck/generator/DeckGenerator.java
@@ -0,0 +1,361 @@
+package mage.client.deck.generator;
+
+import java.awt.Cursor;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+
+import mage.Constants.CardType;
+import mage.Constants.ColoredManaSymbol;
+import mage.cards.Card;
+import mage.cards.CardImpl;
+import mage.cards.ExpansionSet;
+import mage.cards.decks.Deck;
+import mage.client.util.gui.ColorsChooser;
+import mage.sets.Sets;
+import mage.utils.CardUtil;
+
+public class DeckGenerator {
+
+ private static JDialog dlg;
+ private static String selectedColors;
+
+ private static final int SPELL_BOOSTER_PACK_SIZE = 60;
+
+ private static final int DECK_COUNT[] = { 3, 6, 6, 4, 3, 2 };
+ private static final int DECK_COST[] = { 1, 2, 3, 4, 6, 10 };
+ private static final int DECK_SPELLS = 24;
+ private static final int DECK_LANDS = 16;
+ private static final int DECK_SIZE = DECK_SPELLS + DECK_LANDS;
+ private static final int MIN_CARD_SCORE = 25;
+ private static final int MIN_SOURCE = 16;
+ private static final int MAX_NON_BASIC_SOURCE = DECK_LANDS / 2;
+
+ private static Deck deck = new Deck();
+ private static String manaSource;
+
+ public static String generateDeck() {
+ JPanel p0 = new JPanel();
+ p0.setLayout(new BoxLayout(p0, BoxLayout.Y_AXIS));
+ JLabel text = new JLabel("Choose color for your deck: ");
+ p0.add(text);
+ p0.add(Box.createVerticalStrut(5));
+ final ColorsChooser colorsChooser = new ColorsChooser("bu");
+ p0.add(colorsChooser);
+
+ final JButton btnGenerate = new JButton("Ok");
+ btnGenerate.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ btnGenerate.setEnabled(false);
+ colorsChooser.setEnabled(false);
+ selectedColors = (String) colorsChooser.getSelectedItem();
+ dlg.setVisible(false);
+ }
+ });
+ final JButton btnCancel = new JButton("Cancel");
+ btnCancel.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ dlg.setVisible(false);
+ selectedColors = null;
+ }
+ });
+ Object[] options = { btnGenerate, btnCancel };
+ JOptionPane optionPane = new JOptionPane(p0, JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[1]);
+ dlg = optionPane.createDialog("Generating deck");
+ dlg.setVisible(true);
+ dlg.dispose();
+
+ if (selectedColors != null) {
+ buildDeck();
+ try {
+ File tmp = File.createTempFile("tempDeck" + UUID.randomUUID().toString(), ".dck");
+ tmp.createNewFile();
+ deck.setName("Generated-Deck-" + UUID.randomUUID());
+ deck.getDeckCardLists().save(tmp.getAbsolutePath());
+ JOptionPane.showMessageDialog(null, "Deck has been generated.");
+ return tmp.getAbsolutePath();
+ } catch (Exception e) {
+ e.printStackTrace();
+ JOptionPane.showMessageDialog(null, "Couldn't generate deck. Try once again.");
+ }
+ }
+
+ return selectedColors;
+ }
+
+ protected static void buildDeck() {
+ deck = new Deck();
+ List allowedColors = new ArrayList();
+ selectedColors = selectedColors.toUpperCase();
+ for (int i = 0; i < selectedColors.length(); i++) {
+ char c = selectedColors.charAt(i);
+ allowedColors.add(ColoredManaSymbol.lookup(c));
+ }
+
+ List spellCardPool = new ArrayList();
+ List landCardPool = new ArrayList();
+ int nonBasicLandCount = 0;
+ for (ExpansionSet set : Sets.getInstance().values()) {
+ try {
+ List booster = set.createBooster();
+ for (Card card : booster) {
+ if (!card.getCardType().contains(CardType.LAND)) {
+ spellCardPool.add(card);
+ } else {
+ if (!CardUtil.isBasicLand(card)) {
+ if (nonBasicLandCount < MAX_NON_BASIC_SOURCE) {
+ nonBasicLandCount++;
+ landCardPool.add(card);
+ }
+ } else {
+ landCardPool.add(card);
+ }
+ }
+ }
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ System.out.println("deck generator card pool: spells=" + spellCardPool.size() + ", lands=" + landCardPool.size());
+
+ final Collection remainingCards = new ArrayList();
+ for (final Card card : spellCardPool) {
+ remainingCards.add(new MageScoredCard(card, allowedColors));
+ }
+ int min = 0;
+ for (int index = 0; index < DECK_COUNT.length; index++) {
+ final int max = DECK_COST[index];
+ addCardsToDeck(remainingCards, min, max, DECK_COUNT[index]);
+ min = max + 1;
+ }
+ addCardsToDeck(remainingCards, 0, 4, DECK_SPELLS - deck.getCards().size());
+ addCardsToDeck(remainingCards, 5, 10, DECK_SPELLS - deck.getCards().size());
+ addLandsToDeck(allowedColors, landCardPool);
+ }
+
+ private static void addCardsToDeck(final Collection remainingCards, final int minCost, final int maxCost,
+ final int count) {
+
+ for (int c = count; c > 0; c--) {
+
+ MageScoredCard bestCard = null;
+ int bestScore = -1;
+
+ for (final MageScoredCard draftedCard : remainingCards) {
+
+ final int score = draftedCard.getScore();
+ final int cost = draftedCard.getConvertedCost();
+ if (score > bestScore && cost >= minCost && cost <= maxCost) {
+ bestScore = score;
+ bestCard = draftedCard;
+ }
+ }
+
+ if (bestCard == null || bestScore < MIN_CARD_SCORE) {
+ break;
+ }
+ deck.getCards().add(bestCard.card);
+ remainingCards.remove(bestCard);
+ }
+ }
+
+ private static void addLandsToDeck(List allowedColors, List landCardPool) {
+
+ // Calculate statistics per color.
+ final Map colorCount = new HashMap();
+ for (final Card card : deck.getCards()) {
+
+ for (String symbol : card.getManaCost().getSymbols()) {
+ int count = 0;
+ symbol = symbol.replace("{", "").replace("}", "");
+ if (isColoredMana(symbol)) {
+ for (ColoredManaSymbol allowed : allowedColors) {
+ if (allowed.toString().equals(symbol)) {
+ count++;
+ }
+ }
+ if (count > 0) {
+ Integer typeCount = colorCount.get(symbol);
+ if (typeCount == null) {
+ typeCount = new Integer(0);
+ }
+ typeCount += 1;
+ colorCount.put(symbol, typeCount);
+ }
+ }
+ }
+ }
+
+
+
+ // Add suitable non basic lands to deck in order of pack.
+ final Map colorSource = new HashMap();
+ for (final ColoredManaSymbol color : ColoredManaSymbol.values()) {
+ colorSource.put(color.toString(), 0);
+ }
+ for (final Card card : landCardPool) {
+ //TODO: add non basic lands: need to get know what mana a land can produce
+ }
+
+ // Add optimal basic lands to deck.
+ while (deck.getCards().size() < DECK_SIZE) {
+
+ ColoredManaSymbol bestColor = null;
+ int lowestRatio = Integer.MAX_VALUE;
+ for (final ColoredManaSymbol color : ColoredManaSymbol.values()) {
+
+ final Integer count = colorCount.get(color.toString());
+ if (count != null && count > 0) {
+ final int source = colorSource.get(color.toString());
+ final int ratio;
+ if (source < MIN_SOURCE) {
+ ratio = source - count;
+ } else {
+ ratio = source * 100 / count;
+ }
+ if (ratio < lowestRatio) {
+ lowestRatio = ratio;
+ bestColor = color;
+ }
+ }
+ }
+ final Card landCard = getBestBasicLand(bestColor);
+ Integer count = colorSource.get(bestColor.toString());
+ count++;
+ colorSource.put(bestColor.toString(), count);
+ deck.getCards().add(landCard);
+ }
+ }
+
+ private static Card getBestBasicLand(ColoredManaSymbol color) {
+ manaSource = color.toString();
+ if (color.equals(ColoredManaSymbol.G)) {
+ return CardImpl.createCard(Sets.findCard("Forest"));
+ }
+ if (color.equals(ColoredManaSymbol.R)) {
+ return CardImpl.createCard(Sets.findCard("Mountain"));
+ }
+ if (color.equals(ColoredManaSymbol.B)) {
+ return CardImpl.createCard(Sets.findCard("Swamp"));
+ }
+ if (color.equals(ColoredManaSymbol.U)) {
+ return CardImpl.createCard(Sets.findCard("Island"));
+ }
+ if (color.equals(ColoredManaSymbol.W)) {
+ return CardImpl.createCard(Sets.findCard("Plains"));
+ }
+
+ return null;
+ }
+
+ private static class MageScoredCard {
+
+ private Card card;
+ private int score;
+
+ private static final int SINGLE_PENALTY[] = { 0, 1, 1, 3, 6, 9 };
+ //private static final int DOUBLE_PENALTY[] = { 0, 0, 1, 2, 4, 6 };
+
+ public MageScoredCard(Card card, List allowedColors) {
+ this.card = card;
+
+ int type = 0;
+ if (card.getCardType().contains(CardType.CREATURE)) {
+ type = 10;
+ } else if (card.getSubtype().contains("Equipment")) {
+ type = 8;
+ } else if (card.getSubtype().contains("Aura")) {
+ type = 5;
+ } else if (card.getCardType().contains(CardType.INSTANT)) {
+ type = 7;
+ } else {
+ type = 6;
+ }
+
+ this.score = // 5*card.getValue() + // not possible now
+ // 3*card.getRemoval() + // not possible now
+ type + getManaCostScore(card, allowedColors);
+ }
+
+ private int getManaCostScore(Card card, List allowedColors) {
+ int converted = card.getManaCost().convertedManaCost();
+ final Map singleCount = new HashMap();
+ int maxSingleCount = 0;
+ for (String symbol : card.getManaCost().getSymbols()) {
+ int count = 0;
+ symbol = symbol.replace("{", "").replace("}", "");
+ if (isColoredMana(symbol)) {
+ for (ColoredManaSymbol allowed : allowedColors) {
+ if (allowed.toString().equals(symbol)) {
+ count++;
+ }
+ }
+ if (count == 0) {
+ return 0;
+ }
+ Integer typeCount = singleCount.get(symbol);
+ if (typeCount == null) {
+ typeCount = new Integer(0);
+ }
+ typeCount += 1;
+ singleCount.put(symbol, typeCount);
+ maxSingleCount = Math.max(maxSingleCount, typeCount);
+ }
+ }
+ return 2 * converted + +3 * (10 - SINGLE_PENALTY[maxSingleCount]/*-DOUBLE_PENALTY[doubleCount]*/);
+ }
+
+ public int getScore() {
+ return this.score;
+ }
+
+ public int getConvertedCost() {
+ return this.card.getManaCost().convertedManaCost();
+ }
+
+ public Card getCard() {
+ return this.card;
+ }
+ }
+
+ protected static boolean isColoredMana(String symbol) {
+ return symbol.equals("W") || symbol.equals("G") || symbol.equals("U") || symbol.equals("B") || symbol.equals("R");
+ }
+
+ public static void main(String[] args) {
+ /*for (Card card : CardsStorage.getAllCards()) {
+ System.out.println(card.getName());
+ System.out.print(" ");
+ for (String symbol : card.getManaCost().getSymbols()) {
+ symbol = symbol.replace("{", "").replace("}", "");
+ System.out.print(symbol + " ");
+ }
+ System.out.println(CardUtil.isBasicLand(card));
+ List allowedColors = new ArrayList();
+ allowedColors.add(ColoredManaSymbol.lookup('W'));
+ allowedColors.add(ColoredManaSymbol.lookup('G'));
+ DeckGenerator.MageScoredCard m = new DeckGenerator.MageScoredCard(card, allowedColors);
+
+ System.out.println();
+ System.out.println(" score: " + m.getScore());
+ System.out.println();
+ }*/
+
+ System.out.println("Done! Path: " + generateDeck());
+
+ }
+}
diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.java b/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.java
index 13c63b1e280..b64f8e66f17 100644
--- a/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.java
+++ b/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.java
@@ -47,6 +47,7 @@ import mage.cards.Card;
import mage.cards.ExpansionSet;
import mage.client.cards.BigCard;
import mage.client.cards.CardGrid;
+import mage.client.cards.CardsStorage;
import mage.filter.Filter.ComparisonScope;
import mage.filter.FilterCard;
import mage.sets.Sets;
@@ -58,7 +59,6 @@ import mage.view.CardsView;
*/
public class CardSelector extends javax.swing.JPanel implements ComponentListener {
- private final Set allCards = new LinkedHashSet();
private final List cards = new ArrayList();
private final FilterCard filter = new FilterCard();
private BigCard bigCard;
@@ -73,9 +73,6 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
this.bigCard = bigCard;
cbExpansionSet.setModel(new DefaultComboBoxModel(Sets.getInstance().values().toArray()));
// cbExpansionSet.insertItemAt("All sets", 0);
- for (ExpansionSet set: Sets.getInstance().values()) {
- allCards.addAll(set.createCards());
- }
cbExpansionSet.setSelectedIndex(0);
filter.setUseColor(true);
filter.getColor().setBlack(true);
@@ -103,7 +100,7 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
try {
setCursor(new Cursor(Cursor.WAIT_CURSOR));
cards.clear();
- for (Card card: allCards) {
+ for (Card card: CardsStorage.getAllCards()) {
if (filter.match(card))
cards.add(card);
}
diff --git a/Mage.Client/src/main/java/mage/client/table/NewPlayerPanel.java b/Mage.Client/src/main/java/mage/client/table/NewPlayerPanel.java
index 73792a8fe28..fd144064f11 100644
--- a/Mage.Client/src/main/java/mage/client/table/NewPlayerPanel.java
+++ b/Mage.Client/src/main/java/mage/client/table/NewPlayerPanel.java
@@ -34,12 +34,30 @@
package mage.client.table;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JDialog;
import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
import javax.swing.filechooser.FileFilter;
+
+import mage.cards.Card;
+import mage.cards.ExpansionSet;
import mage.client.MageFrame;
+import mage.client.deck.generator.DeckGenerator;
import mage.client.util.Config;
+import mage.client.util.gui.ColorsChooser;
+import mage.sets.Sets;
/**
*
@@ -80,6 +98,13 @@ public class NewPlayerPanel extends javax.swing.JPanel {
fcSelectDeck.setSelectedFile(null);
}
+ protected void generateDeck() {
+ String path = DeckGenerator.generateDeck();
+ if (path != null) {
+ this.txtPlayerDeck.setText(path);
+ }
+ }
+
public String getPlayerName() {
return this.txtPlayerName.getText();
}
@@ -95,6 +120,7 @@ public class NewPlayerPanel extends javax.swing.JPanel {
*/
@SuppressWarnings("unchecked")
// //GEN-BEGIN:initComponents
+ // //GEN-END:initComponents
private void initComponents() {
lblPlayerName = new javax.swing.JLabel();
@@ -102,7 +128,8 @@ public class NewPlayerPanel extends javax.swing.JPanel {
lblPlayerDeck = new javax.swing.JLabel();
txtPlayerDeck = new javax.swing.JTextField();
btnPlayerDeck = new javax.swing.JButton();
-
+ btnGenerate = new javax.swing.JButton();
+
lblPlayerName.setLabelFor(txtPlayerName);
lblPlayerName.setText("Name:");
@@ -115,6 +142,13 @@ public class NewPlayerPanel extends javax.swing.JPanel {
btnPlayerDeckActionPerformed(evt);
}
});
+
+ btnGenerate.setText("Generate deck");
+ btnGenerate.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ btnGenerateActionPerformed(evt);
+ }
+ });
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
@@ -131,7 +165,10 @@ public class NewPlayerPanel extends javax.swing.JPanel {
.addComponent(txtPlayerName, javax.swing.GroupLayout.DEFAULT_SIZE, 405, Short.MAX_VALUE)
.addComponent(txtPlayerDeck, javax.swing.GroupLayout.DEFAULT_SIZE, 405, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(btnPlayerDeck, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addComponent(btnPlayerDeck, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ )
+ .addComponent(btnGenerate)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@@ -143,14 +180,22 @@ public class NewPlayerPanel extends javax.swing.JPanel {
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblPlayerDeck)
.addComponent(txtPlayerDeck, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addComponent(btnPlayerDeck, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE)))
+ .addComponent(btnPlayerDeck, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGap(3, 3, 3)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(btnGenerate)
+ )
+ )
);
- }// //GEN-END:initComponents
+ }
private void btnPlayerDeckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnPlayerDeckActionPerformed
playerLoadDeck();
}//GEN-LAST:event_btnPlayerDeckActionPerformed
+ private void btnGenerateActionPerformed(java.awt.event.ActionEvent evt) {
+ generateDeck();
+ }
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnPlayerDeck;
@@ -160,6 +205,7 @@ public class NewPlayerPanel extends javax.swing.JPanel {
private javax.swing.JTextField txtPlayerName;
// End of variables declaration//GEN-END:variables
+ private javax.swing.JButton btnGenerate;
}
class DeckFilter extends FileFilter {
diff --git a/Mage.Client/src/main/java/mage/client/util/Constants.java b/Mage.Client/src/main/java/mage/client/util/Constants.java
index e3a77f2212a..05435cc70eb 100644
--- a/Mage.Client/src/main/java/mage/client/util/Constants.java
+++ b/Mage.Client/src/main/java/mage/client/util/Constants.java
@@ -28,7 +28,8 @@
package mage.client.util;
-import java.io.File;
+import javax.swing.BorderFactory;
+import javax.swing.border.Border;
/**
*
@@ -67,6 +68,8 @@ public final class Constants {
public static final int POWBOX_TEXT_MAX_LEFT = 212;
public static final int DAMAGE_MAX_LEFT = 180;
+ public static final Border EMPTY_BORDER = BorderFactory.createEmptyBorder(2,2,2,2);
+
public static final double SCALE_FACTOR = 0.5;
public static final String PLUGINS_DIRECTORY = "plugins/";
diff --git a/Mage.Client/src/main/java/mage/client/util/FileUtils.java b/Mage.Client/src/main/java/mage/client/util/FileUtils.java
new file mode 100644
index 00000000000..21032b988f7
--- /dev/null
+++ b/Mage.Client/src/main/java/mage/client/util/FileUtils.java
@@ -0,0 +1,23 @@
+package mage.client.util;
+
+import java.io.File;
+
+public class FileUtils {
+ public static File getTempDir(String key) {
+ String tmpDir = System.getProperty("java.io.tmpdir");
+ String sep = System.getProperty("file.separator");
+
+ if (!tmpDir.endsWith(sep))
+ tmpDir += sep;
+
+ tmpDir += key + "-" + java.util.UUID.randomUUID().toString();
+
+ File dir = new File(tmpDir);
+ if (!dir.mkdirs()) {
+ throw new RuntimeException("couldn't create temp directory " + tmpDir);
+ }
+
+ return dir;
+
+ }
+}
diff --git a/Mage.Client/src/main/java/mage/client/util/gui/ColorsChooser.java b/Mage.Client/src/main/java/mage/client/util/gui/ColorsChooser.java
new file mode 100644
index 00000000000..4c97b5688ea
--- /dev/null
+++ b/Mage.Client/src/main/java/mage/client/util/gui/ColorsChooser.java
@@ -0,0 +1,57 @@
+package mage.client.util.gui;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.GridLayout;
+
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.ListCellRenderer;
+
+import mage.client.util.Constants;
+
+public class ColorsChooser extends JComboBox implements ListCellRenderer {
+
+ private static final long serialVersionUID = 1L;
+
+ public ColorsChooser(final String colors) {
+
+ this.setRenderer(this);
+
+ final DefaultComboBoxModel model = new DefaultComboBoxModel();
+ model.addElement("bu");
+ model.addElement("bg");
+ model.addElement("br");
+ model.addElement("bw");
+ model.addElement("ug");
+ model.addElement("ur");
+ model.addElement("uw");
+ model.addElement("gr");
+ model.addElement("gw");
+ model.addElement("rw");
+ setModel(model);
+ setSelectedItem(colors);
+ this.setFocusable(false);
+ }
+
+ @Override
+ public Component getListCellRendererComponent(final JList list, final Object value, final int index, final boolean isSelected,
+ final boolean cellHasFocus) {
+
+ final JPanel panel = new JPanel(new GridLayout(1, 3));
+ drawOn(panel, (String) value);
+ panel.setBorder(Constants.EMPTY_BORDER);
+ if (isSelected) {
+ panel.setBackground(Color.LIGHT_GRAY);
+ }
+ return panel;
+ }
+
+ private void drawOn(JPanel panel, String value) {
+ String s = value.replace("b", "{B}").replace("r", "{R}").replace("g", "{G}").replace("w", "{W}").replace("u", "{U}");
+ panel.add(new JLabel(s));
+ }
+}
diff --git a/Mage.Common/src/mage/utils/CardUtil.java b/Mage.Common/src/mage/utils/CardUtil.java
index 57b4729fe8e..b864a9bcae1 100644
--- a/Mage.Common/src/mage/utils/CardUtil.java
+++ b/Mage.Common/src/mage/utils/CardUtil.java
@@ -1,6 +1,7 @@
package mage.utils;
import mage.Constants.CardType;
+import mage.cards.Card;
import mage.cards.MagePermanent;
import mage.view.CardView;
@@ -39,4 +40,8 @@ public class CardUtil {
public static boolean is(CardView card, CardType type) {
return card.getCardTypes().contains(type);
}
+
+ public static boolean isBasicLand(Card card) {
+ return card.getSupertype().contains("Basic");
+ }
}