Merge pull request #87 from magefree/master

Merge https://github.com/magefree/mage
This commit is contained in:
L_J 2019-01-20 02:29:42 +01:00 committed by GitHub
commit dd585c174f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
650 changed files with 4977 additions and 3030 deletions

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.32</version>
<version>1.4.33</version>
</parent>
<groupId>org.mage</groupId>

View file

@ -1,22 +1,22 @@
NAME:Douglas Scheinberg's Séance Combo
1 [AVR:42] Alchemist's Apprentice
4 [RTR:1] Angel of Serenity
1 [ISD:68] Mirror-Mad Phantasm
2 [ISD:248] Sulfur Falls
4 [RTR:249] Transguild Promenade
3 [RTR:247] Steam Vents
1 [AVR:1] Angel of Glory's Rise
4 [ISD:122] Unburial Rites
4 [RTR:201] Supreme Verdict
1 [ISD:55] Forbidden Alchemy
1 [ISD:61] Laboratory Maniac
3 [ISD:238] Clifftop Retreat
3 [ISD:43] Armored Skaab
2 [GTC:245] Sacred Foundry
4 [M13:69] Sphinx of Uthuun
3 [M13:225] Glacial Fortress
4 [RTR:172] Izzet Charm
2 [AVR:229] Slayers' Stronghold
2 [AVR:226] Cavern of Souls
4 [DKA:87] Faithless Looting
4 [RTR:241] Hallowed Fountain
NAME:Douglas Scheinberg's Séance Combo
1 [AVR:42] Alchemist's Apprentice
4 [RTR:1] Angel of Serenity
1 [ISD:68] Mirror-Mad Phantasm
2 [ISD:248] Sulfur Falls
4 [RTR:249] Transguild Promenade
3 [RTR:247] Steam Vents
1 [AVR:1] Angel of Glory's Rise
4 [ISD:122] Unburial Rites
4 [RTR:201] Supreme Verdict
1 [ISD:55] Forbidden Alchemy
1 [ISD:61] Laboratory Maniac
3 [ISD:238] Clifftop Retreat
3 [ISD:43] Armored Skaab
2 [GTC:245] Sacred Foundry
4 [M13:69] Sphinx of Uthuun
3 [M13:225] Glacial Fortress
4 [RTR:172] Izzet Charm
2 [AVR:229] Slayers' Stronghold
2 [AVR:226] Cavern of Souls
4 [DKA:87] Faithless Looting
4 [RTR:241] Hallowed Fountain

View file

@ -1,31 +1,31 @@
NAME:Emmanuel Ramírez's Reanimator
4 [ISD:170] Avacyn's Pilgrim
2 [ISD:249] Woodland Cemetery
3 [M13:159] Acidic Slime
3 [ISD:196] Mulch
1 [ISD:239] Gavony Township
3 [ISD:15] Fiend Hunter
3 [RTR:1] Angel of Serenity
2 [AVR:226] Cavern of Souls
4 [AVR:32] Restoration Angel
2 [ISD:242] Isolated Chapel
4 [RTR:248] Temple Garden
4 [RTR:243] Overgrown Tomb
3 [M13:160] Arbor Elf
4 [M13:193] Thragtusk
2 [DGM:103] Sin Collector
4 [RTR:165] Grisly Salvage
3 [M13:229] Sunpetal Grove
3 [RTR:270] Forest
2 [GTC:242] Godless Shrine
4 [ISD:122] Unburial Rites
SB: 1 [RTR:148] Centaur Healer
SB: 2 [DKA:17] Ray of Revelation
SB: 1 [M13:159] Acidic Slime
SB: 2 [ISD:181] Garruk Relentless
SB: 2 [RTR:141] Abrupt Decay
SB: 1 [ISD:15] Fiend Hunter
SB: 2 [RTR:213] Deathrite Shaman
SB: 1 [DGM:103] Sin Collector
SB: 2 [RTR:178] Loxodon Smiter
SB: 1 [ISD:115] Sever the Bloodline
NAME:Emmanuel Ramírez's Reanimator
4 [ISD:170] Avacyn's Pilgrim
2 [ISD:249] Woodland Cemetery
3 [M13:159] Acidic Slime
3 [ISD:196] Mulch
1 [ISD:239] Gavony Township
3 [ISD:15] Fiend Hunter
3 [RTR:1] Angel of Serenity
2 [AVR:226] Cavern of Souls
4 [AVR:32] Restoration Angel
2 [ISD:242] Isolated Chapel
4 [RTR:248] Temple Garden
4 [RTR:243] Overgrown Tomb
3 [M13:160] Arbor Elf
4 [M13:193] Thragtusk
2 [DGM:103] Sin Collector
4 [RTR:165] Grisly Salvage
3 [M13:229] Sunpetal Grove
3 [RTR:270] Forest
2 [GTC:242] Godless Shrine
4 [ISD:122] Unburial Rites
SB: 1 [RTR:148] Centaur Healer
SB: 2 [DKA:17] Ray of Revelation
SB: 1 [M13:159] Acidic Slime
SB: 2 [ISD:181] Garruk Relentless
SB: 2 [RTR:141] Abrupt Decay
SB: 1 [ISD:15] Fiend Hunter
SB: 2 [RTR:213] Deathrite Shaman
SB: 1 [DGM:103] Sin Collector
SB: 2 [RTR:178] Loxodon Smiter
SB: 1 [ISD:115] Sever the Bloodline

View file

@ -1,33 +1,33 @@
NAME:Frédéric Mercier's Esper Control
2 [M13:26] Planar Cleansing
1 [RTR:250] Plains
4 [M13:225] Glacial Fortress
2 [GTC:63] Devour Flesh
4 [ISD:83] Think Twice
4 [RTR:145] Azorius Charm
2 [ISD:78] Snapcaster Mage
2 [GTC:249] Watery Grave
1 [RTR:82] Ultimate Price
1 [RTR:156] Dramatic Rescue
2 [GPT:157] Godless Shrine
3 [AVR:32] Restoration Angel
4 [M13:43] Augur of Bolas
4 [ISD:242] Isolated Chapel
4 [RTR:201] Supreme Verdict
2 [MIR:61] Dissipate
1 [RTR:256] Island
1 [RTR:255] Island
4 [ISD:245] Nephalia Drownyard
4 [RTR:241] Hallowed Fountain
4 [M13:223] Drowned Catacomb
4 [RTR:200] Sphinx's Revelation
SB: 1 [WWK:26] Dispel
SB: 3 [AVR:104] Gloom Surgeon
SB: 2 [M11:96] Duress
SB: 2 [ISD:236] Witchbane Orb
SB: 1 [RTR:18] Rest in Peace
SB: 1 [RTR:36] Dispel
SB: 1 [SOK:158] Pithing Needle
SB: 1 [RTR:47] Psychic Spiral
SB: 2 [M13:56] Jace, Memory Adept
SB: 1 [M12:69] Negate
NAME:Frédéric Mercier's Esper Control
2 [M13:26] Planar Cleansing
1 [RTR:250] Plains
4 [M13:225] Glacial Fortress
2 [GTC:63] Devour Flesh
4 [ISD:83] Think Twice
4 [RTR:145] Azorius Charm
2 [ISD:78] Snapcaster Mage
2 [GTC:249] Watery Grave
1 [RTR:82] Ultimate Price
1 [RTR:156] Dramatic Rescue
2 [GPT:157] Godless Shrine
3 [AVR:32] Restoration Angel
4 [M13:43] Augur of Bolas
4 [ISD:242] Isolated Chapel
4 [RTR:201] Supreme Verdict
2 [MIR:61] Dissipate
1 [RTR:256] Island
1 [RTR:255] Island
4 [ISD:245] Nephalia Drownyard
4 [RTR:241] Hallowed Fountain
4 [M13:223] Drowned Catacomb
4 [RTR:200] Sphinx's Revelation
SB: 1 [WWK:26] Dispel
SB: 3 [AVR:104] Gloom Surgeon
SB: 2 [M11:96] Duress
SB: 2 [ISD:236] Witchbane Orb
SB: 1 [RTR:18] Rest in Peace
SB: 1 [RTR:36] Dispel
SB: 1 [SOK:158] Pithing Needle
SB: 1 [RTR:47] Psychic Spiral
SB: 2 [M13:56] Jace, Memory Adept
SB: 1 [M12:69] Negate

View file

@ -1,36 +1,36 @@
NAME:Jérémy Dezani's Jund Midrange
4 [M13:170] Farseek
3 [AVR:129] Bonfire of the Damned
1 [DKA:76] Tragic Slip
4 [ISD:249] Woodland Cemetery
2 [RTR:141] Abrupt Decay
3 [ISD:105] Liliana of the Veil
3 [M13:222] Dragonskull Summit
1 [RTR:82] Ultimate Price
2 [ISD:243] Kessig Wolf Run
1 [M13:217] Staff of Nin
1 [M13:101] Murder
4 [GTC:247] Stomping Ground
3 [ISD:215] Olivia Voldaren
2 [M13:174] Garruk, Primal Hunter
2 [RTR:188] Rakdos's Return
4 [DKA:140] Huntmaster of the Fells
4 [RTR:243] Overgrown Tomb
2 [M13:160] Arbor Elf
4 [M13:193] Thragtusk
4 [RTR:238] Blood Crypt
2 [M13:228] Rootbound Crag
1 [RTR:101] Mizzium Mortars
1 [RTR:157] Dreadbore
2 [RTR:270] Forest
SB: 1 [RTR:188] Rakdos's Return
SB: 1 [AVR:129] Bonfire of the Damned
SB: 1 [DKA:76] Tragic Slip
SB: 2 [M13:159] Acidic Slime
SB: 1 [RTR:141] Abrupt Decay
SB: 1 [DKA:149] Grafdigger's Cage
SB: 2 [M13:90] Duress
SB: 1 [M13:219] Tormod's Crypt
SB: 3 [RTR:197] Slaughter Games
SB: 1 [RTR:101] Mizzium Mortars
SB: 1 [AVR:149] Pillar of Flame
NAME:Jérémy Dezani's Jund Midrange
4 [M13:170] Farseek
3 [AVR:129] Bonfire of the Damned
1 [DKA:76] Tragic Slip
4 [ISD:249] Woodland Cemetery
2 [RTR:141] Abrupt Decay
3 [ISD:105] Liliana of the Veil
3 [M13:222] Dragonskull Summit
1 [RTR:82] Ultimate Price
2 [ISD:243] Kessig Wolf Run
1 [M13:217] Staff of Nin
1 [M13:101] Murder
4 [GTC:247] Stomping Ground
3 [ISD:215] Olivia Voldaren
2 [M13:174] Garruk, Primal Hunter
2 [RTR:188] Rakdos's Return
4 [DKA:140] Huntmaster of the Fells
4 [RTR:243] Overgrown Tomb
2 [M13:160] Arbor Elf
4 [M13:193] Thragtusk
4 [RTR:238] Blood Crypt
2 [M13:228] Rootbound Crag
1 [RTR:101] Mizzium Mortars
1 [RTR:157] Dreadbore
2 [RTR:270] Forest
SB: 1 [RTR:188] Rakdos's Return
SB: 1 [AVR:129] Bonfire of the Damned
SB: 1 [DKA:76] Tragic Slip
SB: 2 [M13:159] Acidic Slime
SB: 1 [RTR:141] Abrupt Decay
SB: 1 [DKA:149] Grafdigger's Cage
SB: 2 [M13:90] Duress
SB: 1 [M13:219] Tormod's Crypt
SB: 3 [RTR:197] Slaughter Games
SB: 1 [RTR:101] Mizzium Mortars
SB: 1 [AVR:149] Pillar of Flame

View file

@ -1,32 +1,32 @@
NAME:Philipp Schönegger's Miracles
4 [C13:341] Island
4 [CHK:268] Sensei's Divining Top
4 [ONS:316] Flooded Strand
2 [AVR:20] Entreat the Angels
3 [WWK:31] Jace, the Mind Sculptor
3 [ISD:78] Snapcaster Mage
4 [ALL:42] Force of Will
2 [ZEN:211] Arid Mesa
2 [M12:73] Ponder
1 [MMA:70] Vendilion Clique
4 [CMD:40] Brainstorm
1 [LEG:248] Karakas
2 [7ED:67] Counterspell
3 [CSP:31] Counterbalance
4 [AVR:38] Terminus
4 [ZEN:223] Scalding Tarn
2 [ZEN:67] Spell Pierce
2 [C13:337] Plains
2 [3ED:306] Volcanic Island
3 [3ED:304] Tundra
4 [DDF:22] Swords to Plowshares
SB: 1 [5ED:262] Pyroblast
SB: 1 [AVR:20] Entreat the Angels
SB: 3 [CMD:46] Flusterstorm
SB: 2 [4ED:236] Red Elemental Blast
SB: 1 [TSB:6] Disenchant
SB: 2 [MMA:204] Engineered Explosives
SB: 1 [7ED:67] Counterspell
SB: 1 [RTR:201] Supreme Verdict
SB: 1 [MMA:70] Vendilion Clique
SB: 2 [RTR:18] Rest in Peace
NAME:Philipp Schönegger's Miracles
4 [C13:341] Island
4 [CHK:268] Sensei's Divining Top
4 [ONS:316] Flooded Strand
2 [AVR:20] Entreat the Angels
3 [WWK:31] Jace, the Mind Sculptor
3 [ISD:78] Snapcaster Mage
4 [ALL:42] Force of Will
2 [ZEN:211] Arid Mesa
2 [M12:73] Ponder
1 [MMA:70] Vendilion Clique
4 [CMD:40] Brainstorm
1 [LEG:248] Karakas
2 [7ED:67] Counterspell
3 [CSP:31] Counterbalance
4 [AVR:38] Terminus
4 [ZEN:223] Scalding Tarn
2 [ZEN:67] Spell Pierce
2 [C13:337] Plains
2 [3ED:306] Volcanic Island
3 [3ED:304] Tundra
4 [DDF:22] Swords to Plowshares
SB: 1 [5ED:262] Pyroblast
SB: 1 [AVR:20] Entreat the Angels
SB: 3 [CMD:46] Flusterstorm
SB: 2 [4ED:236] Red Elemental Blast
SB: 1 [TSB:6] Disenchant
SB: 2 [MMA:204] Engineered Explosives
SB: 1 [7ED:67] Counterspell
SB: 1 [RTR:201] Supreme Verdict
SB: 1 [MMA:70] Vendilion Clique
SB: 2 [RTR:18] Rest in Peace

View file

