1
0
Fork 0
mirror of https://github.com/correl/mage.git synced 2025-04-04 01:06:04 -09:00

fix conflicts

This commit is contained in:
Ingmar Goudt 2019-12-29 19:28:20 +01:00
commit ce23f6900d
2451 changed files with 84128 additions and 14873 deletions
.gitignore
Mage.Client
Mage.Common
Mage.Plugins
Mage.Counter.Plugin
pom.xml
Mage.Server.Console
pom.xml
src/main/java/mage/server/console
Mage.Server.Plugins/Mage.Deck.Constructed

5
.gitignore vendored
View file

@ -48,6 +48,8 @@ Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/target/
Mage.Server.Plugins/Mage.Game.FreeForAll/target Mage.Server.Plugins/Mage.Game.FreeForAll/target
Mage.Server.Plugins/Mage.Game.MomirDuel/target Mage.Server.Plugins/Mage.Game.MomirDuel/target
Mage.Server.Plugins/Mage.Game.MomirGame/target/ Mage.Server.Plugins/Mage.Game.MomirGame/target/
Mage.Server.Plugins/Mage.Game.OathbreakerDuel/target/
Mage.Server.Plugins/Mage.Game.OathbreakerFreeForAll/target/
Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/target Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/target
Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/target/ Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/target/
Mage.Server.Plugins/Mage.Game.FreeformCommanderFreeForAll/target/ Mage.Server.Plugins/Mage.Game.FreeformCommanderFreeForAll/target/
@ -150,3 +152,6 @@ mage-bundle
# build-tools config and log files when building client/server with Atom # build-tools config and log files when building client/server with Atom
.build-tools.cson .build-tools.cson
build-output.log build-output.log
# Visual Studio Code
.history

View file

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-root</artifactId> <artifactId>mage-root</artifactId>
<version>1.4.35</version> <version>1.4.41</version>
</parent> </parent>
<artifactId>mage-client</artifactId> <artifactId>mage-client</artifactId>

View file

@ -0,0 +1,88 @@
1 [C19:207] Vraska the Unseen
1 [C19:48] Rayami, First of the Fallen
1 [C19:51] Volrath, the Shapestealer
1 [C19:8] Kadena's Silencer
1 [C19:12] Thought Sponge
1 [C19:21] Thieving Amalgam
1 [C19:31] Apex Altisaur
1 [C19:44] Grismold, the Dreadsower
1 [C19:160] Deathmist Raptor
1 [C19:172] Hooded Hydra
1 [C19:81] Chromeshell Crab
1 [C19:87] Ixidron
1 [C19:89] Kheru Spellsnatcher
1 [C19:96] Stratus Dancer
1 [C19:100] Thousand Winds
1 [C19:101] Vesuvan Shapeshifter
1 [C19:104] Bane of the Living
1 [C19:118] Grim Haruspex
1 [C19:128] Silumgar Assassin
1 [C19:161] Den Protector
1 [C19:179] Seedborn Muse
1 [C19:184] Thelonite Hermit
1 [C19:200] Sagu Mauler
1 [C19:36] Voice of Many
1 [C19:57] Scaretiller
1 [C19:102] Willbender
1 [C19:129] Skinthinner
1 [C19:156] Ainok Survivalist
1 [C19:170] Great Oak Guardian
1 [C19:174] Nantuko Vigilante
1 [C19:177] Sakura-Tribe Elder
1 [C19:194] Icefeather Aven
1 [C19:34] Road of Return
1 [C19:115] Ghastly Conscription
1 [C19:120] Hex
1 [C19:175] Overwhelming Stampede
1 [C19:183] Tempt with Discovery
1 [C19:19] Mire in Misery
1 [C19:98] Tezzeret's Gambit
1 [C19:159] Cultivate
1 [C19:164] Explore
1 [C19:165] Farseek
1 [C19:205] Urban Evolution
1 [C19:11] Sudden Substitution
1 [C19:187] Biomass Mutation
1 [C19:9] Leadership Vacuum
1 [C19:84] Echoing Truth
1 [C19:92] Reality Shift
1 [C19:197] Putrefy
1 [C19:202] Sultai Charm
1 [C19:56] Pendant of Prosperity
1 [C19:58] Scroll of Fate
1 [C19:224] Strionic Resonator
1 [C19:221] Sol Ring
1 [C19:225] Thran Dynamo
1 [C19:17] Gift of Doom
1 [C19:186] Trail of Mystery
1 [C19:189] Bounty of the Luxa
1 [C19:201] Secret Plans
1 [C19:238] Darkwater Catacombs
1 [C19:242] Exotic Orchard
1 [C19:258] Llanowar Wastes
1 [C19:273] Shrine of the Forsaken Gods
1 [C19:278] Sunken Hollow
1 [C19:282] Thespian's Stage
1 [C19:287] Yavimaya Coast
5 [C19:291] Island
3 [C19:294] Swamp
7 [C19:300] Forest
1 [C19:227] Ash Barrens
1 [C19:232] Bojuka Bog
1 [C19:237] Command Tower
1 [C19:239] Dimir Aqueduct
1 [C19:241] Evolving Wilds
1 [C19:244] Foul Orchard
1 [C19:247] Golgari Guildgate
1 [C19:248] Golgari Rot Farm
1 [C19:254] Jungle Hollow
1 [C19:261] Myriad Landscape
1 [C19:264] Opulent Palace
1 [C19:268] Reliquary Tower
1 [C19:274] Simic Growth Chamber
1 [C19:275] Simic Guildgate
1 [C19:280] Temple of the False God
1 [C19:281] Terramorphic Expanse
1 [C19:283] Thornwood Falls
1 [C19:286] Woodland Stream
SB: 1 [C19:45] Kadena, Slinking Sorcerer

View file

@ -0,0 +1,82 @@
1 [C19:124] Ob Nixilis Reignited
1 [C19:39] Chainer, Nightmare Adept
1 [C19:43] Greven, Predator Captain
1 [C19:14] Archfiend of Spite
1 [C19:15] Bone Miser
1 [C19:18] K'rrik, Son of Yawgmoth
1 [C19:22] Anje's Ravager
1 [C19:28] Skyfire Phoenix
1 [C19:30] Wildfire Devils
1 [C19:109] Champion of Stray Souls
1 [C19:114] Geth, Lord of the Vault
1 [C19:130] Soul of Innistrad
1 [C19:103] Asylum Visitor
1 [C19:111] Doomed Necromancer
1 [C19:125] Overseer of the Damned
1 [C19:144] Flayer of the Hatebound
1 [C19:149] Magus of the Wheel
1 [C19:152] Squee, Goblin Nabob
1 [C19:153] Stromkirk Occultist
1 [C19:188] Bloodhall Priest
1 [C19:222] Solemn Simulacrum
1 [C19:57] Scaretiller
1 [C19:106] Big Game Hunter
1 [C19:116] Gorgon Recluse
1 [C19:117] Grave Scrabbler
1 [C19:123] Nightshade Assassin
1 [C19:126] Plaguecrafter
1 [C19:127] Sanitarium Skeleton
1 [C19:218] Meteor Golem
1 [C19:20] Nightmare Unmaking
1 [C19:107] Boneyard Parley
1 [C19:105] Beacon of Unrest
1 [C19:113] From Under the Floorboards
1 [C19:121] In Garruk's Wake
1 [C19:134] Avacyn's Judgment
1 [C19:19] Mire in Misery
1 [C19:26] Hate Mirage
1 [C19:108] Call to the Netherworld
1 [C19:122] Murderous Compulsion
1 [C19:133] Alchemist's Greeting
1 [C19:150] Malevolent Whispers
1 [C19:136] Chaos Warp
1 [C19:110] Dark Withering
1 [C19:142] Fiery Temper
1 [C19:154] Violent Eruption
1 [C19:213] Grimoire of the Dead
1 [C19:216] Key to the City
1 [C19:53] Bloodthirsty Blade
1 [C19:52] Aeon Engine
1 [C19:209] Armillary Sphere
1 [C19:214] Hedron Archive
1 [C19:220] Rakdos Locket
1 [C19:221] Sol Ring
1 [C19:16] Curse of Fool's Wisdom
1 [C19:119] Hedonist's Trove
1 [C19:155] Warstorm Surge
1 [C19:112] Faith of the Devoted
1 [C19:131] The Eldest Reborn
1 [C19:132] Zombie Infestation
1 [C19:59] Sanctum of Eternity
1 [C19:240] Drownyard Temple
1 [C19:242] Exotic Orchard
1 [C19:246] Geier Reach Sanitarium
10 [C19:294] Swamp
10 [C19:297] Mountain
1 [C19:226] Akoum Refuge
1 [C19:227] Ash Barrens
1 [C19:229] Barren Moor
1 [C19:230] Bloodfell Caves
1 [C19:235] Cinder Barrens
1 [C19:237] Command Tower
1 [C19:241] Evolving Wilds
1 [C19:243] Forgotten Cave
1 [C19:259] Memorial to Folly
1 [C19:260] Mortuary Mire
1 [C19:261] Myriad Landscape
1 [C19:266] Rakdos Carnarium
1 [C19:267] Rakdos Guildgate
1 [C19:269] Rix Maadi, Dungeon Palace
1 [C19:281] Terramorphic Expanse
1 [C19:280] Temple of the False God
SB: 1 [C19:37] Anje Falkenrath

View file

@ -0,0 +1,82 @@
1 [C19:198] Ral Zarek
1 [C19:40] Elsha of the Infinite
1 [C19:47] Pramikon, Sky Rampart
1 [C19:7] Thalia's Geistcaller
1 [C19:13] Wall of Stolen Identity
1 [C19:23] Backdraft Hellkite
1 [C19:24] Dockside Extortionist
1 [C19:41] Gerrard, Weatherlight Hero
1 [C19:70] Pristine Angel
1 [C19:76] Sun Titan
1 [C19:82] Clever Impersonator
1 [C19:79] Zetalpa, Primal Dawn
1 [C19:93] River Kelpie
1 [C19:97] Talrand, Sky Summoner
1 [C19:196] Pristine Skywise
1 [C19:1] Cliffside Rescuer
1 [C19:57] Scaretiller
1 [C19:145] Guttersnipe
1 [C19:190] Crackling Drake
1 [C19:211] Burnished Hart
1 [C19:5] Sevinne's Reclamation
1 [C19:10] Mass Diminish
1 [C19:27] Ignite the Future
1 [C19:62] Divine Reckoning
1 [C19:63] Dusk // Dawn
1 [C19:66] Increasing Devotion
1 [C19:75] Storm Herd
1 [C19:138] Devil's Play
1 [C19:83] Deep Analysis
1 [C19:90] Mystic Retrieval
1 [C19:94] Runic Repetition
1 [C19:140] Faithless Looting
1 [C19:151] Rolling Temblor
1 [C19:4] Mandate of Peace
1 [C19:147] Increasing Vengeance
1 [C19:148] Magmaquake
1 [C19:199] Refuse // Cooperate
1 [C19:9] Leadership Vacuum
1 [C19:69] Prismatic Strands
1 [C19:71] Purify the Grave
1 [C19:72] Ray of Distortion
1 [C19:80] Chemister's Insight
1 [C19:85] Fact or Fiction
1 [C19:86] Fervent Denial
1 [C19:91] Oona's Grace
1 [C19:99] Think Twice
1 [C19:137] Desperate Ravings
1 [C19:192] Farm // Market
1 [C19:54] Empowered Autogenerator
1 [C19:53] Bloodthirsty Blade
1 [C19:209] Armillary Sphere
1 [C19:210] Azorius Locket
1 [C19:212] Commander's Sphere
1 [C19:215] Izzet Locket
1 [C19:221] Sol Ring
1 [C19:88] Jace's Sanctum
1 [C19:64] Ghostly Prison
1 [C19:95] Secrets of the Dead
1 [C19:135] Burning Vengeance
1 [C19:242] Exotic Orchard
1 [C19:265] Prairie Stream
9 [C19:288] Plains
8 [C19:291] Island
4 [C19:297] Mountain
1 [C19:227] Ash Barrens
1 [C19:228] Azorius Chancery
1 [C19:233] Boros Garrison
1 [C19:234] Boros Guildgate
1 [C19:237] Command Tower
1 [C19:241] Evolving Wilds
1 [C19:251] Highland Lake
1 [C19:252] Izzet Boilerworks
1 [C19:253] Izzet Guildgate
1 [C19:261] Myriad Landscape
1 [C19:262] Mystic Monastery
1 [C19:276] Stone Quarry
1 [C19:279] Swiftwater Cliffs
1 [C19:280] Temple of the False God
1 [C19:281] Terramorphic Expanse
1 [C19:284] Tranquil Cove
1 [C19:285] Wind-Scarred Crag
SB: 1 [C19:49] Sevinne, the Chronoclasm

View file

@ -0,0 +1,84 @@
1 [C19:167] Garruk, Primal Hunter
1 [C19:38] Atla Palani, Nest Tender
1 [C19:46] Marisi, Breaker of the Coil
1 [C19:3] Doomed Artisan
1 [C19:29] Tectonic Hellion
1 [C19:33] Ohran Frostfang
1 [C19:35] Selesnya Eulogist
1 [C19:50] Tahngarth, First Mate
1 [C19:61] Angel of Sanctions
1 [C19:78] Wingmate Roc
1 [C19:139] Dragonmaster Outcast
1 [C19:141] Feldon of the Third Path
1 [C19:169] Giant Adephage
1 [C19:182] Soul of Zendikar
1 [C19:204] Trostani, Selesnya's Voice
1 [C19:60] Desolation Twin
1 [C19:143] Flamerush Rider
1 [C19:146] Heart-Piercer Manticore
1 [C19:176] Rampaging Baloths
1 [C19:185] Thragtusk
1 [C19:191] Emmara Tandris
1 [C19:208] Wayfaring Temple
1 [C19:1] Cliffside Rescuer
1 [C19:36] Voice of Many
1 [C19:57] Scaretiller
1 [C19:73] Roc Egg
1 [C19:168] Garruk's Packleader
1 [C19:177] Sakura-Tribe Elder
1 [C19:206] Vitu-Ghazi Guildmage
1 [C19:25] Ghired's Belligerence
1 [C19:32] Full Flowering
1 [C19:65] Hour of Reckoning
1 [C19:68] Phyrexian Rebirth
1 [C19:180] Shamanic Revelation
1 [C19:26] Hate Mirage
1 [C19:159] Cultivate
1 [C19:164] Explore
1 [C19:165] Farseek
1 [C19:171] Harmonize
1 [C19:166] Fresh Meat
1 [C19:173] Momentous Fall
1 [C19:178] Second Harvest
1 [C19:74] Rootborn Defenses
1 [C19:77] Trostani's Judgment
1 [C19:157] Beast Within
1 [C19:162] Druid's Deliverance
1 [C19:181] Slice in Twain
1 [C19:195] Naya Charm
1 [C19:203] Sundering Growth
1 [C19:55] Idol of Oblivion
1 [C19:219] Mimic Vat
1 [C19:223] Soul Foundry
1 [C19:217] Lightning Greaves
1 [C19:221] Sol Ring
1 [C19:2] Commander's Insignia
1 [C19:6] Song of the Worldsoul
1 [C19:193] Growing Ranks
1 [C19:67] Intangible Virtue
1 [C19:158] Colossal Majesty
1 [C19:163] Elemental Bond
1 [C19:236] Cinder Glade
1 [C19:242] Exotic Orchard
1 [C19:245] Gargoyle Castle
1 [C19:277] Sungrass Prairie
7 [C19:288] Plains
4 [C19:297] Mountain
8 [C19:300] Forest
1 [C19:227] Ash Barrens
1 [C19:231] Blossoming Sands
1 [C19:233] Boros Garrison
1 [C19:237] Command Tower
1 [C19:241] Evolving Wilds
1 [C19:249] Graypelt Refuge
1 [C19:250] Gruul Turf
1 [C19:255] Jungle Shrine
1 [C19:256] Kazandu Refuge
1 [C19:257] Krosan Verge
1 [C19:261] Myriad Landscape
1 [C19:263] Naya Panorama
1 [C19:270] Rogue's Passage
1 [C19:271] Rugged Highlands
1 [C19:272] Selesnya Sanctuary
1 [C19:281] Terramorphic Expanse
SB: 1 [C19:42] Ghired, Conclave Exile

View file

@ -988,6 +988,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
btnDebug.setFocusable(false); btnDebug.setFocusable(false);
btnDebug.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); btnDebug.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
btnDebug.addMouseListener(new java.awt.event.MouseAdapter() { btnDebug.addMouseListener(new java.awt.event.MouseAdapter() {
@Override
public void mouseClicked(java.awt.event.MouseEvent evt) { public void mouseClicked(java.awt.event.MouseEvent evt) {
btnDebugMouseClicked(evt); btnDebugMouseClicked(evt);
} }

View file

@ -517,7 +517,7 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis
} }
@Override @Override
public void setSelected(boolean selected) { public void setSelected(boolean isSelected) {
} }
@Override @Override

View file

@ -952,13 +952,16 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
searchByTextField = new JTextField(); searchByTextField = new JTextField();
searchByTextField.setToolTipText("Searches for card names, types, rarity, casting cost and rules text. NB: Mana symbols are written like {W},{U},{C} etc"); searchByTextField.setToolTipText("Searches for card names, types, rarity, casting cost and rules text. NB: Mana symbols are written like {W},{U},{C} etc");
searchByTextField.addKeyListener(new KeyAdapter() { searchByTextField.addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) { public void keyReleased(KeyEvent e) {
reselectBy(); reselectBy();
} }
@Override
public void keyTyped(KeyEvent e) { public void keyTyped(KeyEvent e) {
} }
@Override
public void keyPressed(KeyEvent e) { public void keyPressed(KeyEvent e) {
} }
}); });

View file

@ -9,6 +9,7 @@ import java.awt.Rectangle;
import java.awt.Stroke; import java.awt.Stroke;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -16,12 +17,12 @@ import javax.swing.JComponent;
public class ManaBarChart extends JComponent { public class ManaBarChart extends JComponent {
HashMap<String, Integer> pips_at_cmcs = new HashMap<String, Integer>(); Map<String, Integer> pips_at_cmcs = new HashMap<String, Integer>();
ManaBarChart() { ManaBarChart() {
} }
ManaBarChart(HashMap<String, Integer> pips_at_cmcs) { ManaBarChart(Map<String, Integer> pips_at_cmcs) {
this.pips_at_cmcs = pips_at_cmcs; this.pips_at_cmcs = pips_at_cmcs;
} }
@ -35,6 +36,7 @@ public class ManaBarChart extends JComponent {
return preferred; return preferred;
} }
@Override
public void paint(Graphics g) { public void paint(Graphics g) {
drawBar((Graphics2D) g, getBounds()); drawBar((Graphics2D) g, getBounds());
} }

View file

@ -60,6 +60,7 @@ public class ManaPieChart extends JComponent {
return preferred; return preferred;
} }
@Override
public void paint(Graphics g) { public void paint(Graphics g) {
drawPie((Graphics2D) g, getBounds(), slices.toArray(new Slice[slices.size()])); drawPie((Graphics2D) g, getBounds(), slices.toArray(new Slice[slices.size()]));
} }

View file

@ -374,6 +374,7 @@ public class ChatPanelBasic extends javax.swing.JPanel {
txtMessage.setName(""); // NOI18N txtMessage.setName(""); // NOI18N
txtMessage.setPreferredSize(new java.awt.Dimension(6, 70)); txtMessage.setPreferredSize(new java.awt.Dimension(6, 70));
txtMessage.addKeyListener(new java.awt.event.KeyAdapter() { txtMessage.addKeyListener(new java.awt.event.KeyAdapter() {
@Override
public void keyTyped(java.awt.event.KeyEvent evt) { public void keyTyped(java.awt.event.KeyEvent evt) {
txtMessageKeyTyped(evt); txtMessageKeyTyped(evt);
} }

View file

@ -20,39 +20,48 @@ class TranslucentSynthSytle extends SynthStyle {
style = s; style = s;
} }
@Override
public Object get(SynthContext context, Object key) { public Object get(SynthContext context, Object key) {
return style.get(context, key); return style.get(context, key);
} }
@Override
public boolean getBoolean(SynthContext context, Object key, public boolean getBoolean(SynthContext context, Object key,
boolean defaultValue) { boolean defaultValue) {
return style.getBoolean(context, key, defaultValue); return style.getBoolean(context, key, defaultValue);
} }
@Override
public Color getColor(SynthContext context, ColorType type) { public Color getColor(SynthContext context, ColorType type) {
return style.getColor(context, type); return style.getColor(context, type);
} }
@Override
public Font getFont(SynthContext context) { public Font getFont(SynthContext context) {
return style.getFont(context); return style.getFont(context);
} }
@Override
public SynthGraphicsUtils getGraphicsUtils(SynthContext context) { public SynthGraphicsUtils getGraphicsUtils(SynthContext context) {
return style.getGraphicsUtils(context); return style.getGraphicsUtils(context);
} }
@Override
public Icon getIcon(SynthContext context, Object key) { public Icon getIcon(SynthContext context, Object key) {
return style.getIcon(context, key); return style.getIcon(context, key);
} }
@Override
public Insets getInsets(SynthContext context, Insets insets) { public Insets getInsets(SynthContext context, Insets insets) {
return style.getInsets(context, insets); return style.getInsets(context, insets);
} }
@Override
public int getInt(SynthContext context, Object key, int defaultValue) { public int getInt(SynthContext context, Object key, int defaultValue) {
return style.getInt(context, key, defaultValue); return style.getInt(context, key, defaultValue);
} }
@Override
public SynthPainter getPainter(final SynthContext context) { public SynthPainter getPainter(final SynthContext context) {
return new SynthPainter() { return new SynthPainter() {
public void paintInternalFrameBackground(SynthContext context, public void paintInternalFrameBackground(SynthContext context,
@ -63,19 +72,23 @@ class TranslucentSynthSytle extends SynthStyle {
}; };
} }
@Override
public String getString(SynthContext context, Object key, public String getString(SynthContext context, Object key,
String defaultValue) { String defaultValue) {
return style.getString(context, key, defaultValue); return style.getString(context, key, defaultValue);
} }
@Override
public void installDefaults(SynthContext context) { public void installDefaults(SynthContext context) {
style.installDefaults(context); style.installDefaults(context);
} }
@Override
public void uninstallDefaults(SynthContext context) { public void uninstallDefaults(SynthContext context) {
style.uninstallDefaults(context); style.uninstallDefaults(context);
} }
@Override
public boolean isOpaque(SynthContext context) { public boolean isOpaque(SynthContext context) {
if (context.getRegion() == Region.INTERNAL_FRAME) { if (context.getRegion() == Region.INTERNAL_FRAME) {
return false; return false;

View file

@ -60,6 +60,8 @@ public class ShadowLabel extends JLabel {
this.invertColors = invertColors; this.invertColors = invertColors;
} }
@Override
public void setText(String text) { public void setText(String text) {
this.text = text; this.text = text;
repaint(); repaint();

View file

@ -1415,14 +1415,15 @@ class ImportFilter extends FileFilter {
|| ext.equalsIgnoreCase("dek") || ext.equalsIgnoreCase("dek")
|| ext.equalsIgnoreCase("cod") || ext.equalsIgnoreCase("cod")
|| ext.equalsIgnoreCase("o8d") || ext.equalsIgnoreCase("o8d")
|| ext.equalsIgnoreCase("draft"); || ext.equalsIgnoreCase("draft")
|| ext.equalsIgnoreCase("mtga");
} }
return false; return false;
} }
@Override @Override
public String getDescription() { public String getDescription() {
return "All formats (*.dec; *.mwDeck; *.txt; *.dek; *.cod; *.o8d; *.draft)"; return "All formats (*.dec; *.mwDeck; *.txt; *.dek; *.cod; *.o8d; *.draft; *.mtga)";
} }
} }

View file

@ -352,7 +352,7 @@ public class MageBook extends JComponent {
List<Plane> planes = getPlanes(currentPage, currentSet, numTokensEmblems); List<Plane> planes = getPlanes(currentPage, currentSet, numTokensEmblems);
int numPlanes = 0; int numPlanes = 0;
if (planes != null && planes.size() > 0) { if (!planes.isEmpty()) {
int size = planes.size(); int size = planes.size();
numPlanes = size; numPlanes = size;
Rectangle rectangle = new Rectangle(); Rectangle rectangle = new Rectangle();
@ -523,7 +523,7 @@ public class MageBook extends JComponent {
// second run for empty numbers // second run for empty numbers
int countHave = haveNumbers.size(); int countHave = haveNumbers.size();
int countNotHave = 0; int countNotHave = 0;
if (cards.size() > 0) { if (!cards.isEmpty()) {
for (int i = startNumber; i <= endNumber; i++) { for (int i = startNumber; i <= endNumber; i++) {
if (!haveNumbers.contains(i)) { if (!haveNumbers.contains(i)) {
countNotHave++; countNotHave++;
@ -593,8 +593,8 @@ public class MageBook extends JComponent {
} }
private List<Emblem> getEmblems(int page, String set, int numTokensEmblems) { private List<Emblem> getEmblems(int page, String set, int numTokensEmblems) {
ArrayList<CardDownloadData> allEmblems = getTokenCardUrls(); List<CardDownloadData> allEmblems = getTokenCardUrls();
ArrayList<Emblem> emblems = new ArrayList<>(); List<Emblem> emblems = new ArrayList<>();
for (CardDownloadData emblem : allEmblems) { for (CardDownloadData emblem : allEmblems) {
if (emblem.getSet().equals(set)) { if (emblem.getSet().equals(set)) {
@ -650,8 +650,8 @@ public class MageBook extends JComponent {
} }
private List<Plane> getPlanes(int page, String set, int numTokensEmblems) { private List<Plane> getPlanes(int page, String set, int numTokensEmblems) {
ArrayList<CardDownloadData> allPlanes = getTokenCardUrls(); List<CardDownloadData> allPlanes = getTokenCardUrls();
ArrayList<Plane> planes = new ArrayList<>(); List<Plane> planes = new ArrayList<>();
for (CardDownloadData plane : allPlanes) { for (CardDownloadData plane : allPlanes) {
if (plane.getSet().equals(set)) { if (plane.getSet().equals(set)) {
@ -695,13 +695,13 @@ public class MageBook extends JComponent {
int totalTokensEmblems = totalTokens + getTotalNumEmblems(set); int totalTokensEmblems = totalTokens + getTotalNumEmblems(set);
int start = 0; int start = 0;
if (!(page * conf.CARDS_PER_PAGE <= totalTokensEmblems && (page + 1) * conf.CARDS_PER_PAGE >= totalTokensEmblems)) { if (!(page * conf.CARDS_PER_PAGE <= totalTokensEmblems && (page + 1) * conf.CARDS_PER_PAGE >= totalTokensEmblems)) {
start = page * conf.CARDS_PER_PAGE - totalTokensEmblems; start = Math.max(0, page * conf.CARDS_PER_PAGE - totalTokensEmblems);
pageRight.setVisible(true); pageRight.setVisible(true);
} }
int end = planes.size(); int end = planes.size();
if ((page + 1) * conf.CARDS_PER_PAGE < totalTokensEmblems + planes.size()) { if ((page + 1) * conf.CARDS_PER_PAGE < totalTokensEmblems + planes.size()) {
end = (page + 1) * conf.CARDS_PER_PAGE - totalTokensEmblems; end = Math.max(0, (page + 1) * conf.CARDS_PER_PAGE - totalTokensEmblems);
pageRight.setVisible(true); pageRight.setVisible(true);
} else { } else {
pageRight.setVisible(false); pageRight.setVisible(false);

View file

@ -37,6 +37,10 @@ public class AddLandDialog extends MageDialog {
this.setModal(true); this.setModal(true);
} }
private boolean setHaveSnowLands(ExpansionInfo exp) {
return CardRepository.instance.haveSnowLands(exp.getCode());
}
public void showDialog(Deck deck, DeckEditorMode mode) { public void showDialog(Deck deck, DeckEditorMode mode) {
this.deck = deck; this.deck = deck;
SortedSet<String> landSetNames = new TreeSet<>(); SortedSet<String> landSetNames = new TreeSet<>();
@ -45,7 +49,7 @@ public class AddLandDialog extends MageDialog {
// decide from which sets basic lands are taken from // decide from which sets basic lands are taken from
for (String setCode : deck.getExpansionSetCodes()) { for (String setCode : deck.getExpansionSetCodes()) {
ExpansionInfo expansionInfo = ExpansionRepository.instance.getSetByCode(setCode); ExpansionInfo expansionInfo = ExpansionRepository.instance.getSetByCode(setCode);
if (expansionInfo != null && expansionInfo.hasBasicLands()) { if (expansionInfo != null && expansionInfo.hasBasicLands() && !setHaveSnowLands(expansionInfo)) {
defaultSetName = expansionInfo.getName(); defaultSetName = expansionInfo.getName();
break; break;
} }
@ -58,7 +62,7 @@ public class AddLandDialog extends MageDialog {
if (expansionInfo != null) { if (expansionInfo != null) {
List<ExpansionInfo> blockSets = ExpansionRepository.instance.getSetsFromBlock(expansionInfo.getBlockName()); List<ExpansionInfo> blockSets = ExpansionRepository.instance.getSetsFromBlock(expansionInfo.getBlockName());
for (ExpansionInfo blockSet : blockSets) { for (ExpansionInfo blockSet : blockSets) {
if (blockSet.hasBasicLands()) { if (blockSet.hasBasicLands() && !setHaveSnowLands(expansionInfo)) {
defaultSetName = expansionInfo.getName(); defaultSetName = expansionInfo.getName();
break; break;
} }
@ -70,6 +74,10 @@ public class AddLandDialog extends MageDialog {
// if still no set with lands found, add list of all available // if still no set with lands found, add list of all available
List<ExpansionInfo> basicLandSets = ExpansionRepository.instance.getSetsWithBasicLandsByReleaseDate(); List<ExpansionInfo> basicLandSets = ExpansionRepository.instance.getSetsWithBasicLandsByReleaseDate();
for (ExpansionInfo expansionInfo : basicLandSets) { for (ExpansionInfo expansionInfo : basicLandSets) {
// snow lands only in free mode
if (mode != DeckEditorMode.FREE_BUILDING && setHaveSnowLands(expansionInfo)) {
continue;
}
landSetNames.add(expansionInfo.getName()); landSetNames.add(expansionInfo.getName());
} }
if (landSetNames.isEmpty()) { if (landSetNames.isEmpty()) {
@ -472,19 +480,32 @@ public class AddLandDialog extends MageDialog {
white += m.getWhite(); white += m.getWhite();
} }
int total = red + green + black + blue + white; int total = red + green + black + blue + white;
int redcards = Math.round(land_number * ((float) red / (float) total));
total -= red; int redcards = 0;
land_number -= redcards; int greencards = 0;
int greencards = Math.round(land_number * ((float) green / (float) total)); int blackcards = 0;
total -= green; int bluecards = 0;
land_number -= greencards; int whitecards = 0;
int blackcards = Math.round(land_number * ((float) black / (float) total)); if (total > 0) {
total -= black; redcards = Math.round(land_number * ((float) red / (float) total));
land_number -= blackcards; total -= red;
int bluecards = Math.round(land_number * ((float) blue / (float) total)); land_number -= redcards;
total -= blue;
land_number -= bluecards; greencards = Math.round(land_number * ((float) green / (float) total));
int whitecards = land_number; total -= green;
land_number -= greencards;
blackcards = Math.round(land_number * ((float) black / (float) total));
total -= black;
land_number -= blackcards;
bluecards = Math.round(land_number * ((float) blue / (float) total));
total -= blue;
land_number -= bluecards;
whitecards = land_number;
}
spnMountain.setValue(redcards); spnMountain.setValue(redcards);
spnForest.setValue(greencards); spnForest.setValue(greencards);
spnSwamp.setValue(blackcards); spnSwamp.setValue(blackcards);

View file

@ -422,8 +422,8 @@
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor"> <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/flags/us.png"/> <Image iconType="3" name="/flags/us.png"/>
</Property> </Property>
<Property name="text" type="java.lang.String" value="P"/> <Property name="text" type="java.lang.String" value="US"/>
<Property name="toolTipText" type="java.lang.String" value="Connect to mtg.powersofwar.com (USA, use any username without registration)"/> <Property name="toolTipText" type="java.lang.String" value="Connect to us.xmage.today (USA, use any username without registration)"/>
<Property name="actionCommand" type="java.lang.String" value="connectXmageus"/> <Property name="actionCommand" type="java.lang.String" value="connectXmageus"/>
<Property name="alignmentY" type="float" value="0.0"/> <Property name="alignmentY" type="float" value="0.0"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor"> <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">

View file

@ -283,8 +283,8 @@ public class ConnectDialog extends MageDialog {
}); });
btnFindUs.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/us.png"))); // NOI18N btnFindUs.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/us.png"))); // NOI18N
btnFindUs.setText("P"); btnFindUs.setText("US");
btnFindUs.setToolTipText("Connect to mtg.powersofwar.com (USA, use any username without registration)"); btnFindUs.setToolTipText("Connect to us.xmage.today (USA, use any username without registration)");
btnFindUs.setActionCommand("connectXmageus"); btnFindUs.setActionCommand("connectXmageus");
btnFindUs.setAlignmentY(0.0F); btnFindUs.setAlignmentY(0.0F);
btnFindUs.setMargin(new java.awt.Insets(2, 2, 2, 2)); btnFindUs.setMargin(new java.awt.Insets(2, 2, 2, 2));
@ -309,31 +309,31 @@ public class ConnectDialog extends MageDialog {
javax.swing.GroupLayout panelFastLayout = new javax.swing.GroupLayout(panelFast); javax.swing.GroupLayout panelFastLayout = new javax.swing.GroupLayout(panelFast);
panelFast.setLayout(panelFastLayout); panelFast.setLayout(panelFastLayout);
panelFastLayout.setHorizontalGroup( panelFastLayout.setHorizontalGroup(
panelFastLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) panelFastLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelFastLayout.createSequentialGroup() .addGroup(panelFastLayout.createSequentialGroup()
.addGap(0, 0, 0) .addGap(0, 0, 0)
.addComponent(btnFindMain, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(btnFindMain, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFindUs, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(btnFindUs, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFindBeta, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(btnFindBeta, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFindLocal, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(btnFindLocal, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFindOther, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(btnFindOther, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGap(0, 0, 0)) .addGap(0, 0, 0))
); );
panelFastLayout.setVerticalGroup( panelFastLayout.setVerticalGroup(
panelFastLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) panelFastLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelFastLayout.createSequentialGroup() .addGroup(panelFastLayout.createSequentialGroup()
.addGap(0, 0, 0) .addGap(0, 0, 0)
.addGroup(panelFastLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(panelFastLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnFindMain, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(btnFindMain, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnFindLocal, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(btnFindLocal, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnFindUs, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(btnFindUs, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnFindBeta, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(btnFindBeta, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnFindOther, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(btnFindOther, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(0, 0, 0)) .addGap(0, 0, 0))
); );
txtPort.addKeyListener(new java.awt.event.KeyAdapter() { txtPort.addKeyListener(new java.awt.event.KeyAdapter() {
@ -360,26 +360,26 @@ public class ConnectDialog extends MageDialog {
javax.swing.GroupLayout panelServerLayout = new javax.swing.GroupLayout(panelServer); javax.swing.GroupLayout panelServerLayout = new javax.swing.GroupLayout(panelServer);
panelServer.setLayout(panelServerLayout); panelServer.setLayout(panelServerLayout);
panelServerLayout.setHorizontalGroup( panelServerLayout.setHorizontalGroup(
panelServerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) panelServerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelServerLayout.createSequentialGroup() .addGroup(panelServerLayout.createSequentialGroup()
.addComponent(txtServer, javax.swing.GroupLayout.PREFERRED_SIZE, 212, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(txtServer, javax.swing.GroupLayout.PREFERRED_SIZE, 212, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblPort) .addComponent(lblPort)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCheckStatus, javax.swing.GroupLayout.DEFAULT_SIZE, 205, Short.MAX_VALUE) .addComponent(btnCheckStatus, javax.swing.GroupLayout.DEFAULT_SIZE, 205, Short.MAX_VALUE)
.addGap(0, 0, 0)) .addGap(0, 0, 0))
); );
panelServerLayout.setVerticalGroup( panelServerLayout.setVerticalGroup(
panelServerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) panelServerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelServerLayout.createSequentialGroup() .addGroup(panelServerLayout.createSequentialGroup()
.addGap(0, 0, 0) .addGap(0, 0, 0)
.addGroup(panelServerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(panelServerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(txtServer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(txtServer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblPort) .addComponent(lblPort)
.addComponent(btnCheckStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) .addComponent(btnCheckStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
); );
btnWhatsNew.setText("Show what's new"); btnWhatsNew.setText("Show what's new");
@ -394,92 +394,92 @@ public class ConnectDialog extends MageDialog {
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout); getContentPane().setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(lblUserName, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(lblUserName, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lblServer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(lblServer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lblFastConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(lblFastConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lblPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(lblPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lblFlag, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(lblFlag, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(18, 18, 18) .addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblStatus, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(lblStatus, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(chkForceUpdateDB, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(chkForceUpdateDB, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(chkAutoConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(chkAutoConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(txtUserName) .addComponent(txtUserName)
.addComponent(panelFlag, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(panelFlag, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(btnConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(btnConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(btnRegister, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(btnRegister, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnForgotPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(btnForgotPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 77, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(btnCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 77, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(panelFast, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(panelFast, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(panelServer, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(panelServer, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(jProxySettingsButton) .addComponent(jProxySettingsButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnWhatsNew) .addComponent(btnWhatsNew)
.addGap(0, 0, Short.MAX_VALUE)) .addGap(0, 0, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(txtPassword) .addComponent(txtPassword)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel1))) .addComponent(jLabel1)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(filler2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(filler2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap()) .addContainerGap())
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(panelFast, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(panelFast, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lblFastConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(lblFastConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(panelServer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(panelServer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lblServer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(lblServer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(txtUserName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(txtUserName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblUserName, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(lblUserName, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(txtPassword) .addComponent(txtPassword)
.addComponent(jLabel1)) .addComponent(jLabel1))
.addComponent(lblPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) .addComponent(lblPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addComponent(filler2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(filler2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(panelFlag, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(panelFlag, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblFlag, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(lblFlag, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(chkAutoConnect) .addComponent(chkAutoConnect)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(chkForceUpdateDB) .addComponent(chkForceUpdateDB)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jProxySettingsButton, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jProxySettingsButton, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnWhatsNew, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(btnWhatsNew, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(lblStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(lblStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(btnRegister, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(btnRegister, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnForgotPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(btnForgotPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addComponent(btnConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(btnConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnCancel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(btnCancel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(23, 23, 23)) .addGap(23, 23, 23))
); );
lblFastConnect.getAccessibleContext().setAccessibleName("Fast connect to:"); lblFastConnect.getAccessibleContext().setAccessibleName("Fast connect to:");
@ -765,7 +765,7 @@ public class ConnectDialog extends MageDialog {
}//GEN-LAST:event_btnFind2findPublicServerActionPerformed }//GEN-LAST:event_btnFind2findPublicServerActionPerformed
private void connectXmageus(java.awt.event.ActionEvent evt) { private void connectXmageus(java.awt.event.ActionEvent evt) {
String serverAddress = "mtg.powersofwar.com"; String serverAddress = "us.xmage.today";
this.txtServer.setText(serverAddress); this.txtServer.setText(serverAddress);
this.txtPort.setText("17171"); this.txtPort.setText("17171");
// Update userName and password according to the chosen server. // Update userName and password according to the chosen server.
@ -774,7 +774,7 @@ public class ConnectDialog extends MageDialog {
} }
private void connectBeta(java.awt.event.ActionEvent evt) { private void connectBeta(java.awt.event.ActionEvent evt) {
String serverAddress = "xmage.today"; String serverAddress = "beta.xmage.today";
this.txtServer.setText(serverAddress); this.txtServer.setText(serverAddress);
this.txtPort.setText("17171"); this.txtPort.setText("17171");
// Update userName and password according to the chosen server. // Update userName and password according to the chosen server.

View file

@ -359,7 +359,7 @@
<Component class="javax.swing.JLabel" name="lbTimeLimit"> <Component class="javax.swing.JLabel" name="lbTimeLimit">
<Properties> <Properties>
<Property name="text" type="java.lang.String" value="Time Limit:"/> <Property name="text" type="java.lang.String" value="Time Limit:"/>
<Property name="toolTipText" type="java.lang.String" value="The active time a player may use to finish the match. If his or her time runs out, the player looses the current game."/> <Property name="toolTipText" type="java.lang.String" value="The active time a player may use to finish the match. If their time runs out, the player looses the current game."/>
</Properties> </Properties>
</Component> </Component>
<Component class="javax.swing.JComboBox" name="cbTimeLimit"> <Component class="javax.swing.JComboBox" name="cbTimeLimit">

View file

@ -187,7 +187,7 @@ public class NewTableDialog extends MageDialog {
lbDeckType.setText("Deck Type:"); lbDeckType.setText("Deck Type:");
lbTimeLimit.setText("Time Limit:"); lbTimeLimit.setText("Time Limit:");
lbTimeLimit.setToolTipText("The active time a player may use to finish the match. If his or her time runs out, the player looses the current game."); lbTimeLimit.setToolTipText("The active time a player may use to finish the match. If their time runs out, the player looses the current game.");
lblGameType.setText("Game Type:"); lblGameType.setText("Game Type:");
@ -637,6 +637,7 @@ public class NewTableDialog extends MageDialog {
case "Variant Magic - Commander": case "Variant Magic - Commander":
case "Variant Magic - Duel Commander": case "Variant Magic - Duel Commander":
case "Variant Magic - MTGO 1v1 Commander": case "Variant Magic - MTGO 1v1 Commander":
case "Variant Magic - Centurion Commander":
case "Variant Magic - Penny Dreadful Commander": case "Variant Magic - Penny Dreadful Commander":
if (!options.getGameType().startsWith("Commander")) { if (!options.getGameType().startsWith("Commander")) {
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Deck type Commander needs also a Commander game type", "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Deck type Commander needs also a Commander game type", "Error", JOptionPane.ERROR_MESSAGE);
@ -668,6 +669,12 @@ public class NewTableDialog extends MageDialog {
return false; return false;
} }
break; break;
case "Variant Magic - Oathbreaker":
if (!options.getGameType().startsWith("Oathbreaker")) {
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Deck type Oathbreaker needs also a Oathbreaker game type", "Error", JOptionPane.ERROR_MESSAGE);
return false;
}
break;
} }
// game => deck // game => deck
@ -677,6 +684,7 @@ public class NewTableDialog extends MageDialog {
if (!options.getDeckType().equals("Variant Magic - Commander") if (!options.getDeckType().equals("Variant Magic - Commander")
&& !options.getDeckType().equals("Variant Magic - Duel Commander") && !options.getDeckType().equals("Variant Magic - Duel Commander")
&& !options.getDeckType().equals("Variant Magic - MTGO 1v1 Commander") && !options.getDeckType().equals("Variant Magic - MTGO 1v1 Commander")
&& !options.getDeckType().equals("Variant Magic - Centurion Commander")
&& !options.getDeckType().equals("Variant Magic - Freeform Commander") && !options.getDeckType().equals("Variant Magic - Freeform Commander")
&& !options.getDeckType().equals("Variant Magic - Penny Dreadful Commander")) { && !options.getDeckType().equals("Variant Magic - Penny Dreadful Commander")) {
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Deck type Commander needs also a Commander game type", "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Deck type Commander needs also a Commander game type", "Error", JOptionPane.ERROR_MESSAGE);
@ -704,6 +712,13 @@ public class NewTableDialog extends MageDialog {
return false; return false;
} }
break; break;
case "Oathbreaker Two Player Duel":
case "Oathbreaker Free For All":
if (!options.getDeckType().equals("Variant Magic - Oathbreaker")) {
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Deck type Oathbreaker needs also a Oathbreaker game type", "Error", JOptionPane.ERROR_MESSAGE);
return false;
}
break;
} }
return true; return true;
} }

View file

@ -362,7 +362,7 @@
<Component class="javax.swing.JLabel" name="lbTimeLimit"> <Component class="javax.swing.JLabel" name="lbTimeLimit">
<Properties> <Properties>
<Property name="text" type="java.lang.String" value="Time Limit:"/> <Property name="text" type="java.lang.String" value="Time Limit:"/>
<Property name="toolTipText" type="java.lang.String" value="The time a player has for the whole match. If a player runs out of time during a game, he loses the complete match. "/> <Property name="toolTipText" type="java.lang.String" value="The time a player has for the whole match. If a player runs out of time during a game, they lose the complete match. "/>
</Properties> </Properties>
<BindingProperties> <BindingProperties>
<BindingProperty name="labelFor" source="cbTimeLimit" target="lbTimeLimit" targetPath="labelFor" updateStrategy="0" immediately="false"/> <BindingProperty name="labelFor" source="cbTimeLimit" target="lbTimeLimit" targetPath="labelFor" updateStrategy="0" immediately="false"/>
@ -370,13 +370,13 @@
</Component> </Component>
<Component class="javax.swing.JComboBox" name="cbTimeLimit"> <Component class="javax.swing.JComboBox" name="cbTimeLimit">
<Properties> <Properties>
<Property name="toolTipText" type="java.lang.String" value="The time a player has for the whole match. If a player runs out of time during a game, he loses the complete match. "/> <Property name="toolTipText" type="java.lang.String" value="The time a player has for the whole match. If a player runs out of time during a game, they lose the complete match. "/>
</Properties> </Properties>
</Component> </Component>
<Component class="javax.swing.JLabel" name="lbSkillLevel"> <Component class="javax.swing.JLabel" name="lbSkillLevel">
<Properties> <Properties>
<Property name="text" type="java.lang.String" value="Skill Level:"/> <Property name="text" type="java.lang.String" value="Skill Level:"/>
<Property name="toolTipText" type="java.lang.String" value="The time a player has for the whole match. If a player runs out of time during a game, he loses the complete match. "/> <Property name="toolTipText" type="java.lang.String" value="The time a player has for the whole match. If a player runs out of time during a game, they lose the complete match. "/>
</Properties> </Properties>
</Component> </Component>
<Component class="javax.swing.JComboBox" name="cbSkillLevel"> <Component class="javax.swing.JComboBox" name="cbSkillLevel">

View file

@ -1,5 +1,10 @@
package mage.client.dialog; package mage.client.dialog;
import java.awt.*;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;
import javax.swing.*;
import mage.cards.decks.Deck; import mage.cards.decks.Deck;
import mage.cards.decks.DeckFileFilter; import mage.cards.decks.DeckFileFilter;
import mage.cards.decks.importer.DeckImporter; import mage.cards.decks.importer.DeckImporter;
@ -26,13 +31,6 @@ import mage.view.TableView;
import mage.view.TournamentTypeView; import mage.view.TournamentTypeView;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/** /**
* @author BetaSteward_at_googlemail.com, JayDi85 * @author BetaSteward_at_googlemail.com, JayDi85
*/ */
@ -41,13 +39,13 @@ public class NewTournamentDialog extends MageDialog {
private static final Logger logger = Logger.getLogger(NewTournamentDialog.class); private static final Logger logger = Logger.getLogger(NewTournamentDialog.class);
private TableView table; private TableView table;
private UUID playerId; // private UUID playerId;
private UUID roomId; private UUID roomId;
private String lastSessionId; private String lastSessionId;
private RandomPacksSelectorDialog randomPackSelector; private RandomPacksSelectorDialog randomPackSelector;
private JTextArea txtRandomPacks; private JTextArea txtRandomPacks;
private final List<TournamentPlayerPanel> players = new ArrayList<>(); private final java.util.List<TournamentPlayerPanel> players = new ArrayList<>();
private final List<JPanel> packPanels = new ArrayList<>(); private final java.util.List<JPanel> packPanels = new ArrayList<>();
private static final int CONSTRUCTION_TIME_MIN = 6; private static final int CONSTRUCTION_TIME_MIN = 6;
private static final int CONSTRUCTION_TIME_MAX = 30; private static final int CONSTRUCTION_TIME_MAX = 30;
private boolean isRandom = false; private boolean isRandom = false;
@ -231,15 +229,15 @@ public class NewTournamentDialog extends MageDialog {
lblName.setText("Name:"); lblName.setText("Name:");
lbTimeLimit.setText("Time Limit:"); lbTimeLimit.setText("Time Limit:");
lbTimeLimit.setToolTipText("The time a player has for the whole match. If a player runs out of time during a game, he loses the complete match. "); lbTimeLimit.setToolTipText("The time a player has for the whole match. If a player runs out of time during a game, they lose the complete match. ");
org.jdesktop.beansbinding.Binding binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, cbTimeLimit, org.jdesktop.beansbinding.ObjectProperty.create(), lbTimeLimit, org.jdesktop.beansbinding.BeanProperty.create("labelFor")); org.jdesktop.beansbinding.Binding binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, cbTimeLimit, org.jdesktop.beansbinding.ObjectProperty.create(), lbTimeLimit, org.jdesktop.beansbinding.BeanProperty.create("labelFor"));
bindingGroup.addBinding(binding); bindingGroup.addBinding(binding);
cbTimeLimit.setToolTipText("The time a player has for the whole match. If a player runs out of time during a game, he loses the complete match. "); cbTimeLimit.setToolTipText("The time a player has for the whole match. If a player runs out of time during a game, they lose the complete match. ");
lbSkillLevel.setText("Skill Level:"); lbSkillLevel.setText("Skill Level:");
lbSkillLevel.setToolTipText("The time a player has for the whole match. If a player runs out of time during a game, he loses the complete match. "); lbSkillLevel.setToolTipText("The time a player has for the whole match. If a player runs out of time during a game, they lose the complete match. ");
cbSkillLevel.setToolTipText("<HTML>This option can be used to make it easier to find matches<br>\nwith opponents of the appropriate skill level."); cbSkillLevel.setToolTipText("<HTML>This option can be used to make it easier to find matches<br>\nwith opponents of the appropriate skill level.");
@ -709,12 +707,12 @@ public class NewTournamentDialog extends MageDialog {
private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed
this.table = null; this.table = null;
this.playerId = null; // this.playerId = null;
this.hideDialog(); this.hideDialog();
}//GEN-LAST:event_btnCancelActionPerformed }//GEN-LAST:event_btnCancelActionPerformed
private void updateNumSeats() { private void updateNumSeats() {
int numPlayers = (Integer) this.spnNumPlayers.getValue(); // int numPlayers = (Integer) this.spnNumPlayers.getValue();
int numSeats = (Integer) this.spnNumSeats.getValue(); int numSeats = (Integer) this.spnNumSeats.getValue();
if (numSeats > 2) { if (numSeats > 2) {
@ -966,11 +964,6 @@ public class NewTournamentDialog extends MageDialog {
} }
randomPackSelector.setSelectedPacks(packList); randomPackSelector.setSelectedPacks(packList);
txtRandomPacks.setText(packNames); txtRandomPacks.setText(packNames);
// workaround to apply field's auto-size
this.pack();
this.revalidate();
this.repaint();
} }
private void createRandomPacks() { private void createRandomPacks() {
@ -993,6 +986,7 @@ public class NewTournamentDialog extends MageDialog {
btnSelectRandomPacks.setToolTipText(RandomPacksSelectorDialog.randomDraftDescription); btnSelectRandomPacks.setToolTipText(RandomPacksSelectorDialog.randomDraftDescription);
btnSelectRandomPacks.addActionListener(evt -> showRandomPackSelectorDialog()); btnSelectRandomPacks.addActionListener(evt -> showRandomPackSelectorDialog());
pnlRandomPacks.add(btnSelectRandomPacks); pnlRandomPacks.add(btnSelectRandomPacks);
this.pnlRandomPacks.setMinimumSize(new Dimension(784, 150));
} }
txtRandomPacks.setText(txtRandomPacks.getText()); // workaround to apply field's auto-size txtRandomPacks.setText(txtRandomPacks.getText()); // workaround to apply field's auto-size
this.pack(); this.pack();
@ -1154,7 +1148,7 @@ public class NewTournamentDialog extends MageDialog {
int packNumber = 0; int packNumber = 0;
for (String pack : packsArray) { for (String pack : packsArray) {
packNumber++; packNumber++;
if (this.packPanels.size() >= packNumber - 1) { if (!packPanels.isEmpty() && this.packPanels.size() >= packNumber - 1) {
JPanel panel = packPanels.get(packNumber - 1); JPanel panel = packPanels.get(packNumber - 1);
JComboBox comboBox = findComboInComponent(panel); JComboBox comboBox = findComboInComponent(panel);
@ -1466,4 +1460,4 @@ public class NewTournamentDialog extends MageDialog {
private org.jdesktop.beansbinding.BindingGroup bindingGroup; private org.jdesktop.beansbinding.BindingGroup bindingGroup;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables
} }

View file

@ -36,12 +36,17 @@
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<Component id="pnlSelect" min="-2" pref="241" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<EmptySpace pref="300" max="32767" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0">
<Component id="pnlApply" min="-2" max="-2" attributes="0"/> <Group type="102" attributes="0">
</Group> <Component id="pnlSelect" min="-2" pref="196" max="-2" attributes="0"/>
<Group type="102" attributes="0"> <EmptySpace pref="402" max="32767" attributes="0"/>
<Component id="pnlPacks" max="32767" attributes="0"/> <Component id="pnlApply" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnApply" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="pnlPacks" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
@ -49,11 +54,13 @@
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Component id="pnlPacks" min="-2" pref="372" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="pnlPacks" min="-2" pref="362" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="pnlApply" min="-2" pref="32" max="-2" attributes="0"/> <Component id="pnlApply" min="-2" pref="32" max="-2" attributes="0"/>
<Component id="pnlSelect" min="-2" pref="32" max="-2" attributes="0"/> <Component id="pnlSelect" min="-2" pref="32" max="-2" attributes="0"/>
<Component id="btnApply" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace max="32767" attributes="0"/> <EmptySpace max="32767" attributes="0"/>
</Group> </Group>
@ -64,8 +71,8 @@
<Container class="java.awt.Panel" name="pnlPacks"> <Container class="java.awt.Panel" name="pnlPacks">
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridLayout"> <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridLayout">
<Property name="columns" type="int" value="12"/> <Property name="columns" type="int" value="13"/>
<Property name="rows" type="int" value="11"/> <Property name="rows" type="int" value="12"/>
</Layout> </Layout>
</Container> </Container>
<Container class="javax.swing.JPanel" name="pnlSelect"> <Container class="javax.swing.JPanel" name="pnlSelect">
@ -94,17 +101,15 @@
<Container class="javax.swing.JPanel" name="pnlApply"> <Container class="javax.swing.JPanel" name="pnlApply">
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/> <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/>
<SubComponents>
<Component class="javax.swing.JButton" name="btnApply">
<Properties>
<Property name="text" type="java.lang.String" value="Apply"/>
<Property name="toolTipText" type="java.lang.String" value="At least two packs must be selected"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnApplyActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container> </Container>
<Component class="javax.swing.JButton" name="btnApply">
<Properties>
<Property name="text" type="java.lang.String" value="Apply"/>
<Property name="toolTipText" type="java.lang.String" value="At least two packs must be selected"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnApplyActionPerformed"/>
</Events>
</Component>
</SubComponents> </SubComponents>
</Form> </Form>

View file

@ -58,25 +58,25 @@ public class RandomPacksSelectorDialog extends javax.swing.JDialog {
this.setModal(true); this.setModal(true);
} }
public void setSelectedPacks(ArrayList<String> packs){ public void setSelectedPacks(ArrayList<String> packs) {
if (!boxesCreated){ if (!boxesCreated) {
createCheckboxes(); createCheckboxes();
} }
for (Component pack : pnlPacks.getComponents()) { for (Component pack : pnlPacks.getComponents()) {
JCheckBox thePack = (JCheckBox) pack; JCheckBox thePack = (JCheckBox) pack;
if (packs.contains(thePack.getText())) { if (packs.contains(thePack.getText())) {
thePack.setSelected(true); thePack.setSelected(true);
} else{ } else {
thePack.setSelected(false); thePack.setSelected(false);
} }
} }
} }
public ArrayList<String> getSelectedPacks() { public ArrayList<String> getSelectedPacks() {
ArrayList<String> returnVal = new ArrayList<>(); ArrayList<String> returnVal = new ArrayList<>();
for (Component pack: pnlPacks.getComponents()){ for (Component pack : pnlPacks.getComponents()) {
JCheckBox thePack = (JCheckBox) pack; JCheckBox thePack = (JCheckBox) pack;
if (thePack.isSelected()){ if (thePack.isSelected()) {
returnVal.add(thePack.getText()); returnVal.add(thePack.getText());
} }
} }
@ -100,7 +100,6 @@ public class RandomPacksSelectorDialog extends javax.swing.JDialog {
} }
} }
/** /**
* This method is called from within the constructor to initialize the form. * This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always * WARNING: Do NOT modify this code. The content of this method is always
@ -118,7 +117,7 @@ public class RandomPacksSelectorDialog extends javax.swing.JDialog {
btnApply = new javax.swing.JButton(); btnApply = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE); setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
setTitle(title); setTitle("Random Booster Draft Packs Selector");
setModal(true); setModal(true);
setModalExclusionType(java.awt.Dialog.ModalExclusionType.APPLICATION_EXCLUDE); setModalExclusionType(java.awt.Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
setPreferredSize(new java.awt.Dimension(600, 450)); setPreferredSize(new java.awt.Dimension(600, 450));
@ -129,50 +128,63 @@ public class RandomPacksSelectorDialog extends javax.swing.JDialog {
} }
}); });
pnlPacks.setLayout(new java.awt.GridLayout(11, 12)); pnlPacks.setLayout(new java.awt.GridLayout(12, 13));
pnlSelect.setLayout(new javax.swing.BoxLayout(pnlSelect, javax.swing.BoxLayout.LINE_AXIS)); pnlSelect.setLayout(new javax.swing.BoxLayout(pnlSelect, javax.swing.BoxLayout.LINE_AXIS));
btnNone.setText("Select none"); btnNone.setText("Select none");
btnNone.setActionCommand("none"); btnNone.setActionCommand("none");
btnNone.addActionListener(evt -> btnNoneActionPerformed(evt)); btnNone.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnNoneActionPerformed(evt);
}
});
pnlSelect.add(btnNone); pnlSelect.add(btnNone);
btnAll.setText("Select all"); btnAll.setText("Select all");
btnAll.addActionListener(evt -> btnAllActionPerformed(evt)); btnAll.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnAllActionPerformed(evt);
}
});
pnlSelect.add(btnAll); pnlSelect.add(btnAll);
pnlApply.setLayout(new javax.swing.BoxLayout(pnlApply, javax.swing.BoxLayout.LINE_AXIS)); pnlApply.setLayout(new javax.swing.BoxLayout(pnlApply, javax.swing.BoxLayout.LINE_AXIS));
btnApply.setText("Apply"); btnApply.setText("Apply");
if (isRandomDraft) { btnApply.setToolTipText("At least two packs must be selected");
btnApply.setToolTipText("At least 2 packs must be selected"); btnApply.addActionListener(new java.awt.event.ActionListener() {
} else if (isRichManDraft) { public void actionPerformed(java.awt.event.ActionEvent evt) {
btnApply.setToolTipText("At least 1 pack must be selected"); btnApplyActionPerformed(evt);
} }
btnApply.addActionListener(evt -> btnApplyActionPerformed(evt)); });
pnlApply.add(btnApply);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout); getContentPane().setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(pnlSelect, javax.swing.GroupLayout.PREFERRED_SIZE, 241, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 300, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(pnlApply, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(layout.createSequentialGroup()
.addGroup(layout.createSequentialGroup() .addComponent(pnlSelect, javax.swing.GroupLayout.PREFERRED_SIZE, 196, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(pnlPacks, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 402, Short.MAX_VALUE)
.addComponent(pnlApply, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnApply))
.addComponent(pnlPacks, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap()) .addContainerGap())
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(pnlPacks, javax.swing.GroupLayout.PREFERRED_SIZE, 372, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap()
.addComponent(pnlPacks, javax.swing.GroupLayout.PREFERRED_SIZE, 362, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(pnlApply, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(pnlApply, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(pnlSelect, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(pnlSelect, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnApply))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
); );
@ -198,7 +210,7 @@ public class RandomPacksSelectorDialog extends javax.swing.JDialog {
public void doApply() { public void doApply() {
if (getSelectedPacks().size() < 2 && isRandomDraft) { if (getSelectedPacks().size() < 2 && isRandomDraft) {
JOptionPane.showMessageDialog(this, "At least 2 sets must be selected", "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(this, "At least 2 sets must be selected", "Error", JOptionPane.ERROR_MESSAGE);
} else if (getSelectedPacks().size() < 1 && isRichManDraft) { } else if (getSelectedPacks().isEmpty() && isRichManDraft) {
JOptionPane.showMessageDialog(this, "At least 1 set must be selected", "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(this, "At least 1 set must be selected", "Error", JOptionPane.ERROR_MESSAGE);
} else { } else {
this.setVisible(false); this.setVisible(false);
@ -220,4 +232,4 @@ public class RandomPacksSelectorDialog extends javax.swing.JDialog {
private java.awt.Panel pnlPacks; private java.awt.Panel pnlPacks;
private javax.swing.JPanel pnlSelect; private javax.swing.JPanel pnlSelect;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables
} }

View file

@ -22,7 +22,7 @@ import mage.game.command.emblems.AjaniAdversaryOfTyrantsEmblem;
import mage.game.command.planes.AkoumPlane; import mage.game.command.planes.AkoumPlane;
import mage.game.match.MatchType; import mage.game.match.MatchType;
import mage.game.mulligan.Mulligan; import mage.game.mulligan.Mulligan;
import mage.game.mulligan.VancouverMulligan; import mage.game.mulligan.MulliganType;
import mage.game.permanent.PermanentCard; import mage.game.permanent.PermanentCard;
import mage.players.Player; import mage.players.Player;
import mage.players.StubPlayer; import mage.players.StubPlayer;
@ -113,7 +113,7 @@ public class TestCardRenderDialog extends MageDialog {
cardsPanel.cleanUp(); cardsPanel.cleanUp();
cardsPanel.setCustomRenderMode(comboRenderMode.getSelectedIndex()); cardsPanel.setCustomRenderMode(comboRenderMode.getSelectedIndex());
Game game = new TestGame(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ALL, new VancouverMulligan(0), 20); Game game = new TestGame(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ALL, MulliganType.GAME_DEFAULT.getMulligan(0), 20);
Player player = new StubPlayer("player1", RangeOfInfluence.ALL); Player player = new StubPlayer("player1", RangeOfInfluence.ALL);
Deck deck = new Deck(); Deck deck = new Deck();
game.addPlayer(player, deck); game.addPlayer(player, deck);

View file

@ -606,10 +606,13 @@ public final class GamePanel extends javax.swing.JPanel {
} }
public synchronized void updateGame(GameView game) { public synchronized void updateGame(GameView game) {
updateGame(game, null); updateGame(game, false, null, null);
} }
public synchronized void updateGame(GameView game, Map<String, Serializable> options) { public synchronized void updateGame(GameView game, boolean showPlayable, Map<String, Serializable> options, Set<UUID> targets) {
prepareSelectableView(game, showPlayable, options, targets);
if (playerId == null && game.getWatchedHands() == null) { if (playerId == null && game.getWatchedHands() == null) {
this.handContainer.setVisible(false); this.handContainer.setVisible(false);
} else { } else {
@ -622,14 +625,6 @@ public final class GamePanel extends javax.swing.JPanel {
} }
if (playerId != null) { if (playerId != null) {
handCards.put(YOUR_HAND, game.getHand()); handCards.put(YOUR_HAND, game.getHand());
// Mark playable
if (game.getCanPlayInHand() != null) {
for (CardView card : handCards.get(YOUR_HAND).values()) {
if (game.getCanPlayInHand().contains(card.getId())) {
card.setPlayable(true);
}
}
}
// Get opponents hand cards if available (only possible for players) // Get opponents hand cards if available (only possible for players)
if (game.getOpponentHands() != null) { if (game.getOpponentHands() != null) {
for (Map.Entry<String, SimpleCardsView> hand : game.getOpponentHands().entrySet()) { for (Map.Entry<String, SimpleCardsView> hand : game.getOpponentHands().entrySet()) {
@ -719,7 +714,7 @@ public final class GamePanel extends javax.swing.JPanel {
} }
} }
} }
players.get(player.getPlayerId()).update(player); players.get(player.getPlayerId()).update(game, player, targets);
if (player.getPlayerId().equals(playerId)) { if (player.getPlayerId().equals(playerId)) {
skipButtons.updateFromPlayer(player); skipButtons.updateFromPlayer(player);
} }
@ -1183,25 +1178,23 @@ public final class GamePanel extends javax.swing.JPanel {
} }
public void ask(String question, GameView gameView, int messageId, Map<String, Serializable> options) { public void ask(String question, GameView gameView, int messageId, Map<String, Serializable> options) {
updateGame(gameView); updateGame(gameView, false, options, null);
this.feedbackPanel.getFeedback(FeedbackMode.QUESTION, question, false, options, messageId, true, gameView.getPhase()); this.feedbackPanel.getFeedback(FeedbackMode.QUESTION, question, false, options, messageId, true, gameView.getPhase());
} }
private void prepareSelectableView(GameView gameView, Map<String, Serializable> options, Set<UUID> targets) { private void prepareSelectableView(GameView gameView, boolean showPlayable, Map<String, Serializable> options, Set<UUID> targets) {
// make cards/perm selectable // make cards/perm selectable/chooseable/playable
// highlighting chosen // playable must be used for ask dialog only (priority and mana pay)
// code calls after each selects or updates, no needs in switch off cards
Zone needZone = Zone.ALL; Zone needZone = Zone.ALL;
if (options.containsKey("targetZone")) { if (options != null && options.containsKey("targetZone")) {
needZone = (Zone) options.get("targetZone"); needZone = (Zone) options.get("targetZone");
} }
List<UUID> needChoosen = null; List<UUID> needChoosen;
if (options.containsKey("chosen")) { if (options != null && options.containsKey("chosen")) {
needChoosen = (List<UUID>) options.get("chosen"); needChoosen = (List<UUID>) options.get("chosen");
} } else {
if (needChoosen == null) {
needChoosen = new ArrayList<>(); needChoosen = new ArrayList<>();
} }
@ -1212,7 +1205,14 @@ public final class GamePanel extends javax.swing.JPanel {
needSelectable = new HashSet<>(); needSelectable = new HashSet<>();
} }
if (needChoosen.size() == 0 && needSelectable.size() == 0) { Map<UUID, Integer> needPlayable;
if (showPlayable && gameView.getCanPlayObjects() != null) {
needPlayable = gameView.getCanPlayObjects();
} else {
needPlayable = new HashMap<>();
}
if (needChoosen.isEmpty() && needSelectable.isEmpty() && needPlayable.isEmpty()) {
return; return;
} }
@ -1225,6 +1225,10 @@ public final class GamePanel extends javax.swing.JPanel {
if (needChoosen.contains(card.getId())) { if (needChoosen.contains(card.getId())) {
card.setSelected(true); card.setSelected(true);
} }
if (needPlayable.containsKey(card.getId())) {
card.setPlayable(true);
card.setPlayableAmount(needPlayable.get(card.getId()));
}
} }
} }
@ -1237,6 +1241,7 @@ public final class GamePanel extends javax.swing.JPanel {
if (needChoosen.contains(card.getKey())) { if (needChoosen.contains(card.getKey())) {
card.getValue().setSelected(true); card.getValue().setSelected(true);
} }
// play from stack unsupported
} }
} }
@ -1250,6 +1255,10 @@ public final class GamePanel extends javax.swing.JPanel {
if (needChoosen.contains(perm.getKey())) { if (needChoosen.contains(perm.getKey())) {
perm.getValue().setSelected(true); perm.getValue().setSelected(true);
} }
if (needPlayable.containsKey(perm.getKey())) {
perm.getValue().setPlayable(true);
perm.getValue().setPlayableAmount(needPlayable.get(perm.getKey()));
}
} }
} }
} }
@ -1264,6 +1273,10 @@ public final class GamePanel extends javax.swing.JPanel {
if (needChoosen.contains(card.getKey())) { if (needChoosen.contains(card.getKey())) {
card.getValue().setSelected(true); card.getValue().setSelected(true);
} }
if (needPlayable.containsKey(card.getKey())) {
card.getValue().setPlayable(true);
card.getValue().setPlayableAmount(needPlayable.get(card.getKey()));
}
} }
} }
} }
@ -1278,6 +1291,28 @@ public final class GamePanel extends javax.swing.JPanel {
if (needChoosen.contains(card.getKey())) { if (needChoosen.contains(card.getKey())) {
card.getValue().setSelected(true); card.getValue().setSelected(true);
} }
if (needPlayable.containsKey(card.getKey())) {
card.getValue().setPlayable(true);
card.getValue().setPlayableAmount(needPlayable.get(card.getKey()));
}
}
}
}
// command
if (needZone == Zone.COMMAND || needZone == Zone.ALL) {
for (PlayerView player : gameView.getPlayers()) {
for (CommandObjectView com : player.getCommandObjectList()) {
if (needSelectable.contains(com.getId())) {
com.setChoosable(true);
}
if (needChoosen.contains(com.getId())) {
com.setSelected(true);
}
if (needPlayable.containsKey(com.getId())) {
com.setPlayable(true);
com.setPlayableAmount(needPlayable.get(com.getId()));
}
} }
} }
} }
@ -1291,6 +1326,20 @@ public final class GamePanel extends javax.swing.JPanel {
if (needChoosen.contains(card.getKey())) { if (needChoosen.contains(card.getKey())) {
card.getValue().setSelected(true); card.getValue().setSelected(true);
} }
if (needPlayable.containsKey(card.getKey())) {
card.getValue().setPlayable(true);
card.getValue().setPlayableAmount(needPlayable.get(card.getKey()));
}
}
}
// looked at
for (LookedAtView look : gameView.getLookedAt()) {
for (Map.Entry<UUID, SimpleCardView> card : look.getCards().entrySet()) {
if (needPlayable.containsKey(card.getKey())) {
card.getValue().setPlayable(true);
card.getValue().setPlayableAmount(needPlayable.get(card.getKey()));
}
} }
} }
} }
@ -1315,10 +1364,8 @@ public final class GamePanel extends javax.swing.JPanel {
switch (needType) { switch (needType) {
case PICK_ABILITY: case PICK_ABILITY:
popupMenuType = PopUpMenuType.TRIGGER_ORDER; popupMenuType = PopUpMenuType.TRIGGER_ORDER;
prepareSelectableView(gameView, options, targets);
break; break;
case PICK_TARGET: case PICK_TARGET:
prepareSelectableView(gameView, options, targets);
break; break;
default: default:
logger.warn("Unknown query type in pick target: " + needType + " in " + message); logger.warn("Unknown query type in pick target: " + needType + " in " + message);
@ -1327,7 +1374,8 @@ public final class GamePanel extends javax.swing.JPanel {
} }
} }
updateGame(gameView); updateGame(gameView, false, options, targets);
Map<String, Serializable> options0 = options == null ? new HashMap<>() : options; Map<String, Serializable> options0 = options == null ? new HashMap<>() : options;
ShowCardsDialog dialog = null; ShowCardsDialog dialog = null;
if (cardView != null && !cardView.isEmpty()) { if (cardView != null && !cardView.isEmpty()) {
@ -1359,7 +1407,8 @@ public final class GamePanel extends javax.swing.JPanel {
PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"), PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"),
false); false);
updateGame(gameView, options); updateGame(gameView, true, options, null);
boolean controllingPlayer = false; boolean controllingPlayer = false;
for (PlayerView playerView : gameView.getPlayers()) { for (PlayerView playerView : gameView.getPlayers()) {
if (playerView.getPlayerId().equals(playerId)) { if (playerView.getPlayerId().equals(playerId)) {
@ -1393,13 +1442,13 @@ public final class GamePanel extends javax.swing.JPanel {
} }
public void playMana(String message, GameView gameView, Map<String, Serializable> options, int messageId) { public void playMana(String message, GameView gameView, Map<String, Serializable> options, int messageId) {
updateGame(gameView); updateGame(gameView, true, options, null);
DialogManager.getManager(gameId).fadeOut(); DialogManager.getManager(gameId).fadeOut();
this.feedbackPanel.getFeedback(FeedbackMode.CANCEL, message, gameView.getSpecial(), options, messageId, true, gameView.getPhase()); this.feedbackPanel.getFeedback(FeedbackMode.CANCEL, message, gameView.getSpecial(), options, messageId, true, gameView.getPhase());
} }
public void playXMana(String message, GameView gameView, int messageId) { public void playXMana(String message, GameView gameView, int messageId) {
updateGame(gameView); updateGame(gameView, true, null, null);
DialogManager.getManager(gameId).fadeOut(); DialogManager.getManager(gameId).fadeOut();
this.feedbackPanel.getFeedback(FeedbackMode.CONFIRM, message, gameView.getSpecial(), null, messageId, true, gameView.getPhase()); this.feedbackPanel.getFeedback(FeedbackMode.CONFIRM, message, gameView.getSpecial(), null, messageId, true, gameView.getPhase());
} }

View file

@ -365,7 +365,7 @@ public class HelperPanel extends JPanel {
this.mainPanel.setOpaque(false); this.mainPanel.setOpaque(false);
} }
if (buttons.size() == 0) { if (buttons.isEmpty()) {
return; return;
} }

View file

@ -1,42 +1,29 @@
package mage.client.game; package mage.client.game;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.lang.reflect.Field;
import java.util.UUID;
import javax.swing.BorderFactory;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.MenuSelectionManager;
import javax.swing.event.ChangeListener;
import mage.cards.decks.importer.DeckImporter; import mage.cards.decks.importer.DeckImporter;
import mage.client.MageFrame; import mage.client.MageFrame;
import mage.client.SessionHandler; import mage.client.SessionHandler;
import mage.client.cards.BigCard; import mage.client.cards.BigCard;
import mage.client.dialog.PreferencesDialog; import mage.client.dialog.PreferencesDialog;
import static mage.client.dialog.PreferencesDialog.KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS;
import static mage.client.dialog.PreferencesDialog.KEY_GAME_MANA_AUTOPAYMENT;
import static mage.client.dialog.PreferencesDialog.KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE;
import static mage.client.dialog.PreferencesDialog.KEY_USE_FIRST_MANA_ABILITY;
import mage.client.util.GUISizeHelper; import mage.client.util.GUISizeHelper;
import mage.constants.PlayerAction; import mage.constants.PlayerAction;
import mage.view.GameView;
import mage.view.PlayerView; import mage.view.PlayerView;
import mage.view.UserRequestMessage; import mage.view.UserRequestMessage;
import javax.swing.*;
import javax.swing.GroupLayout.Alignment;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.Field;
import java.util.Set;
import java.util.UUID;
import static mage.client.dialog.PreferencesDialog.*;
/** /**
*
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class PlayAreaPanel extends javax.swing.JPanel { public class PlayAreaPanel extends javax.swing.JPanel {
@ -77,7 +64,7 @@ public class PlayAreaPanel extends javax.swing.JPanel {
popupMenu = new JPopupMenu(); popupMenu = new JPopupMenu();
if (options.isPlayer) { if (options.isPlayer) {
addPopupMenuPlayer(player.getUserData().isAllowRequestShowHandCards()); addPopupMenuPlayer(player.getUserData().isAllowRequestHandToAll());
} else { } else {
addPopupMenuWatcher(); addPopupMenuWatcher();
} }
@ -85,7 +72,7 @@ public class PlayAreaPanel extends javax.swing.JPanel {
setGUISize(); setGUISize();
init(player, bigCard, gameId, priorityTime); init(player, bigCard, gameId, priorityTime);
update(player); update(null, player, null);
} }
public void CleanUp() { public void CleanUp() {
@ -331,12 +318,12 @@ public class PlayAreaPanel extends javax.swing.JPanel {
// Request to see hand cards // Request to see hand cards
menuItem.addActionListener(e -> SessionHandler.sendPlayerAction(PlayerAction.REQUEST_PERMISSION_TO_SEE_HAND_CARDS, gameId, playerId)); menuItem.addActionListener(e -> SessionHandler.sendPlayerAction(PlayerAction.REQUEST_PERMISSION_TO_SEE_HAND_CARDS, gameId, playerId));
} else { } else {
allowViewHandCardsMenuItem = new JCheckBoxMenuItem("Allow requests to show from other users", allowRequestToShowHandCards); allowViewHandCardsMenuItem = new JCheckBoxMenuItem("Allow hand requests from other users", allowRequestToShowHandCards);
allowViewHandCardsMenuItem.setMnemonic(KeyEvent.VK_A); allowViewHandCardsMenuItem.setMnemonic(KeyEvent.VK_A);
allowViewHandCardsMenuItem.setToolTipText("If activated watchers or other players can request to see your hand cards. If you grant this to a user, it's valid for the complete match."); allowViewHandCardsMenuItem.setToolTipText("Watchers or other players can request your hand cards once per game. Re-activate it to allow new requests.");
handCardsMenu.add(allowViewHandCardsMenuItem); handCardsMenu.add(allowViewHandCardsMenuItem);
// Requests allowed // requests allowed (disable -> enable to reset requested list)
allowViewHandCardsMenuItem.addActionListener(e -> { allowViewHandCardsMenuItem.addActionListener(e -> {
boolean requestsAllowed = ((JCheckBoxMenuItem) e.getSource()).getState(); boolean requestsAllowed = ((JCheckBoxMenuItem) e.getSource()).getState();
PreferencesDialog.setPrefValue(KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS, requestsAllowed); PreferencesDialog.setPrefValue(KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS, requestsAllowed);
@ -451,13 +438,13 @@ public class PlayAreaPanel extends javax.swing.JPanel {
} }
}); });
popupMenu.addSeparator(); popupMenu.addSeparator();
menuItem = new JMenuItem("<html>View current deck"); menuItem = new JMenuItem("<html>View current deck");
menuItem.setMnemonic(KeyEvent.VK_V); menuItem.setMnemonic(KeyEvent.VK_V);
popupMenu.add(menuItem); popupMenu.add(menuItem);
// View limited deck // View limited deck
menuItem.addActionListener(e -> { menuItem.addActionListener(e -> {
SessionHandler.sendPlayerAction(PlayerAction.VIEW_LIMITED_DECK, gameId, null); SessionHandler.sendPlayerAction(PlayerAction.VIEW_LIMITED_DECK, gameId, null);
@ -518,11 +505,11 @@ public class PlayAreaPanel extends javax.swing.JPanel {
} }
} }
public final void update(PlayerView player) { public final void update(GameView game, PlayerView player, Set<UUID> possibleTargets) {
this.playerPanel.update(player); this.playerPanel.update(game, player, possibleTargets);
this.battlefieldPanel.update(player.getBattlefield()); this.battlefieldPanel.update(player.getBattlefield());
if (this.allowViewHandCardsMenuItem != null) { if (this.allowViewHandCardsMenuItem != null) {
this.allowViewHandCardsMenuItem.setSelected(player.getUserData().isAllowRequestShowHandCards()); this.allowViewHandCardsMenuItem.setSelected(player.getUserData().isAllowRequestHandToAll());
} }
} }
@ -547,14 +534,14 @@ public class PlayAreaPanel extends javax.swing.JPanel {
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createSequentialGroup() layout.createSequentialGroup()
.addComponent(playerPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addComponent(playerPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(ComponentPlacement.RELATED) .addPreferredGap(ComponentPlacement.RELATED)
.addComponent(battlefieldPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(battlefieldPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(Alignment.LEADING) layout.createParallelGroup(Alignment.LEADING)
.addComponent(playerPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addComponent(playerPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(battlefieldPanel, GroupLayout.DEFAULT_SIZE, 160, Short.MAX_VALUE) .addComponent(battlefieldPanel, GroupLayout.DEFAULT_SIZE, 160, Short.MAX_VALUE)
); );
this.setLayout(layout); this.setLayout(layout);
} }

View file

@ -1,34 +1,5 @@
/*
* PlayerPanel.java
*
* Created on Nov 18, 2009, 3:01:31 PM
*/
package mage.client.game; package mage.client.game;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.swing.BorderFactory;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.SwingConstants;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import mage.cards.decks.importer.DckDeckImporter; import mage.cards.decks.importer.DckDeckImporter;
import mage.client.MageFrame; import mage.client.MageFrame;
import mage.client.SessionHandler; import mage.client.SessionHandler;
@ -44,26 +15,34 @@ import mage.client.util.gui.countryBox.CountryUtil;
import mage.components.ImagePanel; import mage.components.ImagePanel;
import mage.components.ImagePanelStyle; import mage.components.ImagePanelStyle;
import mage.constants.CardType; import mage.constants.CardType;
import static mage.constants.Constants.DEFAULT_AVATAR_ID;
import static mage.constants.Constants.MAX_AVATAR_ID;
import static mage.constants.Constants.MIN_AVATAR_ID;
import mage.constants.ManaType; import mage.constants.ManaType;
import mage.counters.Counter; import mage.counters.Counter;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.designations.DesignationType; import mage.designations.DesignationType;
import mage.utils.timer.PriorityTimer; import mage.utils.timer.PriorityTimer;
import mage.view.CardView; import mage.view.*;
import mage.view.ManaPoolView;
import mage.view.PlayerView;
import org.mage.card.arcane.ManaSymbols; import org.mage.card.arcane.ManaSymbols;
import javax.swing.*;
import javax.swing.GroupLayout.Alignment;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.*;
import static mage.constants.Constants.*;
/** /**
* Enhanced player pane. * Enhanced player pane.
* *
* @author nantuko * @author nantuko, JayDi85
*/ */
public class PlayerPanelExt extends javax.swing.JPanel { public class PlayerPanelExt extends javax.swing.JPanel {
// TODO: *.form file was lost, panel must be reworks in designer
private UUID playerId; private UUID playerId;
private UUID gameId; private UUID gameId;
private PlayerView player; private PlayerView player;
@ -84,6 +63,10 @@ public class PlayerPanelExt extends javax.swing.JPanel {
private final Color activeBackgroundColor = new Color(200, 255, 200, 200); private final Color activeBackgroundColor = new Color(200, 255, 200, 200);
private final Color deadBackgroundColor = new Color(131, 94, 83, 200); private final Color deadBackgroundColor = new Color(131, 94, 83, 200);
private final Color activeValueColor = new Color(244, 9, 47);
private final Font fontValuesZero = this.getFont().deriveFont(Font.PLAIN);
private final Font fontValuesNonZero = this.getFont().deriveFont(Font.BOLD);
private int avatarId = -1; private int avatarId = -1;
private String flagName; private String flagName;
private String basicTooltipText; private String basicTooltipText;
@ -140,15 +123,44 @@ public class PlayerPanelExt extends javax.swing.JPanel {
} }
private void setTextForLabel(JLabel label, int amount, boolean alwaysBlack) { private void setTextForLabel(JLabel label, int amount, boolean alwaysBlack) {
setTextForLabel(label, amount, alwaysBlack, Color.BLACK);
}
private void setTextForLabel(JLabel label, int amount, boolean alwaysBlack, Color fontColor) {
label.setText(Integer.toString(amount)); label.setText(Integer.toString(amount));
if (amount != 0 || alwaysBlack) { if (amount != 0 || alwaysBlack) {
label.setForeground(Color.BLACK); label.setForeground(fontColor);
label.setFont(fontValuesNonZero);
} else { } else {
label.setForeground(new Color(100, 100, 100)); label.setForeground(new Color(100, 100, 100));
label.setFont(fontValuesZero);
} }
} }
public void update(PlayerView player) { private boolean isCardsPlayable(Collection<CardView> cards, GameView gameView, Set<UUID> possibleTargets) {
if (cards != null) {
// can play
if (gameView != null && gameView.getCanPlayObjects() != null && !gameView.getCanPlayObjects().isEmpty()) {
for (CardView card : cards) {
if (gameView.getCanPlayObjects().containsKey(card.getId())) {
return true;
}
}
}
// can select
if (possibleTargets != null && !possibleTargets.isEmpty()) {
for (CardView card : cards) {
if (possibleTargets.contains(card.getId())) {
return true;
}
}
}
}
return false;
}
public void update(GameView game, PlayerView player, Set<UUID> possibleTargets) {
this.player = player; this.player = player;
int pastLife = player.getLife(); int pastLife = player.getLife();
if (playerLives != null) { if (playerLives != null) {
@ -220,10 +232,26 @@ public class PlayerPanelExt extends javax.swing.JPanel {
graveLabel.setFont(font); graveLabel.setFont(font);
changedFontGrave = false; changedFontGrave = false;
} }
setTextForLabel(graveLabel, graveCards, false);
Color graveColor = isCardsPlayable(player.getGraveyard().values(), game, possibleTargets) ? activeValueColor : Color.BLACK;
setTextForLabel(graveLabel, graveCards, false, graveColor);
graveLabel.setToolTipText("Card Types: " + qtyCardTypes(player.getGraveyard())); graveLabel.setToolTipText("Card Types: " + qtyCardTypes(player.getGraveyard()));
Color commandColor = Color.BLACK;
for (CommandObjectView com : player.getCommandObjectList()) {
if (game != null && game.getCanPlayObjects() != null && game.getCanPlayObjects().containsKey(com.getId())) {
commandColor = activeValueColor;
break;
}
if (possibleTargets != null && possibleTargets.contains(com.getId())) {
commandColor = activeValueColor;
break;
}
}
setTextForLabel(commandLabel, player.getCommandObjectList().size(), false, commandColor);
int exileCards = player.getExile().size(); int exileCards = player.getExile().size();
Color excileColor = isCardsPlayable(player.getExile().values(), game, possibleTargets) ? activeValueColor : Color.BLACK;
if (exileCards > 99) { if (exileCards > 99) {
if (!changedFontExile) { if (!changedFontExile) {
Font font = exileLabel.getFont(); Font font = exileLabel.getFont();
@ -237,21 +265,21 @@ public class PlayerPanelExt extends javax.swing.JPanel {
exileLabel.setFont(font); exileLabel.setFont(font);
changedFontExile = false; changedFontExile = false;
} }
setTextForLabel(exileLabel, exileCards, false); setTextForLabel(exileLabel, exileCards, false, excileColor);
if (!MageFrame.isLite()) { if (!MageFrame.isLite()) {
int id = player.getUserData().getAvatarId(); int id = player.getUserData().getAvatarId();
if (!(id >= 1000) && (id <= 0 || (id <= MIN_AVATAR_ID && id > MAX_AVATAR_ID))) { if (!(id > 1000) && (id != 64) && (id < MIN_AVATAR_ID || id > MAX_AVATAR_ID)) {
id = DEFAULT_AVATAR_ID; id = DEFAULT_AVATAR_ID;
} }
if (id != avatarId) { if (id != avatarId) {
avatarId = id; avatarId = id;
String path = "/avatars/" + String.valueOf(avatarId) + ".jpg"; String path = "/avatars/" + avatarId + ".jpg";
if (avatarId == 64) { if (avatarId == 64) {
path = "/avatars/i64.jpg"; path = "/avatars/i64.jpg";
} else if (avatarId >= 1000) { } else if (avatarId >= 1000) {
avatarId = avatarId - 1000; avatarId = avatarId - 1000;
path = "/avatars/special/" + String.valueOf(avatarId) + ".gif"; path = "/avatars/special/" + avatarId + ".gif";
} }
Image image = ImageHelper.getImageFromResources(path); Image image = ImageHelper.getImageFromResources(path);
Rectangle r = new Rectangle(80, 80); Rectangle r = new Rectangle(80, 80);
@ -364,15 +392,41 @@ public class PlayerPanelExt extends javax.swing.JPanel {
} }
protected void update(ManaPoolView pool) { protected void update(ManaPoolView pool) {
setTextForLabel(manaLabels.get("B"), pool.getBlack(), false); for (Map.Entry<JLabel, ManaType> mana : manaLabels.entrySet()) {
setTextForLabel(manaLabels.get("R"), pool.getRed(), false); switch (mana.getValue()) {
setTextForLabel(manaLabels.get("W"), pool.getWhite(), false); case BLACK:
setTextForLabel(manaLabels.get("G"), pool.getGreen(), false); setTextForLabel(mana.getKey(), pool.getBlack(), false, activeValueColor);
setTextForLabel(manaLabels.get("U"), pool.getBlue(), false); break;
setTextForLabel(manaLabels.get("X"), pool.getColorless(), false); case RED:
setTextForLabel(mana.getKey(), pool.getRed(), false, activeValueColor);
break;
case WHITE:
setTextForLabel(mana.getKey(), pool.getWhite(), false, activeValueColor);
break;
case GREEN:
setTextForLabel(mana.getKey(), pool.getGreen(), false, activeValueColor);
break;
case BLUE:
setTextForLabel(mana.getKey(), pool.getBlue(), false, activeValueColor);
break;
case COLORLESS:
setTextForLabel(mana.getKey(), pool.getColorless(), false, activeValueColor);
break;
}
//HoverButton btn = manaButtons.get(mana.getKey());
//mana.getKey().setOpaque(true);
//mana.getKey().setBackground(Color.green);
}
} }
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() { private void initComponents() {
panelBackground = new MageRoundPane(); panelBackground = new MageRoundPane();
@ -387,6 +441,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
energyLabel = new JLabel(); energyLabel = new JLabel();
experienceLabel = new JLabel(); experienceLabel = new JLabel();
graveLabel = new JLabel(); graveLabel = new JLabel();
commandLabel = new JLabel();
libraryLabel = new JLabel(); libraryLabel = new JLabel();
setOpaque(false); setOpaque(false);
@ -482,6 +537,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
cheat.addActionListener(e -> btnCheatActionPerformed(e)); cheat.addActionListener(e -> btnCheatActionPerformed(e));
zonesPanel = new JPanel(); zonesPanel = new JPanel();
//zonesPanel.setBorder(BorderFactory.createLineBorder(Color.red));
zonesPanel.setPreferredSize(new Dimension(100, 60)); zonesPanel.setPreferredSize(new Dimension(100, 60));
zonesPanel.setSize(100, 60); zonesPanel.setSize(100, 60);
zonesPanel.setLayout(null); zonesPanel.setLayout(null);
@ -491,13 +547,17 @@ public class PlayerPanelExt extends javax.swing.JPanel {
r = new Rectangle(21, 21); r = new Rectangle(21, 21);
resized = ImageHelper.getResizedImage(BufferedImageBuilder.bufferImage(image, BufferedImage.TYPE_INT_ARGB), r); resized = ImageHelper.getResizedImage(BufferedImageBuilder.bufferImage(image, BufferedImage.TYPE_INT_ARGB), r);
commandZone = new HoverButton(null, resized, resized, resized, r); commandZone = new HoverButton(null, resized, resized, resized, r);
commandZone.setToolTipText("Command Zone (Commander and Emblems)"); commandZone.setToolTipText("Command Zone (Commanders, Emblems and Planes)");
commandZone.setOpaque(false); commandZone.setOpaque(false);
commandZone.setObserver(() -> btnCommandZoneActionPerformed(null)); commandZone.setObserver(() -> btnCommandZoneActionPerformed(null));
commandZone.setBounds(5, 0, 21, 21); commandZone.setBounds(3, 0, 21, 21);
zonesPanel.add(commandZone); zonesPanel.add(commandZone);
cheat.setBounds(28, 0, 25, 21); commandLabel.setToolTipText("Command zone");
commandLabel.setBounds(25, 0, 21, 21);
zonesPanel.add(commandLabel);
cheat.setBounds(40, 2, 25, 21);
zonesPanel.add(cheat); zonesPanel.add(cheat);
energyExperiencePanel = new JPanel(); energyExperiencePanel = new JPanel();
@ -533,72 +593,99 @@ public class PlayerPanelExt extends javax.swing.JPanel {
btnPlayer.addActionListener(e -> SessionHandler.sendPlayerUUID(gameId, playerId)); btnPlayer.addActionListener(e -> SessionHandler.sendPlayerUUID(gameId, playerId));
// Add mana symbols // Add mana symbols
// TODO: replace "button + label" to label on rework
/*
MouseAdapter manaMouseAdapter = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent evt) {
JLabel label = (JLabel) evt.getSource();
if (manaLabels.containsKey(label)) {
btnManaActionPerformed(manaLabels.get(label));
}
}
};
JLabel manaCountLabelW = new JLabel(); JLabel manaCountLabelW = new JLabel();
manaCountLabelW.setToolTipText("White mana"); manaCountLabelW.setToolTipText("White mana");
setTextForLabel(manaCountLabelW, 0, false); setTextForLabel(manaCountLabelW, 0, false);
manaLabels.put("W", manaCountLabelW); manaCountLabelW.setIcon(new ImageIcon(ManaSymbols.getSizedManaSymbol("W", 15)));
manaCountLabelW.addMouseListener(manaMouseAdapter);
manaLabels.put(manaCountLabelW, ManaType.WHITE);l
//*/
///*
JLabel manaCountLabelW = new JLabel();
manaCountLabelW.setToolTipText("White mana");
setTextForLabel(manaCountLabelW, 0, false);
manaLabels.put(manaCountLabelW, ManaType.WHITE);
r = new Rectangle(15, 15); r = new Rectangle(15, 15);
BufferedImage imageManaW = ManaSymbols.getSizedManaSymbol("W", 15); BufferedImage imageManaW = ManaSymbols.getSizedManaSymbol("W", 15);
HoverButton btnWhiteMana = new HoverButton(null, imageManaW, imageManaW, imageManaW, r); HoverButton btnWhiteMana = new HoverButton(null, imageManaW, imageManaW, imageManaW, r);
btnWhiteMana.setToolTipText("White mana"); btnWhiteMana.setToolTipText("White mana");
btnWhiteMana.setOpaque(false); btnWhiteMana.setOpaque(false);
btnWhiteMana.setObserver(() -> btnManaActionPerformed(ManaType.WHITE)); btnWhiteMana.setObserver(() -> btnManaActionPerformed(ManaType.WHITE));
manaButtons.put(manaCountLabelW, btnWhiteMana);
//*/
JLabel manaCountLabelU = new JLabel(); JLabel manaCountLabelU = new JLabel();
manaCountLabelU.setToolTipText("Blue mana"); manaCountLabelU.setToolTipText("Blue mana");
setTextForLabel(manaCountLabelU, 0, false); setTextForLabel(manaCountLabelU, 0, false);
manaLabels.put("U", manaCountLabelU); manaLabels.put(manaCountLabelU, ManaType.BLUE);
r = new Rectangle(15, 15); r = new Rectangle(15, 15);
BufferedImage imageManaU = ManaSymbols.getSizedManaSymbol("U", 15); BufferedImage imageManaU = ManaSymbols.getSizedManaSymbol("U", 15);
HoverButton btnBlueMana = new HoverButton(null, imageManaU, imageManaU, imageManaU, r); HoverButton btnBlueMana = new HoverButton(null, imageManaU, imageManaU, imageManaU, r);
btnBlueMana.setToolTipText("Blue mana"); btnBlueMana.setToolTipText("Blue mana");
btnBlueMana.setOpaque(false); btnBlueMana.setOpaque(false);
btnBlueMana.setObserver(() -> btnManaActionPerformed(ManaType.BLUE)); btnBlueMana.setObserver(() -> btnManaActionPerformed(ManaType.BLUE));
manaButtons.put(manaCountLabelU, btnBlueMana);
JLabel manaCountLabelB = new JLabel(); JLabel manaCountLabelB = new JLabel();
manaCountLabelB.setToolTipText("Black mana"); manaCountLabelB.setToolTipText("Black mana");
setTextForLabel(manaCountLabelB, 0, false); setTextForLabel(manaCountLabelB, 0, false);
manaLabels.put("B", manaCountLabelB); manaLabels.put(manaCountLabelB, ManaType.BLACK);
r = new Rectangle(15, 15); r = new Rectangle(15, 15);
BufferedImage imageManaB = ManaSymbols.getSizedManaSymbol("B", 15); BufferedImage imageManaB = ManaSymbols.getSizedManaSymbol("B", 15);
HoverButton btnBlackMana = new HoverButton(null, imageManaB, imageManaB, imageManaB, r); HoverButton btnBlackMana = new HoverButton(null, imageManaB, imageManaB, imageManaB, r);
btnBlackMana.setToolTipText("Black mana"); btnBlackMana.setToolTipText("Black mana");
btnBlackMana.setOpaque(false); btnBlackMana.setOpaque(false);
btnBlackMana.setObserver(() -> btnManaActionPerformed(ManaType.BLACK)); btnBlackMana.setObserver(() -> btnManaActionPerformed(ManaType.BLACK));
manaButtons.put(manaCountLabelB, btnBlackMana);
JLabel manaCountLabelR = new JLabel(); JLabel manaCountLabelR = new JLabel();
manaCountLabelR.setToolTipText("Red mana"); manaCountLabelR.setToolTipText("Red mana");
setTextForLabel(manaCountLabelR, 0, false); setTextForLabel(manaCountLabelR, 0, false);
manaLabels.put("R", manaCountLabelR); manaLabels.put(manaCountLabelR, ManaType.RED);
r = new Rectangle(15, 15); r = new Rectangle(15, 15);
BufferedImage imageManaR = ManaSymbols.getSizedManaSymbol("R", 15); BufferedImage imageManaR = ManaSymbols.getSizedManaSymbol("R", 15);
HoverButton btnRedMana = new HoverButton(null, imageManaR, imageManaR, imageManaR, r); HoverButton btnRedMana = new HoverButton(null, imageManaR, imageManaR, imageManaR, r);
btnRedMana.setToolTipText("Red mana"); btnRedMana.setToolTipText("Red mana");
btnRedMana.setOpaque(false); btnRedMana.setOpaque(false);
btnRedMana.setObserver(() -> btnManaActionPerformed(ManaType.RED)); btnRedMana.setObserver(() -> btnManaActionPerformed(ManaType.RED));
manaButtons.put(manaCountLabelR, btnRedMana);
JLabel manaCountLabelG = new JLabel(); JLabel manaCountLabelG = new JLabel();
manaCountLabelG.setToolTipText("Green mana"); manaCountLabelG.setToolTipText("Green mana");
setTextForLabel(manaCountLabelG, 0, false); setTextForLabel(manaCountLabelG, 0, false);
manaLabels.put("G", manaCountLabelG); manaLabels.put(manaCountLabelG, ManaType.GREEN);
r = new Rectangle(15, 15); r = new Rectangle(15, 15);
BufferedImage imageManaG = ManaSymbols.getSizedManaSymbol("G", 15); BufferedImage imageManaG = ManaSymbols.getSizedManaSymbol("G", 15);
HoverButton btnGreenMana = new HoverButton(null, imageManaG, imageManaG, imageManaG, r); HoverButton btnGreenMana = new HoverButton(null, imageManaG, imageManaG, imageManaG, r);
btnGreenMana.setToolTipText("Green mana"); btnGreenMana.setToolTipText("Green mana");
btnGreenMana.setOpaque(false); btnGreenMana.setOpaque(false);
btnGreenMana.setObserver(() -> btnManaActionPerformed(ManaType.GREEN)); btnGreenMana.setObserver(() -> btnManaActionPerformed(ManaType.GREEN));
manaButtons.put(manaCountLabelG, btnGreenMana);
JLabel manaCountLabelX = new JLabel(); JLabel manaCountLabelX = new JLabel();
manaCountLabelX.setToolTipText("Colorless mana"); manaCountLabelX.setToolTipText("Colorless mana");
setTextForLabel(manaCountLabelX, 0, false); setTextForLabel(manaCountLabelX, 0, false);
manaLabels.put("X", manaCountLabelX); manaLabels.put(manaCountLabelX, ManaType.COLORLESS);
r = new Rectangle(15, 15); r = new Rectangle(15, 15);
BufferedImage imageManaX = ManaSymbols.getSizedManaSymbol("C", 15); BufferedImage imageManaX = ManaSymbols.getSizedManaSymbol("C", 15);
HoverButton btnColorlessMana = new HoverButton(null, imageManaX, imageManaX, imageManaX, r); HoverButton btnColorlessMana = new HoverButton(null, imageManaX, imageManaX, imageManaX, r);
btnColorlessMana.setToolTipText("Colorless mana"); btnColorlessMana.setToolTipText("Colorless mana");
btnColorlessMana.setOpaque(false); btnColorlessMana.setOpaque(false);
btnColorlessMana.setObserver(() -> btnManaActionPerformed(ManaType.COLORLESS)); btnColorlessMana.setObserver(() -> btnManaActionPerformed(ManaType.COLORLESS));
manaButtons.put(manaCountLabelX, btnColorlessMana);
GroupLayout gl_panelBackground = new GroupLayout(panelBackground); GroupLayout gl_panelBackground = new GroupLayout(panelBackground);
gl_panelBackground.setHorizontalGroup( gl_panelBackground.setHorizontalGroup(
@ -674,9 +761,6 @@ public class PlayerPanelExt extends javax.swing.JPanel {
.addGroup(gl_panelBackground.createSequentialGroup() .addGroup(gl_panelBackground.createSequentialGroup()
.addGap(40) .addGap(40)
.addComponent(experienceLabel, GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE)) .addComponent(experienceLabel, GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE))
/*.addGroup(gl_panelBackground.createSequentialGroup()
.addGap(18)
.addComponent(cheat, GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE))*/
.addGroup(gl_panelBackground.createSequentialGroup() .addGroup(gl_panelBackground.createSequentialGroup()
.addGap(18) .addGap(18)
.addComponent(exileZone, GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE) .addComponent(exileZone, GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE)
@ -776,9 +860,6 @@ public class PlayerPanelExt extends javax.swing.JPanel {
.addGap(31) .addGap(31)
.addComponent(manaCountLabelG, GroupLayout.PREFERRED_SIZE, 30, GroupLayout.PREFERRED_SIZE)) .addComponent(manaCountLabelG, GroupLayout.PREFERRED_SIZE, 30, GroupLayout.PREFERRED_SIZE))
.addComponent(experienceLabel, GroupLayout.PREFERRED_SIZE, 20, GroupLayout.PREFERRED_SIZE) .addComponent(experienceLabel, GroupLayout.PREFERRED_SIZE, 20, GroupLayout.PREFERRED_SIZE)
/*.addGroup(gl_panelBackground.createSequentialGroup()
.addGap(76)
.addComponent(cheat, GroupLayout.PREFERRED_SIZE, 21, GroupLayout.PREFERRED_SIZE))*/
.addGroup(gl_panelBackground.createSequentialGroup() .addGroup(gl_panelBackground.createSequentialGroup()
.addGap(76) .addGap(76)
.addComponent(exileZone, GroupLayout.PREFERRED_SIZE, 21, GroupLayout.PREFERRED_SIZE) .addComponent(exileZone, GroupLayout.PREFERRED_SIZE, 21, GroupLayout.PREFERRED_SIZE)
@ -812,7 +893,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
); );
setLayout(groupLayout); setLayout(groupLayout);
} }// </editor-fold>//GEN-END:initComponents
protected void sizePlayerPanel(boolean smallMode) { protected void sizePlayerPanel(boolean smallMode) {
if (smallMode) { if (smallMode) {
@ -850,7 +931,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
DialogManager.getManager(gameId).showExileDialog(player.getExile(), bigCard, gameId); DialogManager.getManager(gameId).showExileDialog(player.getExile(), bigCard, gameId);
} }
private void btnCheatActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCheatActionPerformed private void btnCheatActionPerformed(java.awt.event.ActionEvent evt) {
DckDeckImporter deckImporter = new DckDeckImporter(); DckDeckImporter deckImporter = new DckDeckImporter();
SessionHandler.cheat(gameId, playerId, deckImporter.importDeck("cheat.dck")); SessionHandler.cheat(gameId, playerId, deckImporter.importDeck("cheat.dck"));
} }
@ -875,6 +956,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
} }
} }
// Variables declaration - do not modify//GEN-BEGIN:variables
private HoverButton avatar; private HoverButton avatar;
private JButton btnPlayer; private JButton btnPlayer;
private ImagePanel life; private ImagePanel life;
@ -895,16 +977,20 @@ public class PlayerPanelExt extends javax.swing.JPanel {
private JLabel energyLabel; private JLabel energyLabel;
private JLabel experienceLabel; private JLabel experienceLabel;
private JLabel graveLabel; private JLabel graveLabel;
private JLabel commandLabel;
private JLabel exileLabel; private JLabel exileLabel;
private boolean changedFontLibrary;
private boolean changedFontLife;
private boolean changedFontGrave;
private boolean changedFontExile;
private JPanel zonesPanel; private JPanel zonesPanel;
private JPanel energyExperiencePanel; private JPanel energyExperiencePanel;
private HoverButton exileZone; private HoverButton exileZone;
private HoverButton commandZone; private HoverButton commandZone;
// End of variables declaration//GEN-END:variables
private boolean changedFontLibrary;
private boolean changedFontLife;
private boolean changedFontGrave;
private boolean changedFontExile;
private final Map<JLabel, ManaType> manaLabels = new HashMap<>();
private final Map<JLabel, HoverButton> manaButtons = new HashMap<>();
private final Map<String, JLabel> manaLabels = new HashMap<>();
} }

View file

@ -274,7 +274,7 @@ public class CallbackClientImpl implements CallbackClient {
if (panel != null) { if (panel != null) {
appendJsonEvent("GAME_UPDATE", callback.getObjectId(), callback.getData()); appendJsonEvent("GAME_UPDATE", callback.getObjectId(), callback.getData());
panel.updateGame((GameView) callback.getData()); panel.updateGame((GameView) callback.getData(), true, null, null); // update after undo
} }
break; break;
} }

View file

@ -47,7 +47,7 @@
<Component id="btnQuickStartDuel" min="-2" max="-2" attributes="0"/> <Component id="btnQuickStartDuel" min="-2" max="-2" attributes="0"/>
<Component id="btnQuickStartCommander" min="-2" max="-2" attributes="0"/> <Component id="btnQuickStartCommander" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace pref="734" max="32767" attributes="0"/> <EmptySpace pref="667" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -290,7 +290,7 @@
<Property name="verticalTextPosition" type="int" value="3"/> <Property name="verticalTextPosition" type="int" value="3"/>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnRatedbtnFilterActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFilterActionPerformed"/>
</Events> </Events>
</Component> </Component>
<Component class="javax.swing.JToggleButton" name="btnUnrated"> <Component class="javax.swing.JToggleButton" name="btnUnrated">
@ -307,7 +307,7 @@
<Property name="verticalTextPosition" type="int" value="3"/> <Property name="verticalTextPosition" type="int" value="3"/>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnUnratedbtnFilterActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFilterActionPerformed"/>
</Events> </Events>
</Component> </Component>
</SubComponents> </SubComponents>
@ -366,6 +366,20 @@
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFilterActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFilterActionPerformed"/>
</Events> </Events>
</Component>
<Component class="javax.swing.JToggleButton" name="btnFormatPioneer">
<Properties>
<Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" value="Pioneer"/>
<Property name="toolTipText" type="java.lang.String" value="Pioneer format."/>
<Property name="focusPainted" type="boolean" value="false"/>
<Property name="focusable" type="boolean" value="false"/>
<Property name="requestFocusEnabled" type="boolean" value="false"/>
<Property name="verifyInputWhenFocusTarget" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFilterActionPerformed"/>
</Events>
</Component> </Component>
<Component class="javax.swing.JToggleButton" name="btnFormatLegacy"> <Component class="javax.swing.JToggleButton" name="btnFormatLegacy">
<Properties> <Properties>
@ -396,7 +410,7 @@
<Property name="verticalTextPosition" type="int" value="3"/> <Property name="verticalTextPosition" type="int" value="3"/>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFormatVintageActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFilterActionPerformed"/>
</Events> </Events>
</Component> </Component>
<Component class="javax.swing.JToggleButton" name="btnFormatPremodern"> <Component class="javax.swing.JToggleButton" name="btnFormatPremodern">
@ -412,7 +426,7 @@
<Property name="verticalTextPosition" type="int" value="3"/> <Property name="verticalTextPosition" type="int" value="3"/>
</Properties> </Properties>
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFormatPremodernActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFilterActionPerformed"/>
</Events> </Events>
</Component> </Component>
<Component class="javax.swing.JToolBar$Separator" name="jSeparator3"> <Component class="javax.swing.JToolBar$Separator" name="jSeparator3">
@ -433,6 +447,22 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFilterActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFilterActionPerformed"/>
</Events> </Events>
</Component> </Component>
<Component class="javax.swing.JToggleButton" name="btnFormatOathbreaker">
<Properties>
<Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" value="Oathbreaker"/>
<Property name="toolTipText" type="java.lang.String" value="Oathbreaker format."/>
<Property name="focusPainted" type="boolean" value="false"/>
<Property name="focusable" type="boolean" value="false"/>
<Property name="horizontalTextPosition" type="int" value="0"/>
<Property name="requestFocusEnabled" type="boolean" value="false"/>
<Property name="verifyInputWhenFocusTarget" type="boolean" value="false"/>
<Property name="verticalTextPosition" type="int" value="3"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFilterActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JToggleButton" name="btnFormatTinyLeader"> <Component class="javax.swing.JToggleButton" name="btnFormatTinyLeader">
<Properties> <Properties>
<Property name="selected" type="boolean" value="true"/> <Property name="selected" type="boolean" value="true"/>

View file

@ -329,11 +329,11 @@ public class TablesPanel extends javax.swing.JPanel {
chatPanelMain.getUserChatPanel().setBorder(null); chatPanelMain.getUserChatPanel().setBorder(null);
chatPanelMain.getUserChatPanel().setChatType(ChatPanelBasic.ChatType.TABLES); chatPanelMain.getUserChatPanel().setChatType(ChatPanelBasic.ChatType.TABLES);
// 4. BUTTONS // 4. BUTTONS (add new buttons to the end of the list -- if not then users lost their filter settings)
filterButtons = new JToggleButton[]{btnStateWaiting, btnStateActive, btnStateFinished, filterButtons = new JToggleButton[]{btnStateWaiting, btnStateActive, btnStateFinished,
btnTypeMatch, btnTypeTourneyConstructed, btnTypeTourneyLimited, btnTypeMatch, btnTypeTourneyConstructed, btnTypeTourneyLimited,
btnFormatBlock, btnFormatStandard, btnFormatModern, btnFormatLegacy, btnFormatVintage, btnFormatPremodern, btnFormatCommander, btnFormatTinyLeader, btnFormatLimited, btnFormatOther, btnFormatBlock, btnFormatStandard, btnFormatModern, btnFormatLegacy, btnFormatVintage, btnFormatPremodern, btnFormatCommander, btnFormatTinyLeader, btnFormatLimited, btnFormatOther,
btnSkillBeginner, btnSkillCasual, btnSkillSerious, btnRated, btnUnrated, btnOpen, btnPassword}; btnSkillBeginner, btnSkillCasual, btnSkillSerious, btnRated, btnUnrated, btnOpen, btnPassword, btnFormatOathbreaker, btnFormatPioneer};
JComponent[] components = new JComponent[]{chatPanelMain, jSplitPane1, jScrollPaneTablesActive, jScrollPaneTablesFinished, jPanelTop, jPanelTables}; JComponent[] components = new JComponent[]{chatPanelMain, jSplitPane1, jScrollPaneTablesActive, jScrollPaneTablesFinished, jPanelTop, jPanelTables};
for (JComponent component : components) { for (JComponent component : components) {
@ -802,6 +802,9 @@ public class TablesPanel extends javax.swing.JPanel {
if (btnFormatModern.isSelected()) { if (btnFormatModern.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Constructed - Modern", TablesTableModel.COLUMN_DECK_TYPE)); formatFilterList.add(RowFilter.regexFilter("^Constructed - Modern", TablesTableModel.COLUMN_DECK_TYPE));
} }
if (btnFormatPioneer.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Constructed - Pioneer", TablesTableModel.COLUMN_DECK_TYPE));
}
if (btnFormatLegacy.isSelected()) { if (btnFormatLegacy.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Constructed - Legacy", TablesTableModel.COLUMN_DECK_TYPE)); formatFilterList.add(RowFilter.regexFilter("^Constructed - Legacy", TablesTableModel.COLUMN_DECK_TYPE));
} }
@ -812,11 +815,14 @@ public class TablesPanel extends javax.swing.JPanel {
formatFilterList.add(RowFilter.regexFilter("^Constructed - Premodern", TablesTableModel.COLUMN_DECK_TYPE)); formatFilterList.add(RowFilter.regexFilter("^Constructed - Premodern", TablesTableModel.COLUMN_DECK_TYPE));
} }
if (btnFormatCommander.isSelected()) { if (btnFormatCommander.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Commander|^Duel Commander|^Penny Dreadful Commander|^Freeform Commander|^MTGO 1v1 Commander|^Duel Brawl|^Brawl", TablesTableModel.COLUMN_DECK_TYPE)); formatFilterList.add(RowFilter.regexFilter("^Commander|^Duel Commander|^Centurion Commander|^Penny Dreadful Commander|^Freeform Commander|^MTGO 1v1 Commander|^Duel Brawl|^Brawl", TablesTableModel.COLUMN_DECK_TYPE));
} }
if (btnFormatTinyLeader.isSelected()) { if (btnFormatTinyLeader.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Tiny", TablesTableModel.COLUMN_DECK_TYPE)); formatFilterList.add(RowFilter.regexFilter("^Tiny", TablesTableModel.COLUMN_DECK_TYPE));
} }
if (btnFormatOathbreaker.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Oathbreaker", TablesTableModel.COLUMN_DECK_TYPE));
}
if (btnFormatLimited.isSelected()) { if (btnFormatLimited.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Limited", TablesTableModel.COLUMN_DECK_TYPE)); formatFilterList.add(RowFilter.regexFilter("^Limited", TablesTableModel.COLUMN_DECK_TYPE));
} }
@ -962,11 +968,13 @@ public class TablesPanel extends javax.swing.JPanel {
btnFormatBlock = new javax.swing.JToggleButton(); btnFormatBlock = new javax.swing.JToggleButton();
btnFormatStandard = new javax.swing.JToggleButton(); btnFormatStandard = new javax.swing.JToggleButton();
btnFormatModern = new javax.swing.JToggleButton(); btnFormatModern = new javax.swing.JToggleButton();
btnFormatPioneer = new javax.swing.JToggleButton();
btnFormatLegacy = new javax.swing.JToggleButton(); btnFormatLegacy = new javax.swing.JToggleButton();
btnFormatVintage = new javax.swing.JToggleButton(); btnFormatVintage = new javax.swing.JToggleButton();
btnFormatPremodern = new javax.swing.JToggleButton(); btnFormatPremodern = new javax.swing.JToggleButton();
jSeparator3 = new javax.swing.JToolBar.Separator(); jSeparator3 = new javax.swing.JToolBar.Separator();
btnFormatCommander = new javax.swing.JToggleButton(); btnFormatCommander = new javax.swing.JToggleButton();
btnFormatOathbreaker = new javax.swing.JToggleButton();
btnFormatTinyLeader = new javax.swing.JToggleButton(); btnFormatTinyLeader = new javax.swing.JToggleButton();
jSeparator2 = new javax.swing.JToolBar.Separator(); jSeparator2 = new javax.swing.JToolBar.Separator();
btnFormatLimited = new javax.swing.JToggleButton(); btnFormatLimited = new javax.swing.JToggleButton();
@ -1180,7 +1188,7 @@ public class TablesPanel extends javax.swing.JPanel {
btnRated.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); btnRated.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
btnRated.addActionListener(new java.awt.event.ActionListener() { btnRated.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
btnRatedbtnFilterActionPerformed(evt); btnFilterActionPerformed(evt);
} }
}); });
filterBar1.add(btnRated); filterBar1.add(btnRated);
@ -1197,7 +1205,7 @@ public class TablesPanel extends javax.swing.JPanel {
btnUnrated.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); btnUnrated.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
btnUnrated.addActionListener(new java.awt.event.ActionListener() { btnUnrated.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
btnUnratedbtnFilterActionPerformed(evt); btnFilterActionPerformed(evt);
} }
}); });
filterBar1.add(btnUnrated); filterBar1.add(btnUnrated);
@ -1252,6 +1260,20 @@ public class TablesPanel extends javax.swing.JPanel {
}); });
filterBar2.add(btnFormatModern); filterBar2.add(btnFormatModern);
btnFormatPioneer.setSelected(true);
btnFormatPioneer.setText("Pioneer");
btnFormatPioneer.setToolTipText("Pioneer format.");
btnFormatPioneer.setFocusPainted(false);
btnFormatPioneer.setFocusable(false);
btnFormatPioneer.setRequestFocusEnabled(false);
btnFormatPioneer.setVerifyInputWhenFocusTarget(false);
btnFormatPioneer.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnFilterActionPerformed(evt);
}
});
filterBar2.add(btnFormatPioneer);
btnFormatLegacy.setSelected(true); btnFormatLegacy.setSelected(true);
btnFormatLegacy.setText("Legacy"); btnFormatLegacy.setText("Legacy");
btnFormatLegacy.setToolTipText("Legacy format."); btnFormatLegacy.setToolTipText("Legacy format.");
@ -1279,7 +1301,7 @@ public class TablesPanel extends javax.swing.JPanel {
btnFormatVintage.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); btnFormatVintage.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
btnFormatVintage.addActionListener(new java.awt.event.ActionListener() { btnFormatVintage.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
btnFormatVintageActionPerformed(evt); btnFilterActionPerformed(evt);
} }
}); });
filterBar2.add(btnFormatVintage); filterBar2.add(btnFormatVintage);
@ -1295,7 +1317,7 @@ public class TablesPanel extends javax.swing.JPanel {
btnFormatPremodern.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); btnFormatPremodern.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
btnFormatPremodern.addActionListener(new java.awt.event.ActionListener() { btnFormatPremodern.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
btnFormatPremodernActionPerformed(evt); btnFilterActionPerformed(evt);
} }
}); });
filterBar2.add(btnFormatPremodern); filterBar2.add(btnFormatPremodern);
@ -1317,6 +1339,22 @@ public class TablesPanel extends javax.swing.JPanel {
}); });
filterBar2.add(btnFormatCommander); filterBar2.add(btnFormatCommander);
btnFormatOathbreaker.setSelected(true);
btnFormatOathbreaker.setText("Oathbreaker");
btnFormatOathbreaker.setToolTipText("Oathbreaker format.");
btnFormatOathbreaker.setFocusPainted(false);
btnFormatOathbreaker.setFocusable(false);
btnFormatOathbreaker.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
btnFormatOathbreaker.setRequestFocusEnabled(false);
btnFormatOathbreaker.setVerifyInputWhenFocusTarget(false);
btnFormatOathbreaker.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
btnFormatOathbreaker.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnFilterActionPerformed(evt);
}
});
filterBar2.add(btnFormatOathbreaker);
btnFormatTinyLeader.setSelected(true); btnFormatTinyLeader.setSelected(true);
btnFormatTinyLeader.setText("Tiny Leader"); btnFormatTinyLeader.setText("Tiny Leader");
btnFormatTinyLeader.setToolTipText("Tiny Leader format."); btnFormatTinyLeader.setToolTipText("Tiny Leader format.");
@ -1432,7 +1470,7 @@ public class TablesPanel extends javax.swing.JPanel {
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(btnQuickStartDuel) .addComponent(btnQuickStartDuel)
.addComponent(btnQuickStartCommander)) .addComponent(btnQuickStartCommander))
.addContainerGap(734, Short.MAX_VALUE)) .addContainerGap(667, Short.MAX_VALUE))
); );
jPanelTopLayout.setVerticalGroup( jPanelTopLayout.setVerticalGroup(
jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -1631,22 +1669,6 @@ public class TablesPanel extends javax.swing.JPanel {
this.startUpdateTasks(true); this.startUpdateTasks(true);
}//GEN-LAST:event_btnStateFinishedActionPerformed }//GEN-LAST:event_btnStateFinishedActionPerformed
private void btnRatedbtnFilterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRatedbtnFilterActionPerformed
setTableFilter();
}//GEN-LAST:event_btnRatedbtnFilterActionPerformed
private void btnUnratedbtnFilterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnUnratedbtnFilterActionPerformed
setTableFilter();
}//GEN-LAST:event_btnUnratedbtnFilterActionPerformed
private void btnFormatPremodernActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFormatPremodernActionPerformed
setTableFilter();
}//GEN-LAST:event_btnFormatPremodernActionPerformed
private void btnFormatVintageActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFormatVintageActionPerformed
setTableFilter();
}//GEN-LAST:event_btnFormatVintageActionPerformed
private void buttonWhatsNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonWhatsNewActionPerformed private void buttonWhatsNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonWhatsNewActionPerformed
MageFrame.getInstance().showWhatsNewDialog(true); MageFrame.getInstance().showWhatsNewDialog(true);
}//GEN-LAST:event_buttonWhatsNewActionPerformed }//GEN-LAST:event_buttonWhatsNewActionPerformed
@ -1666,6 +1688,8 @@ public class TablesPanel extends javax.swing.JPanel {
private javax.swing.JToggleButton btnFormatLegacy; private javax.swing.JToggleButton btnFormatLegacy;
private javax.swing.JToggleButton btnFormatLimited; private javax.swing.JToggleButton btnFormatLimited;
private javax.swing.JToggleButton btnFormatModern; private javax.swing.JToggleButton btnFormatModern;
private javax.swing.JToggleButton btnFormatPioneer;
private javax.swing.JToggleButton btnFormatOathbreaker;
private javax.swing.JToggleButton btnFormatOther; private javax.swing.JToggleButton btnFormatOther;
private javax.swing.JToggleButton btnFormatPremodern; private javax.swing.JToggleButton btnFormatPremodern;
private javax.swing.JToggleButton btnFormatStandard; private javax.swing.JToggleButton btnFormatStandard;

View file

@ -38,6 +38,8 @@ public class CombatDialog extends MageDialog {
JPanel contentPane = new JPanel() { JPanel contentPane = new JPanel() {
private static final long serialVersionUID = -8283955788355547309L; private static final long serialVersionUID = -8283955788355547309L;
@Override
public void paintComponent(Graphics g) { public void paintComponent(Graphics g) {
g.setColor(new Color(50, 50, 50, 100)); g.setColor(new Color(50, 50, 50, 100));
g.fillRect(0, 0, getWidth(), getHeight()); g.fillRect(0, 0, getWidth(), getHeight());

View file

@ -1,15 +1,14 @@
package mage.client.util; package mage.client.util;
import java.util.List;
import java.util.Map;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.repository.CardInfo; import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository; import mage.cards.repository.CardRepository;
import mage.view.*; import mage.view.*;
import java.util.List;
import java.util.Map;
/** /**
*
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public final class CardsViewUtil { public final class CardsViewUtil {
@ -21,7 +20,7 @@ public final class CardsViewUtil {
CardInfo cardInfo = CardRepository.instance.findCard(simple.getExpansionSetCode(), simple.getCardNumber()); CardInfo cardInfo = CardRepository.instance.findCard(simple.getExpansionSetCode(), simple.getCardNumber());
Card card = cardInfo != null ? cardInfo.getMockCard() : null; Card card = cardInfo != null ? cardInfo.getMockCard() : null;
if (card != null) { if (card != null) {
cards.put(simple.getId(), new CardView(card, simple.getId())); cards.put(simple.getId(), new CardView(card, simple));
} }
} }
@ -40,7 +39,7 @@ public final class CardsViewUtil {
loadedCards.put(key, card); loadedCards.put(key, card);
} }
if (card != null) { if (card != null) {
cards.put(simple.getId(), new CardView(card, simple.getId())); cards.put(simple.getId(), new CardView(card, simple));
} }
} }
@ -55,9 +54,8 @@ public final class CardsViewUtil {
CardView cardView = new CardView((EmblemView) commandObject); CardView cardView = new CardView((EmblemView) commandObject);
cards.put(commandObject.getId(), cardView); cards.put(commandObject.getId(), cardView);
} else if (commandObject instanceof PlaneView) { } else if (commandObject instanceof PlaneView) {
CardView cardView = null; CardView cardView = new CardView((PlaneView) commandObject);
cardView = new CardView((PlaneView) commandObject); cards.put(commandObject.getId(), cardView);
cards.put(commandObject.getId(), cardView);
} else if (commandObject instanceof CommanderView) { } else if (commandObject instanceof CommanderView) {
cards.put(commandObject.getId(), (CommanderView) commandObject); cards.put(commandObject.getId(), (CommanderView) commandObject);
} }

View file

@ -119,6 +119,8 @@ public class MusicPlayer {
} }
@Override
public void run() { public void run() {
try { try {
TimeUnit.MILLISECONDS.sleep(100); TimeUnit.MILLISECONDS.sleep(100);
@ -146,6 +148,8 @@ public class MusicPlayer {
final byte[] tempBuffer = new byte[320]; final byte[] tempBuffer = new byte[320];
@Override
public void run() { public void run() {
try { try {
sourceDataLine.flush(); sourceDataLine.flush();

View file

@ -32,6 +32,8 @@ public class Arrow extends JPanel {
setOpacity(0.6f); setOpacity(0.6f);
} }
@Override
protected void paintComponent(Graphics g) { protected void paintComponent(Graphics g) {
super.paintComponent(g); super.paintComponent(g);
float ex = endX - startX; float ex = endX - startX;

View file

@ -112,10 +112,11 @@ public class ArrowBuilder {
* Removes all arrows from the screen. * Removes all arrows from the screen.
*/ */
public void removeAllArrows(UUID gameId) { public void removeAllArrows(UUID gameId) {
if (map.containsKey(gameId)) { synchronized (map) {
Map<Type, List<Arrow>> innerMap = map.get(gameId); if (map.containsKey(gameId)) {
JPanel p = getArrowsPanel(gameId); Map<Type, List<Arrow>> innerMap = map.get(gameId);
synchronized (map) { JPanel p = getArrowsPanel(gameId);
if (p != null && p.getComponentCount() > 0) { if (p != null && p.getComponentCount() > 0) {
p.removeAll(); p.removeAll();
p.revalidate(); p.revalidate();

View file

@ -194,7 +194,7 @@ public class CountryComboBox extends JComboBox {
{"Portugal", "pt"}, {"Portugal", "pt"},
{"Puerto Rico", "pr"}, {"Puerto Rico", "pr"},
{"Qatar", "qa"}, {"Qatar", "qa"},
{"Réunion", "re"}, {"Reunion", "re"},
{"Romania", "ro"}, {"Romania", "ro"},
{"Russian Federation", "ru"}, {"Russian Federation", "ru"},
{"Rwanda", "rw"}, {"Rwanda", "rw"},
@ -228,7 +228,7 @@ public class CountryComboBox extends JComboBox {
{"Sweden", "se"}, {"Sweden", "se"},
{"Switzerland", "ch"}, {"Switzerland", "ch"},
{"Syrian Arab Republic", "sy"}, {"Syrian Arab Republic", "sy"},
{"Taiwan, Province of China", "tw"}, {"Taiwan", "tw"},
{"Tajikistan", "tj"}, {"Tajikistan", "tj"},
{"Tanzania, United Republic of", "tz"}, {"Tanzania, United Republic of", "tz"},
{"Thailand", "th"}, {"Thailand", "th"},

View file

@ -20,6 +20,7 @@ public final class ConstructedFormats {
public static final String STANDARD = "- Standard"; public static final String STANDARD = "- Standard";
public static final String EXTENDED = "- Extended"; public static final String EXTENDED = "- Extended";
public static final String FRONTIER = "- Frontier"; public static final String FRONTIER = "- Frontier";
public static final String PIONEER = "- Pioneer";
public static final String MODERN = "- Modern"; public static final String MODERN = "- Modern";
public static final String VINTAGE_LEGACY = "- Vintage / Legacy"; public static final String VINTAGE_LEGACY = "- Vintage / Legacy";
public static final String JOKE = "- Joke Sets"; public static final String JOKE = "- Joke Sets";
@ -27,9 +28,10 @@ public final class ConstructedFormats {
public static final Standard STANDARD_CARDS = new Standard(); public static final Standard STANDARD_CARDS = new Standard();
// Attention -Month is 0 Based so Feb = 1 for example. // // Attention -Month is 0 Based so Feb = 1 for example. //
private static final Date extendedDate = new GregorianCalendar(2009, 7, 20).getTime(); private static final Date extendedDate = new GregorianCalendar(2009, Calendar.AUGUST, 20).getTime();
private static final Date frontierDate = new GregorianCalendar(2014, 6, 17).getTime(); private static final Date frontierDate = new GregorianCalendar(2014, Calendar.JULY, 17).getTime();
private static final Date modernDate = new GregorianCalendar(2003, 6, 20).getTime(); private static final Date pioneerDate = new GregorianCalendar(2012, Calendar.NOVEMBER, 5).getTime();
private static final Date modernDate = new GregorianCalendar(2003, Calendar.JULY, 20).getTime();
// for all sets just return empty list // for all sets just return empty list
private static final List<String> all = new ArrayList<>(); private static final List<String> all = new ArrayList<>();
@ -82,6 +84,7 @@ public final class ConstructedFormats {
underlyingSetCodesPerFormat.put(STANDARD, new ArrayList<>()); underlyingSetCodesPerFormat.put(STANDARD, new ArrayList<>());
underlyingSetCodesPerFormat.put(EXTENDED, new ArrayList<>()); underlyingSetCodesPerFormat.put(EXTENDED, new ArrayList<>());
underlyingSetCodesPerFormat.put(FRONTIER, new ArrayList<>()); underlyingSetCodesPerFormat.put(FRONTIER, new ArrayList<>());
underlyingSetCodesPerFormat.put(PIONEER, new ArrayList<>());
underlyingSetCodesPerFormat.put(MODERN, new ArrayList<>()); underlyingSetCodesPerFormat.put(MODERN, new ArrayList<>());
underlyingSetCodesPerFormat.put(VINTAGE_LEGACY, new ArrayList<>()); underlyingSetCodesPerFormat.put(VINTAGE_LEGACY, new ArrayList<>());
underlyingSetCodesPerFormat.put(JOKE, new ArrayList<>()); underlyingSetCodesPerFormat.put(JOKE, new ArrayList<>());
@ -134,6 +137,11 @@ public final class ConstructedFormats {
underlyingSetCodesPerFormat.get(FRONTIER).add(set.getCode()); underlyingSetCodesPerFormat.get(FRONTIER).add(set.getCode());
} }
// frontier
if (set.getType().isStandardLegal() && set.getReleaseDate().after(pioneerDate)) {
underlyingSetCodesPerFormat.get(PIONEER).add(set.getCode());
}
// modern // modern
if (set.getType().isModernLegal() && set.getReleaseDate().after(modernDate)) { if (set.getType().isModernLegal() && set.getReleaseDate().after(modernDate)) {
underlyingSetCodesPerFormat.get(MODERN).add(set.getCode()); underlyingSetCodesPerFormat.get(MODERN).add(set.getCode());
@ -251,6 +259,7 @@ public final class ConstructedFormats {
formats.add(0, JOKE); formats.add(0, JOKE);
formats.add(0, VINTAGE_LEGACY); formats.add(0, VINTAGE_LEGACY);
formats.add(0, MODERN); formats.add(0, MODERN);
formats.add(0, PIONEER);
formats.add(0, FRONTIER); formats.add(0, FRONTIER);
formats.add(0, EXTENDED); formats.add(0, EXTENDED);
formats.add(0, STANDARD); formats.add(0, STANDARD);

View file

@ -0,0 +1,19 @@
package org.mage.plugins.card.dl;
import java.net.Proxy;
/**
* @author JayDi85
*/
public interface DownloadServiceInfo {
Proxy getProxy();
boolean isNeedCancel();
void incErrorCount();
void updateMessage(String text);
void showDownloadControls(boolean needToShow);
}

View file

@ -1,10 +1,12 @@
package org.mage.plugins.card.dl.sources; package org.mage.plugins.card.dl.sources;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.mage.plugins.card.dl.DownloadServiceInfo;
import org.mage.plugins.card.images.CardDownloadData; import org.mage.plugins.card.images.CardDownloadData;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
/** /**
* @author spjspj * @author spjspj
@ -57,6 +59,11 @@ public enum AltMtgOnlTokensImageSource implements CardImageSource {
return null; return null;
} }
@Override
public boolean prepareDownloadList(DownloadServiceInfo downloadServiceInfo, List<CardDownloadData> downloadList) {
return true;
}
@Override @Override
public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception {
return null; return null;

View file

@ -1,9 +1,11 @@
package org.mage.plugins.card.dl.sources; package org.mage.plugins.card.dl.sources;
import mage.client.util.CardLanguage; import mage.client.util.CardLanguage;
import org.mage.plugins.card.dl.DownloadServiceInfo;
import org.mage.plugins.card.images.CardDownloadData; import org.mage.plugins.card.images.CardDownloadData;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
/** /**
* @author North, JayDi85 * @author North, JayDi85
@ -14,6 +16,8 @@ public interface CardImageSource {
CardImageUrls generateTokenUrl(CardDownloadData card) throws Exception; CardImageUrls generateTokenUrl(CardDownloadData card) throws Exception;
boolean prepareDownloadList(DownloadServiceInfo downloadServiceInfo, List<CardDownloadData> downloadList);
String getNextHttpImageUrl(); String getNextHttpImageUrl();
String getFileForHttpImage(String httpImageUrl); String getFileForHttpImage(String httpImageUrl);

View file

@ -1,6 +1,7 @@
package org.mage.plugins.card.dl.sources; package org.mage.plugins.card.dl.sources;
import mage.cards.Sets; import mage.cards.Sets;
import org.mage.plugins.card.dl.DownloadServiceInfo;
import org.mage.plugins.card.images.CardDownloadData; import org.mage.plugins.card.images.CardDownloadData;
import javax.swing.*; import javax.swing.*;
@ -8,10 +9,8 @@ import java.awt.*;
import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.StringSelection;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.List;
import java.util.HashMap; import java.util.*;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -73,6 +72,11 @@ public enum CopyPasteImageSource implements CardImageSource {
return null; return null;
} }
@Override
public boolean prepareDownloadList(DownloadServiceInfo downloadServiceInfo, List<CardDownloadData> downloadList) {
return true;
}
@Override @Override
public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception {
if (singleLinks == null) { if (singleLinks == null) {
@ -141,7 +145,7 @@ public enum CopyPasteImageSource implements CardImageSource {
final CopyPasteImageSourceDialog dialog = new CopyPasteImageSourceDialog(); final CopyPasteImageSourceDialog dialog = new CopyPasteImageSourceDialog();
dialog.pack(); dialog.pack();
int count = 0; int count = 0;
if (viewMissingCards && missingCards.size() > 0 && singleLinks.size() == 0) { if (viewMissingCards && !missingCards.isEmpty() && singleLinks.isEmpty()) {
viewMissingCards = false; viewMissingCards = false;
String displayMissingCardsStr = "Up to the first 20 cards are:\n"; String displayMissingCardsStr = "Up to the first 20 cards are:\n";
String missingCardsStr = ""; String missingCardsStr = "";
@ -224,7 +228,7 @@ public enum CopyPasteImageSource implements CardImageSource {
public ArrayList<String> getSupportedSets() { public ArrayList<String> getSupportedSets() {
setupLinks(); setupLinks();
ArrayList<String> supportedSetsCopy = new ArrayList<>(); ArrayList<String> supportedSetsCopy = new ArrayList<>();
if (supportedSets.size() == 0) { if (supportedSets.isEmpty()) {
for (String setCode : Sets.getInstance().keySet()) { for (String setCode : Sets.getInstance().keySet()) {
supportedSets.add(setCode); supportedSets.add(setCode);
} }

View file

@ -6,12 +6,14 @@ import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import mage.cards.ExpansionSet; import mage.cards.ExpansionSet;
import mage.cards.Sets; import mage.cards.Sets;
import mage.client.constants.Constants; import mage.client.constants.Constants;
import mage.constants.Rarity; import mage.constants.Rarity;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.mage.plugins.card.dl.DownloadJob; import org.mage.plugins.card.dl.DownloadJob;
import static org.mage.plugins.card.dl.DownloadJob.fromURL; import static org.mage.plugins.card.dl.DownloadJob.fromURL;
import static org.mage.plugins.card.dl.DownloadJob.toFile; import static org.mage.plugins.card.dl.DownloadJob.toFile;
import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir; import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir;
@ -27,12 +29,12 @@ public class GathererSets implements Iterable<DownloadJob> {
boolean haveRare; boolean haveRare;
boolean haveMyth; boolean haveMyth;
private CheckResult(String ACode, ExpansionSet ASet, boolean AHaveCommon, boolean AHaveUncommon, boolean AHhaveRare, boolean AHaveMyth) { private CheckResult(String ACode, ExpansionSet ASet, boolean AHaveCommon, boolean AHaveUncommon, boolean AHaveRare, boolean AHaveMyth) {
code = ACode; code = ACode;
set = ASet; set = ASet;
haveCommon = AHaveCommon; haveCommon = AHaveCommon;
haveUncommon = AHaveUncommon; haveUncommon = AHaveUncommon;
haveRare = AHhaveRare; haveRare = AHaveRare;
haveMyth = AHaveMyth; haveMyth = AHaveMyth;
} }
} }
@ -43,63 +45,69 @@ public class GathererSets implements Iterable<DownloadJob> {
private static final Logger logger = Logger.getLogger(GathererSets.class); private static final Logger logger = Logger.getLogger(GathererSets.class);
private static final String[] symbolsBasic = {"10E", "9ED", "8ED", "7ED", "6ED", "5ED", "4ED", "3ED", "2ED", "LEB", "LEA", private static final String[] symbolsBasic = {"10E", "9ED", "8ED", "7ED", "6ED", "5ED", "4ED", "3ED", "2ED", "LEB", "LEA",
"HOP", "HOP",
"ARN", "ATQ", "LEG", "DRK", "FEM", "HML", "ARN", "ATQ", "LEG", "DRK", "FEM", "HML",
"ICE", "ALL", "CSP", "ICE", "ALL", "CSP",
"MIR", "VIS", "WTH", "MIR", "VIS", "WTH",
"TMP", "STH", "EXO", "TMP", "STH", "EXO",
"USG", "ULG", "UDS", "USG", "ULG", "UDS",
"MMQ", "NEM", "PCY", "MMQ", "NEM", "PCY",
"INV", "PLS", "APC", "INV", "PLS", "APC",
"ODY", "TOR", "JUD", "ODY", "TOR", "JUD",
"ONS", "LGN", "SCG", "ONS", "LGN", "SCG",
"MRD", "DST", "5DN", "MRD", "DST", "5DN",
"CHK", "BOK", "SOK", "CHK", "BOK", "SOK",
"RAV", "GPT", "DIS", "RAV", "GPT", "DIS",
"TSP", "TSB", "PLC", "FUT", "TSP", "TSB", "PLC", "FUT",
"LRW", "MOR", "LRW", "MOR",
"SHM", "EVE", "SHM", "EVE",
"MED", "ME2", "ME3", "ME4", "MED", "ME2", "ME3", "ME4",
"POR", "P02", "PTK", "POR", "P02", "PTK",
"ARC", "DD3EVG", "ARC", "DD3EVG",
"W16", "W17", "W16", "W17",
//"APAC" -- gatherer do not have that set, scryfall has PALP // "APAC" -- gatherer do not have that set, scryfall has PALP
//"ARENA" -- is't many set with different codes, not one // "ARENA" -- is't many set with different codes, not one
"CLASH", "CP", "DD3GVL", "DPA", "EURO", "FNMP", "GPX", "GRC", "GUR", "H17", "JR", "MBP", "MGDC", "MLP", "MPRP", "MPS-AKH", "PTC", "S00", "S99", "SUS", "SWS", "UGIN", "UGL", "V10", "V17", "WMCQ", // need to fix // "ATH" -- has cards from many sets, symbol does not exist on gatherer
"H09", "PD2", "PD3", "UNH", "CM1", "V11", "A25", "UST", "IMA", "DD2", "EVG", "DDC", "DDE", "DDD", "8EB", "9EB", "CHR" // ok // "CLASH", "CP", "DPA", "EURO", "FNMP", "GPX", "GRC", "GUR", "H17", "JR", "MBP", "MGDC", "MLP", "MPRP", "PTC", "SUS", "SWS", "WMCQ", // need to fix
// current testing "H09", "PD2", "PD3", "UNH", "CM1", "V11", "A25", "UST", "IMA", "DD2", "EVG", "DDC", "DDE", "DDD", "8EB", "9EB", "CHR", "G18", "DD3GVL", "S00", "S99", "UGL" // ok
// current testing
}; };
private static final String[] symbolsBasicWithMyth = {"M10", "M11", "M12", "M13", "M14", "M15", "ORI", private static final String[] symbolsBasicWithMyth = {"M10", "M11", "M12", "M13", "M14", "M15", "ORI",
"DDF", "DDG", "DDH", "DDI", "DDJ", "DDK", "DDL", "DDM", "DDN", "DDF", "DDG", "DDH", "DDI", "DDJ", "DDK", "DDL", "DDM", "DDN",
"DD3DVD", "DD3JVC", "DDO", "DDP", "DDQ", "DDR", "DDS", "DDT", "DDU", "DD3DVD", "DD3JVC", "DDO", "DDP", "DDQ", "DDR", "DDS", "DDT", "DDU",
"ALA", "CON", "ARB", "ALA", "CON", "ARB",
"ZEN", "WWK", "ROE", "ZEN", "WWK", "ROE",
"SOM", "MBS", "NPH", "SOM", "MBS", "NPH",
"CMD", "C13", "C14", "C15", "C16", "CMA", "CMD", "C13", "C14", "C15", "C16", "CMA",
"PC2", "PCA", "PC2", "PCA",
"ISD", "DKA", "AVR", "ISD", "DKA", "AVR",
"RTR", "GTC", "DGM", "RTR", "GTC", "DGM",
"MMA", "MM2", "EMA", "MM3", "MMA", "MM2", "EMA", "MM3",
"THS", "BNG", "JOU", "THS", "BNG", "JOU",
"CNS", "CN2", "CNS", "CN2",
"VMA", "TPR", "VMA", "TPR",
"KTK", "FRF", "DTK", "KTK", "FRF", "UGIN", "DTK",
"BFZ", "OGW", "BFZ", "OGW",
"SOI", "EMN", "SOI", "EMN",
"KLD", "AER", "KLD", "AER",
"AKH", "HOU", "AKH", "HOU",
"XLN", "C17", "XLN", "C17",
"RIX", "DOM", "M19", "RIX", "DOM", "M19",
"E01", "CM2", "E02", "E01", "CM2", "E02",
"GS1", "BBD", "C18" "GS1", "BBD", "C18",
"GNT", "UMA", "GRN",
"RNA", "WAR", "MH1",
"M20"
// "HHO", "ANA" -- do not exist on gatherer
}; };
private static final String[] symbolsOnlyMyth = { private static final String[] symbolsOnlyMyth = {
"DRB", "V09", "V12", "V13", "V14", "V15", "V16", "EXP" "DRB", "V09", "V10", "V12", "V13", "V14", "V15", "V16", "V17", "EXP", "MEDM"
// "HTR" does not exist
}; };
private static final String[] symbolsOnlySpecial = { private static final String[] symbolsOnlySpecial = {
"MPS" "MPS", "MPS-AKH"
}; };
private static final HashMap<String, String> codeReplacements = new HashMap<>(); private static final HashMap<String, String> codeReplacements = new HashMap<>();
@ -116,8 +124,10 @@ public class GathererSets implements Iterable<DownloadJob> {
codeReplacements.put("ARN", "AN"); codeReplacements.put("ARN", "AN");
codeReplacements.put("ATQ", "AQ"); codeReplacements.put("ATQ", "AQ");
codeReplacements.put("CMA", "CM1"); codeReplacements.put("CMA", "CM1");
codeReplacements.put("CHR", "CH");
codeReplacements.put("DD3DVD", "DD3_DVD"); codeReplacements.put("DD3DVD", "DD3_DVD");
codeReplacements.put("DD3EVG", "DD3_EVG"); codeReplacements.put("DD3EVG", "DD3_EVG");
codeReplacements.put("DD3GVL", "DD3_GVL");
codeReplacements.put("DD3JVC", "DD3_JVC"); codeReplacements.put("DD3JVC", "DD3_JVC");
codeReplacements.put("DRK", "DK"); codeReplacements.put("DRK", "DK");
codeReplacements.put("EXO", "EX"); codeReplacements.put("EXO", "EX");
@ -128,7 +138,9 @@ public class GathererSets implements Iterable<DownloadJob> {
codeReplacements.put("LEA", "1E"); codeReplacements.put("LEA", "1E");
codeReplacements.put("LEB", "2E"); codeReplacements.put("LEB", "2E");
codeReplacements.put("LEG", "LE"); codeReplacements.put("LEG", "LE");
codeReplacements.put("MEDM", "MPS_WAR");
codeReplacements.put("MPS", "MPS_KLD"); codeReplacements.put("MPS", "MPS_KLD");
codeReplacements.put("MPS-AKH", "MPS_AKH");
codeReplacements.put("MIR", "MI"); codeReplacements.put("MIR", "MI");
codeReplacements.put("MMQ", "MM"); codeReplacements.put("MMQ", "MM");
codeReplacements.put("NEM", "NE"); codeReplacements.put("NEM", "NE");
@ -138,16 +150,19 @@ public class GathererSets implements Iterable<DownloadJob> {
codeReplacements.put("POR", "PO"); codeReplacements.put("POR", "PO");
codeReplacements.put("P02", "P2"); codeReplacements.put("P02", "P2");
codeReplacements.put("PTK", "PK"); codeReplacements.put("PTK", "PK");
codeReplacements.put("S00", "P4");
codeReplacements.put("S99", "P3");
codeReplacements.put("STH", "ST"); codeReplacements.put("STH", "ST");
codeReplacements.put("TMP", "TE"); codeReplacements.put("TMP", "TE");
codeReplacements.put("UDS", "CG"); codeReplacements.put("UDS", "CG");
codeReplacements.put("UGIN", "FRF_UGIN");
codeReplacements.put("UGL", "UG");
codeReplacements.put("ULG", "GU"); codeReplacements.put("ULG", "GU");
codeReplacements.put("USG", "UZ"); codeReplacements.put("USG", "UZ");
codeReplacements.put("VIS", "VI"); codeReplacements.put("VIS", "VI");
codeReplacements.put("WTH", "WL"); codeReplacements.put("WTH", "WL");
codeReplacements.put("8EB", "8ED"); // inner xmage set for 8th edition codeReplacements.put("8EB", "8ED"); // inner xmage set for 8th edition
codeReplacements.put("9EB", "8ED"); // inner xmage set for 9th edition codeReplacements.put("9EB", "8ED"); // inner xmage set for 9th edition
codeReplacements.put("CHR", "CH");
} }
public GathererSets() { public GathererSets() {
@ -172,7 +187,7 @@ public class GathererSets implements Iterable<DownloadJob> {
} }
private void CheckSearchResult(String searchCode, ExpansionSet foundedExp, boolean canDownloadTask, private void CheckSearchResult(String searchCode, ExpansionSet foundedExp, boolean canDownloadTask,
boolean haveCommon, boolean haveUncommon, boolean haveRare, boolean haveMyth) { boolean haveCommon, boolean haveUncommon, boolean haveRare, boolean haveMyth) {
// duplicated in settings // duplicated in settings
CheckResult res = setsToDownload.get(searchCode); CheckResult res = setsToDownload.get(searchCode);
@ -223,16 +238,16 @@ public class GathererSets implements Iterable<DownloadJob> {
// 2. missing rarity icon: // 2. missing rarity icon:
// WARNING, need too much time (60+ secs), only for debug mode // WARNING, need too much time (60+ secs), only for debug mode
///* ///*
if ((set.getCardsByRarity(Rarity.COMMON).size() > 0) && !res.haveCommon) { if (!set.getCardsByRarity(Rarity.COMMON).isEmpty() && !res.haveCommon) {
logger.error(String.format("Symbols: set have common cards, but don't download icon: %s (%s)", set.getCode(), set.getName())); logger.error(String.format("Symbols: set have common cards, but don't download icon: %s (%s)", set.getCode(), set.getName()));
} }
if ((set.getCardsByRarity(Rarity.UNCOMMON).size() > 0) && !res.haveUncommon) { if (!set.getCardsByRarity(Rarity.UNCOMMON).isEmpty() && !res.haveUncommon) {
logger.error(String.format("Symbols: set have uncommon cards, but don't download icon: %s (%s)", set.getCode(), set.getName())); logger.error(String.format("Symbols: set have uncommon cards, but don't download icon: %s (%s)", set.getCode(), set.getName()));
} }
if ((set.getCardsByRarity(Rarity.RARE).size() > 0) && !res.haveRare) { if (!set.getCardsByRarity(Rarity.RARE).isEmpty() && !res.haveRare) {
logger.error(String.format("Symbols: set have rare cards, but don't download icon: %s (%s)", set.getCode(), set.getName())); logger.error(String.format("Symbols: set have rare cards, but don't download icon: %s (%s)", set.getCode(), set.getName()));
} }
if ((set.getCardsByRarity(Rarity.MYTHIC).size() > 0) && !res.haveMyth) { if (!set.getCardsByRarity(Rarity.MYTHIC).isEmpty() && !res.haveMyth) {
logger.error(String.format("Symbols: set have mythic cards, but don't download icon: %s (%s)", set.getCode(), set.getName())); logger.error(String.format("Symbols: set have mythic cards, but don't download icon: %s (%s)", set.getCode(), set.getName()));
} }
//*/ //*/
@ -332,7 +347,7 @@ public class GathererSets implements Iterable<DownloadJob> {
if (codeReplacements.containsKey(set)) { if (codeReplacements.containsKey(set)) {
set = codeReplacements.get(set); set = codeReplacements.get(set);
} }
String url = "http://gatherer.wizards.com/Handlers/Image.ashx?type=symbol&set=" + set + "&size=small&rarity=" + urlRarity; String url = "https://gatherer.wizards.com/Handlers/Image.ashx?type=symbol&set=" + set + "&size=small&rarity=" + urlRarity;
return new DownloadJob(set + '-' + rarity, fromURL(url), toFile(dst)); return new DownloadJob(set + '-' + rarity, fromURL(url), toFile(dst));
} }
} }

View file

@ -23,11 +23,11 @@ import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir;
*/ */
public class GathererSymbols implements Iterable<DownloadJob> { public class GathererSymbols implements Iterable<DownloadJob> {
//TODO chaos and planeswalker symbol //TODO chaos and planeswalker symbol
//chaos: http://gatherer.wizards.com/Images/Symbols/chaos.gif //chaos: https://gatherer.wizards.com/Images/Symbols/chaos.gif
private static File outDir; private static File outDir;
private static final String urlFmt = "http://gatherer.wizards.com/handlers/image.ashx?size=%1$s&name=%2$s&type=symbol"; private static final String urlFmt = "https://gatherer.wizards.com/handlers/image.ashx?size=%1$s&name=%2$s&type=symbol";
private static final String[] sizes = {"small", "medium", "large"}; private static final String[] sizes = {"small", "medium", "large"};

View file

@ -1,13 +1,11 @@
package org.mage.plugins.card.dl.sources; package org.mage.plugins.card.dl.sources;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.mage.plugins.card.dl.DownloadServiceInfo;
import org.mage.plugins.card.images.CardDownloadData; import org.mage.plugins.card.images.CardDownloadData;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Level; import java.util.logging.Level;
@ -46,6 +44,11 @@ public enum GrabbagImageSource implements CardImageSource {
return null; return null;
} }
@Override
public boolean prepareDownloadList(DownloadServiceInfo downloadServiceInfo, List<CardDownloadData> downloadList) {
return true;
}
@Override @Override
public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception {
if (singleLinks == null) { if (singleLinks == null) {
@ -290,7 +293,7 @@ public enum GrabbagImageSource implements CardImageSource {
singleLinks.put("SWS/Senator Bail Organa", "BRkUuYU.jpg"); singleLinks.put("SWS/Senator Bail Organa", "BRkUuYU.jpg");
singleLinks.put("SWS/Senator Lott Dod", "yYQtXZo.jpg"); singleLinks.put("SWS/Senator Lott Dod", "yYQtXZo.jpg");
singleLinks.put("SWS/Senator Onaconda Farr", "oPez77z.png"); singleLinks.put("SWS/Senator Onaconda Farr", "oPez77z.png");
singleLinks.put("SWS/Senator Padmé Amidala", "287deD9.jpg"); singleLinks.put("SWS/Senator Padme Amidala", "287deD9.jpg");
singleLinks.put("SWS/Senator Passel Argente", "51qpnaE.jpg"); singleLinks.put("SWS/Senator Passel Argente", "51qpnaE.jpg");
singleLinks.put("SWS/Shaak Herd", "PtnZD0I.jpg"); singleLinks.put("SWS/Shaak Herd", "PtnZD0I.jpg");
singleLinks.put("SWS/Shadow Trooper", "09NAiGa.jpg"); singleLinks.put("SWS/Shadow Trooper", "09NAiGa.jpg");

View file

@ -1,5 +1,6 @@
package org.mage.plugins.card.dl.sources; package org.mage.plugins.card.dl.sources;
import org.mage.plugins.card.dl.DownloadServiceInfo;
import org.mage.plugins.card.images.CardDownloadData; import org.mage.plugins.card.images.CardDownloadData;
import java.net.URI; import java.net.URI;
@ -227,6 +228,11 @@ public enum MagidexImageSource implements CardImageSource {
return null; return null;
} }
@Override
public boolean prepareDownloadList(DownloadServiceInfo downloadServiceInfo, List<CardDownloadData> downloadList) {
return true;
}
@Override @Override
public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception {
String cardDownloadName = card.getDownloadName().toLowerCase(Locale.ENGLISH); String cardDownloadName = card.getDownloadName().toLowerCase(Locale.ENGLISH);

View file

@ -1,7 +1,9 @@
package org.mage.plugins.card.dl.sources; package org.mage.plugins.card.dl.sources;
import org.mage.plugins.card.dl.DownloadServiceInfo;
import org.mage.plugins.card.images.CardDownloadData; import org.mage.plugins.card.images.CardDownloadData;
import java.util.List;
import java.util.Locale; import java.util.Locale;
/** /**
@ -28,6 +30,11 @@ public enum MtgImageSource implements CardImageSource {
return null; return null;
} }
@Override
public boolean prepareDownloadList(DownloadServiceInfo downloadServiceInfo, List<CardDownloadData> downloadList) {
return true;
}
@Override @Override
public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception {
String collectorId = card.getCollectorId(); String collectorId = card.getCollectorId();

View file

@ -1,10 +1,12 @@
package org.mage.plugins.card.dl.sources; package org.mage.plugins.card.dl.sources;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.mage.plugins.card.dl.DownloadServiceInfo;
import org.mage.plugins.card.images.CardDownloadData; import org.mage.plugins.card.images.CardDownloadData;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
/** /**
* @author spjspj * @author spjspj
@ -57,6 +59,11 @@ public enum MtgOnlTokensImageSource implements CardImageSource {
return null; return null;
} }
@Override
public boolean prepareDownloadList(DownloadServiceInfo downloadServiceInfo, List<CardDownloadData> downloadList) {
return true;
}
@Override @Override
public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception {
return null; return null;

View file

@ -7,6 +7,7 @@ import org.jsoup.Jsoup;
import org.jsoup.nodes.Document; import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element; import org.jsoup.nodes.Element;
import org.jsoup.select.Elements; import org.jsoup.select.Elements;
import org.mage.plugins.card.dl.DownloadServiceInfo;
import org.mage.plugins.card.images.CardDownloadData; import org.mage.plugins.card.images.CardDownloadData;
import java.io.BufferedReader; import java.io.BufferedReader;
@ -381,6 +382,11 @@ public enum MythicspoilerComSource implements CardImageSource {
return pageLinks; return pageLinks;
} }
@Override
public boolean prepareDownloadList(DownloadServiceInfo downloadServiceInfo, List<CardDownloadData> downloadList) {
return true;
}
@Override @Override
public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception {
String collectorId = card.getCollectorId(); String collectorId = card.getCollectorId();

View file

@ -1,12 +1,24 @@
package org.mage.plugins.card.dl.sources; package org.mage.plugins.card.dl.sources;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import mage.cards.ExpansionSet;
import mage.cards.Sets;
import mage.client.util.CardLanguage; import mage.client.util.CardLanguage;
import org.apache.log4j.Logger;
import org.mage.plugins.card.dl.DownloadServiceInfo;
import org.mage.plugins.card.images.CardDownloadData; import org.mage.plugins.card.images.CardDownloadData;
import java.util.ArrayList; import java.io.InputStream;
import java.util.HashMap; import java.io.InputStreamReader;
import java.util.Locale; import java.io.UnsupportedEncodingException;
import java.util.Map; import java.net.Proxy;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.*;
/** /**
* @author JayDi85 * @author JayDi85
@ -15,8 +27,11 @@ public enum ScryfallImageSource implements CardImageSource {
instance; instance;
private static final Logger logger = Logger.getLogger(ScryfallImageSource.class);
private final Map<CardLanguage, String> languageAliases; private final Map<CardLanguage, String> languageAliases;
private CardLanguage currentLanguage = CardLanguage.ENGLISH; // working language private CardLanguage currentLanguage = CardLanguage.ENGLISH; // working language
private Map<CardDownloadData, String> preparedUrls = new HashMap<>();
ScryfallImageSource() { ScryfallImageSource() {
// LANGUAGES // LANGUAGES
@ -36,6 +51,11 @@ public enum ScryfallImageSource implements CardImageSource {
} }
private CardImageUrls innerGenerateURL(CardDownloadData card, boolean isToken) { private CardImageUrls innerGenerateURL(CardDownloadData card, boolean isToken) {
String prepared = preparedUrls.getOrDefault(card, null);
if (prepared != null) {
return new CardImageUrls(prepared, null);
}
String defaultCode = CardLanguage.ENGLISH.getCode(); String defaultCode = CardLanguage.ENGLISH.getCode();
String localizedCode = languageAliases.getOrDefault(this.getCurrentLanguage(), defaultCode); String localizedCode = languageAliases.getOrDefault(this.getCurrentLanguage(), defaultCode);
// loc example: https://api.scryfall.com/cards/xln/121/ru?format=image // loc example: https://api.scryfall.com/cards/xln/121/ru?format=image
@ -62,29 +82,40 @@ public enum ScryfallImageSource implements CardImageSource {
alternativeUrl = null; alternativeUrl = null;
} }
// special card number like "103a" and "U123" already compatible // art variation cards
if (baseUrl == null && card.isCollectorIdWithStr()) { // ARN and POR use notation
// WARNING, after 2018 it's not compatible and some new sets have GUID files instead card numbers // PLS uses notation
// TODO: replace card number links to API calls (need test with lands, alternative images and double faces), replace not working images by direct links if (baseUrl == null && card.getUsesVariousArt() && card.getSet().matches("ARN|POR|PLS")) {
String scryfallCollectorId = card.getCollectorIdAsInt().toString();
if (card.getCollectorId().startsWith("U") || card.getCollectorIdAsInt() == -1) { if (card.getCollectorId().endsWith("b")) {
// fix for Ultimate Box Topper (PUMA) and Mythic Edition (MED) -- need to use API if (card.getSet().matches("ARN|POR")) {
// ignored and go to API call at the end scryfallCollectorId += "";
} else { } else if (card.getSet().matches("PLS")) {
baseUrl = "https://img.scryfall.com/cards/large/" + localizedCode + "/" + formatSetName(card.getSet(), isToken) + "/" scryfallCollectorId += "";
+ card.getCollectorId() + ".jpg"; }
alternativeUrl = "https://img.scryfall.com/cards/large/" + defaultCode + "/" + formatSetName(card.getSet(), isToken) + "/"
+ card.getCollectorId() + ".jpg";
} }
try {
scryfallCollectorId = URLEncoder.encode(scryfallCollectorId, "utf-8");
} catch (UnsupportedEncodingException e) {
// URL failed to encode, this will cause download to miss in certain environments
}
baseUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet(), isToken) + "/"
+ scryfallCollectorId + "/" + localizedCode + "?format=image";
alternativeUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet(), isToken) + "/"
+ scryfallCollectorId + "/" + defaultCode + "?format=image";
} }
// double faced cards do not supports by API (need direct link for img) // double faced card
// example: https://img.scryfall.com/cards/large/en/xln/173b.jpg // the front face can be downloaded normally
if (baseUrl == null && card.isTwoFacedCard()) { // the back face is prepared beforehand
baseUrl = "https://img.scryfall.com/cards/large/" + localizedCode + "/" + formatSetName(card.getSet(), isToken) + "/" if (baseUrl == null && card.isTwoFacedCard() && !card.isSecondSide()) {
+ card.getCollectorId() + (card.isSecondSide() ? "b" : "a") + ".jpg"; baseUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet(), isToken) + "/"
alternativeUrl = "https://img.scryfall.com/cards/large/" + defaultCode + "/" + formatSetName(card.getSet(), isToken) + "/" + card.getCollectorIdAsInt() + "/" + localizedCode + "?format=image";
+ card.getCollectorId() + (card.isSecondSide() ? "b" : "a") + ".jpg"; alternativeUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet(), isToken) + "/"
+ card.getCollectorIdAsInt() + "/" + defaultCode + "?format=image";
} }
// basic cards by api call (redirect to img link) // basic cards by api call (redirect to img link)
@ -99,6 +130,120 @@ public enum ScryfallImageSource implements CardImageSource {
return new CardImageUrls(baseUrl, alternativeUrl); return new CardImageUrls(baseUrl, alternativeUrl);
} }
private String getFaceImageUrl(Proxy proxy, CardDownloadData card, boolean isToken, String localizationCode) throws Exception {
// connect to Scryfall API
final URL cardUrl = new URL("https://api.scryfall.com/cards/" + formatSetName(card.getSet(), isToken) + "/"
+ (card.getCollectorIdAsInt() % 1000) + "/" + localizationCode);
URLConnection request = proxy == null ? cardUrl.openConnection() : cardUrl.openConnection(proxy);
request.connect();
// parse the response and return the image URI from the correct card face
JsonParser jp = new JsonParser();
JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent()));
JsonObject jsonCard = root.getAsJsonObject();
if (!jsonCard.has("card_faces")) {
throw new Exception("Couldn't find card_faces in Card JSON.");
}
JsonArray jsonCardFaces = jsonCard.getAsJsonArray("card_faces");
JsonObject jsonCardFace = jsonCardFaces.get(card.isSecondSide() ? 1 : 0).getAsJsonObject();
JsonObject jsonImageUris = jsonCardFace.getAsJsonObject("image_uris");
return jsonImageUris.get("large").getAsString();
}
@Override
public boolean prepareDownloadList(DownloadServiceInfo downloadServiceInfo, List<CardDownloadData> downloadList) {
// prepare download list example (
Proxy proxy = downloadServiceInfo.getProxy();
preparedUrls.clear();
final List<ExpansionSet.SetCardInfo> sixthEditionCards = Sets.findSet("6ED").getSetCardInfo();
for (CardDownloadData card : downloadList) {
// need cancel
if (downloadServiceInfo.isNeedCancel()) {
return false;
}
// prepare the back face URL
if (card.isTwoFacedCard() && card.isSecondSide()) {
final String defaultCode = CardLanguage.ENGLISH.getCode();
final String localizedCode = languageAliases.getOrDefault(this.getCurrentLanguage(), defaultCode);
String url = null;
try {
url = getFaceImageUrl(proxy, card, card.isToken(), localizedCode);
} catch (Exception e) {
logger.warn("Failed to prepare image URL for " + card.getName() + " (" + card.getSet() + ") #" + card.getCollectorId());
downloadServiceInfo.incErrorCount();
continue;
}
preparedUrls.put(card, url);
}
// if a S00 card is in 6ED, it's actually a 6ED card
if (card.getSet().equals("S00") && sixthEditionCards.stream().anyMatch(sixthEditionCard -> sixthEditionCard.getName().equals(card.getName()))) {
// we have direct links for the lands because there are multiple search results
if (card.getUsesVariousArt()) { // lands are the only defined multiple art cards in S00 in XMage
continue;
}
String url = null;
try {
url = searchCard(proxy, "6ED", card.getName());
} catch (Exception e) {
logger.warn("Failed to prepare image URL for " + card.getName() + " (" + card.getSet() + ") #" + card.getCollectorId());
downloadServiceInfo.incErrorCount();
continue;
}
preparedUrls.put(card, url);
}
// if an E01 card number is above 106, it's actually an AKH card
if (card.getSet().equals("E01") && card.getCollectorIdAsInt() > 106) {
String url = null;
try {
url = searchCard(proxy, "AKH", card.getName());
} catch (Exception e) {
logger.warn("Failed to prepare image URL for " + card.getName() + " (" + card.getSet() + ") #" + card.getCollectorId());
downloadServiceInfo.incErrorCount();
continue;
}
preparedUrls.put(card, url);
}
// inc error count to stop on too many errors
// downloadServiceInfo.incErrorCount();
}
return true;
}
private String searchCard(Proxy proxy, String set, String name) throws Exception {
final URL searchUrl = new URL("https://api.scryfall.com/cards/search?q=s:" + URLEncoder.encode(set + " " + name, "UTF-8"));
URLConnection request = proxy == null ? searchUrl.openConnection() : searchUrl.openConnection(proxy);
request.connect();
// parse the response and return the image URI from the correct card face
JsonParser jp = new JsonParser();
JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent()));
JsonObject searchResult = root.getAsJsonObject();
if (searchResult.get("total_cards").getAsInt() != 1) {
throw new Exception("Card not found in Scryfall.");
}
JsonObject jsonCard = searchResult.getAsJsonArray("data").get(0).getAsJsonObject();
JsonObject jsonImageUris = jsonCard.getAsJsonObject("image_uris");
return jsonImageUris.get("large").getAsString();
}
@Override @Override
public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception {
return innerGenerateURL(card, false); return innerGenerateURL(card, false);

View file

@ -23,9 +23,9 @@ public class ScryfallImageSupportCards {
put("EURO", "pelp"). put("EURO", "pelp").
put("GPX", "pgpx"). put("GPX", "pgpx").
put("MED", "me1"). put("MED", "me1").
put("MEDM", "med").build(); put("MEDM", "med").
put("CELD", "eld"). // scryfall moved ELD and CELD cards in one set, but card numbers are different
build();
private static final Set<String> supportedSets = new ArraySet<String>() { private static final Set<String> supportedSets = new ArraySet<String>() {
{ {
@ -239,12 +239,25 @@ public class ScryfallImageSupportCards {
add("GK2"); add("GK2");
add("MH1"); add("MH1");
add("WAR"); add("WAR");
add("M20");
add("C19");
add("ELD");
add("CELD");
add("THB");
// //
add("EURO"); add("EURO");
add("GPX"); add("GPX");
add("ATH"); add("ATH");
add("GRC"); add("GRC");
add("ANA"); add("ANA");
add("G18");
add("PM20");
add("PS19");
add("SS1");
add("SS2");
add("PPP1");
add("PF19");
add("MPS-AKH");
} }
}; };
@ -266,104 +279,109 @@ public class ScryfallImageSupportCards {
// Duels of the Planeswalkers Promos -- xmage uses one set (DPAP), but scryfall store it by years // Duels of the Planeswalkers Promos -- xmage uses one set (DPAP), but scryfall store it by years
// 2009 - https://scryfall.com/sets/pdtp // 2009 - https://scryfall.com/sets/pdtp
put("DPAP/Garruk Wildspeaker", "https://img.scryfall.com/cards/large/en/pdtp/1.jpg"); put("DPAP/Garruk Wildspeaker", "https://api.scryfall.com/cards/pdtp/1/en?format=image");
// 2010 - https://scryfall.com/sets/pdp10 // 2010 - https://scryfall.com/sets/pdp10
put("DPAP/Liliana Vess", "https://img.scryfall.com/cards/large/en/pdp10/1.jpg"); put("DPAP/Liliana Vess", "https://api.scryfall.com/cards/pdp10/1/en?format=image");
put("DPAP/Nissa Revane", "https://img.scryfall.com/cards/large/en/pdp10/2.jpg"); put("DPAP/Nissa Revane", "https://api.scryfall.com/cards/pdp10/2/en?format=image");
// 2011 - https://scryfall.com/sets/pdp11 // 2011 - https://scryfall.com/sets/pdp11
put("DPAP/Frost Titan", "https://img.scryfall.com/cards/large/en/pdp11/1.jpg"); put("DPAP/Frost Titan", "https://api.scryfall.com/cards/pdp11/1/en?format=image");
put("DPAP/Grave Titan", "https://img.scryfall.com/cards/large/en/pdp11/2.jpg"); put("DPAP/Grave Titan", "https://api.scryfall.com/cards/pdp11/2/en?format=image");
put("DPAP/Inferno Titan", "https://img.scryfall.com/cards/large/en/pdp11/3.jpg"); put("DPAP/Inferno Titan", "https://api.scryfall.com/cards/pdp11/3/en?format=image");
// 2012 - https://scryfall.com/sets/pdp12 // 2012 - https://scryfall.com/sets/pdp12
put("DPAP/Primordial Hydra", "https://img.scryfall.com/cards/large/en/pdp12/1.jpg"); put("DPAP/Primordial Hydra", "https://api.scryfall.com/cards/pdp12/1/en?format=image");
put("DPAP/Serra Avatar", "https://img.scryfall.com/cards/large/en/pdp12/2.jpg"); put("DPAP/Serra Avatar", "https://api.scryfall.com/cards/pdp12/2/en?format=image");
put("DPAP/Vampire Nocturnus", "https://img.scryfall.com/cards/large/en/pdp12/3.jpg"); put("DPAP/Vampire Nocturnus", "https://api.scryfall.com/cards/pdp12/3/en?format=image");
// 2013 - https://scryfall.com/sets/pdp13 // 2013 - https://scryfall.com/sets/pdp13
put("DPAP/Bonescythe Sliver", "https://img.scryfall.com/cards/large/en/pdp13/1.jpg"); put("DPAP/Bonescythe Sliver", "https://api.scryfall.com/cards/pdp13/1/en?format=image");
put("DPAP/Ogre Battledriver", "https://img.scryfall.com/cards/large/en/pdp13/2.jpg"); put("DPAP/Ogre Battledriver", "https://api.scryfall.com/cards/pdp13/2/en?format=image");
put("DPAP/Scavenging Ooze", "https://img.scryfall.com/cards/large/en/pdp13/3.jpg"); put("DPAP/Scavenging Ooze", "https://api.scryfall.com/cards/pdp13/3/en?format=image");
// 2014 - https://scryfall.com/sets/pdp14 // 2014 - https://scryfall.com/sets/pdp14
put("DPAP/Soul of Ravnica", "https://img.scryfall.com/cards/large/en/pdp14/1.jpg"); put("DPAP/Soul of Ravnica", "https://api.scryfall.com/cards/pdp14/1/en?format=image");
put("DPAP/Soul of Zendikar", "https://img.scryfall.com/cards/large/en/pdp14/2.jpg"); put("DPAP/Soul of Zendikar", "https://api.scryfall.com/cards/pdp14/2/en?format=image");
// Gateway Promos -- xmage uses one set (GRC), but scryfall store it by years // Gateway Promos -- xmage uses one set (GRC), but scryfall store it by years
// 2006 - https://scryfall.com/sets/pgtw // 2006 - https://scryfall.com/sets/pgtw
put("GRC/Fiery Temper", "https://img.scryfall.com/cards/large/en/pgtw/3.jpg"); put("GRC/Fiery Temper", "https://api.scryfall.com/cards/pgtw/3/en?format=image");
put("GRC/Icatian Javelineers", "https://img.scryfall.com/cards/large/en/pgtw/2.jpg"); put("GRC/Icatian Javelineers", "https://api.scryfall.com/cards/pgtw/2/en?format=image");
put("GRC/Wood Elves", "https://img.scryfall.com/cards/large/en/pgtw/1.jpg"); put("GRC/Wood Elves", "https://api.scryfall.com/cards/pgtw/1/en?format=image");
// 2007 - https://scryfall.com/sets/pg07 // 2007 - https://scryfall.com/sets/pg07
put("GRC/Boomerang", "https://img.scryfall.com/cards/large/en/pg07/4.jpg"); put("GRC/Boomerang", "https://api.scryfall.com/cards/pg07/4/en?format=image");
put("GRC/Calciderm", "https://img.scryfall.com/cards/large/en/pg07/5.jpg"); put("GRC/Calciderm", "https://api.scryfall.com/cards/pg07/5/en?format=image");
put("GRC/Dauntless Dourbark", "https://img.scryfall.com/cards/large/en/pg07/12.jpg"); put("GRC/Dauntless Dourbark", "https://api.scryfall.com/cards/pg07/12/en?format=image");
put("GRC/Llanowar Elves", "https://img.scryfall.com/cards/large/en/pg07/9.jpg"); put("GRC/Llanowar Elves", "https://api.scryfall.com/cards/pg07/9/en?format=image");
put("GRC/Mind Stone", "https://img.scryfall.com/cards/large/en/pg07/11.jpg"); put("GRC/Mind Stone", "https://api.scryfall.com/cards/pg07/11/en?format=image");
put("GRC/Mogg Fanatic", "https://img.scryfall.com/cards/large/en/pg07/10.jpg"); put("GRC/Mogg Fanatic", "https://api.scryfall.com/cards/pg07/10/en?format=image");
put("GRC/Reckless Wurm", "https://img.scryfall.com/cards/large/en/pg07/6.jpg"); put("GRC/Reckless Wurm", "https://api.scryfall.com/cards/pg07/6/en?format=image");
put("GRC/Yixlid Jailer", "https://img.scryfall.com/cards/large/en/pg07/7.jpg"); put("GRC/Yixlid Jailer", "https://api.scryfall.com/cards/pg07/7/en?format=image");
put("GRC/Zoetic Cavern", "https://img.scryfall.com/cards/large/en/pg07/8.jpg"); put("GRC/Zoetic Cavern", "https://api.scryfall.com/cards/pg07/8/en?format=image");
// 2008a - https://scryfall.com/sets/pg08 // 2008a - https://scryfall.com/sets/pg08
put("GRC/Boggart Ram-Gang", "https://img.scryfall.com/cards/large/en/pg08/17.jpg"); put("GRC/Boggart Ram-Gang", "https://api.scryfall.com/cards/pg08/17/en?format=image");
put("GRC/Cenn's Tactician", "https://img.scryfall.com/cards/large/en/pg08/14.jpg"); put("GRC/Cenn's Tactician", "https://api.scryfall.com/cards/pg08/14/en?format=image");
put("GRC/Duergar Hedge-Mage", "https://img.scryfall.com/cards/large/en/pg08/19.jpg"); put("GRC/Duergar Hedge-Mage", "https://api.scryfall.com/cards/pg08/19/en?format=image");
put("GRC/Gravedigger", "https://img.scryfall.com/cards/large/en/pg08/16.jpg"); put("GRC/Gravedigger", "https://api.scryfall.com/cards/pg08/16/en?format=image");
put("GRC/Lava Axe", "https://img.scryfall.com/cards/large/en/pg08/13.jpg"); put("GRC/Lava Axe", "https://api.scryfall.com/cards/pg08/13/en?format=image");
put("GRC/Oona's Blackguard", "https://img.scryfall.com/cards/large/en/pg08/15.jpg"); put("GRC/Oona's Blackguard", "https://api.scryfall.com/cards/pg08/15/en?format=image");
put("GRC/Selkie Hedge-Mage", "https://img.scryfall.com/cards/large/en/pg08/20.jpg"); put("GRC/Selkie Hedge-Mage", "https://api.scryfall.com/cards/pg08/20/en?format=image");
put("GRC/Wilt-Leaf Cavaliers", "https://img.scryfall.com/cards/large/en/pg08/18.jpg"); put("GRC/Wilt-Leaf Cavaliers", "https://api.scryfall.com/cards/pg08/18/en?format=image");
// Wizards Play Network Promos -- xmage uses one set (GRC), but scryfall store it by years // Wizards Play Network Promos -- xmage uses one set (GRC), but scryfall store it by years
// 2008b - https://scryfall.com/sets/pwpn // 2008b - https://scryfall.com/sets/pwpn
put("GRC/Sprouting Thrinax", "https://img.scryfall.com/cards/large/en/pwpn/21.jpg"); put("GRC/Sprouting Thrinax", "https://api.scryfall.com/cards/pwpn/21/en?format=image");
put("GRC/Woolly Thoctar", "https://img.scryfall.com/cards/large/en/pwpn/22.jpg"); put("GRC/Woolly Thoctar", "https://api.scryfall.com/cards/pwpn/22/en?format=image");
// 2009 - https://scryfall.com/sets/pwp09 // 2009 - https://scryfall.com/sets/pwp09
put("GRC/Hellspark Elemental", "https://img.scryfall.com/cards/large/en/pwp09/25.jpg"); put("GRC/Hellspark Elemental", "https://api.scryfall.com/cards/pwp09/25/en?format=image");
put("GRC/Kor Duelist", "https://img.scryfall.com/cards/large/en/pwp09/32.jpg"); put("GRC/Kor Duelist", "https://api.scryfall.com/cards/pwp09/32/en?format=image");
put("GRC/Marisi's Twinclaws", "https://img.scryfall.com/cards/large/en/pwp09/26.jpg"); put("GRC/Marisi's Twinclaws", "https://api.scryfall.com/cards/pwp09/26/en?format=image");
put("GRC/Mind Control", "https://img.scryfall.com/cards/large/en/pwp09/30.jpg"); put("GRC/Mind Control", "https://api.scryfall.com/cards/pwp09/30/en?format=image");
put("GRC/Path to Exile", "https://img.scryfall.com/cards/large/en/pwp09/24.jpg"); put("GRC/Path to Exile", "https://api.scryfall.com/cards/pwp09/24/en?format=image");
put("GRC/Rise from the Grave", "https://img.scryfall.com/cards/large/en/pwp09/31.jpg"); put("GRC/Rise from the Grave", "https://api.scryfall.com/cards/pwp09/31/en?format=image");
put("GRC/Slave of Bolas", "https://img.scryfall.com/cards/large/en/pwp09/27.jpg"); put("GRC/Slave of Bolas", "https://api.scryfall.com/cards/pwp09/27/en?format=image");
put("GRC/Vampire Nighthawk", "https://img.scryfall.com/cards/large/en/pwp09/33.jpg"); put("GRC/Vampire Nighthawk", "https://api.scryfall.com/cards/pwp09/33/en?format=image");
// 2010 - https://scryfall.com/sets/pwp10 // 2010 - https://scryfall.com/sets/pwp10
put("GRC/Kor Firewalker", "https://img.scryfall.com/cards/large/en/pwp10/36.jpg"); put("GRC/Kor Firewalker", "https://api.scryfall.com/cards/pwp10/36/en?format=image");
put("GRC/Leatherback Baloth", "https://img.scryfall.com/cards/large/en/pwp10/37.jpg"); put("GRC/Leatherback Baloth", "https://api.scryfall.com/cards/pwp10/37/en?format=image");
put("GRC/Syphon Mind", "https://img.scryfall.com/cards/large/en/pwp10/40.jpg"); put("GRC/Syphon Mind", "https://api.scryfall.com/cards/pwp10/40/en?format=image");
put("GRC/Pathrazer of Ulamog", "https://img.scryfall.com/cards/large/en/pwp10/46.jpg"); put("GRC/Pathrazer of Ulamog", "https://api.scryfall.com/cards/pwp10/46/en?format=image");
put("GRC/Curse of Wizardry", "https://img.scryfall.com/cards/large/en/pwp10/47.jpg"); put("GRC/Curse of Wizardry", "https://api.scryfall.com/cards/pwp10/47/en?format=image");
put("GRC/Fling/50", "https://img.scryfall.com/cards/large/en/pwp10/50.jpg"); // same card but different year put("GRC/Fling/50", "https://api.scryfall.com/cards/pwp10/50/en?format=image"); // same card but different year
put("GRC/Sylvan Ranger/51", "https://img.scryfall.com/cards/large/en/pwp10/51.jpg"); // same card but different year put("GRC/Sylvan Ranger/51", "https://api.scryfall.com/cards/pwp10/51/en?format=image"); // same card but different year
put("GRC/Plague Stinger", "https://img.scryfall.com/cards/large/en/pwp10/59.jpg"); put("GRC/Plague Stinger", "https://api.scryfall.com/cards/pwp10/59/en?format=image");
put("GRC/Golem's Heart", "https://img.scryfall.com/cards/large/en/pwp10/60.jpg"); put("GRC/Golem's Heart", "https://api.scryfall.com/cards/pwp10/60/en?format=image");
put("GRC/Skinrender", "https://img.scryfall.com/cards/large/en/pwp10/63.jpg"); put("GRC/Skinrender", "https://api.scryfall.com/cards/pwp10/63/en?format=image");
// 2011 - https://scryfall.com/sets/pwp11 // 2011 - https://scryfall.com/sets/pwp11
put("GRC/Auramancer", "https://img.scryfall.com/cards/large/en/pwp11/77.jpg"); put("GRC/Auramancer", "https://api.scryfall.com/cards/pwp11/77/en?format=image");
put("GRC/Bloodcrazed Neonate", "https://img.scryfall.com/cards/large/en/pwp11/83.jpg"); put("GRC/Bloodcrazed Neonate", "https://api.scryfall.com/cards/pwp11/83/en?format=image");
put("GRC/Boneyard Wurm", "https://img.scryfall.com/cards/large/en/pwp11/84.jpg"); put("GRC/Boneyard Wurm", "https://api.scryfall.com/cards/pwp11/84/en?format=image");
put("GRC/Circle of Flame", "https://img.scryfall.com/cards/large/en/pwp11/78.jpg"); put("GRC/Circle of Flame", "https://api.scryfall.com/cards/pwp11/78/en?format=image");
put("GRC/Curse of the Bloody Tome", "https://img.scryfall.com/cards/large/en/pwp11/80.jpg"); put("GRC/Curse of the Bloody Tome", "https://api.scryfall.com/cards/pwp11/80/en?format=image");
put("GRC/Fling/69", "https://img.scryfall.com/cards/large/en/pwp11/69.jpg"); // same card but different year put("GRC/Fling/69", "https://api.scryfall.com/cards/pwp11/69/en?format=image"); // same card but different year
put("GRC/Master's Call", "https://img.scryfall.com/cards/large/en/pwp11/64.jpg"); put("GRC/Master's Call", "https://api.scryfall.com/cards/pwp11/64/en?format=image");
put("GRC/Maul Splicer", "https://img.scryfall.com/cards/large/en/pwp11/72.jpg"); put("GRC/Maul Splicer", "https://api.scryfall.com/cards/pwp11/72/en?format=image");
put("GRC/Plague Myr", "https://img.scryfall.com/cards/large/en/pwp11/65.jpg"); put("GRC/Plague Myr", "https://api.scryfall.com/cards/pwp11/65/en?format=image");
put("GRC/Shrine of Burning Rage", "https://img.scryfall.com/cards/large/en/pwp11/73.jpg"); put("GRC/Shrine of Burning Rage", "https://api.scryfall.com/cards/pwp11/73/en?format=image");
put("GRC/Signal Pest", "https://img.scryfall.com/cards/large/en/pwp11/66.jpg"); put("GRC/Signal Pest", "https://api.scryfall.com/cards/pwp11/66/en?format=image");
put("GRC/Sylvan Ranger/70", "https://img.scryfall.com/cards/large/en/pwp11/70.jpg"); // same card but different year put("GRC/Sylvan Ranger/70", "https://api.scryfall.com/cards/pwp11/70/en?format=image"); // same card but different year
put("GRC/Tormented Soul", "https://img.scryfall.com/cards/large/en/pwp11/76.jpg"); put("GRC/Tormented Soul", "https://api.scryfall.com/cards/pwp11/76/en?format=image");
put("GRC/Vault Skirge", "https://img.scryfall.com/cards/large/en/pwp11/71.jpg"); put("GRC/Vault Skirge", "https://api.scryfall.com/cards/pwp11/71/en?format=image");
// 2012 - https://scryfall.com/sets/pwp12 // 2012 - https://scryfall.com/sets/pwp12
put("GRC/Curse of Thirst", "https://img.scryfall.com/cards/large/en/pwp12/81.jpg"); put("GRC/Curse of Thirst", "https://api.scryfall.com/cards/pwp12/81/en?format=image");
put("GRC/Gather the Townsfolk", "https://img.scryfall.com/cards/large/en/pwp12/79.jpg"); put("GRC/Gather the Townsfolk", "https://api.scryfall.com/cards/pwp12/79/en?format=image");
put("GRC/Nearheath Stalker", "https://img.scryfall.com/cards/large/en/pwp12/82.jpg"); put("GRC/Nearheath Stalker", "https://api.scryfall.com/cards/pwp12/82/en?format=image");
// TODO: remove Grand Prix fix after scryfall fix image's link (that's link must be work: https://img.scryfall.com/cards/large/en/pgpx/2016b.jpg ) // Spined Wurm print in Starter 2000 is actually from Magazine Inserts
put("GPX/Sword of Feast and Famine", "https://img.scryfall.com/cards/large/en/pgpx/1%E2%98%85.jpg"); put("S00/Spined Wurm", "https://api.scryfall.com/cards/pmei/11/en?format=image");
// Most of the other S00 cards are from 6ED
// TODO: remove after scryfall add lands to RNA (that's link must works: https://api.scryfall.com/cards/rna/262/en?format=image) // We'll download lands manually because we have multiple arts and XMage has totally different ID's
put("RNA/Plains", "https://api.scryfall.com/cards/grn/260/en?format=image"); put("S00/Forest/49", "https://api.scryfall.com/cards/6ed/347/en?format=image");
put("RNA/Island", "https://api.scryfall.com/cards/grn/261/en?format=image"); put("S00/Forest/50", "https://api.scryfall.com/cards/6ed/348/en?format=image");
put("RNA/Swamp", "https://api.scryfall.com/cards/grn/262/en?format=image"); put("S00/Island/51", "https://api.scryfall.com/cards/6ed/335/en?format=image");
put("RNA/Mountain", "https://api.scryfall.com/cards/grn/263/en?format=image"); put("S00/Island/52", "https://api.scryfall.com/cards/6ed/336/en?format=image");
put("RNA/Forest", "https://api.scryfall.com/cards/grn/264/en?format=image"); put("S00/Mountain/53", "https://api.scryfall.com/cards/6ed/343/en?format=image");
put("S00/Mountain/54", "https://api.scryfall.com/cards/6ed/344/en?format=image");
put("S00/Plains/55", "https://api.scryfall.com/cards/6ed/331/en?format=image");
put("S00/Plains/56", "https://api.scryfall.com/cards/6ed/332/en?format=image");
put("S00/Swamp/57", "https://api.scryfall.com/cards/6ed/339/en?format=image");
put("S00/Swamp/58", "https://api.scryfall.com/cards/6ed/340/en?format=image");
} }
}; };

View file

@ -49,6 +49,143 @@ public class ScryfallImageSupportTokens {
put("RNA/Treasure", "https://api.scryfall.com/cards/trna/12/en?format=image"); put("RNA/Treasure", "https://api.scryfall.com/cards/trna/12/en?format=image");
put("RNA/Zombie", "https://api.scryfall.com/cards/trna/3/en?format=image"); put("RNA/Zombie", "https://api.scryfall.com/cards/trna/3/en?format=image");
//GRN
put("GRN/Angel", "https://api.scryfall.com/cards/tgrn/1/en?format=image");
put("GRN/Bird Illusion", "https://api.scryfall.com/cards/tgrn/3/en?format=image");
put("GRN/Elf Knight", "https://api.scryfall.com/cards/tgrn/6/en?format=image");
put("GRN/Goblin", "https://api.scryfall.com/cards/tgrn/4/en?format=image");
put("GRN/Insect", "https://api.scryfall.com/cards/tgrn/5/en?format=image");
put("GRN/Emblem Ral, Izzet Viceroy", "https://api.scryfall.com/cards/tgrn/7/en?format=image");
put("GRN/Soldier", "https://api.scryfall.com/cards/tgrn/2/en?format=image");
put("GRN/Emblem Vraska, Golgari Queen", "https://api.scryfall.com/cards/tgrn/8/en?format=image");
//DOM
put("DOM/Cleric", "https://api.scryfall.com/cards/tdom/4/en?format=image");
put("DOM/Construct", "https://api.scryfall.com/cards/tdom/14/en?format=image");
put("DOM/Demon", "https://api.scryfall.com/cards/tdom/7/en?format=image");
put("DOM/Elemental", "https://api.scryfall.com/cards/tdom/8/en?format=image");
put("DOM/Goblin", "https://api.scryfall.com/cards/tdom/9/en?format=image");
put("DOM/Emblem Jaya Ballard", "https://api.scryfall.com/cards/tdom/15/en?format=image");
put("DOM/Karox Bladewing", "https://api.scryfall.com/cards/tdom/10/en?format=image");
put("DOM/Knight/1", "https://api.scryfall.com/cards/tdom/1/en?format=image");
put("DOM/Knight/2", "https://api.scryfall.com/cards/tdom/2/en?format=image");
put("DOM/Nightmare Horror", "https://api.scryfall.com/cards/tdom/6/en?format=image");
put("DOM/Saproling/1", "https://api.scryfall.com/cards/tdom/11/en?format=image");
put("DOM/Saproling/2", "https://api.scryfall.com/cards/tdom/12/en?format=image");
put("DOM/Saproling/3", "https://api.scryfall.com/cards/tdom/13/en?format=image");
put("DOM/Soldier", "https://api.scryfall.com/cards/tdom/3/en?format=image");
put("DOM/Emblem Teferi, Hero of Dominaria", "https://api.scryfall.com/cards/tdom/16/en?format=image");
put("DOM/Zombie Knight", "https://api.scryfall.com/cards/tdom/5/en?format=image");
//XLN
put("XLN/Dinosaur", "https://api.scryfall.com/cards/txln/5/en?format=image");
put("XLN/Illusion", "https://api.scryfall.com/cards/txln/2/en?format=image");
put("XLN/Merfolk", "https://api.scryfall.com/cards/txln/3/en?format=image");
put("XLN/Pirate", "https://api.scryfall.com/cards/txln/4/en?format=image");
put("XLN/Plant", "https://api.scryfall.com/cards/txln/6/en?format=image");
put("XLN/Treasure/1", "https://api.scryfall.com/cards/txln/7/en?format=image");
put("XLN/Treasure/2", "https://api.scryfall.com/cards/txln/8/en?format=image");
put("XLN/Treasure/3", "https://api.scryfall.com/cards/txln/9/en?format=image");
put("XLN/Treasure/4", "https://api.scryfall.com/cards/txln/10/en?format=image");
put("XLN/Vampire", "https://api.scryfall.com/cards/txln/1/en?format=image");
//HOU
put("HOU/Horse", "https://api.scryfall.com/cards/thou/10/en?format=image");
put("HOU/Insect", "https://api.scryfall.com/cards/thou/12/en?format=image");
put("HOU/Snake", "https://api.scryfall.com/cards/thou/11/en?format=image");
//AKH
put("AKH/Beast", "https://api.scryfall.com/cards/takh/21/en?format=image");
put("AKH/Cat", "https://api.scryfall.com/cards/takh/16/en?format=image");
put("AKH/Drake", "https://api.scryfall.com/cards/takh/18/en?format=image");
put("AKH/Emblem Gideon", "https://api.scryfall.com/cards/takh/25/en?format=image");
put("AKH/Hippo", "https://api.scryfall.com/cards/takh/22/en?format=image");
put("AKH/Snake", "https://api.scryfall.com/cards/takh/23/en?format=image");
put("AKH/Warrior", "https://api.scryfall.com/cards/takh/17/en?format=image");
put("AKH/Wurm", "https://api.scryfall.com/cards/takh/24/en?format=image");
put("AKH/Zombie", "https://api.scryfall.com/cards/takh/20/en?format=image");
//AER
put("AER/Etherium Cell", "https://api.scryfall.com/cards/taer/3/en?format=image");
put("AER/Gremlin", "https://api.scryfall.com/cards/taer/1/en?format=image");
put("AER/Ragavan", "https://api.scryfall.com/cards/taer/2/en?format=image");
put("AER/Emblem Tezzeret the Schemer", "https://api.scryfall.com/cards/taer/4/en?format=image");
//KLD
put("KLD/Beast", "https://api.scryfall.com/cards/tkld/1/en?format=image");
put("KLD/Emblem Chandra", "https://api.scryfall.com/cards/tkld/10/en?format=image");
put("KLD/Construct/1", "https://api.scryfall.com/cards/tkld/2/en?format=image");
put("KLD/Construct/2", "https://api.scryfall.com/cards/tkld/3/en?format=image");
put("KLD/Emblem Dovin", "https://api.scryfall.com/cards/tkld/12/en?format=image");
put("KLD/Emblem Nissa", "https://api.scryfall.com/cards/tkld/11/en?format=image");
put("KLD/Servo/1", "https://api.scryfall.com/cards/tkld/4/en?format=image");
put("KLD/Servo/2", "https://api.scryfall.com/cards/tkld/5/en?format=image");
put("KLD/Servo/3", "https://api.scryfall.com/cards/tkld/6/en?format=image");
put("KLD/Thopter/1", "https://api.scryfall.com/cards/tkld/7/en?format=image");
put("KLD/Thopter/2", "https://api.scryfall.com/cards/tkld/8/en?format=image");
put("KLD/Thopter/3", "https://api.scryfall.com/cards/tkld/9/en?format=image");
//EMN
put("EMN/Eldrazi Horror", "https://api.scryfall.com/cards/temn/1/en?format=image");
put("EMN/Human", "https://api.scryfall.com/cards/temn/7/en?format=image");
put("EMN/Human Wizard", "https://api.scryfall.com/cards/temn/2/en?format=image");
put("EMN/Emblem Liliana", "https://api.scryfall.com/cards/temn/9/en?format=image");
put("EMN/Spider", "https://api.scryfall.com/cards/temn/8/en?format=image");
put("EMN/Emblem Tamiyo", "https://api.scryfall.com/cards/temn/10/en?format=image");
put("EMN/Zombie/1", "https://api.scryfall.com/cards/temn/3/en?format=image");
put("EMN/Zombie/2", "https://api.scryfall.com/cards/temn/4/en?format=image");
put("EMN/Zombie/3", "https://api.scryfall.com/cards/temn/5/en?format=image");
put("EMN/Zombie/4", "https://api.scryfall.com/cards/temn/6/en?format=image");
//SOI
put("SOI/Angel", "https://api.scryfall.com/cards/tsoi/1/en?format=image");
put("SOI/Emblem Arlinn", "https://api.scryfall.com/cards/tsoi/18/en?format=image");
put("SOI/Clue/1", "https://api.scryfall.com/cards/tsoi/11/en?format=image");
put("SOI/Clue/2", "https://api.scryfall.com/cards/tsoi/12/en?format=image");
put("SOI/Clue/3", "https://api.scryfall.com/cards/tsoi/13/en?format=image");
put("SOI/Clue/4", "https://api.scryfall.com/cards/tsoi/14/en?format=image");
put("SOI/Clue/5", "https://api.scryfall.com/cards/tsoi/15/en?format=image");
put("SOI/Clue/6", "https://api.scryfall.com/cards/tsoi/16/en?format=image");
put("SOI/Devil", "https://api.scryfall.com/cards/tsoi/6/en?format=image");
put("SOI/Human Cleric", "https://api.scryfall.com/cards/tsoi/10/en?format=image");
put("SOI/Human Soldier", "https://api.scryfall.com/cards/tsoi/2/en?format=image");
put("SOI/Insect", "https://api.scryfall.com/cards/tsoi/7/en?format=image");
put("SOI/Emblem Jace", "https://api.scryfall.com/cards/tsoi/17/en?format=image");
put("SOI/Ooze", "https://api.scryfall.com/cards/tsoi/8/en?format=image");
put("SOI/Spirit", "https://api.scryfall.com/cards/tsoi/3/en?format=image");
put("SOI/Vampire Knight", "https://api.scryfall.com/cards/tsoi/4/en?format=image");
put("SOI/Wolf", "https://api.scryfall.com/cards/tsoi/9/en?format=image");
put("SOI/Zombie", "https://api.scryfall.com/cards/tsoi/5/en?format=image");
//OGW
put("OGW/Angel", "https://api.scryfall.com/cards/togw/7/en?format=image");
put("OGW/Eldrazi Scion/1", "https://api.scryfall.com/cards/togw/1/en?format=image");
put("OGW/Eldrazi Scion/2", "https://api.scryfall.com/cards/togw/2/en?format=image");
put("OGW/Eldrazi Scion/3", "https://api.scryfall.com/cards/togw/3/en?format=image");
put("OGW/Eldrazi Scion/4", "https://api.scryfall.com/cards/togw/4/en?format=image");
put("OGW/Eldrazi Scion/5", "https://api.scryfall.com/cards/togw/5/en?format=image");
put("OGW/Eldrazi Scion/6", "https://api.scryfall.com/cards/togw/6/en?format=image");
put("OGW/Elemental/1", "https://api.scryfall.com/cards/togw/10/en?format=image");
put("OGW/Elemental/2", "https://api.scryfall.com/cards/togw/9/en?format=image");
put("OGW/Plant", "https://api.scryfall.com/cards/togw/11/en?format=image");
put("OGW/Zombie", "https://api.scryfall.com/cards/togw/8/en?format=image");
//BFZ
put("BFZ/Dragon", "https://api.scryfall.com/cards/tbfz/8/en?format=image");
put("BFZ/Eldrazi", "https://api.scryfall.com/cards/tbfz/1/en?format=image");
put("BFZ/Eldrazi Scion/1", "https://api.scryfall.com/cards/tbfz/2/en?format=image");
put("BFZ/Eldrazi Scion/2", "https://api.scryfall.com/cards/tbfz/3/en?format=image");
put("BFZ/Eldrazi Scion/3", "https://api.scryfall.com/cards/tbfz/4/en?format=image");
put("BFZ/Elemental/1", "https://api.scryfall.com/cards/tbfz/11/en?format=image");
put("BFZ/Elemental/2", "https://api.scryfall.com/cards/tbfz/9/en?format=image");
put("BFZ/Emblem Gideon", "https://api.scryfall.com/cards/tbfz/12/en?format=image");
put("BFZ/Emblem Kiora", "https://api.scryfall.com/cards/tbfz/14/en?format=image");
put("BFZ/Knight Ally", "https://api.scryfall.com/cards/tbfz/5/en?format=image");
put("BFZ/Kor Ally", "https://api.scryfall.com/cards/tbfz/6/en?format=image");
put("BFZ/Emblem Nixilis", "https://api.scryfall.com/cards/tbfz/13/en?format=image");
put("BFZ/Octopus", "https://api.scryfall.com/cards/tbfz/7/en?format=image");
put("BFZ/Plant", "https://api.scryfall.com/cards/tbfz/10/en?format=image");
// WAR // WAR
put("WAR/Angel", "https://api.scryfall.com/cards/twar/2/en?format=image"); put("WAR/Angel", "https://api.scryfall.com/cards/twar/2/en?format=image");
put("WAR/Assassin", "https://api.scryfall.com/cards/twar/6/en?format=image"); put("WAR/Assassin", "https://api.scryfall.com/cards/twar/6/en?format=image");
@ -70,6 +207,133 @@ public class ScryfallImageSupportTokens {
put("WAR/Zombie Warrior", "https://api.scryfall.com/cards/twar/11/en?format=image"); put("WAR/Zombie Warrior", "https://api.scryfall.com/cards/twar/11/en?format=image");
put("WAR/Zombie", "https://api.scryfall.com/cards/twar/7/en?format=image"); put("WAR/Zombie", "https://api.scryfall.com/cards/twar/7/en?format=image");
// MH1
put("MH1/Angel", "https://api.scryfall.com/cards/tmh1/2/en?format=image");
put("MH1/Bear", "https://api.scryfall.com/cards/tmh1/11/en?format=image");
put("MH1/Bird", "https://api.scryfall.com/cards/tmh1/3/en?format=image");
put("MH1/Construct", "https://api.scryfall.com/cards/tmh1/17/en?format=image");
put("MH1/Elemental/1", "https://api.scryfall.com/cards/tmh1/8/en?format=image");
put("MH1/Elemental/2", "https://api.scryfall.com/cards/tmh1/9/en?format=image");
put("MH1/Elephant", "https://api.scryfall.com/cards/tmh1/12/en?format=image");
put("MH1/Goblin", "https://api.scryfall.com/cards/tmh1/10/en?format=image");
put("MH1/Golem", "https://api.scryfall.com/cards/tmh1/18/en?format=image");
put("MH1/Illusion", "https://api.scryfall.com/cards/tmh1/5/en?format=image");
put("MH1/Marit Lage", "https://api.scryfall.com/cards/tmh1/6/en?format=image");
put("MH1/Myr", "https://api.scryfall.com/cards/tmh1/19/en?format=image");
put("MH1/Rhino", "https://api.scryfall.com/cards/tmh1/13/en?format=image");
put("MH1/Emblem Serra the Benevolent", "https://api.scryfall.com/cards/tmh1/20/en?format=image");
put("MH1/Shapeshifter", "https://api.scryfall.com/cards/tmh1/1/en?format=image");
put("MH1/Soldier", "https://api.scryfall.com/cards/tmh1/4/en?format=image");
put("MH1/Spider", "https://api.scryfall.com/cards/tmh1/14/en?format=image");
put("MH1/Spirit", "https://api.scryfall.com/cards/tmh1/16/en?format=image");
put("MH1/Squirrel", "https://api.scryfall.com/cards/tmh1/15/en?format=image");
put("MH1/Emblem Wrenn and Six", "https://api.scryfall.com/cards/tmh1/21/en?format=image");
put("MH1/Zombie", "https://api.scryfall.com/cards/tmh1/7/en?format=image");
// M19
put("M19/Emblem Ajani, Adversary of Tyrants", "https://api.scryfall.com/cards/tm19/15/en?format=image");
put("M19/Angel", "https://api.scryfall.com/cards/tm19/1/en?format=image");
put("M19/Avatar", "https://api.scryfall.com/cards/tm19/2/en?format=image");
put("M19/Bat", "https://api.scryfall.com/cards/tm19/7/en?format=image");
put("M19/Beast", "https://api.scryfall.com/cards/tm19/12/en?format=image");
put("M19/Cat", "https://api.scryfall.com/cards/tm19/3/en?format=image");
put("M19/Dragon/1", "https://api.scryfall.com/cards/tm19/9/en?format=image");
put("M19/Dragon/2", "https://api.scryfall.com/cards/tm19/10/en?format=image");
put("M19/Elf Warrior", "https://api.scryfall.com/cards/tm19/13/en?format=image");
put("M19/Goblin", "https://api.scryfall.com/cards/tm19/11/en?format=image");
put("M19/Knight", "https://api.scryfall.com/cards/tm19/4/en?format=image");
put("M19/Ox", "https://api.scryfall.com/cards/tm19/5/en?format=image");
put("M19/Soldier", "https://api.scryfall.com/cards/tm19/6/en?format=image");
put("M19/Emblem Tezzeret, Artifice Master", "https://api.scryfall.com/cards/tm19/16/en?format=image");
put("M19/Thopter", "https://api.scryfall.com/cards/tm19/14/en?format=image");
put("M19/Emblem Vivien Reid", "https://api.scryfall.com/cards/tm19/17/en?format=image");
put("M19/Zombie", "https://api.scryfall.com/cards/tm19/8/en?format=image");
// M20
put("M20/Ajani's Pridemate", "https://api.scryfall.com/cards/tm20/1/en?format=image");
put("M20/Emblem Chandra, Awakened Inferno", "https://api.scryfall.com/cards/tm20/11/en?format=image");
put("M20/Demon", "https://api.scryfall.com/cards/tm20/5/en?format=image");
put("M20/Elemental Bird", "https://api.scryfall.com/cards/tm20/4/en?format=image");
put("M20/Elemental", "https://api.scryfall.com/cards/tm20/7/en?format=image");
put("M20/Golem", "https://api.scryfall.com/cards/tm20/9/en?format=image");
put("M20/Emblem Mu Yanling, Sky Dancer", "https://api.scryfall.com/cards/tm20/12/en?format=image");
put("M20/Soldier", "https://api.scryfall.com/cards/tm20/2/en?format=image");
put("M20/Spirit", "https://api.scryfall.com/cards/tm20/3/en?format=image");
put("M20/Treasure", "https://api.scryfall.com/cards/tm20/10/en?format=image");
put("M20/Wolf", "https://api.scryfall.com/cards/tm20/8/en?format=image");
put("M20/Zombie", "https://api.scryfall.com/cards/tm20/6/en?format=image");
// C18
put("C18/Angel", "https://api.scryfall.com/cards/tc18/3/en?format=image");
put("C18/Cat Warrior", "https://api.scryfall.com/cards/tc18/15/en?format=image");
put("C18/Cat", "https://api.scryfall.com/cards/tc18/5/en?format=image");
put("C18/Clue", "https://api.scryfall.com/cards/tc18/19/en?format=image");
put("C18/Construct/1", "https://api.scryfall.com/cards/tc18/20/en?format=image");
put("C18/Construct/2", "https://api.scryfall.com/cards/tc18/21/en?format=image");
put("C18/Dragon Egg", "https://api.scryfall.com/cards/tc18/10/en?format=image");
put("C18/Dragon", "https://api.scryfall.com/cards/tc18/11/en?format=image");
put("C18/Elemental", "https://api.scryfall.com/cards/tc18/16/en?format=image");
put("C18/Horror", "https://api.scryfall.com/cards/tc18/22/en?format=image");
put("C18/Manifest", "https://api.scryfall.com/cards/tc18/1/en?format=image");
put("C18/Mask", "https://api.scryfall.com/cards/tc18/4/en?format=image");
put("C18/Myr", "https://api.scryfall.com/cards/tc18/7/en?format=image");
put("C18/Plant", "https://api.scryfall.com/cards/tc18/17/en?format=image");
put("C18/Servo", "https://api.scryfall.com/cards/tc18/24/en?format=image");
put("C18/Survivor", "https://api.scryfall.com/cards/tc18/12/en?format=image");
put("C18/Thopter/1", "https://api.scryfall.com/cards/tc18/25/en?format=image");
put("C18/Thopter/2", "https://api.scryfall.com/cards/tc18/26/en?format=image");
put("C18/Thopter/3", "https://api.scryfall.com/cards/tc18/8/en?format=image");
put("C18/Worm", "https://api.scryfall.com/cards/tc18/18/en?format=image");
put("C18/Zombie", "https://api.scryfall.com/cards/tc18/9/en?format=image");
//C19
put("C19/Assassin", "https://api.scryfall.com/cards/tc19/9/en?format=image");
put("C19/Beast/1", "https://api.scryfall.com/cards/tc19/13/en?format=image");
put("C19/Beast/2", "https://api.scryfall.com/cards/tc19/14/en?format=image");
put("C19/Bird/1", "https://api.scryfall.com/cards/tc19/2/en?format=image");
put("C19/Bird/2", "https://api.scryfall.com/cards/tc19/1/en?format=image");
put("C19/Centaur", "https://api.scryfall.com/cards/tc19/15/en?format=image");
put("C19/Dragon", "https://api.scryfall.com/cards/tc19/12/en?format=image");
put("C19/Drake", "https://api.scryfall.com/cards/tc19/8/en?format=image");
put("C19/Egg", "https://api.scryfall.com/cards/tc19/16/en?format=image");
put("C19/Eldrazi", "https://api.scryfall.com/cards/tc19/26/en?format=image");
put("C19/Gargoyle", "https://api.scryfall.com/cards/tc19/22/en?format=image");
put("C19/Horror", "https://api.scryfall.com/cards/tc19/23/en?format=image");
put("C19/Human", "https://api.scryfall.com/cards/tc19/3/en?format=image");
put("C19/Emblem Ob Nixilis Reignited", "https://api.scryfall.com/cards/tc19/29/en?format=image");
put("C19/Pegasus", "https://api.scryfall.com/cards/tc19/4/en?format=image");
put("C19/Plant", "https://api.scryfall.com/cards/tc19/17/en?format=image");
put("C19/Rhino", "https://api.scryfall.com/cards/tc19/18/en?format=image");
put("C19/Saproling", "https://api.scryfall.com/cards/tc19/19/en?format=image");
put("C19/Sculpture", "https://api.scryfall.com/cards/tc19/24/en?format=image");
put("C19/Snake", "https://api.scryfall.com/cards/tc19/20/en?format=image");
put("C19/Spirit", "https://api.scryfall.com/cards/tc19/5/en?format=image");
put("C19/Treasure", "https://api.scryfall.com/cards/tc19/25/en?format=image");
put("C19/Wurm", "https://api.scryfall.com/cards/tc19/21/en?format=image");
put("C19/Zombie/1", "https://api.scryfall.com/cards/tc19/11/en?format=image");
put("C19/Zombie/2", "https://api.scryfall.com/cards/tc19/10/en?format=image");
// ELD
put("ELD/Bear", "https://api.scryfall.com/cards/teld/8/en?format=image");
put("ELD/Boar", "https://api.scryfall.com/cards/teld/9/en?format=image");
put("ELD/Dwarf", "https://api.scryfall.com/cards/teld/7/en?format=image");
put("ELD/Faerie", "https://api.scryfall.com/cards/teld/5/en?format=image");
put("ELD/Food/1", "https://api.scryfall.com/cards/teld/15/en?format=image");
put("ELD/Food/2", "https://api.scryfall.com/cards/teld/16/en?format=image");
put("ELD/Food/3", "https://api.scryfall.com/cards/teld/17/en?format=image");
put("ELD/Food/4", "https://api.scryfall.com/cards/teld/18/en?format=image");
put("ELD/Emblem Garruk, Cursed Huntsman", "https://api.scryfall.com/cards/teld/19/en?format=image");
put("ELD/Giant", "https://api.scryfall.com/cards/teld/10/en?format=image");
put("ELD/Goat", "https://api.scryfall.com/cards/teld/1/en?format=image");
put("ELD/Human Cleric", "https://api.scryfall.com/cards/teld/11/en?format=image");
put("ELD/Human Rogue", "https://api.scryfall.com/cards/teld/12/en?format=image");
put("ELD/Human Warrior", "https://api.scryfall.com/cards/teld/13/en?format=image");
put("ELD/Human", "https://api.scryfall.com/cards/teld/2/en?format=image");
put("ELD/Knight", "https://api.scryfall.com/cards/teld/3/en?format=image");
put("ELD/Mouse", "https://api.scryfall.com/cards/teld/4/en?format=image");
put("ELD/Rat", "https://api.scryfall.com/cards/teld/6/en?format=image");
put("ELD/Wolf", "https://api.scryfall.com/cards/teld/14/en?format=image");
// generate supported sets // generate supported sets
supportedSets.clear(); supportedSets.clear();
for (String cardName : this.keySet()) { for (String cardName : this.keySet()) {

View file

@ -2,6 +2,7 @@ package org.mage.plugins.card.dl.sources;
import mage.constants.SubType; import mage.constants.SubType;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.mage.plugins.card.dl.DownloadServiceInfo;
import org.mage.plugins.card.images.CardDownloadData; import org.mage.plugins.card.images.CardDownloadData;
import org.mage.plugins.card.images.DownloadPicturesService; import org.mage.plugins.card.images.DownloadPicturesService;
import org.mage.plugins.card.utils.CardImageUtils; import org.mage.plugins.card.utils.CardImageUtils;
@ -50,6 +51,11 @@ public enum TokensMtgImageSource implements CardImageSource {
return null; return null;
} }
@Override
public boolean prepareDownloadList(DownloadServiceInfo downloadServiceInfo, List<CardDownloadData> downloadList) {
return true;
}
@Override @Override
public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception {
return null; return null;
@ -180,7 +186,7 @@ public enum TokensMtgImageSource implements CardImageSource {
private HashMap<String, List<TokenData>> getTokensData() throws IOException { private HashMap<String, List<TokenData>> getTokensData() throws IOException {
synchronized (tokensDataSync) { synchronized (tokensDataSync) {
if (tokensData == null) { if (tokensData == null) {
DownloadPicturesService.getInstance().updateAndViewMessage("Find tokens data..."); DownloadPicturesService.getInstance().updateMessage("Find tokens data...");
tokensData = new HashMap<>(); tokensData = new HashMap<>();
// get tokens data from resource file // get tokens data from resource file
@ -231,10 +237,11 @@ public enum TokensMtgImageSource implements CardImageSource {
} }
} }
} }
DownloadPicturesService.getInstance().updateAndViewMessage(""); DownloadPicturesService.getInstance().updateMessage("");
DownloadPicturesService.getInstance().showDownloadControls(true);
} catch (Exception ex) { } catch (Exception ex) {
logger.warn("Failed to get tokens description from tokens.mtg.onl", ex); logger.warn("Failed to get tokens description from tokens.mtg.onl", ex);
DownloadPicturesService.getInstance().updateAndViewMessage(ex.getMessage()); DownloadPicturesService.getInstance().updateMessage(ex.getMessage());
} }
} }
} }

View file

@ -9,6 +9,7 @@ import org.apache.log4j.Logger;
import org.jsoup.nodes.Document; import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element; import org.jsoup.nodes.Element;
import org.jsoup.select.Elements; import org.jsoup.select.Elements;
import org.mage.plugins.card.dl.DownloadServiceInfo;
import org.mage.plugins.card.images.CardDownloadData; import org.mage.plugins.card.images.CardDownloadData;
import org.mage.plugins.card.utils.CardImageUtils; import org.mage.plugins.card.utils.CardImageUtils;
@ -451,6 +452,11 @@ public enum WizardCardsImageSource implements CardImageSource {
return null; return null;
} }
@Override
public boolean prepareDownloadList(DownloadServiceInfo downloadServiceInfo, List<CardDownloadData> downloadList) {
return true;
}
@Override @Override
public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception {
String collectorId = card.getCollectorId(); String collectorId = card.getCollectorId();
@ -495,8 +501,8 @@ public enum WizardCardsImageSource implements CardImageSource {
} }
} }
} }
if (link != null && !link.startsWith("http://")) { if (link != null && !link.startsWith("https://")) {
link = "http://gatherer.wizards.com" + link; link = "https://gatherer.wizards.com" + link;
} }
if (link != null) { if (link != null) {
@ -522,7 +528,7 @@ public enum WizardCardsImageSource implements CardImageSource {
int firstMultiverseIdLastPage = 0; int firstMultiverseIdLastPage = 0;
Pages: Pages:
while (page < 999) { while (page < 999) {
String searchUrl = "http://gatherer.wizards.com/Pages/Search/Default.aspx?sort=cn+&page=" + page + "&action=advanced&output=spoiler&method=visual&set=+%5B%22" + URLSetName + "%22%5D"; String searchUrl = "https://gatherer.wizards.com/Pages/Search/Default.aspx?sort=cn+&page=" + page + "&action=advanced&output=spoiler&method=visual&set=+%5B%22" + URLSetName + "%22%5D";
logger.debug("URL: " + searchUrl); logger.debug("URL: " + searchUrl);
Document doc = CardImageUtils.downloadHtmlDocument(searchUrl); Document doc = CardImageUtils.downloadHtmlDocument(searchUrl);
Elements cardsImages = doc.select("img[src^=../../Handlers/]"); Elements cardsImages = doc.select("img[src^=../../Handlers/]");
@ -582,7 +588,7 @@ public enum WizardCardsImageSource implements CardImageSource {
criteria.setCodes(cardSet); criteria.setCodes(cardSet);
List<CardInfo> cards = CardRepository.instance.findCards(criteria); List<CardInfo> cards = CardRepository.instance.findCards(criteria);
String urlLandDocument = "http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=" + multiverseId; String urlLandDocument = "https://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=" + multiverseId;
Document landDoc = CardImageUtils.downloadHtmlDocument(urlLandDocument); Document landDoc = CardImageUtils.downloadHtmlDocument(urlLandDocument);
Elements variations = landDoc.select("a.variationlink"); Elements variations = landDoc.select("a.variationlink");
if (!variations.isEmpty()) { if (!variations.isEmpty()) {
@ -629,7 +635,7 @@ public enum WizardCardsImageSource implements CardImageSource {
} }
private HashMap<String, Integer> getlocalizedMultiverseIds(Integer englishMultiverseId) throws IOException { private HashMap<String, Integer> getlocalizedMultiverseIds(Integer englishMultiverseId) throws IOException {
String cardLanguagesUrl = "http://gatherer.wizards.com/Pages/Card/Languages.aspx?multiverseid=" + englishMultiverseId; String cardLanguagesUrl = "https://gatherer.wizards.com/Pages/Card/Languages.aspx?multiverseid=" + englishMultiverseId;
Document cardLanguagesDoc = CardImageUtils.downloadHtmlDocument(cardLanguagesUrl); Document cardLanguagesDoc = CardImageUtils.downloadHtmlDocument(cardLanguagesUrl);
Elements languageTableRows = cardLanguagesDoc.select("tr.cardItem"); Elements languageTableRows = cardLanguagesDoc.select("tr.cardItem");
HashMap<String, Integer> localizedIds = new HashMap<>(); HashMap<String, Integer> localizedIds = new HashMap<>();

View file

@ -16,6 +16,7 @@ import net.java.truevfs.access.TFileOutputStream;
import net.java.truevfs.access.TVFS; import net.java.truevfs.access.TVFS;
import net.java.truevfs.kernel.spec.FsSyncException; import net.java.truevfs.kernel.spec.FsSyncException;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.mage.plugins.card.dl.DownloadServiceInfo;
import org.mage.plugins.card.dl.sources.*; import org.mage.plugins.card.dl.sources.*;
import org.mage.plugins.card.utils.CardImageUtils; import org.mage.plugins.card.utils.CardImageUtils;
@ -37,7 +38,7 @@ import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir;
/** /**
* @author JayDi85 * @author JayDi85
*/ */
public class DownloadPicturesService extends DefaultBoundedRangeModel implements Runnable { public class DownloadPicturesService extends DefaultBoundedRangeModel implements DownloadServiceInfo, Runnable {
// don't forget to remove new sets from ignore.urls to download (properties file in resources) // don't forget to remove new sets from ignore.urls to download (properties file in resources)
private static DownloadPicturesService instance; private static DownloadPicturesService instance;
@ -65,7 +66,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
private static CardImageSource selectedSource; private static CardImageSource selectedSource;
private final Object sync = new Object(); private final Object sync = new Object();
private Proxy p = Proxy.NO_PROXY; private Proxy proxy = Proxy.NO_PROXY;
enum DownloadSources { enum DownloadSources {
WIZARDS("1. wizards.com - low quality CARDS, multi-language, slow download", WizardCardsImageSource.instance), WIZARDS("1. wizards.com - low quality CARDS, multi-language, slow download", WizardCardsImageSource.instance),
@ -118,7 +119,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
instance.setNeedCancel(true); instance.setNeedCancel(true);
} }
private boolean getNeedCancel() { public boolean isNeedCancel() {
return this.needCancel || (this.errorCount > MAX_ERRORS_COUNT_BEFORE_CANCEL); return this.needCancel || (this.errorCount > MAX_ERRORS_COUNT_BEFORE_CANCEL);
} }
@ -126,8 +127,12 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
this.needCancel = needCancel; this.needCancel = needCancel;
} }
private void incErrorCount() { public void incErrorCount() {
this.errorCount = this.errorCount + 1; this.errorCount = this.errorCount + 1;
if (this.errorCount == MAX_ERRORS_COUNT_BEFORE_CANCEL + 1) {
logger.warn("Too many errors (> " + MAX_ERRORS_COUNT_BEFORE_CANCEL + ") in images download");
}
} }
private void resetErrorCount() { private void resetErrorCount() {
@ -196,23 +201,24 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
} }
public void findMissingCards() { public void findMissingCards() {
updateAndViewMessage("Loading..."); updateMessage("Loading...");
this.cardsAll.clear(); this.cardsAll.clear();
this.cardsMissing.clear(); this.cardsMissing.clear();
this.cardsDownloadQueue.clear(); this.cardsDownloadQueue.clear();
updateAndViewMessage("Loading cards list..."); updateMessage("Loading cards list...");
this.cardsAll = Collections.synchronizedList(CardRepository.instance.findCards(new CardCriteria())); this.cardsAll = Collections.synchronizedList(CardRepository.instance.findCards(new CardCriteria()));
updateAndViewMessage("Finding missing images..."); updateMessage("Finding missing images...");
this.cardsMissing = prepareMissingCards(this.cardsAll, uiDialog.getRedownloadCheckbox().isSelected()); this.cardsMissing = prepareMissingCards(this.cardsAll, uiDialog.getRedownloadCheckbox().isSelected());
updateAndViewMessage("Finding available sets from selected source..."); updateMessage("Finding available sets from selected source...");
this.uiDialog.getSetsCombo().setModel(new DefaultComboBoxModel<>(getSetsForCurrentImageSource())); this.uiDialog.getSetsCombo().setModel(new DefaultComboBoxModel<>(getSetsForCurrentImageSource()));
reloadCardsToDownload(this.uiDialog.getSetsCombo().getSelectedItem().toString()); reloadCardsToDownload(this.uiDialog.getSetsCombo().getSelectedItem().toString());
this.uiDialog.showDownloadControls(true); this.uiDialog.showDownloadControls(true);
updateAndViewMessage(""); updateMessage("");
showDownloadControls(true);
} }
private void reloadLanguagesForSelectedSource() { private void reloadLanguagesForSelectedSource() {
@ -237,13 +243,13 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
} }
} }
public void updateAndViewMessage(String text) { public void updateMessage(String text) {
this.uiDialog.setGlobalInfo(text); this.uiDialog.setGlobalInfo(text);
}
// auto-size on empty message (on complete) public void showDownloadControls(boolean needToShow) {
if (text.isEmpty()) { // auto-size form on show
this.uiDialog.showDownloadControls(true); this.uiDialog.showDownloadControls(needToShow);
}
} }
private String getSetNameWithYear(ExpansionSet exp) { private String getSetNameWithYear(ExpansionSet exp) {
@ -433,7 +439,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
throw new IllegalStateException("Second side card can't have empty name."); throw new IllegalStateException("Second side card can't have empty name.");
} }
CardInfo secondSideCard = CardRepository.instance.findCard(card.getSecondSideName()); CardInfo secondSideCard = CardRepository.instance.findCardWPreferredSet(card.getSecondSideName(), card.getSetCode(), false);
if (secondSideCard == null) { if (secondSideCard == null) {
throw new IllegalStateException("Can''t find second side card in database: " + card.getSecondSideName()); throw new IllegalStateException("Can''t find second side card in database: " + card.getSecondSideName());
} }
@ -541,9 +547,11 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
CardDownloadData card = new CardDownloadData(params[3], set, "0", false, type, "", "", true, fileName); CardDownloadData card = new CardDownloadData(params[3], set, "0", false, type, "", "", true, fileName);
card.setTokenClassName(tokenClassName); card.setTokenClassName(tokenClassName);
list.add(card); list.add(card);
} else {
logger.error("wrong line format in tokens file: " + line);
} }
} else { } else {
logger.error("wrong format for image urls: " + line); logger.error("wrong line data in tokens file: " + line);
} }
} }
line = reader.readLine(); line = reader.readLine();
@ -569,6 +577,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
@Override @Override
public void run() { public void run() {
this.cardIndex = 0; this.cardIndex = 0;
this.resetErrorCount();
File base = new File(getImagesDir()); File base = new File(getImagesDir());
if (!base.exists()) { if (!base.exists()) {
@ -587,7 +596,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
break; break;
case NONE: case NONE:
default: default:
p = Proxy.NO_PROXY; proxy = Proxy.NO_PROXY;
break; break;
} }
@ -595,67 +604,69 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
try { try {
String address = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_ADDRESS, ""); String address = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_ADDRESS, "");
Integer port = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_PORT, "80")); Integer port = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_PORT, "80"));
p = new Proxy(type, new InetSocketAddress(address, port)); proxy = new Proxy(type, new InetSocketAddress(address, port));
} catch (Exception ex) { } catch (Exception ex) {
throw new RuntimeException("Gui_DownloadPicturesService : error 1 - " + ex); throw new RuntimeException("Gui_DownloadPicturesService : error 1 - " + ex);
} }
} }
if (p != null) { if (proxy != null) {
update(0, cardsDownloadQueue.size());
logger.info("Started download of " + cardsDownloadQueue.size() + " images" logger.info("Started download of " + cardsDownloadQueue.size() + " images"
+ " from source: " + selectedSource.getSourceName() + " from source: " + selectedSource.getSourceName()
+ ", language: " + selectedSource.getCurrentLanguage().getCode()); + ", language: " + selectedSource.getCurrentLanguage().getCode());
uiDialog.getProgressBar().setString("Preparing download list...");
if (selectedSource.prepareDownloadList(this, cardsDownloadQueue)) {
update(0, cardsDownloadQueue.size());
int numberOfThreads = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_THREADS, "10"));
ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
for (int i = 0; i < cardsDownloadQueue.size() && !this.isNeedCancel(); i++) {
try {
CardDownloadData card = cardsDownloadQueue.get(i);
int numberOfThreads = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_THREADS, "10")); logger.debug("Downloading image: " + card.getName() + " (" + card.getSet() + ')');
ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
for (int i = 0; i < cardsDownloadQueue.size() && !this.getNeedCancel(); i++) {
try {
CardDownloadData card = cardsDownloadQueue.get(i);
logger.debug("Downloading image: " + card.getName() + " (" + card.getSet() + ')'); CardImageUrls urls;
if (card.isToken()) {
CardImageUrls urls; if (!"0".equals(card.getCollectorId())) {
if (card.isToken()) { continue;
if (!"0".equals(card.getCollectorId())) {
continue;
}
urls = selectedSource.generateTokenUrl(card);
} else {
urls = selectedSource.generateCardUrl(card);
}
if (urls == null) {
String imageRef = selectedSource.getNextHttpImageUrl();
String fileName = selectedSource.getFileForHttpImage(imageRef);
if (imageRef != null && fileName != null) {
imageRef = selectedSource.getSourceName() + imageRef;
try {
card.setToken(selectedSource.isTokenSource());
Runnable task = new DownloadTask(card, imageRef, fileName, selectedSource.getTotalImages());
executor.execute(task);
} catch (Exception ex) {
}
} else if (selectedSource.getTotalImages() == -1) {
logger.info("Image not available on " + selectedSource.getSourceName() + ": " + card.getName() + " (" + card.getSet() + ')');
synchronized (sync) {
update(cardIndex + 1, cardsDownloadQueue.size());
} }
urls = selectedSource.generateTokenUrl(card);
} else {
urls = selectedSource.generateCardUrl(card);
} }
} else {
Runnable task = new DownloadTask(card, urls, cardsDownloadQueue.size()); if (urls == null) {
executor.execute(task); String imageRef = selectedSource.getNextHttpImageUrl();
String fileName = selectedSource.getFileForHttpImage(imageRef);
if (imageRef != null && fileName != null) {
imageRef = selectedSource.getSourceName() + imageRef;
try {
card.setToken(selectedSource.isTokenSource());
Runnable task = new DownloadTask(card, imageRef, fileName, selectedSource.getTotalImages());
executor.execute(task);
} catch (Exception ex) {
}
} else if (selectedSource.getTotalImages() == -1) {
logger.info("Image not available on " + selectedSource.getSourceName() + ": " + card.getName() + " (" + card.getSet() + ')');
synchronized (sync) {
update(cardIndex + 1, cardsDownloadQueue.size());
}
}
} else {
Runnable task = new DownloadTask(card, urls, cardsDownloadQueue.size());
executor.execute(task);
}
} catch (Exception ex) {
logger.error(ex, ex);
} }
} catch (Exception ex) {
logger.error(ex, ex);
} }
}
executor.shutdown(); executor.shutdown();
while (!executor.isTerminated()) { while (!executor.isTerminated()) {
try { try {
TimeUnit.SECONDS.sleep(1); TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ie) { } catch (InterruptedException ie) {
}
} }
} }
} }
@ -671,6 +682,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
// stop // stop
reloadCardsToDownload(uiDialog.getSetsCombo().getSelectedItem().toString()); reloadCardsToDownload(uiDialog.getSetsCombo().getSelectedItem().toString());
enableDialogButtons();
// reset images cache // reset images cache
ImageCache.clearCache(); ImageCache.clearCache();
@ -707,7 +719,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
@Override @Override
public void run() { public void run() {
if (DownloadPicturesService.getInstance().getNeedCancel()) { if (DownloadPicturesService.getInstance().isNeedCancel()) {
synchronized (sync) { synchronized (sync) {
update(cardIndex + 1, count); update(cardIndex + 1, count);
} }
@ -791,14 +803,14 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
URL url = new URL(currentUrl); URL url = new URL(currentUrl);
// on download cancel need to stop // on download cancel need to stop
if (DownloadPicturesService.getInstance().getNeedCancel()) { if (DownloadPicturesService.getInstance().isNeedCancel()) {
return; return;
} }
// download // download
selectedSource.doPause(url.getPath()); selectedSource.doPause(url.getPath());
httpConn = url.openConnection(p); httpConn = url.openConnection(proxy);
if (httpConn != null) { if (httpConn != null) {
httpConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2"); httpConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2");
@ -838,7 +850,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
} }
// can save result // can save result
if (isDownloadOK & httpConn != null) { if (isDownloadOK && httpConn != null) {
// save data to temp // save data to temp
try (InputStream in = new BufferedInputStream(httpConn.getInputStream()); try (InputStream in = new BufferedInputStream(httpConn.getInputStream());
OutputStream tfileout = new TFileOutputStream(fileTempImage); OutputStream tfileout = new TFileOutputStream(fileTempImage);
@ -847,7 +859,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
int len; int len;
while ((len = in.read(buf)) != -1) { while ((len = in.read(buf)) != -1) {
// user cancelled // user cancelled
if (DownloadPicturesService.getInstance().getNeedCancel()) { if (DownloadPicturesService.getInstance().isNeedCancel()) {
// stop download, save current state and exit // stop download, save current state and exit
TFile archive = destFile.getTopLevelArchive(); TFile archive = destFile.getTopLevelArchive();
///* not need to unmout/close - it's auto action ///* not need to unmout/close - it's auto action
@ -934,14 +946,21 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
// try download again // try download again
} }
this.uiDialog.getRedownloadCheckbox().setSelected(false); enableDialogButtons();
uiDialog.enableActionControls(true);
uiDialog.getStartButton().setEnabled(true);
} }
} }
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private void enableDialogButtons() {
uiDialog.getRedownloadCheckbox().setSelected(false); // reset re-download button after finished
uiDialog.enableActionControls(true);
uiDialog.getStartButton().setEnabled(true);
}
public Proxy getProxy() {
return proxy;
}
} }
class LoadMissingCardDataNew implements Runnable { class LoadMissingCardDataNew implements Runnable {

View file

@ -54,6 +54,7 @@
|Generate|EMBLEM!:C14|Emblem Nixilis|||ObNixilisOfTheBlackOathEmblem| |Generate|EMBLEM!:C14|Emblem Nixilis|||ObNixilisOfTheBlackOathEmblem|
|Generate|EMBLEM!:C14|Emblem Teferi|||TeferiTemporalArchmageEmblem| |Generate|EMBLEM!:C14|Emblem Teferi|||TeferiTemporalArchmageEmblem|
|Generate|EMBLEM!:C16|Emblem Daretti|||DarettiScrapSavantEmblem| |Generate|EMBLEM!:C16|Emblem Daretti|||DarettiScrapSavantEmblem|
|Generate|EMBLEM:C19|Ob Nixilis Reignited||Emblem Nixilis|ObNixilisReignitedEmblem|
|Generate|EMBLEM!:CNS|Emblem Dack Fayden||Emblem Dack|DackFaydenEmblem| |Generate|EMBLEM!:CNS|Emblem Dack Fayden||Emblem Dack|DackFaydenEmblem|
|Generate|EMBLEM!:DTK|Emblem Narset|||NarsetTranscendentEmblem| |Generate|EMBLEM!:DTK|Emblem Narset|||NarsetTranscendentEmblem|
|Generate|EMBLEM!:EMA|Emblem Dack Fayden||Emblem Dack|DackFaydenEmblem| |Generate|EMBLEM!:EMA|Emblem Dack Fayden||Emblem Dack|DackFaydenEmblem|
@ -62,7 +63,6 @@
|Generate|EMBLEM!:KLD|Emblem Chandra|||ChandraTorchOfDefianceEmblem| |Generate|EMBLEM!:KLD|Emblem Chandra|||ChandraTorchOfDefianceEmblem|
|Generate|EMBLEM!:KLD|Emblem Dovin|||DovinBaanEmblem| |Generate|EMBLEM!:KLD|Emblem Dovin|||DovinBaanEmblem|
|Generate|EMBLEM!:KLD|Emblem Nissa|||NissaVitalForceEmblem| |Generate|EMBLEM!:KLD|Emblem Nissa|||NissaVitalForceEmblem|
|Generate|EMBLEM!:KLD|Emblem Tezzeret|||TezzeretTheSchemerEmblem|
|Generate|EMBLEM!:KTK|Emblem Sarkhan|||SarkhanTheDragonspeakerEmblem| |Generate|EMBLEM!:KTK|Emblem Sarkhan|||SarkhanTheDragonspeakerEmblem|
|Generate|EMBLEM!:KTK|Emblem Sorin|||SorinSolemnVisitorEmblem| |Generate|EMBLEM!:KTK|Emblem Sorin|||SorinSolemnVisitorEmblem|
|Generate|EMBLEM!:M15|Emblem Ajani|||AjaniSteadfastEmblem| |Generate|EMBLEM!:M15|Emblem Ajani|||AjaniSteadfastEmblem|
@ -88,6 +88,19 @@
|Generate|EMBLEM:RIX|Huatli, Radiant Champion||Emblem Huatli|HuatliRadiantChampionEmblem| |Generate|EMBLEM:RIX|Huatli, Radiant Champion||Emblem Huatli|HuatliRadiantChampionEmblem|
|Generate|EMBLEM:RNA|Domri, Chaos Bringer||Emblem Domri|DomriChaosBringerEmblem| |Generate|EMBLEM:RNA|Domri, Chaos Bringer||Emblem Domri|DomriChaosBringerEmblem|
|Generate|EMBLEM:WAR|Nissa, Who Shakes the World||Emblem Nissa|NissaWhoShakesTheWorldEmblem| |Generate|EMBLEM:WAR|Nissa, Who Shakes the World||Emblem Nissa|NissaWhoShakesTheWorldEmblem|
|Generate|EMBLEM:MH1|Serra the Benevolent||Emblem Serra|SerraTheBenevolentEmblem|
|Generate|EMBLEM:MH1|Wrenn and Six||Emblem Wrenn|WrennAndSixEmblem|
|Generate|EMBLEM:M19|Ajani, Adversary of Tyrants||Emblem Ajani|AjaniAdversaryOfTyrantsEmblem|
|Generate|EMBLEM:M19|Tezzeret, Artifice Master||Emblem Tezzeret|TezzeretArtificeMasterEmblem|
|Generate|EMBLEM:M19|Vivien Reid||Emblem Vivien|VivienReidEmblem|
|Generate|EMBLEM:M20|Chandra, Awakened Inferno||Emblem Chandra|ChandraAwakenedInfernoEmblem|
|Generate|EMBLEM:M20|Mu Yanling, Sky Dancer||Emblem Yanling|MuYanlingSkyDancerEmblem|
|Generate|EMBLEM:GRN|Ral, Izzet Viceroy||Emblem Ral|RalIzzetViceroyEmblem|
|Generate|EMBLEM:GRN|Vraska, Golgari Queen||Emblem Vraska|VraskaGolgariQueenEmblem|
|Generate|EMBLEM:DOM|Jaya Ballard||Emblem Jaya Ballard|JayaBallardEmblem|
|Generate|EMBLEM:DOM|Teferi, Hero of Dominaria||Emblem Teferi|TeferiHeroOfDominariaEmblem|
|Generate|EMBLEM:AER|Tezzeret the Schemer||Emblem Tezzeret|TezzeretTheSchemerEmblem|
|Generate|EMBLEM:ELD|Garruk, Cursed Huntsman||Emblem Garruk|GarrukCursedHuntsmanEmblem|
|Generate|PLANE:PCA|Plane - Academy At Tolaria West|||AcademyAtTolariaWestPlane| |Generate|PLANE:PCA|Plane - Academy At Tolaria West|||AcademyAtTolariaWestPlane|
|Generate|PLANE:PCA|Plane - Agyrem|||AgyremPlane| |Generate|PLANE:PCA|Plane - Agyrem|||AgyremPlane|
|Generate|PLANE:PCA|Plane - Akoum|||AkoumPlane| |Generate|PLANE:PCA|Plane - Akoum|||AkoumPlane|
@ -149,32 +162,33 @@
|Generate|TOK:8ED|Rukh|| |Generate|TOK:8ED|Rukh||
|Generate|TOK:9ED|Bird|||RukhEggBirdToken| |Generate|TOK:9ED|Bird|||RukhEggBirdToken|
|Generate|TOK:9ED|Saproling|||SaprolingToken| |Generate|TOK:9ED|Saproling|||SaprolingToken|
|Generate|TOK:AER|Etherium Cell|| |Generate|TOK:AER|Etherium Cell|||EtheriumCellToken|
|Generate|TOK:AER|Gremlin|| |Generate|TOK:AER|Gremlin|||GremlinToken|
|Generate|TOK:AER|Ragavan|| |Generate|TOK:AER|Ragavan|||RagavanToken|
|Generate|TOK:AKH|Angel of Sanctions||
|Generate|TOK:AKH|Anointer Priest||
|Generate|TOK:AKH|Aven Initiate||
|Generate|TOK:AKH|Aven Wind Guide||
|Generate|TOK:AKH|Beast|||BeastToken3| |Generate|TOK:AKH|Beast|||BeastToken3|
|Generate|TOK:AKH|Cat|||CatToken2| |Generate|TOK:AKH|Cat|||CatToken2|
|Generate|TOK:AKH|Drake|| |Generate|TOK:AKH|Drake|||DrakeToken|
|Generate|TOK:AKH|Glyph Keeper||
|Generate|TOK:AKH|Heart-Piercer Manticore||
|Generate|TOK:AKH|Hippo|||HippoToken2| |Generate|TOK:AKH|Hippo|||HippoToken2|
|Generate|TOK:AKH|Honored Hydra||
|Generate|TOK:AKH|Labyrinth Guardian||
|Generate|TOK:AKH|Oketra's Attendant||
|Generate|TOK:AKH|Sacred Cat||
|Generate|TOK:AKH|Snake|||DeathtouchSnakeToken| |Generate|TOK:AKH|Snake|||DeathtouchSnakeToken|
|Generate|TOK:AKH|Tah-Crop Skirmisher||
|Generate|TOK:AKH|Temmet, Vizier of Naktamun||
|Generate|TOK:AKH|Trueheart Duelist||
|Generate|TOK:AKH|Unwavering Initiate||
|Generate|TOK:AKH|Vizier of Many Faces||
|Generate|TOK:AKH|Warrior|||WarriorVigilantToken| |Generate|TOK:AKH|Warrior|||WarriorVigilantToken|
|Generate|TOK:AKH|Wurm|||WurmToken3| |Generate|TOK:AKH|Wurm|||WurmToken3|
|Generate|TOK:AKH|Zombie|| |Generate|TOK:AKH|Zombie|||ZombieToken
#TOK:AKH - some tokens from real cards (see Embalm ability)
#|Generate|TOK:AKH|Angel of Sanctions||
#|Generate|TOK:AKH|Anointer Priest||
#|Generate|TOK:AKH|Aven Initiate||
#|Generate|TOK:AKH|Aven Wind Guide||
#|Generate|TOK:AKH|Glyph Keeper||
#|Generate|TOK:AKH|Heart-Piercer Manticore||
#|Generate|TOK:AKH|Honored Hydra||
#|Generate|TOK:AKH|Labyrinth Guardian||
#|Generate|TOK:AKH|Oketra's Attendant||
#|Generate|TOK:AKH|Sacred Cat||
#|Generate|TOK:AKH|Tah-Crop Skirmisher||
#|Generate|TOK:AKH|Temmet, Vizier of Naktamun||
#|Generate|TOK:AKH|Trueheart Duelist||
#|Generate|TOK:AKH|Unwavering Initiate||
#|Generate|TOK:AKH|Vizier of Many Faces||
|Generate|TOK:ALA|Beast|||GodSireBeastToken| |Generate|TOK:ALA|Beast|||GodSireBeastToken|
|Generate|TOK:ALA|Dragon|||DragonToken| |Generate|TOK:ALA|Dragon|||DragonToken|
|Generate|TOK:ALA|Goblin|||GoblinTokenWithHaste| |Generate|TOK:ALA|Goblin|||GoblinTokenWithHaste|
@ -229,7 +243,7 @@
|Generate|TOK:BFZ|Eldrazi Scion|3||EldraziScionToken| |Generate|TOK:BFZ|Eldrazi Scion|3||EldraziScionToken|
|Generate|TOK:BFZ|Eldrazi|||EldraziToken| |Generate|TOK:BFZ|Eldrazi|||EldraziToken|
|Generate|TOK:BFZ|Elemental|1||OmnathElementalToken| |Generate|TOK:BFZ|Elemental|1||OmnathElementalToken|
|Generate|TOK:BFZ|Elemental|2||ElementalToken| |Generate|TOK:BFZ|Elemental|2||AkoumStonewakerElementalToken|
|Generate|TOK:BFZ|Knight Ally|||KnightAllyToken| |Generate|TOK:BFZ|Knight Ally|||KnightAllyToken|
|Generate|TOK:BFZ|Kor Ally|||KorAllyToken| |Generate|TOK:BFZ|Kor Ally|||KorAllyToken|
|Generate|TOK:BFZ|Octopus|||OctopusToken| |Generate|TOK:BFZ|Octopus|||OctopusToken|
@ -356,13 +370,56 @@
|Generate|TOK:C17|Cat Dragon|||WasitoraCatDragonToken| |Generate|TOK:C17|Cat Dragon|||WasitoraCatDragonToken|
|Generate|TOK:C17|Cat Warrior|| |Generate|TOK:C17|Cat Warrior||
|Generate|TOK:C17|Dragon|1||DragonToken| |Generate|TOK:C17|Dragon|1||DragonToken|
|Generate|TOK:C17|Dragon|2||UtavaraHellkiteDragonToken| |Generate|TOK:C17|Dragon|2||UtvaraHellkiteDragonToken|
|Generate|TOK:C17|Eldrazi Spawn|| |Generate|TOK:C17|Eldrazi Spawn||
|Generate|TOK:C17|Gold|| |Generate|TOK:C17|Gold||
|Generate|TOK:C17|Rat|||DeathtouchRatToken| |Generate|TOK:C17|Rat|||DeathtouchRatToken|
|Generate|TOK:C17|Vampire|||EdgarMarkovToken| |Generate|TOK:C17|Vampire|||EdgarMarkovToken|
|Generate|TOK:C17|Zombie|| |Generate|TOK:C17|Zombie||
|Generate|TOK:C18|Myr|||BrudicladTelchorMyrToken| |Generate|TOK:C18|Myr|||BrudicladTelchorMyrToken|
|Generate|TOK:C18|Angel|||AngelToken|
|Generate|TOK:C18|Cat|||CatToken|
|Generate|TOK:C18|Cat Warrior|||CatWarriorToken|
|Generate|TOK:C18|Clue|||ClueArtifactToken|
|Generate|TOK:C18|Construct|1||RetrofitterFoundryToken|
|Generate|TOK:C18|Construct|2||StoneTrapIdolToken|
|Generate|TOK:C18|Dragon|||DragonEggDragonToken|
|Generate|TOK:C18|Dragon Egg|||NestingDragonToken|
|Generate|TOK:C18|Elemental|||DokaiWeaverofLifeToken|
|Generate|TOK:C18|Horror|||PhyrexianRebirthHorrorToken|
|Generate|TOK:C18|Mask|||MaskToken|
|Generate|TOK:C18|Plant|||PlantToken|
|Generate|TOK:C18|Servo|||ServoToken|
|Generate|TOK:C18|Survivor|||SurvivorToken|
|Generate|TOK:C18|Thopter|1||ThopterColorlessToken|
|Generate|TOK:C18|Thopter|2||ThopterColorlessToken|
|Generate|TOK:C18|Thopter|3||ThopterColorlessToken|
|Generate|TOK:C18|Worm|||WormHarvestToken|
|Generate|TOK:C18|Zombie|||ZombieToken|
|Generate|TOK:C19|Assassin|||AssassinToken|
|Generate|TOK:C19|Beast|1||BeastToken|
|Generate|TOK:C19|Beast|2||BeastToken2|
|Generate|TOK:C19|Bird|1||RocEggToken|
|Generate|TOK:C19|Bird|2||WingmateRocToken|
|Generate|TOK:C19|Centaur|||CentaurToken|
|Generate|TOK:C19|Dragon|||DragonToken2|
|Generate|TOK:C19|Drake|||DrakeToken|
|Generate|TOK:C19|Egg|||AtlaPalaniToken|
|Generate|TOK:C19|Eldrazi|||EldraziToken|
|Generate|TOK:C19|Gargoyle|||GargoyleToken|
|Generate|TOK:C19|Horror|||PhyrexianRebirthHorrorToken|
|Generate|TOK:C19|Human|||HumanToken|
|Generate|TOK:C19|Pegasus|||PegasusToken|
|Generate|TOK:C19|Plant|||GrismoldPlantToken|
|Generate|TOK:C19|Rhino|||RhinoToken|
|Generate|TOK:C19|Saproling|||SaprolingToken|
|Generate|TOK:C19|Sculpture|||DoomedArtisanToken|
|Generate|TOK:C19|Snake|||SnakeToken|
|Generate|TOK:C19|Spirit|||SpiritToken|
|Generate|TOK:C19|Treasure|||TreasureToken|
|Generate|TOK:C19|Wurm|||WurmToken|
|Generate|TOK:C19|Zombie|1||ZombieToken|
|Generate|TOK:C19|Zombie|2||ZombieToken|
|Generate|TOK:CHK|Dragon Spirit|||TatsumaDragonToken| |Generate|TOK:CHK|Dragon Spirit|||TatsumaDragonToken|
|Generate|TOK:CHK|Elemental|||SeedGuardianToken| |Generate|TOK:CHK|Elemental|||SeedGuardianToken|
|Generate|TOK:CHK|Illusion|||MelokuTheCloudedMirrorToken| |Generate|TOK:CHK|Illusion|||MelokuTheCloudedMirrorToken|
@ -524,16 +581,16 @@
|Generate|TOK:DOM|Construct|||KarnConstructToken| |Generate|TOK:DOM|Construct|||KarnConstructToken|
|Generate|TOK:DOM|Demon|||BelzenlokDemonToken| |Generate|TOK:DOM|Demon|||BelzenlokDemonToken|
|Generate|TOK:DOM|Elemental|||ValdukElementalToken| |Generate|TOK:DOM|Elemental|||ValdukElementalToken|
|Gererate|TOK:DOM|Goblin|| |Generate|TOK:DOM|Goblin|||GoblinToken|
|Generate|TOK:DOM|Karox Bladewing|||KaroxBladewingDragonToken| |Generate|TOK:DOM|Karox Bladewing|||KaroxBladewingDragonToken|
|Generate|TOK:DOM|Knight|1| |Generate|TOK:DOM|Knight|1||KnightToken|
|Generate|TOK:DOM|Knight|2| |Generate|TOK:DOM|Knight|2||KnightToken|
|Generate|TOK:DOM|Nightmare Horror|||ChainersTormentNightmareToken| |Generate|TOK:DOM|Nightmare Horror|||ChainersTormentNightmareToken|
|Generate|TOK:DOM|Saproling|1| |Generate|TOK:DOM|Saproling|1||SaprolingToken|
|Generate|TOK:DOM|Saproling|2| |Generate|TOK:DOM|Saproling|2||SaprolingToken|
|Generate|TOK:DOM|Saproling|3| |Generate|TOK:DOM|Saproling|3||SaprolingToken|
|Generate|TOK:DOM|Soldier|| |Generate|TOK:DOM|Soldier|||SoldierToken|
|Generate|TOK:DOM|Zombie Knight|| |Generate|TOK:DOM|Zombie Knight|||ZombieKnightToken|
|Generate|TOK:DRB|Saproling|||SaprolingToken| |Generate|TOK:DRB|Saproling|||SaprolingToken|
|Generate|TOK:DST|Beast|||BeastToken| |Generate|TOK:DST|Beast|||BeastToken|
|Generate|TOK:DST|Elemental|1||WandOfTheElementsFirstToken| |Generate|TOK:DST|Elemental|1||WandOfTheElementsFirstToken|
@ -572,15 +629,16 @@
|Generate|TOK:EMA|Wall|||TidalWaveWallToken| |Generate|TOK:EMA|Wall|||TidalWaveWallToken|
|Generate|TOK:EMA|Wurm|||WurmToken| |Generate|TOK:EMA|Wurm|||WurmToken|
|Generate|TOK:EMA|Zombie|||ZombieToken| |Generate|TOK:EMA|Zombie|||ZombieToken|
|Generate|TOK:EMN|Devil|||DevilToken| #TOK:EMN - Human Soldier, Spirit, Devil, Insect and Wolf tokens from SOI set
#|Generate|TOK:EMN|Devil|||DevilToken|
#|Generate|TOK:EMN|Human Soldier|||HumanSoldierToken|
#|Generate|TOK:EMN|Insect|||InsectToken|
#|Generate|TOK:EMN|Spirit|||SpiritWhiteToken|
#|Generate|TOK:EMN|Wolf|||WolfToken|
|Generate|TOK:EMN|Eldrazi Horror|||EldraziHorrorToken| |Generate|TOK:EMN|Eldrazi Horror|||EldraziHorrorToken|
|Generate|TOK:EMN|Human Soldier|||HumanSoldierToken|
|Generate|TOK:EMN|Human Wizard|||HumanWizardToken| |Generate|TOK:EMN|Human Wizard|||HumanWizardToken|
|Generate|TOK:EMN|Human|||RedHumanToken| |Generate|TOK:EMN|Human|||RedHumanToken|
|Generate|TOK:EMN|Insect|||InsectToken|
|Generate|TOK:EMN|Spider|||SpiderToken| |Generate|TOK:EMN|Spider|||SpiderToken|
|Generate|TOK:EMN|Spirit|||SpiritWhiteToken|
|Generate|TOK:EMN|Wolf|||WolfToken|
|Generate|TOK:EMN|Zombie|1||ZombieToken| |Generate|TOK:EMN|Zombie|1||ZombieToken|
|Generate|TOK:EMN|Zombie|2||ZombieToken| |Generate|TOK:EMN|Zombie|2||ZombieToken|
|Generate|TOK:EMN|Zombie|3||ZombieToken| |Generate|TOK:EMN|Zombie|3||ZombieToken|
@ -650,19 +708,20 @@
|Generate|TOK:HOP|Pentavite|||PentaviteToken| |Generate|TOK:HOP|Pentavite|||PentaviteToken|
|Generate|TOK:HOP|Pest|||PestToken| |Generate|TOK:HOP|Pest|||PestToken|
|Generate|TOK:HOP|Saproling|||SaprolingToken| |Generate|TOK:HOP|Saproling|||SaprolingToken|
|Generate|TOK:HOU|Horse|||CrestedSunmareToken|
|Generate|TOK:HOU|Insect|||TheLocustGodInsectToken|
|Generate|TOK:HOU|Snake|||RhonassLastStandToken|
#TOK:HOU - some tokens from real cards (see Eternalize ability)
#TOK:HOU - Cat, Warrior and Zombie tokens from AKH set
|Generate|TOK:HOU|Adorned Pouncer|||| |Generate|TOK:HOU|Adorned Pouncer||||
|Generate|TOK:HOU|Champion of Wits|||| |Generate|TOK:HOU|Champion of Wits||||
|Generate|TOK:HOU|Dreamstealer|||| |Generate|TOK:HOU|Dreamstealer||||
|Generate|TOK:HOU|Earthshaker Khenra|||| |Generate|TOK:HOU|Earthshaker Khenra||||
|Generate|TOK:HOU|Horse|||CrestedSunmareToken|
|Generate|TOK:HOU|Insect|||TheLocustGodInsectToken|
|Generate|TOK:HOU|Proven Combatant|||| |Generate|TOK:HOU|Proven Combatant||||
|Generate|TOK:HOU|Resilient Khenra|||| |Generate|TOK:HOU|Resilient Khenra||||
|Generate|TOK:HOU|Sinuous Striker|||| |Generate|TOK:HOU|Sinuous Striker||||
|Generate|TOK:HOU|Snake|||RhonassLastStandToken|
|Generate|TOK:HOU|Steadfast Sentinel|||| |Generate|TOK:HOU|Steadfast Sentinel||||
|Generate|TOK:HOU|Sunscourge Champion|||| |Generate|TOK:HOU|Sunscourge Champion||||
|Generate|TOK:HOU|Zombie||
|Generate|TOK:ICE|Caribou|||CaribouToken| |Generate|TOK:ICE|Caribou|||CaribouToken|
|Generate|TOK:INV|Bird|||OwlToken| |Generate|TOK:INV|Bird|||OwlToken|
|Generate|TOK:INV|Elephant|||ElephantToken| |Generate|TOK:INV|Elephant|||ElephantToken|
@ -1199,6 +1258,12 @@
|Generate|TOK:RNA|Thopter|||ThopterToken| |Generate|TOK:RNA|Thopter|||ThopterToken|
|Generate|TOK:RNA|Treasure|||TreasureToken| |Generate|TOK:RNA|Treasure|||TreasureToken|
|Generate|TOK:RNA|Zombie|||ZombieToken| |Generate|TOK:RNA|Zombie|||ZombieToken|
|Generate|TOK:GRN|Angel|||AngelVigilanceToken|
|Generate|TOK:GRN|Bird Illusion|||BirdIllusionToken|
|Generate|TOK:GRN|Elf Knight|||ElfKnightToken|
|Generate|TOK:GRN|Goblin|||GoblinToken|
|Generate|TOK:GRN|Insect|||IzoniInsectToken|
|Generate|TOK:GRN|Soldier|||SoldierLifelinkToken|
|Generate|TOK:WAR|Angel|||AngelVigilanceToken| |Generate|TOK:WAR|Angel|||AngelVigilanceToken|
|Generate|TOK:WAR|Assassin|||AssassinToken2| |Generate|TOK:WAR|Assassin|||AssassinToken2|
|Generate|TOK:WAR|Devil|||DevilToken| |Generate|TOK:WAR|Devil|||DevilToken|
@ -1216,10 +1281,64 @@
|Generate|TOK:WAR|Zombie Army|1||ZombieArmyToken| |Generate|TOK:WAR|Zombie Army|1||ZombieArmyToken|
|Generate|TOK:WAR|Zombie Army|2||ZombieArmyToken| |Generate|TOK:WAR|Zombie Army|2||ZombieArmyToken|
|Generate|TOK:WAR|Zombie Army|3||ZombieArmyToken| |Generate|TOK:WAR|Zombie Army|3||ZombieArmyToken|
|Generate|TOK:MH1|Shapeshifter|||ShapeshifterToken|
|Generate|TOK:MH1|Angel|||AngelVigilanceToken|
|Generate|TOK:MH1|Bear|||BearToken|
|Generate|TOK:MH1|Bird|||BirdToken|
|Generate|TOK:MH1|Construct|||KarnConstructToken|
|Generate|TOK:MH1|Elemental|1||YoungPyromancerElementalToken|
|Generate|TOK:MH1|Elemental|2||AkoumStonewakerElementalToken|
|Generate|TOK:MH1|Elephant|||ElephantToken|
|Generate|TOK:MH1|Goblin|||GoblinToken|
|Generate|TOK:MH1|Golem|||GolemToken|
|Generate|TOK:MH1|Illusion|||MelokuTheCloudedMirrorToken|
|Generate|TOK:MH1|Marit Lage|||MaritLageToken|
|Generate|TOK:MH1|Myr|||MyrToken|
|Generate|TOK:MH1|Rhino|||RhinoToken|
|Generate|TOK:MH1|Soldier|||SoldierToken|
|Generate|TOK:MH1|Spider|||SpiderToken|
|Generate|TOK:MH1|Spirit|||WhiteBlackSpiritToken|
|Generate|TOK:MH1|Squirrel|||SquirrelToken|
|Generate|TOK:MH1|Zombie|||ZombieToken|
|Generate|TOK:M19|Angel|||AngelVigilanceToken|
|Generate|TOK:M19|Avatar|||AvatarToken2|
|Generate|TOK:M19|Bat|||BatToken|
|Generate|TOK:M19|Beast|||BeastToken|
|Generate|TOK:M19|Cat|||CatToken2|
|Generate|TOK:M19|Dragon|1||DragonEggDragonToken|
|Generate|TOK:M19|Dragon|2||DragonToken2|
|Generate|TOK:M19|Elf Warrior|||ElfToken|
|Generate|TOK:M19|Goblin|||GoblinToken|
|Generate|TOK:M19|Knight|||KnightToken|
|Generate|TOK:M19|Ox|||OxToken|
|Generate|TOK:M19|Soldier|||SoldierToken|
|Generate|TOK:M19|Thopter|||ThopterColorlessToken|
|Generate|TOK:M19|Zombie|||ZombieToken|
|Generate|TOK:M20|Ajani's Pridemate|||AjanisPridemateToken|
|Generate|TOK:M20|Demon|||DemonToken|
|Generate|TOK:M20|Elemental|||YoungPyromancerElementalToken|
|Generate|TOK:M20|Elemental Bird|||MuYanlingSkyDancerToken|
|Generate|TOK:M20|Golem|||GolemToken|
|Generate|TOK:M20|Soldier|||SoldierToken|
|Generate|TOK:M20|Spirit|||SpiritWhiteToken|
|Generate|TOK:M20|Treasure|||TreasureToken|
|Generate|TOK:M20|Wolf|||WolfToken|
|Generate|TOK:M20|Zombie|||ZombieToken|
|Generate|TOK:ELD|Bear|||BearToken|
|Generate|TOK:ELD|Boar|||WolfsQuarryToken|
|Generate|TOK:ELD|Dwarf|||DwarfToken|
|Generate|TOK:ELD|Faerie|||FaerieToken|
|Generate|TOK:ELD|Food|1||FoodToken|
|Generate|TOK:ELD|Food|2||FoodToken|
|Generate|TOK:ELD|Food|3||FoodToken|
|Generate|TOK:ELD|Food|4||FoodToken|
|Generate|TOK:ELD|Giant|||GiantOpportunityToken|
|Generate|TOK:ELD|Goat|||GoatToken|
|Generate|TOK:ELD|Human|||HumanToken|
|Generate|TOK:ELD|Human Cleric|||OutlawsMerrimentClericToken|
|Generate|TOK:ELD|Human Rogue|||OutlawsMerrimentRogueToken|
|Generate|TOK:ELD|Human Warrior|||OutlawsMerrimentWarriorToken|
|Generate|TOK:ELD|Knight|||KnightToken|
|Generate|TOK:ELD|Mouse|||MouseToken|
|Generate|TOK:ELD|Rat|||RatToken|
|Generate|TOK:ELD|Wolf|||GarrukCursedHuntsmanToken|

View file

@ -655,7 +655,7 @@ Elemental, 008, G, 2|2, -, Creature - Elemental, Marco Nelor, -
Elf Warrior, 009, G, 1|1, -, Creature - Elf Warrior, William O'Connor, - Elf Warrior, 009, G, 1|1, -, Creature - Elf Warrior, William O'Connor, -
Thopter, 010, -, 1|1, -, Artifact Creature - Thopter, Adam Paquette, Flying Thopter, 010, -, 1|1, -, Artifact Creature - Thopter, Adam Paquette, Flying
Thopter, 011, -, 1|1, -, Artifact Creature - Thopter, Svetlin Velinov, Flying Thopter, 011, -, 1|1, -, Artifact Creature - Thopter, Svetlin Velinov, Flying
Jace Emblem, 012, -, -, -, Emblem - Jace, Jaime Jones, Whenever you cast a spell<6C> target opponent puts the top five cards of his or her library into his or her graveyard. Jace Emblem, 012, -, -, -, Emblem - Jace, Jaime Jones, Whenever you cast a spell<6C> target opponent puts the top five cards of their library into their graveyard.
Liliana Emblem, 013, -, -, -, Emblem - Liliana, Karla Ortiz, Whenever a creature dies<65> return it to the battlefield under your control at the beginning of the next end step. Liliana Emblem, 013, -, -, -, Emblem - Liliana, Karla Ortiz, Whenever a creature dies<65> return it to the battlefield under your control at the beginning of the next end step.
Chandra Emblem, 014, -, -, -, Emblem - Chandra, Eric Deschamps, At the beginning of your upkeep<65> this emblem deals 3 damage to you. Chandra Emblem, 014, -, -, -, Emblem - Chandra, Eric Deschamps, At the beginning of your upkeep<65> this emblem deals 3 damage to you.
@ -743,7 +743,7 @@ Clue, 013, -, -, -, Artifact - Clue, Zezhou Chen, {2} Sacrifice this Artifact
Clue, 014, -, -, -, Artifact - Clue, Cliff Childs, {2} Sacrifice this Artifact: Draw a card. Clue, 014, -, -, -, Artifact - Clue, Cliff Childs, {2} Sacrifice this Artifact: Draw a card.
Clue, 015, -, -, -, Artifact - Clue, James Paick, {2} Sacrifice this Artifact: Draw a card. Clue, 015, -, -, -, Artifact - Clue, James Paick, {2} Sacrifice this Artifact: Draw a card.
Clue, 016, -, -, -, Artifact - Clue, Franz Vohwinkel, {2} Sacrifice this Artifact: Draw a card. Clue, 016, -, -, -, Artifact - Clue, Franz Vohwinkel, {2} Sacrifice this Artifact: Draw a card.
Jace Emblem, 017, -, -, -, Emblem - Jace, Tyler Jacobson, Whenever an opponent casts his or her first spell each turn<72> counter that spell. Jace Emblem, 017, -, -, -, Emblem - Jace, Tyler Jacobson, Whenever an opponent casts their first spell each turn<72> counter that spell.
Arlinn Emblem, 018, -, -, -, Emblem - Arlinn, Winona Nelson, Creatures you control have haste and '{T}: This creature deals damage equal to its power to any target.' Arlinn Emblem, 018, -, -, -, Emblem - Arlinn, Winona Nelson, Creatures you control have haste and '{T}: This creature deals damage equal to its power to any target.'

Can't render this file because it contains an unexpected character in line 549 and column 140.

View file

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-root</artifactId> <artifactId>mage-root</artifactId>
<version>1.4.35</version> <version>1.4.41</version>
</parent> </parent>
<artifactId>mage-common</artifactId> <artifactId>mage-common</artifactId>

View file

@ -56,6 +56,8 @@ public class ImagePanel extends JPanel {
super.add(component, constraints); super.add(component, constraints);
} }
@Override
protected void paintComponent(Graphics g) { protected void paintComponent(Graphics g) {
super.paintComponent(g); super.paintComponent(g);

View file

@ -1,5 +1,12 @@
package mage.remote; package mage.remote;
import java.io.*;
import java.lang.reflect.UndeclaredThrowableException;
import java.net.*;
import java.util.*;
import java.util.concurrent.CancellationException;
import java.util.concurrent.TimeUnit;
import javax.swing.*;
import mage.MageException; import mage.MageException;
import mage.cards.decks.DeckCardLists; import mage.cards.decks.DeckCardLists;
import mage.cards.repository.CardInfo; import mage.cards.repository.CardInfo;
@ -28,14 +35,6 @@ import org.jboss.remoting.transport.bisocket.Bisocket;
import org.jboss.remoting.transport.socket.SocketWrapper; import org.jboss.remoting.transport.socket.SocketWrapper;
import org.jboss.remoting.transporter.TransporterClient; import org.jboss.remoting.transporter.TransporterClient;
import javax.swing.*;
import java.io.*;
import java.lang.reflect.UndeclaredThrowableException;
import java.net.*;
import java.util.*;
import java.util.concurrent.CancellationException;
import java.util.concurrent.TimeUnit;
/** /**
* @author BetaSteward_at_googlemail.com, JayDi85 * @author BetaSteward_at_googlemail.com, JayDi85
*/ */
@ -502,7 +501,7 @@ public class SessionImpl implements Session {
/** /**
* @param askForReconnect - true = connection was lost because of error and * @param askForReconnect - true = connection was lost because of error and
* ask the user if he want to try to reconnect * ask the user if they want to try to reconnect
*/ */
@Override @Override
public synchronized void disconnect(boolean askForReconnect) { public synchronized void disconnect(boolean askForReconnect) {
@ -557,8 +556,21 @@ public class SessionImpl implements Session {
@Override @Override
public void handleCallback(Callback callback) throws HandleCallbackException { public void handleCallback(Callback callback) throws HandleCallbackException {
//logger.info("callback handler"); try {
client.processCallback((ClientCallback) callback.getCallbackObject()); // Object object = callback.getCallbackObject();
// if (((ClientCallback) object).getMethod().equals(ClientCallbackMethod.GAME_TARGET)) {
// Object data = ((ClientCallback) object).getData();
// if (data instanceof GameClientMessage) {
// GameClientMessage message = (GameClientMessage) ((ClientCallback) object).getData();
// logger.info("Client Session Event->" + ((ClientCallback) object).getMethod() + " (id:" + ((ClientCallback) object).getMessageId() + ") " + message.getMessage()
// );
// }
// }
client.processCallback((ClientCallback) callback.getCallbackObject());
} catch (Exception ex) {
logger.error("handleCallback error", ex);
}
} }
} }

View file

@ -11,11 +11,11 @@ public class MageVersion implements Serializable, Comparable<MageVersion> {
public static final int MAGE_VERSION_MAJOR = 1; public static final int MAGE_VERSION_MAJOR = 1;
public static final int MAGE_VERSION_MINOR = 4; public static final int MAGE_VERSION_MINOR = 4;
public static final int MAGE_VERSION_PATCH = 35; public static final int MAGE_VERSION_PATCH = 41;
public static final String MAGE_EDITION_INFO = ""; // set "-beta" for 1.4.32-betaV0 public static final String MAGE_EDITION_INFO = ""; // set "-beta" for 1.4.32-betaV0
public static final String MAGE_VERSION_MINOR_PATCH = "V5"; // default public static final String MAGE_VERSION_MINOR_PATCH = "V1"; // default
// strict mode // strict mode
private static final boolean MAGE_VERSION_MINOR_PATCH_MUST_BE_SAME = true; // set true on uncompatible github changes, set false after new major release (after MAGE_VERSION_PATCH changes) private static final boolean MAGE_VERSION_MINOR_PATCH_MUST_BE_SAME = false; // set true on uncompatible github changes, set false after new major release (after MAGE_VERSION_PATCH changes)
public static final boolean MAGE_VERSION_SHOW_BUILD_TIME = true; public static final boolean MAGE_VERSION_SHOW_BUILD_TIME = true;
private final int major; private final int major;

View file

@ -50,9 +50,9 @@ public class CardView extends SimpleCardView {
@Expose @Expose
protected String loyalty = ""; protected String loyalty = "";
protected String startingLoyalty; protected String startingLoyalty;
protected EnumSet<CardType> cardTypes; protected Set<CardType> cardTypes;
protected SubTypeList subTypes; protected SubTypeList subTypes;
protected EnumSet<SuperType> superTypes; protected Set<SuperType> superTypes;
protected ObjectColor color; protected ObjectColor color;
protected ObjectColor frameColor; protected ObjectColor frameColor;
protected FrameStyle frameStyle; protected FrameStyle frameStyle;
@ -104,9 +104,6 @@ public class CardView extends SimpleCardView {
protected boolean rotate; protected boolean rotate;
protected boolean hideInfo; // controls if the tooltip window is shown (eg. controlled face down morph card) protected boolean hideInfo; // controls if the tooltip window is shown (eg. controlled face down morph card)
protected boolean isPlayable;
protected boolean isChoosable;
protected boolean selected;
protected boolean canAttack; protected boolean canAttack;
protected boolean canBlock; protected boolean canBlock;
protected boolean inViewerOnly; protected boolean inViewerOnly;
@ -117,9 +114,13 @@ public class CardView extends SimpleCardView {
this(card, null, false); this(card, null, false);
} }
public CardView(Card card, UUID cardId) { public CardView(Card card, SimpleCardView simpleCardView) {
this(card, null, false); this(card, null, false);
this.id = cardId; this.id = simpleCardView.getId();
this.isPlayable = simpleCardView.isPlayable;
this.isChoosable = simpleCardView.isChoosable;
this.isSelected = simpleCardView.isSelected;
} }
public CardView(Card card, Game game, UUID cardId) { public CardView(Card card, Game game, UUID cardId) {
@ -128,10 +129,12 @@ public class CardView extends SimpleCardView {
} }
public CardView(CardView cardView) { public CardView(CardView cardView) {
super(cardView.id, cardView.expansionSetCode, cardView.cardNumber, cardView.usesVariousArt, cardView.tokenSetCode, cardView.gameObject, cardView.tokenDescriptor); super(cardView);
this.originalCard = cardView.originalCard; this.originalCard = cardView.originalCard;
// generetate new ID
this.id = UUID.randomUUID(); this.id = UUID.randomUUID();
this.parentId = cardView.parentId; this.parentId = cardView.parentId;
this.name = cardView.name; this.name = cardView.name;
this.displayName = cardView.displayName; this.displayName = cardView.displayName;
@ -198,9 +201,6 @@ public class CardView extends SimpleCardView {
this.rotate = cardView.rotate; this.rotate = cardView.rotate;
this.hideInfo = cardView.hideInfo; this.hideInfo = cardView.hideInfo;
this.isPlayable = cardView.isPlayable;
this.isChoosable = cardView.isChoosable;
this.selected = cardView.selected;
this.canAttack = cardView.canAttack; this.canAttack = cardView.canAttack;
this.canBlock = cardView.canBlock; this.canBlock = cardView.canBlock;
this.inViewerOnly = cardView.inViewerOnly; this.inViewerOnly = cardView.inViewerOnly;
@ -468,8 +468,6 @@ public class CardView extends SimpleCardView {
// Get starting loyalty // Get starting loyalty
this.startingLoyalty = "" + card.getStartingLoyalty(); this.startingLoyalty = "" + card.getStartingLoyalty();
} }
public CardView(MageObject object) { public CardView(MageObject object) {
@ -731,7 +729,7 @@ public class CardView extends SimpleCardView {
return subTypes; return subTypes;
} }
public EnumSet<SuperType> getSuperTypes() { public Set<SuperType> getSuperTypes() {
return superTypes; return superTypes;
} }
@ -964,30 +962,6 @@ public class CardView extends SimpleCardView {
return hideInfo; return hideInfo;
} }
public boolean isPlayable() {
return isPlayable;
}
public void setPlayable(boolean isPlayable) {
this.isPlayable = isPlayable;
}
public boolean isChoosable() {
return isChoosable;
}
public void setChoosable(boolean isChoosable) {
this.isChoosable = isChoosable;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
public boolean isCanAttack() { public boolean isCanAttack() {
return canAttack; return canAttack;
} }

View file

@ -1,11 +1,5 @@
package mage.view; package mage.view;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
@ -20,8 +14,9 @@ import mage.game.permanent.PermanentToken;
import mage.target.targetpointer.TargetPointer; import mage.target.targetpointer.TargetPointer;
import mage.util.GameLog; import mage.util.GameLog;
import java.util.*;
/** /**
*
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class CardsView extends LinkedHashMap<UUID, CardView> { public class CardsView extends LinkedHashMap<UUID, CardView> {
@ -91,11 +86,11 @@ public class CardsView extends LinkedHashMap<UUID, CardView> {
// throw new IllegalArgumentException("Source card for emblem not found."); // throw new IllegalArgumentException("Source card for emblem not found.");
// } // }
abilityView = new AbilityView(ability, sourceObject.getName(), new CardView(new EmblemView((Emblem) sourceObject))); abilityView = new AbilityView(ability, sourceObject.getName(), new CardView(new EmblemView((Emblem) sourceObject)));
abilityView.setName(((Emblem) sourceObject).getName()); abilityView.setName(sourceObject.getName());
// abilityView.setExpansionSetCode(sourceCard.getExpansionSetCode()); // abilityView.setExpansionSetCode(sourceCard.getExpansionSetCode());
} else if (sourceObject instanceof Plane) { } else if (sourceObject instanceof Plane) {
abilityView = new AbilityView(ability, sourceObject.getName(), new CardView(new PlaneView((Plane) sourceObject))); abilityView = new AbilityView(ability, sourceObject.getName(), new CardView(new PlaneView((Plane) sourceObject)));
abilityView.setName(((Plane) sourceObject).getName()); abilityView.setName(sourceObject.getName());
} }
break; break;
} }
@ -131,7 +126,10 @@ public class CardsView extends LinkedHashMap<UUID, CardView> {
if ((mageObject instanceof Card) && ((Card) mageObject).isFaceDown(game)) { if ((mageObject instanceof Card) && ((Card) mageObject).isFaceDown(game)) {
continue; continue;
} }
names.add(GameLog.getColoredObjectIdNameForTooltip(mageObject)); String newName = GameLog.getColoredObjectIdNameForTooltip(mageObject);
if (!names.contains(newName)) {
names.add(newName);
}
} }
} }
if (!names.isEmpty()) { if (!names.isEmpty()) {

View file

@ -1,21 +1,18 @@
package mage.view; package mage.view;
import java.io.Serializable;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
/** /**
*
* @author Plopman * @author Plopman
*/ */
public interface CommandObjectView extends Serializable { public interface CommandObjectView extends SelectableObjectView {
public String getExpansionSetCode();
public String getName(); String getExpansionSetCode();
public UUID getId(); String getName();
public List<String> getRules(); UUID getId();
List<String> getRules();
} }

View file

@ -1,10 +1,11 @@
package mage.view; package mage.view;
import mage.cards.Card;
import mage.game.command.Emblem;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import mage.cards.Card;
import mage.game.command.Emblem;
/** /**
* @author noxx * @author noxx
@ -15,24 +16,25 @@ public class EmblemView implements CommandObjectView, Serializable {
protected String name; protected String name;
protected String expansionSetCode; protected String expansionSetCode;
protected List<String> rules; protected List<String> rules;
protected boolean isPlayable = false;
protected int playableAmount = 0;
public EmblemView(Emblem emblem, Card sourceCard) { public EmblemView(Emblem emblem, Card sourceCard) {
id = emblem.getId(); this.id = emblem.getId();
name = "Emblem " + sourceCard.getName(); this.name = "Emblem " + sourceCard.getName();
if (emblem.getExpansionSetCodeForImage() == null) { if (emblem.getExpansionSetCodeForImage() == null) {
expansionSetCode = sourceCard.getExpansionSetCode(); this.expansionSetCode = sourceCard.getExpansionSetCode();
} else { } else {
expansionSetCode = emblem.getExpansionSetCodeForImage(); this.expansionSetCode = emblem.getExpansionSetCodeForImage();
} }
this.rules = emblem.getAbilities().getRules(sourceCard.getName());
rules = emblem.getAbilities().getRules(sourceCard.getName());
} }
public EmblemView(Emblem emblem) { public EmblemView(Emblem emblem) {
id = emblem.getId(); this.id = emblem.getId();
name = emblem.getName(); this.name = emblem.getName();
expansionSetCode = emblem.getExpansionSetCodeForImage(); this.expansionSetCode = emblem.getExpansionSetCodeForImage();
rules = emblem.getAbilities().getRules(emblem.getName()); this.rules = emblem.getAbilities().getRules(emblem.getName());
} }
@Override @Override
@ -54,4 +56,47 @@ public class EmblemView implements CommandObjectView, Serializable {
public List<String> getRules() { public List<String> getRules() {
return rules; return rules;
} }
@Override
public boolean isPlayable() {
return isPlayable;
}
@Override
public void setPlayable(boolean isPlayable) {
this.isPlayable = isPlayable;
}
@Override
public void setPlayableAmount(int playableAmount) {
this.playableAmount = playableAmount;
}
@Override
public int getPlayableAmount() {
return playableAmount;
}
@Override
public boolean isChoosable() {
// unsupported
return false;
}
@Override
public void setChoosable(boolean isChoosable) {
// unsupported
}
@Override
public boolean isSelected() {
// unsupported
return false;
}
@Override
public void setSelected(boolean isSelected) {
// unsupported
}
} }

View file

@ -26,7 +26,10 @@ import mage.watchers.common.CastSpellLastTurnWatcher;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import java.io.Serializable; import java.io.Serializable;
import java.util.*; import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
@ -39,7 +42,7 @@ public class GameView implements Serializable {
private final int priorityTime; private final int priorityTime;
private final List<PlayerView> players = new ArrayList<>(); private final List<PlayerView> players = new ArrayList<>();
private CardsView hand; private CardsView hand;
private Set<UUID> canPlayInHand; private Map<UUID, Integer> canPlayObjects;
private Map<String, SimpleCardsView> opponentHands; private Map<String, SimpleCardsView> opponentHands;
private Map<String, SimpleCardsView> watchedHands; private Map<String, SimpleCardsView> watchedHands;
private final CardsView stack = new CardsView(); private final CardsView stack = new CardsView();
@ -300,12 +303,12 @@ public class GameView implements Serializable {
return isPlayer; return isPlayer;
} }
public Set<UUID> getCanPlayInHand() { public Map<UUID, Integer> getCanPlayObjects() {
return canPlayInHand; return canPlayObjects;
} }
public void setCanPlayInHand(Set<UUID> canPlayInHand) { public void setCanPlayObjects(Map<UUID, Integer> canPlayObjects) {
this.canPlayInHand = canPlayInHand; this.canPlayObjects = canPlayObjects;
} }
public int getSpellsCastCurrentTurn() { public int getSpellsCastCurrentTurn() {

View file

@ -111,8 +111,8 @@ public class PermanentView extends CardView {
this.rules.add("A manifested creature card can be turned face up any time for it's mana cost." this.rules.add("A manifested creature card can be turned face up any time for it's mana cost."
+ " A face-down card can also be turned face up for its morph cost."); + " A face-down card can also be turned face up for its morph cost.");
} else if (permanent.isMorphed()) { } else if (permanent.isMorphed()) {
this.rules.add("If the controller has priority, he or she may turn this permanent face up." this.rules.add("If the controller has priority, they may turn this permanent face up."
+ " This is a special action; it doesn't use the stack. To do this he or she pays the morph costs," + " This is a special action; it doesn't use the stack. To do this they pay the morph costs,"
+ " then turns this permanent face up."); + " then turns this permanent face up.");
} }
} }

View file

@ -1,10 +1,11 @@
package mage.view; package mage.view;
import mage.cards.Card;
import mage.game.command.Plane;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import mage.cards.Card;
import mage.game.command.Plane;
/** /**
* @author spjspj * @author spjspj
@ -16,23 +17,25 @@ public class PlaneView implements CommandObjectView, Serializable {
protected String expansionSetCode; protected String expansionSetCode;
protected List<String> rules; protected List<String> rules;
public PlaneView(Plane plane, Card sourceCard) { protected boolean isPlayable = false;
id = plane.getId(); protected int playableAmount = 0;
name = "Plane " + sourceCard.getName();
if (plane.getExpansionSetCodeForImage() == null) {
expansionSetCode = sourceCard.getExpansionSetCode();
} else {
expansionSetCode = plane.getExpansionSetCodeForImage();
}
rules = plane.getAbilities().getRules(sourceCard.getName()); public PlaneView(Plane plane, Card sourceCard) {
this.id = plane.getId();
this.name = "Plane " + sourceCard.getName();
if (plane.getExpansionSetCodeForImage() == null) {
this.expansionSetCode = sourceCard.getExpansionSetCode();
} else {
this.expansionSetCode = plane.getExpansionSetCodeForImage();
}
this.rules = plane.getAbilities().getRules(sourceCard.getName());
} }
public PlaneView(Plane plane) { public PlaneView(Plane plane) {
id = plane.getId(); this.id = plane.getId();
name = plane.getName(); this.name = plane.getName();
expansionSetCode = plane.getExpansionSetCodeForImage(); this.expansionSetCode = plane.getExpansionSetCodeForImage();
rules = plane.getAbilities().getRules(plane.getName()); this.rules = plane.getAbilities().getRules(plane.getName());
} }
@Override @Override
@ -54,4 +57,46 @@ public class PlaneView implements CommandObjectView, Serializable {
public List<String> getRules() { public List<String> getRules() {
return rules; return rules;
} }
@Override
public boolean isPlayable() {
return isPlayable;
}
@Override
public void setPlayable(boolean isPlayable) {
this.isPlayable = isPlayable;
}
@Override
public void setPlayableAmount(int playableAmount) {
this.playableAmount = playableAmount;
}
@Override
public int getPlayableAmount() {
return playableAmount;
}
@Override
public boolean isChoosable() {
// unsupported
return false;
}
@Override
public void setChoosable(boolean isChoosable) {
// unsupported
}
@Override
public boolean isSelected() {
// unsupported
return false;
}
@Override
public void setSelected(boolean isSelected) {
// unsupported
}
} }

View file

@ -0,0 +1,23 @@
package mage.view;
/**
* @author JayDi85
*/
public interface SelectableObjectView {
boolean isPlayable();
void setPlayable(boolean isPlayable);
void setPlayableAmount(int playableAmount);
int getPlayableAmount();
boolean isChoosable();
void setChoosable(boolean isChoosable);
boolean isSelected();
void setSelected(boolean isSelected);
}

View file

@ -1,5 +1,3 @@
package mage.view; package mage.view;
import com.google.gson.annotations.Expose; import com.google.gson.annotations.Expose;
@ -8,10 +6,9 @@ import java.io.Serializable;
import java.util.UUID; import java.util.UUID;
/** /**
*
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class SimpleCardView implements Serializable { public class SimpleCardView implements Serializable, SelectableObjectView {
@Expose @Expose
protected UUID id; protected UUID id;
protected String expansionSetCode; protected String expansionSetCode;
@ -21,9 +18,30 @@ public class SimpleCardView implements Serializable {
protected boolean usesVariousArt; protected boolean usesVariousArt;
protected boolean gameObject; protected boolean gameObject;
protected boolean isPlayable;
protected boolean isChoosable;
protected boolean isSelected;
protected int playableAmount; // playable abilities count on object
public SimpleCardView(final SimpleCardView view) {
this.id = view.id;
this.expansionSetCode = view.expansionSetCode;
this.tokenSetCode = view.tokenSetCode;
this.tokenDescriptor = view.tokenDescriptor;
this.cardNumber = view.cardNumber;
this.usesVariousArt = view.usesVariousArt;
this.gameObject = view.gameObject;
this.isPlayable = view.isPlayable;
this.isChoosable = view.isChoosable;
this.isSelected = view.isSelected;
this.playableAmount = view.playableAmount;
}
public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt, String tokenSetCode, String tokenDescriptor) { public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt, String tokenSetCode, String tokenDescriptor) {
this(id, expansionSetCode, cardNumber, usesVariousArt, tokenSetCode, false, tokenDescriptor); this(id, expansionSetCode, cardNumber, usesVariousArt, tokenSetCode, false, tokenDescriptor);
} }
public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt, String tokenSetCode, boolean isGameObject, String tokenDescriptor) { public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt, String tokenSetCode, boolean isGameObject, String tokenDescriptor) {
this.id = id; this.id = id;
this.expansionSetCode = expansionSetCode; this.expansionSetCode = expansionSetCode;
@ -53,12 +71,52 @@ public class SimpleCardView implements Serializable {
public String getTokenSetCode() { public String getTokenSetCode() {
return tokenSetCode; return tokenSetCode;
} }
public String getTokenDescriptor() { public String getTokenDescriptor() {
return tokenDescriptor; return tokenDescriptor;
} }
public boolean isGameObject() { public boolean isGameObject() {
return gameObject; return gameObject;
} }
@Override
public boolean isPlayable() {
return isPlayable;
}
@Override
public void setPlayable(boolean isPlayable) {
this.isPlayable = isPlayable;
}
@Override
public void setPlayableAmount(int playableAmount) {
this.playableAmount = playableAmount;
}
@Override
public int getPlayableAmount() {
return playableAmount;
}
@Override
public boolean isChoosable() {
return isChoosable;
}
@Override
public void setChoosable(boolean isChoosable) {
this.isChoosable = isChoosable;
}
@Override
public boolean isSelected() {
return isSelected;
}
@Override
public void setSelected(boolean isSelected) {
this.isSelected = isSelected;
}
} }

View file

@ -1,9 +1,5 @@
package mage.view; package mage.view;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Mode; import mage.abilities.Mode;
import mage.abilities.Modes; import mage.abilities.Modes;
@ -18,8 +14,11 @@ import mage.target.targetpointer.FixedTarget;
import mage.target.targetpointer.TargetPointer; import mage.target.targetpointer.TargetPointer;
import mage.util.GameLog; import mage.util.GameLog;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/** /**
*
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class StackAbilityView extends CardView { public class StackAbilityView extends CardView {
@ -94,7 +93,10 @@ public class StackAbilityView extends CardView {
if ((mageObject instanceof Card) && ((Card) mageObject).isFaceDown(game)) { if ((mageObject instanceof Card) && ((Card) mageObject).isFaceDown(game)) {
continue; continue;
} }
names.add(GameLog.getColoredObjectIdNameForTooltip(mageObject)); String newName = GameLog.getColoredObjectIdNameForTooltip(mageObject);
if (!names.contains(newName)) {
names.add(newName);
}
} }
} }

View file

@ -135,6 +135,7 @@ public class TableView implements Serializable {
switch (table.getState()) { switch (table.getState()) {
case WAITING: case WAITING:
stateText.append(" (").append(table.getTournament().getPlayers().size()).append('/').append(table.getNumberOfSeats()).append(')'); stateText.append(" (").append(table.getTournament().getPlayers().size()).append('/').append(table.getNumberOfSeats()).append(')');
break;
case READY_TO_START: case READY_TO_START:
case STARTING: case STARTING:
infoText.append(" Time: ").append(table.getTournament().getOptions().getMatchOptions().getMatchTimeLimit().toString()); infoText.append(" Time: ").append(table.getTournament().getOptions().getMatchOptions().getMatchTimeLimit().toString());
@ -153,6 +154,7 @@ public class TableView implements Serializable {
if (draft != null) { if (draft != null) {
stateText.append(' ').append(draft.getBoosterNum()).append('/').append(draft.getCardNum() - 1); stateText.append(' ').append(draft.getBoosterNum()).append('/').append(draft.getCardNum() - 1);
} }
break;
default: default:
} }
this.additionalInfo = infoText.toString(); this.additionalInfo = infoText.toString();

View file

@ -1,9 +1,10 @@
package mage.view; package mage.view;
import java.io.Serializable;
import mage.players.net.UserData; import mage.players.net.UserData;
import mage.players.net.UserSkipPrioritySteps; import mage.players.net.UserSkipPrioritySteps;
import java.io.Serializable;
/** /**
* Transfer object for {@link mage.players.net.UserData} * Transfer object for {@link mage.players.net.UserData}
* *
@ -14,7 +15,6 @@ public class UserDataView implements Serializable {
protected int avatarId; protected int avatarId;
protected int userGroup; protected int userGroup;
protected boolean showAbilityPickerForced; protected boolean showAbilityPickerForced;
protected boolean allowRequestShowHandCards;
protected boolean confirmEmptyManaPool; protected boolean confirmEmptyManaPool;
protected UserSkipPrioritySteps userSkipPrioritySteps; protected UserSkipPrioritySteps userSkipPrioritySteps;
String flagName; String flagName;
@ -29,10 +29,9 @@ public class UserDataView implements Serializable {
} }
public UserDataView(int avatarId, boolean showAbilityPickerForced, boolean allowRequestShowHandCards, public UserDataView(int avatarId, boolean showAbilityPickerForced, boolean allowRequestShowHandCards,
boolean confirmEmptyManaPool, UserSkipPrioritySteps userSkipPrioritySteps, String flagName, boolean askMoveToGraveOrder) { boolean confirmEmptyManaPool, UserSkipPrioritySteps userSkipPrioritySteps, String flagName, boolean askMoveToGraveOrder) {
this.avatarId = avatarId; this.avatarId = avatarId;
this.showAbilityPickerForced = showAbilityPickerForced; this.showAbilityPickerForced = showAbilityPickerForced;
this.allowRequestShowHandCards = allowRequestShowHandCards;
this.userSkipPrioritySteps = userSkipPrioritySteps; this.userSkipPrioritySteps = userSkipPrioritySteps;
this.confirmEmptyManaPool = confirmEmptyManaPool; this.confirmEmptyManaPool = confirmEmptyManaPool;
this.flagName = flagName; this.flagName = flagName;
@ -43,7 +42,6 @@ public class UserDataView implements Serializable {
public UserDataView(UserData userData) { public UserDataView(UserData userData) {
this.avatarId = userData.getAvatarId(); this.avatarId = userData.getAvatarId();
this.userGroup = userData.getGroupId(); this.userGroup = userData.getGroupId();
this.allowRequestShowHandCards = userData.isAllowRequestShowHandCards();
this.showAbilityPickerForced = userData.isShowAbilityPickerForced(); this.showAbilityPickerForced = userData.isShowAbilityPickerForced();
this.userSkipPrioritySteps = userData.getUserSkipPrioritySteps(); this.userSkipPrioritySteps = userData.getUserSkipPrioritySteps();
this.confirmEmptyManaPool = userData.confirmEmptyManaPool(); this.confirmEmptyManaPool = userData.confirmEmptyManaPool();
@ -59,10 +57,6 @@ public class UserDataView implements Serializable {
return showAbilityPickerForced; return showAbilityPickerForced;
} }
public boolean allowRequestShowHandCards() {
return allowRequestShowHandCards;
}
public UserSkipPrioritySteps getUserSkipPrioritySteps() { public UserSkipPrioritySteps getUserSkipPrioritySteps() {
return userSkipPrioritySteps; return userSkipPrioritySteps;
} }

View file

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-plugins</artifactId> <artifactId>mage-plugins</artifactId>
<version>1.4.35</version> <version>1.4.41</version>
</parent> </parent>
<artifactId>mage-counter-plugin</artifactId> <artifactId>mage-counter-plugin</artifactId>

View file

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-root</artifactId> <artifactId>mage-root</artifactId>
<version>1.4.35</version> <version>1.4.41</version>
</parent> </parent>
<artifactId>mage-plugins</artifactId> <artifactId>mage-plugins</artifactId>

View file

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-root</artifactId> <artifactId>mage-root</artifactId>
<version>1.4.35</version> <version>1.4.41</version>
</parent> </parent>
<artifactId>mage.server.console</artifactId> <artifactId>mage.server.console</artifactId>

View file

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId> <artifactId>mage-server-plugins</artifactId>
<version>1.4.35</version> <version>1.4.41</version>
</parent> </parent>
<artifactId>mage-deck-constructed</artifactId> <artifactId>mage-deck-constructed</artifactId>

View file

@ -12,7 +12,7 @@ public class AmonkhetBlock extends Constructed {
public AmonkhetBlock() { public AmonkhetBlock() {
super("Constructed - Amonkhet Block"); super("Constructed - Amonkhet Block");
setCodes.add("AKH"); setCodes.add(mage.sets.Amonkhet.getInstance().getCode());
setCodes.add("HOU"); setCodes.add(mage.sets.HourOfDevastation.getInstance().getCode());
} }
} }

View file

@ -29,7 +29,6 @@ public class AusHighlander extends Constructed {
pointMap.put("Sol Ring", 3); pointMap.put("Sol Ring", 3);
pointMap.put("Time Walk", 3); pointMap.put("Time Walk", 3);
pointMap.put("Vampiric Tutor", 3); pointMap.put("Vampiric Tutor", 3);
pointMap.put("Yawgmoth's Will", 3);
pointMap.put("Channel", 2); pointMap.put("Channel", 2);
pointMap.put("Dig Through Time", 2); pointMap.put("Dig Through Time", 2);
pointMap.put("Library of Alexandria", 2); pointMap.put("Library of Alexandria", 2);
@ -37,17 +36,20 @@ public class AusHighlander extends Constructed {
pointMap.put("Mind Twist", 2); pointMap.put("Mind Twist", 2);
pointMap.put("Mystical Tutor", 2); pointMap.put("Mystical Tutor", 2);
pointMap.put("Protean Hulk", 2); pointMap.put("Protean Hulk", 2);
pointMap.put("Strip Mine", 2);
pointMap.put("Tinker", 2); pointMap.put("Tinker", 2);
pointMap.put("Tolarian Academy", 2); pointMap.put("Tolarian Academy", 2);
pointMap.put("Treasure Cruise", 2); pointMap.put("Treasure Cruise", 2);
pointMap.put("True-Name Nemesis", 2);
pointMap.put("Balance", 1); pointMap.put("Balance", 1);
pointMap.put("Birthing Pod", 1); pointMap.put("Birthing Pod", 1);
pointMap.put("Crop Rotation", 1); pointMap.put("Crop Rotation", 1);
pointMap.put("Dark Petition", 1); pointMap.put("Dark Petition", 1);
pointMap.put("Doomsday", 1);
pointMap.put("Enlightened Tutor", 1); pointMap.put("Enlightened Tutor", 1);
pointMap.put("Fastbond", 1); pointMap.put("Fastbond", 1);
pointMap.put("Flash", 1);
pointMap.put("Force of Will", 1); pointMap.put("Force of Will", 1);
pointMap.put("Gifts Ungiven", 1);
pointMap.put("Green Sun's Zenith", 1); pointMap.put("Green Sun's Zenith", 1);
pointMap.put("Hermit Druid", 1); pointMap.put("Hermit Druid", 1);
pointMap.put("Intuition", 1); pointMap.put("Intuition", 1);
@ -57,25 +59,25 @@ public class AusHighlander extends Constructed {
pointMap.put("Lim-Dul's Vault", 1); pointMap.put("Lim-Dul's Vault", 1);
pointMap.put("Mana Drain", 1); pointMap.put("Mana Drain", 1);
pointMap.put("Mana Vault", 1); pointMap.put("Mana Vault", 1);
pointMap.put("Memory Jar", 1);
pointMap.put("Merchant Scroll", 1); pointMap.put("Merchant Scroll", 1);
pointMap.put("Mishra's Workshop", 1); pointMap.put("Mishra's Workshop", 1);
pointMap.put("Natural Order", 1); pointMap.put("Natural Order", 1);
pointMap.put("Oath of Druids", 1); pointMap.put("Oath of Druids", 1);
pointMap.put("Personal Tutor", 1); pointMap.put("Personal Tutor", 1);
pointMap.put("Scheming Symmetry", 1);
pointMap.put("Sensei's Divining Top", 1); pointMap.put("Sensei's Divining Top", 1);
pointMap.put("Skullclamp", 1); pointMap.put("Skullclamp", 1);
pointMap.put("Snapcaster Mage", 1); pointMap.put("Snapcaster Mage", 1);
pointMap.put("Stoneforge Mystic", 1); pointMap.put("Stoneforge Mystic", 1);
pointMap.put("Strip Mine", 1);
pointMap.put("Survival of the Fittest", 1); pointMap.put("Survival of the Fittest", 1);
pointMap.put("Tainted Pact", 1); pointMap.put("Tainted Pact", 1);
pointMap.put("Tendrils of Agony", 1);
pointMap.put("Time Spiral", 1); pointMap.put("Time Spiral", 1);
pointMap.put("Timetwister", 1); pointMap.put("Timetwister", 1);
pointMap.put("True-Name Nemesis", 1);
pointMap.put("Umezawa's Jitte", 1); pointMap.put("Umezawa's Jitte", 1);
pointMap.put("Wasteland", 1); pointMap.put("Wasteland", 1);
pointMap.put("Yawgmoth's Bargain", 1); pointMap.put("Yawgmoth's Bargain", 1);
pointMap.put("Yawgmoth's Will", 1);
} }
public AusHighlander() { public AusHighlander() {
@ -133,14 +135,7 @@ public class AusHighlander extends Constructed {
Map<String, Integer> counts = new HashMap<>(); Map<String, Integer> counts = new HashMap<>();
countCards(counts, deck.getCards()); countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard()); countCards(counts, deck.getSideboard());
for (Map.Entry<String, Integer> entry : counts.entrySet()) { valid = checkCounts(1, counts) && valid;
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
int totalPoints = 0; int totalPoints = 0;
for (Map.Entry<String, Integer> entry : counts.entrySet()) { for (Map.Entry<String, Integer> entry : counts.entrySet()) {

View file

@ -12,7 +12,7 @@ public class BattleForZendikarBlock extends Constructed {
public BattleForZendikarBlock() { public BattleForZendikarBlock() {
super("Constructed - Battle for Zendikar Block"); super("Constructed - Battle for Zendikar Block");
setCodes.add("BFZ"); setCodes.add(mage.sets.BattleForZendikar.getInstance().getCode());
setCodes.add("OGW"); setCodes.add(mage.sets.OathOfTheGatewatch.getInstance().getCode());
} }
} }

View file

@ -5,6 +5,7 @@ import mage.cards.Card;
import mage.cards.decks.Constructed; import mage.cards.decks.Constructed;
import mage.cards.decks.Deck; import mage.cards.decks.Deck;
import mage.filter.FilterMana; import mage.filter.FilterMana;
import mage.util.ManaUtil;
import java.util.*; import java.util.*;
@ -21,8 +22,7 @@ public class Brawl extends Constructed {
// Copy of standard sets // Copy of standard sets
setCodes.addAll(Standard.makeLegalSets()); setCodes.addAll(Standard.makeLegalSets());
banned.add("Baral, Chief of Compliance"); banned.add("Oko, Thief of Crowns");
banned.add("Smuggler's Copter");
banned.add("Sorcerous Spyglass"); banned.add("Sorcerous Spyglass");
} }
@ -48,14 +48,7 @@ public class Brawl extends Constructed {
Map<String, Integer> counts = new HashMap<>(); Map<String, Integer> counts = new HashMap<>();
countCards(counts, deck.getCards()); countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard()); countCards(counts, deck.getSideboard());
for (Map.Entry<String, Integer> entry : counts.entrySet()) { valid = checkCounts(1, counts) && valid;
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
for (String bannedCard : banned) { for (String bannedCard : banned) {
if (counts.containsKey(bannedCard)) { if (counts.containsKey(bannedCard)) {
@ -78,25 +71,7 @@ public class Brawl extends Constructed {
invalid.put("Brawl", "Invalid Commander (" + commander.getName() + ')'); invalid.put("Brawl", "Invalid Commander (" + commander.getName() + ')');
valid = false; valid = false;
} }
FilterMana commanderColor = commander.getColorIdentity(); ManaUtil.collectColorIdentity(colorIdentity, commander.getColorIdentity());
if (commanderColor.isWhite()) {
colorIdentity.setWhite(true);
}
if (commanderColor.isBlue()) {
colorIdentity.setBlue(true);
}
if (commanderColor.isBlack()) {
colorIdentity.setBlack(true);
}
if (commanderColor.isRed()) {
colorIdentity.setRed(true);
}
if (commanderColor.isGreen()) {
colorIdentity.setGreen(true);
}
if (commanderColor.isColorless()) {
colorIdentity.setColorless(true);
}
} }
} }
Set<String> basicsInDeck = new HashSet<>(); Set<String> basicsInDeck = new HashSet<>();
@ -108,7 +83,7 @@ public class Brawl extends Constructed {
} }
} }
for (Card card : deck.getCards()) { for (Card card : deck.getCards()) {
if (!cardHasValidColor(colorIdentity, card) if (!ManaUtil.isColorIdentityCompatible(colorIdentity, card.getColorIdentity())
&& !(colorIdentity.isColorless() && !(colorIdentity.isColorless()
&& basicsInDeck.size() == 1 && basicsInDeck.size() == 1
&& basicsInDeck.contains(card.getName()))) { && basicsInDeck.contains(card.getName()))) {
@ -135,13 +110,4 @@ public class Brawl extends Constructed {
return valid; return valid;
} }
public boolean cardHasValidColor(FilterMana commander, Card card) {
FilterMana cardColor = card.getColorIdentity();
return !(cardColor.isBlack() && !commander.isBlack()
|| cardColor.isBlue() && !commander.isBlue()
|| cardColor.isGreen() && !commander.isGreen()
|| cardColor.isRed() && !commander.isRed()
|| cardColor.isWhite() && !commander.isWhite());
}
} }

View file

@ -13,23 +13,23 @@ import java.util.Map;
*/ */
public class CanadianHighlander extends Constructed { public class CanadianHighlander extends Constructed {
public static final Map<String, Integer> pointMap = new HashMap<>(); private static final Map<String, Integer> pointMap = new HashMap<>();
static { static {
pointMap.put("Ancestral Recall", 7); pointMap.put("Ancestral Recall", 7);
pointMap.put("Balance", 1); pointMap.put("Balance", 1);
pointMap.put("Birthing Pod", 2); pointMap.put("Birthing Pod", 2);
pointMap.put("Black Lotus", 7); pointMap.put("Black Lotus", 7);
pointMap.put("Demonic Tutor", 3); pointMap.put("Crop Rotation", 1);
pointMap.put("Demonic Tutor", 4);
pointMap.put("Dig Through Time", 1); pointMap.put("Dig Through Time", 1);
pointMap.put("Enlightened Tutor", 1); pointMap.put("Enlightened Tutor", 1);
pointMap.put("Fastbond", 1); pointMap.put("Flash", 6);
pointMap.put("Flash", 7);
pointMap.put("Gifts Ungiven", 2); pointMap.put("Gifts Ungiven", 2);
pointMap.put("Imperial Seal", 1); pointMap.put("Imperial Seal", 1);
pointMap.put("Intuition", 1); pointMap.put("Intuition", 1);
pointMap.put("Library of Alexandria", 1); pointMap.put("Library of Alexandria", 1);
pointMap.put("Mana Crypt", 3); pointMap.put("Mana Crypt", 4);
pointMap.put("Mana Drain", 1); pointMap.put("Mana Drain", 1);
pointMap.put("Mana Vault", 1); pointMap.put("Mana Vault", 1);
pointMap.put("Merchant Scroll", 1); pointMap.put("Merchant Scroll", 1);
@ -42,7 +42,7 @@ public class CanadianHighlander extends Constructed {
pointMap.put("Mystical Tutor", 2); pointMap.put("Mystical Tutor", 2);
pointMap.put("Natural Order", 4); pointMap.put("Natural Order", 4);
pointMap.put("Protean Hulk", 3); pointMap.put("Protean Hulk", 3);
pointMap.put("Sol Ring", 3); pointMap.put("Sol Ring", 4);
pointMap.put("Spellseeker", 1); pointMap.put("Spellseeker", 1);
pointMap.put("Stoneforge Mystic", 1); pointMap.put("Stoneforge Mystic", 1);
pointMap.put("Strip Mine", 2); pointMap.put("Strip Mine", 2);
@ -56,7 +56,7 @@ public class CanadianHighlander extends Constructed {
pointMap.put("Treasure Cruise", 1); pointMap.put("Treasure Cruise", 1);
pointMap.put("True-Name Nemesis", 1); pointMap.put("True-Name Nemesis", 1);
pointMap.put("Umezawa's Jitte", 2); pointMap.put("Umezawa's Jitte", 2);
pointMap.put("Vampiric Tutor", 3); pointMap.put("Vampiric Tutor", 2);
} }
public CanadianHighlander() { public CanadianHighlander() {
@ -89,14 +89,7 @@ public class CanadianHighlander extends Constructed {
Map<String, Integer> counts = new HashMap<>(); Map<String, Integer> counts = new HashMap<>();
countCards(counts, deck.getCards()); countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard()); countCards(counts, deck.getSideboard());
for (Map.Entry<String, Integer> entry : counts.entrySet()) { valid = checkCounts(1, counts) && valid;
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
int allowedPoints = 10; int allowedPoints = 10;
int totalPoints = 0; int totalPoints = 0;

View file

@ -0,0 +1,86 @@
package mage.deck;
/**
*
* @author andreacosta
*/
public class CenturionCommander extends Commander {
public CenturionCommander() {
super("Centurion Commander");
banned.add("Ancestral Recall");
banned.add("Ancient Tomb");
banned.add("Back to Basic");
banned.add("Balance");
banned.add("Bazaar of Baghdad");
banned.add("Black Lotus");
banned.add("Cataclysm");
banned.add("Channel");
banned.add("Chaos Orb");
banned.add("Chrome Mox");
banned.add("Demonic Tutor");
banned.add("Dig Through Time");
banned.add("Emrakul, the Aeons Torn");
banned.add("Emrakul, the Promised End");
banned.add("Entomb");
banned.add("Erayo, Soratami Ascendant");
banned.add("Falling Star");
banned.add("Fastbond");
banned.add("Food Chain");
banned.add("Gaeas Cradle");
banned.add("Gifts Ungiven");
banned.add("Grim Monolith");
banned.add("Grindstone");
banned.add("Hermit Druid");
banned.add("High Tide");
banned.add("Humility");
banned.add("Imperial Seal");
banned.add("Karakas");
banned.add("Library of Alexandria");
banned.add("Mana Crypt");
banned.add("Mana Drain");
banned.add("Mana Vault");
banned.add("Mishras Workshop");
banned.add("Mind Twist");
banned.add("Mox Diamond");
banned.add("Mox Emerald");
banned.add("Mox Jet");
banned.add("Mox Pearl");
banned.add("Mox Ruby");
banned.add("Mox Sapphire");
banned.add("Mystical Tutor");
banned.add("Natural Order");
banned.add("Necropotence");
banned.add("Oath of Druids");
banned.add("Protean Hulk");
banned.add("Senseis Diving Top");
banned.add("Serra Ascendant");
banned.add("Sharazad");
banned.add("Survival of the Fittest");
banned.add("Sol Ring");
banned.add("Strip Mine");
banned.add("The Tabernacle at Pendrell Vale");
banned.add("Time Vault");
banned.add("Time Walk");
banned.add("Tinker");
banned.add("Tolarian Academy");
banned.add("Treasure Cruise");
banned.add("Vampiric Tutor");
banned.add("Vanishing");
banned.add("Winter Orb");
banned.add("Yawgmoths Bargain");
bannedCommander.add("Baral, Chief of Compliance");
bannedCommander.add("Derevi, Empyrial Tactician");
bannedCommander.add("Edgar Markov");
bannedCommander.add("Kess, Dissident Mage");
bannedCommander.add("Rofellos, Llanowar Emissary");
bannedPartner.add("Rowan Kenrith");
bannedPartner.add("Tymna the Weaver");
bannedPartner.add("Will Kenrith");
bannedPartner.add("Vial Smasher The Fierce");
}
}

View file

@ -12,6 +12,7 @@ import mage.cards.Sets;
import mage.cards.decks.Constructed; import mage.cards.decks.Constructed;
import mage.cards.decks.Deck; import mage.cards.decks.Deck;
import mage.filter.FilterMana; import mage.filter.FilterMana;
import mage.util.ManaUtil;
import java.util.*; import java.util.*;
@ -20,7 +21,8 @@ import java.util.*;
*/ */
public class Commander extends Constructed { public class Commander extends Constructed {
protected List<String> bannedCommander = new ArrayList<>(); protected final List<String> bannedCommander = new ArrayList<>();
protected final List<String> bannedPartner = new ArrayList<>();
protected boolean partnerAllowed = true; protected boolean partnerAllowed = true;
public Commander() { public Commander() {
@ -42,6 +44,7 @@ public class Commander extends Constructed {
banned.add("Fastbond"); banned.add("Fastbond");
banned.add("Gifts Ungiven"); banned.add("Gifts Ungiven");
banned.add("Griselbrand"); banned.add("Griselbrand");
banned.add("Iona, Shield of Emeria");
banned.add("Karakas"); banned.add("Karakas");
banned.add("Leovold, Emissary of Trest"); banned.add("Leovold, Emissary of Trest");
banned.add("Library of Alexandria"); banned.add("Library of Alexandria");
@ -51,8 +54,8 @@ public class Commander extends Constructed {
banned.add("Mox Pearl"); banned.add("Mox Pearl");
banned.add("Mox Ruby"); banned.add("Mox Ruby");
banned.add("Mox Sapphire"); banned.add("Mox Sapphire");
banned.add("Painter's Servant");
banned.add("Panoptic Mirror"); banned.add("Panoptic Mirror");
banned.add("Paradox Engine");
banned.add("Primeval Titan"); banned.add("Primeval Titan");
banned.add("Prophet of Kruphix"); banned.add("Prophet of Kruphix");
banned.add("Recurring Nightmare"); banned.add("Recurring Nightmare");
@ -97,14 +100,7 @@ public class Commander extends Constructed {
Map<String, Integer> counts = new HashMap<>(); Map<String, Integer> counts = new HashMap<>();
countCards(counts, deck.getCards()); countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard()); countCards(counts, deck.getSideboard());
for (Map.Entry<String, Integer> entry : counts.entrySet()) { valid = checkCounts(1, counts) && valid;
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
for (String bannedCard : banned) { for (String bannedCard : banned) {
if (counts.containsKey(bannedCard)) { if (counts.containsKey(bannedCard)) {
@ -113,7 +109,7 @@ public class Commander extends Constructed {
} }
} }
if (deck.getSideboard().size() < 1 || deck.getSideboard().size() > 2) { if (deck.getSideboard().isEmpty() || deck.getSideboard().size() > 2) {
if ((deck.getSideboard().size() > 1 && !partnerAllowed)) { if ((deck.getSideboard().size() > 1 && !partnerAllowed)) {
invalid.put("Commander", "You may only have one commander"); invalid.put("Commander", "You may only have one commander");
} }
@ -134,40 +130,36 @@ public class Commander extends Constructed {
invalid.put("Commander", "Commander invalid (" + commander.getName() + ')'); invalid.put("Commander", "Commander invalid (" + commander.getName() + ')');
valid = false; valid = false;
} }
if (deck.getSideboard().size() == 2 && !commander.getAbilities().contains(PartnerAbility.getInstance())) { if (deck.getSideboard().size() == 2) {
boolean partnersWith = false; if (commander.getAbilities().contains(PartnerAbility.getInstance())) {
for (Ability ability : commander.getAbilities()) { if (bannedPartner.contains(commander.getName())) {
if (ability instanceof PartnerWithAbility invalid.put("Commander", "Partner banned (" + commander.getName() + ')');
&& commanderNames.contains(((PartnerWithAbility) ability).getPartnerName())) { valid = false;
partnersWith = true; }
break; } else {
boolean partnersWith = commander.getAbilities()
.stream()
.filter(PartnerWithAbility.class::isInstance)
.map(PartnerWithAbility.class::cast)
.map(PartnerWithAbility::getPartnerName)
.anyMatch(commanderNames::contains);
if (!partnersWith) {
invalid.put("Commander", "Commander without Partner (" + commander.getName() + ')');
valid = false;
} }
} }
if (!partnersWith) {
invalid.put("Commander", "Commander without Partner (" + commander.getName() + ')');
valid = false;
}
}
FilterMana commanderColor = commander.getColorIdentity();
if (commanderColor.isWhite()) {
colorIdentity.setWhite(true);
}
if (commanderColor.isBlue()) {
colorIdentity.setBlue(true);
}
if (commanderColor.isBlack()) {
colorIdentity.setBlack(true);
}
if (commanderColor.isRed()) {
colorIdentity.setRed(true);
}
if (commanderColor.isGreen()) {
colorIdentity.setGreen(true);
} }
ManaUtil.collectColorIdentity(colorIdentity, commander.getColorIdentity());
} }
} }
// no needs in cards check on wrong commanders
if (!valid) {
return false;
}
for (Card card : deck.getCards()) { for (Card card : deck.getCards()) {
if (!cardHasValidColor(colorIdentity, card)) { if (!ManaUtil.isColorIdentityCompatible(colorIdentity, card.getColorIdentity())) {
invalid.put(card.getName(), "Invalid color (" + colorIdentity.toString() + ')'); invalid.put(card.getName(), "Invalid color (" + colorIdentity.toString() + ')');
valid = false; valid = false;
} }
@ -191,15 +183,6 @@ public class Commander extends Constructed {
return valid; return valid;
} }
public boolean cardHasValidColor(FilterMana commander, Card card) {
FilterMana cardColor = card.getColorIdentity();
return !(cardColor.isBlack() && !commander.isBlack()
|| cardColor.isBlue() && !commander.isBlue()
|| cardColor.isGreen() && !commander.isGreen()
|| cardColor.isRed() && !commander.isRed()
|| cardColor.isWhite() && !commander.isWhite());
}
@Override @Override
public int getEdhPowerLevel(Deck deck) { public int getEdhPowerLevel(Deck deck) {
if (deck == null) { if (deck == null) {

View file

@ -47,6 +47,7 @@ public class DuelCommander extends Commander {
banned.add("Polymorph"); banned.add("Polymorph");
banned.add("Price of Progress"); banned.add("Price of Progress");
banned.add("Protean Hulk"); banned.add("Protean Hulk");
banned.add("Scapeshift");
banned.add("Sensei's Divining Top"); banned.add("Sensei's Divining Top");
banned.add("Shahrazad"); banned.add("Shahrazad");
banned.add("Sol Ring"); banned.add("Sol Ring");
@ -55,25 +56,30 @@ public class DuelCommander extends Commander {
banned.add("The Tabernacle at Pendrell Vale"); banned.add("The Tabernacle at Pendrell Vale");
banned.add("Time Vault"); banned.add("Time Vault");
banned.add("Time Walk"); banned.add("Time Walk");
banned.add("Timetwister");
banned.add("Tinker"); banned.add("Tinker");
banned.add("Tolarian Academy"); banned.add("Tolarian Academy");
banned.add("Treasure Cruise"); banned.add("Treasure Cruise");
banned.add("Vampiric Tutor"); banned.add("Vampiric Tutor");
bannedCommander.add("Arahbo, Roar of the World");
bannedCommander.add("Breya, Etherium Shaper"); bannedCommander.add("Breya, Etherium Shaper");
bannedCommander.add("Bruse Tarl, Boorish Herder"); bannedCommander.add("Bruse Tarl, Boorish Herder");
bannedCommander.add("Derevi, Empyrial Tactician"); bannedCommander.add("Derevi, Empyrial Tactician");
bannedCommander.add("Edgar Markov"); bannedCommander.add("Edgar Markov");
bannedCommander.add("Edric, Spymaster of Trest"); bannedCommander.add("Edric, Spymaster of Trest");
bannedCommander.add("Erayo, Soratami Ascendant"); bannedCommander.add("Emry, Lurker of the Loch");
bannedCommander.add("Geist of Saint Traft"); bannedCommander.add("Geist of Saint Traft");
bannedCommander.add("Jace, Vryn's Prodigy"); bannedCommander.add("Jace, Vryn's Prodigy");
bannedCommander.add("Marath, Will of the Wild"); bannedCommander.add("Marath, Will of the Wild");
bannedCommander.add("Najeela, the Blade-Blossom");
bannedCommander.add("Oloro, Ageless Ascetic"); bannedCommander.add("Oloro, Ageless Ascetic");
bannedCommander.add("Rofellos, Llanowar Emissary"); bannedCommander.add("Rofellos, Llanowar Emissary");
bannedCommander.add("Tasigur, the Golden Fang"); bannedCommander.add("Tasigur, the Golden Fang");
bannedCommander.add("Teferi, Temporal Archmage");
bannedCommander.add("Urza, Lord High Artificer");
bannedCommander.add("Vial Smasher the Fierce"); bannedCommander.add("Vial Smasher the Fierce");
bannedCommander.add("Zur the Enchanter"); bannedCommander.add("Yuriko, the Tigers Shadow");
bannedCommander.add("Zurgo Bellstriker"); bannedCommander.add("Zurgo Bellstriker");
} }

View file

@ -9,6 +9,7 @@ import mage.cards.Sets;
import mage.cards.decks.Constructed; import mage.cards.decks.Constructed;
import mage.cards.decks.Deck; import mage.cards.decks.Deck;
import mage.filter.FilterMana; import mage.filter.FilterMana;
import mage.util.ManaUtil;
import java.util.*; import java.util.*;
@ -58,18 +59,9 @@ public class FreeformCommander extends Constructed {
countCards(counts, deck.getCards()); countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard()); countCards(counts, deck.getSideboard());
for (Map.Entry<String, Integer> entry : counts.entrySet()) { valid = checkCounts(1, counts) && valid;
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
generateFreeformHash(); if (deck.getSideboard().isEmpty() || deck.getSideboard().size() > 2) {
if (deck.getSideboard().size() < 1 || deck.getSideboard().size() > 2) {
invalid.put("Commander", "Sideboard must contain only the commander(s)"); invalid.put("Commander", "Sideboard must contain only the commander(s)");
valid = false; valid = false;
} else { } else {
@ -97,27 +89,17 @@ public class FreeformCommander extends Constructed {
valid = false; valid = false;
} }
} }
FilterMana commanderColor = commander.getColorIdentity(); ManaUtil.collectColorIdentity(colorIdentity, commander.getColorIdentity());
if (commanderColor.isWhite()) {
colorIdentity.setWhite(true);
}
if (commanderColor.isBlue()) {
colorIdentity.setBlue(true);
}
if (commanderColor.isBlack()) {
colorIdentity.setBlack(true);
}
if (commanderColor.isRed()) {
colorIdentity.setRed(true);
}
if (commanderColor.isGreen()) {
colorIdentity.setGreen(true);
}
} }
} }
// no needs in cards check on wrong commanders
if (!valid) {
return false;
}
for (Card card : deck.getCards()) { for (Card card : deck.getCards()) {
if (!cardHasValidColor(colorIdentity, card)) { if (!ManaUtil.isColorIdentityCompatible(colorIdentity, card.getColorIdentity())) {
invalid.put(card.getName(), "Invalid color (" + colorIdentity.toString() + ')'); invalid.put(card.getName(), "Invalid color (" + colorIdentity.toString() + ')');
valid = false; valid = false;
} }
@ -133,17 +115,4 @@ public class FreeformCommander extends Constructed {
} }
return valid; return valid;
} }
public boolean cardHasValidColor(FilterMana commander, Card card) {
FilterMana cardColor = card.getColorIdentity();
return !(cardColor.isBlack() && !commander.isBlack()
|| cardColor.isBlue() && !commander.isBlue()
|| cardColor.isGreen() && !commander.isGreen()
|| cardColor.isRed() && !commander.isRed()
|| cardColor.isWhite() && !commander.isWhite());
}
public void generateFreeformHash() {
return;
}
} }

View file

@ -4,6 +4,7 @@ import mage.cards.ExpansionSet;
import mage.cards.Sets; import mage.cards.Sets;
import mage.cards.decks.Constructed; import mage.cards.decks.Constructed;
import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
@ -15,7 +16,7 @@ public class Frontier extends Constructed {
public Frontier() { public Frontier() {
super("Constructed - Frontier"); super("Constructed - Frontier");
Date cutoff = new GregorianCalendar(2014, 6, 18).getTime(); // M15 release date Date cutoff = new GregorianCalendar(2014, Calendar.JULY, 18).getTime(); // M15 release date
for (ExpansionSet set : Sets.getInstance().values()) { for (ExpansionSet set : Sets.getInstance().values()) {
if (set.getSetType().isStandardLegal() && (set.getReleaseDate().after(cutoff) || set.getReleaseDate().equals(cutoff))) { if (set.getSetType().isStandardLegal() && (set.getReleaseDate().after(cutoff) || set.getReleaseDate().equals(cutoff))) {
setCodes.add(set.getCode()); setCodes.add(set.getCode());

View file

@ -12,9 +12,9 @@ public class InnistradBlock extends Constructed {
public InnistradBlock() { public InnistradBlock() {
super("Constructed - Innistrad Block"); super("Constructed - Innistrad Block");
setCodes.add("ISD"); setCodes.add(mage.sets.Innistrad.getInstance().getCode());
setCodes.add("DKA"); setCodes.add(mage.sets.DarkAscension.getInstance().getCode());
setCodes.add("AVR"); setCodes.add(mage.sets.AvacynRestored.getInstance().getCode());
} }
} }

View file

@ -11,7 +11,7 @@ public class IxalanBlock extends Constructed {
public IxalanBlock() { public IxalanBlock() {
super("Constructed - Ixalan Block"); super("Constructed - Ixalan Block");
setCodes.add("XLN"); setCodes.add(mage.sets.Ixalan.getInstance().getCode());
setCodes.add("RIX"); setCodes.add(mage.sets.RivalsOfIxalan.getInstance().getCode());
} }
} }

View file

@ -12,7 +12,7 @@ public class KaladeshBlock extends Constructed {
public KaladeshBlock() { public KaladeshBlock() {
super("Constructed - Kaladesh Block"); super("Constructed - Kaladesh Block");
setCodes.add("KLD"); setCodes.add(mage.sets.Kaladesh.getInstance().getCode());
setCodes.add("AER"); setCodes.add(mage.sets.AetherRevolt.getInstance().getCode());
} }
} }

View file

@ -12,9 +12,9 @@ public class KamigawaBlock extends Constructed {
public KamigawaBlock() { public KamigawaBlock() {
super("Constructed - Kamigawa Block"); super("Constructed - Kamigawa Block");
setCodes.add("CHK"); setCodes.add(mage.sets.ChampionsOfKamigawa.getInstance().getCode());
setCodes.add("BOK"); setCodes.add(mage.sets.BetrayersOfKamigawa.getInstance().getCode());
setCodes.add("SOK"); setCodes.add(mage.sets.SaviorsOfKamigawa.getInstance().getCode());
} }
} }

View file

@ -12,9 +12,9 @@ public class KhansOfTarkirBlock extends Constructed {
public KhansOfTarkirBlock() { public KhansOfTarkirBlock() {
super("Constructed - Khans of Tarkir Block"); super("Constructed - Khans of Tarkir Block");
setCodes.add("KTK"); setCodes.add(mage.sets.KhansOfTarkir.getInstance().getCode());
setCodes.add("FRF"); setCodes.add(mage.sets.FateReforged.getInstance().getCode());
setCodes.add("DTK"); setCodes.add(mage.sets.DragonsOfTarkir.getInstance().getCode());
} }
} }

View file

@ -90,6 +90,7 @@ public class Legacy extends Constructed {
banned.add("Wheel of Fortune"); banned.add("Wheel of Fortune");
banned.add("Windfall"); banned.add("Windfall");
banned.add("Worldknit"); banned.add("Worldknit");
banned.add("Wrenn and Six");
banned.add("Yawgmoth's Bargain"); banned.add("Yawgmoth's Bargain");
banned.add("Yawgmoth's Will"); banned.add("Yawgmoth's Will");

View file

@ -11,7 +11,7 @@ public class LorwynBlock extends Constructed {
public LorwynBlock() { public LorwynBlock() {
super("Constructed - Lorwyn Block"); super("Constructed - Lorwyn Block");
setCodes.add("LRW"); setCodes.add(mage.sets.Lorwyn.getInstance().getCode());
setCodes.add("MOR"); setCodes.add(mage.sets.Morningtide.getInstance().getCode());
} }
} }

View file

@ -4,6 +4,7 @@ import mage.cards.ExpansionSet;
import mage.cards.Sets; import mage.cards.Sets;
import mage.cards.decks.Constructed; import mage.cards.decks.Constructed;
import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
@ -15,7 +16,7 @@ public class Modern extends Constructed {
public Modern() { public Modern() {
super("Constructed - Modern"); super("Constructed - Modern");
Date cutoff = new GregorianCalendar(2003, 6, 28).getTime(); // Eight edition release date Date cutoff = new GregorianCalendar(2003, Calendar.JULY, 28).getTime(); // Eight edition release date
for (ExpansionSet set : Sets.getInstance().values()) { for (ExpansionSet set : Sets.getInstance().values()) {
if (set.getSetType().isModernLegal() && (set.getReleaseDate().after(cutoff) || set.getReleaseDate().equals(cutoff))) { if (set.getSetType().isModernLegal() && (set.getReleaseDate().after(cutoff) || set.getReleaseDate().equals(cutoff))) {
setCodes.add(set.getCode()); setCodes.add(set.getCode());
@ -25,6 +26,7 @@ public class Modern extends Constructed {
banned.add("Ancient Den"); banned.add("Ancient Den");
banned.add("Birthing Pod"); banned.add("Birthing Pod");
banned.add("Blazing Shoal"); banned.add("Blazing Shoal");
banned.add("Bridge from Below");
banned.add("Chrome Mox"); banned.add("Chrome Mox");
banned.add("Cloudpost"); banned.add("Cloudpost");
banned.add("Dark Depths"); banned.add("Dark Depths");
@ -32,11 +34,13 @@ public class Modern extends Constructed {
banned.add("Dig Through Time"); banned.add("Dig Through Time");
banned.add("Dread Return"); banned.add("Dread Return");
banned.add("Eye of Ugin"); banned.add("Eye of Ugin");
banned.add("Faithless Looting");
banned.add("Gitaxian Probe"); banned.add("Gitaxian Probe");
banned.add("Glimpse of Nature"); banned.add("Glimpse of Nature");
banned.add("Golgari Grave-Troll"); banned.add("Golgari Grave-Troll");
banned.add("Great Furnace"); banned.add("Great Furnace");
banned.add("Green Sun's Zenith"); banned.add("Green Sun's Zenith");
banned.add("Hogaak, Arisen Necropolis");
banned.add("Hypergenesis"); banned.add("Hypergenesis");
banned.add("Krark-Clan Ironworks"); banned.add("Krark-Clan Ironworks");
banned.add("Mental Misstep"); banned.add("Mental Misstep");
@ -48,7 +52,6 @@ public class Modern extends Constructed {
banned.add("Second Sunrise"); banned.add("Second Sunrise");
banned.add("Seething Song"); banned.add("Seething Song");
banned.add("Sensei's Divining Top"); banned.add("Sensei's Divining Top");
banned.add("Stoneforge Mystic");
banned.add("Skullclamp"); banned.add("Skullclamp");
banned.add("Splinter Twin"); banned.add("Splinter Twin");
banned.add("Summer Bloom"); banned.add("Summer Bloom");

View file

@ -4,6 +4,7 @@ import mage.cards.ExpansionSet;
import mage.cards.Sets; import mage.cards.Sets;
import mage.cards.decks.Constructed; import mage.cards.decks.Constructed;
import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
@ -15,7 +16,7 @@ public class ModernNoBannedList extends Constructed {
public ModernNoBannedList() { public ModernNoBannedList() {
super("Constructed - Modern - No Banned List"); super("Constructed - Modern - No Banned List");
Date cutoff = new GregorianCalendar(2003, 6, 28).getTime(); // Eight edition release date Date cutoff = new GregorianCalendar(2003, Calendar.JULY, 28).getTime(); // Eight edition release date
for (ExpansionSet set : Sets.getInstance().values()) { for (ExpansionSet set : Sets.getInstance().values()) {
if (set.getSetType().isModernLegal() && (set.getReleaseDate().after(cutoff) || set.getReleaseDate().equals(cutoff))) { if (set.getSetType().isModernLegal() && (set.getReleaseDate().after(cutoff) || set.getReleaseDate().equals(cutoff))) {
setCodes.add(set.getCode()); setCodes.add(set.getCode());

View file

@ -0,0 +1,205 @@
package mage.deck;
import mage.abilities.Ability;
import mage.abilities.keyword.PartnerAbility;
import mage.abilities.keyword.PartnerWithAbility;
import mage.cards.Card;
import mage.cards.decks.Deck;
import mage.filter.FilterMana;
import mage.util.ManaUtil;
import java.util.*;
/**
* @author JayDi85
*/
public class Oathbreaker extends Vintage {
protected List<String> bannedCommander = new ArrayList<>();
private static final Map<String, Integer> pdAllowed = new HashMap<>();
public Oathbreaker() {
super();
this.name = "Oathbreaker";
// banned = vintage + oathbreaker's list: https://weirdcards.org/oathbreaker-ban-list
// last updated 8/2/19 - Primeval Titan unbanned
banned.add("Ad Nauseam");
banned.add("Ancestral Recall");
banned.add("Balance");
banned.add("Biorhythm");
banned.add("Black Lotus");
banned.add("Channel");
banned.add("Doomsday");
banned.add("Emrakul, the Aeons Torn");
banned.add("Expropriate");
banned.add("Fastbond");
banned.add("Gifts Ungiven");
banned.add("Griselbrand");
banned.add("High Tide");
banned.add("Library of Alexandria");
banned.add("Limited Resources");
banned.add("Lion's Eye Diamond");
banned.add("Mana Crypt");
banned.add("Mana Geyser");
banned.add("Mana Vault");
banned.add("Mox Emerald");
banned.add("Mox Jet");
banned.add("Mox Pearl");
banned.add("Mox Ruby");
banned.add("Mox Sapphire");
banned.add("Natural Order");
banned.add("Painter's Servant");
banned.add("Panoptic Mirror");
banned.add("Primal Surge");
banned.add("Saheeli, the Gifted");
banned.add("Sol Ring");
banned.add("Sundering Titan");
banned.add("Sway of the Stars");
banned.add("Sylvan Primordial");
banned.add("Time Vault");
banned.add("Time Walk");
banned.add("Tinker");
banned.add("Tolarian Academy");
banned.add("Tooth and Nail");
banned.add("Trade Secrets");
banned.add("Upheaval");
banned.add("Worldfire");
banned.add("Yawgmoth's Bargain");
}
@Override
public int getDeckMinSize() {
return 60 - (2 + 2); // 2 x spells + 2 x partner oathbreakers
}
@Override
public int getSideboardMinSize() {
return 2; // spell + oathbreaker
}
@Override
public boolean validate(Deck deck) {
boolean valid = true;
if (deck.getCards().size() + deck.getSideboard().size() != 60) {
invalid.put("Deck", "Must contain " + 60 + " cards: has " + (deck.getCards().size() + deck.getSideboard().size()) + " cards");
valid = false;
}
Map<String, Integer> counts = new HashMap<>();
countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard());
for (String bannedCard : banned) {
if (counts.containsKey(bannedCard)) {
invalid.put(bannedCard, "Banned");
valid = false;
}
}
valid = checkCounts(1, counts) && valid;
Set<String> commanderNames = new HashSet<>();
Set<String> signatureSpells = new HashSet<>();
FilterMana allCommandersColor = new FilterMana();
if (deck.getSideboard().size() < 2 || deck.getSideboard().size() > 4) {
invalid.put("Oathbreaker", "Sideboard must contain only 2 or 4 cards (oathbreaker + signature spell)");
valid = false;
} else {
// collect data
for (Card commander : deck.getSideboard()) {
if (commander.isInstantOrSorcery()) {
signatureSpells.add(commander.getName());
} else {
if (commander.isPlaneswalker()) {
commanderNames.add(commander.getName());
// color identity from commanders only, not spell
ManaUtil.collectColorIdentity(allCommandersColor, commander.getColorIdentity());
} else {
invalid.put("Oathbreaker", "Only planeswalker can be Oathbreaker, not " + commander.getName());
valid = false;
}
}
}
// check size (1+1 or 2+2 allows)
if (commanderNames.isEmpty() || commanderNames.size() > 2) {
invalid.put("Oathbreaker", "Sideboard must contains 1 or 2 oathbreakers, but found: " + commanderNames.size());
valid = false;
}
if (signatureSpells.isEmpty() || signatureSpells.size() > 2) {
invalid.put("Signature Spell", "Sideboard must contains 1 or 2 signature spells, but found: " + signatureSpells.size());
valid = false;
}
if (signatureSpells.size() != commanderNames.size()) {
invalid.put("Oathbreaker", "Sideboard must contains 1 + 1 or 2 + 2 cards, but found: " + commanderNames.size() + " + " + signatureSpells.size());
valid = false;
}
// check partners
for (Card commander : deck.getSideboard()) {
if (commanderNames.contains(commander.getName())) {
// partner checks
if (commanderNames.size() == 2 && !commander.getAbilities().contains(PartnerAbility.getInstance())) {
boolean partnersWith = false;
for (Ability ability : commander.getAbilities()) {
if (ability instanceof PartnerWithAbility && commanderNames.contains(((PartnerWithAbility) ability).getPartnerName())) {
partnersWith = true;
break;
}
}
if (!partnersWith) {
invalid.put("Oathbreaker", "Oathbreaker without Partner (" + commander.getName() + ')');
valid = false;
}
}
}
}
// check spell color (one spell must be used by one oathbreaker)
// xmage doesn't allows to select pairs of spell + oathbreaker, what's why it requires one color combo minimum
for (Card spell : deck.getSideboard()) {
if (signatureSpells.contains(spell.getName())) {
FilterMana spellColor = spell.getColorIdentity();
boolean haveSameColor = false;
for (Card commander : deck.getSideboard()) {
if (commanderNames.contains(commander.getName())) {
FilterMana commanderColor = commander.getColorIdentity();
if (ManaUtil.isColorIdentityCompatible(commanderColor, spellColor)) {
haveSameColor = true;
}
}
}
if (!haveSameColor) {
invalid.put("Signature Spell", "Can't find oathbreaker with compatible color identity (" + spell.getName() + " - " + spellColor + ")");
valid = false;
}
}
}
}
// no needs in cards check on wrong commanders
if (!valid) {
return false;
}
for (Card card : deck.getCards()) {
if (!ManaUtil.isColorIdentityCompatible(allCommandersColor, card.getColorIdentity())) {
invalid.put(card.getName(), "Invalid color (" + card.getColorIdentity() + ')');
valid = false;
}
}
for (Card card : deck.getSideboard()) {
if (!isSetAllowed(card.getExpansionSetCode())) {
if (!legalSets(card)) {
invalid.put(card.getName(), "Not allowed Set: " + card.getExpansionSetCode());
valid = false;
}
}
}
return valid;
}
}

Some files were not shown because too many files have changed in this diff Show more