1
0
Fork 0
mirror of https://github.com/correl/mage.git synced 2025-04-02 03:18:09 -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.MomirDuel/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.FreeformCommanderDuel/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.cson
build-output.log
# Visual Studio Code
.history

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.35</version>
<version>1.4.41</version>
</parent>
<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.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
btnDebug.addMouseListener(new java.awt.event.MouseAdapter() {
@Override
public void mouseClicked(java.awt.event.MouseEvent evt) {
btnDebugMouseClicked(evt);
}

View file

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

View file

@ -952,13 +952,16 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
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.addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
reselectBy();
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
});

View file

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

View file

@ -60,6 +60,7 @@ public class ManaPieChart extends JComponent {
return preferred;
}
@Override
public void paint(Graphics g) {
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.setPreferredSize(new java.awt.Dimension(6, 70));
txtMessage.addKeyListener(new java.awt.event.KeyAdapter() {
@Override
public void keyTyped(java.awt.event.KeyEvent evt) {
txtMessageKeyTyped(evt);
}

View file

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

View file

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

View file

@ -1415,14 +1415,15 @@ class ImportFilter extends FileFilter {
|| ext.equalsIgnoreCase("dek")
|| ext.equalsIgnoreCase("cod")
|| ext.equalsIgnoreCase("o8d")
|| ext.equalsIgnoreCase("draft");
|| ext.equalsIgnoreCase("draft")
|| ext.equalsIgnoreCase("mtga");
}
return false;
}
@Override
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);
int numPlanes = 0;
if (planes != null && planes.size() > 0) {
if (!planes.isEmpty()) {
int size = planes.size();
numPlanes = size;
Rectangle rectangle = new Rectangle();
@ -523,7 +523,7 @@ public class MageBook extends JComponent {
// second run for empty numbers
int countHave = haveNumbers.size();
int countNotHave = 0;
if (cards.size() > 0) {
if (!cards.isEmpty()) {
for (int i = startNumber; i <= endNumber; i++) {
if (!haveNumbers.contains(i)) {
countNotHave++;
@ -593,8 +593,8 @@ public class MageBook extends JComponent {
}
private List<Emblem> getEmblems(int page, String set, int numTokensEmblems) {
ArrayList<CardDownloadData> allEmblems = getTokenCardUrls();
ArrayList<Emblem> emblems = new ArrayList<>();
List<CardDownloadData> allEmblems = getTokenCardUrls();
List<Emblem> emblems = new ArrayList<>();
for (CardDownloadData emblem : allEmblems) {
if (emblem.getSet().equals(set)) {
@ -650,8 +650,8 @@ public class MageBook extends JComponent {
}
private List<Plane> getPlanes(int page, String set, int numTokensEmblems) {
ArrayList<CardDownloadData> allPlanes = getTokenCardUrls();
ArrayList<Plane> planes = new ArrayList<>();
List<CardDownloadData> allPlanes = getTokenCardUrls();
List<Plane> planes = new ArrayList<>();
for (CardDownloadData plane : allPlanes) {
if (plane.getSet().equals(set)) {
@ -695,13 +695,13 @@ public class MageBook extends JComponent {
int totalTokensEmblems = totalTokens + getTotalNumEmblems(set);
int start = 0;
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);
}
int end = 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);
} else {
pageRight.setVisible(false);

View file

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

View file

@ -422,8 +422,8 @@
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/flags/us.png"/>
</Property>
<Property name="text" type="java.lang.String" value="P"/>
<Property name="toolTipText" type="java.lang.String" value="Connect to mtg.powersofwar.com (USA, use any username without registration)"/>
<Property name="text" type="java.lang.String" value="US"/>
<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="alignmentY" type="float" value="0.0"/>
<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.setText("P");
btnFindUs.setToolTipText("Connect to mtg.powersofwar.com (USA, use any username without registration)");
btnFindUs.setText("US");
btnFindUs.setToolTipText("Connect to us.xmage.today (USA, use any username without registration)");
btnFindUs.setActionCommand("connectXmageus");
btnFindUs.setAlignmentY(0.0F);
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);
panelFast.setLayout(panelFastLayout);
panelFastLayout.setHorizontalGroup(
panelFastLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelFastLayout.createSequentialGroup()
.addGap(0, 0, 0)
.addComponent(btnFindMain, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFindUs, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFindBeta, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFindLocal, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFindOther, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGap(0, 0, 0))
panelFastLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelFastLayout.createSequentialGroup()
.addGap(0, 0, 0)
.addComponent(btnFindMain, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFindUs, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFindBeta, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFindLocal, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFindOther, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGap(0, 0, 0))
);
panelFastLayout.setVerticalGroup(
panelFastLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelFastLayout.createSequentialGroup()
.addGap(0, 0, 0)
.addGroup(panelFastLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.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(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(btnFindOther, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(0, 0, 0))
panelFastLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelFastLayout.createSequentialGroup()
.addGap(0, 0, 0)
.addGroup(panelFastLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.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(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(btnFindOther, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(0, 0, 0))
);
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);
panelServer.setLayout(panelServerLayout);
panelServerLayout.setHorizontalGroup(
panelServerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelServerLayout.createSequentialGroup()
.addComponent(txtServer, javax.swing.GroupLayout.PREFERRED_SIZE, 212, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblPort)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCheckStatus, javax.swing.GroupLayout.DEFAULT_SIZE, 205, Short.MAX_VALUE)
.addGap(0, 0, 0))
panelServerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelServerLayout.createSequentialGroup()
.addComponent(txtServer, javax.swing.GroupLayout.PREFERRED_SIZE, 212, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblPort)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCheckStatus, javax.swing.GroupLayout.DEFAULT_SIZE, 205, Short.MAX_VALUE)
.addGap(0, 0, 0))
);
panelServerLayout.setVerticalGroup(
panelServerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelServerLayout.createSequentialGroup()
.addGap(0, 0, 0)
.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(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblPort)
.addComponent(btnCheckStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
panelServerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelServerLayout.createSequentialGroup()
.addGap(0, 0, 0)
.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(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblPort)
.addComponent(btnCheckStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
);
btnWhatsNew.setText("Show what's new");
@ -394,92 +394,92 @@ public class ConnectDialog extends MageDialog {
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.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(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(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))
.addGap(18, 18, 18)
.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(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(txtUserName)
.addComponent(panelFlag, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(btnConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.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))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.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(panelServer, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(jProxySettingsButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnWhatsNew)
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addComponent(txtPassword)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel1)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(filler2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.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(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(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))
.addGap(18, 18, 18)
.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(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(txtUserName)
.addComponent(panelFlag, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(btnConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.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))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.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(panelServer, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(jProxySettingsButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnWhatsNew)
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addComponent(txtPassword)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel1)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(filler2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.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))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.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))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.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(lblUserName, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(txtPassword)
.addComponent(jLabel1))
.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))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.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))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(chkAutoConnect)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(chkForceUpdateDB)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.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))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(lblStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addGroup(layout.createSequentialGroup()
.addComponent(btnRegister, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.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(btnCancel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(23, 23, 23))
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.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))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.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))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.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(lblUserName, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(txtPassword)
.addComponent(jLabel1))
.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))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.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))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(chkAutoConnect)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(chkForceUpdateDB)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.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))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(lblStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addGroup(layout.createSequentialGroup()
.addComponent(btnRegister, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.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(btnCancel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(23, 23, 23))
);
lblFastConnect.getAccessibleContext().setAccessibleName("Fast connect to:");
@ -765,7 +765,7 @@ public class ConnectDialog extends MageDialog {
}//GEN-LAST:event_btnFind2findPublicServerActionPerformed
private void connectXmageus(java.awt.event.ActionEvent evt) {
String serverAddress = "mtg.powersofwar.com";
String serverAddress = "us.xmage.today";
this.txtServer.setText(serverAddress);
this.txtPort.setText("17171");
// 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) {
String serverAddress = "xmage.today";
String serverAddress = "beta.xmage.today";
this.txtServer.setText(serverAddress);
this.txtPort.setText("17171");
// Update userName and password according to the chosen server.

View file

@ -359,7 +359,7 @@
<Component class="javax.swing.JLabel" name="lbTimeLimit">
<Properties>
<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>
</Component>
<Component class="javax.swing.JComboBox" name="cbTimeLimit">

View file

@ -187,7 +187,7 @@ public class NewTableDialog extends MageDialog {
lbDeckType.setText("Deck Type:");
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:");
@ -637,6 +637,7 @@ public class NewTableDialog extends MageDialog {
case "Variant Magic - Commander":
case "Variant Magic - Duel Commander":
case "Variant Magic - MTGO 1v1 Commander":
case "Variant Magic - Centurion Commander":
case "Variant Magic - Penny Dreadful Commander":
if (!options.getGameType().startsWith("Commander")) {
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;
}
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
@ -677,6 +684,7 @@ public class NewTableDialog extends MageDialog {
if (!options.getDeckType().equals("Variant Magic - Commander")
&& !options.getDeckType().equals("Variant Magic - Duel 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 - Penny Dreadful Commander")) {
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;
}
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;
}

View file

@ -362,7 +362,7 @@
<Component class="javax.swing.JLabel" name="lbTimeLimit">
<Properties>
<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>
<BindingProperties>
<BindingProperty name="labelFor" source="cbTimeLimit" target="lbTimeLimit" targetPath="labelFor" updateStrategy="0" immediately="false"/>
@ -370,13 +370,13 @@
</Component>
<Component class="javax.swing.JComboBox" name="cbTimeLimit">
<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>
</Component>
<Component class="javax.swing.JLabel" name="lbSkillLevel">
<Properties>
<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>
</Component>
<Component class="javax.swing.JComboBox" name="cbSkillLevel">

View file

@ -1,5 +1,10 @@
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.DeckFileFilter;
import mage.cards.decks.importer.DeckImporter;
@ -26,13 +31,6 @@ import mage.view.TableView;
import mage.view.TournamentTypeView;
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
*/
@ -41,13 +39,13 @@ public class NewTournamentDialog extends MageDialog {
private static final Logger logger = Logger.getLogger(NewTournamentDialog.class);
private TableView table;
private UUID playerId;
// private UUID playerId;
private UUID roomId;
private String lastSessionId;
private RandomPacksSelectorDialog randomPackSelector;
private JTextArea txtRandomPacks;
private final List<TournamentPlayerPanel> players = new ArrayList<>();
private final List<JPanel> packPanels = new ArrayList<>();
private final java.util.List<TournamentPlayerPanel> players = 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_MAX = 30;
private boolean isRandom = false;
@ -231,15 +229,15 @@ public class NewTournamentDialog extends MageDialog {
lblName.setText("Name:");
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"));
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.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.");
@ -709,12 +707,12 @@ public class NewTournamentDialog extends MageDialog {
private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed
this.table = null;
this.playerId = null;
// this.playerId = null;
this.hideDialog();
}//GEN-LAST:event_btnCancelActionPerformed
private void updateNumSeats() {
int numPlayers = (Integer) this.spnNumPlayers.getValue();
// int numPlayers = (Integer) this.spnNumPlayers.getValue();
int numSeats = (Integer) this.spnNumSeats.getValue();
if (numSeats > 2) {
@ -966,11 +964,6 @@ public class NewTournamentDialog extends MageDialog {
}
randomPackSelector.setSelectedPacks(packList);
txtRandomPacks.setText(packNames);
// workaround to apply field's auto-size
this.pack();
this.revalidate();
this.repaint();
}
private void createRandomPacks() {
@ -993,6 +986,7 @@ public class NewTournamentDialog extends MageDialog {
btnSelectRandomPacks.setToolTipText(RandomPacksSelectorDialog.randomDraftDescription);
btnSelectRandomPacks.addActionListener(evt -> showRandomPackSelectorDialog());
pnlRandomPacks.add(btnSelectRandomPacks);
this.pnlRandomPacks.setMinimumSize(new Dimension(784, 150));
}
txtRandomPacks.setText(txtRandomPacks.getText()); // workaround to apply field's auto-size
this.pack();
@ -1154,7 +1148,7 @@ public class NewTournamentDialog extends MageDialog {
int packNumber = 0;
for (String pack : packsArray) {
packNumber++;
if (this.packPanels.size() >= packNumber - 1) {
if (!packPanels.isEmpty() && this.packPanels.size() >= packNumber - 1) {
JPanel panel = packPanels.get(packNumber - 1);
JComboBox comboBox = findComboInComponent(panel);
@ -1466,4 +1460,4 @@ public class NewTournamentDialog extends MageDialog {
private org.jdesktop.beansbinding.BindingGroup bindingGroup;
// End of variables declaration//GEN-END:variables
}
}

View file

@ -36,12 +36,17 @@
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="pnlSelect" min="-2" pref="241" max="-2" attributes="0"/>
<EmptySpace pref="300" max="32767" attributes="0"/>
<Component id="pnlApply" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Component id="pnlPacks" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="pnlSelect" min="-2" pref="196" max="-2" attributes="0"/>
<EmptySpace pref="402" 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"/>
</Group>
</Group>
@ -49,11 +54,13 @@
<DimensionLayout dim="1">
<Group type="103" groupAlignment="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"/>
<Group type="103" groupAlignment="0" 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="btnApply" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
@ -64,8 +71,8 @@
<Container class="java.awt.Panel" name="pnlPacks">
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridLayout">
<Property name="columns" type="int" value="12"/>
<Property name="rows" type="int" value="11"/>
<Property name="columns" type="int" value="13"/>
<Property name="rows" type="int" value="12"/>
</Layout>
</Container>
<Container class="javax.swing.JPanel" name="pnlSelect">
@ -94,17 +101,15 @@
<Container class="javax.swing.JPanel" name="pnlApply">
<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>
<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>
</Form>

View file

@ -58,25 +58,25 @@ public class RandomPacksSelectorDialog extends javax.swing.JDialog {
this.setModal(true);
}
public void setSelectedPacks(ArrayList<String> packs){
if (!boxesCreated){
createCheckboxes();
}
for (Component pack : pnlPacks.getComponents()) {
JCheckBox thePack = (JCheckBox) pack;
if (packs.contains(thePack.getText())) {
thePack.setSelected(true);
} else{
thePack.setSelected(false);
}
}
}
public void setSelectedPacks(ArrayList<String> packs) {
if (!boxesCreated) {
createCheckboxes();
}
for (Component pack : pnlPacks.getComponents()) {
JCheckBox thePack = (JCheckBox) pack;
if (packs.contains(thePack.getText())) {
thePack.setSelected(true);
} else {
thePack.setSelected(false);
}
}
}
public ArrayList<String> getSelectedPacks() {
ArrayList<String> returnVal = new ArrayList<>();
for (Component pack: pnlPacks.getComponents()){
for (Component pack : pnlPacks.getComponents()) {
JCheckBox thePack = (JCheckBox) pack;
if (thePack.isSelected()){
if (thePack.isSelected()) {
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.
* 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();
setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
setTitle(title);
setTitle("Random Booster Draft Packs Selector");
setModal(true);
setModalExclusionType(java.awt.Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
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));
btnNone.setText("Select 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);
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);
pnlApply.setLayout(new javax.swing.BoxLayout(pnlApply, javax.swing.BoxLayout.LINE_AXIS));
btnApply.setText("Apply");
if (isRandomDraft) {
btnApply.setToolTipText("At least 2 packs must be selected");
} else if (isRichManDraft) {
btnApply.setToolTipText("At least 1 pack must be selected");
}
btnApply.addActionListener(evt -> btnApplyActionPerformed(evt));
pnlApply.add(btnApply);
btnApply.setToolTipText("At least two packs must be selected");
btnApply.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnApplyActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(pnlSelect, javax.swing.GroupLayout.PREFERRED_SIZE, 241, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 300, Short.MAX_VALUE)
.addComponent(pnlApply, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addComponent(pnlPacks, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(pnlSelect, javax.swing.GroupLayout.PREFERRED_SIZE, 196, javax.swing.GroupLayout.PREFERRED_SIZE)
.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())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.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)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.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))
);
@ -198,7 +210,7 @@ public class RandomPacksSelectorDialog extends javax.swing.JDialog {
public void doApply() {
if (getSelectedPacks().size() < 2 && isRandomDraft) {
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);
} else {
this.setVisible(false);
@ -220,4 +232,4 @@ public class RandomPacksSelectorDialog extends javax.swing.JDialog {
private java.awt.Panel pnlPacks;
private javax.swing.JPanel pnlSelect;
// 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.match.MatchType;
import mage.game.mulligan.Mulligan;
import mage.game.mulligan.VancouverMulligan;
import mage.game.mulligan.MulliganType;
import mage.game.permanent.PermanentCard;
import mage.players.Player;
import mage.players.StubPlayer;
@ -113,7 +113,7 @@ public class TestCardRenderDialog extends MageDialog {
cardsPanel.cleanUp();
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);
Deck deck = new 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) {
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) {
this.handContainer.setVisible(false);
} else {
@ -622,14 +625,6 @@ public final class GamePanel extends javax.swing.JPanel {
}
if (playerId != null) {
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)
if (game.getOpponentHands() != null) {
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)) {
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) {
updateGame(gameView);
updateGame(gameView, false, options, null);
this.feedbackPanel.getFeedback(FeedbackMode.QUESTION, question, false, options, messageId, true, gameView.getPhase());
}
private void prepareSelectableView(GameView gameView, Map<String, Serializable> options, Set<UUID> targets) {
// make cards/perm selectable
// highlighting chosen
// code calls after each selects or updates, no needs in switch off cards
private void prepareSelectableView(GameView gameView, boolean showPlayable, Map<String, Serializable> options, Set<UUID> targets) {
// make cards/perm selectable/chooseable/playable
// playable must be used for ask dialog only (priority and mana pay)
Zone needZone = Zone.ALL;
if (options.containsKey("targetZone")) {
if (options != null && options.containsKey("targetZone")) {
needZone = (Zone) options.get("targetZone");
}
List<UUID> needChoosen = null;
if (options.containsKey("chosen")) {
List<UUID> needChoosen;
if (options != null && options.containsKey("chosen")) {
needChoosen = (List<UUID>) options.get("chosen");
}
if (needChoosen == null) {
} else {
needChoosen = new ArrayList<>();
}
@ -1212,7 +1205,14 @@ public final class GamePanel extends javax.swing.JPanel {
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;
}
@ -1225,6 +1225,10 @@ public final class GamePanel extends javax.swing.JPanel {
if (needChoosen.contains(card.getId())) {
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())) {
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())) {
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())) {
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())) {
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())) {
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) {
case PICK_ABILITY:
popupMenuType = PopUpMenuType.TRIGGER_ORDER;
prepareSelectableView(gameView, options, targets);
break;
case PICK_TARGET:
prepareSelectableView(gameView, options, targets);
break;
default:
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;
ShowCardsDialog dialog = null;
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"),
false);
updateGame(gameView, options);
updateGame(gameView, true, options, null);
boolean controllingPlayer = false;
for (PlayerView playerView : gameView.getPlayers()) {
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) {
updateGame(gameView);
updateGame(gameView, true, options, null);
DialogManager.getManager(gameId).fadeOut();
this.feedbackPanel.getFeedback(FeedbackMode.CANCEL, message, gameView.getSpecial(), options, messageId, true, gameView.getPhase());
}
public void playXMana(String message, GameView gameView, int messageId) {
updateGame(gameView);
updateGame(gameView, true, null, null);
DialogManager.getManager(gameId).fadeOut();
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);
}
if (buttons.size() == 0) {
if (buttons.isEmpty()) {
return;
}

View file

@ -1,42 +1,29 @@
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.client.MageFrame;
import mage.client.SessionHandler;
import mage.client.cards.BigCard;
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.constants.PlayerAction;
import mage.view.GameView;
import mage.view.PlayerView;
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
*/
public class PlayAreaPanel extends javax.swing.JPanel {
@ -77,7 +64,7 @@ public class PlayAreaPanel extends javax.swing.JPanel {
popupMenu = new JPopupMenu();
if (options.isPlayer) {
addPopupMenuPlayer(player.getUserData().isAllowRequestShowHandCards());
addPopupMenuPlayer(player.getUserData().isAllowRequestHandToAll());
} else {
addPopupMenuWatcher();
}
@ -85,7 +72,7 @@ public class PlayAreaPanel extends javax.swing.JPanel {
setGUISize();
init(player, bigCard, gameId, priorityTime);
update(player);
update(null, player, null);
}
public void CleanUp() {
@ -331,12 +318,12 @@ public class PlayAreaPanel extends javax.swing.JPanel {
// Request to see hand cards
menuItem.addActionListener(e -> SessionHandler.sendPlayerAction(PlayerAction.REQUEST_PERMISSION_TO_SEE_HAND_CARDS, gameId, playerId));
} 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.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);
// Requests allowed
// requests allowed (disable -> enable to reset requested list)
allowViewHandCardsMenuItem.addActionListener(e -> {
boolean requestsAllowed = ((JCheckBoxMenuItem) e.getSource()).getState();
PreferencesDialog.setPrefValue(KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS, requestsAllowed);
@ -451,13 +438,13 @@ public class PlayAreaPanel extends javax.swing.JPanel {
}
});
popupMenu.addSeparator();
menuItem = new JMenuItem("<html>View current deck");
menuItem.setMnemonic(KeyEvent.VK_V);
popupMenu.add(menuItem);
// View limited deck
menuItem.addActionListener(e -> {
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) {
this.playerPanel.update(player);
public final void update(GameView game, PlayerView player, Set<UUID> possibleTargets) {
this.playerPanel.update(game, player, possibleTargets);
this.battlefieldPanel.update(player.getBattlefield());
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);
layout.setHorizontalGroup(
layout.createSequentialGroup()
.addComponent(playerPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(battlefieldPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(playerPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(battlefieldPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(Alignment.LEADING)
.addComponent(playerPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(battlefieldPanel, GroupLayout.DEFAULT_SIZE, 160, Short.MAX_VALUE)
.addComponent(playerPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(battlefieldPanel, GroupLayout.DEFAULT_SIZE, 160, Short.MAX_VALUE)
);
this.setLayout(layout);
}

View file

@ -1,34 +1,5 @@
/*
* PlayerPanel.java
*
* Created on Nov 18, 2009, 3:01:31 PM
*/
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.client.MageFrame;
import mage.client.SessionHandler;
@ -44,26 +15,34 @@ import mage.client.util.gui.countryBox.CountryUtil;
import mage.components.ImagePanel;
import mage.components.ImagePanelStyle;
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.counters.Counter;
import mage.counters.CounterType;
import mage.designations.DesignationType;
import mage.utils.timer.PriorityTimer;
import mage.view.CardView;
import mage.view.ManaPoolView;
import mage.view.PlayerView;
import mage.view.*;
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.
*
* @author nantuko
* @author nantuko, JayDi85
*/
public class PlayerPanelExt extends javax.swing.JPanel {
// TODO: *.form file was lost, panel must be reworks in designer
private UUID playerId;
private UUID gameId;
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 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 String flagName;
private String basicTooltipText;
@ -140,15 +123,44 @@ public class PlayerPanelExt extends javax.swing.JPanel {
}
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));
if (amount != 0 || alwaysBlack) {
label.setForeground(Color.BLACK);
label.setForeground(fontColor);
label.setFont(fontValuesNonZero);
} else {
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;
int pastLife = player.getLife();
if (playerLives != null) {
@ -220,10 +232,26 @@ public class PlayerPanelExt extends javax.swing.JPanel {
graveLabel.setFont(font);
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()));
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();
Color excileColor = isCardsPlayable(player.getExile().values(), game, possibleTargets) ? activeValueColor : Color.BLACK;
if (exileCards > 99) {
if (!changedFontExile) {
Font font = exileLabel.getFont();
@ -237,21 +265,21 @@ public class PlayerPanelExt extends javax.swing.JPanel {
exileLabel.setFont(font);
changedFontExile = false;
}
setTextForLabel(exileLabel, exileCards, false);
setTextForLabel(exileLabel, exileCards, false, excileColor);
if (!MageFrame.isLite()) {
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;
}
if (id != avatarId) {
avatarId = id;
String path = "/avatars/" + String.valueOf(avatarId) + ".jpg";
String path = "/avatars/" + avatarId + ".jpg";
if (avatarId == 64) {
path = "/avatars/i64.jpg";
} else if (avatarId >= 1000) {
avatarId = avatarId - 1000;
path = "/avatars/special/" + String.valueOf(avatarId) + ".gif";
path = "/avatars/special/" + avatarId + ".gif";
}
Image image = ImageHelper.getImageFromResources(path);
Rectangle r = new Rectangle(80, 80);
@ -364,15 +392,41 @@ public class PlayerPanelExt extends javax.swing.JPanel {
}
protected void update(ManaPoolView pool) {
setTextForLabel(manaLabels.get("B"), pool.getBlack(), false);
setTextForLabel(manaLabels.get("R"), pool.getRed(), false);
setTextForLabel(manaLabels.get("W"), pool.getWhite(), false);
setTextForLabel(manaLabels.get("G"), pool.getGreen(), false);
setTextForLabel(manaLabels.get("U"), pool.getBlue(), false);
setTextForLabel(manaLabels.get("X"), pool.getColorless(), false);
for (Map.Entry<JLabel, ManaType> mana : manaLabels.entrySet()) {
switch (mana.getValue()) {
case BLACK:
setTextForLabel(mana.getKey(), pool.getBlack(), false, activeValueColor);
break;
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")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
panelBackground = new MageRoundPane();
@ -387,6 +441,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
energyLabel = new JLabel();
experienceLabel = new JLabel();
graveLabel = new JLabel();
commandLabel = new JLabel();
libraryLabel = new JLabel();
setOpaque(false);
@ -482,6 +537,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
cheat.addActionListener(e -> btnCheatActionPerformed(e));
zonesPanel = new JPanel();
//zonesPanel.setBorder(BorderFactory.createLineBorder(Color.red));
zonesPanel.setPreferredSize(new Dimension(100, 60));
zonesPanel.setSize(100, 60);
zonesPanel.setLayout(null);
@ -491,13 +547,17 @@ public class PlayerPanelExt extends javax.swing.JPanel {
r = new Rectangle(21, 21);
resized = ImageHelper.getResizedImage(BufferedImageBuilder.bufferImage(image, BufferedImage.TYPE_INT_ARGB), 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.setObserver(() -> btnCommandZoneActionPerformed(null));
commandZone.setBounds(5, 0, 21, 21);
commandZone.setBounds(3, 0, 21, 21);
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);
energyExperiencePanel = new JPanel();
@ -533,72 +593,99 @@ public class PlayerPanelExt extends javax.swing.JPanel {
btnPlayer.addActionListener(e -> SessionHandler.sendPlayerUUID(gameId, playerId));
// 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();
manaCountLabelW.setToolTipText("White mana");
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);
BufferedImage imageManaW = ManaSymbols.getSizedManaSymbol("W", 15);
HoverButton btnWhiteMana = new HoverButton(null, imageManaW, imageManaW, imageManaW, r);
btnWhiteMana.setToolTipText("White mana");
btnWhiteMana.setOpaque(false);
btnWhiteMana.setObserver(() -> btnManaActionPerformed(ManaType.WHITE));
manaButtons.put(manaCountLabelW, btnWhiteMana);
//*/
JLabel manaCountLabelU = new JLabel();
manaCountLabelU.setToolTipText("Blue mana");
setTextForLabel(manaCountLabelU, 0, false);
manaLabels.put("U", manaCountLabelU);
manaLabels.put(manaCountLabelU, ManaType.BLUE);
r = new Rectangle(15, 15);
BufferedImage imageManaU = ManaSymbols.getSizedManaSymbol("U", 15);
HoverButton btnBlueMana = new HoverButton(null, imageManaU, imageManaU, imageManaU, r);
btnBlueMana.setToolTipText("Blue mana");
btnBlueMana.setOpaque(false);
btnBlueMana.setObserver(() -> btnManaActionPerformed(ManaType.BLUE));
manaButtons.put(manaCountLabelU, btnBlueMana);
JLabel manaCountLabelB = new JLabel();
manaCountLabelB.setToolTipText("Black mana");
setTextForLabel(manaCountLabelB, 0, false);
manaLabels.put("B", manaCountLabelB);
manaLabels.put(manaCountLabelB, ManaType.BLACK);
r = new Rectangle(15, 15);
BufferedImage imageManaB = ManaSymbols.getSizedManaSymbol("B", 15);
HoverButton btnBlackMana = new HoverButton(null, imageManaB, imageManaB, imageManaB, r);
btnBlackMana.setToolTipText("Black mana");
btnBlackMana.setOpaque(false);
btnBlackMana.setObserver(() -> btnManaActionPerformed(ManaType.BLACK));
manaButtons.put(manaCountLabelB, btnBlackMana);
JLabel manaCountLabelR = new JLabel();
manaCountLabelR.setToolTipText("Red mana");
setTextForLabel(manaCountLabelR, 0, false);
manaLabels.put("R", manaCountLabelR);
manaLabels.put(manaCountLabelR, ManaType.RED);
r = new Rectangle(15, 15);
BufferedImage imageManaR = ManaSymbols.getSizedManaSymbol("R", 15);
HoverButton btnRedMana = new HoverButton(null, imageManaR, imageManaR, imageManaR, r);
btnRedMana.setToolTipText("Red mana");
btnRedMana.setOpaque(false);
btnRedMana.setObserver(() -> btnManaActionPerformed(ManaType.RED));
manaButtons.put(manaCountLabelR, btnRedMana);
JLabel manaCountLabelG = new JLabel();
manaCountLabelG.setToolTipText("Green mana");
setTextForLabel(manaCountLabelG, 0, false);
manaLabels.put("G", manaCountLabelG);
manaLabels.put(manaCountLabelG, ManaType.GREEN);
r = new Rectangle(15, 15);
BufferedImage imageManaG = ManaSymbols.getSizedManaSymbol("G", 15);
HoverButton btnGreenMana = new HoverButton(null, imageManaG, imageManaG, imageManaG, r);
btnGreenMana.setToolTipText("Green mana");
btnGreenMana.setOpaque(false);
btnGreenMana.setObserver(() -> btnManaActionPerformed(ManaType.GREEN));
manaButtons.put(manaCountLabelG, btnGreenMana);
JLabel manaCountLabelX = new JLabel();
manaCountLabelX.setToolTipText("Colorless mana");
setTextForLabel(manaCountLabelX, 0, false);
manaLabels.put("X", manaCountLabelX);
manaLabels.put(manaCountLabelX, ManaType.COLORLESS);
r = new Rectangle(15, 15);
BufferedImage imageManaX = ManaSymbols.getSizedManaSymbol("C", 15);
HoverButton btnColorlessMana = new HoverButton(null, imageManaX, imageManaX, imageManaX, r);
btnColorlessMana.setToolTipText("Colorless mana");
btnColorlessMana.setOpaque(false);
btnColorlessMana.setObserver(() -> btnManaActionPerformed(ManaType.COLORLESS));
manaButtons.put(manaCountLabelX, btnColorlessMana);
GroupLayout gl_panelBackground = new GroupLayout(panelBackground);
gl_panelBackground.setHorizontalGroup(
@ -674,9 +761,6 @@ public class PlayerPanelExt extends javax.swing.JPanel {
.addGroup(gl_panelBackground.createSequentialGroup()
.addGap(40)
.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()
.addGap(18)
.addComponent(exileZone, GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE)
@ -776,9 +860,6 @@ public class PlayerPanelExt extends javax.swing.JPanel {
.addGap(31)
.addComponent(manaCountLabelG, GroupLayout.PREFERRED_SIZE, 30, 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()
.addGap(76)
.addComponent(exileZone, GroupLayout.PREFERRED_SIZE, 21, GroupLayout.PREFERRED_SIZE)
@ -812,7 +893,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
);
setLayout(groupLayout);
}
}// </editor-fold>//GEN-END:initComponents
protected void sizePlayerPanel(boolean smallMode) {
if (smallMode) {
@ -850,7 +931,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
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();
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 JButton btnPlayer;
private ImagePanel life;
@ -895,16 +977,20 @@ public class PlayerPanelExt extends javax.swing.JPanel {
private JLabel energyLabel;
private JLabel experienceLabel;
private JLabel graveLabel;
private JLabel commandLabel;
private JLabel exileLabel;
private boolean changedFontLibrary;
private boolean changedFontLife;
private boolean changedFontGrave;
private boolean changedFontExile;
private JPanel zonesPanel;
private JPanel energyExperiencePanel;
private HoverButton exileZone;
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) {
appendJsonEvent("GAME_UPDATE", callback.getObjectId(), callback.getData());
panel.updateGame((GameView) callback.getData());
panel.updateGame((GameView) callback.getData(), true, null, null); // update after undo
}
break;
}

View file

@ -47,7 +47,7 @@
<Component id="btnQuickStartDuel" min="-2" max="-2" attributes="0"/>
<Component id="btnQuickStartCommander" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="734" max="32767" attributes="0"/>
<EmptySpace pref="667" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -290,7 +290,7 @@
<Property name="verticalTextPosition" type="int" value="3"/>
</Properties>
<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>
</Component>
<Component class="javax.swing.JToggleButton" name="btnUnrated">
@ -307,7 +307,7 @@
<Property name="verticalTextPosition" type="int" value="3"/>
</Properties>
<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>
</Component>
</SubComponents>
@ -366,6 +366,20 @@
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFilterActionPerformed"/>
</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 class="javax.swing.JToggleButton" name="btnFormatLegacy">
<Properties>
@ -396,7 +410,7 @@
<Property name="verticalTextPosition" type="int" value="3"/>
</Properties>
<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>
</Component>
<Component class="javax.swing.JToggleButton" name="btnFormatPremodern">
@ -412,7 +426,7 @@
<Property name="verticalTextPosition" type="int" value="3"/>
</Properties>
<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>
</Component>
<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"/>
</Events>
</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">
<Properties>
<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().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,
btnTypeMatch, btnTypeTourneyConstructed, btnTypeTourneyLimited,
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};
for (JComponent component : components) {
@ -802,6 +802,9 @@ public class TablesPanel extends javax.swing.JPanel {
if (btnFormatModern.isSelected()) {
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()) {
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));
}
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()) {
formatFilterList.add(RowFilter.regexFilter("^Tiny", TablesTableModel.COLUMN_DECK_TYPE));
}
if (btnFormatOathbreaker.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Oathbreaker", TablesTableModel.COLUMN_DECK_TYPE));
}
if (btnFormatLimited.isSelected()) {
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();
btnFormatStandard = new javax.swing.JToggleButton();
btnFormatModern = new javax.swing.JToggleButton();
btnFormatPioneer = new javax.swing.JToggleButton();
btnFormatLegacy = new javax.swing.JToggleButton();
btnFormatVintage = new javax.swing.JToggleButton();
btnFormatPremodern = new javax.swing.JToggleButton();
jSeparator3 = new javax.swing.JToolBar.Separator();
btnFormatCommander = new javax.swing.JToggleButton();
btnFormatOathbreaker = new javax.swing.JToggleButton();
btnFormatTinyLeader = new javax.swing.JToggleButton();
jSeparator2 = new javax.swing.JToolBar.Separator();
btnFormatLimited = new javax.swing.JToggleButton();
@ -1180,7 +1188,7 @@ public class TablesPanel extends javax.swing.JPanel {
btnRated.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
btnRated.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnRatedbtnFilterActionPerformed(evt);
btnFilterActionPerformed(evt);
}
});
filterBar1.add(btnRated);
@ -1197,7 +1205,7 @@ public class TablesPanel extends javax.swing.JPanel {
btnUnrated.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
btnUnrated.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnUnratedbtnFilterActionPerformed(evt);
btnFilterActionPerformed(evt);
}
});
filterBar1.add(btnUnrated);
@ -1252,6 +1260,20 @@ public class TablesPanel extends javax.swing.JPanel {
});
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.setText("Legacy");
btnFormatLegacy.setToolTipText("Legacy format.");
@ -1279,7 +1301,7 @@ public class TablesPanel extends javax.swing.JPanel {
btnFormatVintage.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
btnFormatVintage.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnFormatVintageActionPerformed(evt);
btnFilterActionPerformed(evt);
}
});
filterBar2.add(btnFormatVintage);
@ -1295,7 +1317,7 @@ public class TablesPanel extends javax.swing.JPanel {
btnFormatPremodern.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
btnFormatPremodern.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnFormatPremodernActionPerformed(evt);
btnFilterActionPerformed(evt);
}
});
filterBar2.add(btnFormatPremodern);
@ -1317,6 +1339,22 @@ public class TablesPanel extends javax.swing.JPanel {
});
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.setText("Tiny Leader");
btnFormatTinyLeader.setToolTipText("Tiny Leader format.");
@ -1432,7 +1470,7 @@ public class TablesPanel extends javax.swing.JPanel {
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(btnQuickStartDuel)
.addComponent(btnQuickStartCommander))
.addContainerGap(734, Short.MAX_VALUE))
.addContainerGap(667, Short.MAX_VALUE))
);
jPanelTopLayout.setVerticalGroup(
jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -1631,22 +1669,6 @@ public class TablesPanel extends javax.swing.JPanel {
this.startUpdateTasks(true);
}//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
MageFrame.getInstance().showWhatsNewDialog(true);
}//GEN-LAST:event_buttonWhatsNewActionPerformed
@ -1666,6 +1688,8 @@ public class TablesPanel extends javax.swing.JPanel {
private javax.swing.JToggleButton btnFormatLegacy;
private javax.swing.JToggleButton btnFormatLimited;
private javax.swing.JToggleButton btnFormatModern;
private javax.swing.JToggleButton btnFormatPioneer;
private javax.swing.JToggleButton btnFormatOathbreaker;
private javax.swing.JToggleButton btnFormatOther;
private javax.swing.JToggleButton btnFormatPremodern;
private javax.swing.JToggleButton btnFormatStandard;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -20,6 +20,7 @@ public final class ConstructedFormats {
public static final String STANDARD = "- Standard";
public static final String EXTENDED = "- Extended";
public static final String FRONTIER = "- Frontier";
public static final String PIONEER = "- Pioneer";
public static final String MODERN = "- Modern";
public static final String VINTAGE_LEGACY = "- Vintage / Legacy";
public static final String JOKE = "- Joke Sets";
@ -27,9 +28,10 @@ public final class ConstructedFormats {
public static final Standard STANDARD_CARDS = new Standard();
// 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 frontierDate = new GregorianCalendar(2014, 6, 17).getTime();
private static final Date modernDate = new GregorianCalendar(2003, 6, 20).getTime();
private static final Date extendedDate = new GregorianCalendar(2009, Calendar.AUGUST, 20).getTime();
private static final Date frontierDate = new GregorianCalendar(2014, Calendar.JULY, 17).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
private static final List<String> all = new ArrayList<>();
@ -82,6 +84,7 @@ public final class ConstructedFormats {
underlyingSetCodesPerFormat.put(STANDARD, new ArrayList<>());
underlyingSetCodesPerFormat.put(EXTENDED, new ArrayList<>());
underlyingSetCodesPerFormat.put(FRONTIER, new ArrayList<>());
underlyingSetCodesPerFormat.put(PIONEER, new ArrayList<>());
underlyingSetCodesPerFormat.put(MODERN, new ArrayList<>());
underlyingSetCodesPerFormat.put(VINTAGE_LEGACY, new ArrayList<>());
underlyingSetCodesPerFormat.put(JOKE, new ArrayList<>());
@ -134,6 +137,11 @@ public final class ConstructedFormats {
underlyingSetCodesPerFormat.get(FRONTIER).add(set.getCode());
}
// frontier
if (set.getType().isStandardLegal() && set.getReleaseDate().after(pioneerDate)) {
underlyingSetCodesPerFormat.get(PIONEER).add(set.getCode());
}
// modern
if (set.getType().isModernLegal() && set.getReleaseDate().after(modernDate)) {
underlyingSetCodesPerFormat.get(MODERN).add(set.getCode());
@ -251,6 +259,7 @@ public final class ConstructedFormats {
formats.add(0, JOKE);
formats.add(0, VINTAGE_LEGACY);
formats.add(0, MODERN);
formats.add(0, PIONEER);
formats.add(0, FRONTIER);
formats.add(0, EXTENDED);
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;
import org.apache.log4j.Logger;
import org.mage.plugins.card.dl.DownloadServiceInfo;
import org.mage.plugins.card.images.CardDownloadData;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
/**
* @author spjspj
@ -57,6 +59,11 @@ public enum AltMtgOnlTokensImageSource implements CardImageSource {
return null;
}
@Override
public boolean prepareDownloadList(DownloadServiceInfo downloadServiceInfo, List<CardDownloadData> downloadList) {
return true;
}
@Override
public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception {
return null;

View file

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

View file

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

View file

@ -6,12 +6,14 @@ import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import mage.cards.ExpansionSet;
import mage.cards.Sets;
import mage.client.constants.Constants;
import mage.constants.Rarity;
import org.apache.log4j.Logger;
import org.mage.plugins.card.dl.DownloadJob;
import static org.mage.plugins.card.dl.DownloadJob.fromURL;
import static org.mage.plugins.card.dl.DownloadJob.toFile;
import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir;
@ -27,12 +29,12 @@ public class GathererSets implements Iterable<DownloadJob> {
boolean haveRare;
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;
set = ASet;
haveCommon = AHaveCommon;
haveUncommon = AHaveUncommon;
haveRare = AHhaveRare;
haveRare = AHaveRare;
haveMyth = AHaveMyth;
}
}
@ -43,63 +45,69 @@ public class GathererSets implements Iterable<DownloadJob> {
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",
"HOP",
"ARN", "ATQ", "LEG", "DRK", "FEM", "HML",
"ICE", "ALL", "CSP",
"MIR", "VIS", "WTH",
"TMP", "STH", "EXO",
"USG", "ULG", "UDS",
"MMQ", "NEM", "PCY",
"INV", "PLS", "APC",
"ODY", "TOR", "JUD",
"ONS", "LGN", "SCG",
"MRD", "DST", "5DN",
"CHK", "BOK", "SOK",
"RAV", "GPT", "DIS",
"TSP", "TSB", "PLC", "FUT",
"LRW", "MOR",
"SHM", "EVE",
"MED", "ME2", "ME3", "ME4",
"POR", "P02", "PTK",
"ARC", "DD3EVG",
"W16", "W17",
//"APAC" -- gatherer do not have that set, scryfall has PALP
//"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
"H09", "PD2", "PD3", "UNH", "CM1", "V11", "A25", "UST", "IMA", "DD2", "EVG", "DDC", "DDE", "DDD", "8EB", "9EB", "CHR" // ok
// current testing
"HOP",
"ARN", "ATQ", "LEG", "DRK", "FEM", "HML",
"ICE", "ALL", "CSP",
"MIR", "VIS", "WTH",
"TMP", "STH", "EXO",
"USG", "ULG", "UDS",
"MMQ", "NEM", "PCY",
"INV", "PLS", "APC",
"ODY", "TOR", "JUD",
"ONS", "LGN", "SCG",
"MRD", "DST", "5DN",
"CHK", "BOK", "SOK",
"RAV", "GPT", "DIS",
"TSP", "TSB", "PLC", "FUT",
"LRW", "MOR",
"SHM", "EVE",
"MED", "ME2", "ME3", "ME4",
"POR", "P02", "PTK",
"ARC", "DD3EVG",
"W16", "W17",
// "APAC" -- gatherer do not have that set, scryfall has PALP
// "ARENA" -- is't many set with different codes, not one
// "ATH" -- has cards from many sets, symbol does not exist on gatherer
// "CLASH", "CP", "DPA", "EURO", "FNMP", "GPX", "GRC", "GUR", "H17", "JR", "MBP", "MGDC", "MLP", "MPRP", "PTC", "SUS", "SWS", "WMCQ", // need to fix
"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",
"DDF", "DDG", "DDH", "DDI", "DDJ", "DDK", "DDL", "DDM", "DDN",
"DD3DVD", "DD3JVC", "DDO", "DDP", "DDQ", "DDR", "DDS", "DDT", "DDU",
"ALA", "CON", "ARB",
"ZEN", "WWK", "ROE",
"SOM", "MBS", "NPH",
"CMD", "C13", "C14", "C15", "C16", "CMA",
"PC2", "PCA",
"ISD", "DKA", "AVR",
"RTR", "GTC", "DGM",
"MMA", "MM2", "EMA", "MM3",
"THS", "BNG", "JOU",
"CNS", "CN2",
"VMA", "TPR",
"KTK", "FRF", "DTK",
"BFZ", "OGW",
"SOI", "EMN",
"KLD", "AER",
"AKH", "HOU",
"XLN", "C17",
"RIX", "DOM", "M19",
"E01", "CM2", "E02",
"GS1", "BBD", "C18"
"DDF", "DDG", "DDH", "DDI", "DDJ", "DDK", "DDL", "DDM", "DDN",
"DD3DVD", "DD3JVC", "DDO", "DDP", "DDQ", "DDR", "DDS", "DDT", "DDU",
"ALA", "CON", "ARB",
"ZEN", "WWK", "ROE",
"SOM", "MBS", "NPH",
"CMD", "C13", "C14", "C15", "C16", "CMA",
"PC2", "PCA",
"ISD", "DKA", "AVR",
"RTR", "GTC", "DGM",
"MMA", "MM2", "EMA", "MM3",
"THS", "BNG", "JOU",
"CNS", "CN2",
"VMA", "TPR",
"KTK", "FRF", "UGIN", "DTK",
"BFZ", "OGW",
"SOI", "EMN",
"KLD", "AER",
"AKH", "HOU",
"XLN", "C17",
"RIX", "DOM", "M19",
"E01", "CM2", "E02",
"GS1", "BBD", "C18",
"GNT", "UMA", "GRN",
"RNA", "WAR", "MH1",
"M20"
// "HHO", "ANA" -- do not exist on gatherer
};
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 = {
"MPS"
"MPS", "MPS-AKH"
};
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("ATQ", "AQ");
codeReplacements.put("CMA", "CM1");
codeReplacements.put("CHR", "CH");
codeReplacements.put("DD3DVD", "DD3_DVD");
codeReplacements.put("DD3EVG", "DD3_EVG");
codeReplacements.put("DD3GVL", "DD3_GVL");
codeReplacements.put("DD3JVC", "DD3_JVC");
codeReplacements.put("DRK", "DK");
codeReplacements.put("EXO", "EX");
@ -128,7 +138,9 @@ public class GathererSets implements Iterable<DownloadJob> {
codeReplacements.put("LEA", "1E");
codeReplacements.put("LEB", "2E");
codeReplacements.put("LEG", "LE");
codeReplacements.put("MEDM", "MPS_WAR");
codeReplacements.put("MPS", "MPS_KLD");
codeReplacements.put("MPS-AKH", "MPS_AKH");
codeReplacements.put("MIR", "MI");
codeReplacements.put("MMQ", "MM");
codeReplacements.put("NEM", "NE");
@ -138,16 +150,19 @@ public class GathererSets implements Iterable<DownloadJob> {
codeReplacements.put("POR", "PO");
codeReplacements.put("P02", "P2");
codeReplacements.put("PTK", "PK");
codeReplacements.put("S00", "P4");
codeReplacements.put("S99", "P3");
codeReplacements.put("STH", "ST");
codeReplacements.put("TMP", "TE");
codeReplacements.put("UDS", "CG");
codeReplacements.put("UGIN", "FRF_UGIN");
codeReplacements.put("UGL", "UG");
codeReplacements.put("ULG", "GU");
codeReplacements.put("USG", "UZ");
codeReplacements.put("VIS", "VI");
codeReplacements.put("WTH", "WL");
codeReplacements.put("8EB", "8ED"); // inner xmage set for 8th edition
codeReplacements.put("9EB", "8ED"); // inner xmage set for 9th edition
codeReplacements.put("CHR", "CH");
}
public GathererSets() {
@ -172,7 +187,7 @@ public class GathererSets implements Iterable<DownloadJob> {
}
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
CheckResult res = setsToDownload.get(searchCode);
@ -223,16 +238,16 @@ public class GathererSets implements Iterable<DownloadJob> {
// 2. missing rarity icon:
// 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()));
}
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()));
}
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()));
}
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()));
}
//*/
@ -332,7 +347,7 @@ public class GathererSets implements Iterable<DownloadJob> {
if (codeReplacements.containsKey(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));
}
}

View file

@ -23,11 +23,11 @@ import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir;
*/
public class GathererSymbols implements Iterable<DownloadJob> {
//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 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"};

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,12 +1,24 @@
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 org.apache.log4j.Logger;
import org.mage.plugins.card.dl.DownloadServiceInfo;
import org.mage.plugins.card.images.CardDownloadData;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.Proxy;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.*;
/**
* @author JayDi85
@ -15,8 +27,11 @@ public enum ScryfallImageSource implements CardImageSource {
instance;
private static final Logger logger = Logger.getLogger(ScryfallImageSource.class);
private final Map<CardLanguage, String> languageAliases;
private CardLanguage currentLanguage = CardLanguage.ENGLISH; // working language
private Map<CardDownloadData, String> preparedUrls = new HashMap<>();
ScryfallImageSource() {
// LANGUAGES
@ -36,6 +51,11 @@ public enum ScryfallImageSource implements CardImageSource {
}
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 localizedCode = languageAliases.getOrDefault(this.getCurrentLanguage(), defaultCode);
// loc example: https://api.scryfall.com/cards/xln/121/ru?format=image
@ -62,29 +82,40 @@ public enum ScryfallImageSource implements CardImageSource {
alternativeUrl = null;
}
// special card number like "103a" and "U123" already compatible
if (baseUrl == null && card.isCollectorIdWithStr()) {
// WARNING, after 2018 it's not compatible and some new sets have GUID files instead card numbers
// TODO: replace card number links to API calls (need test with lands, alternative images and double faces), replace not working images by direct links
// art variation cards
// ARN and POR use notation
// PLS uses notation
if (baseUrl == null && card.getUsesVariousArt() && card.getSet().matches("ARN|POR|PLS")) {
String scryfallCollectorId = card.getCollectorIdAsInt().toString();
if (card.getCollectorId().startsWith("U") || card.getCollectorIdAsInt() == -1) {
// fix for Ultimate Box Topper (PUMA) and Mythic Edition (MED) -- need to use API
// ignored and go to API call at the end
} else {
baseUrl = "https://img.scryfall.com/cards/large/" + localizedCode + "/" + formatSetName(card.getSet(), isToken) + "/"
+ card.getCollectorId() + ".jpg";
alternativeUrl = "https://img.scryfall.com/cards/large/" + defaultCode + "/" + formatSetName(card.getSet(), isToken) + "/"
+ card.getCollectorId() + ".jpg";
if (card.getCollectorId().endsWith("b")) {
if (card.getSet().matches("ARN|POR")) {
scryfallCollectorId += "";
} else if (card.getSet().matches("PLS")) {
scryfallCollectorId += "";
}
}
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)
// example: https://img.scryfall.com/cards/large/en/xln/173b.jpg
if (baseUrl == null && card.isTwoFacedCard()) {
baseUrl = "https://img.scryfall.com/cards/large/" + localizedCode + "/" + formatSetName(card.getSet(), isToken) + "/"
+ card.getCollectorId() + (card.isSecondSide() ? "b" : "a") + ".jpg";
alternativeUrl = "https://img.scryfall.com/cards/large/" + defaultCode + "/" + formatSetName(card.getSet(), isToken) + "/"
+ card.getCollectorId() + (card.isSecondSide() ? "b" : "a") + ".jpg";
// double faced card
// the front face can be downloaded normally
// the back face is prepared beforehand
if (baseUrl == null && card.isTwoFacedCard() && !card.isSecondSide()) {
baseUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet(), isToken) + "/"
+ card.getCollectorIdAsInt() + "/" + localizedCode + "?format=image";
alternativeUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet(), isToken) + "/"
+ card.getCollectorIdAsInt() + "/" + defaultCode + "?format=image";
}
// basic cards by api call (redirect to img link)
@ -99,6 +130,120 @@ public enum ScryfallImageSource implements CardImageSource {
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
public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception {
return innerGenerateURL(card, false);

View file

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

View file

@ -2,6 +2,7 @@ package org.mage.plugins.card.dl.sources;
import mage.constants.SubType;
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.DownloadPicturesService;
import org.mage.plugins.card.utils.CardImageUtils;
@ -50,6 +51,11 @@ public enum TokensMtgImageSource implements CardImageSource {
return null;
}
@Override
public boolean prepareDownloadList(DownloadServiceInfo downloadServiceInfo, List<CardDownloadData> downloadList) {
return true;
}
@Override
public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception {
return null;
@ -180,7 +186,7 @@ public enum TokensMtgImageSource implements CardImageSource {
private HashMap<String, List<TokenData>> getTokensData() throws IOException {
synchronized (tokensDataSync) {
if (tokensData == null) {
DownloadPicturesService.getInstance().updateAndViewMessage("Find tokens data...");
DownloadPicturesService.getInstance().updateMessage("Find tokens data...");
tokensData = new HashMap<>();
// 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) {
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.Element;
import org.jsoup.select.Elements;
import org.mage.plugins.card.dl.DownloadServiceInfo;
import org.mage.plugins.card.images.CardDownloadData;
import org.mage.plugins.card.utils.CardImageUtils;
@ -451,6 +452,11 @@ public enum WizardCardsImageSource implements CardImageSource {
return null;
}
@Override
public boolean prepareDownloadList(DownloadServiceInfo downloadServiceInfo, List<CardDownloadData> downloadList) {
return true;
}
@Override
public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception {
String collectorId = card.getCollectorId();
@ -495,8 +501,8 @@ public enum WizardCardsImageSource implements CardImageSource {
}
}
}
if (link != null && !link.startsWith("http://")) {
link = "http://gatherer.wizards.com" + link;
if (link != null && !link.startsWith("https://")) {
link = "https://gatherer.wizards.com" + link;
}
if (link != null) {
@ -522,7 +528,7 @@ public enum WizardCardsImageSource implements CardImageSource {
int firstMultiverseIdLastPage = 0;
Pages:
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);
Document doc = CardImageUtils.downloadHtmlDocument(searchUrl);
Elements cardsImages = doc.select("img[src^=../../Handlers/]");
@ -582,7 +588,7 @@ public enum WizardCardsImageSource implements CardImageSource {
criteria.setCodes(cardSet);
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);
Elements variations = landDoc.select("a.variationlink");
if (!variations.isEmpty()) {
@ -629,7 +635,7 @@ public enum WizardCardsImageSource implements CardImageSource {
}
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);
Elements languageTableRows = cardLanguagesDoc.select("tr.cardItem");
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.kernel.spec.FsSyncException;
import org.apache.log4j.Logger;
import org.mage.plugins.card.dl.DownloadServiceInfo;
import org.mage.plugins.card.dl.sources.*;
import org.mage.plugins.card.utils.CardImageUtils;
@ -37,7 +38,7 @@ import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir;
/**
* @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)
private static DownloadPicturesService instance;
@ -65,7 +66,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
private static CardImageSource selectedSource;
private final Object sync = new Object();
private Proxy p = Proxy.NO_PROXY;
private Proxy proxy = Proxy.NO_PROXY;
enum DownloadSources {
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);
}
private boolean getNeedCancel() {
public boolean isNeedCancel() {
return this.needCancel || (this.errorCount > MAX_ERRORS_COUNT_BEFORE_CANCEL);
}
@ -126,8 +127,12 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
this.needCancel = needCancel;
}
private void incErrorCount() {
public void incErrorCount() {
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() {
@ -196,23 +201,24 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
}
public void findMissingCards() {
updateAndViewMessage("Loading...");
updateMessage("Loading...");
this.cardsAll.clear();
this.cardsMissing.clear();
this.cardsDownloadQueue.clear();
updateAndViewMessage("Loading cards list...");
updateMessage("Loading cards list...");
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());
updateAndViewMessage("Finding available sets from selected source...");
updateMessage("Finding available sets from selected source...");
this.uiDialog.getSetsCombo().setModel(new DefaultComboBoxModel<>(getSetsForCurrentImageSource()));
reloadCardsToDownload(this.uiDialog.getSetsCombo().getSelectedItem().toString());
this.uiDialog.showDownloadControls(true);
updateAndViewMessage("");
updateMessage("");
showDownloadControls(true);
}
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);
}
// auto-size on empty message (on complete)
if (text.isEmpty()) {
this.uiDialog.showDownloadControls(true);
}
public void showDownloadControls(boolean needToShow) {
// auto-size form on show
this.uiDialog.showDownloadControls(needToShow);
}
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.");
}
CardInfo secondSideCard = CardRepository.instance.findCard(card.getSecondSideName());
CardInfo secondSideCard = CardRepository.instance.findCardWPreferredSet(card.getSecondSideName(), card.getSetCode(), false);
if (secondSideCard == null) {
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);
card.setTokenClassName(tokenClassName);
list.add(card);
} else {
logger.error("wrong line format in tokens file: " + line);
}
} else {
logger.error("wrong format for image urls: " + line);
logger.error("wrong line data in tokens file: " + line);
}
}
line = reader.readLine();
@ -569,6 +577,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
@Override
public void run() {
this.cardIndex = 0;
this.resetErrorCount();
File base = new File(getImagesDir());
if (!base.exists()) {
@ -587,7 +596,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
break;
case NONE:
default:
p = Proxy.NO_PROXY;
proxy = Proxy.NO_PROXY;
break;
}
@ -595,67 +604,69 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
try {
String address = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_ADDRESS, "");
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) {
throw new RuntimeException("Gui_DownloadPicturesService : error 1 - " + ex);
}
}
if (p != null) {
update(0, cardsDownloadQueue.size());
if (proxy != null) {
logger.info("Started download of " + cardsDownloadQueue.size() + " images"
+ " from source: " + selectedSource.getSourceName()
+ ", 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"));
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() + ')');
logger.debug("Downloading image: " + card.getName() + " (" + card.getSet() + ')');
CardImageUrls urls;
if (card.isToken()) {
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());
CardImageUrls urls;
if (card.isToken()) {
if (!"0".equals(card.getCollectorId())) {
continue;
}
urls = selectedSource.generateTokenUrl(card);
} else {
urls = selectedSource.generateCardUrl(card);
}
} else {
Runnable task = new DownloadTask(card, urls, cardsDownloadQueue.size());
executor.execute(task);
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());
}
}
} 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();
while (!executor.isTerminated()) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ie) {
executor.shutdown();
while (!executor.isTerminated()) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ie) {
}
}
}
}
@ -671,6 +682,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
// stop
reloadCardsToDownload(uiDialog.getSetsCombo().getSelectedItem().toString());
enableDialogButtons();
// reset images cache
ImageCache.clearCache();
@ -707,7 +719,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
@Override
public void run() {
if (DownloadPicturesService.getInstance().getNeedCancel()) {
if (DownloadPicturesService.getInstance().isNeedCancel()) {
synchronized (sync) {
update(cardIndex + 1, count);
}
@ -791,14 +803,14 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
URL url = new URL(currentUrl);
// on download cancel need to stop
if (DownloadPicturesService.getInstance().getNeedCancel()) {
if (DownloadPicturesService.getInstance().isNeedCancel()) {
return;
}
// download
selectedSource.doPause(url.getPath());
httpConn = url.openConnection(p);
httpConn = url.openConnection(proxy);
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");
@ -838,7 +850,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
}
// can save result
if (isDownloadOK & httpConn != null) {
if (isDownloadOK && httpConn != null) {
// save data to temp
try (InputStream in = new BufferedInputStream(httpConn.getInputStream());
OutputStream tfileout = new TFileOutputStream(fileTempImage);
@ -847,7 +859,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
int len;
while ((len = in.read(buf)) != -1) {
// user cancelled
if (DownloadPicturesService.getInstance().getNeedCancel()) {
if (DownloadPicturesService.getInstance().isNeedCancel()) {
// stop download, save current state and exit
TFile archive = destFile.getTopLevelArchive();
///* not need to unmout/close - it's auto action
@ -934,14 +946,21 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
// try download again
}
this.uiDialog.getRedownloadCheckbox().setSelected(false);
uiDialog.enableActionControls(true);
uiDialog.getStartButton().setEnabled(true);
enableDialogButtons();
}
}
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 {

View file

@ -54,6 +54,7 @@
|Generate|EMBLEM!:C14|Emblem Nixilis|||ObNixilisOfTheBlackOathEmblem|
|Generate|EMBLEM!:C14|Emblem Teferi|||TeferiTemporalArchmageEmblem|
|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!:DTK|Emblem Narset|||NarsetTranscendentEmblem|
|Generate|EMBLEM!:EMA|Emblem Dack Fayden||Emblem Dack|DackFaydenEmblem|
@ -62,7 +63,6 @@
|Generate|EMBLEM!:KLD|Emblem Chandra|||ChandraTorchOfDefianceEmblem|
|Generate|EMBLEM!:KLD|Emblem Dovin|||DovinBaanEmblem|
|Generate|EMBLEM!:KLD|Emblem Nissa|||NissaVitalForceEmblem|
|Generate|EMBLEM!:KLD|Emblem Tezzeret|||TezzeretTheSchemerEmblem|
|Generate|EMBLEM!:KTK|Emblem Sarkhan|||SarkhanTheDragonspeakerEmblem|
|Generate|EMBLEM!:KTK|Emblem Sorin|||SorinSolemnVisitorEmblem|
|Generate|EMBLEM!:M15|Emblem Ajani|||AjaniSteadfastEmblem|
@ -88,6 +88,19 @@
|Generate|EMBLEM:RIX|Huatli, Radiant Champion||Emblem Huatli|HuatliRadiantChampionEmblem|
|Generate|EMBLEM:RNA|Domri, Chaos Bringer||Emblem Domri|DomriChaosBringerEmblem|
|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 - Agyrem|||AgyremPlane|
|Generate|PLANE:PCA|Plane - Akoum|||AkoumPlane|
@ -149,32 +162,33 @@
|Generate|TOK:8ED|Rukh||
|Generate|TOK:9ED|Bird|||RukhEggBirdToken|
|Generate|TOK:9ED|Saproling|||SaprolingToken|
|Generate|TOK:AER|Etherium Cell||
|Generate|TOK:AER|Gremlin||
|Generate|TOK:AER|Ragavan||
|Generate|TOK:AKH|Angel of Sanctions||
|Generate|TOK:AKH|Anointer Priest||
|Generate|TOK:AKH|Aven Initiate||
|Generate|TOK:AKH|Aven Wind Guide||
|Generate|TOK:AER|Etherium Cell|||EtheriumCellToken|
|Generate|TOK:AER|Gremlin|||GremlinToken|
|Generate|TOK:AER|Ragavan|||RagavanToken|
|Generate|TOK:AKH|Beast|||BeastToken3|
|Generate|TOK:AKH|Cat|||CatToken2|
|Generate|TOK:AKH|Drake||
|Generate|TOK:AKH|Glyph Keeper||
|Generate|TOK:AKH|Heart-Piercer Manticore||
|Generate|TOK:AKH|Drake|||DrakeToken|
|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|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|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|Dragon|||DragonToken|
|Generate|TOK:ALA|Goblin|||GoblinTokenWithHaste|
@ -229,7 +243,7 @@
|Generate|TOK:BFZ|Eldrazi Scion|3||EldraziScionToken|
|Generate|TOK:BFZ|Eldrazi|||EldraziToken|
|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|Kor Ally|||KorAllyToken|
|Generate|TOK:BFZ|Octopus|||OctopusToken|
@ -356,13 +370,56 @@
|Generate|TOK:C17|Cat Dragon|||WasitoraCatDragonToken|
|Generate|TOK:C17|Cat Warrior||
|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|Gold||
|Generate|TOK:C17|Rat|||DeathtouchRatToken|
|Generate|TOK:C17|Vampire|||EdgarMarkovToken|
|Generate|TOK:C17|Zombie||
|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|Elemental|||SeedGuardianToken|
|Generate|TOK:CHK|Illusion|||MelokuTheCloudedMirrorToken|
@ -524,16 +581,16 @@
|Generate|TOK:DOM|Construct|||KarnConstructToken|
|Generate|TOK:DOM|Demon|||BelzenlokDemonToken|
|Generate|TOK:DOM|Elemental|||ValdukElementalToken|
|Gererate|TOK:DOM|Goblin||
|Generate|TOK:DOM|Goblin|||GoblinToken|
|Generate|TOK:DOM|Karox Bladewing|||KaroxBladewingDragonToken|
|Generate|TOK:DOM|Knight|1|
|Generate|TOK:DOM|Knight|2|
|Generate|TOK:DOM|Knight|1||KnightToken|
|Generate|TOK:DOM|Knight|2||KnightToken|
|Generate|TOK:DOM|Nightmare Horror|||ChainersTormentNightmareToken|
|Generate|TOK:DOM|Saproling|1|
|Generate|TOK:DOM|Saproling|2|
|Generate|TOK:DOM|Saproling|3|
|Generate|TOK:DOM|Soldier||
|Generate|TOK:DOM|Zombie Knight||
|Generate|TOK:DOM|Saproling|1||SaprolingToken|
|Generate|TOK:DOM|Saproling|2||SaprolingToken|
|Generate|TOK:DOM|Saproling|3||SaprolingToken|
|Generate|TOK:DOM|Soldier|||SoldierToken|
|Generate|TOK:DOM|Zombie Knight|||ZombieKnightToken|
|Generate|TOK:DRB|Saproling|||SaprolingToken|
|Generate|TOK:DST|Beast|||BeastToken|
|Generate|TOK:DST|Elemental|1||WandOfTheElementsFirstToken|
@ -572,15 +629,16 @@
|Generate|TOK:EMA|Wall|||TidalWaveWallToken|
|Generate|TOK:EMA|Wurm|||WurmToken|
|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|Human Soldier|||HumanSoldierToken|
|Generate|TOK:EMN|Human Wizard|||HumanWizardToken|
|Generate|TOK:EMN|Human|||RedHumanToken|
|Generate|TOK:EMN|Insect|||InsectToken|
|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|2||ZombieToken|
|Generate|TOK:EMN|Zombie|3||ZombieToken|
@ -650,19 +708,20 @@
|Generate|TOK:HOP|Pentavite|||PentaviteToken|
|Generate|TOK:HOP|Pest|||PestToken|
|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|Champion of Wits||||
|Generate|TOK:HOU|Dreamstealer||||
|Generate|TOK:HOU|Earthshaker Khenra||||
|Generate|TOK:HOU|Horse|||CrestedSunmareToken|
|Generate|TOK:HOU|Insect|||TheLocustGodInsectToken|
|Generate|TOK:HOU|Proven Combatant||||
|Generate|TOK:HOU|Resilient Khenra||||
|Generate|TOK:HOU|Sinuous Striker||||
|Generate|TOK:HOU|Snake|||RhonassLastStandToken|
|Generate|TOK:HOU|Steadfast Sentinel||||
|Generate|TOK:HOU|Sunscourge Champion||||
|Generate|TOK:HOU|Zombie||
|Generate|TOK:ICE|Caribou|||CaribouToken|
|Generate|TOK:INV|Bird|||OwlToken|
|Generate|TOK:INV|Elephant|||ElephantToken|
@ -1199,6 +1258,12 @@
|Generate|TOK:RNA|Thopter|||ThopterToken|
|Generate|TOK:RNA|Treasure|||TreasureToken|
|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|Assassin|||AssassinToken2|
|Generate|TOK:WAR|Devil|||DevilToken|
@ -1216,10 +1281,64 @@
|Generate|TOK:WAR|Zombie Army|1||ZombieArmyToken|
|Generate|TOK:WAR|Zombie Army|2||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, -
Thopter, 010, -, 1|1, -, Artifact Creature - Thopter, Adam Paquette, 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.
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, 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.
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.'

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

View file

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

View file

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

View file

@ -1,5 +1,12 @@
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.cards.decks.DeckCardLists;
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.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
*/
@ -502,7 +501,7 @@ public class SessionImpl implements Session {
/**
* @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
public synchronized void disconnect(boolean askForReconnect) {
@ -557,8 +556,21 @@ public class SessionImpl implements Session {
@Override
public void handleCallback(Callback callback) throws HandleCallbackException {
//logger.info("callback handler");
client.processCallback((ClientCallback) callback.getCallbackObject());
try {
// 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_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_VERSION_MINOR_PATCH = "V5"; // default
public static final String MAGE_VERSION_MINOR_PATCH = "V1"; // default
// 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;
private final int major;

View file

@ -50,9 +50,9 @@ public class CardView extends SimpleCardView {
@Expose
protected String loyalty = "";
protected String startingLoyalty;
protected EnumSet<CardType> cardTypes;
protected Set<CardType> cardTypes;
protected SubTypeList subTypes;
protected EnumSet<SuperType> superTypes;
protected Set<SuperType> superTypes;
protected ObjectColor color;
protected ObjectColor frameColor;
protected FrameStyle frameStyle;
@ -104,9 +104,6 @@ public class CardView extends SimpleCardView {
protected boolean rotate;
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 canBlock;
protected boolean inViewerOnly;
@ -117,9 +114,13 @@ public class CardView extends SimpleCardView {
this(card, null, false);
}
public CardView(Card card, UUID cardId) {
public CardView(Card card, SimpleCardView simpleCardView) {
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) {
@ -128,10 +129,12 @@ public class CardView extends SimpleCardView {
}
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;
// generetate new ID
this.id = UUID.randomUUID();
this.parentId = cardView.parentId;
this.name = cardView.name;
this.displayName = cardView.displayName;
@ -198,9 +201,6 @@ public class CardView extends SimpleCardView {
this.rotate = cardView.rotate;
this.hideInfo = cardView.hideInfo;
this.isPlayable = cardView.isPlayable;
this.isChoosable = cardView.isChoosable;
this.selected = cardView.selected;
this.canAttack = cardView.canAttack;
this.canBlock = cardView.canBlock;
this.inViewerOnly = cardView.inViewerOnly;
@ -468,8 +468,6 @@ public class CardView extends SimpleCardView {
// Get starting loyalty
this.startingLoyalty = "" + card.getStartingLoyalty();
}
public CardView(MageObject object) {
@ -731,7 +729,7 @@ public class CardView extends SimpleCardView {
return subTypes;
}
public EnumSet<SuperType> getSuperTypes() {
public Set<SuperType> getSuperTypes() {
return superTypes;
}
@ -964,30 +962,6 @@ public class CardView extends SimpleCardView {
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() {
return canAttack;
}

View file

@ -1,11 +1,5 @@
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.abilities.Ability;
import mage.abilities.effects.Effect;
@ -20,8 +14,9 @@ import mage.game.permanent.PermanentToken;
import mage.target.targetpointer.TargetPointer;
import mage.util.GameLog;
import java.util.*;
/**
*
* @author BetaSteward_at_googlemail.com
*/
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.");
// }
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());
} else if (sourceObject instanceof Plane) {
abilityView = new AbilityView(ability, sourceObject.getName(), new CardView(new PlaneView((Plane) sourceObject)));
abilityView.setName(((Plane) sourceObject).getName());
abilityView.setName(sourceObject.getName());
}
break;
}
@ -131,7 +126,10 @@ public class CardsView extends LinkedHashMap<UUID, CardView> {
if ((mageObject instanceof Card) && ((Card) mageObject).isFaceDown(game)) {
continue;
}
names.add(GameLog.getColoredObjectIdNameForTooltip(mageObject));
String newName = GameLog.getColoredObjectIdNameForTooltip(mageObject);
if (!names.contains(newName)) {
names.add(newName);
}
}
}
if (!names.isEmpty()) {

View file

@ -1,21 +1,18 @@
package mage.view;
import java.io.Serializable;
import java.util.List;
import java.util.UUID;
/**
*
* @author Plopman
*/
public interface CommandObjectView extends Serializable {
public String getExpansionSetCode();
public interface CommandObjectView extends SelectableObjectView {
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;
import mage.cards.Card;
import mage.game.command.Emblem;
import java.io.Serializable;
import java.util.List;
import java.util.UUID;
import mage.cards.Card;
import mage.game.command.Emblem;
/**
* @author noxx
@ -15,24 +16,25 @@ public class EmblemView implements CommandObjectView, Serializable {
protected String name;
protected String expansionSetCode;
protected List<String> rules;
protected boolean isPlayable = false;
protected int playableAmount = 0;
public EmblemView(Emblem emblem, Card sourceCard) {
id = emblem.getId();
name = "Emblem " + sourceCard.getName();
this.id = emblem.getId();
this.name = "Emblem " + sourceCard.getName();
if (emblem.getExpansionSetCodeForImage() == null) {
expansionSetCode = sourceCard.getExpansionSetCode();
this.expansionSetCode = sourceCard.getExpansionSetCode();
} else {
expansionSetCode = emblem.getExpansionSetCodeForImage();
this.expansionSetCode = emblem.getExpansionSetCodeForImage();
}
rules = emblem.getAbilities().getRules(sourceCard.getName());
this.rules = emblem.getAbilities().getRules(sourceCard.getName());
}
public EmblemView(Emblem emblem) {
id = emblem.getId();
name = emblem.getName();
expansionSetCode = emblem.getExpansionSetCodeForImage();
rules = emblem.getAbilities().getRules(emblem.getName());
this.id = emblem.getId();
this.name = emblem.getName();
this.expansionSetCode = emblem.getExpansionSetCodeForImage();
this.rules = emblem.getAbilities().getRules(emblem.getName());
}
@Override
@ -54,4 +56,47 @@ public class EmblemView implements CommandObjectView, Serializable {
public List<String> getRules() {
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 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
@ -39,7 +42,7 @@ public class GameView implements Serializable {
private final int priorityTime;
private final List<PlayerView> players = new ArrayList<>();
private CardsView hand;
private Set<UUID> canPlayInHand;
private Map<UUID, Integer> canPlayObjects;
private Map<String, SimpleCardsView> opponentHands;
private Map<String, SimpleCardsView> watchedHands;
private final CardsView stack = new CardsView();
@ -300,12 +303,12 @@ public class GameView implements Serializable {
return isPlayer;
}
public Set<UUID> getCanPlayInHand() {
return canPlayInHand;
public Map<UUID, Integer> getCanPlayObjects() {
return canPlayObjects;
}
public void setCanPlayInHand(Set<UUID> canPlayInHand) {
this.canPlayInHand = canPlayInHand;
public void setCanPlayObjects(Map<UUID, Integer> canPlayObjects) {
this.canPlayObjects = canPlayObjects;
}
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."
+ " A face-down card can also be turned face up for its morph cost.");
} else if (permanent.isMorphed()) {
this.rules.add("If the controller has priority, he or she 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.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 they pay the morph costs,"
+ " then turns this permanent face up.");
}
}

View file

@ -1,10 +1,11 @@
package mage.view;
import mage.cards.Card;
import mage.game.command.Plane;
import java.io.Serializable;
import java.util.List;
import java.util.UUID;
import mage.cards.Card;
import mage.game.command.Plane;
/**
* @author spjspj
@ -16,23 +17,25 @@ public class PlaneView implements CommandObjectView, Serializable {
protected String expansionSetCode;
protected List<String> rules;
public PlaneView(Plane plane, Card sourceCard) {
id = plane.getId();
name = "Plane " + sourceCard.getName();
if (plane.getExpansionSetCodeForImage() == null) {
expansionSetCode = sourceCard.getExpansionSetCode();
} else {
expansionSetCode = plane.getExpansionSetCodeForImage();
}
protected boolean isPlayable = false;
protected int playableAmount = 0;
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) {
id = plane.getId();
name = plane.getName();
expansionSetCode = plane.getExpansionSetCodeForImage();
rules = plane.getAbilities().getRules(plane.getName());
this.id = plane.getId();
this.name = plane.getName();
this.expansionSetCode = plane.getExpansionSetCodeForImage();
this.rules = plane.getAbilities().getRules(plane.getName());
}
@Override
@ -54,4 +57,46 @@ public class PlaneView implements CommandObjectView, Serializable {
public List<String> getRules() {
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;
import com.google.gson.annotations.Expose;
@ -8,10 +6,9 @@ import java.io.Serializable;
import java.util.UUID;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class SimpleCardView implements Serializable {
public class SimpleCardView implements Serializable, SelectableObjectView {
@Expose
protected UUID id;
protected String expansionSetCode;
@ -21,9 +18,30 @@ public class SimpleCardView implements Serializable {
protected boolean usesVariousArt;
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) {
this(id, expansionSetCode, cardNumber, usesVariousArt, tokenSetCode, false, tokenDescriptor);
}
public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt, String tokenSetCode, boolean isGameObject, String tokenDescriptor) {
this.id = id;
this.expansionSetCode = expansionSetCode;
@ -53,12 +71,52 @@ public class SimpleCardView implements Serializable {
public String getTokenSetCode() {
return tokenSetCode;
}
public String getTokenDescriptor() {
return tokenDescriptor;
}
public boolean isGameObject() {
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;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Mode;
import mage.abilities.Modes;
@ -18,8 +14,11 @@ import mage.target.targetpointer.FixedTarget;
import mage.target.targetpointer.TargetPointer;
import mage.util.GameLog;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class StackAbilityView extends CardView {
@ -94,7 +93,10 @@ public class StackAbilityView extends CardView {
if ((mageObject instanceof Card) && ((Card) mageObject).isFaceDown(game)) {
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()) {
case WAITING:
stateText.append(" (").append(table.getTournament().getPlayers().size()).append('/').append(table.getNumberOfSeats()).append(')');
break;
case READY_TO_START:
case STARTING:
infoText.append(" Time: ").append(table.getTournament().getOptions().getMatchOptions().getMatchTimeLimit().toString());
@ -153,6 +154,7 @@ public class TableView implements Serializable {
if (draft != null) {
stateText.append(' ').append(draft.getBoosterNum()).append('/').append(draft.getCardNum() - 1);
}
break;
default:
}
this.additionalInfo = infoText.toString();

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -12,7 +12,7 @@ public class BattleForZendikarBlock extends Constructed {
public BattleForZendikarBlock() {
super("Constructed - Battle for Zendikar Block");
setCodes.add("BFZ");
setCodes.add("OGW");
setCodes.add(mage.sets.BattleForZendikar.getInstance().getCode());
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.Deck;
import mage.filter.FilterMana;
import mage.util.ManaUtil;
import java.util.*;
@ -21,8 +22,7 @@ public class Brawl extends Constructed {
// Copy of standard sets
setCodes.addAll(Standard.makeLegalSets());
banned.add("Baral, Chief of Compliance");
banned.add("Smuggler's Copter");
banned.add("Oko, Thief of Crowns");
banned.add("Sorcerous Spyglass");
}
@ -48,14 +48,7 @@ public class Brawl extends Constructed {
Map<String, Integer> counts = new HashMap<>();
countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard());
for (Map.Entry<String, Integer> entry : counts.entrySet()) {
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
valid = checkCounts(1, counts) && valid;
for (String bannedCard : banned) {
if (counts.containsKey(bannedCard)) {
@ -78,25 +71,7 @@ public class Brawl extends Constructed {
invalid.put("Brawl", "Invalid Commander (" + 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);
}
if (commanderColor.isColorless()) {
colorIdentity.setColorless(true);
}
ManaUtil.collectColorIdentity(colorIdentity, commander.getColorIdentity());
}
}
Set<String> basicsInDeck = new HashSet<>();
@ -108,7 +83,7 @@ public class Brawl extends Constructed {
}
}
for (Card card : deck.getCards()) {
if (!cardHasValidColor(colorIdentity, card)
if (!ManaUtil.isColorIdentityCompatible(colorIdentity, card.getColorIdentity())
&& !(colorIdentity.isColorless()
&& basicsInDeck.size() == 1
&& basicsInDeck.contains(card.getName()))) {
@ -135,13 +110,4 @@ public class Brawl extends Constructed {
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 static final Map<String, Integer> pointMap = new HashMap<>();
private static final Map<String, Integer> pointMap = new HashMap<>();
static {
pointMap.put("Ancestral Recall", 7);
pointMap.put("Balance", 1);
pointMap.put("Birthing Pod", 2);
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("Enlightened Tutor", 1);
pointMap.put("Fastbond", 1);
pointMap.put("Flash", 7);
pointMap.put("Flash", 6);
pointMap.put("Gifts Ungiven", 2);
pointMap.put("Imperial Seal", 1);
pointMap.put("Intuition", 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 Vault", 1);
pointMap.put("Merchant Scroll", 1);
@ -42,7 +42,7 @@ public class CanadianHighlander extends Constructed {
pointMap.put("Mystical Tutor", 2);
pointMap.put("Natural Order", 4);
pointMap.put("Protean Hulk", 3);
pointMap.put("Sol Ring", 3);
pointMap.put("Sol Ring", 4);
pointMap.put("Spellseeker", 1);
pointMap.put("Stoneforge Mystic", 1);
pointMap.put("Strip Mine", 2);
@ -56,7 +56,7 @@ public class CanadianHighlander extends Constructed {
pointMap.put("Treasure Cruise", 1);
pointMap.put("True-Name Nemesis", 1);
pointMap.put("Umezawa's Jitte", 2);
pointMap.put("Vampiric Tutor", 3);
pointMap.put("Vampiric Tutor", 2);
}
public CanadianHighlander() {
@ -89,14 +89,7 @@ public class CanadianHighlander extends Constructed {
Map<String, Integer> counts = new HashMap<>();
countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard());
for (Map.Entry<String, Integer> entry : counts.entrySet()) {
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
valid = checkCounts(1, counts) && valid;
int allowedPoints = 10;
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.Deck;
import mage.filter.FilterMana;
import mage.util.ManaUtil;
import java.util.*;
@ -20,7 +21,8 @@ import java.util.*;
*/
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;
public Commander() {
@ -42,6 +44,7 @@ public class Commander extends Constructed {
banned.add("Fastbond");
banned.add("Gifts Ungiven");
banned.add("Griselbrand");
banned.add("Iona, Shield of Emeria");
banned.add("Karakas");
banned.add("Leovold, Emissary of Trest");
banned.add("Library of Alexandria");
@ -51,8 +54,8 @@ public class Commander extends Constructed {
banned.add("Mox Pearl");
banned.add("Mox Ruby");
banned.add("Mox Sapphire");
banned.add("Painter's Servant");
banned.add("Panoptic Mirror");
banned.add("Paradox Engine");
banned.add("Primeval Titan");
banned.add("Prophet of Kruphix");
banned.add("Recurring Nightmare");
@ -97,14 +100,7 @@ public class Commander extends Constructed {
Map<String, Integer> counts = new HashMap<>();
countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard());
for (Map.Entry<String, Integer> entry : counts.entrySet()) {
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
valid = checkCounts(1, counts) && valid;
for (String bannedCard : banned) {
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)) {
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() + ')');
valid = false;
}
if (deck.getSideboard().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 (deck.getSideboard().size() == 2) {
if (commander.getAbilities().contains(PartnerAbility.getInstance())) {
if (bannedPartner.contains(commander.getName())) {
invalid.put("Commander", "Partner banned (" + commander.getName() + ')');
valid = false;
}
} 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()) {
if (!cardHasValidColor(colorIdentity, card)) {
if (!ManaUtil.isColorIdentityCompatible(colorIdentity, card.getColorIdentity())) {
invalid.put(card.getName(), "Invalid color (" + colorIdentity.toString() + ')');
valid = false;
}
@ -191,15 +183,6 @@ public class Commander extends Constructed {
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
public int getEdhPowerLevel(Deck deck) {
if (deck == null) {

View file

@ -47,6 +47,7 @@ public class DuelCommander extends Commander {
banned.add("Polymorph");
banned.add("Price of Progress");
banned.add("Protean Hulk");
banned.add("Scapeshift");
banned.add("Sensei's Divining Top");
banned.add("Shahrazad");
banned.add("Sol Ring");
@ -55,25 +56,30 @@ public class DuelCommander extends Commander {
banned.add("The Tabernacle at Pendrell Vale");
banned.add("Time Vault");
banned.add("Time Walk");
banned.add("Timetwister");
banned.add("Tinker");
banned.add("Tolarian Academy");
banned.add("Treasure Cruise");
banned.add("Vampiric Tutor");
bannedCommander.add("Arahbo, Roar of the World");
bannedCommander.add("Breya, Etherium Shaper");
bannedCommander.add("Bruse Tarl, Boorish Herder");
bannedCommander.add("Derevi, Empyrial Tactician");
bannedCommander.add("Edgar Markov");
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("Jace, Vryn's Prodigy");
bannedCommander.add("Marath, Will of the Wild");
bannedCommander.add("Najeela, the Blade-Blossom");
bannedCommander.add("Oloro, Ageless Ascetic");
bannedCommander.add("Rofellos, Llanowar Emissary");
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("Zur the Enchanter");
bannedCommander.add("Yuriko, the Tigers Shadow");
bannedCommander.add("Zurgo Bellstriker");
}

View file

@ -9,6 +9,7 @@ import mage.cards.Sets;
import mage.cards.decks.Constructed;
import mage.cards.decks.Deck;
import mage.filter.FilterMana;
import mage.util.ManaUtil;
import java.util.*;
@ -58,18 +59,9 @@ public class FreeformCommander extends Constructed {
countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard());
for (Map.Entry<String, Integer> entry : counts.entrySet()) {
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
valid = checkCounts(1, counts) && valid;
generateFreeformHash();
if (deck.getSideboard().size() < 1 || deck.getSideboard().size() > 2) {
if (deck.getSideboard().isEmpty() || deck.getSideboard().size() > 2) {
invalid.put("Commander", "Sideboard must contain only the commander(s)");
valid = false;
} else {
@ -97,27 +89,17 @@ public class FreeformCommander extends Constructed {
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()) {
if (!cardHasValidColor(colorIdentity, card)) {
if (!ManaUtil.isColorIdentityCompatible(colorIdentity, card.getColorIdentity())) {
invalid.put(card.getName(), "Invalid color (" + colorIdentity.toString() + ')');
valid = false;
}
@ -133,17 +115,4 @@ public class FreeformCommander extends Constructed {
}
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.decks.Constructed;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
@ -15,7 +16,7 @@ public class Frontier extends Constructed {
public 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()) {
if (set.getSetType().isStandardLegal() && (set.getReleaseDate().after(cutoff) || set.getReleaseDate().equals(cutoff))) {
setCodes.add(set.getCode());

View file

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

View file

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

View file

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

View file

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

View file

@ -12,9 +12,9 @@ public class KhansOfTarkirBlock extends Constructed {
public KhansOfTarkirBlock() {
super("Constructed - Khans of Tarkir Block");
setCodes.add("KTK");
setCodes.add("FRF");
setCodes.add("DTK");
setCodes.add(mage.sets.KhansOfTarkir.getInstance().getCode());
setCodes.add(mage.sets.FateReforged.getInstance().getCode());
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("Windfall");
banned.add("Worldknit");
banned.add("Wrenn and Six");
banned.add("Yawgmoth's Bargain");
banned.add("Yawgmoth's Will");

View file

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

View file

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

View file

@ -4,6 +4,7 @@ import mage.cards.ExpansionSet;
import mage.cards.Sets;
import mage.cards.decks.Constructed;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
@ -15,7 +16,7 @@ public class ModernNoBannedList extends Constructed {
public ModernNoBannedList() {
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()) {
if (set.getSetType().isModernLegal() && (set.getReleaseDate().after(cutoff) || set.getReleaseDate().equals(cutoff))) {
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