@ -1,42 +1,42 @@
NAME:Stefan Böttcher's Deathblade
1 [WWK:134] Creeping Tar Pit
4 [RTR:213] Deathrite Shaman
1 [AVR:20] Entreat the Angels
2 [C13:63] True-Name Nemesis
2 [WWK:31] Jace, the Mind Sculptor
3 [ISD:78] Snapcaster Mage
3 [MMA:75] Dark Confidant
1 [MMA:70] Vendilion Clique
1 [NPH:130] Batterskull
1 [ARB:85] Zealous Persecution
4 [CMD:40] Brainstorm
2 [THS:107] Thoughtseize
1 [MMA:204] Engineered Explosives
1 [BOK:163] Umezawa's Jitte
1 [3ED:298] Scrubland
1 [C13:337] Plains
3 [3ED:305] Underground Sea
3 [3ED:304] Tundra
4 [DDF:22] Swords to Plowshares
1 [3ED:303] Tropical Island
1 [C13:341] Island
3 [ONS:316] Flooded Strand
1 [C13:345] Swamp
1 [ZEN:219] Marsh Flats
2 [TMP:340] Wasteland
1 [LEG:248] Karakas
1 [MMA:219] Academy Ruins
1 [7ED:67] Counterspell
3 [ONS:321] Polluted Delta
3 [ZEN:67] Spell Pierce
3 [WWK:20] Stoneforge Mystic
SB: 1 [ISD:105] Liliana of the Veil
SB: 1 [RTR:155] Detention Sphere
SB: 3 [ALL:42] Force of Will
SB: 1 [RTR:201] Supreme Verdict
SB: 3 [M11:21] Leyline of Sanctity
SB: 1 [MBS:138] Sword of Feast and Famine
SB: 2 [NPH:74] Surgical Extraction
SB: 1 [THS:65] Swan Song
SB: 1 [MMA:213] Relic of Progenitus
SB: 1 [NMS:111] Reverent Silence
NAME:Stefan Böttcher's Deathblade
1 [WWK:134] Creeping Tar Pit
4 [RTR:213] Deathrite Shaman
1 [AVR:20] Entreat the Angels
2 [C13:63] True-Name Nemesis
2 [WWK:31] Jace, the Mind Sculptor
3 [ISD:78] Snapcaster Mage
3 [MMA:75] Dark Confidant
1 [MMA:70] Vendilion Clique
1 [NPH:130] Batterskull
1 [ARB:85] Zealous Persecution
4 [CMD:40] Brainstorm
2 [THS:107] Thoughtseize
1 [MMA:204] Engineered Explosives
1 [BOK:163] Umezawa's Jitte
1 [3ED:298] Scrubland
1 [C13:337] Plains
3 [3ED:305] Underground Sea
3 [3ED:304] Tundra
4 [DDF:22] Swords to Plowshares
1 [3ED:303] Tropical Island
1 [C13:341] Island
3 [ONS:316] Flooded Strand
1 [C13:345] Swamp
1 [ZEN:219] Marsh Flats
2 [TMP:340] Wasteland
1 [LEG:248] Karakas
1 [MMA:219] Academy Ruins
1 [7ED:67] Counterspell
3 [ONS:321] Polluted Delta
3 [ZEN:67] Spell Pierce
3 [WWK:20] Stoneforge Mystic
SB: 1 [ISD:105] Liliana of the Veil
SB: 1 [RTR:155] Detention Sphere
SB: 3 [ALL:42] Force of Will
SB: 1 [RTR:201] Supreme Verdict
SB: 3 [M11:21] Leyline of Sanctity
SB: 1 [MBS:138] Sword of Feast and Famine
SB: 2 [NPH:74] Surgical Extraction
SB: 1 [THS:65] Swan Song
SB: 1 [MMA:213] Relic of Progenitus
SB: 1 [NMS:111] Reverent Silence

View file

@ -3,6 +3,7 @@ package mage.client;
import mage.cards.action.ActionCallback;
import mage.cards.decks.Deck;
import mage.cards.repository.CardRepository;
import mage.cards.repository.ExpansionRepository;
import mage.cards.repository.RepositoryUtil;
import mage.client.cards.BigCard;
import mage.client.chat.ChatPanelBasic;
@ -719,6 +720,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
boolean autoConnectParamValue = startUser != null || Boolean.parseBoolean(PREFS.get("autoConnect", "false"));
boolean status = false;
if (autoConnectParamValue) {
LOGGER.info("Auto-connecting to " + MagePreferences.getServerAddress());
status = performConnect(false);
}
return status;
@ -741,6 +743,9 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
currentConnection.setPassword(password);
currentConnection.setHost(server);
currentConnection.setPort(port);
// force to redownload db on updates
boolean redownloadDatabase = (ExpansionRepository.instance.getSetByCode("GRN") == null || CardRepository.instance.findCard("Island") == null);
currentConnection.setForceDBComparison(redownloadDatabase);
String allMAC = "";
try {
allMAC = Connection.getMAC();
@ -762,7 +767,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
prepareAndShowTablesPane();
return true;
} else {
showMessage("Unable connect to server");
showMessage("Unable connect to server: " + SessionHandler.getLastConnectError());
}
} finally {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));

View file

