diff --git a/Mage.Client/pom.xml b/Mage.Client/pom.xml
index 76158ee4df4..9d8aed08b81 100644
--- a/Mage.Client/pom.xml
+++ b/Mage.Client/pom.xml
@@ -47,6 +47,12 @@
java-image-scaling
0.8.4
+
+ com.google.collections
+ google-collections
+ 1.0
+ provided
+
diff --git a/Mage.Client/src/main/java/mage/client/MageFrame.java b/Mage.Client/src/main/java/mage/client/MageFrame.java
index 67687103ba2..ca3e208f597 100644
--- a/Mage.Client/src/main/java/mage/client/MageFrame.java
+++ b/Mage.Client/src/main/java/mage/client/MageFrame.java
@@ -37,19 +37,24 @@ package mage.client;
import java.awt.Cursor;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
-import java.io.File;
+import java.util.LinkedHashSet;
+import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.Preferences;
import javax.swing.Box;
+import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JLayeredPane;
import javax.swing.JOptionPane;
+import javax.swing.JToolBar.Separator;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
+import mage.cards.Card;
+import mage.cards.ExpansionSet;
import mage.client.dialog.AboutDialog;
import mage.client.dialog.CombatDialog;
import mage.client.dialog.ConnectDialog;
@@ -57,11 +62,8 @@ import mage.client.dialog.PickNumberDialog;
import mage.client.plugins.impl.Plugins;
import mage.client.remote.Session;
import mage.client.util.EDTExceptionHandler;
-import mage.interfaces.plugin.ThemePlugin;
+import mage.sets.Sets;
import mage.util.Logging;
-import net.xeoh.plugins.base.PluginManager;
-import net.xeoh.plugins.base.impl.PluginManagerFactory;
-import net.xeoh.plugins.base.util.PluginManagerUtil;
/**
*
@@ -127,7 +129,31 @@ public class MageFrame extends javax.swing.JFrame {
enableButtons();
else
disableButtons();
+
+ //TODO:
+ Separator separator = new javax.swing.JToolBar.Separator();
+ mageToolbar.add(separator);
+
+ JButton btnDownload = new JButton("Images");
+ btnDownload.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
+ btnDownload.setFocusable(false);
+ btnDownload.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
+ btnDownload.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
+ btnDownload.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ btnImagesActionPerformed(evt);
+ }
+ });
+ mageToolbar.add(btnDownload);
}
+
+ 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);
+ }
public void showGame(UUID gameId, UUID playerId) {
this.tablesPane.hideTables();
diff --git a/Mage.Client/src/main/java/mage/client/game/BattlefieldPanel.java b/Mage.Client/src/main/java/mage/client/game/BattlefieldPanel.java
index aa2b2fed676..b972e588765 100644
--- a/Mage.Client/src/main/java/mage/client/game/BattlefieldPanel.java
+++ b/Mage.Client/src/main/java/mage/client/game/BattlefieldPanel.java
@@ -84,9 +84,6 @@ public class BattlefieldPanel extends javax.swing.JLayeredPane implements Compon
ui.put("jScrollPane", jScrollPane);
ui.put("battlefieldPanel", this);
initComponents();
-
- addMouseListener(new MageMouseAdapter(this, gameId));
- addMouseMotionListener(new MageMouseMotionAdapter(this, bigCard));
}
public void init(UUID gameId, BigCard bigCard) {
@@ -95,13 +92,13 @@ public class BattlefieldPanel extends javax.swing.JLayeredPane implements Compon
if (Plugins.getInstance().isCardPluginLoaded()) {
bigCard.removeTextComponent();
}
+ addMouseListener(new MageMouseAdapter(this, gameId));
+ addMouseMotionListener(new MageMouseMotionAdapter(this, bigCard));
}
public void update(Map battlefield) {
for (PermanentView permanent: battlefield.values()) {
if (!permanents.containsKey(permanent.getId())) {
- //TODO: remove me
- //System.out.println("Add permanent: " + permanent.getCardNumber());
addPermanent(permanent);
}
else {
@@ -133,8 +130,10 @@ public class BattlefieldPanel extends javax.swing.JLayeredPane implements Compon
}
permanents.put(permanent.getId(), perm);
this.add(perm, 10);
- moveToFront(perm);
- perm.update(permanent);
+ if (!Plugins.getInstance().isCardPluginLoaded()) {
+ moveToFront(perm);
+ perm.update(permanent);
+ }
}
private void groupAttachments(PermanentView permanent) {
@@ -228,7 +227,7 @@ public class BattlefieldPanel extends javax.swing.JLayeredPane implements Compon
}
private void resizeBattlefield() {
- Dimension area = new Dimension(0, 0);
+ /*Dimension area = new Dimension(0, 0);
Dimension size = getPreferredSize();
for (Component comp: getComponents()) {
@@ -244,7 +243,7 @@ public class BattlefieldPanel extends javax.swing.JLayeredPane implements Compon
setPreferredSize(area);
revalidate();
repaint();
- }
+ }*/
}
diff --git a/Mage.Client/src/main/java/mage/client/plugins/MagePlugins.java b/Mage.Client/src/main/java/mage/client/plugins/MagePlugins.java
index d4fce6bc6c7..b19e253236a 100644
--- a/Mage.Client/src/main/java/mage/client/plugins/MagePlugins.java
+++ b/Mage.Client/src/main/java/mage/client/plugins/MagePlugins.java
@@ -2,10 +2,12 @@ package mage.client.plugins;
import java.util.Collection;
import java.util.Map;
+import java.util.Set;
import java.util.UUID;
import javax.swing.JComponent;
+import mage.cards.Card;
import mage.cards.CardDimensions;
import mage.cards.MagePermanent;
import mage.client.cards.BigCard;
@@ -18,4 +20,5 @@ public interface MagePlugins {
MagePermanent getMagePermanent(PermanentView card, BigCard bigCard, CardDimensions dimension, UUID gameId);
boolean isCardPluginLoaded();
void sortPermanents(Map ui, Collection permanents);
+ void downloadImage(Set allCards);
}
diff --git a/Mage.Client/src/main/java/mage/client/plugins/adapters/MageMouseMotionAdapter.java b/Mage.Client/src/main/java/mage/client/plugins/adapters/MageMouseMotionAdapter.java
index efa2d8b942b..8f2b5bb1ab3 100644
--- a/Mage.Client/src/main/java/mage/client/plugins/adapters/MageMouseMotionAdapter.java
+++ b/Mage.Client/src/main/java/mage/client/plugins/adapters/MageMouseMotionAdapter.java
@@ -24,6 +24,7 @@ public class MageMouseMotionAdapter extends MouseMotionAdapter {
@Override
public void mouseMoved(MouseEvent e) {
if (!Plugins.getInstance().isCardPluginLoaded()) return;
+ if (bigCard == null) return;
Object o = parent.getComponentAt(e.getPoint());
if (o instanceof MagePermanent) {
MagePermanent card = (MagePermanent) o;
diff --git a/Mage.Client/src/main/java/mage/client/plugins/impl/Plugins.java b/Mage.Client/src/main/java/mage/client/plugins/impl/Plugins.java
index 00d4c594bf7..ef786e7562b 100644
--- a/Mage.Client/src/main/java/mage/client/plugins/impl/Plugins.java
+++ b/Mage.Client/src/main/java/mage/client/plugins/impl/Plugins.java
@@ -2,14 +2,18 @@ package mage.client.plugins.impl;
import java.io.File;
import java.util.Collection;
+import java.util.LinkedHashSet;
import java.util.Map;
+import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComponent;
+import mage.cards.Card;
import mage.cards.CardDimensions;
+import mage.cards.ExpansionSet;
import mage.cards.MagePermanent;
import mage.cards.action.impl.EmptyCallback;
import mage.client.cards.BigCard;
@@ -20,6 +24,7 @@ import mage.client.util.DefaultActionCallback;
import mage.constants.Constants;
import mage.interfaces.plugin.CardPlugin;
import mage.interfaces.plugin.ThemePlugin;
+import mage.sets.Sets;
import mage.util.Logging;
import mage.view.PermanentView;
import net.xeoh.plugins.base.PluginManager;
@@ -81,4 +86,9 @@ public class Plugins implements MagePlugins {
public void sortPermanents(Map ui, Collection permanents) {
if (this.cardPlugin != null) this.cardPlugin.sortPermanents(ui, permanents);
}
+
+ @Override
+ public void downloadImage(Set allCards) {
+ if (this.cardPlugin != null) this.cardPlugin.downloadImages(allCards);
+ }
}
diff --git a/Mage.Common/src/mage/interfaces/plugin/CardPlugin.java b/Mage.Common/src/mage/interfaces/plugin/CardPlugin.java
index 584f611ffd9..91f2f110ae6 100644
--- a/Mage.Common/src/mage/interfaces/plugin/CardPlugin.java
+++ b/Mage.Common/src/mage/interfaces/plugin/CardPlugin.java
@@ -2,10 +2,12 @@ package mage.interfaces.plugin;
import java.util.Collection;
import java.util.Map;
+import java.util.Set;
import java.util.UUID;
import javax.swing.JComponent;
+import mage.cards.Card;
import mage.cards.CardDimensions;
import mage.cards.MagePermanent;
import mage.cards.action.ActionCallback;
@@ -21,4 +23,5 @@ import net.xeoh.plugins.base.Plugin;
public interface CardPlugin extends Plugin {
MagePermanent getMagePermanent(PermanentView permanent, CardDimensions dimension, UUID gameId, ActionCallback callback);
void sortPermanents(Map ui, Collection cards);
+ void downloadImages(Set allCards);
}
diff --git a/Mage.Plugins/Mage.Card.Plugin/pom.xml b/Mage.Plugins/Mage.Card.Plugin/pom.xml
index 5a674465c5f..2e0ea047534 100644
--- a/Mage.Plugins/Mage.Card.Plugin/pom.xml
+++ b/Mage.Plugins/Mage.Card.Plugin/pom.xml
@@ -18,8 +18,8 @@
- org.mage
- Mage-Common
+ org.mage
+ Mage-Common
${mage-version}
@@ -33,6 +33,18 @@
1.2.9
provided
+
+ com.google.collections
+ google-collections
+ 1.0
+ provided
+
+
+ com.mortennobel
+ java-image-scaling
+ 0.8.4
+ provided
+
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/card/arcane/CardPanel.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/card/arcane/CardPanel.java
index 606b3ae73ca..989e7776124 100644
--- a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/card/arcane/CardPanel.java
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/card/arcane/CardPanel.java
@@ -15,7 +15,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
-import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;
@@ -28,6 +27,8 @@ import mage.view.PermanentView;
import org.apache.log4j.Logger;
import org.mage.card.arcane.ScaledImagePanel.MultipassType;
import org.mage.card.arcane.ScaledImagePanel.ScalingType;
+import org.mage.plugins.card.images.ImageCache;
+
@SuppressWarnings({"unchecked","rawtypes"})
public class CardPanel extends MagePermanent {
@@ -125,21 +126,15 @@ public class CardPanel extends MagePermanent {
Util.threadPool.submit(new Runnable() {
public void run () {
- //BufferedImage srcImage = null; //TODO: ImageCache.getImageOriginal(gameCard);
- tappedAngle = gameCard.isTapped() ? CardPanel.TAPPED_ANGLE : 0;
-
- try {
- log.info(gameCard.getCardNumber() + " " + gameCard.getName() + " " + gameCard.getExpansionSetCode());
- BufferedImage srcImage = ImageIO.read(CardPanel.class.getClassLoader().getResourceAsStream("Mountain.40.full.jpg"));
+ tappedAngle = gameCard.isTapped() ? CardPanel.TAPPED_ANGLE : 0;
+ BufferedImage srcImage = ImageCache.getImageOriginal(gameCard);
if (srcImage != null) {
//setImage(srcImage, ImageUtil.getBlurredImage(srcImage, 3, 1.0f));
hasImage = true;
setText(gameCard);
setImage(srcImage, srcImage);
}
- } catch (IOException io) {
- io.printStackTrace();
- }
+
}
});
}
@@ -424,7 +419,7 @@ public class CardPanel extends MagePermanent {
@Override
public boolean isTapped() {
- return false;
+ return gameCard.isTapped();
}
@Override
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/CardPluginImpl.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/CardPluginImpl.java
index 1fc33d21f2e..a4c5a4a6084 100644
--- a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/CardPluginImpl.java
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/CardPluginImpl.java
@@ -1,18 +1,18 @@
package org.mage.plugins.card;
-import java.awt.Color;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.UUID;
-import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JLayeredPane;
import javax.swing.JScrollPane;
+import mage.cards.Card;
import mage.cards.CardDimensions;
import mage.cards.MagePermanent;
import mage.cards.action.ActionCallback;
@@ -27,7 +27,14 @@ import net.xeoh.plugins.base.annotations.meta.Author;
import org.apache.log4j.Logger;
import org.mage.card.arcane.CardPanel;
import org.mage.plugins.card.constants.Constants;
+import org.mage.plugins.card.images.DownloadPictures;
+/**
+ * {@link CardPlugin} implementation.
+ *
+ * @version 0.1 01.11.2010
+ * @author nantuko
+ */
@PluginImplementation
@Author(name = "nantuko")
public class CardPluginImpl implements CardPlugin {
@@ -62,7 +69,7 @@ public class CardPluginImpl implements CardPlugin {
}
public String toString() {
- return "[Card plugin, version 0.1]";
+ return "[Card plugin, version 0.2]";
}
@Override
@@ -216,7 +223,7 @@ public class CardPluginImpl implements CardPlugin {
int panelY = y + (stackPosition * stackSpacingY);
//panel.setLocation(panelX, panelY);
battlefieldPanel.moveToBack(panel);
- panel.setCardBounds(panelX + 100, panelY+70, cardWidth, cardHeight);
+ panel.setCardBounds(panelX, panelY, cardWidth, cardHeight);
}
rowBottom = Math.max(rowBottom, y + stack.getHeight());
x += stack.getWidth();
@@ -370,5 +377,8 @@ public class CardPluginImpl implements CardPlugin {
}
}
-
+ @Override
+ public void downloadImages(Set allCards) {
+ DownloadPictures.startDownload(null, allCards);
+ }
}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/CardUrl.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/CardUrl.java
new file mode 100644
index 00000000000..f318d5a12e0
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/CardUrl.java
@@ -0,0 +1,55 @@
+package org.mage.plugins.card;
+
+import java.io.Serializable;
+
+/**
+ * Contains card data and image url.
+ *
+ * @author nantuko
+ */
+public class CardUrl implements Serializable {
+
+ public String name;
+ public String set;
+ public boolean token = false;
+ public Integer collector;
+ public String url = "";
+ public boolean existsInTheGame = false;
+
+ public CardUrl(String cardName, String cardSet, Integer collectorId, boolean isToken) {
+ name = cardName;
+ set = cardSet;
+ collector = collectorId;
+ token = isToken;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == null) { return false; }
+ if (other instanceof CardUrl) {
+ return name.equals(((CardUrl) other).name) && set.equals(((CardUrl) other).set)
+ && collector.equals(((CardUrl) other).collector) && token==((CardUrl)other).token;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 0;
+ hash = name.hashCode();
+ hash = 31*hash + set.hashCode();
+ hash = 31*hash + collector.hashCode();
+ hash = 31*hash + (token ? 1 : 0);
+ return hash;
+ }
+
+ public boolean isExistsInTheGame() {
+ return existsInTheGame;
+ }
+
+ public void setExistsInTheGame(boolean existsInTheGame) {
+ this.existsInTheGame = existsInTheGame;
+ }
+
+ private static final long serialVersionUID = 2L;
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/constants/Constants.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/constants/Constants.java
index 632578704cc..0713b66a342 100644
--- a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/constants/Constants.java
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/constants/Constants.java
@@ -1,13 +1,20 @@
package org.mage.plugins.card.constants;
import java.awt.Rectangle;
+import java.io.File;
public class Constants {
public static final String RESOURCE_PATH = "/images";
public static final String RESOURCE_PATH_MANA = resourcePath("mana");
-
public static final Rectangle CARD_SIZE_FULL = new Rectangle(101, 149);
+ public interface IO {
+ public static final String imageBaseDir = "." + File.separator + "plugins" + File.separator + "images" + File.separator;
+ public static final String IMAGE_PROPERTIES_FILE = "image.url.properties";
+ }
+
+ public static final String CARD_IMAGE_PATH_TEMPLATE = "." + File.separator + "plugins" + File.separator + "images/{set}/{name}.{collector}.full.jpg";
+
/**
* Build resource path.
*
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/images/CardInfo.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/images/CardInfo.java
new file mode 100644
index 00000000000..66c6b808e3a
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/images/CardInfo.java
@@ -0,0 +1,13 @@
+package org.mage.plugins.card.images;
+
+public class CardInfo {
+ public String name;
+ public String set;
+ public Integer collectorId;
+ public boolean isToken = false;
+ public CardInfo(String name, String set, Integer collectorId) {
+ this.name = name;
+ this.set = set;
+ this.collectorId = collectorId;
+ }
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/images/DownloadPictures.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/images/DownloadPictures.java
new file mode 100644
index 00000000000..8a448fe06ae
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/images/DownloadPictures.java
@@ -0,0 +1,409 @@
+package org.mage.plugins.card.images;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.swing.AbstractButton;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.ButtonGroup;
+import javax.swing.ComboBoxModel;
+import javax.swing.DefaultBoundedRangeModel;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
+import javax.swing.JRadioButton;
+import javax.swing.JTextField;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import mage.cards.Card;
+
+import org.apache.log4j.Logger;
+import org.mage.plugins.card.CardUrl;
+import org.mage.plugins.card.constants.Constants;
+import org.mage.plugins.card.properties.SettingsManager;
+import org.mage.plugins.card.utils.CardImageUtils;
+
+public class DownloadPictures extends DefaultBoundedRangeModel implements Runnable {
+
+ private int type;
+ private JTextField addr, port;
+ private JProgressBar bar;
+ private JOptionPane dlg;
+ private boolean cancel;
+ private JButton close;
+ private int cardIndex;
+ private ArrayList cards;
+ private ArrayList cardsInGame;
+ private JComboBox jComboBox1;
+ private JLabel jLabel1;
+ private static boolean offlineMode = false;
+ private JCheckBox checkBox;
+
+ public static final Proxy.Type[] types = Proxy.Type.values();
+
+ public static void main(String[] args) {
+ startDownload(null, null);
+ }
+
+ public static void startDownload(JFrame frame, Set allCards) {
+ ArrayList cards = getNeededCards(allCards);
+
+ if (cards == null || cards.size() == 0) {
+ JOptionPane.showMessageDialog(null, "All card pictures have been downloaded.");
+ return;
+ }
+
+ DownloadPictures download = new DownloadPictures(cards);
+ JDialog dlg = download.getDlg(frame);
+ dlg.setVisible(true);
+ dlg.dispose();
+ download.setCancel(true);
+ }
+
+ public JDialog getDlg(JFrame frame) {
+ String title = "Downloading";
+ if (offlineMode) {
+ title += " (using local card db)";
+ }
+ final JDialog dlg = this.dlg.createDialog(frame, title);
+ close.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ dlg.setVisible(false);
+ }
+ });
+ return dlg;
+ }
+
+ public void setCancel(boolean cancel) {
+ this.cancel = cancel;
+ }
+
+ public DownloadPictures(ArrayList cards) {
+ this.cards = cards;
+
+ this.cardsInGame = new ArrayList();
+ for (CardUrl url : cards) {
+ if (url.isExistsInTheGame())
+ cardsInGame.add(url);
+ }
+
+ addr = new JTextField("Proxy Address");
+ port = new JTextField("Proxy Port");
+ bar = new JProgressBar(this);
+
+ JPanel p0 = new JPanel();
+ p0.setLayout(new BoxLayout(p0, BoxLayout.Y_AXIS));
+
+ // Proxy Choice
+ ButtonGroup bg = new ButtonGroup();
+ String[] labels = { "No Proxy", "HTTP Proxy", "SOCKS Proxy" };
+ for (int i = 0; i < types.length; i++) {
+ JRadioButton rb = new JRadioButton(labels[i]);
+ rb.addChangeListener(new ProxyHandler(i));
+ bg.add(rb);
+ p0.add(rb);
+ if (i == 0)
+ rb.setSelected(true);
+ }
+
+ // Proxy config
+ p0.add(addr);
+ p0.add(port);
+
+ p0.add(Box.createVerticalStrut(5));
+ jLabel1 = new JLabel();
+ jLabel1.setText("Please select server:");
+
+ jLabel1.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+ p0.add(jLabel1);
+ p0.add(Box.createVerticalStrut(5));
+ ComboBoxModel jComboBox1Model = new DefaultComboBoxModel(new String[] { "magiccards.info" });
+ jComboBox1 = new JComboBox();
+
+ jComboBox1.setModel(jComboBox1Model);
+ jComboBox1.setAlignmentX(Component.LEFT_ALIGNMENT);
+ p0.add(jComboBox1);
+ p0.add(Box.createVerticalStrut(5));
+
+ // Start
+ final JButton b = new JButton("Start download");
+ b.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ new Thread(DownloadPictures.this).start();
+ b.setEnabled(false);
+ checkBox.setEnabled(false);
+ }
+ });
+ p0.add(Box.createVerticalStrut(5));
+
+ // Progress
+ p0.add(bar);
+ bar.setStringPainted(true);
+ int count = cards.size();
+ float mb = (count * 70.0f) / 1024;
+ bar.setString(String.format(cardIndex == cards.size() ? "%d of %d cards finished! Please close!"
+ : "%d of %d cards finished! Please wait! [%.1f Mb]", 0, cards.size(), mb));
+ Dimension d = bar.getPreferredSize();
+ d.width = 300;
+ bar.setPreferredSize(d);
+
+ p0.add(Box.createVerticalStrut(5));
+ checkBox = new JCheckBox("Download for current game only.");
+ p0.add(checkBox);
+ p0.add(Box.createVerticalStrut(5));
+ checkBox.setEnabled(!offlineMode);
+
+ checkBox.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ if (checkBox.isSelected()) {
+ int count = DownloadPictures.this.cardsInGame.size();
+ float mb = (count * 70.0f) / 1024;
+ bar.setString(String.format(count == 0 ? "No images to download!" : "%d of %d cards finished! Please wait! [%.1f Mb]",
+ 0, DownloadPictures.this.cardsInGame.size(), mb));
+ } else {
+ int count = DownloadPictures.this.cards.size();
+ float mb = (count * 70.0f) / 1024;
+ bar.setString(String.format(cardIndex == count ? "%d of %d cards finished! Please close!"
+ : "%d of %d cards finished! Please wait! [%.1f Mb]", 0, count, mb));
+ }
+ }
+ });
+
+ // JOptionPane
+ Object[] options = { b, close = new JButton("Cancel") };
+ dlg = new JOptionPane(p0, JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[1]);
+ }
+
+ private static ArrayList getNeededCards(Set allCards) {
+
+ ArrayList cardsToDownload = new ArrayList();
+
+ /**
+ * read all card names and urls
+ */
+ ArrayList allcards = new ArrayList();
+
+ try {
+ offlineMode = true;
+
+ for (Card card : allCards) {
+ if (card.getCardNumber() > 0 && !card.getExpansionSetCode().isEmpty()) {
+ CardUrl url = new CardUrl(card.getName(), card.getExpansionSetCode(), card.getCardNumber(), false);
+ allcards.add(url);
+ } else {
+ if (card.getCardNumber() < 1) {
+ System.err.println("There was a critical error!");
+ log.error("Card has no collector ID and won't be sent to client: " + card);
+ } else if (card.getExpansionSetCode().isEmpty()) {
+ System.err.println("There was a critical error!");
+ log.error("Card has no set name and won't be sent to client:" + card);
+ }
+ }
+ }
+ } catch (Exception e) {
+ log.error(e);
+ }
+
+ File file;
+
+ /**
+ * check to see which cards we already have
+ */
+ for (CardUrl card : allcards) {
+ boolean withCollectorId = false;
+ if (card.name.equals("Forest") || card.name.equals("Mountain") || card.name.equals("Swamp") || card.name.equals("Island")
+ || card.name.equals("Plains")) {
+ withCollectorId = true;
+ }
+ file = new File(CardImageUtils.getImagePath(card, withCollectorId));
+ if (!file.exists()) {
+ cardsToDownload.add(card);
+ }
+ }
+
+ for (CardUrl card : cardsToDownload) {
+ if (card.token) {
+ log.info("Card to download: " + card.name + " (Token) " + card.url);
+ } else {
+ try {
+ log.info("Card to download: " + card.name + " (" + card.set + ") "
+ + CardImageUtils.generateURL(card.collector, card.set));
+ } catch (Exception e) {
+ log.error(e);
+ }
+ }
+ }
+
+ return cardsToDownload;
+ }
+
+ private class ProxyHandler implements ChangeListener {
+ private int type;
+
+ public ProxyHandler(int type) {
+ this.type = type;
+ }
+
+ public void stateChanged(ChangeEvent e) {
+ if (((AbstractButton) e.getSource()).isSelected()) {
+ DownloadPictures.this.type = type;
+ addr.setEnabled(type != 0);
+ port.setEnabled(type != 0);
+ }
+ }
+ }
+
+ public void run() {
+ BufferedInputStream in;
+ BufferedOutputStream out;
+
+ File base = new File(Constants.IO.imageBaseDir);
+ if (!base.exists()) {
+ base.mkdir();
+ }
+
+ Proxy p = null;
+ if (type == 0)
+ p = Proxy.NO_PROXY;
+ else
+ try {
+ p = new Proxy(types[type], new InetSocketAddress(addr.getText(), Integer.parseInt(port.getText())));
+ } catch (Exception ex) {
+ throw new RuntimeException("Gui_DownloadPictures : error 1 - " + ex);
+ }
+
+ if (p != null) {
+ byte[] buf = new byte[1024];
+ int len;
+ HashSet ignoreUrls = SettingsManager.getIntance().getIgnoreUrls();
+
+ for (update(0); (checkBox.isSelected() ? cardIndex < cardsInGame.size() : cardIndex < cards.size()) && !cancel; update(cardIndex + 1)) {
+ try {
+
+ CardUrl card = checkBox.isSelected() ? cardsInGame.get(cardIndex) : cards.get(cardIndex);
+
+ log.info("Downloading card: " + card.name + " (" + card.set + ")");
+
+ URL url = new URL(CardImageUtils.generateURL(card.collector, card.set));
+ if (ignoreUrls.contains(card.set) || card.token) {
+ // we have card in scripts, but we should ignore
+ // downloading image for it
+ // (e.g. for cards from custom or not released yet sets
+ // such urls should come from card-pictures files
+ // instead
+ if (card.collector != 0) {
+ continue;
+ }
+ url = new URL(card.url);
+ }
+ in = new BufferedInputStream(url.openConnection(p).getInputStream());
+
+ createDirForCard(card);
+
+ boolean withCollectorId = false;
+ if (card.name.equals("Forest") || card.name.equals("Mountain") || card.name.equals("Swamp")
+ || card.name.equals("Island") || card.name.equals("Plains")) {
+ withCollectorId = true;
+ }
+ File fileOut = new File(CardImageUtils.getImagePath(card, withCollectorId));
+
+ out = new BufferedOutputStream(new FileOutputStream(fileOut));
+
+ while ((len = in.read(buf)) != -1) {
+ // user cancelled
+ if (cancel) {
+ in.close();
+ out.flush();
+ out.close();
+
+ // delete what was written so far
+ fileOut.delete();
+
+ return;
+ }
+
+ out.write(buf, 0, len);
+ }
+
+ in.close();
+ out.flush();
+ out.close();
+ } catch (Exception ex) {
+ log.error(ex, ex);
+ /*
+ * int more = JOptionPane.showConfirmDialog(null,
+ * "Some error occured. Continue downloading pictures?",
+ * "Error", JOptionPane.YES_NO_OPTION); if (more ==
+ * JOptionPane.NO_OPTION) { break; }
+ */
+ }
+ }
+ }
+ close.setText("Close");
+ }
+
+ private static File createDirForCard(CardUrl card) throws Exception {
+ File setDir = new File(CardImageUtils.getImageDir(card));
+ if (!setDir.exists()) {
+ setDir.mkdirs();
+ }
+ return setDir;
+ }
+
+ private void update(int card) {
+ this.cardIndex = card;
+ final class Worker implements Runnable {
+ private int card;
+
+ Worker(int card) {
+ this.card = card;
+ }
+
+ public void run() {
+ fireStateChanged();
+ if (checkBox.isSelected()) {
+ int count = DownloadPictures.this.cardsInGame.size();
+ int countLeft = count - card;
+ float mb = (countLeft * 70.0f) / 1024;
+ bar.setString(String.format(this.card == count ? "%d of %d cards finished! Please close!"
+ : "%d of %d cards finished! Please wait! [%.1f Mb]", this.card, count, mb));
+ } else {
+ int count = DownloadPictures.this.cards.size();
+ int countLeft = count - card;
+ float mb = (countLeft * 70.0f) / 1024;
+ bar.setString(String.format(cardIndex == count ? "%d of %d cards finished! Please close!"
+ : "%d of %d cards finished! Please wait! [%.1f Mb]", this.card, count, mb));
+ }
+ }
+ }
+
+ EventQueue.invokeLater(new Worker(card));
+ }
+
+ private static final Logger log = Logger.getLogger(DownloadPictures.class);
+
+ private static final long serialVersionUID = 1L;
+}
\ No newline at end of file
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/images/ImageCache.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/images/ImageCache.java
new file mode 100644
index 00000000000..53217e2c2f5
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/images/ImageCache.java
@@ -0,0 +1,197 @@
+package org.mage.plugins.card.images;
+
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.imageio.ImageIO;
+
+import mage.view.CardView;
+
+import org.apache.log4j.Logger;
+import org.mage.plugins.card.utils.CardImageUtils;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ComputationException;
+import com.google.common.collect.MapMaker;
+import com.mortennobel.imagescaling.ResampleOp;
+
+/**
+ * This class stores ALL card images in a cache with soft values. this means
+ * that the images may be collected when they are not needed any more, but will
+ * be kept as long as possible.
+ *
+ * Key format: "###"
+ *
+ * where param is:
+ *
+ *
+ * - #Normal: request for unrotated image
+ * - #Tapped: request for rotated image
+ * - #Cropped: request for cropped image that is used for Shandalar like card
+ * look
+ *
+ */
+public class ImageCache {
+
+ private static final Logger log = Logger.getLogger(ImageCache.class);
+
+ private static final Map imageCache;
+
+ /**
+ * Common pattern for keys.
+ * Format: "##"
+ */
+ private static final Pattern KEY_PATTERN = Pattern.compile("(.*)#(.*)#(.*)");
+
+ static {
+ imageCache = new MapMaker().softValues().makeComputingMap(new Function() {
+ public BufferedImage apply(String key) {
+ try {
+ Matcher m = KEY_PATTERN.matcher(key);
+
+ if (m.matches()) {
+ String name = m.group(1);
+ String set = m.group(2);
+ Integer collectorId = Integer.parseInt(m.group(3));
+
+ CardInfo info = new CardInfo(name, set, collectorId);
+
+ if (collectorId == 0) info.isToken = true;
+ String path = CardImageUtils.getImagePath(info);
+ if (path == null) return null;
+ File file = new File(path);
+
+ BufferedImage image = loadImage(file);
+ return image;
+ } else {
+ throw new RuntimeException(
+ "Requested image doesn't fit the requirement for key (##): " + key);
+ }
+ } catch (Exception ex) {
+ if (ex instanceof ComputationException)
+ throw (ComputationException) ex;
+ else
+ throw new ComputationException(ex);
+ }
+ }
+ });
+ }
+
+ public static BufferedImage getImageOriginal(CardView card) {
+ String key = getKey(card);
+ log.debug("#key: " + key);
+ return getImage(key);
+ }
+
+ /**
+ * Returns the Image corresponding to the key
+ */
+ private static BufferedImage getImage(String key) {
+ try {
+ BufferedImage image = imageCache.get(key);
+ return image;
+ } catch (NullPointerException ex) {
+ // unfortunately NullOutputException, thrown when apply() returns
+ // null, is not public
+ // NullOutputException is a subclass of NullPointerException
+ // legitimate, happens when a card has no image
+ return null;
+ } catch (ComputationException ex) {
+ if (ex.getCause() instanceof NullPointerException)
+ return null;
+ log.error(ex,ex);
+ return null;
+ }
+ }
+
+ /**
+ * Returns the map key for a card, without any suffixes for the image size.
+ */
+ private static String getKey(CardView card) {
+ String set = card.getExpansionSetCode();
+ String key = card.getName() + "#" + set + "#" + String.valueOf(card.getCardNumber());
+
+ return key;
+ }
+
+ /**
+ * Load image from file
+ *
+ * @param file
+ * file to load image from
+ * @return {@link BufferedImage}
+ */
+ public static BufferedImage loadImage(File file) {
+ BufferedImage image = null;
+ if (!file.exists()) {
+ return null;
+ }
+ try {
+ image = ImageIO.read(file);
+ } catch (Exception e) {
+ log.error(e, e);
+ }
+
+ return image;
+ }
+
+ /**
+ * Returns an image scaled to the size given
+ */
+ /*private static BufferedImage getNormalSizeImage(BufferedImage original) {
+ int srcWidth = original.getWidth();
+ int srcHeight = original.getHeight();
+
+ int tgtWidth = SettingsManager.getManager().getCardSize().width;
+ int tgtHeight = SettingsManager.getManager().getCardSize().height;
+
+ if (srcWidth == tgtWidth && srcHeight == tgtHeight)
+ return original;
+
+ ResampleOp resampleOp = new ResampleOp(tgtWidth, tgtHeight);
+ BufferedImage image = resampleOp.filter(original, null);
+ return image;
+ }*/
+
+ /**
+ * Returns an image scaled to the size appropriate for the card picture
+ * panel For future use.
+ */
+ private static BufferedImage getFullSizeImage(BufferedImage original, double scale) {
+ if (scale == 1)
+ return original;
+ ResampleOp resampleOp = new ResampleOp((int) (original.getWidth() * scale), (int) (original.getHeight() * scale));
+ BufferedImage image = resampleOp.filter(original, null);
+ return image;
+ }
+
+ /**
+ * Returns an image scaled to the size appropriate for the card picture
+ * panel
+ */
+ private static BufferedImage getResizedImage(BufferedImage original, Rectangle sizeNeed) {
+ ResampleOp resampleOp = new ResampleOp(sizeNeed.width, sizeNeed.height);
+ BufferedImage image = resampleOp.filter(original, null);
+ return image;
+ }
+
+ /**
+ * Returns the image appropriate to display the card in the picture panel
+ */
+ public static BufferedImage getImage(CardView card, int width, int height) {
+ String key = getKey(card);
+ BufferedImage original = getImage(key);
+ if (original == null)
+ return null;
+
+ double scale = Math.min((double) width / original.getWidth(), (double) height / original.getHeight());
+ if (scale > 1)
+ scale = 1;
+
+ return getFullSizeImage(original, scale);
+ }
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/properties/SettingsManager.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/properties/SettingsManager.java
new file mode 100644
index 00000000000..a5d6bf2091b
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/properties/SettingsManager.java
@@ -0,0 +1,81 @@
+package org.mage.plugins.card.properties;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Properties;
+
+import org.mage.plugins.card.constants.Constants;
+
+public class SettingsManager {
+
+ private static SettingsManager settingsManager = null;
+
+ public static SettingsManager getIntance() {
+ if (settingsManager == null) {
+ synchronized (SettingsManager.class) {
+ if (settingsManager == null) settingsManager = new SettingsManager();
+ }
+ }
+ return settingsManager;
+ }
+
+ private SettingsManager() {
+ loadImageProperties();
+ }
+
+ public void reloadImageProperties() {
+ loadImageProperties();
+ }
+
+ private void loadImageProperties() {
+ imageUrlProperties = new Properties();
+ try {
+ InputStream is = SettingsManager.class.getClassLoader().getResourceAsStream(Constants.IO.IMAGE_PROPERTIES_FILE);
+ if (is == null)
+ throw new RuntimeException("Couldn't load " + Constants.IO.IMAGE_PROPERTIES_FILE);
+ imageUrlProperties.load(is);
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ }
+ }
+
+ public String getSetNameReplacement(String setName) {
+ String result = setName;
+ if (imageUrlProperties != null) {
+ result = imageUrlProperties.getProperty(setName, setName);
+ }
+ return result;
+ }
+
+ public HashSet getIgnoreUrls() {
+ HashSet ignoreUrls = new HashSet();
+ if (imageUrlProperties != null) {
+ String result = imageUrlProperties.getProperty("ignore.urls");
+ if (result != null) {
+ String[] ignore = result.split(",");
+ for (String i : ignore) {
+ ignoreUrls.add(i);
+ }
+ }
+ }
+ return ignoreUrls;
+ }
+
+ public ArrayList getTokenLookupOrder() {
+ ArrayList order = new ArrayList();
+ if (imageUrlProperties != null) {
+ String result = imageUrlProperties.getProperty("token.lookup.order");
+ if (result != null) {
+ String[] sets = result.split(",");
+ for (String s : sets) {
+ order.add(s);
+ }
+ }
+ }
+ return order;
+ }
+
+ private Properties imageUrlProperties;
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java
new file mode 100644
index 00000000000..55aea6d3997
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java
@@ -0,0 +1,174 @@
+package org.mage.plugins.card.utils;
+
+import java.io.File;
+import java.util.HashMap;
+
+import mage.cards.Card;
+import mage.game.permanent.PermanentToken;
+
+import org.mage.plugins.card.CardUrl;
+import org.mage.plugins.card.constants.Constants;
+import org.mage.plugins.card.images.CardInfo;
+import org.mage.plugins.card.properties.SettingsManager;
+
+public class CardImageUtils {
+
+ private static HashMap pathCache = new HashMap();
+
+ /**
+ * Get path to image for specific card.
+ *
+ * @param c
+ * card to get path for
+ * @return String if image exists, else null
+ */
+ public static String getImagePath(CardInfo c) {
+ String filePath;
+ String suffix = ".jpg";
+ String cardname = c.name;
+ String set = c.set;
+
+ CardUrl card = new CardUrl(cardname, set, c.collectorId, c.isToken);
+
+ File file = null;
+ if (c.isToken) {
+ if (pathCache.containsKey(card)) {
+ return pathCache.get(card);
+ }
+ filePath = getTokenImagePath(card);
+ file = new File(filePath);
+
+ if (!file.exists()) {
+ filePath = searchForCardImage(card);
+ file = new File(filePath);
+ }
+
+ if (file.exists()) {
+ pathCache.put(card, filePath);
+ }
+ } else {
+ filePath = getImagePath(card, false);
+ file = new File(filePath);
+
+ if (!file.exists()) {
+ filePath = getImagePath(card, true);
+ file = new File(filePath);
+ }
+ }
+
+ /**
+ * try current directory
+ */
+ if (file == null || !file.exists()) {
+ filePath = cleanString(c.name) + suffix;
+ file = new File(filePath);
+ }
+
+ if (file.exists()) {
+ return filePath;
+ } else {
+ return null;
+ }
+ }
+
+ private static boolean isToken(Card c) {
+ return c != null && c instanceof PermanentToken;
+ }
+
+ private static String getTokenImagePath(CardUrl card) {
+ String filename = getImagePath(card, false);
+ CardUrl c = new CardUrl(card.name, card.set, 0, card.token);
+
+ File file = new File(filename);
+ if (!file.exists()) {
+ c.name = card.name + " 1";
+ filename = getImagePath(c, false);
+ file = new File(filename);
+ if (!file.exists()) {
+ c.name = card.name + " 2";
+ filename = getImagePath(c, false);
+ file = new File(filename);
+ }
+ }
+
+ return filename;
+ }
+
+ private static String searchForCardImage(CardUrl card) {
+ File file = null;
+ String path = "";
+ CardUrl c = new CardUrl(card.name, card.set, 0, card.token);
+ boolean found = false; // search only in older sets
+ for (String set : SettingsManager.getIntance().getTokenLookupOrder()) {
+ if (found) { // start looking for image only if we have found card.set in the list (as this list is ordered)
+ c.set = set;
+ path = getTokenImagePath(c);
+ file = new File(path);
+ if (file.exists()) {
+ pathCache.put(card, path);
+ return path;
+ }
+ }
+ if (set.equals(card.set)) found = true;
+ }
+ return "";
+ }
+
+ public static String cleanString(String in) {
+ in = in.trim();
+ StringBuffer out = new StringBuffer();
+ char c;
+ for (int i = 0; i < in.length(); i++) {
+ c = in.charAt(i);
+ if (c == ' ' || c == '-')
+ out.append('_');
+ else if (Character.isLetterOrDigit(c)) {
+ out.append(c);
+ }
+ }
+
+ return out.toString().toLowerCase();
+ }
+
+ public static String generateURL(Integer collectorId, String cardSet) throws Exception {
+ if (collectorId == null || cardSet == null) {
+ throw new Exception("Wrong parameters for image: collector id: " + collectorId + ",card set: " + cardSet);
+ }
+ String set = updateSet(cardSet,true);
+ String url = "http://magiccards.info/scans/en/";
+ url += set.toLowerCase() + "/" + collectorId + ".jpg";
+
+ return url;
+ }
+
+ private static String updateSet(String cardSet, boolean forUrl) {
+ String set = cardSet.toLowerCase();
+ if (set.equals("con")) {
+ set = "cfx";
+ }
+ if (forUrl) {
+ set = SettingsManager.getIntance().getSetNameReplacement(set);
+ }
+ return set;
+ }
+
+ public static String getImageDir(CardUrl card) {
+ if (card.set == null) {
+ return "";
+ }
+ String set = updateSet(card.set,false).toUpperCase();
+ if (card.token) {
+ return Constants.IO.imageBaseDir + File.separator + "TOK" + File.separator + set;
+ } else {
+ return Constants.IO.imageBaseDir + set;
+ }
+ }
+
+ public static String getImagePath(CardUrl card, boolean withCollector) {
+ if (withCollector) {
+ return getImageDir(card) + File.separator + card.name + "." + card.collector + ".full.jpg";
+ } else {
+ return getImageDir(card) + File.separator + card.name + ".full.jpg";
+ }
+ }
+}
diff --git a/Mage.Plugins/Mage.Card.Plugin/src/main/resources/image.url.properties b/Mage.Plugins/Mage.Card.Plugin/src/main/resources/image.url.properties
new file mode 100644
index 00000000000..6f4bbe654fb
--- /dev/null
+++ b/Mage.Plugins/Mage.Card.Plugin/src/main/resources/image.url.properties
@@ -0,0 +1,59 @@
+tsp=ts
+tor=tr
+mor=mt
+ody=od
+lrw=lw
+plc=pc
+gpt=gp
+inv=in
+ons=on
+scg=sc
+jud=ju
+mmq=mm
+pls=ps
+mrd=mi
+mir=mr
+tst=ts
+usg=us
+apc=ap
+nms=ne
+dis=di
+vis=vi
+9ed=9e
+8ed=8e
+7ed=7e
+4ed=4e
+tsb=tsts
+ulg=ul
+5ed=5e
+6ed=6e
+btd=bd
+sth=sh
+nem=ne
+por=po
+s99=st
+lgn=le
+ice=ia
+csp=cs
+tmp=tp
+s00=st2k
+dst=ds
+pcy=pr
+uds=ud
+exo=ex
+lea=al
+hop=pch
+chr=ch
+arn=an
+wth=wl
+leb=be
+2ed=un
+3ed=rv
+brb=br
+atq=aq
+fem=fe
+leg=lg
+ptk=p3k
+ignore.urls=TOK
+# sets ordered by release time (newest goes first)
+token.lookup.order=ROE,PVC,WWK,ZEN,M10,GVL,ARB,DVD,CFX,JVC,ALA,EVE,SHM,EVG,MOR,LRW,10E,CLS
\ No newline at end of file