Merge branch 'master' into fix-tapped-for-mana-event

This commit is contained in:
Oleg Agafonov 2019-12-31 12:12:25 +01:00 committed by GitHub
commit 60781604f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
1600 changed files with 42766 additions and 10461 deletions

3
.gitignore vendored
View file

@ -152,3 +152,6 @@ mage-bundle
# build-tools config and log files when building client/server with Atom # build-tools config and log files when building client/server with Atom
.build-tools.cson .build-tools.cson
build-output.log build-output.log
# Visual Studio Code
.history

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -26,6 +26,7 @@ import mage.client.plugins.impl.Plugins;
import mage.client.preference.MagePreferences; import mage.client.preference.MagePreferences;
import mage.client.remote.CallbackClientImpl; import mage.client.remote.CallbackClientImpl;
import mage.client.table.TablesPane; import mage.client.table.TablesPane;
import mage.client.table.TablesPanel;
import mage.client.tournament.TournamentPane; import mage.client.tournament.TournamentPane;
import mage.client.util.*; import mage.client.util.*;
import mage.client.util.audio.MusicPlayer; import mage.client.util.audio.MusicPlayer;
@ -261,7 +262,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
desktopPane.add(errorDialog, JLayeredPane.MODAL_LAYER); desktopPane.add(errorDialog, JLayeredPane.MODAL_LAYER);
UI.addComponent(MageComponents.DESKTOP_PANE, desktopPane); UI.addComponent(MageComponents.DESKTOP_PANE, desktopPane);
PING_TASK_EXECUTOR.scheduleAtFixedRate(() -> SessionHandler.ping(), 60, 60, TimeUnit.SECONDS); PING_TASK_EXECUTOR.scheduleAtFixedRate(() -> SessionHandler.ping(), TablesPanel.PING_SERVER_SECS, TablesPanel.PING_SERVER_SECS, TimeUnit.SECONDS);
updateMemUsageTask = new UpdateMemUsageTask(jMemUsageLabel); updateMemUsageTask = new UpdateMemUsageTask(jMemUsageLabel);

View file

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

View file