@ -1,6 +1,5 @@
package mage.client;
import java.util.*;
import mage.cards.decks.DeckCardLists;
import mage.client.chat.LocalCommands;
import mage.client.dialog.PreferencesDialog;
@ -16,19 +15,22 @@ import mage.remote.Session;
import mage.remote.SessionImpl;
import mage.view.*;
import java.util.*;
/**
* Created by IGOUDT on 15-9-2016.
*/
public final class SessionHandler {
private static Session session;
private static String lastConnectError = "";
public static void startSession(MageFrame mageFrame) {
session = new SessionImpl(mageFrame);
session.setJsonLogActive("true".equals(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_LOG_AUTO_SAVE, "true")));
}
public static void ping() {
session.ping();
}
@ -46,7 +48,17 @@ public final class SessionHandler {
}
public static boolean connect(Connection connection) {
return session.connect(connection);
lastConnectError = "";
if (session.connect(connection)) {
return true;
} else {
lastConnectError = session.getLastError();
return false;
}
}
public static String getLastConnectError() {
return lastConnectError;
}
public static boolean stopConnecting() {

View file

@ -3,9 +3,6 @@
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JInternalFrameFormInfo">
<Properties>
<Property name="title" type="java.lang.String" value="Connect to server"/>
<Property name="normalBounds" type="java.awt.Rectangle" editor="org.netbeans.beaninfo.editors.RectangleEditor">
<Rectangle value="[100, 100, 410, 307]"/>
</Property>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
@ -26,30 +23,26 @@
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" pref="29" max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="lblPort" alignment="1" min="-2" max="-2" attributes="0"/>
<Component id="lblServer" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="lblFlag" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="lblUserName" min="-2" max="-2" attributes="0"/>
<Component id="lblPassword" alignment="1" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="lblUserName" alignment="0" max="32767" attributes="0"/>
<Component id="lblServer" alignment="0" max="32767" attributes="0"/>
<Component id="lblFastConnect" alignment="0" max="32767" attributes="0"/>
<Component id="lblPassword" alignment="0" max="32767" attributes="0"/>
<Component id="lblFlag" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="jProxySettingsButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Component id="lblStatus" alignment="1" max="32767" attributes="0"/>
<Component id="chkForceUpdateDB" alignment="0" max="32767" attributes="0"/>
<Component id="chkAutoConnect" alignment="0" max="32767" attributes="0"/>
<Component id="txtUserName" alignment="0" max="32767" attributes="0"/>
<Component id="txtPassword" alignment="0" max="32767" attributes="0"/>
<Component id="panelFlag" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="btnConnect" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
@ -57,82 +50,58 @@
<Component id="btnRegister" max="32767" attributes="0"/>
<Component id="btnForgotPassword" max="32767" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnCancel" min="-2" pref="77" max="-2" attributes="0"/>
</Group>
<Component id="lblStatus" alignment="1" max="32767" attributes="0"/>
<Component id="chkForceUpdateDB" alignment="0" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Component id="jProxySettingsButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Component id="chkAutoConnect" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="1" attributes="0">
<Group type="103" groupAlignment="1" attributes="0">
<Component id="panelFlag" alignment="0" max="32767" attributes="0"/>
<Component id="txtServer" alignment="0" max="32767" attributes="0"/>
<Component id="txtUserName" alignment="0" max="32767" attributes="0"/>
<Component id="txtPassword" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="1" attributes="0">
<Component id="txtPort" min="-2" pref="71" max="-2" attributes="0"/>
<EmptySpace pref="11" max="32767" attributes="0"/>
<Component id="lblFastConnect" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnFind1" min="-2" pref="70" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnFind3" min="-2" pref="70" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnFind2" min="-2" pref="40" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="btnFind" max="-2" attributes="0"/>
</Group>
<Component id="panelFast" alignment="0" max="32767" attributes="0"/>
<Component id="panelServer" alignment="1" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="filler2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblServer" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtServer" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnFind" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="txtPort" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="lblPort" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnFind1" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnFind2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnFind3" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="lblFastConnect" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="txtUserName" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="lblUserName" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="txtPassword" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="lblPassword" alignment="3" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="panelFast" max="32767" attributes="0"/>
<Component id="lblFastConnect" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="panelServer" max="32767" attributes="0"/>
<Component id="lblServer" max="32767" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="txtUserName" min="-2" max="-2" attributes="0"/>
<Component id="lblUserName" min="-2" pref="20" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="txtPassword" max="32767" attributes="0"/>
<Component id="lblPassword" max="32767" attributes="0"/>
</Group>
</Group>
<Component id="filler2" pref="53" max="32767" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="panelFlag" min="-2" pref="20" max="-2" attributes="0"/>
<Component id="lblFlag" min="-2" pref="18" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="chkAutoConnect" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="chkForceUpdateDB" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="jProxySettingsButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jProxySettingsButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="lblStatus" min="-2" pref="24" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" max="-2" attributes="0">
@ -152,49 +121,27 @@
<SubComponents>
<Component class="javax.swing.JLabel" name="lblServer">
<Properties>
<Property name="horizontalAlignment" type="int" value="4"/>
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="txtServer"/>
</Property>
<Property name="text" type="java.lang.String" value="Server:"/>
<Property name="text" type="java.lang.String" value="Server name:"/>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="txtServer">
</Component>
<Component class="javax.swing.JButton" name="btnFind">
<Properties>
<Property name="text" type="java.lang.String" value="Find..."/>
<Property name="toolTipText" type="java.lang.String" value="Shows the list of public servers"/>
<Property name="name" type="java.lang.String" value="findServerBtn" noResource="true"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="findPublicServerActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblPort">
<Properties>
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="txtPort"/>
</Property>
<Property name="text" type="java.lang.String" value="Port:"/>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="txtPort">
<Events>
<EventHandler event="keyTyped" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="keyTyped"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblUserName">
<Properties>
<Property name="horizontalAlignment" type="int" value="4"/>
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="txtUserName"/>
</Property>
<Property name="text" type="java.lang.String" value="User name:"/>
<Property name="text" type="java.lang.String" value="Username:"/>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="txtUserName">
</Component>
<Component class="javax.swing.JLabel" name="lblPassword">
<Properties>
<Property name="horizontalAlignment" type="int" value="4"/>
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="txtPassword"/>
</Property>
@ -205,10 +152,11 @@
</Component>
<Component class="javax.swing.JLabel" name="lblFlag">
<Properties>
<Property name="horizontalAlignment" type="int" value="4"/>
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="txtUserName"/>
</Property>
<Property name="text" type="java.lang.String" value="User flag:"/>
<Property name="text" type="java.lang.String" value="User&apos;s flag:"/>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="chkAutoConnect">
@ -289,86 +237,23 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnForgotPasswordActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnFind1">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/flags/de.png"/>
</Property>
<Property name="text" type="java.lang.String" value="X"/>
<Property name="toolTipText" type="java.lang.String" value="Connect to xmage.de (Europe, most popular)"/>
<Property name="actionCommand" type="java.lang.String" value="connectXmageDe"/>
<Property name="alignmentY" type="float" value="0.0"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[2, 2, 2, 2]"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[42, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[42, 23]"/>
</Property>
<Property name="name" type="java.lang.String" value="connectXmageDeBtn" noResource="true"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[23, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="connectXmageDe"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnFind2">
<Properties>
<Property name="text" type="java.lang.String" value="L"/>
<Property name="toolTipText" type="java.lang.String" value="Connect to localhost (local server)"/>
<Property name="actionCommand" type="java.lang.String" value="connectLocalhost"/>
<Property name="alignmentY" type="float" value="0.0"/>
<Property name="horizontalTextPosition" type="int" value="0"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[2, 2, 2, 2]"/>
</Property>
<Property name="name" type="java.lang.String" value="connectLocalhostBtn" noResource="true"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[23, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="connectLocalhost"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnFind3">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/flags/us.png"/>
</Property>
<Property name="text" type="java.lang.String" value="P"/>
<Property name="toolTipText" type="java.lang.String" value="Connect to mtg.powersofwar.com (USA)"/>
<Property name="actionCommand" type="java.lang.String" value="connectXmageus"/>
<Property name="alignmentY" type="float" value="0.0"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[2, 2, 2, 2]"/>
</Property>
<Property name="name" type="java.lang.String" value="connectXmageusBtn" noResource="true"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[23, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="connectXmageus"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblFastConnect">
<Properties>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="btnFind1"/>
<ComponentRef name="btnFindMain"/>
</Property>
<Property name="text" type="java.lang.String" value="Fast connect to:"/>
<Property name="text" type="java.lang.String" value="Connect to:"/>
<Property name="name" type="java.lang.String" value="" noResource="true"/>
</Properties>
<AccessibilityProperties>
<Property name="AccessibleContext.accessibleName" type="java.lang.String" value="Fast connect to:"/>
</AccessibilityProperties>
</Component>
<Container class="javax.swing.JPanel" name="panelFlag">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[189, 30]"/>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[50, 33]"/>
</Property>
</Properties>
@ -420,5 +305,223 @@
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="panelFast">
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="btnFindMain" min="-2" pref="75" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="btnFindUs" min="-2" pref="75" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="btnFindBeta" min="-2" pref="75" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="btnFindLocal" min="-2" pref="75" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnFindOther" max="32767" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="btnFindMain" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnFindLocal" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnFindUs" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnFindBeta" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnFindOther" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JButton" name="btnFindMain">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/flags/de.png"/>
</Property>
<Property name="text" type="java.lang.String" value="X"/>
<Property name="toolTipText" type="java.lang.String" value="Connect to xmage.de (Europe, most popular, registration needs)"/>
<Property name="actionCommand" type="java.lang.String" value="connectXmageDe"/>
<Property name="alignmentY" type="float" value="0.0"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[2, 2, 2, 2]"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[42, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[42, 23]"/>
</Property>
<Property name="name" type="java.lang.String" value="connectXmageDeBtn" noResource="true"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[23, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="connectXmageDe"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnFindLocal">
<Properties>
<Property name="text" type="java.lang.String" value="LOCAL"/>
<Property name="toolTipText" type="java.lang.String" value="Connect to localhost (local server)"/>
<Property name="actionCommand" type="java.lang.String" value="connectLocalhost"/>
<Property name="alignmentY" type="float" value="0.0"/>
<Property name="horizontalTextPosition" type="int" value="0"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[2, 2, 2, 2]"/>
</Property>
<Property name="name" type="java.lang.String" value="connectLocalhostBtn" noResource="true"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[23, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="connectLocalhost"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnFindBeta">
<Properties>
<Property name="text" type="java.lang.String" value="BETA"/>
<Property name="toolTipText" type="java.lang.String" value="Connect to BETA server (use any username without registration)"/>
<Property name="alignmentY" type="float" value="0.0"/>
<Property name="horizontalTextPosition" type="int" value="0"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[2, 2, 2, 2]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[23, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFindBetaconnectLocalhost"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnFindUs">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/flags/us.png"/>
</Property>
<Property name="text" type="java.lang.String" value="P"/>
<Property name="toolTipText" type="java.lang.String" value="Connect to mtg.powersofwar.com (USA, use any username without registration)"/>
<Property name="actionCommand" type="java.lang.String" value="connectXmageus"/>
<Property name="alignmentY" type="float" value="0.0"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[2, 2, 2, 2]"/>
</Property>
<Property name="name" type="java.lang.String" value="connectXmageusBtn" noResource="true"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[23, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="connectXmageus"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnFindOther">
<Properties>
<Property name="text" type="java.lang.String" value="Other servers..."/>
<Property name="toolTipText" type="java.lang.String" value="Choose server from full servers list"/>
<Property name="horizontalTextPosition" type="int" value="0"/>
<Property name="name" type="java.lang.String" value="findServerBtn" noResource="true"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="findPublicServerActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="panelServer">
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="txtServer" min="-2" pref="212" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblPort" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtPort" min="-2" pref="75" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnCheckStatus" pref="141" max="32767" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="txtServer" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtPort" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="lblPort" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnCheckStatus" alignment="3" max="32767" attributes="0"/>
</Group>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JTextField" name="txtServer">
</Component>
<Component class="javax.swing.JTextField" name="txtPort">
<Events>
<EventHandler event="keyTyped" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="keyTyped"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblPort">
<Properties>
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="txtPort"/>
</Property>
<Property name="text" type="java.lang.String" value="Port:"/>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="btnCheckStatus">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/flags/world.png"/>
</Property>
<Property name="text" type="java.lang.String" value="Check online status"/>
<Property name="toolTipText" type="java.lang.String" value="Go to servers online statuses page"/>
<Property name="alignmentY" type="float" value="0.0"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[2, 2, 2, 2]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[23, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnCheckStatusActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.Box$Filler" name="filler2">
<Properties>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[32767, 50]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 50]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 50]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalStrut"/>
</AuxValues>
</Component>
</SubComponents>
</Form>

View file

@ -5,44 +5,12 @@
*/
package mage.client.dialog;
import java.awt.Cursor;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.Writer;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JLayeredPane;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
import mage.cards.repository.CardRepository;
import mage.cards.repository.ExpansionRepository;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.client.MageFrame;
import static mage.client.dialog.PreferencesDialog.KEY_CONNECTION_URL_SERVER_LIST;
import static mage.client.dialog.PreferencesDialog.KEY_CONNECT_AUTO_CONNECT;
import static mage.client.dialog.PreferencesDialog.KEY_CONNECT_FLAG;
import mage.client.SessionHandler;
import mage.client.preference.MagePreferences;
import mage.client.util.Config;
import mage.client.util.gui.countryBox.CountryItemEditor;
@ -51,6 +19,20 @@ import mage.remote.Connection;
import mage.utils.StreamUtils;
import org.apache.log4j.Logger;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.*;
import java.util.List;
import java.util.*;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static mage.client.dialog.PreferencesDialog.*;
/**
* @author BetaSteward_at_googlemail.com
*/
@ -124,10 +106,6 @@ public class ConnectDialog extends MageDialog {
private void initComponents() {
lblServer = new javax.swing.JLabel();
txtServer = new javax.swing.JTextField();
btnFind = new javax.swing.JButton();
lblPort = new javax.swing.JLabel();
txtPort = new javax.swing.JTextField();
lblUserName = new javax.swing.JLabel();
txtUserName = new javax.swing.JTextField();
lblPassword = new javax.swing.JLabel();
@ -141,47 +119,41 @@ public class ConnectDialog extends MageDialog {
lblStatus = new javax.swing.JLabel();
btnRegister = new javax.swing.JButton();
btnForgotPassword = new javax.swing.JButton();
btnFind1 = new javax.swing.JButton();
btnFind2 = new javax.swing.JButton();
btnFind3 = new javax.swing.JButton();
lblFastConnect = new javax.swing.JLabel();
panelFlag = new javax.swing.JPanel();
cbFlag = new mage.client.util.gui.countryBox.CountryComboBox();
filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(5, 0), new java.awt.Dimension(4, 0), new java.awt.Dimension(5, 32767));
btnFlagSearch = new javax.swing.JButton();
panelFast = new javax.swing.JPanel();
btnFindMain = new javax.swing.JButton();
btnFindLocal = new javax.swing.JButton();
btnFindBeta = new javax.swing.JButton();
btnFindUs = new javax.swing.JButton();
btnFindOther = new javax.swing.JButton();
panelServer = new javax.swing.JPanel();
txtServer = new javax.swing.JTextField();
txtPort = new javax.swing.JTextField();
lblPort = new javax.swing.JLabel();
btnCheckStatus = new javax.swing.JButton();
filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 50), new java.awt.Dimension(0, 50), new java.awt.Dimension(32767, 50));
setTitle("Connect to server");
setNormalBounds(new java.awt.Rectangle(100, 100, 410, 307));
lblServer.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
lblServer.setLabelFor(txtServer);
lblServer.setText("Server:");
btnFind.setText("Find...");
btnFind.setToolTipText("Shows the list of public servers");
btnFind.setName("findServerBtn"); // NOI18N
btnFind.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
findPublicServerActionPerformed(evt);
}
});
lblPort.setLabelFor(txtPort);
lblPort.setText("Port:");
txtPort.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyTyped(java.awt.event.KeyEvent evt) {
ConnectDialog.this.keyTyped(evt);
}
});
lblServer.setText("Server name:");
lblUserName.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
lblUserName.setLabelFor(txtUserName);
lblUserName.setText("User name:");
lblUserName.setText("Username:");
lblPassword.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
lblPassword.setLabelFor(txtPassword);
lblPassword.setText("Password:");
lblFlag.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
lblFlag.setLabelFor(txtUserName);
lblFlag.setText("User flag:");
lblFlag.setText("User's flag:");
chkAutoConnect.setText("Automatically connect to this server next time");
chkAutoConnect.setToolTipText("<HTML>If active this connect dialog will not be shown if you choose to connect.<br>\nInstead XMage tries to connect to the last server you were connected to.");
@ -242,55 +214,12 @@ public class ConnectDialog extends MageDialog {
}
});
btnFind1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/de.png"))); // NOI18N
btnFind1.setText("X");
btnFind1.setToolTipText("Connect to xmage.de (Europe, most popular)");
btnFind1.setActionCommand("connectXmageDe");
btnFind1.setAlignmentY(0.0F);
btnFind1.setMargin(new java.awt.Insets(2, 2, 2, 2));
btnFind1.setMaximumSize(new java.awt.Dimension(42, 23));
btnFind1.setMinimumSize(new java.awt.Dimension(42, 23));
btnFind1.setName("connectXmageDeBtn"); // NOI18N
btnFind1.setPreferredSize(new java.awt.Dimension(23, 23));
btnFind1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
connectXmageDe(evt);
}
});
btnFind2.setText("L");
btnFind2.setToolTipText("Connect to localhost (local server)");
btnFind2.setActionCommand("connectLocalhost");
btnFind2.setAlignmentY(0.0F);
btnFind2.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
btnFind2.setMargin(new java.awt.Insets(2, 2, 2, 2));
btnFind2.setName("connectLocalhostBtn"); // NOI18N
btnFind2.setPreferredSize(new java.awt.Dimension(23, 23));
btnFind2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
connectLocalhost(evt);
}
});
btnFind3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/us.png"))); // NOI18N
btnFind3.setText("P");
btnFind3.setToolTipText("Connect to mtg.powersofwar.com (USA)");
btnFind3.setActionCommand("connectXmageus");
btnFind3.setAlignmentY(0.0F);
btnFind3.setMargin(new java.awt.Insets(2, 2, 2, 2));
btnFind3.setName("connectXmageusBtn"); // NOI18N
btnFind3.setPreferredSize(new java.awt.Dimension(23, 23));
btnFind3.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
connectXmageus(evt);
}
});
lblFastConnect.setLabelFor(btnFind1);
lblFastConnect.setText("Fast connect to:");
lblFastConnect.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
lblFastConnect.setLabelFor(btnFindMain);
lblFastConnect.setText("Connect to:");
lblFastConnect.setName(""); // NOI18N
panelFlag.setPreferredSize(new java.awt.Dimension(189, 30));
panelFlag.setMinimumSize(new java.awt.Dimension(50, 33));
panelFlag.setLayout(new javax.swing.BoxLayout(panelFlag, javax.swing.BoxLayout.LINE_AXIS));
cbFlag.setEditable(true);
@ -312,109 +241,232 @@ public class ConnectDialog extends MageDialog {
});
panelFlag.add(btnFlagSearch);
btnFindMain.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/de.png"))); // NOI18N
btnFindMain.setText("X");
btnFindMain.setToolTipText("Connect to xmage.de (Europe, most popular, registration needs)");
btnFindMain.setActionCommand("connectXmageDe");
btnFindMain.setAlignmentY(0.0F);
btnFindMain.setMargin(new java.awt.Insets(2, 2, 2, 2));
btnFindMain.setMaximumSize(new java.awt.Dimension(42, 23));
btnFindMain.setMinimumSize(new java.awt.Dimension(42, 23));
btnFindMain.setName("connectXmageDeBtn"); // NOI18N
btnFindMain.setPreferredSize(new java.awt.Dimension(23, 23));
btnFindMain.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
connectXmageDe(evt);
}
});
btnFindLocal.setText("LOCAL");
btnFindLocal.setToolTipText("Connect to localhost (local server)");
btnFindLocal.setActionCommand("connectLocalhost");
btnFindLocal.setAlignmentY(0.0F);
btnFindLocal.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
btnFindLocal.setMargin(new java.awt.Insets(2, 2, 2, 2));
btnFindLocal.setName("connectLocalhostBtn"); // NOI18N
btnFindLocal.setPreferredSize(new java.awt.Dimension(23, 23));
btnFindLocal.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
connectLocalhost(evt);
}
});
btnFindBeta.setText("BETA");
btnFindBeta.setToolTipText("Connect to BETA server (use any username without registration)");
btnFindBeta.setAlignmentY(0.0F);
btnFindBeta.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
btnFindBeta.setMargin(new java.awt.Insets(2, 2, 2, 2));
btnFindBeta.setPreferredSize(new java.awt.Dimension(23, 23));
btnFindBeta.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnFindBetaconnectLocalhost(evt);
}
});
btnFindUs.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/us.png"))); // NOI18N
btnFindUs.setText("P");
btnFindUs.setToolTipText("Connect to mtg.powersofwar.com (USA, use any username without registration)");
btnFindUs.setActionCommand("connectXmageus");
btnFindUs.setAlignmentY(0.0F);
btnFindUs.setMargin(new java.awt.Insets(2, 2, 2, 2));
btnFindUs.setName("connectXmageusBtn"); // NOI18N
btnFindUs.setPreferredSize(new java.awt.Dimension(23, 23));
btnFindUs.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
connectXmageus(evt);
}
});
btnFindOther.setText("Other servers...");
btnFindOther.setToolTipText("Choose server from full servers list");
btnFindOther.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
btnFindOther.setName("findServerBtn"); // NOI18N
btnFindOther.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
findPublicServerActionPerformed(evt);
}
});
javax.swing.GroupLayout panelFastLayout = new javax.swing.GroupLayout(panelFast);
panelFast.setLayout(panelFastLayout);
panelFastLayout.setHorizontalGroup(
panelFastLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelFastLayout.createSequentialGroup()
.addGap(0, 0, 0)
.addComponent(btnFindMain, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFindUs, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFindBeta, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFindLocal, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFindOther, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGap(0, 0, 0))
);
panelFastLayout.setVerticalGroup(
panelFastLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelFastLayout.createSequentialGroup()
.addGap(0, 0, 0)
.addGroup(panelFastLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnFindMain, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnFindLocal, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnFindUs, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnFindBeta, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnFindOther))
.addGap(0, 0, 0))
);
txtPort.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyTyped(java.awt.event.KeyEvent evt) {
ConnectDialog.this.keyTyped(evt);
}
});
lblPort.setLabelFor(txtPort);
lblPort.setText("Port:");
btnCheckStatus.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/world.png"))); // NOI18N
btnCheckStatus.setText("Check online status");
btnCheckStatus.setToolTipText("Go to servers online statuses page");
btnCheckStatus.setAlignmentY(0.0F);
btnCheckStatus.setMargin(new java.awt.Insets(2, 2, 2, 2));
btnCheckStatus.setPreferredSize(new java.awt.Dimension(23, 23));
btnCheckStatus.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnCheckStatusActionPerformed(evt);
}
});
javax.swing.GroupLayout panelServerLayout = new javax.swing.GroupLayout(panelServer);
panelServer.setLayout(panelServerLayout);
panelServerLayout.setHorizontalGroup(
panelServerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelServerLayout.createSequentialGroup()
.addComponent(txtServer, javax.swing.GroupLayout.PREFERRED_SIZE, 212, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblPort)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCheckStatus, javax.swing.GroupLayout.DEFAULT_SIZE, 141, Short.MAX_VALUE)
.addGap(0, 0, 0))
);
panelServerLayout.setVerticalGroup(
panelServerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelServerLayout.createSequentialGroup()
.addGap(0, 0, 0)
.addGroup(panelServerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(txtServer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblPort)
.addComponent(btnCheckStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(29, 29, 29)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(lblPort)
.addComponent(lblServer)))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(lblFlag)))
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblUserName)
.addComponent(lblPassword, javax.swing.GroupLayout.Alignment.TRAILING))))
.addGap(0, 0, 0)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(btnConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(btnRegister, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnForgotPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 77, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(lblStatus, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(chkForceUpdateDB, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(jProxySettingsButton)
.addGap(0, 0, Short.MAX_VALUE))
.addComponent(chkAutoConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(panelFlag, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(txtServer, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(txtUserName, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(txtPassword, javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 11, Short.MAX_VALUE)
.addComponent(lblFastConnect)
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(lblUserName, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lblServer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lblFastConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lblPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lblFlag, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jProxySettingsButton)
.addGap(0, 0, Short.MAX_VALUE))
.addComponent(lblStatus, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(chkForceUpdateDB, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(chkAutoConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(txtUserName)
.addComponent(txtPassword)
.addComponent(panelFlag, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(btnConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(btnRegister, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnForgotPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 77, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(panelFast, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(panelServer, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFind1, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFind3, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnFind2, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(0, 0, 0)
.addComponent(btnFind)))
.addContainerGap())
.addComponent(filler2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblServer)
.addComponent(txtServer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnFind))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblPort)
.addComponent(btnFind1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnFind2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnFind3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblFastConnect))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(txtUserName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblUserName))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblPassword))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(panelFlag, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblFlag, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(chkAutoConnect)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(chkForceUpdateDB)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jProxySettingsButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addGroup(layout.createSequentialGroup()
.addComponent(btnRegister, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnForgotPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addComponent(btnConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnCancel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(23, 23, 23))
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(panelFast, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lblFastConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(panelServer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lblServer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(txtUserName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblUserName, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(txtPassword)
.addComponent(lblPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addComponent(filler2, javax.swing.GroupLayout.DEFAULT_SIZE, 53, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(panelFlag, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblFlag, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(chkAutoConnect)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(chkForceUpdateDB)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jProxySettingsButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(lblStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addGroup(layout.createSequentialGroup()
.addComponent(btnRegister, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnForgotPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addComponent(btnConnect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnCancel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(23, 23, 23))
);
lblFastConnect.getAccessibleContext().setAccessibleName("Fast connect to:");
pack();
}// </editor-fold>//GEN-END:initComponents
@ -457,13 +509,12 @@ public class ConnectDialog extends MageDialog {
connection.setPort(Integer.valueOf(this.txtPort.getText().trim()));
connection.setUsername(this.txtUserName.getText().trim());
connection.setPassword(this.txtPassword.getText().trim());
// force to redownload db
boolean redownloadDatabase = (ExpansionRepository.instance.getSetByCode("GRN") == null || CardRepository.instance.findCard("Island") == null);
connection.setForceDBComparison(this.chkForceUpdateDB.isSelected() || redownloadDatabase);
String allMAC = "";
try {
allMAC = connection.getMAC();
allMAC = Connection.getMAC();
} catch (SocketException ex) {
}
connection.setUserIdStr(System.getProperty("user.name") + ":" + System.getProperty("os.name") + ":" + MagePreferences.getUserNames() + ":" + allMAC);
@ -485,6 +536,7 @@ public class ConnectDialog extends MageDialog {
private class ConnectTask extends SwingWorker<Boolean, Void> {
private boolean result = false;
private String lastConnectError = "";
private static final int CONNECTION_TIMEOUT_MS = 2100;
@ -493,6 +545,7 @@ public class ConnectDialog extends MageDialog {
lblStatus.setText("Connecting...");
btnConnect.setEnabled(false);
result = MageFrame.connect(connection);
lastConnectError = SessionHandler.getLastConnectError();
return result;
}
@ -506,7 +559,7 @@ public class ConnectDialog extends MageDialog {
connected();
MageFrame.getInstance().prepareAndShowTablesPane();
} else {
lblStatus.setText("Could not connect");
lblStatus.setText("Could not connect: " + lastConnectError);
}
} catch (InterruptedException ex) {
logger.fatal("Update Players Task error", ex);
@ -679,8 +732,7 @@ public class ConnectDialog extends MageDialog {
this.txtPort.setText("17171");
// Update userName and password according to the chosen server.
this.txtUserName.setText(MagePreferences.getUserName(serverAddress));
this.txtPassword.setText(MagePreferences.getPassword(serverAddress));
this.txtPassword.setText(MagePreferences.getPassword(serverAddress)); // TODO add your handling code here:
}//GEN-LAST:event_btnFind1findPublicServerActionPerformed
private void connectLocalhost(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFind2findPublicServerActionPerformed
@ -702,10 +754,33 @@ public class ConnectDialog extends MageDialog {
this.txtPassword.setText(MagePreferences.getPassword(serverAddress));
}
private void connectBeta(java.awt.event.ActionEvent evt) {
String serverAddress = "xmage.today";
this.txtServer.setText(serverAddress);
this.txtPort.setText("17171");
// Update userName and password according to the chosen server.
this.txtUserName.setText(MagePreferences.getUserName(serverAddress));
this.txtPassword.setText(MagePreferences.getPassword(serverAddress));
}
private void btnFlagSearchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFlagSearchActionPerformed
doFastFlagSearch();
}//GEN-LAST:event_btnFlagSearchActionPerformed
private void btnFindBetaconnectLocalhost(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFindBetaconnectLocalhost
connectBeta(evt);
}//GEN-LAST:event_btnFindBetaconnectLocalhost
private void btnCheckStatusActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCheckStatusActionPerformed
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
try {
Desktop.getDesktop().browse(new URI("http://xmageservers.online/"));
} catch (Exception e) {
//
}
}
}//GEN-LAST:event_btnCheckStatusActionPerformed
private void doFastFlagSearch() {
Choice choice = new ChoiceImpl(false);
@ -751,11 +826,13 @@ public class ConnectDialog extends MageDialog {
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnCancel;
private javax.swing.JButton btnCheckStatus;
private javax.swing.JButton btnConnect;
private javax.swing.JButton btnFind;
private javax.swing.JButton btnFind1;
private javax.swing.JButton btnFind2;
private javax.swing.JButton btnFind3;
private javax.swing.JButton btnFindBeta;
private javax.swing.JButton btnFindLocal;
private javax.swing.JButton btnFindMain;
private javax.swing.JButton btnFindOther;
private javax.swing.JButton btnFindUs;
private javax.swing.JButton btnFlagSearch;
private javax.swing.JButton btnForgotPassword;
private javax.swing.JButton btnRegister;
@ -763,6 +840,7 @@ public class ConnectDialog extends MageDialog {
private javax.swing.JCheckBox chkAutoConnect;
private javax.swing.JCheckBox chkForceUpdateDB;
private javax.swing.Box.Filler filler1;
private javax.swing.Box.Filler filler2;
private javax.swing.JButton jProxySettingsButton;
private javax.swing.JLabel lblFastConnect;
private javax.swing.JLabel lblFlag;
@ -771,7 +849,9 @@ public class ConnectDialog extends MageDialog {
private javax.swing.JLabel lblServer;
private javax.swing.JLabel lblStatus;
private javax.swing.JLabel lblUserName;
private javax.swing.JPanel panelFast;
private javax.swing.JPanel panelFlag;
private javax.swing.JPanel panelServer;
private javax.swing.JPasswordField txtPassword;
private javax.swing.JTextField txtPort;
private javax.swing.JTextField txtServer;

View file

@ -18,6 +18,8 @@ public class TablesUtil {
searchId = ((TablesTableModel) table.getModel()).findTableAndGameInfoByRow(row);
} else if (table.getModel() instanceof MatchesTableModel) {
searchId = ((MatchesTableModel) table.getModel()).findTableAndGameInfoByRow(row);
} else if (table.getModel() instanceof TournamentMatchesTableModel) {
searchId = ((TournamentMatchesTableModel) table.getModel()).findTableAndGameInfoByRow(row);
} else {
logger.error("Not supported tables model " + table.getModel().getClass().toString());
}
@ -31,6 +33,8 @@ public class TablesUtil {
row = ((TablesTableModel) tableModel).findRowByTableAndGameInfo(searchId);
} else if (tableModel instanceof MatchesTableModel) {
row = ((MatchesTableModel) tableModel).findRowByTableAndGameInfo(searchId);
} else if (tableModel instanceof TournamentMatchesTableModel) {
row = ((TournamentMatchesTableModel) tableModel).findRowByTableAndGameInfo(searchId);
} else {
logger.error("Not supported tables model " + tableModel.getClass().toString());
}

View file

@ -0,0 +1,116 @@
package mage.client.table;
import mage.view.RoundView;
import mage.view.TournamentGameView;
import mage.view.TournamentView;
import javax.swing.table.AbstractTableModel;
import java.util.ArrayList;
import java.util.List;
/**
* @author JayDi85
*/
public class TournamentMatchesTableModel extends AbstractTableModel {
public static final int ACTION_COLUMN = 4; // column the action is located
private final String[] columnNames = new String[]{"Round Number", "Players", "State", "Result", "Action"};
private TournamentGameView[] games = new TournamentGameView[0];
private boolean watchingAllowed;
public void loadData(TournamentView tournament) {
List<TournamentGameView> views = new ArrayList<>();
watchingAllowed = tournament.isWatchingAllowed();
for (RoundView round : tournament.getRounds()) {
for (TournamentGameView game : round.getGames()) {
views.add(game);
}
}
games = views.toArray(new TournamentGameView[0]);
this.fireTableDataChanged();
}
public String getTableAndGameInfo(int row) {
return this.games[row].getTableId().toString() + ";" + games[row].toString();
}
public String findTableAndGameInfoByRow(int row) {
if (row >= 0 && row < this.games.length) {
return getTableAndGameInfo(row);
} else {
return null;
}
}
public int findRowByTableAndGameInfo(String tableAndGame) {
for (int i = 0; i < this.games.length; i++) {
String rowID = this.games[i].getTableId().toString() + ";" + this.games[i].toString();
if (tableAndGame.equals(rowID)) {
return i;
}
}
return -1;
}
@Override
public int getRowCount() {
return games.length;
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public Object getValueAt(int arg0, int arg1) {
switch (arg1) {
case 0:
return Integer.toString(games[arg0].getRoundNum());
case 1:
return games[arg0].getPlayers();
case 2:
return games[arg0].getState();
case 3:
return games[arg0].getResult();
case 4:
// if (games[arg0].getState().equals("Finished")) {
// return "Replay";
// }
if (watchingAllowed && games[arg0].getState().startsWith("Dueling")) {
return "Watch";
}
return "";
case 5:
return games[arg0].getTableId().toString();
case 6:
return games[arg0].getMatchId().toString();
case 7:
return games[arg0].getGameId().toString();
}
return "";
}
@Override
public String getColumnName(int columnIndex) {
String colName = "";
if (columnIndex <= getColumnCount()) {
colName = columnNames[columnIndex];
}
return colName;
}
@Override
public Class getColumnClass(int columnIndex) {
return String.class;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == ACTION_COLUMN;
}
}

View file

@ -5,12 +5,16 @@ import mage.client.SessionHandler;
import mage.client.chat.ChatPanelBasic;
import mage.client.dialog.PreferencesDialog;
import mage.client.table.TablesButtonColumn;
import mage.client.table.TablesUtil;
import mage.client.table.TournamentMatchesTableModel;
import mage.client.util.Format;
import mage.client.util.GUISizeHelper;
import mage.client.util.gui.TableUtil;
import mage.client.util.gui.countryBox.CountryCellRenderer;
import mage.constants.PlayerAction;
import mage.view.*;
import mage.view.TournamentPlayerView;
import mage.view.TournamentView;
import mage.view.UserRequestMessage;
import org.apache.log4j.Logger;
import javax.swing.*;
@ -18,7 +22,6 @@ import javax.swing.table.AbstractTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@ -74,7 +77,11 @@ public class TournamentPanel extends javax.swing.JPanel {
Action action = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
int modelRow = Integer.valueOf(e.getActionCommand());
String searchID = e.getActionCommand();
int modelRow = TablesUtil.findTableRowFromSearchId(matchesModel, searchID);
if (modelRow == -1) {
return;
}
String state = (String) tableMatches.getValueAt(modelRow, tableMatches.convertColumnIndexToView(2));
String actionText = (String) tableMatches.getValueAt(modelRow, tableMatches.convertColumnIndexToView(TournamentMatchesTableModel.ACTION_COLUMN));
@ -132,7 +139,7 @@ public class TournamentPanel extends javax.swing.JPanel {
private void saveDividerLocations() {
// save panel sizes and divider locations.
Rectangle rec = MageFrame.getDesktop().getBounds();
String sb = Double.toString(rec.getWidth()) + 'x' + Double.toString(rec.getHeight());
String sb = Double.toString(rec.getWidth()) + 'x' + rec.getHeight();
PreferencesDialog.saveValue(PreferencesDialog.KEY_MAGE_PANEL_LAST_SIZE, sb);
PreferencesDialog.saveValue(PreferencesDialog.KEY_TOURNAMENT_DIVIDER_LOCATION_1, Integer.toString(this.jSplitPane1.getDividerLocation()));
PreferencesDialog.saveValue(PreferencesDialog.KEY_TOURNAMENT_DIVIDER_LOCATION_2, Integer.toString(this.jSplitPane2.getDividerLocation()));
@ -142,7 +149,7 @@ public class TournamentPanel extends javax.swing.JPanel {
Rectangle rec = MageFrame.getDesktop().getBounds();
if (rec != null) {
String size = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_MAGE_PANEL_LAST_SIZE, null);
String sb = Double.toString(rec.getWidth()) + 'x' + Double.toString(rec.getHeight());
String sb = Double.toString(rec.getWidth()) + 'x' + rec.getHeight();
// use divider positions only if screen size is the same as it was the time the settings were saved
if (size != null && size.equals(sb)) {
String location = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_TOURNAMENT_DIVIDER_LOCATION_1, null);
@ -585,88 +592,6 @@ class TournamentPlayersTableModel extends AbstractTableModel {
}
class TournamentMatchesTableModel extends AbstractTableModel {
public static final int ACTION_COLUMN = 4; // column the action is located
private final String[] columnNames = new String[]{"Round Number", "Players", "State", "Result", "Action"};
private TournamentGameView[] games = new TournamentGameView[0];
private boolean watchingAllowed;
public void loadData(TournamentView tournament) {
List<TournamentGameView> views = new ArrayList<>();
watchingAllowed = tournament.isWatchingAllowed();
for (RoundView round : tournament.getRounds()) {
for (TournamentGameView game : round.getGames()) {
views.add(game);
}
}
games = views.toArray(new TournamentGameView[0]);
this.fireTableDataChanged();
}
@Override
public int getRowCount() {
return games.length;
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public Object getValueAt(int arg0, int arg1) {
switch (arg1) {
case 0:
return Integer.toString(games[arg0].getRoundNum());
case 1:
return games[arg0].getPlayers();
case 2:
return games[arg0].getState();
case 3:
return games[arg0].getResult();
case 4:
// if (games[arg0].getState().equals("Finished")) {
// return "Replay";
// }
if (watchingAllowed && games[arg0].getState().startsWith("Dueling")) {
return "Watch";
}
return "";
case 5:
return games[arg0].getTableId().toString();
case 6:
return games[arg0].getMatchId().toString();
case 7:
return games[arg0].getGameId().toString();
}
return "";
}
@Override
public String getColumnName(int columnIndex) {
String colName = "";
if (columnIndex <= getColumnCount()) {
colName = columnNames[columnIndex];
}
return colName;
}
@Override
public Class getColumnClass(int columnIndex) {
return String.class;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == ACTION_COLUMN;
}
}
class UpdateTournamentTask extends SwingWorker<Void, TournamentView> {
@ -709,4 +634,4 @@ class UpdateTournamentTask extends SwingWorker<Void, TournamentView> {
}
}
}
}

View file

@ -354,6 +354,13 @@ public class ScryfallImageSupportCards {
// TODO: remove Grand Prix fix after scryfall fix image's link (that's link must be work: https://img.scryfall.com/cards/large/en/pgpx/2016b.jpg )
put("GPX/Sword of Feast and Famine", "https://img.scryfall.com/cards/large/en/pgpx/1%E2%98%85.jpg");
// TODO: remove after scryfall add lands to RNA (that's link must works: https://api.scryfall.com/cards/rna/262/en?format=image)
put("RNA/Plains", "https://api.scryfall.com/cards/grn/260/en?format=image");
put("RNA/Island", "https://api.scryfall.com/cards/grn/261/en?format=image");
put("RNA/Swamp", "https://api.scryfall.com/cards/grn/262/en?format=image");
put("RNA/Mountain", "https://api.scryfall.com/cards/grn/263/en?format=image");
put("RNA/Forest", "https://api.scryfall.com/cards/grn/264/en?format=image");
}
};

View file

@ -70,10 +70,7 @@ public class ScryfallSymbolsSource implements Iterable<DownloadJob> {
}
// gen symbols list
ArrayList<String> allMageSymbols = new ArrayList<>();
for (int i = 0; i < SYMBOLS_LIST.length; i++) {
allMageSymbols.add(SYMBOLS_LIST[i]);
}
List<String> allMageSymbols = Arrays.asList(SYMBOLS_LIST);
for (Integer i = SYMBOLS_NUMBER_START; i <= SYMBOLS_NUMBER_END; i++) {
allMageSymbols.add(String.valueOf(SYMBOLS_NUMBER_START + i));
}
@ -111,21 +108,17 @@ public class ScryfallSymbolsSource implements Iterable<DownloadJob> {
if (destFile.exists() && (destFile.length() > 0)) {
continue;
}
FileOutputStream stream = null;
try {
try(FileOutputStream stream = new FileOutputStream(destFile)) {
// base64 transform
String data64 = foundedData.get(searchCode);
Base64.Decoder dec = Base64.getDecoder();
byte[] fileData = dec.decode(data64);
stream = new FileOutputStream(destFile);
stream.write(fileData);
LOGGER.info("New svg symbol downloaded: " + needCode);
} catch (Exception e) {
LOGGER.error("Can't decode svg icon and save to file: " + destFile.getPath() + ", reason: " + e.getMessage());
} finally {
StreamUtils.closeQuietly(stream);
}
}
}
@ -166,7 +159,7 @@ public class ScryfallSymbolsSource implements Iterable<DownloadJob> {
org.jsoup.nodes.Document doc = CardImageUtils.downloadHtmlDocument(CSS_SOURCE_URL);
org.jsoup.select.Elements cssList = doc.select(CSS_SOURCE_SELECTOR);
if (cssList.size() == 1) {
this.cssUrl = cssList.first().attr("href").toString();
this.cssUrl = cssList.first().attr("href");
}
if (this.cssUrl.isEmpty()) {

View file

@ -26,8 +26,8 @@ import java.awt.event.ItemEvent;
import java.io.*;
import java.net.*;
import java.nio.file.AccessDeniedException;
import java.util.List;
import java.util.*;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@ -817,13 +817,9 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
// can save result
if (isDownloadOK & httpConn != null) {
// save data to temp
OutputStream out = null;
OutputStream tfileout = null;
InputStream in = null;
try {
in = new BufferedInputStream(httpConn.getInputStream());
tfileout = new TFileOutputStream(fileTempImage);
out = new BufferedOutputStream(tfileout);
try (InputStream in = new BufferedInputStream(httpConn.getInputStream());
OutputStream tfileout = new TFileOutputStream(fileTempImage);
OutputStream out = new BufferedOutputStream(tfileout)) {
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) != -1) {
@ -849,13 +845,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
}
out.write(buf, 0, len);
}
} finally {
StreamUtils.closeQuietly(in);
StreamUtils.closeQuietly(out);
StreamUtils.closeQuietly(tfileout);
}
// TODO: add two faces card correction? (WTF)
// SAVE final data
if (fileTempImage.exists()) {
@ -912,7 +902,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
this.cardsDownloadQueue.removeAll(downloadedCards);
this.cardsMissing.removeAll(downloadedCards);
if (this.cardsDownloadQueue.size() == 0) {
if (this.cardsDownloadQueue.isEmpty()) {
// stop download
uiDialog.getProgressBar().setString("0 images remaining. Please close.");
} else {

View file

@ -126,6 +126,15 @@ public final class CardImageUtils {
return path;
}
public static String fixSetNameForWindows(String set) {
// windows can't create con folders
if (set.equals("CON") || set.equals("con")) {
return "COX";
} else {
return set;
}
}
public static String buildImagePathToTokens() {
String imagesPath = getImagesDir() + File.separator;
@ -159,14 +168,14 @@ public final class CardImageUtils {
String imagesPath = getImagesDir() + File.separator;
if (PreferencesDialog.isSaveImagesToZip()) {
return imagesPath + set + ".zip" + File.separator + set + File.separator;
return imagesPath + fixSetNameForWindows(set) + ".zip" + File.separator + fixSetNameForWindows(set) + File.separator;
} else {
return imagesPath + set + File.separator;
return imagesPath + fixSetNameForWindows(set) + File.separator;
}
}
private static String buildImagePathToSetAsToken(String set) {
return buildImagePathToTokens() + set + File.separator;
return buildImagePathToTokens() + fixSetNameForWindows(set) + File.separator;
}
public static String buildImagePathToCard(CardDownloadData card) {
@ -217,7 +226,7 @@ public final class CardImageUtils {
}
public static String generateFaceImagePath(String cardname, String set) {
return getImagesDir() + File.separator + "FACE" + File.separator + set + File.separator + prepareCardNameForFile(cardname) + ".jpg";
return getImagesDir() + File.separator + "FACE" + File.separator + fixSetNameForWindows(set) + File.separator + prepareCardNameForFile(cardname) + ".jpg";
}
public static String generateTokenDescriptorImagePath(CardDownloadData card) {

View file

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

View file

@ -61,6 +61,7 @@ public class SessionImpl implements Session {
private boolean canceled = false;
private boolean jsonLogActive = false;
private String lastError = "";
static {
debugMode = System.getProperty("debug.mage") != null;
@ -195,20 +196,29 @@ public class SessionImpl implements Session {
&& handleRemotingTaskExceptions(new RemotingTask() {
@Override
public boolean run() throws Throwable {
setLastError("");
logger.info("Trying to log-in as " + getUserName() + " to XMAGE server at " + connection.getHost() + ':' + connection.getPort());
boolean registerResult;
if (connection.getAdminPassword() == null) {
// for backward compatibility. don't remove twice call - first one does nothing but for version checking
registerResult = server.connectUser(connection.getUsername(), connection.getPassword(), sessionId, client.getVersion(), connection.getUserIdStr());
if (registerResult) {
server.setUserData(connection.getUsername(), sessionId, connection.getUserData(), client.getVersion().toString(), connection.getUserIdStr());
}
} else {
registerResult = server.connectAdmin(connection.getAdminPassword(), sessionId, client.getVersion());
}
if (registerResult) {
serverState = server.getServerState();
// client side check for incompatible versions
if (client.getVersion().compareTo(serverState.getVersion()) != 0) {
String err = "Client and server versions are incompatible.";
setLastError(err);
logger.info(err);
disconnect(false);
return false;
}
if (!connection.getUsername().equals("Admin")) {
server.setUserData(connection.getUsername(), sessionId, connection.getUserData(), client.getVersion().toString(), connection.getUserIdStr());
updateDatabase(connection.isForceDBComparison(), serverState);
}
logger.info("Logged-in as " + getUserName() + " to MAGE server at " + connection.getHost() + ':' + connection.getPort());
@ -1621,6 +1631,15 @@ public class SessionImpl implements Session {
this.jsonLogActive = jsonLogActive;
}
private void setLastError(String error) {
lastError = error;
}
@Override
public String getLastError() {
return lastError;
}
}
class MageAuthenticator extends Authenticator {

View file

@ -1,4 +1,3 @@
package mage.remote.interfaces;
import mage.remote.Connection;
@ -37,10 +36,12 @@ public interface Connect {
boolean muteUserChat(String userName, long durationMinute);
boolean setActivation(String userName, boolean active);
boolean toggleActivation(String userName);
boolean lockUser(String userName, long durationMinute);
String getSessionId();
String getLastError();
}

View file

@ -14,9 +14,11 @@ public class MageVersion implements Serializable, Comparable<MageVersion> {
*/
public final static int MAGE_VERSION_MAJOR = 1;
public final static int MAGE_VERSION_MINOR = 4;
public final static int MAGE_VERSION_PATCH = 32;
public final static int MAGE_VERSION_PATCH = 33;
public final static String MAGE_EDITION_INFO = ""; // set "-beta" for 1.4.32-betaV0
public final static String MAGE_VERSION_MINOR_PATCH = "V0";
public final static String MAGE_VERSION_MINOR_PATCH = "V1"; // default V0
// strict mode
private final static 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 final int major;
private final int minor;
@ -74,7 +76,9 @@ public class MageVersion implements Serializable, Comparable<MageVersion> {
if (patch != o.patch) {
return patch - o.patch;
}
if (MAGE_VERSION_MINOR_PATCH_MUST_BE_SAME && !minorPatch.equals(o.minorPatch)) {
return minorPatch.compareTo(o.minorPatch);
}
return editionInfo.compareTo(o.editionInfo);
}
}

View file

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

View file

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

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.32</version>
<version>1.4.33</version>
</parent>
<groupId>org.mage</groupId>

View file

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

View file

@ -631,7 +631,7 @@ public class Commander extends Constructed {
|| cn.equals("krark-clan ironworks") || cn.equals("krenko, mob boss")
|| cn.equals("krosan restorer") || cn.equals("laboratory maniac")
|| cn.equals("leonin relic-warder") || cn.equals("leyline of the void")
|| cn.equals("memnarch") || cn.equals("memnarch")
|| cn.equals("memnarch")
|| cn.equals("meren of clan nel toth") || cn.equals("mikaeus, the unhallowed")
|| cn.equals("mindcrank") || cn.equals("mindslaver")
|| cn.equals("minion reflector") || cn.equals("mycosynth lattice")
@ -649,7 +649,7 @@ public class Commander extends Constructed {
|| cn.equals("sunder")
|| cn.equals("storm cauldron") || cn.equals("teferi's puzzle box")
|| cn.equals("tangle wire")
|| cn.equals("teferi, mage of zhalfir") || cn.equals("teferi, mage of zhalfir")
|| cn.equals("teferi, mage of zhalfir")
|| cn.equals("tezzeret the seeker") || cn.equals("time stretch")
|| cn.equals("time warp") || cn.equals("training grounds")
|| cn.equals("triskelavus") || cn.equals("triskelion")

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.32</version>
<version>1.4.33</version>
</parent>
<artifactId>mage-game-twoplayerduel</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.32</version>
<version>1.4.33</version>
</parent>
<artifactId>mage-player-ai-draftbot</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.32</version>
<version>1.4.33</version>
</parent>
<artifactId>mage-player-ai-ma</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.32</version>
<version>1.4.33</version>
</parent>
<artifactId>mage-player-ai</artifactId>

View file

@ -500,6 +500,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
if (target.getOriginalTarget() instanceof TargetPermanent) {
List<Permanent> targets;
TargetPermanent t = (TargetPermanent) target.getOriginalTarget();
boolean outcomeTargets = true;
if (outcome.isGood()) {
targets = threats(abilityControllerId, source == null ? null : source.getSourceId(), ((TargetPermanent) target).getFilter(), game, target.getTargets());
@ -512,6 +513,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
outcomeTargets = false;
//targets = game.getBattlefield().getActivePermanents(((TargetPermanent)target).getFilter(), playerId, game);
}
if (targets.isEmpty() && target.isRequired()) {
targets = game.getBattlefield().getActivePermanents(t.getFilter(), playerId, game);
}
for (Permanent permanent : targets) {
if (((TargetPermanent) target).canTarget(abilityControllerId, permanent.getId(), source, game)) {
target.addTarget(permanent.getId(), source, game);

View file

@ -0,0 +1,254 @@
Biogenic Ooze:1000
Angel of Grace:986
Rakdos, the Showstopper:974
Skarrgan Hellkite:964
Spawn of Mayhem:954
Seraph of the Scales:945
Hydroid Krasis:937
Domri, Chaos Bringer:929
Ethereal Absolution:922
Lawmage's Binding:915
Electrodominance:908
Sphinx of Foresight:902
Ravager Wurm:896
Bedevil:891
Mesmerizing Benthid:885
Zegana, Utopian Speaker:880
Thrash // Threat:875
Deputy of Detention:870
Mortify:865
Judith, the Scourge Diva:861
Gruul Spellbreaker:856
Pestilent Spirit:852
Dovin, Grand Arbiter:848
Warrant // Warden:843
Skewer the Critics:839
Sunder Shaman:836
Sharktocrab:832
Biomancer's Familiar:828
Prime Speaker Vannifar:824
Kaya's Wrath:821
Incubation Druid:817
Theater of Horrors:814
Frilled Mystic:810
Get the Point:807
Nikya of the Old Ways:804
Combine Guildmage:801
Rix Maadi Reveler:797
Growth-Chamber Guardian:794
Ministrant of Obligation:791
Frenzied Arynx:788
Teysa Karlov:785
Bedeck // Bedazzle:782
Precognitive Perception:779
Final Payment:776
Rhythm of the Wild:774
Captive Audience:771
End-Raze Forerunners:768
Lumbering Battlement:765
Rakdos Firewheeler:763
Senate Guildmage:760
Trollbred Guardian:757
Galloping Lizrog:755
Grotesque Demise:752
Skatewing Spy:749
Azorius Skyguard:747
Sphinx of New Prahv:744
Cry of the Carnarium:742
Dagger Caster:739
Immolation Shaman:737
Orzhov Enforcer:735
Consecrate // Consume:732
Aeromunculus:730
Windstorm Drake:727
Clear the Stage:725
Depose // Deploy:723
Revival // Revenge:720
Mass Manipulation:718
Senate Griffin:716
Biogenic Upgrade:713
Savage Smash:711
Unbreakable Formation:709
Applied Biomancy:707
Pitiless Pontiff:705
Hero of Precinct One:702
Summary Judgment:700
Gyre Engineer:698
Benthic Biomancer:696
Cult Guildmage:694
Zhur-Taa Goblin:691
Spirit of the Spires:689
Collision // Colossus:687
Pteramander:685
Flames of the Raze-Boar:683
Carnival // Carnage:681
Grasping Thrull:679
Hackrobat:677
Clan Guildmage:675
Imperious Oligarch:673
Scorchmark:670
Syndicate Guildmage:668
Gatebreaker Ram:666
Rampaging Rendhorn:664
Forbidding Spirit:662
Tithe Taker:660
Fireblade Artist:658
Azorius Knight-Arbiter:656
Simic Ascendancy:654
Guardian Project:652
Enraged Ceratok:650
Bolrac-Clan Crusher:648
Consign to the Pit:646
Repudiate // Replicate:644
Gruul Beastmaster:642
Gutterbones:640
Spire Mangler:638
Titanic Brawl:636
Dovin's Acuity:634
Incubation // Incongruity:633
Sky Tether:631
Basilica Bell-Haunt:629
Amplifire:627
Essence Capture:625
Arrester's Admonition:623
Chillbringer:621
Clamor Shaman:619
Syndicate Messenger:617
Rubblebelt Runner:615
Faerie Duelist:613
Burning-Tree Vandal:611
Sauroform Hybrid:609
Undercity's Embrace:607
Sphinx of the Guildpact:605
Growth Spiral:603
Orzhov Racketeers:602
Dead Revels:600
Vindictive Vampire:598
Priest of Forgotten Gods:596
Silhana Wayfinder:594
Rumbling Ruin:592
Skitter Eel:590
Wrecking Beast:588
Gateway Sneak:586
Sage's Row Savant:584
Gate Colossus:582
Swirling Torrent:580
Light Up the Stage:578
Senate Courier:576
Sentinel's Mark:574
Ghor-Clan Wrecker:572
Angelic Exaltation:571
Blade Juggler:569
Bring to Trial:567
Code of Constraint:565
Eyes Everywhere:563
Gravel-Hide Goblin:561
Absorb:559
Sphinx's Insight:557
Bladebrand:555
Hallowed Fountain:553
Verity Circle:551
Archway Angel:549
Breeding Pool:547
Twilight Panther:545
Resolute Watchdog:543
Gates Ablaze:541
Rakdos Roustabout:539
Rubblebelt Recluse:537
Mammoth Spider:535
Knight of the Last Breath:533
Territorial Boar:531
Glass of the Guildpact:529
Undercity Scavenger:527
Blood Crypt:525
Macabre Mockery:522
Steeple Creeper:520
Impassioned Orator:518
Arrester's Zeal:516
Kaya, Orzhov Usurper:514
Rubble Slinger:512
Emergency Powers:510
Plague Wight:508
Noxious Groodion:506
Civic Stalwart:503
Vizkopa Vampire:501
Rally to Battle:499
Gift of Strength:497
Stomping Ground:495
High Alert:492
Cindervines:490
Goblin Gathering:488
Storm Strike:486
Shimmer of Possibility:483
Bloodmist Infiltrator:481
Smelt-Ward Ignus:479
Footlight Fiend:477
Godless Shrine:474
Rakdos Trumpeter:472
Slimebind:469
Debtors' Transport:467
Spear Spewer:465
Stony Strength:462
Mirror March:460
Carrion Imp:457
Tome of the Guildpact:455
Open the Gates:452
Concordia Pegasus:450
Ill-Gotten Inheritance:447
Quench:445
Sylvan Brushstrider:442
Tenth District Veteran:439
Lavinia, Azorius Renegade:437
Drill Bit:434
Watchful Giant:431
Scuttlegator:428
Regenesis:426
Humongulus:423
Spikewheel Acrobat:420
Axebane Beast:417
Haazda Officer:414
Prying Eyes:411
Knight of Sorrows:408
Plaza of Harmony:405
Rafter Demon:402
Saruli Caretaker:399
Awaken the Erstwhile:396
Thought Collapse:392
Wilderness Reclamation:389
Act of Treason:386
Smothering Tithe:382
Tin Street Dodger:379
Catacomb Crocodile:375
Sagittars' Volley:371
Cavalcade of Calamity:368
Azorius Guildgate:364
Orzhov Guildgate:360
Bankrupt in Blood:356
Persistent Petitioners:352
Gateway Plaza:348
Simic Guildgate:343
Thirsting Shade:339
Justiciar's Portal:334
Font of Agonies:329
Tower Defense:325
Wall of Lost Thoughts:320
Rakdos Guildgate:314
Feral Maaka:309
Burn Bright:303
Gruul Guildgate:297
Expose to Daylight:291
Gruul Locket:285
Azorius Locket:278
Prowling Caracal:271
Simic Locket:263
Coral Commando:255
Screaming Shield:246
Junktroller:236
Scrabbling Claws:226
Orzhov Locket:214
Rampage of the Clans:201
Deface:186
Clear the Mind:168
Rakdos Locket:145
Rubble Reading:115
Root Snare:66
1 Biogenic Ooze:1000
2 Angel of Grace:986
3 Rakdos, the Showstopper:974
4 Skarrgan Hellkite:964
5 Spawn of Mayhem:954
6 Seraph of the Scales:945
7 Hydroid Krasis:937
8 Domri, Chaos Bringer:929
9 Ethereal Absolution:922
10 Lawmage's Binding:915
11 Electrodominance:908
12 Sphinx of Foresight:902
13 Ravager Wurm:896
14 Bedevil:891
15 Mesmerizing Benthid:885
16 Zegana, Utopian Speaker:880
17 Thrash // Threat:875
18 Deputy of Detention:870
19 Mortify:865
20 Judith, the Scourge Diva:861
21 Gruul Spellbreaker:856
22 Pestilent Spirit:852
23 Dovin, Grand Arbiter:848
24 Warrant // Warden:843
25 Skewer the Critics:839
26 Sunder Shaman:836
27 Sharktocrab:832
28 Biomancer's Familiar:828
29 Prime Speaker Vannifar:824
30 Kaya's Wrath:821
31 Incubation Druid:817
32 Theater of Horrors:814
33 Frilled Mystic:810
34 Get the Point:807
35 Nikya of the Old Ways:804
36 Combine Guildmage:801
37 Rix Maadi Reveler:797
38 Growth-Chamber Guardian:794
39 Ministrant of Obligation:791
40 Frenzied Arynx:788
41 Teysa Karlov:785
42 Bedeck // Bedazzle:782
43 Precognitive Perception:779
44 Final Payment:776
45 Rhythm of the Wild:774
46 Captive Audience:771
47 End-Raze Forerunners:768
48 Lumbering Battlement:765
49 Rakdos Firewheeler:763
50 Senate Guildmage:760
51 Trollbred Guardian:757
52 Galloping Lizrog:755
53 Grotesque Demise:752
54 Skatewing Spy:749
55 Azorius Skyguard:747
56 Sphinx of New Prahv:744
57 Cry of the Carnarium:742
58 Dagger Caster:739
59 Immolation Shaman:737
60 Orzhov Enforcer:735
61 Consecrate // Consume:732
62 Aeromunculus:730
63 Windstorm Drake:727
64 Clear the Stage:725
65 Depose // Deploy:723
66 Revival // Revenge:720
67 Mass Manipulation:718
68 Senate Griffin:716
69 Biogenic Upgrade:713
70 Savage Smash:711
71 Unbreakable Formation:709
72 Applied Biomancy:707
73 Pitiless Pontiff:705
74 Hero of Precinct One:702
75 Summary Judgment:700
76 Gyre Engineer:698
77 Benthic Biomancer:696
78 Cult Guildmage:694
79 Zhur-Taa Goblin:691
80 Spirit of the Spires:689
81 Collision // Colossus:687
82 Pteramander:685
83 Flames of the Raze-Boar:683
84 Carnival // Carnage:681
85 Grasping Thrull:679
86 Hackrobat:677
87 Clan Guildmage:675
88 Imperious Oligarch:673
89 Scorchmark:670
90 Syndicate Guildmage:668
91 Gatebreaker Ram:666
92 Rampaging Rendhorn:664
93 Forbidding Spirit:662
94 Tithe Taker:660
95 Fireblade Artist:658
96 Azorius Knight-Arbiter:656
97 Simic Ascendancy:654
98 Guardian Project:652
99 Enraged Ceratok:650
100 Bolrac-Clan Crusher:648
101 Consign to the Pit:646
102 Repudiate // Replicate:644
103 Gruul Beastmaster:642
104 Gutterbones:640
105 Spire Mangler:638
106 Titanic Brawl:636
107 Dovin's Acuity:634
108 Incubation // Incongruity:633
109 Sky Tether:631
110 Basilica Bell-Haunt:629
111 Amplifire:627
112 Essence Capture:625
113 Arrester's Admonition:623
114 Chillbringer:621
115 Clamor Shaman:619
116 Syndicate Messenger:617
117 Rubblebelt Runner:615
118 Faerie Duelist:613
119 Burning-Tree Vandal:611
120 Sauroform Hybrid:609
121 Undercity's Embrace:607
122 Sphinx of the Guildpact:605
123 Growth Spiral:603
124 Orzhov Racketeers:602
125 Dead Revels:600
126 Vindictive Vampire:598
127 Priest of Forgotten Gods:596
128 Silhana Wayfinder:594
129 Rumbling Ruin:592
130 Skitter Eel:590
131 Wrecking Beast:588
132 Gateway Sneak:586
133 Sage's Row Savant:584
134 Gate Colossus:582
135 Swirling Torrent:580
136 Light Up the Stage:578
137 Senate Courier:576
138 Sentinel's Mark:574
139 Ghor-Clan Wrecker:572
140 Angelic Exaltation:571
141 Blade Juggler:569
142 Bring to Trial:567
143 Code of Constraint:565
144 Eyes Everywhere:563
145 Gravel-Hide Goblin:561
146 Absorb:559
147 Sphinx's Insight:557
148 Bladebrand:555
149 Hallowed Fountain:553
150 Verity Circle:551
151 Archway Angel:549
152 Breeding Pool:547
153 Twilight Panther:545
154 Resolute Watchdog:543
155 Gates Ablaze:541
156 Rakdos Roustabout:539
157 Rubblebelt Recluse:537
158 Mammoth Spider:535
159 Knight of the Last Breath:533
160 Territorial Boar:531
161 Glass of the Guildpact:529
162 Undercity Scavenger:527
163 Blood Crypt:525
164 Macabre Mockery:522
165 Steeple Creeper:520
166 Impassioned Orator:518
167 Arrester's Zeal:516
168 Kaya, Orzhov Usurper:514
169 Rubble Slinger:512
170 Emergency Powers:510
171 Plague Wight:508
172 Noxious Groodion:506
173 Civic Stalwart:503
174 Vizkopa Vampire:501
175 Rally to Battle:499
176 Gift of Strength:497
177 Stomping Ground:495
178 High Alert:492
179 Cindervines:490
180 Goblin Gathering:488
181 Storm Strike:486
182 Shimmer of Possibility:483
183 Bloodmist Infiltrator:481
184 Smelt-Ward Ignus:479
185 Footlight Fiend:477
186 Godless Shrine:474
187 Rakdos Trumpeter:472
188 Slimebind:469
189 Debtors' Transport:467
190 Spear Spewer:465
191 Stony Strength:462
192 Mirror March:460
193 Carrion Imp:457
194 Tome of the Guildpact:455
195 Open the Gates:452
196 Concordia Pegasus:450
197 Ill-Gotten Inheritance:447
198 Quench:445
199 Sylvan Brushstrider:442
200 Tenth District Veteran:439
201 Lavinia, Azorius Renegade:437
202 Drill Bit:434
203 Watchful Giant:431
204 Scuttlegator:428
205 Regenesis:426
206 Humongulus:423
207 Spikewheel Acrobat:420
208 Axebane Beast:417
209 Haazda Officer:414
210 Prying Eyes:411
211 Knight of Sorrows:408
212 Plaza of Harmony:405
213 Rafter Demon:402
214 Saruli Caretaker:399
215 Awaken the Erstwhile:396
216 Thought Collapse:392
217 Wilderness Reclamation:389
218 Act of Treason:386
219 Smothering Tithe:382
220 Tin Street Dodger:379
221 Catacomb Crocodile:375
222 Sagittars' Volley:371
223 Cavalcade of Calamity:368
224 Azorius Guildgate:364
225 Orzhov Guildgate:360
226 Bankrupt in Blood:356
227 Persistent Petitioners:352
228 Gateway Plaza:348
229 Simic Guildgate:343
230 Thirsting Shade:339
231 Justiciar's Portal:334
232 Font of Agonies:329
233 Tower Defense:325
234 Wall of Lost Thoughts:320
235 Rakdos Guildgate:314
236 Feral Maaka:309
237 Burn Bright:303
238 Gruul Guildgate:297
239 Expose to Daylight:291
240 Gruul Locket:285
241 Azorius Locket:278
242 Prowling Caracal:271
243 Simic Locket:263
244 Coral Commando:255
245 Screaming Shield:246
246 Junktroller:236
247 Scrabbling Claws:226
248 Orzhov Locket:214
249 Rampage of the Clans:201
250 Deface:186
251 Clear the Mind:168
252 Rakdos Locket:145
253 Rubble Reading:115
254 Root Snare:66

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.32</version>
<version>1.4.33</version>
</parent>
<artifactId>mage-player-ai-mcts</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.32</version>
<version>1.4.33</version>
</parent>
<artifactId>mage-player-aiminimax</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.32</version>
<version>1.4.33</version>
</parent>
<artifactId>mage-player-human</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.32</version>
<version>1.4.33</version>
</parent>
<artifactId>mage-tournament-boosterdraft</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.32</version>
<version>1.4.33</version>
</parent>
<artifactId>mage-tournament-constructed</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.32</version>
<version>1.4.33</version>
</parent>
<artifactId>mage-tournament-sealed</artifactId>

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.32</version>
<version>1.4.33</version>
</parent>
<artifactId>mage-server-plugins</artifactId>

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.32</version>
<version>1.4.33</version>
</parent>
<artifactId>mage-server</artifactId>

View file

@ -56,9 +56,9 @@ public final class Main {
private static final File extensionFolder = new File("extensions");
public static final PluginClassLoader classLoader = new PluginClassLoader();
public static TransporterServer server;
protected static boolean testMode;
protected static boolean fastDbMode;
private static TransporterServer server;
private static boolean testMode;
private static boolean fastDbMode;
/**
* @param args the command line arguments
@ -418,8 +418,10 @@ public final class Main {
File[] files = directory.listFiles(
(dir, name) -> name.endsWith(".game")
);
for (File file : files) {
file.delete();
if(files != null) {
for (File file : files) {
file.delete();
}
}
}

View file

@ -1,14 +1,15 @@
package mage.server;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.Nonnull;
import mage.MageException;
import mage.players.net.UserData;
import org.apache.log4j.Logger;
import org.jboss.remoting.callback.InvokerCallbackHandler;
import javax.annotation.Nonnull;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author BetaSteward_at_googlemail.com
*/
@ -88,18 +89,15 @@ public enum SessionManager {
}
public boolean setUserData(String userName, String sessionId, UserData userData, String clientVersion, String userIdStr) throws MageException {
Session session = sessions.get(sessionId);
if (session != null) {
session.setUserData(userName, userData, clientVersion, userIdStr);
return true;
}
return false;
return getSession(sessionId)
.map(session -> session.setUserData(userName,userData, clientVersion, userIdStr))
.orElse(false);
}
public void disconnect(String sessionId, DisconnectReason reason) {
Session session = sessions.get(sessionId);
if (session != null) {
if (!sessions.containsKey(sessionId)) {
getSession(sessionId).ifPresent(session -> {
if (!isValidSession(sessionId)) {
// session was removed meanwhile by another thread so we can return
return;
}
@ -122,11 +120,11 @@ public enum SessionManager {
default:
logger.trace("endSession: unexpected reason " + reason.toString() + " - sessionId: " + sessionId);
}
}
});
}
/**
* Admin requested the disconnect of a user
*
@ -150,11 +148,9 @@ public enum SessionManager {
}
private Optional<User> getUserFromSession(String sessionId) {
Optional<Session> session = getSession(sessionId);
if (!session.isPresent()) {
return Optional.empty();
}
return UserManager.instance.getUser(session.get().getUserId());
return getSession(sessionId)
.flatMap(s -> UserManager.instance.getUser(s.getUserId()));
}
public void endUserSession(String sessionId, String userSessionId) {
@ -164,11 +160,8 @@ public enum SessionManager {
}
public boolean isAdmin(String sessionId) {
Session admin = sessions.get(sessionId);
if (admin != null) {
return admin.isAdmin();
}
return false;
return getSession(sessionId).map(Session::isAdmin).orElse(false);
}
public boolean isValidSession(@Nonnull String sessionId) {
@ -185,11 +178,9 @@ public enum SessionManager {
}
public boolean extendUserSession(String sessionId, String pingInfo) {
Session session = sessions.get(sessionId);
if (session != null) {
return UserManager.instance.extendUserSession(session.getUserId(), pingInfo);
}
return false;
return getSession(sessionId)
.map(session -> UserManager.instance.extendUserSession(session.getUserId(), pingInfo))
.orElse(false);
}
public void sendErrorMessageToClient(String sessionId, String message) {

View file

@ -927,12 +927,10 @@ public class TableController {
public boolean isTournamentStillValid() {
if (table.getTournament() != null) {
if (table.getState() != TableState.WAITING && table.getState() != TableState.READY_TO_START && table.getState() != TableState.STARTING) {
TournamentController tournamentController = TournamentManager.instance.getTournamentController(table.getTournament().getId());
if (tournamentController != null) {
return tournamentController.isTournamentStillValid(table.getState());
} else {
return false;
}
return TournamentManager.instance.getTournamentController(table.getTournament().getId())
.map(tc -> tc.isTournamentStillValid(table.getState()))
.orElse(false);
} else {
// check if table creator is still a valid user, if not removeUserFromAllTablesAndChat table
return UserManager.instance.getUser(userId).isPresent();

View file

@ -334,10 +334,10 @@ public class User {
}
for (Iterator<Entry<UUID, UUID>> iterator = userTournaments.entrySet().iterator(); iterator.hasNext();) {
Entry<UUID, UUID> next = iterator.next();
TournamentController tournamentController = TournamentManager.instance.getTournamentController(next.getValue());
if (tournamentController != null) {
Optional<TournamentController> tournamentController = TournamentManager.instance.getTournamentController(next.getValue());
if (tournamentController.isPresent()) {
ccTournamentStarted(next.getValue(), next.getKey());
tournamentController.rejoin(next.getKey());
tournamentController.get().rejoin(next.getKey());
} else {
iterator.remove(); // tournament has ended meanwhile
}

View file

@ -70,13 +70,8 @@ public enum UserManager {
final Lock r = lock.readLock();
r.lock();
try {
Optional<User> u = users.values().stream().filter(user -> user.getName().equals(userName))
return users.values().stream().filter(user -> user.getName().equals(userName))
.findFirst();
if (u.isPresent()) {
return u;
} else {
return Optional.empty();
}
} finally {
r.unlock();
}
@ -84,7 +79,7 @@ public enum UserManager {
}
public Collection<User> getUsers() {
ArrayList<User> userList = new ArrayList<>();
List<User> userList = new ArrayList<>();
final Lock r = lock.readLock();
r.lock();
try {

View file

@ -627,7 +627,7 @@ public class GameController implements GameCallback {
for (MatchPlayer p : TableManager.instance.getTable(tableId).getMatch().getPlayers()) {
if (p.getPlayer().getId().equals(userIdRequester)) {
Optional<User> u = UserManager.instance.getUser(origId);
if (u != null && u.isPresent() && p.getDeck() != null) {
if (u.isPresent() && p.getDeck() != null) {
u.get().ccViewLimitedDeck(p.getDeck(), tableId, requestsOpen, true);
}
}

View file

@ -16,8 +16,8 @@ public enum TournamentManager {
instance;
private final ConcurrentHashMap<UUID, TournamentController> controllers = new ConcurrentHashMap<>();
public TournamentController getTournamentController(UUID tournamentId) {
return controllers.get(tournamentId);
public Optional<TournamentController> getTournamentController(UUID tournamentId) {
return Optional.ofNullable(controllers.get(tournamentId));
}
public void createTournamentSession(Tournament tournament, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId) {

View file

@ -7,9 +7,12 @@ import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.util.RandomUtil;
@ -433,6 +436,13 @@ public final class SystemUtil {
game.addPlane((mage.game.command.Plane) plane, null, player.getId());
continue;
}
} else if ("loyalty".equalsIgnoreCase(command.zone)) {
for (Permanent perm : game.getBattlefield().getAllActivePermanents(player.getId())) {
if (perm.getName().equals(command.cardName) && perm.getCardType().contains(CardType.PLANESWALKER)) {
perm.addCounters(CounterType.LOYALTY.createInstance(command.Amount), null, game);
}
}
continue;
}
Zone gameZone;

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.32</version>
<version>1.4.33</version>
</parent>
<groupId>org.mage</groupId>

View file

@ -34,7 +34,7 @@ public final class AbandonHope extends CardImpl {
this.addAbility(ability);
// Look at target opponent's hand and choose X cards from it. That player discards those cards.
ManacostVariableValue manaX = new ManacostVariableValue();
ManacostVariableValue manaX = ManacostVariableValue.instance;
this.getSpellAbility().addEffect(new DiscardCardYouChooseTargetEffect(manaX, TargetController.ANY));
this.getSpellAbility().addTarget(new TargetPlayer());
this.getSpellAbility().setCostAdjuster(AbandonHopeAdjuster.instance);

View file

@ -1,7 +1,6 @@
package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
@ -14,14 +13,15 @@ import mage.constants.*;
import mage.game.Game;
import mage.players.Player;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class AdamaroFirstToDesire extends CardImpl {
public AdamaroFirstToDesire(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{R}{R}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{R}");
addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.SPIRIT);
@ -46,7 +46,7 @@ class MostCardsInOpponentsHandCount implements DynamicValue {
@Override
public int calculate(Game game, Ability source, Effect effect) {
int maxCards = 0;
for (UUID opponentId: game.getOpponents(source.getControllerId())) {
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
Player opponent = game.getPlayer(opponentId);
if (opponent != null) {
int cards = opponent.getHand().size();
@ -60,7 +60,7 @@ class MostCardsInOpponentsHandCount implements DynamicValue {
@Override
public DynamicValue copy() {
return new mage.abilities.dynamicvalue.common.CardsInControllerHandCount();
return new MostCardsInOpponentsHandCount();
}
@Override

View file

@ -36,7 +36,7 @@ public final class AeonChronicler extends CardImpl {
this.toughness = new MageInt(0);
// Aeon Chronicler's power and toughness are each equal to the number of cards in your hand.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(new CardsInControllerHandCount(), Duration.EndOfGame)));
this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(CardsInControllerHandCount.instance, Duration.EndOfGame)));
// Suspend X-{X}{3}{U}. X can't be 0.
this.addAbility(new SuspendAbility(Integer.MAX_VALUE, new ManaCostsImpl("{3}{U}"), this, true));

View file

@ -25,7 +25,7 @@ public final class AetherMutation extends CardImpl {
this.getSpellAbility().addEffect(new ReturnToHandTargetEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
// create X 1/1 green Saproling creature tokens, where X is that creature's converted mana cost.
this.getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), new TargetConvertedManaCost()));
this.getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), TargetConvertedManaCost.instance));
}
public AetherMutation(final AetherMutation card) {

View file

@ -2,23 +2,22 @@ package mage.cards.a;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.Cost;
import mage.abilities.costs.VariableCostImpl;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.CostAdjuster;
import mage.abilities.costs.common.DiscardTargetCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.InfoEffect;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.common.FilterCreatureCard;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.stack.StackObject;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.common.TargetCardInHand;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetadjustment.TargetAdjuster;
/**
*
@ -30,10 +29,16 @@ public final class AetherTide extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{U}");
// As an additional cost to cast Aether Tide, discard X creature cards.
this.getSpellAbility().addCost(new AetherTideCost());
Ability ability = new SimpleStaticAbility(Zone.ALL, new InfoEffect("As an additional cost to cast {this}, discard X creature cards"));
ability.setRuleAtTheTop(true);
this.addAbility(ability);
// Return X target creatures to their owners' hands.
this.getSpellAbility().addEffect(new ReturnToHandTargetPermanentEffect());
Effect effect = new ReturnToHandTargetEffect(true);
effect.setText("Return X target creatures to their owners' hands");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().setTargetAdjuster(AetherTideTargetAdjuster.instance);
this.getSpellAbility().setCostAdjuster(AetherTideCostAdjuster.instance);
}
@ -47,98 +52,25 @@ public final class AetherTide extends CardImpl {
}
}
class AetherTideCost extends VariableCostImpl {
public AetherTideCost() {
super("discard X creature cards");
text = "As an additional cost to cast {this}, discard X creature cards";
}
public AetherTideCost(AetherTideCost cost) {
super(cost);
}
enum AetherTideTargetAdjuster implements TargetAdjuster {
instance;
@Override
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
return (game.getPlayer(controllerId).getHand().count(new FilterCreatureCard(), game) > 0);
public void adjustTargets(Ability ability, Game game) {
ability.getTargets().clear();
int xValue = ability.getManaCostsToPay().getX();
ability.addTarget(new TargetCreaturePermanent(xValue, xValue, new FilterCreaturePermanent(), false));
}
@Override
public int getMaxValue(Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
return controller.getHand().count(new FilterCreatureCard(), game);
}
return 0;
}
@Override
public int getMinValue(Ability source, Game game) {
return 0;
}
@Override
public Cost getFixedCostsFromAnnouncedValue(int xValue) {
TargetCardInHand target = new TargetCardInHand(xValue, new FilterCreatureCard());
return new DiscardTargetCost(target);
}
@Override
public int announceXValue(Ability source, Game game) {
int xValue = 0;
Player controller = game.getPlayer(source.getControllerId());
StackObject stackObject = game.getStack().getStackObject(source.getId());
if (controller != null
&& stackObject != null) {
xValue = controller.announceXCost(getMinValue(source, game), getMaxValue(source, game),
"Announce the number of creature cards to discard", game, source, this);
}
return xValue;
}
@Override
public AetherTideCost copy() {
return new AetherTideCost(this);
}
}
class ReturnToHandTargetPermanentEffect extends OneShotEffect {
public ReturnToHandTargetPermanentEffect() {
super(Outcome.ReturnToHand);
setText("Return X target creatures to their owners' hands");
}
public ReturnToHandTargetPermanentEffect(final ReturnToHandTargetPermanentEffect effect) {
super(effect);
}
enum AetherTideCostAdjuster implements CostAdjuster {
instance;
@Override
public ReturnToHandTargetPermanentEffect copy() {
return new ReturnToHandTargetPermanentEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
int xPaid = source.getCosts().getVariableCosts().get(0).getAmount();
if (controller != null
&& xPaid > 0) {
int available = game.getBattlefield().count(new FilterCreaturePermanent(),
source.getSourceId(),
source.getControllerId(), game);
if (available > 0) {
TargetPermanent target = new TargetPermanent(Math.min(xPaid, available),
xPaid,
new FilterCreaturePermanent("creatures to return to their owner's hands"),
true);
if (controller.chooseTarget(outcome.Detriment, target, source, game)) {
controller.moveCards(new CardsImpl(target.getTargets()), Zone.HAND, source, game);
}
return true;
}
public void adjustCosts(Ability ability, Game game) {
int xValue = ability.getManaCostsToPay().getX();
if (xValue > 0) {
ability.addCost(new DiscardTargetCost(new TargetCardInHand(xValue, xValue, new FilterCreatureCard("creature cards"))));
}
return false;
}
}

View file

@ -0,0 +1,104 @@
package mage.cards.a;
import java.util.UUID;
import mage.MageObjectReference;
import mage.constants.SubType;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.DestroyAttachedToEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.constants.Outcome;
import mage.target.TargetPermanent;
import mage.abilities.keyword.EnchantAbility;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.watchers.common.AttackedThisTurnWatcher;
/**
*
* @author jeffwadsworth
*/
public final class Aggression extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
static {
filter.add(Predicates.not(new SubtypePredicate(SubType.WALL)));
}
public Aggression(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}");
this.subtype.add(SubType.AURA);
// Enchant non-Wall creature
TargetPermanent auraTarget = new TargetPermanent(filter);
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// Enchanted creature has first strike and trample.
Ability ability2 = new SimpleStaticAbility(
Zone.BATTLEFIELD,
new GainAbilityAttachedEffect(
FirstStrikeAbility.getInstance(),
AttachmentType.AURA));
ability2.addEffect(new GainAbilityAttachedEffect(
TrampleAbility.getInstance(),
AttachmentType.AURA));
this.addAbility(ability2);
// At the beginning of the end step of enchanted creature's controller, destroy that creature if it didn't attack this turn.
this.addAbility(new ConditionalTriggeredAbility(
new AtTheBeginOfNextEndStepDelayedTriggeredAbility(
new DestroyAttachedToEffect("enchanted"),
TargetController.CONTROLLER_ATTACHED_TO),
DidNotAttackedThisTurnEnchantedCondition.instance,
"At the beginning of the end step of enchanted creature's controller, destroy that creature if it didn't attack this turn."),
new AttackedThisTurnWatcher());
}
private Aggression(final Aggression card) {
super(card);
}
@Override
public Aggression copy() {
return new Aggression(this);
}
}
enum DidNotAttackedThisTurnEnchantedCondition implements Condition {
instance;
@Override
public boolean apply(Game game, Ability source) {
Permanent auraPermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (auraPermanent != null) {
Permanent enchantedPermanent = game.getPermanent(auraPermanent.getAttachedTo());
AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class);
return enchantedPermanent != null
&& watcher != null
&& !watcher.getAttackedThisTurnCreatures().contains(
new MageObjectReference(enchantedPermanent, game));
}
return false;
}
}

View file

@ -40,7 +40,7 @@ public final class AgonizingDemise extends CardImpl {
//If Agonizing Demise was kicked, it deals damage equal to that creature's power to the creature's controller.
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new DamageTargetControllerEffect(new TargetPermanentPowerCount()),
new DamageTargetControllerEffect(TargetPermanentPowerCount.instance),
KickedCondition.instance,
"if this spell was kicked, it deals damage equal to that creature's power to the creature's controller."));

View file

@ -42,7 +42,7 @@ public final class AirdropCondor extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// {1}{R}, Sacrifice a Goblin creature: Airdrop Condor deals damage equal to the sacrificed creature's power to any target.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new SacrificeCostCreaturesPower()), new ManaCostsImpl("{1}{R}"));
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(SacrificeCostCreaturesPower.instance), new ManaCostsImpl("{1}{R}"));
ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(filter)));
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);

View file

@ -49,7 +49,7 @@ public final class AjaniCallerOfThePride extends CardImpl {
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
// -8: create X 2/2 white Cat creature tokens, where X is your life total.
this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new CatToken(), new ControllerLifeCount()), -8));
this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new CatToken(), ControllerLifeCount.instance), -8));
}
public AjaniCallerOfThePride(final AjaniCallerOfThePride card) {

View file

@ -44,7 +44,7 @@ public final class AjaniValiantProtector extends CardImpl {
this.addAbility(new LoyaltyAbility(new RevealCardsFromLibraryUntilEffect(new FilterCreatureCard(), Zone.HAND, Zone.LIBRARY), 1));
// -11: Put X +1/+1 counters on target creature, where X is your life total. That creature gains trample until end of turn.
Effect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance(), new ControllerLifeCount());
Effect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance(), ControllerLifeCount.instance);
effect.setText("Put X +1/+1 counters on target creature, where X is your life total.");
ability = new LoyaltyAbility(effect, -11);
effect = new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn);

View file

@ -44,7 +44,7 @@ public final class AjaniWiseCounselor extends CardImpl {
// 9: Put X +1/+1 counters on target creature, where X is your life total.
Ability ability = new LoyaltyAbility(new AddCountersTargetEffect(
CounterType.P1P1.createInstance(),
new ControllerLifeCount()
ControllerLifeCount.instance
).setText("put X +1/+1 counters on target creature, where X is your life total"), -9);
this.addAbility(ability);
}

View file

@ -2,38 +2,37 @@
package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.GainLifeControllerTriggeredAbility;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import java.util.UUID;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public final class AjanisPridemate extends CardImpl {
public AjanisPridemate(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
this.subtype.add(SubType.CAT);
this.subtype.add(SubType.SOLDIER);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
this.addAbility(new AjanisPridemateAbility());
// Whenever you gain life, put a +1/+1 counter on Ajani's Pridemate.
this.addAbility(new GainLifeControllerTriggeredAbility(
new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false
));
}
public AjanisPridemate(final AjanisPridemate card) {
private AjanisPridemate(final AjanisPridemate card) {
super(card);
}
@ -43,35 +42,3 @@ public final class AjanisPridemate extends CardImpl {
}
}
class AjanisPridemateAbility extends TriggeredAbilityImpl {
public AjanisPridemateAbility() {
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()), true);
}
public AjanisPridemateAbility(final AjanisPridemateAbility ability) {
super(ability);
}
@Override
public AjanisPridemateAbility copy() {
return new AjanisPridemateAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.GAINED_LIFE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return event.getPlayerId().equals(controllerId);
}
@Override
public String getRule() {
return "Whenever you gain life, you may put a +1/+1 counter on {this}.";
}
}

View file

@ -23,10 +23,10 @@ public final class AlabasterPotion extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{W}{W}");
// Choose one - Target player gains X life; or prevent the next X damage that would be dealt to any target this turn.
this.getSpellAbility().addEffect(new GainLifeTargetEffect(new ManacostVariableValue()));
this.getSpellAbility().addEffect(new GainLifeTargetEffect(ManacostVariableValue.instance));
this.getSpellAbility().addTarget(new TargetPlayer());
Mode mode = new Mode();
mode.addEffect(new PreventDamageToTargetEffect(Duration.EndOfTurn, false, true, new ManacostVariableValue()));
mode.addEffect(new PreventDamageToTargetEffect(Duration.EndOfTurn, false, true, ManacostVariableValue.instance));
mode.addTarget(new TargetAnyTarget());
this.getSpellAbility().addMode(mode);
}

View file

@ -67,7 +67,7 @@ class AleatoryEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (controller != null && permanent != null) {
if (controller.flipCoin(game)) {
if (controller.flipCoin(source, game, true)) {
game.addEffect(new BoostTargetEffect(1, 1, Duration.EndOfTurn), source);
return true;
}

View file

@ -81,7 +81,7 @@ class AmplifireEffect extends OneShotEffect {
game.addEffect(new SetPowerToughnessSourceEffect(
2 * lastCard.getPower().getValue(),
2 * lastCard.getToughness().getValue(),
Duration.UntilYourNextTurn
Duration.UntilYourNextTurn, SubLayer.SetPT_7b
), source);
}
player.putCardsOnBottomOfLibrary(cards, game, source, false);

View file

@ -61,7 +61,7 @@ class AncientExcavationEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
DynamicValue numCards = new CardsInControllerHandCount();
DynamicValue numCards = CardsInControllerHandCount.instance;
int amount = numCards.calculate(game, source, this);
player.drawCards(amount, game);
player.discard(amount, false, source, game);

View file

@ -35,7 +35,7 @@ public final class ApexHawks extends CardImpl {
// Apex Hawks enters the battlefield with a +1/+1 counter on it for each time it was kicked.
this.addAbility(new EntersBattlefieldAbility(
new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), new MultikickerCount(), true)
new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), MultikickerCount.instance, true)
,"with a +1/+1 counter on it for each time it was kicked"));
}

View file

@ -43,13 +43,13 @@ public final class ArashiTheSkyAsunder extends CardImpl {
this.toughness = new MageInt(5);
// {X}{G}, {tap}: Arashi, the Sky Asunder deals X damage to target creature with flying.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new ManacostVariableValue()), new ManaCostsImpl("{X}{G}"));
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(ManacostVariableValue.instance), new ManaCostsImpl("{X}{G}"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);
// Channel - {X}{G}{G}, Discard Arashi: Arashi deals X damage to each creature with flying.
this.addAbility(new ChannelAbility("{X}{G}{G}", new DamageAllEffect(new ManacostVariableValue(), filter)));
this.addAbility(new ChannelAbility("{X}{G}{G}", new DamageAllEffect(ManacostVariableValue.instance, filter)));
}
public ArashiTheSkyAsunder(final ArashiTheSkyAsunder card) {

View file

@ -25,7 +25,7 @@ public final class ArtifactMutation extends CardImpl {
this.getSpellAbility().addEffect(new DestroyTargetEffect(true));
this.getSpellAbility().addTarget(new TargetArtifactPermanent());
// create X 1/1 green Saproling creature tokens, where X is that artifact's converted mana cost.
this.getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), new TargetConvertedManaCost()));
this.getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), TargetConvertedManaCost.instance));
}
public ArtifactMutation(final ArtifactMutation card) {

View file

@ -16,19 +16,13 @@ import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.watchers.Watcher;
/**
*
* @author stravant
*
* Note, this card is pretty hacky in its implementation due to the fact that
* the alternative cost system doesn't really support "once each turn"
* alternative costs in an obvious way, but it should work in all scenarios as
* far as I can see.
*/
public final class AsForetold extends CardImpl {
@ -43,13 +37,12 @@ public final class AsForetold extends CardImpl {
new StaticValue(1),
true),
TargetController.YOU,
/* optional = */ false));
false));
// Once each turn, you may pay {0} rather than pay the mana cost for a spell you cast with converted mana cost X or less, where X is the number of time counters on As Foretold.
addAbility(new SimpleStaticAbility(
Zone.BATTLEFIELD,
new AsForetoldAddAltCostEffect()),
new AsForetoldAltCostUsedWatcher());
new AsForetoldAddAltCostEffect()));
}
@ -98,7 +91,7 @@ class AsForetoldAlternativeCost extends AlternativeCostSourceAbility {
this.sourceAsForetold = sourceAsForetold;
}
private AsForetoldAlternativeCost(final AsForetoldAlternativeCost ability) {
private AsForetoldAlternativeCost(final AsForetoldAlternativeCost ability) {
super(ability);
this.sourceAsForetold = ability.sourceAsForetold;
this.wasActivated = ability.wasActivated;
@ -115,15 +108,13 @@ class AsForetoldAlternativeCost extends AlternativeCostSourceAbility {
Permanent asForetold = game.getPermanent(sourceAsForetold);
if (controller != null
&& asForetold != null) {
if (controller.chooseUse(Outcome.Neutral, "Do you wish to use " + asForetold.getLogName() + " to pay the alternative cost ?", ability, game)) {
if (controller.chooseUse(Outcome.Neutral, "Do you wish to use "
+ asForetold.getLogName() + " to pay the alternative cost ?", ability, game)) {
wasActivated = super.askToActivateAlternativeCosts(ability, game);
if (wasActivated) {
// Get the watcher
AsForetoldAltCostUsedWatcher asForetoldAltCostUsedWatcher
= game.getState().getWatcher(AsForetoldAltCostUsedWatcher.class, sourceAsForetold);
// Mark as used
asForetoldAltCostUsedWatcher.markUsedThisTurn();
game.getState().setValue(asForetold.getId().toString()
+ asForetold.getZoneChangeCounter(game)
+ asForetold.getTurnsOnBattlefield(), true);
}
}
}
@ -158,17 +149,16 @@ class AsForetoldAddAltCostEffect extends ContinuousEffectImpl {
if (controller != null) {
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (sourcePermanent != null) {
// Get the watcher
AsForetoldAltCostUsedWatcher asForetoldAltCostUsedWatcher
= game.getState().getWatcher(
AsForetoldAltCostUsedWatcher.class, sourcePermanent.getId());
Boolean wasItUsed = (Boolean) game.getState().getValue(
sourcePermanent.getId().toString()
+ sourcePermanent.getZoneChangeCounter(game)
+ sourcePermanent.getTurnsOnBattlefield());
// If we haven't used it yet this turn, give the option of using the zero alternative cost
if (!asForetoldAltCostUsedWatcher.hasBeenUsedThisTurn()) {
if (wasItUsed == null) {
int timeCounters = sourcePermanent.getCounters(game).getCount("time");
controller.getAlternativeSourceCosts().add(new AsForetoldAlternativeCost(sourcePermanent.getId(), timeCounters));
controller.getAlternativeSourceCosts().add(
new AsForetoldAlternativeCost(sourcePermanent.getId(), timeCounters));
}
// Return true even if we didn't add the alt cost. We still applied the effect
return true;
}
@ -186,40 +176,3 @@ class AsForetoldAddAltCostEffect extends ContinuousEffectImpl {
return layer == Layer.RulesEffects;
}
}
/**
* Watcher used as extra storage to record whether a given As Foretold has been
* used this turn. Technically speaking this watcher doesn't *watch* any
* GameEvents, but it does "watch" the alternative cost being used. That just
* isn't possible to watch through a game event. It's still helpful to co-op the
* Watcher system for this since it automatically handles ZoneChangeCounter
* stuff and resetting the condition at the end of the turn.
*/
class AsForetoldAltCostUsedWatcher extends Watcher {
public AsForetoldAltCostUsedWatcher() {
super("asForetoldAltCostUsedWatcher", WatcherScope.CARD);
}
public AsForetoldAltCostUsedWatcher(final AsForetoldAltCostUsedWatcher watcher) {
super(watcher);
}
@Override
public void watch(GameEvent event, Game game) {
// Nothing to do, we explicitly mark used in the alternative cost
}
public boolean hasBeenUsedThisTurn() {
return conditionMet();
}
public void markUsedThisTurn() {
condition = true;
}
@Override
public AsForetoldAltCostUsedWatcher copy() {
return new AsForetoldAltCostUsedWatcher(this);
}
}

View file

@ -27,7 +27,7 @@ public final class AshenSkinZubera extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(2);
Ability ability = new DiesTriggeredAbility(new DiscardTargetEffect(new ZuberasDiedDynamicValue()));
Ability ability = new DiesTriggeredAbility(new DiscardTargetEffect(ZuberasDiedDynamicValue.instance));
ability.addTarget(new TargetOpponent());
this.addAbility(ability, new ZuberasDiedWatcher());
}

View file

@ -41,7 +41,7 @@ public final class AtalyaSamiteMaster extends CardImpl {
this.toughness = new MageInt(3);
// {X}, {tap}: Choose one - Prevent the next X damage that would be dealt to target creature this turn; or you gain X life. Spend only white mana on X.
PreventDamageToTargetEffect effect = new PreventDamageToTargetEffect(Duration.EndOfTurn, false, true, new ManacostVariableValue());
PreventDamageToTargetEffect effect = new PreventDamageToTargetEffect(Duration.EndOfTurn, false, true, ManacostVariableValue.instance);
effect.setText("Prevent the next X damage that would be dealt to target creature this turn. Spend only white mana on X.");
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{X}"));
ability.addCost(new TapSourceCost());
@ -55,7 +55,7 @@ public final class AtalyaSamiteMaster extends CardImpl {
// or you gain X life
Mode mode = new Mode();
mode.addEffect(new GainLifeEffect(new ManacostVariableValue()).setText("You gain X life. Spend only white mana on X."));
mode.addEffect(new GainLifeEffect(ManacostVariableValue.instance).setText("You gain X life. Spend only white mana on X."));
ability.addMode(mode);
this.addAbility(ability);

View file

@ -37,7 +37,7 @@ public final class Atogatog extends CardImpl {
this.power = new MageInt(5);
this.toughness = new MageInt(5);
DynamicValue xValue = new SacrificeCostCreaturesPower();
DynamicValue xValue = SacrificeCostCreaturesPower.instance;
// Sacrifice an Atog creature: Atogatog gets +X/+X until end of turn, where X is the sacrificed creature's power.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD,
new BoostSourceEffect(xValue, xValue,Duration.EndOfTurn),

View file

@ -25,7 +25,7 @@ public final class AuraMutation extends CardImpl {
this.getSpellAbility().addEffect(new DestroyTargetEffect());
this.getSpellAbility().addTarget(new TargetEnchantmentPermanent());
// create X 1/1 green Saproling creature tokens, where X is that enchantment's converted mana cost.
this.getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), new TargetConvertedManaCost()));
this.getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), TargetConvertedManaCost.instance));
}
public AuraMutation(final AuraMutation card) {

View file

@ -62,7 +62,7 @@ public final class AureliasFury extends CardImpl {
// Aurelia's Fury deals X damage divided as you choose among any number of target creatures and/or players.
// Tap each creature dealt damage this way. Players dealt damage this way can't cast noncreature spells this turn.
DynamicValue xValue = new ManacostVariableValue();
DynamicValue xValue = ManacostVariableValue.instance;
this.getSpellAbility().addEffect(new DamageMultiEffect(xValue));
this.getSpellAbility().addEffect(new AureliasFuryEffect());
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(xValue));

View file

@ -85,55 +85,4 @@ class AvatarOfFuryAdjustingCostsAbility extends SimpleStaticAbility implements A
}
}
}
}
//class AvatarOfFuryAdjustingCostsEffect extends CostModificationEffectImpl {
//
// public AvatarOfFuryAdjustingCostsEffect() {
// super(Duration.Custom, Outcome.Benefit, CostModificationType.REDUCE_COST);
// }
//
// public AvatarOfFuryAdjustingCostsEffect(final AvatarOfFuryAdjustingCostsEffect effect) {
// super(effect);
// }
//
// @Override
// public boolean apply(Game game, Ability source, Ability abilityToModify) {
// SpellAbility spellAbility = (SpellAbility)abilityToModify;
// Mana mana = spellAbility.getManaCostsToPay().getMana();
//
// boolean condition = false;
// FilterPermanent filter = new FilterLandPermanent();
// for (UUID playerId: game.getOpponents(source.getControllerId())) {
// if (game.getBattlefield().countAll(filter, playerId, game) > 6) {
// condition = true;
// break;
// }
// }
//
// if (mana.getColorless() > 0 && condition) {
// int newCount = mana.getColorless() - 6;
// if (newCount < 0) {
// newCount = 0;
// }
// mana.setColorless(newCount);
// spellAbility.getManaCostsToPay().load(mana.toString());
// return true;
// }
// return false;
// }
//
// @Override
// public boolean applies(Ability abilityToModify, Ability source, Game game) {
// if ((abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility || abilityToModify instanceof RetraceAbility)
// && abilityToModify.getSourceId().equals(source.getSourceId())) {
// return true;
// }
// return false;
// }
//
// @Override
// public AvatarOfFuryAdjustingCostsEffect copy() {
// return new AvatarOfFuryAdjustingCostsEffect(this);
// }
//}
}

View file

@ -45,7 +45,7 @@ public final class AyliEternalPilgrim extends CardImpl {
this.addAbility(DeathtouchAbility.getInstance());
// {1}, Sacrifice another creature: You gain life equal to the sacrificed creature's toughness.
Effect effect = new GainLifeEffect(new SacrificeCostCreaturesToughness());
Effect effect = new GainLifeEffect(SacrificeCostCreaturesToughness.instance);
effect.setText("You gain life equal to the sacrificed creature's toughness");
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new GenericManaCost(1));
ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE)));

View file

@ -2,14 +2,9 @@ package mage.cards.a;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.AbilityImpl;
import mage.abilities.SpellAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PreventCombatDamageBySourceEffect;
import mage.abilities.effects.common.PreventDamageByTargetEffect;
import mage.abilities.effects.common.PreventDamageToTargetEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@ -46,7 +41,7 @@ public final class AzoriusPloy extends CardImpl {
}
public AzoriusPloy(final AzoriusPloy card) {
private AzoriusPloy(final AzoriusPloy card) {
super(card);
}

View file

@ -11,8 +11,6 @@ import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.common.FilterLandPermanent;
import mage.filter.predicate.mageobject.SupertypePredicate;
import mage.game.permanent.token.TokenImpl;
import mage.game.permanent.token.Token;
import mage.game.permanent.token.custom.CreatureToken;
import mage.target.TargetPermanent;
@ -43,7 +41,7 @@ public final class BalduvianConjurer extends CardImpl {
this.addAbility(ability);
}
public BalduvianConjurer(final BalduvianConjurer card) {
private BalduvianConjurer(final BalduvianConjurer card) {
super(card);
}

View file

@ -3,8 +3,6 @@ package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.constants.Duration;
import mage.constants.SubType;
@ -38,7 +36,7 @@ public final class BalduvianFallen extends CardImpl {
this.addAbility(new BalduvianFallenAbility());
}
public BalduvianFallen(final BalduvianFallen card) {
private BalduvianFallen(final BalduvianFallen card) {
super(card);
}
@ -54,7 +52,7 @@ class BalduvianFallenAbility extends TriggeredAbilityImpl {
super(Zone.BATTLEFIELD, null, false);
}
public BalduvianFallenAbility(final BalduvianFallenAbility ability) {
private BalduvianFallenAbility(final BalduvianFallenAbility ability) {
super(ability);
}

View file

@ -15,7 +15,6 @@ import mage.constants.*;
import mage.filter.common.FilterLandPermanent;
import mage.filter.predicate.mageobject.SupertypePredicate;
import mage.game.permanent.token.TokenImpl;
import mage.game.permanent.token.Token;
import mage.target.TargetPermanent;
/**
@ -44,7 +43,7 @@ public final class BalduvianFrostwaker extends CardImpl {
this.addAbility(ability);
}
public BalduvianFrostwaker(final BalduvianFrostwaker card) {
private BalduvianFrostwaker(final BalduvianFrostwaker card) {
super(card);
}
@ -65,7 +64,7 @@ class BalduvianFrostwakerToken extends TokenImpl {
this.toughness = new MageInt(2);
this.addAbility(FlyingAbility.getInstance());
}
public BalduvianFrostwakerToken(final BalduvianFrostwakerToken token) {
private BalduvianFrostwakerToken(final BalduvianFrostwakerToken token) {
super(token);
}

View file

@ -25,7 +25,7 @@ public final class BalduvianRage extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{R}");
// Target attacking creature gets +X/+0 until end of turn.
this.getSpellAbility().addEffect(new BoostTargetEffect(new ManacostVariableValue(), new StaticValue(0), Duration.EndOfTurn));
this.getSpellAbility().addEffect(new BoostTargetEffect(ManacostVariableValue.instance, new StaticValue(0), Duration.EndOfTurn));
this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterAttackingCreature()));
// Draw a card at the beginning of the next turn's upkeep.

View file

@ -51,7 +51,7 @@ public final class BalduvianWarlord extends CardImpl {
this.addAbility(ability, new BlockedByOnlyOneCreatureThisCombatWatcher());
}
public BalduvianWarlord(final BalduvianWarlord card) {
private BalduvianWarlord(final BalduvianWarlord card) {
super(card);
}
@ -69,7 +69,7 @@ class BalduvianWarlordUnblockEffect extends OneShotEffect {
this.staticText = " Remove target blocking creature from combat. Creatures it was blocking that hadn't become blocked by another creature this combat become unblocked, then it blocks an attacking creature of your choice";
}
public BalduvianWarlordUnblockEffect(final BalduvianWarlordUnblockEffect effect) {
private BalduvianWarlordUnblockEffect(final BalduvianWarlordUnblockEffect effect) {
super(effect);
}

View file

@ -30,7 +30,7 @@ public final class BallistaSquad extends CardImpl {
this.toughness = new MageInt(2);
// {X}{W}, {T}: Ballista Squad deals X damage to target attacking or blocking creature.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new ManacostVariableValue()), new ManaCostsImpl("{X}{W}"));
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(ManacostVariableValue.instance), new ManaCostsImpl("{X}{W}"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetAttackingOrBlockingCreature());
this.addAbility(ability);

View file

@ -32,7 +32,7 @@ public final class BaneOfTheLiving extends CardImpl {
// Morph {X}{B}{B}
this.addAbility(new MorphAbility(this, new ManaCostsImpl("{X}{B}{B}")));
// When Bane of the Living is turned face up, all creatures get -X/-X until end of turn.
DynamicValue morphX = new SignInversionDynamicValue(new MorphManacostVariableValue());
DynamicValue morphX = new SignInversionDynamicValue(MorphManacostVariableValue.instance);
this.addAbility(new TurnedFaceUpSourceTriggeredAbility(new BoostAllEffect(morphX, morphX, Duration.EndOfTurn, new FilterCreaturePermanent("all creatures"), false, "", true)));
}

View file

@ -106,7 +106,7 @@ class BaneFireEffect extends OneShotEffect {
class BanefireCantCounterEffect extends ContinuousRuleModifyingEffectImpl {
Condition condition = new testCondition(new ManacostVariableValue(), 5);
Condition condition = new testCondition(ManacostVariableValue.instance, 5);
public BanefireCantCounterEffect() {
super(Duration.WhileOnStack, Outcome.Benefit);

View file

@ -32,9 +32,9 @@ public final class Banshee extends CardImpl {
this.toughness = new MageInt(1);
// {X}, {T}: Banshee deals half X damage, rounded down, to any target, and half X damage, rounded up, to you.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new HalfValue(new ManacostVariableValue(), false)).setText("Banshee deals half X damage, rounded down, to any target,"), new ManaCostsImpl("{X}"));
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new HalfValue(ManacostVariableValue.instance, false)).setText("Banshee deals half X damage, rounded down, to any target,"), new ManaCostsImpl("{X}"));
ability.addCost(new TapSourceCost());
ability.addEffect(new DamageControllerEffect(new HalfValue(new ManacostVariableValue(), true)).setText(" and half X damage, rounded up, to you"));
ability.addEffect(new DamageControllerEffect(new HalfValue(ManacostVariableValue.instance, true)).setText(" and half X damage, rounded up, to you"));
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
}

View file

@ -45,7 +45,7 @@ public final class BarrageTyrant extends CardImpl {
this.addAbility(new DevoidAbility(this.color));
// {2}{R}, Sacrifice another colorless creature: Barrage Tyrant deals damage equal to the sacrificed creature's power to any target.
Effect effect = new DamageTargetEffect(new SacrificeCostCreaturesPower());
Effect effect = new DamageTargetEffect(SacrificeCostCreaturesPower.instance);
effect.setText("{this} deals damage equal to the sacrificed creature's power to any target");
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{2}{R}"));
ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(filter)));

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