@ -695,13 +695,13 @@ public class MageBook extends JComponent {
int totalTokensEmblems = totalTokens + getTotalNumEmblems(set); int totalTokensEmblems = totalTokens + getTotalNumEmblems(set);
int start = 0; int start = 0;
if (!(page * conf.CARDS_PER_PAGE <= totalTokensEmblems && (page + 1) * conf.CARDS_PER_PAGE >= totalTokensEmblems)) { if (!(page * conf.CARDS_PER_PAGE <= totalTokensEmblems && (page + 1) * conf.CARDS_PER_PAGE >= totalTokensEmblems)) {
start = page * conf.CARDS_PER_PAGE - totalTokensEmblems; start = Math.max(0, page * conf.CARDS_PER_PAGE - totalTokensEmblems);
pageRight.setVisible(true); pageRight.setVisible(true);
} }
int end = planes.size(); int end = planes.size();
if ((page + 1) * conf.CARDS_PER_PAGE < totalTokensEmblems + planes.size()) { if ((page + 1) * conf.CARDS_PER_PAGE < totalTokensEmblems + planes.size()) {
end = (page + 1) * conf.CARDS_PER_PAGE - totalTokensEmblems; end = Math.max(0, (page + 1) * conf.CARDS_PER_PAGE - totalTokensEmblems);
pageRight.setVisible(true); pageRight.setVisible(true);
} else { } else {
pageRight.setVisible(false); pageRight.setVisible(false);

View file

@ -480,19 +480,32 @@ public class AddLandDialog extends MageDialog {
white += m.getWhite(); white += m.getWhite();
} }
int total = red + green + black + blue + white; int total = red + green + black + blue + white;
int redcards = Math.round(land_number * ((float) red / (float) total));
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; total -= red;
land_number -= redcards; land_number -= redcards;
int greencards = Math.round(land_number * ((float) green / (float) total));
greencards = Math.round(land_number * ((float) green / (float) total));
total -= green; total -= green;
land_number -= greencards; land_number -= greencards;
int blackcards = Math.round(land_number * ((float) black / (float) total));
blackcards = Math.round(land_number * ((float) black / (float) total));
total -= black; total -= black;
land_number -= blackcards; land_number -= blackcards;
int bluecards = Math.round(land_number * ((float) blue / (float) total));
bluecards = Math.round(land_number * ((float) blue / (float) total));
total -= blue; total -= blue;
land_number -= bluecards; land_number -= bluecards;
int whitecards = land_number;
whitecards = land_number;
}
spnMountain.setValue(redcards); spnMountain.setValue(redcards);
spnForest.setValue(greencards); spnForest.setValue(greencards);
spnSwamp.setValue(blackcards); spnSwamp.setValue(blackcards);

View file

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

View file

@ -283,11 +283,10 @@ public class ConnectDialog extends MageDialog {
}); });
btnFindUs.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/us.png"))); // NOI18N btnFindUs.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/us.png"))); // NOI18N
btnFindUs.setText("P"); btnFindUs.setText("US");
btnFindUs.setToolTipText("Connect to mtg.powersofwar.com (USA, use any username without registration)"); btnFindUs.setToolTipText("Connect to us.xmage.today (USA, use any username without registration)");
btnFindUs.setActionCommand("connectXmageus"); btnFindUs.setActionCommand("connectXmageus");
btnFindUs.setAlignmentY(0.0F); btnFindUs.setAlignmentY(0.0F);
btnFindUs.setEnabled(false);
btnFindUs.setMargin(new java.awt.Insets(2, 2, 2, 2)); btnFindUs.setMargin(new java.awt.Insets(2, 2, 2, 2));
btnFindUs.setName("connectXmageusBtn"); // NOI18N btnFindUs.setName("connectXmageusBtn"); // NOI18N
btnFindUs.setPreferredSize(new java.awt.Dimension(23, 23)); btnFindUs.setPreferredSize(new java.awt.Dimension(23, 23));
@ -338,8 +337,6 @@ public class ConnectDialog extends MageDialog {
); );
txtPort.addKeyListener(new java.awt.event.KeyAdapter() { txtPort.addKeyListener(new java.awt.event.KeyAdapter() {
@Override
public void keyTyped(java.awt.event.KeyEvent evt) { public void keyTyped(java.awt.event.KeyEvent evt) {
ConnectDialog.this.keyTyped(evt); ConnectDialog.this.keyTyped(evt);
} }
@ -768,7 +765,7 @@ public class ConnectDialog extends MageDialog {
}//GEN-LAST:event_btnFind2findPublicServerActionPerformed }//GEN-LAST:event_btnFind2findPublicServerActionPerformed
private void connectXmageus(java.awt.event.ActionEvent evt) { private void connectXmageus(java.awt.event.ActionEvent evt) {
String serverAddress = "mtg.powersofwar.com"; String serverAddress = "us.xmage.today";
this.txtServer.setText(serverAddress); this.txtServer.setText(serverAddress);
this.txtPort.setText("17171"); this.txtPort.setText("17171");
// Update userName and password according to the chosen server. // Update userName and password according to the chosen server.
@ -777,7 +774,7 @@ public class ConnectDialog extends MageDialog {
} }
private void connectBeta(java.awt.event.ActionEvent evt) { private void connectBeta(java.awt.event.ActionEvent evt) {
String serverAddress = "xmage.today"; String serverAddress = "beta.xmage.today";
this.txtServer.setText(serverAddress); this.txtServer.setText(serverAddress);
this.txtPort.setText("17171"); this.txtPort.setText("17171");
// Update userName and password according to the chosen server. // Update userName and password according to the chosen server.

View file

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

View file

@ -187,7 +187,7 @@ public class NewTableDialog extends MageDialog {
lbDeckType.setText("Deck Type:"); lbDeckType.setText("Deck Type:");
lbTimeLimit.setText("Time Limit:"); lbTimeLimit.setText("Time Limit:");
lbTimeLimit.setToolTipText("The active time a player may use to finish the match. If his or her time runs out, the player looses the current game."); lbTimeLimit.setToolTipText("The active time a player may use to finish the match. If their time runs out, the player looses the current game.");
lblGameType.setText("Game Type:"); lblGameType.setText("Game Type:");
@ -637,6 +637,7 @@ public class NewTableDialog extends MageDialog {
case "Variant Magic - Commander": case "Variant Magic - Commander":
case "Variant Magic - Duel Commander": case "Variant Magic - Duel Commander":
case "Variant Magic - MTGO 1v1 Commander": case "Variant Magic - MTGO 1v1 Commander":
case "Variant Magic - Centurion Commander":
case "Variant Magic - Penny Dreadful Commander": case "Variant Magic - Penny Dreadful Commander":
if (!options.getGameType().startsWith("Commander")) { if (!options.getGameType().startsWith("Commander")) {
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Deck type Commander needs also a Commander game type", "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Deck type Commander needs also a Commander game type", "Error", JOptionPane.ERROR_MESSAGE);
@ -683,6 +684,7 @@ public class NewTableDialog extends MageDialog {
if (!options.getDeckType().equals("Variant Magic - Commander") if (!options.getDeckType().equals("Variant Magic - Commander")
&& !options.getDeckType().equals("Variant Magic - Duel Commander") && !options.getDeckType().equals("Variant Magic - Duel Commander")
&& !options.getDeckType().equals("Variant Magic - MTGO 1v1 Commander") && !options.getDeckType().equals("Variant Magic - MTGO 1v1 Commander")
&& !options.getDeckType().equals("Variant Magic - Centurion Commander")
&& !options.getDeckType().equals("Variant Magic - Freeform Commander") && !options.getDeckType().equals("Variant Magic - Freeform Commander")
&& !options.getDeckType().equals("Variant Magic - Penny Dreadful Commander")) { && !options.getDeckType().equals("Variant Magic - Penny Dreadful Commander")) {
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Deck type Commander needs also a Commander game type", "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Deck type Commander needs also a Commander game type", "Error", JOptionPane.ERROR_MESSAGE);

View file

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

View file

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

View file

@ -36,12 +36,17 @@
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<Component id="pnlSelect" min="-2" pref="241" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<EmptySpace pref="300" max="32767" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0">
<Component id="pnlApply" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" 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"/> <Component id="pnlPacks" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
@ -49,11 +54,13 @@
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Component id="pnlPacks" min="-2" pref="372" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="pnlPacks" min="-2" pref="362" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="pnlApply" min="-2" pref="32" max="-2" attributes="0"/> <Component id="pnlApply" min="-2" pref="32" max="-2" attributes="0"/>
<Component id="pnlSelect" min="-2" pref="32" max="-2" attributes="0"/> <Component id="pnlSelect" min="-2" pref="32" max="-2" attributes="0"/>
<Component id="btnApply" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace max="32767" attributes="0"/> <EmptySpace max="32767" attributes="0"/>
</Group> </Group>
@ -64,8 +71,8 @@
<Container class="java.awt.Panel" name="pnlPacks"> <Container class="java.awt.Panel" name="pnlPacks">
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridLayout"> <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridLayout">
<Property name="columns" type="int" value="12"/> <Property name="columns" type="int" value="13"/>
<Property name="rows" type="int" value="11"/> <Property name="rows" type="int" value="12"/>
</Layout> </Layout>
</Container> </Container>
<Container class="javax.swing.JPanel" name="pnlSelect"> <Container class="javax.swing.JPanel" name="pnlSelect">
@ -94,7 +101,7 @@
<Container class="javax.swing.JPanel" name="pnlApply"> <Container class="javax.swing.JPanel" name="pnlApply">
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/> <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/>
<SubComponents> </Container>
<Component class="javax.swing.JButton" name="btnApply"> <Component class="javax.swing.JButton" name="btnApply">
<Properties> <Properties>
<Property name="text" type="java.lang.String" value="Apply"/> <Property name="text" type="java.lang.String" value="Apply"/>
@ -105,6 +112,4 @@
</Events> </Events>
</Component> </Component>
</SubComponents> </SubComponents>
</Container>
</SubComponents>
</Form> </Form>

View file

@ -100,7 +100,6 @@ public class RandomPacksSelectorDialog extends javax.swing.JDialog {
} }
} }
/** /**
* This method is called from within the constructor to initialize the form. * This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always * WARNING: Do NOT modify this code. The content of this method is always
@ -118,7 +117,7 @@ public class RandomPacksSelectorDialog extends javax.swing.JDialog {
btnApply = new javax.swing.JButton(); btnApply = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE); setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
setTitle(title); setTitle("Random Booster Draft Packs Selector");
setModal(true); setModal(true);
setModalExclusionType(java.awt.Dialog.ModalExclusionType.APPLICATION_EXCLUDE); setModalExclusionType(java.awt.Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
setPreferredSize(new java.awt.Dimension(600, 450)); setPreferredSize(new java.awt.Dimension(600, 450));
@ -129,50 +128,63 @@ public class RandomPacksSelectorDialog extends javax.swing.JDialog {
} }
}); });
pnlPacks.setLayout(new java.awt.GridLayout(11, 12)); pnlPacks.setLayout(new java.awt.GridLayout(12, 13));
pnlSelect.setLayout(new javax.swing.BoxLayout(pnlSelect, javax.swing.BoxLayout.LINE_AXIS)); pnlSelect.setLayout(new javax.swing.BoxLayout(pnlSelect, javax.swing.BoxLayout.LINE_AXIS));
btnNone.setText("Select none"); btnNone.setText("Select none");
btnNone.setActionCommand("none"); btnNone.setActionCommand("none");
btnNone.addActionListener(evt -> btnNoneActionPerformed(evt)); btnNone.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnNoneActionPerformed(evt);
}
});
pnlSelect.add(btnNone); pnlSelect.add(btnNone);
btnAll.setText("Select all"); btnAll.setText("Select all");
btnAll.addActionListener(evt -> btnAllActionPerformed(evt)); btnAll.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnAllActionPerformed(evt);
}
});
pnlSelect.add(btnAll); pnlSelect.add(btnAll);
pnlApply.setLayout(new javax.swing.BoxLayout(pnlApply, javax.swing.BoxLayout.LINE_AXIS)); pnlApply.setLayout(new javax.swing.BoxLayout(pnlApply, javax.swing.BoxLayout.LINE_AXIS));
btnApply.setText("Apply"); btnApply.setText("Apply");
if (isRandomDraft) { btnApply.setToolTipText("At least two packs must be selected");
btnApply.setToolTipText("At least 2 packs must be selected"); btnApply.addActionListener(new java.awt.event.ActionListener() {
} else if (isRichManDraft) { public void actionPerformed(java.awt.event.ActionEvent evt) {
btnApply.setToolTipText("At least 1 pack must be selected"); btnApplyActionPerformed(evt);
} }
btnApply.addActionListener(evt -> btnApplyActionPerformed(evt)); });
pnlApply.add(btnApply);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout); getContentPane().setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(pnlSelect, javax.swing.GroupLayout.PREFERRED_SIZE, 241, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 300, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(pnlApply, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(pnlPacks, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .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()) .addContainerGap())
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(pnlPacks, javax.swing.GroupLayout.PREFERRED_SIZE, 372, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap()
.addComponent(pnlPacks, javax.swing.GroupLayout.PREFERRED_SIZE, 362, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(pnlApply, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(pnlApply, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(pnlSelect, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(pnlSelect, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnApply))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
); );

View file

@ -1205,11 +1205,11 @@ public final class GamePanel extends javax.swing.JPanel {
needSelectable = new HashSet<>(); needSelectable = new HashSet<>();
} }
Set<UUID> needPlayable; Map<UUID, Integer> needPlayable;
if (showPlayable && gameView.getCanPlayObjects() != null) { if (showPlayable && gameView.getCanPlayObjects() != null) {
needPlayable = gameView.getCanPlayObjects(); needPlayable = gameView.getCanPlayObjects();
} else { } else {
needPlayable = new HashSet<>(); needPlayable = new HashMap<>();
} }
if (needChoosen.isEmpty() && needSelectable.isEmpty() && needPlayable.isEmpty()) { if (needChoosen.isEmpty() && needSelectable.isEmpty() && needPlayable.isEmpty()) {
@ -1225,8 +1225,9 @@ public final class GamePanel extends javax.swing.JPanel {
if (needChoosen.contains(card.getId())) { if (needChoosen.contains(card.getId())) {
card.setSelected(true); card.setSelected(true);
} }
if (needPlayable.contains(card.getId())) { if (needPlayable.containsKey(card.getId())) {
card.setPlayable(true); card.setPlayable(true);
card.setPlayableAmount(needPlayable.get(card.getId()));
} }
} }
} }
@ -1254,8 +1255,9 @@ public final class GamePanel extends javax.swing.JPanel {
if (needChoosen.contains(perm.getKey())) { if (needChoosen.contains(perm.getKey())) {
perm.getValue().setSelected(true); perm.getValue().setSelected(true);
} }
if (needPlayable.contains(perm.getKey())) { if (needPlayable.containsKey(perm.getKey())) {
perm.getValue().setPlayable(true); perm.getValue().setPlayable(true);
perm.getValue().setPlayableAmount(needPlayable.get(perm.getKey()));
} }
} }
} }
@ -1271,8 +1273,9 @@ public final class GamePanel extends javax.swing.JPanel {
if (needChoosen.contains(card.getKey())) { if (needChoosen.contains(card.getKey())) {
card.getValue().setSelected(true); card.getValue().setSelected(true);
} }
if (needPlayable.contains(card.getKey())) { if (needPlayable.containsKey(card.getKey())) {
card.getValue().setPlayable(true); card.getValue().setPlayable(true);
card.getValue().setPlayableAmount(needPlayable.get(card.getKey()));
} }
} }
} }
@ -1288,8 +1291,9 @@ public final class GamePanel extends javax.swing.JPanel {
if (needChoosen.contains(card.getKey())) { if (needChoosen.contains(card.getKey())) {
card.getValue().setSelected(true); card.getValue().setSelected(true);
} }
if (needPlayable.contains(card.getKey())) { if (needPlayable.containsKey(card.getKey())) {
card.getValue().setPlayable(true); card.getValue().setPlayable(true);
card.getValue().setPlayableAmount(needPlayable.get(card.getKey()));
} }
} }
} }
@ -1305,8 +1309,9 @@ public final class GamePanel extends javax.swing.JPanel {
if (needChoosen.contains(com.getId())) { if (needChoosen.contains(com.getId())) {
com.setSelected(true); com.setSelected(true);
} }
if (needPlayable.contains(com.getId())) { if (needPlayable.containsKey(com.getId())) {
com.setPlayable(true); com.setPlayable(true);
com.setPlayableAmount(needPlayable.get(com.getId()));
} }
} }
} }
@ -1321,8 +1326,19 @@ public final class GamePanel extends javax.swing.JPanel {
if (needChoosen.contains(card.getKey())) { if (needChoosen.contains(card.getKey())) {
card.getValue().setSelected(true); card.getValue().setSelected(true);
} }
if (needPlayable.contains(card.getKey())) { if (needPlayable.containsKey(card.getKey())) {
card.getValue().setPlayable(true); 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()));
} }
} }
} }

View file

@ -142,7 +142,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
// can play // can play
if (gameView != null && gameView.getCanPlayObjects() != null && !gameView.getCanPlayObjects().isEmpty()) { if (gameView != null && gameView.getCanPlayObjects() != null && !gameView.getCanPlayObjects().isEmpty()) {
for (CardView card : cards) { for (CardView card : cards) {
if (gameView.getCanPlayObjects().contains(card.getId())) { if (gameView.getCanPlayObjects().containsKey(card.getId())) {
return true; return true;
} }
} }
@ -239,7 +239,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
Color commandColor = Color.BLACK; Color commandColor = Color.BLACK;
for (CommandObjectView com : player.getCommandObjectList()) { for (CommandObjectView com : player.getCommandObjectList()) {
if (game != null && game.getCanPlayObjects() != null && game.getCanPlayObjects().contains(com.getId())) { if (game != null && game.getCanPlayObjects() != null && game.getCanPlayObjects().containsKey(com.getId())) {
commandColor = activeValueColor; commandColor = activeValueColor;
break; break;
} }
@ -269,7 +269,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
if (!MageFrame.isLite()) { if (!MageFrame.isLite()) {
int id = player.getUserData().getAvatarId(); int id = player.getUserData().getAvatarId();
if (!(id >= 1000) && (id <= 0 || (id <= MIN_AVATAR_ID && id > MAX_AVATAR_ID))) { if (!(id > 1000) && (id != 64) && (id < MIN_AVATAR_ID || id > MAX_AVATAR_ID)) {
id = DEFAULT_AVATAR_ID; id = DEFAULT_AVATAR_ID;
} }
if (id != avatarId) { if (id != avatarId) {

View file

@ -18,7 +18,6 @@ import mage.interfaces.callback.CallbackClient;
import mage.interfaces.callback.ClientCallback; import mage.interfaces.callback.ClientCallback;
import mage.remote.ActionData; import mage.remote.ActionData;
import mage.remote.Session; import mage.remote.Session;
import mage.utils.CompressUtil;
import mage.view.*; import mage.view.*;
import mage.view.ChatMessage.MessageType; import mage.view.ChatMessage.MessageType;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -44,8 +43,8 @@ public class CallbackClientImpl implements CallbackClient {
@Override @Override
public synchronized void processCallback(final ClientCallback callback) { public synchronized void processCallback(final ClientCallback callback) {
callback.decompressData();
SaveObjectUtil.saveObject(callback.getData(), callback.getMethod().toString()); SaveObjectUtil.saveObject(callback.getData(), callback.getMethod().toString());
callback.setData(CompressUtil.decompress(callback.getData()));
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
try { try {
logger.debug(callback.getMessageId() + " -- " + callback.getMethod()); logger.debug(callback.getMessageId() + " -- " + callback.getMethod());

View file

@ -366,6 +366,20 @@
<Events> <Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFilterActionPerformed"/> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFilterActionPerformed"/>
</Events> </Events>
</Component>
<Component class="javax.swing.JToggleButton" name="btnFormatPioneer">
<Properties>
<Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" value="Pioneer"/>
<Property name="toolTipText" type="java.lang.String" value="Pioneer format."/>
<Property name="focusPainted" type="boolean" value="false"/>
<Property name="focusable" type="boolean" value="false"/>
<Property name="requestFocusEnabled" type="boolean" value="false"/>
<Property name="verifyInputWhenFocusTarget" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFilterActionPerformed"/>
</Events>
</Component> </Component>
<Component class="javax.swing.JToggleButton" name="btnFormatLegacy"> <Component class="javax.swing.JToggleButton" name="btnFormatLegacy">
<Properties> <Properties>

View file

@ -64,6 +64,9 @@ public class TablesPanel extends javax.swing.JPanel {
private static final Logger LOGGER = Logger.getLogger(TablesPanel.class); private static final Logger LOGGER = Logger.getLogger(TablesPanel.class);
private static final int[] DEFAULT_COLUMNS_WIDTH = {35, 150, 100, 50, 120, 180, 80, 120, 80, 60, 40, 40, 60}; private static final int[] DEFAULT_COLUMNS_WIDTH = {35, 150, 100, 50, 120, 180, 80, 120, 80, 60, 40, 40, 60};
// ping timeout (warning, must be less than SERVER_TIMEOUTS_USER_INFORM_OPPONENTS_ABOUT_DISCONNECT_AFTER_SECS)
public static final int PING_SERVER_SECS = 20;
// refresh timeouts for data downloads from server // refresh timeouts for data downloads from server
public static final int REFRESH_ACTIVE_TABLES_SECS = 5; public static final int REFRESH_ACTIVE_TABLES_SECS = 5;
public static final int REFRESH_FINISHED_TABLES_SECS = 30; public static final int REFRESH_FINISHED_TABLES_SECS = 30;
@ -333,7 +336,7 @@ public class TablesPanel extends javax.swing.JPanel {
filterButtons = new JToggleButton[]{btnStateWaiting, btnStateActive, btnStateFinished, filterButtons = new JToggleButton[]{btnStateWaiting, btnStateActive, btnStateFinished,
btnTypeMatch, btnTypeTourneyConstructed, btnTypeTourneyLimited, btnTypeMatch, btnTypeTourneyConstructed, btnTypeTourneyLimited,
btnFormatBlock, btnFormatStandard, btnFormatModern, btnFormatLegacy, btnFormatVintage, btnFormatPremodern, btnFormatCommander, btnFormatTinyLeader, btnFormatLimited, btnFormatOther, btnFormatBlock, btnFormatStandard, btnFormatModern, btnFormatLegacy, btnFormatVintage, btnFormatPremodern, btnFormatCommander, btnFormatTinyLeader, btnFormatLimited, btnFormatOther,
btnSkillBeginner, btnSkillCasual, btnSkillSerious, btnRated, btnUnrated, btnOpen, btnPassword, btnFormatOathbreaker}; btnSkillBeginner, btnSkillCasual, btnSkillSerious, btnRated, btnUnrated, btnOpen, btnPassword, btnFormatOathbreaker, btnFormatPioneer};
JComponent[] components = new JComponent[]{chatPanelMain, jSplitPane1, jScrollPaneTablesActive, jScrollPaneTablesFinished, jPanelTop, jPanelTables}; JComponent[] components = new JComponent[]{chatPanelMain, jSplitPane1, jScrollPaneTablesActive, jScrollPaneTablesFinished, jPanelTop, jPanelTables};
for (JComponent component : components) { for (JComponent component : components) {
@ -802,6 +805,9 @@ public class TablesPanel extends javax.swing.JPanel {
if (btnFormatModern.isSelected()) { if (btnFormatModern.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Constructed - Modern", TablesTableModel.COLUMN_DECK_TYPE)); formatFilterList.add(RowFilter.regexFilter("^Constructed - Modern", TablesTableModel.COLUMN_DECK_TYPE));
} }
if (btnFormatPioneer.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Constructed - Pioneer", TablesTableModel.COLUMN_DECK_TYPE));
}
if (btnFormatLegacy.isSelected()) { if (btnFormatLegacy.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Constructed - Legacy", TablesTableModel.COLUMN_DECK_TYPE)); formatFilterList.add(RowFilter.regexFilter("^Constructed - Legacy", TablesTableModel.COLUMN_DECK_TYPE));
} }
@ -812,7 +818,7 @@ public class TablesPanel extends javax.swing.JPanel {
formatFilterList.add(RowFilter.regexFilter("^Constructed - Premodern", TablesTableModel.COLUMN_DECK_TYPE)); formatFilterList.add(RowFilter.regexFilter("^Constructed - Premodern", TablesTableModel.COLUMN_DECK_TYPE));
} }
if (btnFormatCommander.isSelected()) { if (btnFormatCommander.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Commander|^Duel Commander|^Penny Dreadful Commander|^Freeform Commander|^MTGO 1v1 Commander|^Duel Brawl|^Brawl", TablesTableModel.COLUMN_DECK_TYPE)); formatFilterList.add(RowFilter.regexFilter("^Commander|^Duel Commander|^Centurion Commander|^Penny Dreadful Commander|^Freeform Commander|^MTGO 1v1 Commander|^Duel Brawl|^Brawl", TablesTableModel.COLUMN_DECK_TYPE));
} }
if (btnFormatTinyLeader.isSelected()) { if (btnFormatTinyLeader.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Tiny", TablesTableModel.COLUMN_DECK_TYPE)); formatFilterList.add(RowFilter.regexFilter("^Tiny", TablesTableModel.COLUMN_DECK_TYPE));
@ -965,6 +971,7 @@ public class TablesPanel extends javax.swing.JPanel {
btnFormatBlock = new javax.swing.JToggleButton(); btnFormatBlock = new javax.swing.JToggleButton();
btnFormatStandard = new javax.swing.JToggleButton(); btnFormatStandard = new javax.swing.JToggleButton();
btnFormatModern = new javax.swing.JToggleButton(); btnFormatModern = new javax.swing.JToggleButton();
btnFormatPioneer = new javax.swing.JToggleButton();
btnFormatLegacy = new javax.swing.JToggleButton(); btnFormatLegacy = new javax.swing.JToggleButton();
btnFormatVintage = new javax.swing.JToggleButton(); btnFormatVintage = new javax.swing.JToggleButton();
btnFormatPremodern = new javax.swing.JToggleButton(); btnFormatPremodern = new javax.swing.JToggleButton();
@ -1256,6 +1263,20 @@ public class TablesPanel extends javax.swing.JPanel {
}); });
filterBar2.add(btnFormatModern); filterBar2.add(btnFormatModern);
btnFormatPioneer.setSelected(true);
btnFormatPioneer.setText("Pioneer");
btnFormatPioneer.setToolTipText("Pioneer format.");
btnFormatPioneer.setFocusPainted(false);
btnFormatPioneer.setFocusable(false);
btnFormatPioneer.setRequestFocusEnabled(false);
btnFormatPioneer.setVerifyInputWhenFocusTarget(false);
btnFormatPioneer.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnFilterActionPerformed(evt);
}
});
filterBar2.add(btnFormatPioneer);
btnFormatLegacy.setSelected(true); btnFormatLegacy.setSelected(true);
btnFormatLegacy.setText("Legacy"); btnFormatLegacy.setText("Legacy");
btnFormatLegacy.setToolTipText("Legacy format."); btnFormatLegacy.setToolTipText("Legacy format.");
@ -1670,6 +1691,7 @@ public class TablesPanel extends javax.swing.JPanel {
private javax.swing.JToggleButton btnFormatLegacy; private javax.swing.JToggleButton btnFormatLegacy;
private javax.swing.JToggleButton btnFormatLimited; private javax.swing.JToggleButton btnFormatLimited;
private javax.swing.JToggleButton btnFormatModern; private javax.swing.JToggleButton btnFormatModern;
private javax.swing.JToggleButton btnFormatPioneer;
private javax.swing.JToggleButton btnFormatOathbreaker; private javax.swing.JToggleButton btnFormatOathbreaker;
private javax.swing.JToggleButton btnFormatOther; private javax.swing.JToggleButton btnFormatOther;
private javax.swing.JToggleButton btnFormatPremodern; private javax.swing.JToggleButton btnFormatPremodern;

View file

@ -20,7 +20,7 @@ public final class CardsViewUtil {
CardInfo cardInfo = CardRepository.instance.findCard(simple.getExpansionSetCode(), simple.getCardNumber()); CardInfo cardInfo = CardRepository.instance.findCard(simple.getExpansionSetCode(), simple.getCardNumber());
Card card = cardInfo != null ? cardInfo.getMockCard() : null; Card card = cardInfo != null ? cardInfo.getMockCard() : null;
if (card != null) { if (card != null) {
cards.put(simple.getId(), new CardView(card, simple.getId())); cards.put(simple.getId(), new CardView(card, simple));
} }
} }
@ -39,7 +39,7 @@ public final class CardsViewUtil {
loadedCards.put(key, card); loadedCards.put(key, card);
} }
if (card != null) { if (card != null) {
cards.put(simple.getId(), new CardView(card, simple.getId())); cards.put(simple.getId(), new CardView(card, simple));
} }
} }

View file

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

View file

@ -23,7 +23,9 @@ public class ScryfallImageSupportCards {
put("EURO", "pelp"). put("EURO", "pelp").
put("GPX", "pgpx"). put("GPX", "pgpx").
put("MED", "me1"). put("MED", "me1").
put("MEDM", "med").build(); put("MEDM", "med").
put("CELD", "eld"). // scryfall moved ELD and CELD cards in one set, but card numbers are different
build();
private static final Set<String> supportedSets = new ArraySet<String>() { private static final Set<String> supportedSets = new ArraySet<String>() {
{ {
@ -240,6 +242,8 @@ public class ScryfallImageSupportCards {
add("M20"); add("M20");
add("C19"); add("C19");
add("ELD"); add("ELD");
add("CELD");
add("THB");
// //
add("EURO"); add("EURO");
add("GPX"); add("GPX");
@ -253,6 +257,7 @@ public class ScryfallImageSupportCards {
add("SS2"); add("SS2");
add("PPP1"); add("PPP1");
add("PF19"); add("PF19");
add("MPS-AKH");
} }
}; };

View file

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

View file

@ -547,9 +547,11 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
CardDownloadData card = new CardDownloadData(params[3], set, "0", false, type, "", "", true, fileName); CardDownloadData card = new CardDownloadData(params[3], set, "0", false, type, "", "", true, fileName);
card.setTokenClassName(tokenClassName); card.setTokenClassName(tokenClassName);
list.add(card); list.add(card);
} else {
logger.error("wrong line format in tokens file: " + line);
} }
} else { } else {
logger.error("wrong format for image urls: " + line); logger.error("wrong line data in tokens file: " + line);
} }
} }
line = reader.readLine(); line = reader.readLine();

View file

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

View file

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

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

View file

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

View file

@ -1,12 +1,12 @@
package mage.interfaces.callback; package mage.interfaces.callback;
import mage.remote.traffic.ZippedObject;
import mage.utils.CompressUtil;
import java.io.Serializable; import java.io.Serializable;
import java.util.UUID; import java.util.UUID;
/** /**
*
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class ClientCallback implements Serializable { public class ClientCallback implements Serializable {
@ -16,12 +16,14 @@ public class ClientCallback implements Serializable {
private ClientCallbackMethod method; private ClientCallbackMethod method;
private int messageId; private int messageId;
public ClientCallback() {}
public ClientCallback(ClientCallbackMethod method, UUID objectId, Object data) { public ClientCallback(ClientCallbackMethod method, UUID objectId, Object data) {
this(method, objectId, data, true);
}
public ClientCallback(ClientCallbackMethod method, UUID objectId, Object data, boolean useCompress) {
this.method = method; this.method = method;
this.objectId = objectId; this.objectId = objectId;
this.data = data; this.setData(data, useCompress);
} }
public ClientCallback(ClientCallbackMethod method, UUID objectId) { public ClientCallback(ClientCallbackMethod method, UUID objectId) {
@ -42,11 +44,26 @@ public class ClientCallback implements Serializable {
} }
public Object getData() { public Object getData() {
if (this.data instanceof ZippedObject) {
throw new IllegalStateException("Client data must be decompressed first");
}
return data; return data;
} }
public void setData(Object data) { public void setData(Object data, boolean useCompress) {
if (!useCompress || data == null || data instanceof ZippedObject) {
this.data = data; this.data = data;
} else {
this.data = CompressUtil.compress(data);
}
this.data = data;
}
public void decompressData() {
if (this.data instanceof ZippedObject) {
this.data = CompressUtil.decompress(this.data);
}
} }
public ClientCallbackMethod getMethod() { public ClientCallbackMethod getMethod() {

View file

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

View file

@ -14,7 +14,7 @@ public final class CompressUtil {
* Defines should data be compressed or not. True by default. Read from * Defines should data be compressed or not. True by default. Read from
* system property: * system property:
*/ */
private static boolean compressData = true; private static boolean compressData;
/** /**
* Defines the system property name to disable any compressing. * Defines the system property name to disable any compressing.

View file

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

View file

@ -32,7 +32,7 @@ import java.util.stream.Collectors;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class CardView extends SimpleCardView implements SelectableObjectView { public class CardView extends SimpleCardView {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -104,9 +104,6 @@ public class CardView extends SimpleCardView implements SelectableObjectView {
protected boolean rotate; protected boolean rotate;
protected boolean hideInfo; // controls if the tooltip window is shown (eg. controlled face down morph card) protected boolean hideInfo; // controls if the tooltip window is shown (eg. controlled face down morph card)
protected boolean isPlayable;
protected boolean isChoosable;
protected boolean selected;
protected boolean canAttack; protected boolean canAttack;
protected boolean canBlock; protected boolean canBlock;
protected boolean inViewerOnly; protected boolean inViewerOnly;
@ -117,9 +114,13 @@ public class CardView extends SimpleCardView implements SelectableObjectView {
this(card, null, false); this(card, null, false);
} }
public CardView(Card card, UUID cardId) { public CardView(Card card, SimpleCardView simpleCardView) {
this(card, null, false); this(card, null, false);
this.id = cardId; this.id = simpleCardView.getId();
this.isPlayable = simpleCardView.isPlayable;
this.isChoosable = simpleCardView.isChoosable;
this.isSelected = simpleCardView.isSelected;
} }
public CardView(Card card, Game game, UUID cardId) { public CardView(Card card, Game game, UUID cardId) {
@ -128,10 +129,12 @@ public class CardView extends SimpleCardView implements SelectableObjectView {
} }
public CardView(CardView cardView) { public CardView(CardView cardView) {
super(cardView.id, cardView.expansionSetCode, cardView.cardNumber, cardView.usesVariousArt, cardView.tokenSetCode, cardView.gameObject, cardView.tokenDescriptor); super(cardView);
this.originalCard = cardView.originalCard; this.originalCard = cardView.originalCard;
// generetate new ID
this.id = UUID.randomUUID(); this.id = UUID.randomUUID();
this.parentId = cardView.parentId; this.parentId = cardView.parentId;
this.name = cardView.name; this.name = cardView.name;
this.displayName = cardView.displayName; this.displayName = cardView.displayName;
@ -198,9 +201,6 @@ public class CardView extends SimpleCardView implements SelectableObjectView {
this.rotate = cardView.rotate; this.rotate = cardView.rotate;
this.hideInfo = cardView.hideInfo; this.hideInfo = cardView.hideInfo;
this.isPlayable = cardView.isPlayable;
this.isChoosable = cardView.isChoosable;
this.selected = cardView.selected;
this.canAttack = cardView.canAttack; this.canAttack = cardView.canAttack;
this.canBlock = cardView.canBlock; this.canBlock = cardView.canBlock;
this.inViewerOnly = cardView.inViewerOnly; this.inViewerOnly = cardView.inViewerOnly;
@ -468,8 +468,6 @@ public class CardView extends SimpleCardView implements SelectableObjectView {
// Get starting loyalty // Get starting loyalty
this.startingLoyalty = "" + card.getStartingLoyalty(); this.startingLoyalty = "" + card.getStartingLoyalty();
} }
public CardView(MageObject object) { public CardView(MageObject object) {
@ -964,30 +962,6 @@ public class CardView extends SimpleCardView implements SelectableObjectView {
return hideInfo; return hideInfo;
} }
public boolean isPlayable() {
return isPlayable;
}
public void setPlayable(boolean isPlayable) {
this.isPlayable = isPlayable;
}
public boolean isChoosable() {
return isChoosable;
}
public void setChoosable(boolean isChoosable) {
this.isChoosable = isChoosable;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
public boolean isCanAttack() { public boolean isCanAttack() {
return canAttack; return canAttack;
} }

View file

@ -17,6 +17,7 @@ public class EmblemView implements CommandObjectView, Serializable {
protected String expansionSetCode; protected String expansionSetCode;
protected List<String> rules; protected List<String> rules;
protected boolean isPlayable = false; protected boolean isPlayable = false;
protected int playableAmount = 0;
public EmblemView(Emblem emblem, Card sourceCard) { public EmblemView(Emblem emblem, Card sourceCard) {
this.id = emblem.getId(); this.id = emblem.getId();
@ -67,6 +68,16 @@ public class EmblemView implements CommandObjectView, Serializable {
this.isPlayable = isPlayable; this.isPlayable = isPlayable;
} }
@Override
public void setPlayableAmount(int playableAmount) {
this.playableAmount = playableAmount;
}
@Override
public int getPlayableAmount() {
return playableAmount;
}
@Override @Override
public boolean isChoosable() { public boolean isChoosable() {
// unsupported // unsupported
@ -85,7 +96,7 @@ public class EmblemView implements CommandObjectView, Serializable {
} }
@Override @Override
public void setSelected(boolean selected) { public void setSelected(boolean isSelected) {
// unsupported // unsupported
} }
} }

View file

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

View file

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

View file

@ -18,6 +18,7 @@ public class PlaneView implements CommandObjectView, Serializable {
protected List<String> rules; protected List<String> rules;
protected boolean isPlayable = false; protected boolean isPlayable = false;
protected int playableAmount = 0;
public PlaneView(Plane plane, Card sourceCard) { public PlaneView(Plane plane, Card sourceCard) {
this.id = plane.getId(); this.id = plane.getId();
@ -67,6 +68,16 @@ public class PlaneView implements CommandObjectView, Serializable {
this.isPlayable = isPlayable; this.isPlayable = isPlayable;
} }
@Override
public void setPlayableAmount(int playableAmount) {
this.playableAmount = playableAmount;
}
@Override
public int getPlayableAmount() {
return playableAmount;
}
@Override @Override
public boolean isChoosable() { public boolean isChoosable() {
// unsupported // unsupported
@ -85,7 +96,7 @@ public class PlaneView implements CommandObjectView, Serializable {
} }
@Override @Override
public void setSelected(boolean selected) { public void setSelected(boolean isSelected) {
// unsupported // unsupported
} }
} }

View file

@ -9,11 +9,15 @@ public interface SelectableObjectView {
void setPlayable(boolean isPlayable); void setPlayable(boolean isPlayable);
void setPlayableAmount(int playableAmount);
int getPlayableAmount();
boolean isChoosable(); boolean isChoosable();
void setChoosable(boolean isChoosable); void setChoosable(boolean isChoosable);
boolean isSelected(); boolean isSelected();
void setSelected(boolean selected); void setSelected(boolean isSelected);
} }

View file

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

View file

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

View file

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

View file

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

View file

@ -67,7 +67,7 @@ public class ConsoleFrame extends javax.swing.JFrame implements MageClient {
logger.fatal("", ex); logger.fatal("", ex);
} }
pingTaskExecutor.scheduleAtFixedRate(() -> session.ping(), 60, 60, TimeUnit.SECONDS); pingTaskExecutor.scheduleAtFixedRate(() -> session.ping(), 20, 20, TimeUnit.SECONDS);
} }
public boolean connect(Connection connection) { public boolean connect(Connection connection) {

View file

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

View file

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

View file

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

View file

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

View file

@ -22,8 +22,7 @@ public class Brawl extends Constructed {
// Copy of standard sets // Copy of standard sets
setCodes.addAll(Standard.makeLegalSets()); setCodes.addAll(Standard.makeLegalSets());
banned.add("Baral, Chief of Compliance"); banned.add("Oko, Thief of Crowns");
banned.add("Smuggler's Copter");
banned.add("Sorcerous Spyglass"); banned.add("Sorcerous Spyglass");
} }
@ -49,14 +48,7 @@ public class Brawl extends Constructed {
Map<String, Integer> counts = new HashMap<>(); Map<String, Integer> counts = new HashMap<>();
countCards(counts, deck.getCards()); countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard()); countCards(counts, deck.getSideboard());
for (Map.Entry<String, Integer> entry : counts.entrySet()) { valid = checkCounts(1, counts) && valid;
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
for (String bannedCard : banned) { for (String bannedCard : banned) {
if (counts.containsKey(bannedCard)) { if (counts.containsKey(bannedCard)) {

View file

@ -20,7 +20,8 @@ public class CanadianHighlander extends Constructed {
pointMap.put("Balance", 1); pointMap.put("Balance", 1);
pointMap.put("Birthing Pod", 2); pointMap.put("Birthing Pod", 2);
pointMap.put("Black Lotus", 7); pointMap.put("Black Lotus", 7);
pointMap.put("Demonic Tutor", 3); pointMap.put("Crop Rotation", 1);
pointMap.put("Demonic Tutor", 4);
pointMap.put("Dig Through Time", 1); pointMap.put("Dig Through Time", 1);
pointMap.put("Enlightened Tutor", 1); pointMap.put("Enlightened Tutor", 1);
pointMap.put("Flash", 6); pointMap.put("Flash", 6);
@ -28,7 +29,7 @@ public class CanadianHighlander extends Constructed {
pointMap.put("Imperial Seal", 1); pointMap.put("Imperial Seal", 1);
pointMap.put("Intuition", 1); pointMap.put("Intuition", 1);
pointMap.put("Library of Alexandria", 1); pointMap.put("Library of Alexandria", 1);
pointMap.put("Mana Crypt", 3); pointMap.put("Mana Crypt", 4);
pointMap.put("Mana Drain", 1); pointMap.put("Mana Drain", 1);
pointMap.put("Mana Vault", 1); pointMap.put("Mana Vault", 1);
pointMap.put("Merchant Scroll", 1); pointMap.put("Merchant Scroll", 1);
@ -41,7 +42,7 @@ public class CanadianHighlander extends Constructed {
pointMap.put("Mystical Tutor", 2); pointMap.put("Mystical Tutor", 2);
pointMap.put("Natural Order", 4); pointMap.put("Natural Order", 4);
pointMap.put("Protean Hulk", 3); pointMap.put("Protean Hulk", 3);
pointMap.put("Sol Ring", 3); pointMap.put("Sol Ring", 4);
pointMap.put("Spellseeker", 1); pointMap.put("Spellseeker", 1);
pointMap.put("Stoneforge Mystic", 1); pointMap.put("Stoneforge Mystic", 1);
pointMap.put("Strip Mine", 2); pointMap.put("Strip Mine", 2);
@ -88,14 +89,7 @@ public class CanadianHighlander extends Constructed {
Map<String, Integer> counts = new HashMap<>(); Map<String, Integer> counts = new HashMap<>();
countCards(counts, deck.getCards()); countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard()); countCards(counts, deck.getSideboard());
for (Map.Entry<String, Integer> entry : counts.entrySet()) { valid = checkCounts(1, counts) && valid;
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
int allowedPoints = 10; int allowedPoints = 10;
int totalPoints = 0; int totalPoints = 0;

View file

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

View file

@ -21,7 +21,8 @@ import java.util.*;
*/ */
public class Commander extends Constructed { public class Commander extends Constructed {
protected List<String> bannedCommander = new ArrayList<>(); protected final List<String> bannedCommander = new ArrayList<>();
protected final List<String> bannedPartner = new ArrayList<>();
protected boolean partnerAllowed = true; protected boolean partnerAllowed = true;
public Commander() { public Commander() {
@ -99,14 +100,7 @@ public class Commander extends Constructed {
Map<String, Integer> counts = new HashMap<>(); Map<String, Integer> counts = new HashMap<>();
countCards(counts, deck.getCards()); countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard()); countCards(counts, deck.getSideboard());
for (Map.Entry<String, Integer> entry : counts.entrySet()) { valid = checkCounts(1, counts) && valid;
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
for (String bannedCard : banned) { for (String bannedCard : banned) {
if (counts.containsKey(bannedCard)) { if (counts.containsKey(bannedCard)) {
@ -136,20 +130,25 @@ public class Commander extends Constructed {
invalid.put("Commander", "Commander invalid (" + commander.getName() + ')'); invalid.put("Commander", "Commander invalid (" + commander.getName() + ')');
valid = false; valid = false;
} }
if (deck.getSideboard().size() == 2 && !commander.getAbilities().contains(PartnerAbility.getInstance())) { if (deck.getSideboard().size() == 2) {
boolean partnersWith = false; if (commander.getAbilities().contains(PartnerAbility.getInstance())) {
for (Ability ability : commander.getAbilities()) { if (bannedPartner.contains(commander.getName())) {
if (ability instanceof PartnerWithAbility invalid.put("Commander", "Partner banned (" + commander.getName() + ')');
&& commanderNames.contains(((PartnerWithAbility) ability).getPartnerName())) { valid = false;
partnersWith = true;
break;
}
} }
} else {
boolean partnersWith = commander.getAbilities()
.stream()
.filter(PartnerWithAbility.class::isInstance)
.map(PartnerWithAbility.class::cast)
.map(PartnerWithAbility::getPartnerName)
.anyMatch(commanderNames::contains);
if (!partnersWith) { if (!partnersWith) {
invalid.put("Commander", "Commander without Partner (" + commander.getName() + ')'); invalid.put("Commander", "Commander without Partner (" + commander.getName() + ')');
valid = false; valid = false;
} }
} }
}
ManaUtil.collectColorIdentity(colorIdentity, commander.getColorIdentity()); ManaUtil.collectColorIdentity(colorIdentity, commander.getColorIdentity());
} }
} }

View file

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

View file

@ -59,14 +59,7 @@ public class FreeformCommander extends Constructed {
countCards(counts, deck.getCards()); countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard()); countCards(counts, deck.getSideboard());
for (Map.Entry<String, Integer> entry : counts.entrySet()) { valid = checkCounts(1, counts) && valid;
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
if (deck.getSideboard().isEmpty() || deck.getSideboard().size() > 2) { if (deck.getSideboard().isEmpty() || deck.getSideboard().size() > 2) {
invalid.put("Commander", "Sideboard must contain only the commander(s)"); invalid.put("Commander", "Sideboard must contain only the commander(s)");

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -52,7 +52,6 @@ public class Oathbreaker extends Vintage {
banned.add("Painter's Servant"); banned.add("Painter's Servant");
banned.add("Panoptic Mirror"); banned.add("Panoptic Mirror");
banned.add("Primal Surge"); banned.add("Primal Surge");
banned.add("Recurring Nightmare");
banned.add("Saheeli, the Gifted"); banned.add("Saheeli, the Gifted");
banned.add("Sol Ring"); banned.add("Sol Ring");
banned.add("Sundering Titan"); banned.add("Sundering Titan");
@ -99,14 +98,7 @@ public class Oathbreaker extends Vintage {
} }
} }
for (Map.Entry<String, Integer> entry : counts.entrySet()) { valid = checkCounts(1, counts) && valid;
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
Set<String> commanderNames = new HashSet<>(); Set<String> commanderNames = new HashSet<>();
Set<String> signatureSpells = new HashSet<>(); Set<String> signatureSpells = new HashSet<>();

View file

@ -21,6 +21,7 @@ public class Pauper extends Constructed {
rarities.add(Rarity.COMMON); rarities.add(Rarity.COMMON);
rarities.add(Rarity.LAND); rarities.add(Rarity.LAND);
banned.add("Arcum's Astrolabe");
banned.add("Cloud of Faeries"); banned.add("Cloud of Faeries");
banned.add("Cloudpost"); banned.add("Cloudpost");
banned.add("Cranial Plating"); banned.add("Cranial Plating");

View file

@ -0,0 +1,41 @@
package mage.deck;
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;
/**
* @author TheElk801
*/
public class Pioneer extends Constructed {
public Pioneer() {
super("Constructed - Pioneer");
Date cutoff = new GregorianCalendar(2012, Calendar.OCTOBER, 5).getTime(); // RTR release date
for (ExpansionSet set : Sets.getInstance().values()) {
if (set.getSetType().isStandardLegal() && (set.getReleaseDate().after(cutoff) || set.getReleaseDate().equals(cutoff))) {
setCodes.add(set.getCode());
}
}
banned.add("Bloodstained Mire");
banned.add("Flooded Strand");
banned.add("Polluted Delta");
banned.add("Windswept Heath");
banned.add("Wooded Foothills");
banned.add("Felidar Guardian");
banned.add("Field of the Dead");
banned.add("Leyline of Abundance");
banned.add("Nexus of Fate");
banned.add("Oath of Nissa");
banned.add("Oko, Thief of Crowns");
banned.add("Once Upon a Time");
banned.add("Smuggler's Copter");
banned.add("Veil of Summer");
}
}

View file

@ -54,7 +54,6 @@ public class Premodern extends Constructed {
banned.add("Entomb"); banned.add("Entomb");
banned.add("Flash"); banned.add("Flash");
banned.add("Force of Will"); banned.add("Force of Will");
banned.add("Frantic Search");
banned.add("Goblin Recruiter"); banned.add("Goblin Recruiter");
banned.add("Grim Monolith"); banned.add("Grim Monolith");
banned.add("Jeweled Bird"); banned.add("Jeweled Bird");
@ -76,5 +75,6 @@ public class Premodern extends Constructed {
banned.add("Windfall"); banned.add("Windfall");
banned.add("Worldgorger Dragon"); banned.add("Worldgorger Dragon");
banned.add("Yawgmoth's Will"); banned.add("Yawgmoth's Will");
banned.add("Yawgmoth's Bargain");
} }
} }

View file

@ -12,9 +12,9 @@ public class ReturnToRavnicaBlock extends Constructed {
public ReturnToRavnicaBlock() { public ReturnToRavnicaBlock() {
super("Constructed - Return to Ravnica Block"); super("Constructed - Return to Ravnica Block");
setCodes.add("RTR"); setCodes.add(mage.sets.ReturnToRavnica.getInstance().getCode());
setCodes.add("GTC"); setCodes.add(mage.sets.Gatecrash.getInstance().getCode());
setCodes.add("DGM"); setCodes.add(mage.sets.DragonsMaze.getInstance().getCode());
} }
} }

View file

@ -12,9 +12,9 @@ public class ScarsOfMirrodinBlock extends Constructed {
public ScarsOfMirrodinBlock() { public ScarsOfMirrodinBlock() {
super("Constructed - Scars of Mirrodin Block"); super("Constructed - Scars of Mirrodin Block");
setCodes.add("SOM"); setCodes.add(mage.sets.ScarsOfMirrodin.getInstance().getCode());
setCodes.add("MBS"); setCodes.add(mage.sets.MirrodinBesieged.getInstance().getCode());
setCodes.add("NPH"); setCodes.add(mage.sets.NewPhyrexia.getInstance().getCode());
} }
} }

View file

@ -12,8 +12,8 @@ public class ShadowmoorBlock extends Constructed {
public ShadowmoorBlock() { public ShadowmoorBlock() {
super("Constructed - Shadowmoor Block"); super("Constructed - Shadowmoor Block");
setCodes.add("SHM"); setCodes.add(mage.sets.Shadowmoor.getInstance().getCode());
setCodes.add("EVE"); setCodes.add(mage.sets.Eventide.getInstance().getCode());
} }
} }

View file

@ -12,7 +12,7 @@ public class ShadowsOverInnistradBlock extends Constructed {
public ShadowsOverInnistradBlock() { public ShadowsOverInnistradBlock() {
super("Constructed - Shadows over Innistrad Block"); super("Constructed - Shadows over Innistrad Block");
setCodes.add("SOI"); setCodes.add(mage.sets.ShadowsOverInnistrad.getInstance().getCode());
setCodes.add("EDM"); setCodes.add(mage.sets.EldritchMoon.getInstance().getCode());
} }
} }

View file

@ -12,9 +12,9 @@ public class ShardsOfAlaraBlock extends Constructed {
public ShardsOfAlaraBlock() { public ShardsOfAlaraBlock() {
super("Constructed - Shards of Alara Block"); super("Constructed - Shards of Alara Block");
setCodes.add("ALA"); setCodes.add(mage.sets.ShardsOfAlara.getInstance().getCode());
setCodes.add("CON"); setCodes.add(mage.sets.Conflux.getInstance().getCode());
setCodes.add("ARB"); setCodes.add(mage.sets.AlaraReborn.getInstance().getCode());
} }
} }

View file

@ -17,7 +17,10 @@ public class Standard extends Constructed {
setCodes.addAll(makeLegalSets()); setCodes.addAll(makeLegalSets());
banned.add("Rampaging Ferocidon"); // since 2018-01-15 banned.add("Field of the Dead");
banned.add("Oko, Thief of Crowns");
banned.add("Once Upon a Time");
banned.add("Veil of Summer");
} }
private static boolean isFallSet(ExpansionSet set) { private static boolean isFallSet(ExpansionSet set) {
@ -27,7 +30,7 @@ public class Standard extends Constructed {
return set.getSetType() == SetType.EXPANSION && (cal.get(Calendar.MONTH) > 7); return set.getSetType() == SetType.EXPANSION && (cal.get(Calendar.MONTH) > 7);
} }
public static List<String> makeLegalSets() { static List<String> makeLegalSets() {
List<String> codes = new ArrayList<>(); List<String> codes = new ArrayList<>();
GregorianCalendar current = new GregorianCalendar(); GregorianCalendar current = new GregorianCalendar();
List<ExpansionSet> sets = new ArrayList(Sets.getInstance().values()); List<ExpansionSet> sets = new ArrayList(Sets.getInstance().values());

View file

@ -15,7 +15,7 @@ public class StarWarsBlock extends Constructed {
public StarWarsBlock() { public StarWarsBlock() {
super("Constructed Custom - Star Wars Block"); super("Constructed Custom - Star Wars Block");
setCodes.add("SWS"); setCodes.add(mage.sets.StarWars.getInstance().getCode());
} }
} }

View file

@ -26,7 +26,7 @@ public class SuperType2 extends Constructed {
* Kamigawa/Ravnica standard, where rotation stabilized. * Kamigawa/Ravnica standard, where rotation stabilized.
* Data taken from http://thattournament.website/historic-tournament.php * Data taken from http://thattournament.website/historic-tournament.php
*/ */
protected static final String[][] standards = { private static final String[][] standards = {
// 11th Standard // 11th Standard
{"7ED", "INV", "APC", "PLS", "ODY", "TOR", "JUD"}, {"7ED", "INV", "APC", "PLS", "ODY", "TOR", "JUD"},
// 12th Standard // 12th Standard
@ -72,7 +72,7 @@ public class SuperType2 extends Constructed {
* regular validation function to test validity. * regular validation function to test validity.
* *
* @param deck - the deck to validate. * @param deck - the deck to validate.
* @return * @return boolean if valid deck
*/ */
@Override @Override
public boolean validate(Deck deck) { public boolean validate(Deck deck) {

View file

@ -12,9 +12,9 @@ public class TherosBlock extends Constructed {
public TherosBlock() { public TherosBlock() {
super("Constructed - Theros Block"); super("Constructed - Theros Block");
setCodes.add("THS"); setCodes.add(mage.sets.Theros.getInstance().getCode());
setCodes.add("BNG"); setCodes.add(mage.sets.BornOfTheGods.getInstance().getCode());
setCodes.add("JOU"); setCodes.add(mage.sets.JourneyIntoNyx.getInstance().getCode());
} }
} }

View file

@ -76,6 +76,10 @@ public class TinyLeaders extends Constructed {
banned.add("Wheel of Fortune"); banned.add("Wheel of Fortune");
banned.add("Yawgmoth's Will"); banned.add("Yawgmoth's Will");
// TODO: Karn Liberated can't be used in TinyLeaders game (wrong commanders init like missing watchers)
// GameTinyLeadersImpl must extends GameCommanderImpl, not GameImpl
banned.add("Karn Liberated");
//Additionally, these Legendary creatures cannot be used as Commanders //Additionally, these Legendary creatures cannot be used as Commanders
bannedCommander.add("Erayo, Soratami Ascendant"); bannedCommander.add("Erayo, Soratami Ascendant");
bannedCommander.add("Rofellos, Llanowar Emissary"); bannedCommander.add("Rofellos, Llanowar Emissary");
@ -113,14 +117,7 @@ public class TinyLeaders extends Constructed {
counts.put(deck.getName(), 1); // add the commander to the counts, so it can't be in the deck or sideboard again counts.put(deck.getName(), 1); // add the commander to the counts, so it can't be in the deck or sideboard again
countCards(counts, deck.getCards()); countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard()); countCards(counts, deck.getSideboard());
for (Map.Entry<String, Integer> entry : counts.entrySet()) { valid = checkCounts(1, counts) && valid;
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
for (String bannedCard : banned) { for (String bannedCard : banned) {
if (counts.containsKey(bannedCard)) { if (counts.containsKey(bannedCard)) {

View file

@ -51,11 +51,12 @@ public class Vintage extends Constructed {
restricted.add("Demonic Consultation"); restricted.add("Demonic Consultation");
restricted.add("Demonic Tutor"); restricted.add("Demonic Tutor");
restricted.add("Dig Through Time"); restricted.add("Dig Through Time");
restricted.add("Fastbond");
restricted.add("Flash"); restricted.add("Flash");
restricted.add("Gitaxian Probe"); restricted.add("Gitaxian Probe");
restricted.add("Golgari Grave-Troll");
restricted.add("Gush"); restricted.add("Gush");
restricted.add("Imperial Seal"); restricted.add("Imperial Seal");
restricted.add("Karn, the Great Creator");
restricted.add("Library of Alexandria"); restricted.add("Library of Alexandria");
restricted.add("Lion's Eye Diamond"); restricted.add("Lion's Eye Diamond");
restricted.add("Lodestone Golem"); restricted.add("Lodestone Golem");
@ -63,6 +64,7 @@ public class Vintage extends Constructed {
restricted.add("Mana Crypt"); restricted.add("Mana Crypt");
restricted.add("Mana Vault"); restricted.add("Mana Vault");
restricted.add("Memory Jar"); restricted.add("Memory Jar");
restricted.add("Mental Misstep");
restricted.add("Merchant Scroll"); restricted.add("Merchant Scroll");
restricted.add("Mind's Desire"); restricted.add("Mind's Desire");
restricted.add("Monastery Mentory"); restricted.add("Monastery Mentory");
@ -71,7 +73,9 @@ public class Vintage extends Constructed {
restricted.add("Mox Pearl"); restricted.add("Mox Pearl");
restricted.add("Mox Ruby"); restricted.add("Mox Ruby");
restricted.add("Mox Sapphire"); restricted.add("Mox Sapphire");
restricted.add("Mystic Forge");
restricted.add("Mystical Tutor"); restricted.add("Mystical Tutor");
restricted.add("Narset, Parter of Veils");
restricted.add("Necropotence"); restricted.add("Necropotence");
restricted.add("Ponder"); restricted.add("Ponder");
restricted.add("Sol Ring"); restricted.add("Sol Ring");

View file

@ -15,9 +15,9 @@ public class ZendikarBlock extends Constructed {
public ZendikarBlock() { public ZendikarBlock() {
super("Constructed - Zendikar Block"); super("Constructed - Zendikar Block");
setCodes.add("ZEN"); setCodes.add(mage.sets.Zendikar.getInstance().getCode());
setCodes.add("WWK"); setCodes.add(mage.sets.Worldwake.getInstance().getCode());
setCodes.add("ROE"); setCodes.add(mage.sets.RiseOfTheEldrazi.getInstance().getCode());
} }
} }

View file

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

View file

@ -3,6 +3,9 @@ package mage.deck;
import mage.cards.decks.Deck; import mage.cards.decks.Deck;
import mage.cards.decks.DeckValidator; import mage.cards.decks.DeckValidator;
import java.util.HashMap;
import java.util.Map;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
@ -29,9 +32,15 @@ public class Limited extends DeckValidator {
if (deck.getCards().size() < getDeckMinSize()) { if (deck.getCards().size() < getDeckMinSize()) {
invalid.put("Deck", "Must contain at least " + getDeckMinSize() + " cards: has only " + deck.getCards().size() + " cards"); invalid.put("Deck", "Must contain at least " + getDeckMinSize() + " cards: has only " + deck.getCards().size() + " cards");
valid = false; valid = false;
}
Map<String, Integer> counts = new HashMap<>();
countCards(counts, deck.getCards());
for (Map.Entry<String, Integer> entry : counts.entrySet()) {
if (entry.getValue() > 7 && entry.getKey().equals("Seven Dwarves")) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
} }
return valid; return valid;
} }
} }

View file

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId> <artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version> <version>1.4.41</version>
</parent> </parent>
<artifactId>mage-game-brawlduel</artifactId> <artifactId>mage-game-brawlduel</artifactId>

View file

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId> <artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version> <version>1.4.41</version>
</parent> </parent>
<artifactId>mage-game-brawlfreeforall</artifactId> <artifactId>mage-game-brawlfreeforall</artifactId>

View file

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId> <artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version> <version>1.4.41</version>
</parent> </parent>
<artifactId>mage-game-canadianhighlanderduel</artifactId> <artifactId>mage-game-canadianhighlanderduel</artifactId>

View file

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId> <artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version> <version>1.4.41</version>
</parent> </parent>
<artifactId>mage-game-commanderduel</artifactId> <artifactId>mage-game-commanderduel</artifactId>

View file

@ -22,7 +22,7 @@ public class CommanderDuelMatch extends MatchImpl {
startLife = 20; // Starting with the Commander 2016 update (on November 11th, 2016), Duel Commander will be played with 20 life points instead of 30. startLife = 20; // Starting with the Commander 2016 update (on November 11th, 2016), Duel Commander will be played with 20 life points instead of 30.
checkCommanderDamage = false; // since nov 16 duel commander uses no longer commander damage rule checkCommanderDamage = false; // since nov 16 duel commander uses no longer commander damage rule
} }
if (options.getDeckType().equals("Variant Magic - MTGO 1v1 Commander")) { if (options.getDeckType().equals("Variant Magic - MTGO 1v1 Commander") || options.getDeckType().equals("Variant Magic - Centurion Commander")) {
startLife = 30; startLife = 30;
} }
Mulligan mulligan = options.getMulliganType().getMulligan(options.getFreeMulligans()); Mulligan mulligan = options.getMulliganType().getMulligan(options.getFreeMulligans());

View file

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId> <artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version> <version>1.4.41</version>
</parent> </parent>
<artifactId>mage-game-commanderfreeforall</artifactId> <artifactId>mage-game-commanderfreeforall</artifactId>

View file

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId> <artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version> <version>1.4.41</version>
</parent> </parent>
<artifactId>mage-game-freeforall</artifactId> <artifactId>mage-game-freeforall</artifactId>

View file

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId> <artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version> <version>1.4.41</version>
</parent> </parent>
<artifactId>mage-game-freeformcommanderduel</artifactId> <artifactId>mage-game-freeformcommanderduel</artifactId>

View file

@ -15,7 +15,7 @@ public class FreeformCommanderDuelMatch extends MatchImpl {
@Override @Override
public void startGame() throws GameException { public void startGame() throws GameException {
int startLife = 20; int startLife = 40;
Mulligan mulligan = options.getMulliganType().getMulligan(options.getFreeMulligans()); Mulligan mulligan = options.getMulliganType().getMulligan(options.getFreeMulligans());
FreeformCommanderDuel game = new FreeformCommanderDuel(options.getAttackOption(), options.getRange(), mulligan, startLife); FreeformCommanderDuel game = new FreeformCommanderDuel(options.getAttackOption(), options.getRange(), mulligan, startLife);

View file

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId> <artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version> <version>1.4.41</version>
</parent> </parent>
<artifactId>mage-game-freeformcommanderfreeforall</artifactId> <artifactId>mage-game-freeformcommanderfreeforall</artifactId>

View file

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId> <artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version> <version>1.4.41</version>
</parent> </parent>
<artifactId>mage-game-momirduel</artifactId> <artifactId>mage-game-momirduel</artifactId>

View file

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId> <artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version> <version>1.4.41</version>
</parent> </parent>
<artifactId>mage-game-momirfreeforall</artifactId> <artifactId>mage-game-momirfreeforall</artifactId>

View file

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId> <artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version> <version>1.4.41</version>
</parent> </parent>
<artifactId>mage-game-oathbreakerduel</artifactId> <artifactId>mage-game-oathbreakerduel</artifactId>
@ -22,7 +22,7 @@
<dependency> <dependency>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-game-oathbreakerfreeforall</artifactId> <artifactId>mage-game-oathbreakerfreeforall</artifactId>
<version>1.4.37</version> <version>1.4.41</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View file

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId> <artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version> <version>1.4.41</version>
</parent> </parent>
<artifactId>mage-game-oathbreakerfreeforall</artifactId> <artifactId>mage-game-oathbreakerfreeforall</artifactId>

View file

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId> <artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version> <version>1.4.41</version>
</parent> </parent>
<artifactId>mage-game-pennydreadfulcommanderfreeforall</artifactId> <artifactId>mage-game-pennydreadfulcommanderfreeforall</artifactId>

View file

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId> <artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version> <version>1.4.41</version>
</parent> </parent>
<artifactId>mage-game-tinyleadersduel</artifactId> <artifactId>mage-game-tinyleadersduel</artifactId>

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