mirror of
https://github.com/correl/mage.git
synced 2024-11-16 03:00:12 +00:00
Merge pull request #1 from magefree/master
Merge main repo with my fork
This commit is contained in:
commit
ecef4838d9
1006 changed files with 28082 additions and 5194 deletions
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -82,6 +82,7 @@ Mage.Server.Plugins/Mage.Draft.8PlayerBooster/target
|
|||
|
||||
*.classpath
|
||||
*.iml
|
||||
hs_err*.log
|
||||
/submitted
|
||||
|
||||
/Mage.Server/config/ai.please.cast.this.txt
|
||||
|
@ -91,4 +92,8 @@ Mage.Server.Plugins/Mage.Draft.8PlayerBooster/target
|
|||
*.txt
|
||||
Mage.Client/serverlist.txt
|
||||
/bin/
|
||||
/target/
|
||||
/target/
|
||||
|
||||
client_secrets.json
|
||||
|
||||
dependency-reduced-pom.xml
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<groupId>org.mage</groupId>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
XMage.de 1 (Europe/Germany) fast :xmage.de:17171
|
||||
woogerworks (North America/USA) :xmage.woogerworks.info:17171
|
||||
XMage.info 1 (Europe/France) new network code -> see forum :176.31.186.181:17171
|
||||
XMage Testserver (Europe/France) 1.4.8v0 :176.31.186.181:17171
|
||||
XMage BR (South America/Brazil) :ec2-54-233-67-0.sa-east-1.compute.amazonaws.com:17171
|
||||
Seedds Server (Asia) :115.29.203.80:17171
|
||||
localhost -> connect to your local server (must be started):localhost:17171
|
||||
|
|
|
@ -107,6 +107,7 @@ import mage.client.draft.DraftPanel;
|
|||
import mage.client.game.GamePane;
|
||||
import mage.client.game.GamePanel;
|
||||
import mage.client.plugins.impl.Plugins;
|
||||
import mage.client.preference.MagePreferences;
|
||||
import mage.client.remote.CallbackClientImpl;
|
||||
import mage.client.table.TablesPane;
|
||||
import mage.client.tournament.TournamentPane;
|
||||
|
@ -745,9 +746,10 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
}
|
||||
|
||||
private boolean performConnect() {
|
||||
String userName = prefs.get("userName", "");
|
||||
String server = prefs.get("serverAddress", "");
|
||||
int port = Integer.parseInt(prefs.get("serverPort", ""));
|
||||
String server = MagePreferences.getServerAddress();
|
||||
int port = MagePreferences.getServerPort();
|
||||
String userName = MagePreferences.getUserName(server);
|
||||
String password = MagePreferences.getPassword(server);
|
||||
String proxyServer = prefs.get("proxyAddress", "");
|
||||
int proxyPort = Integer.parseInt(prefs.get("proxyPort", "0"));
|
||||
ProxyType proxyType = ProxyType.valueByText(prefs.get("proxyType", "None"));
|
||||
|
@ -757,6 +759,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
||||
Connection connection = new Connection();
|
||||
connection.setUsername(userName);
|
||||
connection.setPassword(password);
|
||||
connection.setHost(server);
|
||||
connection.setPort(port);
|
||||
connection.setProxyType(proxyType);
|
||||
|
|
|
@ -109,20 +109,20 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
jSplitPane1.setOpaque(false);
|
||||
countdown = new Timer(1000,
|
||||
new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (--timeout > 0) {
|
||||
setTimeout(timeout);
|
||||
} else {
|
||||
if (updateDeckTask != null) {
|
||||
updateDeckTask.cancel(true);
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (--timeout > 0) {
|
||||
setTimeout(timeout);
|
||||
} else {
|
||||
if (updateDeckTask != null) {
|
||||
updateDeckTask.cancel(true);
|
||||
}
|
||||
setTimeout(0);
|
||||
countdown.stop();
|
||||
removeDeckEditor();
|
||||
}
|
||||
}
|
||||
setTimeout(0);
|
||||
countdown.stop();
|
||||
removeDeckEditor();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -154,7 +154,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
this.tableId = tableId;
|
||||
this.mode = mode;
|
||||
this.btnAddLand.setVisible(false);
|
||||
|
||||
|
||||
switch (mode) {
|
||||
case LIMITED_BUILDING:
|
||||
this.btnAddLand.setVisible(true);
|
||||
|
@ -209,149 +209,145 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
component.clearCardEventListeners();
|
||||
component.addCardEventListener(
|
||||
new Listener<Event>() {
|
||||
@Override
|
||||
public void event(Event event) {
|
||||
switch (event.getEventName()) {
|
||||
case "double-click":
|
||||
moveSelectorCardToDeck(event);
|
||||
break;
|
||||
case "alt-double-click":
|
||||
if (mode == DeckEditorMode.FREE_BUILDING) {
|
||||
moveSelectorCardToSideboard(event);
|
||||
} else {
|
||||
// because in match mode selector is used as sideboard the card goes to deck also for shift click
|
||||
moveSelectorCardToDeck(event);
|
||||
@Override
|
||||
public void event(Event event) {
|
||||
switch (event.getEventName()) {
|
||||
case "double-click":
|
||||
moveSelectorCardToDeck(event);
|
||||
break;
|
||||
case "alt-double-click":
|
||||
if (mode == DeckEditorMode.FREE_BUILDING) {
|
||||
moveSelectorCardToSideboard(event);
|
||||
} else {
|
||||
// because in match mode selector is used as sideboard the card goes to deck also for shift click
|
||||
moveSelectorCardToDeck(event);
|
||||
}
|
||||
break;
|
||||
case "remove-main":
|
||||
DeckEditorPanel.this.deckArea.getDeckList().handleDoubleClick();
|
||||
break;
|
||||
case "remove-sideboard":
|
||||
DeckEditorPanel.this.deckArea.getSideboardList().handleDoubleClick();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "remove-main":
|
||||
DeckEditorPanel.this.deckArea.getDeckList().handleDoubleClick();
|
||||
break;
|
||||
case "remove-sideboard":
|
||||
DeckEditorPanel.this.deckArea.getSideboardList().handleDoubleClick();
|
||||
break;
|
||||
}
|
||||
refreshDeck();
|
||||
}
|
||||
});
|
||||
refreshDeck();
|
||||
}
|
||||
});
|
||||
}
|
||||
this.deckArea.clearDeckEventListeners();
|
||||
this.deckArea.addDeckEventListener(
|
||||
new Listener<Event>() {
|
||||
@Override
|
||||
public void event(Event event) {
|
||||
if (mode.equals(DeckEditorMode.FREE_BUILDING)) {
|
||||
switch (event.getEventName()) {
|
||||
case "double-click":
|
||||
{
|
||||
SimpleCardView cardView = (SimpleCardView) event.getSource();
|
||||
for (Card card : deck.getCards()) {
|
||||
if (card.getId().equals(cardView.getId())) {
|
||||
deck.getCards().remove(card);
|
||||
@Override
|
||||
public void event(Event event) {
|
||||
if (mode.equals(DeckEditorMode.FREE_BUILDING)) {
|
||||
switch (event.getEventName()) {
|
||||
case "double-click": {
|
||||
SimpleCardView cardView = (SimpleCardView) event.getSource();
|
||||
for (Card card : deck.getCards()) {
|
||||
if (card.getId().equals(cardView.getId())) {
|
||||
deck.getCards().remove(card);
|
||||
break;
|
||||
}
|
||||
}
|
||||
hidePopup();
|
||||
refreshDeck();
|
||||
break;
|
||||
}
|
||||
case "alt-double-click": {
|
||||
SimpleCardView cardView = (SimpleCardView) event.getSource();
|
||||
for (Card card : deck.getCards()) {
|
||||
if (card.getId().equals(cardView.getId())) {
|
||||
deck.getCards().remove(card);
|
||||
deck.getSideboard().add(card);
|
||||
break;
|
||||
}
|
||||
}
|
||||
hidePopup();
|
||||
refreshDeck();
|
||||
break;
|
||||
}
|
||||
case "set-number": {
|
||||
setCardNumberToCardsList(event, deck.getCards());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// constructing phase or sideboarding during match -> card goes always to sideboard
|
||||
switch (event.getEventName()) {
|
||||
case "double-click":
|
||||
case "alt-double-click": {
|
||||
SimpleCardView cardView = (SimpleCardView) event.getSource();
|
||||
for (Card card : deck.getCards()) {
|
||||
if (card.getId().equals(cardView.getId())) {
|
||||
deck.getCards().remove(card);
|
||||
deck.getSideboard().add(card);
|
||||
cardSelector.loadSideboard(new ArrayList<>(deck.getSideboard()), getBigCard());
|
||||
break;
|
||||
}
|
||||
}
|
||||
hidePopup();
|
||||
refreshDeck();
|
||||
break;
|
||||
}
|
||||
}
|
||||
hidePopup();
|
||||
refreshDeck();
|
||||
break;
|
||||
}
|
||||
case "alt-double-click":
|
||||
{
|
||||
SimpleCardView cardView = (SimpleCardView) event.getSource();
|
||||
for (Card card : deck.getCards()) {
|
||||
if (card.getId().equals(cardView.getId())) {
|
||||
deck.getCards().remove(card);
|
||||
deck.getSideboard().add(card);
|
||||
break;
|
||||
}
|
||||
}
|
||||
hidePopup();
|
||||
refreshDeck();
|
||||
break;
|
||||
}
|
||||
case "set-number":
|
||||
{
|
||||
setCardNumberToCardsList(event, deck.getCards());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// constructing phase or sideboarding during match -> card goes always to sideboard
|
||||
switch (event.getEventName()) {
|
||||
case "double-click":
|
||||
case "alt-double-click":
|
||||
{
|
||||
SimpleCardView cardView = (SimpleCardView) event.getSource();
|
||||
for (Card card : deck.getCards()) {
|
||||
if (card.getId().equals(cardView.getId())) {
|
||||
deck.getCards().remove(card);
|
||||
deck.getSideboard().add(card);
|
||||
cardSelector.loadSideboard(new ArrayList<>(deck.getSideboard()), getBigCard());
|
||||
break;
|
||||
}
|
||||
}
|
||||
hidePopup();
|
||||
refreshDeck();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
this.deckArea.addSideboardEventListener(
|
||||
new Listener<Event>() {
|
||||
@Override
|
||||
public void event(Event event) {
|
||||
if (mode.equals(DeckEditorMode.FREE_BUILDING)) {
|
||||
// normal edit mode
|
||||
switch (event.getEventName()) {
|
||||
case "double-click":
|
||||
// remove card from sideboard (don't add it to deck)
|
||||
SimpleCardView cardView = (SimpleCardView) event.getSource();
|
||||
for (Card card : deck.getSideboard()) {
|
||||
if (card.getId().equals(cardView.getId())) {
|
||||
deck.getSideboard().remove(card);
|
||||
@Override
|
||||
public void event(Event event) {
|
||||
if (mode.equals(DeckEditorMode.FREE_BUILDING)) {
|
||||
// normal edit mode
|
||||
switch (event.getEventName()) {
|
||||
case "double-click":
|
||||
// remove card from sideboard (don't add it to deck)
|
||||
SimpleCardView cardView = (SimpleCardView) event.getSource();
|
||||
for (Card card : deck.getSideboard()) {
|
||||
if (card.getId().equals(cardView.getId())) {
|
||||
deck.getSideboard().remove(card);
|
||||
break;
|
||||
}
|
||||
}
|
||||
hidePopup();
|
||||
refreshDeck();
|
||||
break;
|
||||
}
|
||||
}
|
||||
hidePopup();
|
||||
refreshDeck();
|
||||
break;
|
||||
case "alt-double-click":
|
||||
// remove card from sideboard
|
||||
cardView = (SimpleCardView) event.getSource();
|
||||
for (Card card : deck.getSideboard()) {
|
||||
if (card.getId().equals(cardView.getId())) {
|
||||
deck.getSideboard().remove(card);
|
||||
deck.getCards().add(card);
|
||||
case "alt-double-click":
|
||||
// remove card from sideboard
|
||||
cardView = (SimpleCardView) event.getSource();
|
||||
for (Card card : deck.getSideboard()) {
|
||||
if (card.getId().equals(cardView.getId())) {
|
||||
deck.getSideboard().remove(card);
|
||||
deck.getCards().add(card);
|
||||
break;
|
||||
}
|
||||
}
|
||||
hidePopup();
|
||||
refreshDeck();
|
||||
break;
|
||||
case "set-number": {
|
||||
setCardNumberToCardsList(event, deck.getSideboard());
|
||||
}
|
||||
}
|
||||
hidePopup();
|
||||
refreshDeck();
|
||||
break;
|
||||
case "set-number":
|
||||
{
|
||||
setCardNumberToCardsList(event, deck.getSideboard());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// construct phase or sideboarding during match
|
||||
switch (event.getEventName()) {
|
||||
case "double-click":
|
||||
case "alt-double-click":
|
||||
SimpleCardView cardView = (SimpleCardView) event.getSource();
|
||||
for (Card card : deck.getSideboard()) {
|
||||
if (card.getId().equals(cardView.getId())) {
|
||||
deck.getSideboard().remove(card);
|
||||
deck.getCards().add(card);
|
||||
}
|
||||
} else {
|
||||
// construct phase or sideboarding during match
|
||||
switch (event.getEventName()) {
|
||||
case "double-click":
|
||||
case "alt-double-click":
|
||||
SimpleCardView cardView = (SimpleCardView) event.getSource();
|
||||
for (Card card : deck.getSideboard()) {
|
||||
if (card.getId().equals(cardView.getId())) {
|
||||
deck.getSideboard().remove(card);
|
||||
deck.getCards().add(card);
|
||||
break;
|
||||
}
|
||||
}
|
||||
hidePopup();
|
||||
refreshDeck();
|
||||
break;
|
||||
}
|
||||
} hidePopup();
|
||||
refreshDeck();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
refreshDeck();
|
||||
|
||||
this.setVisible(true);
|
||||
|
@ -364,8 +360,8 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
int cardsFound = 0;
|
||||
List<Card> toDelete = new ArrayList<>();
|
||||
for (Card card : cards) {
|
||||
if (card.getName().equals(cardView.getName())
|
||||
&& card.getCardNumber() == cardView.getCardNumber()
|
||||
if (card.getName().equals(cardView.getName())
|
||||
&& card.getCardNumber() == cardView.getCardNumber()
|
||||
&& card.getExpansionSetCode().equals(cardView.getExpansionSetCode())) {
|
||||
cardsFound++;
|
||||
if (cardsFound > numberToSet) {
|
||||
|
@ -373,23 +369,23 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (toDelete.isEmpty()) {
|
||||
// add cards
|
||||
CardInfo cardInfo = CardRepository.instance.findCard(cardView.getExpansionSetCode(), cardView.getCardNumber());
|
||||
for (int i = cardsFound; i < numberToSet; i++) {
|
||||
cards.add(cardInfo.getMockCard());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// remove cards
|
||||
for (Card card: toDelete) {
|
||||
// remove cards
|
||||
for (Card card : toDelete) {
|
||||
cards.remove(card);
|
||||
}
|
||||
}
|
||||
hidePopup();
|
||||
refreshDeck();
|
||||
}
|
||||
|
||||
|
||||
private void moveSelectorCardToDeck(Event event) {
|
||||
SimpleCardView cardView = (SimpleCardView) event.getSource();
|
||||
CardInfo cardInfo = CardRepository.instance.findCard(cardView.getExpansionSetCode(), cardView.getCardNumber());
|
||||
|
@ -417,7 +413,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
((CardInfoPane) cardInfoPane).setCard(new CardView(card), null);
|
||||
}
|
||||
hidePopup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void moveSelectorCardToSideboard(Event event) {
|
||||
|
@ -432,7 +428,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
}
|
||||
hidePopup();
|
||||
}
|
||||
|
||||
|
||||
private void hidePopup() {
|
||||
Plugins.getInstance().getActionCallback().mouseExited(null, null);
|
||||
}
|
||||
|
@ -483,7 +479,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
text = text + Integer.toString(second);
|
||||
}
|
||||
this.txtTimeRemaining.setText(text);
|
||||
if (s==60) {
|
||||
if (s == 60) {
|
||||
AudioManager.playOnCountdown1();
|
||||
}
|
||||
}
|
||||
|
@ -602,75 +598,73 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
jPanel1Layout.setHorizontalGroup(
|
||||
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
/*.addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(jLayeredPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE))*/
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addGap(6, 6, 6)
|
||||
.addComponent(lblDeckName)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(txtDeckName, javax.swing.GroupLayout.DEFAULT_SIZE, 189, Short.MAX_VALUE))
|
||||
|
||||
.addComponent(cardInfoPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
/*.addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(jLayeredPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE))*/
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(btnSave)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnLoad)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnNew)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnExit))
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(btnImport)
|
||||
.addContainerGap()
|
||||
.addComponent(btnAddLand)
|
||||
.addContainerGap()
|
||||
.addComponent(btnSubmit))
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(txtTimeRemaining))
|
||||
)
|
||||
.addContainerGap()));
|
||||
.addGap(6, 6, 6)
|
||||
.addComponent(lblDeckName)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(txtDeckName, javax.swing.GroupLayout.DEFAULT_SIZE, 189, Short.MAX_VALUE))
|
||||
.addComponent(cardInfoPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(btnSave)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnLoad)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnNew)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnExit))
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(btnImport)
|
||||
.addContainerGap()
|
||||
.addComponent(btnAddLand)
|
||||
.addContainerGap()
|
||||
.addComponent(btnSubmit))
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(txtTimeRemaining))
|
||||
)
|
||||
.addContainerGap()));
|
||||
jPanel1Layout.setVerticalGroup(
|
||||
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(txtDeckName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lblDeckName))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(btnSave)
|
||||
.addComponent(btnLoad)
|
||||
.addComponent(btnNew)
|
||||
.addComponent(btnExit))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(btnImport)
|
||||
.addComponent(btnAddLand)
|
||||
.addComponent(btnSubmit))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(txtTimeRemaining))
|
||||
//.addComponent(jLayeredPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, isShowCardInfo ? 30 : 159, Short.MAX_VALUE)
|
||||
.addComponent(cardInfoPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 104, Short.MAX_VALUE)
|
||||
.addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)));
|
||||
.addContainerGap()
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(txtDeckName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lblDeckName))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(btnSave)
|
||||
.addComponent(btnLoad)
|
||||
.addComponent(btnNew)
|
||||
.addComponent(btnExit))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(btnImport)
|
||||
.addComponent(btnAddLand)
|
||||
.addComponent(btnSubmit))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(txtTimeRemaining))
|
||||
//.addComponent(jLayeredPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, isShowCardInfo ? 30 : 159, Short.MAX_VALUE)
|
||||
.addComponent(cardInfoPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 104, Short.MAX_VALUE)
|
||||
.addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)));
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 261, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 0, 0)
|
||||
.addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 604, Short.MAX_VALUE)));
|
||||
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 261, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 0, 0)
|
||||
.addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 604, Short.MAX_VALUE)));
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
|
@ -697,7 +691,9 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
}
|
||||
refreshDeck();
|
||||
try {
|
||||
MageFrame.getPreferences().put("lastDeckFolder", file.getCanonicalPath());
|
||||
if (file != null) {
|
||||
MageFrame.getPreferences().put("lastDeckFolder", file.getCanonicalPath());
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
}
|
||||
|
@ -800,7 +796,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
addLand.showDialog(deck, mode);
|
||||
refreshDeck();
|
||||
}//GEN-LAST:event_btnAddLandActionPerformed
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private mage.client.cards.BigCard bigCard;
|
||||
private javax.swing.JButton btnExit;
|
||||
|
|
|
@ -28,18 +28,13 @@
|
|||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
<Component id="btnConnect" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnCancel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="0" 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"/>
|
||||
<Component id="lblUserName" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblPassword" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="lblFlag" alignment="1" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
|
@ -53,14 +48,29 @@
|
|||
<Component id="txtServer" pref="286" max="32767" attributes="0"/>
|
||||
<Component id="txtPort" alignment="0" min="-2" pref="71" max="-2" attributes="0"/>
|
||||
<Component id="txtUserName" alignment="1" max="32767" attributes="0"/>
|
||||
<Component id="txtPassword" alignment="1" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnFind" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="chkForceUpdateDB" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="chkAutoConnect" alignment="0" pref="358" max="32767" attributes="0"/>
|
||||
<Component id="chkAutoConnect" alignment="0" pref="375" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="btnRegister" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="btnConnect" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnForgotPassword" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnCancel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="26" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
|
@ -85,6 +95,11 @@
|
|||
<Component id="txtUserName" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblUserName" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="txtPassword" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblPassword" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="lblFlag" max="32767" attributes="0"/>
|
||||
|
@ -96,13 +111,16 @@
|
|||
<Component id="chkForceUpdateDB" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jProxySettingsButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="50" max="32767" attributes="0"/>
|
||||
<EmptySpace pref="38" max="32767" attributes="0"/>
|
||||
<Component id="lblStatus" min="-2" pref="24" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="btnConnect" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btnCancel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btnForgotPassword" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
|
||||
<Component id="btnRegister" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
|
@ -152,6 +170,16 @@
|
|||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="txtUserName">
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblPassword">
|
||||
<Properties>
|
||||
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
|
||||
<ComponentRef name="txtPassword"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Password:"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JPasswordField" name="txtPassword">
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblFlag">
|
||||
<Properties>
|
||||
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
|
||||
|
@ -209,5 +237,23 @@
|
|||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblStatus">
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnRegister">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Register new user"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="<html>XMage now supports user authentication.<br>Register your account before you log in.<html>"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnRegisterActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnForgotPassword">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Forgot password"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value="<html>You can reset your password if you have registered<br>your account with an email address.</html>"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnForgotPasswordActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
|
|
@ -56,16 +56,17 @@ import java.util.concurrent.CancellationException;
|
|||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import javax.swing.JLayeredPane;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.SwingWorker;
|
||||
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.preference.MagePreferences;
|
||||
import mage.client.util.Config;
|
||||
import mage.client.util.gui.countryBox.CountryItemEditor;
|
||||
import mage.remote.Connection;
|
||||
import mage.remote.Connection.ProxyType;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
|
@ -76,6 +77,8 @@ public class ConnectDialog extends MageDialog {
|
|||
private static final Logger logger = Logger.getLogger(ConnectDialog.class);
|
||||
private Connection connection;
|
||||
private ConnectTask task;
|
||||
private RegisterUserDialog registerUserDialog;
|
||||
private ResetPasswordDialog resetPasswordDialog;
|
||||
|
||||
private final ActionListener connectAction = new ActionListener() {
|
||||
@Override
|
||||
|
@ -90,15 +93,24 @@ public class ConnectDialog extends MageDialog {
|
|||
public ConnectDialog() {
|
||||
initComponents();
|
||||
|
||||
this.txtUserName.addActionListener(connectAction);
|
||||
this.txtServer.addActionListener(connectAction);
|
||||
this.txtPort.addActionListener(connectAction);
|
||||
this.txtUserName.addActionListener(connectAction);
|
||||
this.txtPassword.addActionListener(connectAction);
|
||||
|
||||
registerUserDialog = new RegisterUserDialog(this);
|
||||
MageFrame.getDesktop().add(registerUserDialog, JLayeredPane.POPUP_LAYER);
|
||||
|
||||
resetPasswordDialog = new ResetPasswordDialog(this);
|
||||
MageFrame.getDesktop().add(resetPasswordDialog, JLayeredPane.POPUP_LAYER);
|
||||
}
|
||||
|
||||
public void showDialog() {
|
||||
this.txtServer.setText(MageFrame.getPreferences().get("serverAddress", Config.serverName));
|
||||
this.txtPort.setText(MageFrame.getPreferences().get("serverPort", Integer.toString(Config.port)));
|
||||
this.txtUserName.setText(MageFrame.getPreferences().get("userName", ""));
|
||||
String serverAddress = MagePreferences.getServerAddressWithDefault(Config.serverName);
|
||||
this.txtServer.setText(serverAddress);
|
||||
this.txtPort.setText(Integer.toString(MagePreferences.getServerPortWithDefault(Config.port)));
|
||||
this.txtUserName.setText(MagePreferences.getUserName(serverAddress));
|
||||
this.txtPassword.setText(MagePreferences.getPassword(serverAddress));
|
||||
this.chkAutoConnect.setSelected(Boolean.parseBoolean(MageFrame.getPreferences().get(KEY_CONNECT_AUTO_CONNECT, "false")));
|
||||
this.chkForceUpdateDB.setSelected(false); // has always to be set manually to force comparison
|
||||
|
||||
|
@ -117,9 +129,11 @@ public class ConnectDialog extends MageDialog {
|
|||
}
|
||||
|
||||
private void saveSettings() {
|
||||
MageFrame.getPreferences().put("serverAddress", txtServer.getText().trim());
|
||||
MageFrame.getPreferences().put("serverPort", txtPort.getText().trim());
|
||||
MageFrame.getPreferences().put("userName", txtUserName.getText().trim());
|
||||
String serverAddress = txtServer.getText().trim();
|
||||
MagePreferences.setServerAddress(serverAddress);
|
||||
MagePreferences.setServerPort(Integer.parseInt(txtPort.getText().trim()));
|
||||
MagePreferences.setUserName(serverAddress, txtUserName.getText().trim());
|
||||
MagePreferences.setPassword(serverAddress, txtPassword.getText().trim());
|
||||
MageFrame.getPreferences().put(KEY_CONNECT_AUTO_CONNECT, Boolean.toString(chkAutoConnect.isSelected()));
|
||||
}
|
||||
|
||||
|
@ -139,6 +153,8 @@ public class ConnectDialog extends MageDialog {
|
|||
txtPort = new javax.swing.JTextField();
|
||||
lblUserName = new javax.swing.JLabel();
|
||||
txtUserName = new javax.swing.JTextField();
|
||||
lblPassword = new javax.swing.JLabel();
|
||||
txtPassword = new javax.swing.JPasswordField();
|
||||
lblFlag = new javax.swing.JLabel();
|
||||
cbFlag = new mage.client.util.gui.countryBox.CountryComboBox();
|
||||
chkAutoConnect = new javax.swing.JCheckBox();
|
||||
|
@ -147,6 +163,8 @@ public class ConnectDialog extends MageDialog {
|
|||
btnConnect = new javax.swing.JButton();
|
||||
btnCancel = new javax.swing.JButton();
|
||||
lblStatus = new javax.swing.JLabel();
|
||||
btnRegister = new javax.swing.JButton();
|
||||
btnForgotPassword = new javax.swing.JButton();
|
||||
|
||||
setTitle("Connect to server");
|
||||
setNormalBounds(new java.awt.Rectangle(100, 100, 410, 307));
|
||||
|
@ -175,6 +193,9 @@ public class ConnectDialog extends MageDialog {
|
|||
lblUserName.setLabelFor(txtUserName);
|
||||
lblUserName.setText("User name:");
|
||||
|
||||
lblPassword.setLabelFor(txtPassword);
|
||||
lblPassword.setText("Password:");
|
||||
|
||||
lblFlag.setLabelFor(txtUserName);
|
||||
lblFlag.setText("User flag:");
|
||||
|
||||
|
@ -217,6 +238,22 @@ public class ConnectDialog extends MageDialog {
|
|||
}
|
||||
});
|
||||
|
||||
btnRegister.setText("Register new user");
|
||||
btnRegister.setToolTipText("<html>XMage now supports user authentication.<br>Register your account before you log in.<html>");
|
||||
btnRegister.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btnRegisterActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
btnForgotPassword.setText("Forgot password");
|
||||
btnForgotPassword.setToolTipText("<html>You can reset your password if you have registered<br>your account with an email address.</html>");
|
||||
btnForgotPassword.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btnForgotPasswordActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||
getContentPane().setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
|
@ -224,17 +261,13 @@ public class ConnectDialog extends MageDialog {
|
|||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
.addComponent(btnConnect)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnCancel))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(lblPort)
|
||||
.addComponent(lblServer)
|
||||
.addComponent(lblUserName))
|
||||
.addComponent(lblUserName)
|
||||
.addComponent(lblPassword))
|
||||
.addComponent(lblFlag, javax.swing.GroupLayout.Alignment.TRAILING))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
|
@ -245,11 +278,23 @@ public class ConnectDialog extends MageDialog {
|
|||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
|
||||
.addComponent(txtServer, javax.swing.GroupLayout.DEFAULT_SIZE, 286, Short.MAX_VALUE)
|
||||
.addComponent(txtPort, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(txtUserName))
|
||||
.addComponent(txtUserName)
|
||||
.addComponent(txtPassword))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnFind))
|
||||
.addComponent(chkForceUpdateDB, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(chkAutoConnect, javax.swing.GroupLayout.DEFAULT_SIZE, 358, Short.MAX_VALUE))))
|
||||
.addComponent(chkAutoConnect, javax.swing.GroupLayout.DEFAULT_SIZE, 375, Short.MAX_VALUE)))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(btnRegister)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(btnConnect)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnForgotPassword)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnCancel)))
|
||||
.addGap(26, 26, 26)))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
|
@ -269,6 +314,10 @@ public class ConnectDialog extends MageDialog {
|
|||
.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.LEADING)
|
||||
.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.LEADING, false)
|
||||
.addComponent(lblFlag, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(cbFlag, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
|
@ -278,12 +327,15 @@ public class ConnectDialog extends MageDialog {
|
|||
.addComponent(chkForceUpdateDB)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jProxySettingsButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 50, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 38, Short.MAX_VALUE)
|
||||
.addComponent(lblStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(btnConnect)
|
||||
.addComponent(btnCancel))
|
||||
.addComponent(btnCancel)
|
||||
.addComponent(btnForgotPassword))
|
||||
.addGap(3, 3, 3)
|
||||
.addComponent(btnRegister)
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
|
@ -302,10 +354,6 @@ public class ConnectDialog extends MageDialog {
|
|||
|
||||
private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnConnectActionPerformed
|
||||
|
||||
if (txtUserName.getText().isEmpty()) {
|
||||
JOptionPane.showMessageDialog(rootPane, "Please provide a user name");
|
||||
return;
|
||||
}
|
||||
if (txtServer.getText().trim().isEmpty()) {
|
||||
JOptionPane.showMessageDialog(rootPane, "Please provide a server address");
|
||||
return;
|
||||
|
@ -314,9 +362,14 @@ public class ConnectDialog extends MageDialog {
|
|||
JOptionPane.showMessageDialog(rootPane, "Please provide a port number");
|
||||
return;
|
||||
}
|
||||
if (txtUserName.getText().isEmpty()) {
|
||||
JOptionPane.showMessageDialog(rootPane, "Please provide a user name");
|
||||
return;
|
||||
}
|
||||
// txtPassword is not checked here, because authentication might be disabled by the server config.
|
||||
if (Integer.valueOf(txtPort.getText()) < 1 || Integer.valueOf(txtPort.getText()) > 65535) {
|
||||
JOptionPane.showMessageDialog(rootPane, "Invalid port number");
|
||||
txtPort.setText(MageFrame.getPreferences().get("serverPort", Integer.toString(Config.port)));
|
||||
txtPort.setText(Integer.toString(MagePreferences.getServerPortWithDefault(Config.port)));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -327,30 +380,10 @@ public class ConnectDialog extends MageDialog {
|
|||
connection.setHost(this.txtServer.getText().trim());
|
||||
connection.setPort(Integer.valueOf(this.txtPort.getText().trim()));
|
||||
connection.setUsername(this.txtUserName.getText().trim());
|
||||
connection.setPassword(this.txtPassword.getText().trim());
|
||||
connection.setForceDBComparison(this.chkForceUpdateDB.isSelected());
|
||||
MageFrame.getPreferences().put(KEY_CONNECT_FLAG, ((CountryItemEditor) cbFlag.getEditor()).getImageItem());
|
||||
|
||||
ProxyType configProxyType = Connection.ProxyType.valueByText(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_TYPE, "None"));
|
||||
|
||||
if (configProxyType != null) {
|
||||
connection.setProxyType(configProxyType);
|
||||
if (!configProxyType.equals(ProxyType.NONE)) {
|
||||
String host = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_ADDRESS, "");
|
||||
String port = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_PORT, "");
|
||||
if (!host.isEmpty() && !port.isEmpty()) {
|
||||
connection.setProxyHost(host);
|
||||
connection.setProxyPort(Integer.valueOf(port));
|
||||
String username = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_USERNAME, "");
|
||||
connection.setProxyUsername(username);
|
||||
if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_REMEMBER, "false").equals("true")) {
|
||||
String password = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PROXY_PSWD, "");
|
||||
connection.setProxyPassword(password);
|
||||
}
|
||||
} else {
|
||||
logger.warn("host or\\and port are empty: host=" + host + ", port=" + port);
|
||||
}
|
||||
}
|
||||
}
|
||||
PreferencesDialog.setProxyInformation(connection);
|
||||
|
||||
// pref settings
|
||||
MageFrame.getInstance().setUserPrefsToConnection(connection);
|
||||
|
@ -514,8 +547,12 @@ public class ConnectDialog extends MageDialog {
|
|||
if (selectedServer != null) {
|
||||
String[] params = selectedServer.split(":");
|
||||
if (params.length == 3) {
|
||||
this.txtServer.setText(params[1]);
|
||||
String serverAddress = params[1];
|
||||
this.txtServer.setText(serverAddress);
|
||||
this.txtPort.setText(params[2]);
|
||||
// Update userName and password according to the chosen server.
|
||||
this.txtUserName.setText(MagePreferences.getUserName(serverAddress));
|
||||
this.txtPassword.setText(MagePreferences.getPassword(serverAddress));
|
||||
} else {
|
||||
JOptionPane.showMessageDialog(null, "Wrong server data format.");
|
||||
}
|
||||
|
@ -541,19 +578,47 @@ public class ConnectDialog extends MageDialog {
|
|||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_chkForceUpdateDBActionPerformed
|
||||
|
||||
private void txtUserNameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtUserNameActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_txtUserNameActionPerformed
|
||||
|
||||
private void txtPasswordActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtPasswordActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_txtPasswordActionPerformed
|
||||
|
||||
private void btnRegisterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRegisterActionPerformed
|
||||
registerUserDialog.showDialog();
|
||||
}//GEN-LAST:event_btnRegisterActionPerformed
|
||||
|
||||
private void btnForgotPasswordActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnForgotPasswordActionPerformed
|
||||
resetPasswordDialog.showDialog();
|
||||
}//GEN-LAST:event_btnForgotPasswordActionPerformed
|
||||
|
||||
public String getServer() {
|
||||
return this.txtServer.getText();
|
||||
}
|
||||
|
||||
public String getPort() {
|
||||
return this.txtPort.getText();
|
||||
}
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton btnCancel;
|
||||
private javax.swing.JButton btnConnect;
|
||||
private javax.swing.JButton btnFind;
|
||||
private javax.swing.JButton btnForgotPassword;
|
||||
private javax.swing.JButton btnRegister;
|
||||
private mage.client.util.gui.countryBox.CountryComboBox cbFlag;
|
||||
private javax.swing.JCheckBox chkAutoConnect;
|
||||
private javax.swing.JCheckBox chkForceUpdateDB;
|
||||
private javax.swing.JButton jProxySettingsButton;
|
||||
private javax.swing.JLabel lblFlag;
|
||||
private javax.swing.JLabel lblPassword;
|
||||
private javax.swing.JLabel lblPort;
|
||||
private javax.swing.JLabel lblServer;
|
||||
private javax.swing.JLabel lblStatus;
|
||||
private javax.swing.JLabel lblUserName;
|
||||
private javax.swing.JPasswordField txtPassword;
|
||||
private javax.swing.JTextField txtPort;
|
||||
private javax.swing.JTextField txtServer;
|
||||
private javax.swing.JTextField txtUserName;
|
||||
|
|
|
@ -2298,6 +2298,30 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
this.repaint();
|
||||
}
|
||||
|
||||
public static void setProxyInformation(Connection connection) {
|
||||
ProxyType configProxyType = Connection.ProxyType.valueByText(getCachedValue(KEY_PROXY_TYPE, "None"));
|
||||
if (configProxyType == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
connection.setProxyType(configProxyType);
|
||||
if (!configProxyType.equals(ProxyType.NONE)) {
|
||||
String host = getCachedValue(KEY_PROXY_ADDRESS, "");
|
||||
String port = getCachedValue(KEY_PROXY_PORT, "");
|
||||
if (!host.isEmpty() && !port.isEmpty()) {
|
||||
connection.setProxyHost(host);
|
||||
connection.setProxyPort(Integer.valueOf(port));
|
||||
String username = getCachedValue(KEY_PROXY_USERNAME, "");
|
||||
connection.setProxyUsername(username);
|
||||
if (getCachedValue(KEY_PROXY_REMEMBER, "false").equals("true")) {
|
||||
String password = getCachedValue(KEY_PROXY_PSWD, "");
|
||||
connection.setProxyPassword(password);
|
||||
}
|
||||
} else {
|
||||
log.warn("host or\\and port are empty: host=" + host + ", port=" + port);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,219 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JInternalFrameFormInfo">
|
||||
<Properties>
|
||||
<Property name="defaultCloseOperation" type="int" value="3"/>
|
||||
<Property name="title" type="java.lang.String" value="Register"/>
|
||||
</Properties>
|
||||
<SyntheticProperties>
|
||||
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||
</SyntheticProperties>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Group type="103" alignment="0" groupAlignment="1" attributes="0">
|
||||
<Component id="lblPasswordConfirmationReasoning" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="lblServer" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblUserName" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblPort" alignment="1" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblPassword" alignment="1" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblPasswordConfirmation" alignment="1" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblEmail" alignment="1" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="txtServer" min="-2" pref="292" max="-2" attributes="0"/>
|
||||
<Component id="txtPort" min="-2" pref="292" max="-2" attributes="0"/>
|
||||
<Component id="txtUserName" alignment="0" min="-2" pref="292" max="-2" attributes="0"/>
|
||||
<Component id="txtPassword" alignment="0" min="-2" pref="292" max="-2" attributes="0"/>
|
||||
<Component id="txtPasswordConfirmation" alignment="0" min="-2" pref="292" max="-2" attributes="0"/>
|
||||
<Component id="txtEmail" min="-2" pref="292" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Component id="lblEmailReasoning" alignment="1" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="btnRegister" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnCancel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Component id="lblStatus" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace pref="22" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="9" 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"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="lblPort" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="txtPort" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="lblUserName" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="txtUserName" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="lblPassword" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="txtPassword" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="txtPasswordConfirmation" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblPasswordConfirmation" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="lblPasswordConfirmationReasoning" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="lblEmail" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="txtEmail" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="lblEmailReasoning" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="lblStatus" min="-2" pref="28" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="btnCancel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btnRegister" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="lblServer">
|
||||
<Properties>
|
||||
<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:"/>
|
||||
</Properties>
|
||||
</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.JLabel" name="lblUserName">
|
||||
<Properties>
|
||||
<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:"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblPassword">
|
||||
<Properties>
|
||||
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
|
||||
<ComponentRef name="txtPassword"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Password:"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="txtUserName">
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtUserNameActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JPasswordField" name="txtPassword">
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnRegister">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Register"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnRegisterActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnCancel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Cancel"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnCancelActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblStatus">
|
||||
<Properties>
|
||||
<Property name="toolTipText" type="java.lang.String" value=""/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="txtServer">
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="txtPort">
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="txtEmail">
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblPasswordConfirmation">
|
||||
<Properties>
|
||||
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
|
||||
<ComponentRef name="txtPasswordConfirmation"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Password:"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JPasswordField" name="txtPasswordConfirmation">
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblEmail">
|
||||
<Properties>
|
||||
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
|
||||
<ComponentRef name="txtEmail"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Email:"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblPasswordConfirmationReasoning">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Lucida Grande" size="10" style="0"/>
|
||||
</Property>
|
||||
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
|
||||
<ComponentRef name="txtPasswordConfirmation"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="(confirmation)"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblEmailReasoning">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Lucida Grande" size="10" style="0"/>
|
||||
</Property>
|
||||
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
|
||||
<ComponentRef name="txtEmail"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="(used for password reset)"/>
|
||||
<Property name="toolTipText" type="java.lang.String" value=""/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
|
@ -0,0 +1,286 @@
|
|||
package mage.client.dialog;
|
||||
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import javax.swing.SwingWorker;
|
||||
import mage.client.MageFrame;
|
||||
import mage.client.preference.MagePreferences;
|
||||
import mage.remote.Connection;
|
||||
import mage.remote.Session;
|
||||
import mage.remote.SessionImpl;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
public class RegisterUserDialog extends MageDialog {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ConnectDialog.class);
|
||||
private ConnectDialog connectDialog;
|
||||
private Connection connection;
|
||||
private ConnectTask task;
|
||||
private Session session;
|
||||
|
||||
/**
|
||||
* Creates new form RegisterUserDialog
|
||||
*/
|
||||
public RegisterUserDialog(ConnectDialog connectDialog) {
|
||||
initComponents();
|
||||
this.connectDialog = connectDialog;
|
||||
}
|
||||
|
||||
public void showDialog() {
|
||||
this.txtServer.setText(this.connectDialog.getServer());
|
||||
this.txtPort.setText(this.connectDialog.getPort());
|
||||
this.lblStatus.setText("");
|
||||
|
||||
this.setModal(true);
|
||||
this.setLocation(50, 50);
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
lblServer = new javax.swing.JLabel();
|
||||
lblPort = new javax.swing.JLabel();
|
||||
lblUserName = new javax.swing.JLabel();
|
||||
lblPassword = new javax.swing.JLabel();
|
||||
txtUserName = new javax.swing.JTextField();
|
||||
txtPassword = new javax.swing.JPasswordField();
|
||||
btnRegister = new javax.swing.JButton();
|
||||
btnCancel = new javax.swing.JButton();
|
||||
lblStatus = new javax.swing.JLabel();
|
||||
txtServer = new javax.swing.JTextField();
|
||||
txtPort = new javax.swing.JTextField();
|
||||
txtEmail = new javax.swing.JTextField();
|
||||
lblPasswordConfirmation = new javax.swing.JLabel();
|
||||
txtPasswordConfirmation = new javax.swing.JPasswordField();
|
||||
lblEmail = new javax.swing.JLabel();
|
||||
lblPasswordConfirmationReasoning = new javax.swing.JLabel();
|
||||
lblEmailReasoning = new javax.swing.JLabel();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||
setTitle("Register");
|
||||
|
||||
lblServer.setLabelFor(txtServer);
|
||||
lblServer.setText("Server:");
|
||||
|
||||
lblPort.setLabelFor(txtPort);
|
||||
lblPort.setText("Port:");
|
||||
|
||||
lblUserName.setLabelFor(txtUserName);
|
||||
lblUserName.setText("User name:");
|
||||
|
||||
lblPassword.setLabelFor(txtPassword);
|
||||
lblPassword.setText("Password:");
|
||||
|
||||
txtUserName.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
txtUserNameActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
btnRegister.setText("Register");
|
||||
btnRegister.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btnRegisterActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
btnCancel.setText("Cancel");
|
||||
btnCancel.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btnCancelActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
lblStatus.setToolTipText("");
|
||||
|
||||
lblPasswordConfirmation.setLabelFor(txtPasswordConfirmation);
|
||||
lblPasswordConfirmation.setText("Password:");
|
||||
|
||||
lblEmail.setLabelFor(txtEmail);
|
||||
lblEmail.setText("Email:");
|
||||
|
||||
lblPasswordConfirmationReasoning.setFont(new java.awt.Font("Lucida Grande", 0, 10)); // NOI18N
|
||||
lblPasswordConfirmationReasoning.setLabelFor(txtPasswordConfirmation);
|
||||
lblPasswordConfirmationReasoning.setText("(confirmation)");
|
||||
|
||||
lblEmailReasoning.setFont(new java.awt.Font("Lucida Grande", 0, 10)); // NOI18N
|
||||
lblEmailReasoning.setLabelFor(txtEmail);
|
||||
lblEmailReasoning.setText("(used for password reset)");
|
||||
lblEmailReasoning.setToolTipText("");
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||
getContentPane().setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(lblPasswordConfirmationReasoning)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(lblServer)
|
||||
.addComponent(lblUserName)
|
||||
.addComponent(lblPort)
|
||||
.addComponent(lblPassword)
|
||||
.addComponent(lblPasswordConfirmation)
|
||||
.addComponent(lblEmail))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(txtServer, javax.swing.GroupLayout.PREFERRED_SIZE, 292, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, 292, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(txtUserName, javax.swing.GroupLayout.PREFERRED_SIZE, 292, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 292, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(txtPasswordConfirmation, javax.swing.GroupLayout.PREFERRED_SIZE, 292, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(txtEmail, javax.swing.GroupLayout.PREFERRED_SIZE, 292, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addComponent(lblEmailReasoning)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(btnRegister)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnCancel)))
|
||||
.addComponent(lblStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap(22, Short.MAX_VALUE))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(9, 9, 9)
|
||||
.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))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(lblPort)
|
||||
.addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(lblUserName)
|
||||
.addComponent(txtUserName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(lblPassword)
|
||||
.addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(txtPasswordConfirmation, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lblPasswordConfirmation))
|
||||
.addComponent(lblPasswordConfirmationReasoning)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(lblEmail)
|
||||
.addComponent(txtEmail, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lblEmailReasoning)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(lblStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(btnCancel)
|
||||
.addComponent(btnRegister))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
pack();
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void txtUserNameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtUserNameActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_txtUserNameActionPerformed
|
||||
|
||||
private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed
|
||||
this.hideDialog();
|
||||
}//GEN-LAST:event_btnCancelActionPerformed
|
||||
|
||||
private void btnRegisterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRegisterActionPerformed
|
||||
if (!this.txtPassword.getText().equals(this.txtPasswordConfirmation.getText())) {
|
||||
MageFrame.getInstance().showError("Passwords don't match.");
|
||||
return;
|
||||
}
|
||||
connection = new Connection();
|
||||
connection.setHost(this.txtServer.getText().trim());
|
||||
connection.setPort(Integer.valueOf(this.txtPort.getText().trim()));
|
||||
connection.setUsername(this.txtUserName.getText().trim());
|
||||
connection.setPassword(this.txtPassword.getText().trim());
|
||||
connection.setEmail(this.txtEmail.getText().trim());
|
||||
PreferencesDialog.setProxyInformation(connection);
|
||||
task = new ConnectTask();
|
||||
task.execute();
|
||||
}//GEN-LAST:event_btnRegisterActionPerformed
|
||||
|
||||
private class ConnectTask extends SwingWorker<Boolean, Void> {
|
||||
|
||||
private boolean result = false;
|
||||
|
||||
private static final int CONNECTION_TIMEOUT_MS = 2100;
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground() throws Exception {
|
||||
lblStatus.setText("Connecting...");
|
||||
btnRegister.setEnabled(false);
|
||||
session = new SessionImpl(MageFrame.getInstance());
|
||||
result = session.register(connection);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
try {
|
||||
get(CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
if (result) {
|
||||
// Save settings.
|
||||
MagePreferences.setServerAddress(connection.getHost());
|
||||
MagePreferences.setServerPort(connection.getPort());
|
||||
MagePreferences.setUserName(connection.getHost(), connection.getUsername());
|
||||
MagePreferences.setPassword(connection.getHost(), connection.getPassword());
|
||||
MagePreferences.setEmail(connection.getHost(), connection.getEmail());
|
||||
|
||||
String message = "Registration succeeded";
|
||||
lblStatus.setText(message);
|
||||
MageFrame.getInstance().showMessage(message);
|
||||
hideDialog();
|
||||
} else {
|
||||
lblStatus.setText("Could not register");
|
||||
}
|
||||
} catch (InterruptedException | ExecutionException ex) {
|
||||
logger.fatal("Registration task error", ex);
|
||||
} catch (CancellationException ex) {
|
||||
logger.info("Registration was canceled");
|
||||
lblStatus.setText("Registration was canceled (but an account might have been actually created)");
|
||||
} catch (TimeoutException ex) {
|
||||
logger.fatal("Registration timeout: ", ex);
|
||||
} finally {
|
||||
MageFrame.stopConnecting();
|
||||
btnRegister.setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton btnCancel;
|
||||
private javax.swing.JButton btnRegister;
|
||||
private javax.swing.JLabel lblEmail;
|
||||
private javax.swing.JLabel lblEmailReasoning;
|
||||
private javax.swing.JLabel lblPassword;
|
||||
private javax.swing.JLabel lblPasswordConfirmation;
|
||||
private javax.swing.JLabel lblPasswordConfirmationReasoning;
|
||||
private javax.swing.JLabel lblPort;
|
||||
private javax.swing.JLabel lblServer;
|
||||
private javax.swing.JLabel lblStatus;
|
||||
private javax.swing.JLabel lblUserName;
|
||||
private javax.swing.JTextField txtEmail;
|
||||
private javax.swing.JPasswordField txtPassword;
|
||||
private javax.swing.JPasswordField txtPasswordConfirmation;
|
||||
private javax.swing.JTextField txtPort;
|
||||
private javax.swing.JTextField txtServer;
|
||||
private javax.swing.JTextField txtUserName;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
|
@ -0,0 +1,320 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JInternalFrameFormInfo">
|
||||
<Properties>
|
||||
<Property name="defaultCloseOperation" type="int" value="3"/>
|
||||
<Property name="title" type="java.lang.String" value="Reset password"/>
|
||||
</Properties>
|
||||
<SyntheticProperties>
|
||||
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||
</SyntheticProperties>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
<Component id="btnCancel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jPanel2" alignment="1" max="32767" attributes="0"/>
|
||||
<Component id="jPanel1" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="lblStatus" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="lblServer" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblPort" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="txtServer" max="32767" attributes="0"/>
|
||||
<Component id="txtPort" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace 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 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"/>
|
||||
</Group>
|
||||
<EmptySpace 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"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jPanel1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jPanel2" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lblStatus" min="-2" pref="28" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnCancel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="jPanel2">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="jLabel6" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="1" max="-2" attributes="0">
|
||||
<Component id="lblAuthToken" alignment="1" min="-2" pref="74" max="-2" attributes="0"/>
|
||||
<Component id="lblPassword" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="lblPasswordConfirmation" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="txtAuthToken" max="32767" attributes="0"/>
|
||||
<Component id="txtPassword" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="txtPasswordConfirmation" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="0" pref="204" max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="lblPasswordConfirmationReasoning" alignment="1" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btnSubmitNewPassword" alignment="1" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="jLabel6" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="24" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="lblAuthToken" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="txtAuthToken" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="lblPassword" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="txtPassword" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="lblPasswordConfirmation" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="txtPasswordConfirmation" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lblPasswordConfirmationReasoning" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="btnSubmitNewPassword" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="9" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="jLabel6">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Lucida Grande" size="13" style="1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Step 2:"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblAuthToken">
|
||||
<Properties>
|
||||
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
|
||||
<ComponentRef name="txtAuthToken"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Auth token:"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblPassword">
|
||||
<Properties>
|
||||
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
|
||||
<ComponentRef name="txtPassword"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="New password:"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblPasswordConfirmation">
|
||||
<Properties>
|
||||
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
|
||||
<ComponentRef name="txtPasswordConfirmation"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="New password:"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="txtAuthToken">
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnSubmitNewPassword">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Submit a new password"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnSubmitNewPasswordActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblPasswordConfirmationReasoning">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Lucida Grande" size="10" style="0"/>
|
||||
</Property>
|
||||
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
|
||||
<ComponentRef name="txtPasswordConfirmation"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="(confirmation)"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JPasswordField" name="txtPassword">
|
||||
</Component>
|
||||
<Component class="javax.swing.JPasswordField" name="txtPasswordConfirmation">
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="jPanel1">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="jLabel5" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="lblEmail" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="txtEmail" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
<Component id="btnGetAuthToken" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="jLabel5" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="24" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="lblEmail" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="txtEmail" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="btnGetAuthToken" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="jLabel5">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Lucida Grande" size="13" style="1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Step 1:"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblEmail">
|
||||
<Properties>
|
||||
<Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
|
||||
<ComponentRef name="txtEmail"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Email:"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="txtEmail">
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnGetAuthToken">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Email an auth token"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnGetAuthTokenActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="lblStatus">
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="btnCancel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Cancel"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnCancelActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblServer">
|
||||
<Properties>
|
||||
<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:"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="txtServer">
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="txtPort">
|
||||
</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>
|
||||
</SubComponents>
|
||||
</Form>
|
|
@ -0,0 +1,431 @@
|
|||
package mage.client.dialog;
|
||||
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import javax.swing.SwingWorker;
|
||||
import mage.client.MageFrame;
|
||||
import mage.client.preference.MagePreferences;
|
||||
import mage.remote.Connection;
|
||||
import mage.remote.Session;
|
||||
import mage.remote.SessionImpl;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
public class ResetPasswordDialog extends MageDialog {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ResetPasswordDialog.class);
|
||||
private ConnectDialog connectDialog;
|
||||
private Connection connection;
|
||||
private Session session;
|
||||
private GetAuthTokenTask getAuthTokenTask;
|
||||
private ResetPasswordTask resetPasswordTask;
|
||||
|
||||
/**
|
||||
* Creates new form ResetPasswordDialog
|
||||
*/
|
||||
public ResetPasswordDialog(ConnectDialog connectDialog) {
|
||||
initComponents();
|
||||
this.connectDialog = connectDialog;
|
||||
}
|
||||
|
||||
public void showDialog() {
|
||||
String serverAddress = this.connectDialog.getServer();
|
||||
this.txtServer.setText(serverAddress);
|
||||
this.txtPort.setText(this.connectDialog.getPort());
|
||||
this.txtEmail.setText(MagePreferences.getEmail(serverAddress));
|
||||
this.lblStatus.setText("");
|
||||
|
||||
this.setModal(true);
|
||||
this.setLocation(50, 50);
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
jPanel2 = new javax.swing.JPanel();
|
||||
jLabel6 = new javax.swing.JLabel();
|
||||
lblAuthToken = new javax.swing.JLabel();
|
||||
lblPassword = new javax.swing.JLabel();
|
||||
lblPasswordConfirmation = new javax.swing.JLabel();
|
||||
txtAuthToken = new javax.swing.JTextField();
|
||||
btnSubmitNewPassword = new javax.swing.JButton();
|
||||
lblPasswordConfirmationReasoning = new javax.swing.JLabel();
|
||||
txtPassword = new javax.swing.JPasswordField();
|
||||
txtPasswordConfirmation = new javax.swing.JPasswordField();
|
||||
jPanel1 = new javax.swing.JPanel();
|
||||
jLabel5 = new javax.swing.JLabel();
|
||||
lblEmail = new javax.swing.JLabel();
|
||||
txtEmail = new javax.swing.JTextField();
|
||||
btnGetAuthToken = new javax.swing.JButton();
|
||||
lblStatus = new javax.swing.JLabel();
|
||||
btnCancel = new javax.swing.JButton();
|
||||
lblServer = new javax.swing.JLabel();
|
||||
txtServer = new javax.swing.JTextField();
|
||||
txtPort = new javax.swing.JTextField();
|
||||
lblPort = new javax.swing.JLabel();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||
setTitle("Reset password");
|
||||
|
||||
jPanel2.setBorder(javax.swing.BorderFactory.createEtchedBorder());
|
||||
|
||||
jLabel6.setFont(new java.awt.Font("Lucida Grande", 1, 13)); // NOI18N
|
||||
jLabel6.setText("Step 2:");
|
||||
|
||||
lblAuthToken.setLabelFor(txtAuthToken);
|
||||
lblAuthToken.setText("Auth token:");
|
||||
|
||||
lblPassword.setLabelFor(txtPassword);
|
||||
lblPassword.setText("New password:");
|
||||
|
||||
lblPasswordConfirmation.setLabelFor(txtPasswordConfirmation);
|
||||
lblPasswordConfirmation.setText("New password:");
|
||||
|
||||
btnSubmitNewPassword.setText("Submit a new password");
|
||||
btnSubmitNewPassword.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btnSubmitNewPasswordActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
lblPasswordConfirmationReasoning.setFont(new java.awt.Font("Lucida Grande", 0, 10)); // NOI18N
|
||||
lblPasswordConfirmationReasoning.setLabelFor(txtPasswordConfirmation);
|
||||
lblPasswordConfirmationReasoning.setText("(confirmation)");
|
||||
|
||||
javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
|
||||
jPanel2.setLayout(jPanel2Layout);
|
||||
jPanel2Layout.setHorizontalGroup(
|
||||
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel2Layout.createSequentialGroup()
|
||||
.addComponent(jLabel6)
|
||||
.addGap(0, 0, Short.MAX_VALUE))
|
||||
.addGroup(jPanel2Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel2Layout.createSequentialGroup()
|
||||
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
|
||||
.addComponent(lblAuthToken, javax.swing.GroupLayout.PREFERRED_SIZE, 74, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lblPassword, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(lblPasswordConfirmation, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(txtAuthToken)
|
||||
.addComponent(txtPassword)
|
||||
.addComponent(txtPasswordConfirmation)))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
|
||||
.addGap(0, 204, Short.MAX_VALUE)
|
||||
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(lblPasswordConfirmationReasoning, javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(btnSubmitNewPassword, javax.swing.GroupLayout.Alignment.TRAILING))))
|
||||
.addContainerGap())
|
||||
);
|
||||
jPanel2Layout.setVerticalGroup(
|
||||
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel2Layout.createSequentialGroup()
|
||||
.addComponent(jLabel6)
|
||||
.addGap(24, 24, 24)
|
||||
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(lblAuthToken)
|
||||
.addComponent(txtAuthToken, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(lblPassword)
|
||||
.addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(lblPasswordConfirmation)
|
||||
.addComponent(txtPasswordConfirmation, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lblPasswordConfirmationReasoning)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(btnSubmitNewPassword)
|
||||
.addContainerGap(9, Short.MAX_VALUE))
|
||||
);
|
||||
|
||||
jPanel1.setBorder(javax.swing.BorderFactory.createEtchedBorder());
|
||||
|
||||
jLabel5.setFont(new java.awt.Font("Lucida Grande", 1, 13)); // NOI18N
|
||||
jLabel5.setText("Step 1:");
|
||||
|
||||
lblEmail.setLabelFor(txtEmail);
|
||||
lblEmail.setText("Email:");
|
||||
|
||||
btnGetAuthToken.setText("Email an auth token");
|
||||
btnGetAuthToken.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btnGetAuthTokenActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
|
||||
jPanel1.setLayout(jPanel1Layout);
|
||||
jPanel1Layout.setHorizontalGroup(
|
||||
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addComponent(jLabel5)
|
||||
.addGap(0, 0, Short.MAX_VALUE))
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addComponent(lblEmail)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(txtEmail))
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
.addComponent(btnGetAuthToken)))
|
||||
.addContainerGap())
|
||||
);
|
||||
jPanel1Layout.setVerticalGroup(
|
||||
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addComponent(jLabel5)
|
||||
.addGap(24, 24, 24)
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(lblEmail)
|
||||
.addComponent(txtEmail, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(btnGetAuthToken)
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
btnCancel.setText("Cancel");
|
||||
btnCancel.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btnCancelActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
lblServer.setLabelFor(txtServer);
|
||||
lblServer.setText("Server:");
|
||||
|
||||
lblPort.setLabelFor(txtPort);
|
||||
lblPort.setText("Port:");
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||
getContentPane().setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
.addComponent(btnCancel))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jPanel2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(lblStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(lblServer)
|
||||
.addComponent(lblPort))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(txtServer)
|
||||
.addComponent(txtPort))))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(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))
|
||||
.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))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lblStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(btnCancel)
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
|
||||
pack();
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void btnGetAuthTokenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGetAuthTokenActionPerformed
|
||||
if (this.txtEmail.getText().length() == 0) {
|
||||
MageFrame.getInstance().showError("Please enter an email address.");
|
||||
return;
|
||||
}
|
||||
|
||||
connection = new Connection();
|
||||
connection.setHost(this.txtServer.getText().trim());
|
||||
connection.setPort(Integer.valueOf(this.txtPort.getText().trim()));
|
||||
PreferencesDialog.setProxyInformation(connection);
|
||||
connection.setEmail(this.txtEmail.getText().trim());
|
||||
|
||||
getAuthTokenTask = new GetAuthTokenTask();
|
||||
getAuthTokenTask.execute();
|
||||
}//GEN-LAST:event_btnGetAuthTokenActionPerformed
|
||||
|
||||
private void btnSubmitNewPasswordActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSubmitNewPasswordActionPerformed
|
||||
if (this.txtEmail.getText().length() == 0) {
|
||||
MageFrame.getInstance().showError("Please enter an email address.");
|
||||
return;
|
||||
}
|
||||
if (this.txtAuthToken.getText().length() == 0) {
|
||||
MageFrame.getInstance().showError("Please enter an auth token.");
|
||||
return;
|
||||
}
|
||||
if (this.txtPassword.getText().length() == 0) {
|
||||
MageFrame.getInstance().showError("Please enter a new password.");
|
||||
return;
|
||||
}
|
||||
if (!this.txtPassword.getText().equals(this.txtPasswordConfirmation.getText())) {
|
||||
MageFrame.getInstance().showError("Passwords don't match.");
|
||||
return;
|
||||
}
|
||||
|
||||
connection = new Connection();
|
||||
connection.setHost(this.txtServer.getText().trim());
|
||||
connection.setPort(Integer.valueOf(this.txtPort.getText().trim()));
|
||||
PreferencesDialog.setProxyInformation(connection);
|
||||
connection.setEmail(this.txtEmail.getText().trim());
|
||||
connection.setAuthToken(this.txtAuthToken.getText().trim());
|
||||
connection.setPassword(this.txtPassword.getText().trim());
|
||||
|
||||
resetPasswordTask = new ResetPasswordTask();
|
||||
resetPasswordTask.execute();
|
||||
}//GEN-LAST:event_btnSubmitNewPasswordActionPerformed
|
||||
|
||||
private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed
|
||||
this.hideDialog();
|
||||
}//GEN-LAST:event_btnCancelActionPerformed
|
||||
|
||||
void disableButtons() {
|
||||
btnGetAuthToken.setEnabled(false);
|
||||
btnSubmitNewPassword.setEnabled(false);
|
||||
}
|
||||
|
||||
void enableButtons() {
|
||||
btnGetAuthToken.setEnabled(true);
|
||||
btnSubmitNewPassword.setEnabled(true);
|
||||
}
|
||||
|
||||
private class GetAuthTokenTask extends SwingWorker<Boolean, Void> {
|
||||
|
||||
private boolean result = false;
|
||||
|
||||
private static final int CONNECTION_TIMEOUT_MS = 2100;
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground() throws Exception {
|
||||
lblStatus.setText("Connecting...");
|
||||
disableButtons();
|
||||
session = new SessionImpl(MageFrame.getInstance());
|
||||
result = session.emailAuthToken(connection);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
try {
|
||||
get(CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
if (result) {
|
||||
// Save settings.
|
||||
MagePreferences.setEmail(connection.getHost(), connection.getEmail());
|
||||
|
||||
String message = "Auth token is emailed. Please check your inbox.";
|
||||
lblStatus.setText(message);
|
||||
MageFrame.getInstance().showMessage(message);
|
||||
} else {
|
||||
lblStatus.setText("There was an issue while requesting an auth token.");
|
||||
}
|
||||
} catch (InterruptedException | ExecutionException ex) {
|
||||
logger.fatal("Get Auth Token Task error", ex);
|
||||
} catch (CancellationException ex) {
|
||||
logger.info("Canceled");
|
||||
lblStatus.setText("Canceled");
|
||||
} catch (TimeoutException ex) {
|
||||
logger.fatal("Timeout: ", ex);
|
||||
} finally {
|
||||
MageFrame.stopConnecting();
|
||||
enableButtons();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ResetPasswordTask extends SwingWorker<Boolean, Void> {
|
||||
|
||||
private boolean result = false;
|
||||
|
||||
private static final int CONNECTION_TIMEOUT_MS = 2100;
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground() throws Exception {
|
||||
lblStatus.setText("Connecting...");
|
||||
disableButtons();
|
||||
session = new SessionImpl(MageFrame.getInstance());
|
||||
result = session.resetPassword(connection);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
try {
|
||||
get(CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
if (result) {
|
||||
// Save settings.
|
||||
MagePreferences.setPassword(connection.getHost(), connection.getPassword());
|
||||
|
||||
String message = "Password is reset successfully.";
|
||||
lblStatus.setText(message);
|
||||
MageFrame.getInstance().showMessage(message);
|
||||
hideDialog();
|
||||
} else {
|
||||
lblStatus.setText("There was an issue while resetting password.");
|
||||
}
|
||||
} catch (InterruptedException | ExecutionException ex) {
|
||||
logger.fatal("Reset Password Task error", ex);
|
||||
} catch (CancellationException ex) {
|
||||
logger.info("Canceled");
|
||||
lblStatus.setText("Canceled");
|
||||
} catch (TimeoutException ex) {
|
||||
logger.fatal("Timeout: ", ex);
|
||||
} finally {
|
||||
MageFrame.stopConnecting();
|
||||
enableButtons();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton btnCancel;
|
||||
private javax.swing.JButton btnGetAuthToken;
|
||||
private javax.swing.JButton btnSubmitNewPassword;
|
||||
private javax.swing.JLabel jLabel5;
|
||||
private javax.swing.JLabel jLabel6;
|
||||
private javax.swing.JPanel jPanel1;
|
||||
private javax.swing.JPanel jPanel2;
|
||||
private javax.swing.JLabel lblAuthToken;
|
||||
private javax.swing.JLabel lblEmail;
|
||||
private javax.swing.JLabel lblPassword;
|
||||
private javax.swing.JLabel lblPasswordConfirmation;
|
||||
private javax.swing.JLabel lblPasswordConfirmationReasoning;
|
||||
private javax.swing.JLabel lblPort;
|
||||
private javax.swing.JLabel lblServer;
|
||||
private javax.swing.JLabel lblStatus;
|
||||
private javax.swing.JTextField txtAuthToken;
|
||||
private javax.swing.JTextField txtEmail;
|
||||
private javax.swing.JPasswordField txtPassword;
|
||||
private javax.swing.JPasswordField txtPasswordConfirmation;
|
||||
private javax.swing.JTextField txtPort;
|
||||
private javax.swing.JTextField txtServer;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
|
@ -26,7 +26,7 @@
|
|||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* TableWaitingDialog.java
|
||||
*
|
||||
* Created on Dec 16, 2009, 10:27:44 AM
|
||||
|
@ -68,7 +68,7 @@ public class TableWaitingDialog extends MageDialog {
|
|||
private Session session;
|
||||
private final TableWaitModel tableWaitModel;
|
||||
private UpdateSeatsTask updateTask;
|
||||
private static final int[] defaultColumnsWidth = {20, 50, 100, 100};
|
||||
private static final int[] defaultColumnsWidth = {20, 50, 100, 100, 100};
|
||||
|
||||
/**
|
||||
* Creates new form TableWaitingDialog
|
||||
|
@ -268,10 +268,8 @@ public class TableWaitingDialog extends MageDialog {
|
|||
if (session.startMatch(roomId, tableId)) {
|
||||
closeDialog();
|
||||
}
|
||||
} else {
|
||||
if (session.startTournament(roomId, tableId)) {
|
||||
closeDialog();
|
||||
}
|
||||
} else if (session.startTournament(roomId, tableId)) {
|
||||
closeDialog();
|
||||
}
|
||||
}//GEN-LAST:event_btnStartActionPerformed
|
||||
|
||||
|
@ -319,7 +317,7 @@ public class TableWaitingDialog extends MageDialog {
|
|||
|
||||
class TableWaitModel extends AbstractTableModel {
|
||||
|
||||
private final String[] columnNames = new String[]{"Seat", "Loc", "Player Name", "Player Type"};
|
||||
private final String[] columnNames = new String[]{"Seat", "Loc", "Player Name", "Player Type", "History"};
|
||||
private SeatView[] seats = new SeatView[0];
|
||||
|
||||
public void loadData(TableView table) {
|
||||
|
@ -353,6 +351,8 @@ class TableWaitModel extends AbstractTableModel {
|
|||
return seats[arg0].getPlayerName();
|
||||
case 3:
|
||||
return seats[arg0].getPlayerType();
|
||||
case 4:
|
||||
return seats[arg0].getHistory();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* PlayerPanel.java
|
||||
*
|
||||
* Created on Nov 18, 2009, 3:01:31 PM
|
||||
|
@ -288,7 +288,8 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
basicTooltipText = "<HTML>Name: " + player.getName()
|
||||
+ "<br/>Country: " + countryname
|
||||
+ "<br/>Deck hash code: " + player.getDeckHashCode()
|
||||
+ "<br/>Wins: " + player.getWins() + " of " + player.getWinsNeeded() + " (to win the match)";
|
||||
+ "<br/>This match wins: " + player.getWins() + " of " + player.getWinsNeeded() + " (to win the match)"
|
||||
+ (player.getUserData() == null ? "" : "<br/>History: " + player.getUserData().getHistory());
|
||||
}
|
||||
// Extend tooltip
|
||||
StringBuilder tooltipText = new StringBuilder(basicTooltipText);
|
||||
|
@ -580,7 +581,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
manaCountLabelX.setText("0");
|
||||
manaLabels.put("X", manaCountLabelX);
|
||||
r = new Rectangle(12, 12);
|
||||
BufferedImage imageManaX = ManaSymbols.getManaSymbolImageSmall("X");
|
||||
BufferedImage imageManaX = ManaSymbols.getManaSymbolImageSmall("C");
|
||||
HoverButton btnColorlessMana = new HoverButton(null, imageManaX, imageManaX, imageManaX, r);
|
||||
btnColorlessMana.setToolTipText("Colorless mana");
|
||||
btnColorlessMana.setOpaque(false);
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
package mage.client.preference;
|
||||
|
||||
import java.util.prefs.Preferences;
|
||||
import mage.client.MageFrame;
|
||||
|
||||
// TODO: Move all preference related logic from MageFrame and PreferencesDialog to this class.
|
||||
public class MagePreferences {
|
||||
|
||||
private static final String KEY_SERVER_ADDRESS = "serverAddress";
|
||||
private static final String KEY_SERVER_PORT = "serverPort";
|
||||
private static final String KEY_USER_NAME = "userName";
|
||||
private static final String KEY_PASSWORD = "password";
|
||||
private static final String KEY_EMAIL = "email";
|
||||
private static final String KEY_AUTO_CONNECT = "autoConnect";
|
||||
|
||||
private static Preferences prefs() {
|
||||
// TODO: Move MageFrame.prefs to this class.
|
||||
return MageFrame.getPreferences();
|
||||
}
|
||||
|
||||
public static String getServerAddress() {
|
||||
return prefs().get(KEY_SERVER_ADDRESS, "");
|
||||
}
|
||||
|
||||
public static String getServerAddressWithDefault(String defaultValue) {
|
||||
return prefs().get(KEY_SERVER_ADDRESS, defaultValue);
|
||||
}
|
||||
|
||||
public static void setServerAddress(String serverAddress) {
|
||||
prefs().put(KEY_SERVER_ADDRESS, serverAddress);
|
||||
}
|
||||
|
||||
public static int getServerPort() {
|
||||
return prefs().getInt(KEY_SERVER_PORT, 0);
|
||||
}
|
||||
|
||||
public static int getServerPortWithDefault(int defaultValue) {
|
||||
return prefs().getInt(KEY_SERVER_PORT, defaultValue);
|
||||
}
|
||||
|
||||
public static void setServerPort(int port) {
|
||||
prefs().putInt(KEY_SERVER_PORT, port);
|
||||
}
|
||||
|
||||
private static String prefixedKey(String prefix, String key) {
|
||||
return prefix + "/" + key;
|
||||
}
|
||||
|
||||
public static String getUserName(String serverAddress) {
|
||||
String userName = prefs().get(prefixedKey(serverAddress, KEY_USER_NAME), "");
|
||||
if (!userName.isEmpty()) {
|
||||
return userName;
|
||||
}
|
||||
// For clients older than 1.4.7, userName is stored without a serverAddress prefix.
|
||||
return prefs().get(KEY_USER_NAME, "");
|
||||
}
|
||||
|
||||
public static void setUserName(String serverAddress, String userName) {
|
||||
prefs().put(prefixedKey(serverAddress, KEY_USER_NAME), userName);
|
||||
}
|
||||
|
||||
public static String getPassword(String serverAddress) {
|
||||
return prefs().get(prefixedKey(serverAddress, KEY_PASSWORD), "");
|
||||
}
|
||||
|
||||
public static void setPassword(String serverAddress, String password) {
|
||||
prefs().put(prefixedKey(serverAddress, KEY_PASSWORD), password);
|
||||
}
|
||||
|
||||
public static String getEmail(String serverAddress) {
|
||||
return prefs().get(prefixedKey(serverAddress, KEY_EMAIL), "");
|
||||
}
|
||||
|
||||
public static void setEmail(String serverAddress, String userName) {
|
||||
prefs().put(prefixedKey(serverAddress, KEY_EMAIL), userName);
|
||||
}
|
||||
|
||||
public static boolean getAutoConnect() {
|
||||
return prefs().getBoolean(KEY_AUTO_CONNECT, false);
|
||||
}
|
||||
|
||||
public static void setAutoConnect(boolean autoConnect) {
|
||||
prefs().putBoolean(KEY_AUTO_CONNECT, autoConnect);
|
||||
}
|
||||
}
|
|
@ -26,7 +26,7 @@
|
|||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* ChatPanel.java
|
||||
*
|
||||
* Created on 15-Dec-2009, 11:04:31 PM
|
||||
|
@ -61,7 +61,7 @@ public class PlayersChatPanel extends javax.swing.JPanel {
|
|||
|
||||
private final List<String> players = new ArrayList<>();
|
||||
private final UserTableModel userTableModel;
|
||||
private static final int[] defaultColumnsWidth = {20, 100, 100, 80, 80};
|
||||
private static final int[] DEFAULT_COLUMNS_WIDTH = {20, 100, 100, 80, 80};
|
||||
|
||||
|
||||
/*
|
||||
|
@ -78,7 +78,7 @@ public class PlayersChatPanel extends javax.swing.JPanel {
|
|||
jTablePlayers.setForeground(Color.white);
|
||||
jTablePlayers.setRowSorter(new MageTableRowSorter(userTableModel));
|
||||
|
||||
TableUtil.setColumnWidthAndOrder(jTablePlayers, defaultColumnsWidth, KEY_USERS_COLUMNS_WIDTH, KEY_USERS_COLUMNS_ORDER);
|
||||
TableUtil.setColumnWidthAndOrder(jTablePlayers, DEFAULT_COLUMNS_WIDTH, KEY_USERS_COLUMNS_WIDTH, KEY_USERS_COLUMNS_ORDER);
|
||||
jTablePlayers.setDefaultRenderer(Icon.class, new CountryCellRenderer());
|
||||
|
||||
jScrollPaneTalk.setSystemMessagesPane(colorPaneSystem);
|
||||
|
@ -118,7 +118,7 @@ public class PlayersChatPanel extends javax.swing.JPanel {
|
|||
|
||||
class UserTableModel extends AbstractTableModel {
|
||||
|
||||
private final String[] columnNames = new String[]{"Loc", "Players", "Info", "Games", "Connection"};
|
||||
private final String[] columnNames = new String[]{"Loc", "Players", "History", "Games", "Connection"};
|
||||
private UsersView[] players = new UsersView[0];
|
||||
|
||||
public void loadData(Collection<RoomUsersView> roomUserInfoList) throws MageRemoteException {
|
||||
|
@ -154,7 +154,7 @@ public class PlayersChatPanel extends javax.swing.JPanel {
|
|||
case 1:
|
||||
return players[arg0].getUserName();
|
||||
case 2:
|
||||
return players[arg0].getInfoState();
|
||||
return players[arg0].getHistory();
|
||||
case 3:
|
||||
return players[arg0].getInfoGames();
|
||||
case 4:
|
||||
|
|
|
@ -1,31 +1,30 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.client.util;
|
||||
|
||||
import java.awt.Component;
|
||||
|
@ -78,64 +77,64 @@ public class ButtonColumn extends AbstractCellEditor implements TableCellRendere
|
|||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
if (hasFocus)
|
||||
{
|
||||
if (hasFocus) {
|
||||
renderButton.setForeground(table.getForeground());
|
||||
renderButton.setBackground(UIManager.getColor("Button.background"));
|
||||
}
|
||||
else if (isSelected)
|
||||
{
|
||||
} else if (isSelected) {
|
||||
renderButton.setForeground(table.getSelectionForeground());
|
||||
renderButton.setBackground(table.getSelectionBackground());
|
||||
}
|
||||
else
|
||||
{
|
||||
renderButton.setBackground(table.getSelectionBackground());
|
||||
} else {
|
||||
renderButton.setForeground(table.getForeground());
|
||||
renderButton.setBackground(UIManager.getColor("Button.background"));
|
||||
}
|
||||
|
||||
renderButton.setText( (value == null) ? "" : value.toString() );
|
||||
renderButton.setText((value == null) ? "" : value.toString());
|
||||
return renderButton;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
|
||||
text = (value == null) ? "" : value.toString();
|
||||
editButton.setText( text );
|
||||
editButton.setText(text);
|
||||
return editButton;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int row = table.convertRowIndexToModel( table.getEditingRow() );
|
||||
fireEditingStopped();
|
||||
ActionEvent event = new ActionEvent(table, ActionEvent.ACTION_PERFORMED, "" + row);
|
||||
action.actionPerformed(event);
|
||||
|
||||
if (table.getRowCount() >= table.getEditingRow()) {
|
||||
int row = table.convertRowIndexToModel(table.getEditingRow());
|
||||
fireEditingStopped();
|
||||
ActionEvent event = new ActionEvent(table, ActionEvent.ACTION_PERFORMED, "" + row);
|
||||
action.actionPerformed(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent arg0) {
|
||||
if (table.isEditing() && table.getCellEditor() == this)
|
||||
if (table.isEditing() && table.getCellEditor() == this) {
|
||||
isButtonColumnEditor = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent arg0) {
|
||||
if (isButtonColumnEditor && table.isEditing())
|
||||
if (isButtonColumnEditor && table.isEditing()) {
|
||||
table.getCellEditor().stopCellEditing();
|
||||
}
|
||||
|
||||
isButtonColumnEditor = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent arg0) {}
|
||||
public void mouseClicked(MouseEvent arg0) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent arg0) {}
|
||||
public void mouseEntered(MouseEvent arg0) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent arg0) {}
|
||||
|
||||
public void mouseExited(MouseEvent arg0) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
package org.mage.card.arcane;
|
||||
|
||||
import mage.cards.repository.ExpansionRepository;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.client.util.ImageHelper;
|
||||
import mage.client.util.gui.BufferedImageBuilder;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.mage.plugins.card.constants.Constants;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Image;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
|
@ -16,6 +11,13 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.imageio.ImageIO;
|
||||
import mage.cards.repository.ExpansionRepository;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.client.util.ImageHelper;
|
||||
import mage.client.util.gui.BufferedImageBuilder;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.mage.plugins.card.constants.Constants;
|
||||
|
||||
public class ManaSymbols {
|
||||
|
||||
|
@ -30,10 +32,10 @@ public class ManaSymbols {
|
|||
public static void loadImages() {
|
||||
String[] symbols = new String[]{"0", "1", "10", "11", "12", "15", "16", "2", "3", "4", "5", "6", "7", "8", "9", "B", "BG",
|
||||
"BR", "G", "GU", "GW", "R", "RG", "RW", "S", "T", "U", "UB", "UR", "W", "WB", "WU",
|
||||
"WP", "UP", "BP", "RP", "GP", "X" /*, "Y", "Z", "slash"*/};
|
||||
"WP", "UP", "BP", "RP", "GP", "X", "C" /*, "Y", "Z", "slash"*/};
|
||||
|
||||
for (String symbol : symbols) {
|
||||
File file = new File(getSymbolsPath() + Constants.RESOURCE_PATH_MANA_MEDIUM + "/" + symbol + ".jpg");
|
||||
File file = new File(getSymbolsPath() + Constants.RESOURCE_PATH_MANA_MEDIUM + "/" + symbol + ".jpg");
|
||||
Rectangle r = new Rectangle(11, 11);
|
||||
try {
|
||||
Image image = UI.getImageIcon(file.getAbsolutePath()).getImage();
|
||||
|
@ -198,6 +200,7 @@ public class ManaSymbols {
|
|||
}
|
||||
|
||||
public enum Type {
|
||||
|
||||
CARD,
|
||||
TOOLTIP,
|
||||
PAY
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
/**
|
||||
* DownloadJob.java
|
||||
*
|
||||
*
|
||||
* Created on 25.08.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -21,25 +19,26 @@ import org.mage.plugins.card.dl.beans.properties.Property;
|
|||
import org.mage.plugins.card.dl.lm.AbstractLaternaBean;
|
||||
import org.mage.plugins.card.utils.CardImageUtils;
|
||||
|
||||
|
||||
/**
|
||||
* The class DownloadJob.
|
||||
*
|
||||
*
|
||||
* @version V0.0 25.08.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
public class DownloadJob extends AbstractLaternaBean {
|
||||
|
||||
public static enum State {
|
||||
|
||||
NEW, WORKING, FINISHED, ABORTED;
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final Source source;
|
||||
private final Destination destination;
|
||||
private final Property<State> state = properties.property("state", State.NEW);
|
||||
private final Property<String> message = properties.property("message");
|
||||
private final Property<Exception> error = properties.property("error");
|
||||
private final BoundedRangeModel progress = new DefaultBoundedRangeModel();
|
||||
private final String name;
|
||||
private final Source source;
|
||||
private final Destination destination;
|
||||
private final Property<State> state = properties.property("state", State.NEW);
|
||||
private final Property<String> message = properties.property("message");
|
||||
private final Property<Exception> error = properties.property("error");
|
||||
private final BoundedRangeModel progress = new DefaultBoundedRangeModel();
|
||||
|
||||
public DownloadJob(String name, Source source, Destination destination) {
|
||||
this.name = name;
|
||||
|
@ -48,7 +47,9 @@ public class DownloadJob extends AbstractLaternaBean {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the job's state. If the state is {@link State#ABORTED}, it instead sets the error to "ABORTED"
|
||||
* Sets the job's state. If the state is {@link State#ABORTED}, it instead
|
||||
* sets the error to "ABORTED"
|
||||
*
|
||||
* @param state
|
||||
*/
|
||||
public void setState(State state) {
|
||||
|
@ -60,8 +61,9 @@ public class DownloadJob extends AbstractLaternaBean {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the job's state to {@link State#ABORTED} and the error message to the given message. Logs a warning
|
||||
* with the given message.
|
||||
* Sets the job's state to {@link State#ABORTED} and the error message to
|
||||
* the given message. Logs a warning with the given message.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public void setError(String message) {
|
||||
|
@ -69,8 +71,9 @@ public class DownloadJob extends AbstractLaternaBean {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the job's state to {@link State#ABORTED} and the error to the given exception. Logs a warning with the
|
||||
* given exception.
|
||||
* Sets the job's state to {@link State#ABORTED} and the error to the given
|
||||
* exception. Logs a warning with the given exception.
|
||||
*
|
||||
* @param error
|
||||
*/
|
||||
public void setError(Exception error) {
|
||||
|
@ -78,14 +81,15 @@ public class DownloadJob extends AbstractLaternaBean {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the job's state to {@link State#ABORTED} and the error to the given exception. Logs a warning with the
|
||||
* given message and exception.
|
||||
* Sets the job's state to {@link State#ABORTED} and the error to the given
|
||||
* exception. Logs a warning with the given message and exception.
|
||||
*
|
||||
* @param message
|
||||
* @param error
|
||||
*/
|
||||
public void setError(String message, Exception error) {
|
||||
if (message == null) {
|
||||
|
||||
|
||||
message = "Download of " + this.getName() + "from " + this.getSource().toString() + " caused error: " + error.toString();
|
||||
}
|
||||
// log.warn(message, error);
|
||||
|
@ -97,6 +101,7 @@ public class DownloadJob extends AbstractLaternaBean {
|
|||
|
||||
/**
|
||||
* Sets the job's message.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public void setMessage(String message) {
|
||||
|
@ -119,7 +124,6 @@ public class DownloadJob extends AbstractLaternaBean {
|
|||
return message.getValue();
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
@ -163,9 +167,9 @@ public class DownloadJob extends AbstractLaternaBean {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return proxy != null ? proxy.type().toString()+" " :"" + url;
|
||||
return proxy != null ? proxy.type().toString() + " " : "" + url;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -189,11 +193,11 @@ public class DownloadJob extends AbstractLaternaBean {
|
|||
public int length() throws IOException {
|
||||
return getConnection().getContentLength();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return proxy != null ? proxy.type().toString()+" " :"" + url;
|
||||
}
|
||||
return proxy != null ? proxy.type().toString() + " " : "" + url;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -213,6 +217,14 @@ public class DownloadJob extends AbstractLaternaBean {
|
|||
return new FileOutputStream(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() throws IOException {
|
||||
if (file.isFile()) {
|
||||
return file.length() > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists() {
|
||||
return file.isFile();
|
||||
|
@ -228,16 +240,20 @@ public class DownloadJob extends AbstractLaternaBean {
|
|||
}
|
||||
|
||||
public interface Source {
|
||||
|
||||
InputStream open() throws IOException;
|
||||
|
||||
int length() throws IOException;
|
||||
}
|
||||
|
||||
public interface Destination {
|
||||
|
||||
OutputStream open() throws IOException;
|
||||
|
||||
boolean exists() throws IOException;
|
||||
|
||||
boolean isValid() throws IOException;
|
||||
|
||||
void delete() throws IOException;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
/**
|
||||
* Downloader.java
|
||||
*
|
||||
*
|
||||
* Created on 25.08.2010
|
||||
*/
|
||||
|
||||
package org.mage.plugins.card.dl;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
|
@ -29,10 +28,9 @@ import org.mage.plugins.card.dl.DownloadJob.Source;
|
|||
import org.mage.plugins.card.dl.DownloadJob.State;
|
||||
import org.mage.plugins.card.dl.lm.AbstractLaternaBean;
|
||||
|
||||
|
||||
/**
|
||||
* The class Downloader.
|
||||
*
|
||||
*
|
||||
* @version V0.0 25.08.2010
|
||||
* @author Clemens Koza
|
||||
*/
|
||||
|
@ -40,16 +38,16 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
|||
|
||||
private static final Logger logger = Logger.getLogger(Downloader.class);
|
||||
|
||||
private final List<DownloadJob> jobs = properties.list("jobs");
|
||||
private final List<DownloadJob> jobs = properties.list("jobs");
|
||||
private final Channel<DownloadJob> channel = new MemoryChannel<>();
|
||||
|
||||
private final ExecutorService pool = Executors.newCachedThreadPool();
|
||||
private final List<Fiber> fibers = new ArrayList<>();
|
||||
private final ExecutorService pool = Executors.newCachedThreadPool();
|
||||
private final List<Fiber> fibers = new ArrayList<>();
|
||||
|
||||
public Downloader() {
|
||||
PoolFiberFactory f = new PoolFiberFactory(pool);
|
||||
//subscribe multiple fibers for parallel execution
|
||||
for(int i = 0, numThreads = 10; i < numThreads; i++) {
|
||||
for (int i = 0, numThreads = 10; i < numThreads; i++) {
|
||||
Fiber fiber = f.create();
|
||||
fiber.start();
|
||||
fibers.add(fiber);
|
||||
|
@ -59,15 +57,15 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
|||
|
||||
@Override
|
||||
public void dispose() {
|
||||
for(DownloadJob j:getJobs()) {
|
||||
switch(j.getState()) {
|
||||
for (DownloadJob j : getJobs()) {
|
||||
switch (j.getState()) {
|
||||
case NEW:
|
||||
case WORKING:
|
||||
j.setState(State.ABORTED);
|
||||
}
|
||||
}
|
||||
|
||||
for(Fiber f:fibers) {
|
||||
for (Fiber f : fibers) {
|
||||
f.dispose();
|
||||
}
|
||||
pool.shutdown();
|
||||
|
@ -84,10 +82,10 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
|||
}
|
||||
|
||||
public void add(DownloadJob job) {
|
||||
if(job.getState() == State.WORKING) {
|
||||
if (job.getState() == State.WORKING) {
|
||||
throw new IllegalArgumentException("Job already running");
|
||||
}
|
||||
if(job.getState() == State.FINISHED) {
|
||||
if (job.getState() == State.FINISHED) {
|
||||
throw new IllegalArgumentException("Job already finished");
|
||||
}
|
||||
job.setState(State.NEW);
|
||||
|
@ -100,15 +98,17 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Performs the download job: Transfers data from {@link Source} to {@link Destination} and updates the
|
||||
* download job's state to reflect the progress.
|
||||
* Performs the download job: Transfers data from {@link Source} to
|
||||
* {@link Destination} and updates the download job's state to reflect the
|
||||
* progress.
|
||||
*/
|
||||
private class DownloadCallback implements Callback<DownloadJob> {
|
||||
|
||||
@Override
|
||||
public void onMessage(DownloadJob job) {
|
||||
//the job won't be processed by multiple threads
|
||||
synchronized(job) {
|
||||
if(job.getState() != State.NEW) {
|
||||
synchronized (job) {
|
||||
if (job.getState() != State.NEW) {
|
||||
return;
|
||||
}
|
||||
job.setState(State.WORKING);
|
||||
|
@ -118,10 +118,17 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
|||
Destination dst = job.getDestination();
|
||||
BoundedRangeModel progress = job.getProgress();
|
||||
|
||||
if(dst.exists()) {
|
||||
if (dst.isValid()) {
|
||||
progress.setMaximum(1);
|
||||
progress.setValue(1);
|
||||
} else {
|
||||
if (dst.exists()) {
|
||||
try {
|
||||
dst.delete();
|
||||
} catch (IOException ex1) {
|
||||
logger.warn("While deleting not valid file", ex1);
|
||||
}
|
||||
}
|
||||
progress.setMaximum(src.length());
|
||||
InputStream is = new BufferedInputStream(src.open());
|
||||
try {
|
||||
|
@ -129,45 +136,45 @@ public class Downloader extends AbstractLaternaBean implements Disposable {
|
|||
try {
|
||||
byte[] buf = new byte[8 * 1024];
|
||||
int total = 0;
|
||||
for(int len; (len = is.read(buf)) != -1;) {
|
||||
if(job.getState() == State.ABORTED) {
|
||||
for (int len; (len = is.read(buf)) != -1;) {
|
||||
if (job.getState() == State.ABORTED) {
|
||||
throw new IOException("Job was aborted");
|
||||
}
|
||||
progress.setValue(total += len);
|
||||
os.write(buf, 0, len);
|
||||
}
|
||||
} catch(IOException ex) {
|
||||
} catch (IOException ex) {
|
||||
try {
|
||||
dst.delete();
|
||||
} catch(IOException ex1) {
|
||||
} catch (IOException ex1) {
|
||||
logger.warn("While deleting", ex1);
|
||||
}
|
||||
throw ex;
|
||||
} finally {
|
||||
try {
|
||||
os.close();
|
||||
} catch(IOException ex) {
|
||||
} catch (IOException ex) {
|
||||
logger.warn("While closing", ex);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
is.close();
|
||||
} catch(IOException ex) {
|
||||
} catch (IOException ex) {
|
||||
logger.warn("While closing", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
job.setState(State.FINISHED);
|
||||
} catch(ConnectException ex) {
|
||||
} catch (ConnectException ex) {
|
||||
String message;
|
||||
if (ex.getMessage() != null) {
|
||||
message = ex.getMessage();
|
||||
} else {
|
||||
message = "Unknown error";
|
||||
}
|
||||
logger.warn("Error resource download " + job.getName() +" from "+ job.getSource().toString() + ": " + message);
|
||||
} catch(IOException ex) {
|
||||
logger.warn("Error resource download " + job.getName() + " from " + job.getSource().toString() + ": " + message);
|
||||
} catch (IOException ex) {
|
||||
job.setError(ex);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,6 +89,8 @@ public class MythicspoilerComSource implements CardImageSource {
|
|||
cardNameAliases.put("BFZ-unisonstrike", "tandemtactics");
|
||||
cardNameAliases.put("BFZ-eldrazidevastator", "eldrazidevastator");
|
||||
cardNameAliases.put("BFZ-kozliekschanneler", "kozilekschanneler");
|
||||
cardNameAliases.put("OGW-wastes", "wastes1");
|
||||
cardNameAliases.put("OGW-wastes2", "wastes2");
|
||||
|
||||
cardNameAliasesStart = new HashMap<>();
|
||||
HashSet<String> names = new HashSet<>();
|
||||
|
@ -156,14 +158,16 @@ public class MythicspoilerComSource implements CardImageSource {
|
|||
if (cardName != null && !cardName.isEmpty()) {
|
||||
if (cardNameAliases.containsKey(cardSet + "-" + cardName)) {
|
||||
cardName = cardNameAliases.get(cardSet + "-" + cardName);
|
||||
}
|
||||
if (cardName.endsWith("1") || cardName.endsWith("2") || cardName.endsWith("3") || cardName.endsWith("4") || cardName.endsWith("5")) {
|
||||
if (!cardName.startsWith("forest")
|
||||
&& !cardName.startsWith("swamp")
|
||||
&& !cardName.startsWith("mountain")
|
||||
&& !cardName.startsWith("island")
|
||||
&& !cardName.startsWith("plains")) {
|
||||
cardName = cardName.substring(0, cardName.length() - 1);
|
||||
} else {
|
||||
if (cardName.endsWith("1") || cardName.endsWith("2") || cardName.endsWith("3") || cardName.endsWith("4") || cardName.endsWith("5")) {
|
||||
if (!cardName.startsWith("forest")
|
||||
&& !cardName.startsWith("swamp")
|
||||
&& !cardName.startsWith("mountain")
|
||||
&& !cardName.startsWith("island")
|
||||
&& !cardName.startsWith("plains")) {
|
||||
|
||||
cardName = cardName.substring(0, cardName.length() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
setLinks.put(cardName, baseUrl + cardLink);
|
||||
|
@ -203,7 +207,8 @@ public class MythicspoilerComSource implements CardImageSource {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String generateTokenUrl(CardDownloadData card) {
|
||||
public String generateTokenUrl(CardDownloadData card
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -616,7 +616,9 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
new TFile(temporaryFile).cp_rp(outputFile);
|
||||
}
|
||||
} else {
|
||||
logger.warn("Image download for " + card.getName() + "(" + card.getSet() + ") failed - responseCode: " + responseCode + " url: " + url.toString());
|
||||
logger.warn("Image download for " + card.getName()
|
||||
+ (!card.getDownloadName().equals(card.getName()) ? " downloadname: " + card.getDownloadName() : "")
|
||||
+ "(" + card.getSet() + ") failed - responseCode: " + responseCode + " url: " + url.toString());
|
||||
if (logger.isDebugEnabled()) { // Shows the returned html from the request to the web server
|
||||
logger.debug("Return ed HTML ERROR:\n" + convertStreamToString(((HttpURLConnection) httpConn).getErrorStream()));
|
||||
}
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
#Generate|TOK:OGW|Elemental||
|
||||
#Generate|TOK:OGW|Plant||
|
||||
#Generate|TOK:OGW|Zombie||
|
||||
|Generate}TOK:OGW|Angel||
|
||||
|Generate|TOK:OGW|Elemental|1|
|
||||
|Generate|TOK:OGW|Elemental|2|
|
||||
|Generate}TOK:OGW|Eldrazi Scion|1|
|
||||
|Generate}TOK:OGW|Eldrazi Scion|2|
|
||||
|Generate}TOK:OGW|Eldrazi Scion|3|
|
||||
|Generate}TOK:OGW|Eldrazi Scion|4|
|
||||
|Generate}TOK:OGW|Eldrazi Scion|5|
|
||||
|Generate}TOK:OGW|Eldrazi Scion|6|
|
||||
|Generate|TOK:OGW|Plant||
|
||||
|Generate|TOK:OGW|Zombie||
|
||||
|
||||
#|Generate|TOK:DDQ|Angel||
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-common</artifactId>
|
||||
|
|
|
@ -55,10 +55,21 @@ import mage.view.UserView;
|
|||
*/
|
||||
public interface MageServer {
|
||||
|
||||
// registers a user to the user DB.
|
||||
boolean registerUser(String sessionId, String userName, String password, String email) throws MageException;
|
||||
|
||||
boolean emailAuthToken(String sessionId, String email) throws MageException;
|
||||
|
||||
boolean resetPassword(String sessionId, String email, String authToken, String password) throws MageException;
|
||||
|
||||
// connection methods
|
||||
// DEPRECATED - Use connectUser instead. This is only kept for older clients.
|
||||
// This can be deleted once users transitioned to newer clients (1.4.6v1 and later).
|
||||
boolean registerClient(String userName, String sessionId, MageVersion version) throws MageException;
|
||||
|
||||
boolean registerAdmin(String password, String sessionId, MageVersion version) throws MageException;
|
||||
boolean connectUser(String userName, String password, String sessionId, MageVersion version) throws MageException;
|
||||
|
||||
boolean connectAdmin(String password, String sessionId, MageVersion version) throws MageException;
|
||||
// Not used
|
||||
// void deregisterClient(String sessionId) throws MageException;
|
||||
|
||||
|
|
|
@ -45,6 +45,9 @@ public class Connection {
|
|||
private int port;
|
||||
private String username;
|
||||
private String password;
|
||||
private String email;
|
||||
private String authToken;
|
||||
private String adminPassword;
|
||||
private ProxyType proxyType;
|
||||
private String proxyHost;
|
||||
private int proxyPort;
|
||||
|
@ -172,6 +175,30 @@ public class Connection {
|
|||
this.password = password;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getAuthToken() {
|
||||
return authToken;
|
||||
}
|
||||
|
||||
public void setAuthToken(String authToken) {
|
||||
this.authToken = authToken;
|
||||
}
|
||||
|
||||
public String getAdminPassword() {
|
||||
return adminPassword;
|
||||
}
|
||||
|
||||
public void setAdminPassword(String adminPassword) {
|
||||
this.adminPassword = adminPassword;
|
||||
}
|
||||
|
||||
public String getProxyHost() {
|
||||
return proxyHost;
|
||||
}
|
||||
|
|
|
@ -122,195 +122,36 @@ public class SessionImpl implements Session {
|
|||
return sessionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean connect(Connection connection) {
|
||||
if (isConnected()) {
|
||||
disconnect(true);
|
||||
}
|
||||
this.connection = connection;
|
||||
this.canceled = false;
|
||||
return connect();
|
||||
// RemotingTask encapsulates a task which is involved with some JBoss Remoting. This is
|
||||
// intended to be used with handleRemotingTaskExceptions for sharing the common exception
|
||||
// handling.
|
||||
public interface RemotingTask {
|
||||
public boolean run() throws Throwable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stopConnecting() {
|
||||
canceled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean connect() {
|
||||
sessionState = SessionState.CONNECTING;
|
||||
// handleRemotingTaskExceptions runs the given task and handles exceptions appropriately. This
|
||||
// way we can share the common exception handling.
|
||||
private boolean handleRemotingTaskExceptions(RemotingTask remoting) {
|
||||
try {
|
||||
System.setProperty("http.nonProxyHosts", "code.google.com");
|
||||
System.setProperty("socksNonProxyHosts", "code.google.com");
|
||||
|
||||
// clear previous values
|
||||
System.clearProperty("socksProxyHost");
|
||||
System.clearProperty("socksProxyPort");
|
||||
System.clearProperty("http.proxyHost");
|
||||
System.clearProperty("http.proxyPort");
|
||||
|
||||
switch (connection.getProxyType()) {
|
||||
case SOCKS:
|
||||
System.setProperty("socksProxyHost", connection.getProxyHost());
|
||||
System.setProperty("socksProxyPort", Integer.toString(connection.getProxyPort()));
|
||||
break;
|
||||
case HTTP:
|
||||
System.setProperty("http.proxyHost", connection.getProxyHost());
|
||||
System.setProperty("http.proxyPort", Integer.toString(connection.getProxyPort()));
|
||||
Authenticator.setDefault(new MageAuthenticator(connection.getProxyUsername(), connection.getProxyPassword()));
|
||||
break;
|
||||
}
|
||||
InvokerLocator clientLocator = new InvokerLocator(connection.getURI());
|
||||
|
||||
Map<String, String> metadata = new HashMap<>();
|
||||
/*
|
||||
5.8.3.1.1. Write timeouts
|
||||
The socket timeout facility offered by the JDK applies only to read operations on the socket. As of release 2.5.2,
|
||||
the socket and bisocket (and also sslsocket and sslbisocket) transports offer a write timeout facility. When a client
|
||||
or server is configured, in any of the usual ways, with the parameter org.jboss.remoting.transport.socket.SocketWrapper.WRITE_TIMEOUT
|
||||
(actual value "writeTimeout") set to a positive value (in milliseconds), all write operations will time out if they do
|
||||
not complete within the configured period. When a write operation times out, the socket upon which the write was invoked
|
||||
will be closed, which is likely to result in a java.net.SocketException.
|
||||
Note. A SocketException is considered to be a "retriable" exception, so, if the parameter "numberOfCallRetries" is set
|
||||
to a value greater than 1, an invocation interrupted by a write timeout can be retried.
|
||||
Note. The write timeout facility applies to writing of both invocations and responses. It applies to push callbacks as well.
|
||||
*/
|
||||
metadata.put(SocketWrapper.WRITE_TIMEOUT, "2000");
|
||||
metadata.put("generalizeSocketException", "true");
|
||||
server = (MageServer) TransporterClient.createTransporterClient(clientLocator.getLocatorURI(), MageServer.class, metadata);
|
||||
|
||||
// http://docs.jboss.org/jbossremoting/docs/guide/2.5/html_single/#d0e1057
|
||||
Map<String, String> clientMetadata = new HashMap<>();
|
||||
|
||||
clientMetadata.put(SocketWrapper.WRITE_TIMEOUT, "2000");
|
||||
/* generalizeSocketException
|
||||
* If set to false, a failed invocation will be retried in the case of
|
||||
* SocketExceptions. If set to true, a failed invocation will be retried in the case of
|
||||
* <classname>SocketException</classname>s and also any <classname>IOException</classname>
|
||||
* whose message matches the regular expression
|
||||
* <code>^.*(?:connection.*reset|connection.*closed|broken.*pipe).*$</code>.
|
||||
* See also the "numberOfCallRetries" parameter, above. The default value is false.*/
|
||||
clientMetadata.put("generalizeSocketException", "true");
|
||||
|
||||
/* A remoting server also has the capability to detect when a client is no longer available.
|
||||
* This is done by estabilishing a lease with the remoting clients that connect to a server.
|
||||
* On the client side, an org.jboss.remoting.LeasePinger periodically sends PING messages to
|
||||
* the server, and on the server side an org.jboss.remoting.Lease informs registered listeners
|
||||
* if the PING doesn't arrive withing the specified timeout period. */
|
||||
clientMetadata.put(Client.ENABLE_LEASE, "true");
|
||||
/*
|
||||
When the socket client invoker makes its first invocation, it will check to see if there is an available
|
||||
socket connection in its pool. Since is the first invocation, there will not be and will create a new socket
|
||||
connection and use it for making the invocation. Then when finished making invocation, will return the still
|
||||
active socket connection to the pool. As more client invocations are made, is possible for the number of
|
||||
socket connections to reach the maximum allowed (which is controlled by 'clientMaxPoolSize' property). At this
|
||||
point, when the next client invocation is made, it will wait up to some configured number of milliseconds, at
|
||||
which point it will throw an org.jboss.remoting.CannotConnectException. The number of milliseconds is given by
|
||||
the parameter MicroSocketClientInvoker.CONNECTION_WAIT (actual value "connectionWait"), with a default of
|
||||
30000 milliseconds. Note that if more than one call retry is configured (see next paragraph),
|
||||
the CannotConnectException will be swallowed.
|
||||
Once the socket client invoker get an available socket connection from the pool, are not out of the woods yet.
|
||||
For example, a network problem could cause a java.net.SocketException. There is also a possibility that the socket
|
||||
connection, while still appearing to be valid, has "gone stale" while sitting in the pool. For example, a ServerThread
|
||||
on the other side of the connection could time out and close its socket. If the attempt to complete an invocation
|
||||
fails, then MicroSocketClientInvoker will make a number of attempts, according to the parameter "numberOfCallRetries",
|
||||
with a default value of 3. Once the configured number of retries has been exhausted,
|
||||
an org.jboss.remoting.InvocationFailureException will be thrown.
|
||||
*/
|
||||
clientMetadata.put("numberOfCallRetries", "1");
|
||||
|
||||
/**
|
||||
* I'll explain the meaning of "secondaryBindPort" and
|
||||
* "secondaryConnectPort", and maybe that will help. The Remoting
|
||||
* bisocket transport creates two ServerSockets on the server. The
|
||||
* "primary" ServerSocket is used to create connections used for
|
||||
* ordinary invocations, e.g., a request to create a JMS consumer,
|
||||
* and the "secondary" ServerSocket is used to create "control"
|
||||
* connections for internal Remoting messages. The port for the
|
||||
* primary ServerSocket is configured by the "serverBindPort"
|
||||
* parameter, and the port for the secondary ServerSocket is, by
|
||||
* default, chosen randomly. The "secondaryBindPort" parameter can
|
||||
* be used to assign a specific port to the secondary ServerSocket.
|
||||
* Now, if there is a translating firewall between the client and
|
||||
* server, the client should be given the value of the port that is
|
||||
* translated to the actual binding port of the secondary
|
||||
* ServerSocket. For example, your configuration will tell the
|
||||
* secondary ServerSocket to bind to port 14000, and it will tell
|
||||
* the client to connect to port 14001. It assumes that there is a
|
||||
* firewall which will translate 14001 to 14000. Apparently, that's
|
||||
* not happening.
|
||||
*/
|
||||
// secondaryBindPort - the port to which the secondary server socket is to be bound. By default, an arbitrary port is selected.
|
||||
// secondaryConnectPort - the port clients are to use to connect to the secondary server socket.
|
||||
// By default, the value of secondaryBindPort is used. secondaryConnectPort is useful if the server is behind a translating firewall.
|
||||
// Indicated the max number of threads used within oneway thread pool.
|
||||
clientMetadata.put(Client.MAX_NUM_ONEWAY_THREADS, "10");
|
||||
clientMetadata.put(Remoting.USE_CLIENT_CONNECTION_IDENTITY, "true");
|
||||
callbackClient = new Client(clientLocator, "callback", clientMetadata);
|
||||
|
||||
Map<String, String> listenerMetadata = new HashMap<>();
|
||||
if (debugMode) {
|
||||
// prevent client from disconnecting while debugging
|
||||
listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_PERIOD, "1000000");
|
||||
listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_TIMEOUT, "900000");
|
||||
} else {
|
||||
listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_PERIOD, "15000");
|
||||
listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_TIMEOUT, "13000");
|
||||
}
|
||||
callbackClient.connect(new ClientConnectionListener(), listenerMetadata);
|
||||
|
||||
Map<String, String> callbackMetadata = new HashMap<>();
|
||||
callbackMetadata.put(Bisocket.IS_CALLBACK_SERVER, "true");
|
||||
if (callbackHandler == null) {
|
||||
callbackHandler = new CallbackHandler();
|
||||
}
|
||||
callbackClient.addListener(callbackHandler, callbackMetadata);
|
||||
|
||||
Set callbackConnectors = callbackClient.getCallbackConnectors(callbackHandler);
|
||||
if (callbackConnectors.size() != 1) {
|
||||
logger.warn("There should be one callback Connector (number existing = " + callbackConnectors.size() + ")");
|
||||
}
|
||||
|
||||
logger.info("Trying to connect as " + (this.getUserName() == null ? "" : this.getUserName()) + " to XMAGE server at " + connection.getHost() + ":" + connection.getPort());
|
||||
callbackClient.invoke(null);
|
||||
|
||||
this.sessionId = callbackClient.getSessionId();
|
||||
boolean registerResult;
|
||||
if (connection.getPassword() == null) {
|
||||
// for backward compatibility. don't remove twice call - first one does nothing but for version checking
|
||||
registerResult = server.registerClient(connection.getUsername(), sessionId, client.getVersion());
|
||||
if (registerResult) {
|
||||
server.setUserData(connection.getUsername(), sessionId, connection.getUserData());
|
||||
}
|
||||
} else {
|
||||
registerResult = server.registerAdmin(connection.getPassword(), sessionId, client.getVersion());
|
||||
}
|
||||
if (registerResult) {
|
||||
sessionState = SessionState.CONNECTED;
|
||||
serverState = server.getServerState();
|
||||
if (!connection.getUsername().equals("Admin")) {
|
||||
updateDatabase(connection.isForceDBComparison(), serverState);
|
||||
}
|
||||
logger.info("Connected as " + (this.getUserName() == null ? "" : this.getUserName()) + " to MAGE server at " + connection.getHost() + ":" + connection.getPort());
|
||||
client.connected(this.getUserName() == null ? "" : this.getUserName() + "@" + connection.getHost() + ":" + connection.getPort() + " ");
|
||||
return true;
|
||||
}
|
||||
disconnect(false);
|
||||
// client.showMessage("Unable to connect to server.");
|
||||
return remoting.run();
|
||||
} catch (MalformedURLException ex) {
|
||||
logger.fatal("", ex);
|
||||
client.showMessage("Unable to connect to server. " + ex.getMessage());
|
||||
} catch (UndeclaredThrowableException ex) {
|
||||
String addMessage = "";
|
||||
if (ex.getCause() instanceof InvocationFailureException) {
|
||||
InvocationFailureException exep = (InvocationFailureException) ex.getCause();
|
||||
Throwable cause = ex.getCause();
|
||||
if (cause instanceof InvocationFailureException) {
|
||||
InvocationFailureException exep = (InvocationFailureException) cause;
|
||||
if (exep.getCause() instanceof IOException) {
|
||||
if (exep.getCause().getMessage().startsWith("Field hash null is not available on current")) {
|
||||
addMessage = "Probabaly the server version is not compatible to the client. ";
|
||||
}
|
||||
}
|
||||
} else if (cause instanceof NoSuchMethodException) {
|
||||
// NoSuchMethodException is thrown on an invocation of an unknow JBoss remoting
|
||||
// method, so it's likely to be because of a version incompatibility.
|
||||
addMessage = "The following method is not available in the server, probably the " +
|
||||
"server version is not compatible to the client: " + cause.getMessage();
|
||||
}
|
||||
if (addMessage.isEmpty()) {
|
||||
logger.fatal("", ex);
|
||||
|
@ -347,6 +188,247 @@ public class SessionImpl implements Session {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean register(final Connection connection) {
|
||||
return establishJBossRemotingConnection(connection) && handleRemotingTaskExceptions(new RemotingTask() {
|
||||
@Override
|
||||
public boolean run() throws Throwable {
|
||||
logger.info("Trying to register as " + getUserName() + " to XMAGE server at " + connection.getHost() + ":" + connection.getPort());
|
||||
boolean registerResult = server.registerUser(sessionId, connection.getUsername(),
|
||||
connection.getPassword(), connection.getEmail());
|
||||
if (registerResult) {
|
||||
logger.info("Registered as " + getUserName() + " to MAGE server at " + connection.getHost() + ":" + connection.getPort());
|
||||
}
|
||||
return registerResult;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean emailAuthToken(final Connection connection) {
|
||||
return establishJBossRemotingConnection(connection) && handleRemotingTaskExceptions(new RemotingTask() {
|
||||
@Override
|
||||
public boolean run() throws Throwable {
|
||||
logger.info("Trying to ask for an auth token to " + getEmail() + " to XMAGE server at " + connection.getHost() + ":" + connection.getPort());
|
||||
boolean result = server.emailAuthToken(sessionId, connection.getEmail());
|
||||
if (result) {
|
||||
logger.info("An auth token is emailed to " + getEmail() + " from MAGE server at " + connection.getHost() + ":" + connection.getPort());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean resetPassword(final Connection connection) {
|
||||
return establishJBossRemotingConnection(connection) && handleRemotingTaskExceptions(new RemotingTask() {
|
||||
@Override
|
||||
public boolean run() throws Throwable {
|
||||
logger.info("Trying reset the password in XMAGE server at " + connection.getHost() + ":" + connection.getPort());
|
||||
boolean result = server.resetPassword(sessionId, connection.getEmail(), connection.getAuthToken(), connection.getPassword());
|
||||
if (result) {
|
||||
logger.info("Password is successfully reset in MAGE server at " + connection.getHost() + ":" + connection.getPort());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean connect(final Connection connection) {
|
||||
return establishJBossRemotingConnection(connection) && handleRemotingTaskExceptions(new RemotingTask() {
|
||||
@Override
|
||||
public boolean run() throws Throwable {
|
||||
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());
|
||||
if (registerResult) {
|
||||
server.setUserData(connection.getUsername(), sessionId, connection.getUserData());
|
||||
}
|
||||
} else {
|
||||
registerResult = server.connectAdmin(connection.getAdminPassword(), sessionId, client.getVersion());
|
||||
}
|
||||
if (registerResult) {
|
||||
serverState = server.getServerState();
|
||||
if (!connection.getUsername().equals("Admin")) {
|
||||
updateDatabase(connection.isForceDBComparison(), serverState);
|
||||
}
|
||||
logger.info("Logged-in as " + getUserName() + " to MAGE server at " + connection.getHost() + ":" + connection.getPort());
|
||||
client.connected(getUserName() + "@" + connection.getHost() + ":" + connection.getPort() + " ");
|
||||
return true;
|
||||
}
|
||||
disconnect(false);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stopConnecting() {
|
||||
canceled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean establishJBossRemotingConnection(final Connection connection) {
|
||||
if (isConnected()) {
|
||||
disconnect(true);
|
||||
}
|
||||
this.connection = connection;
|
||||
this.canceled = false;
|
||||
sessionState = SessionState.CONNECTING;
|
||||
boolean result = handleRemotingTaskExceptions(new RemotingTask() {
|
||||
@Override
|
||||
public boolean run() throws Throwable {
|
||||
logger.info("Trying to connect to XMAGE server at " + connection.getHost() + ":" + connection.getPort());
|
||||
|
||||
System.setProperty("http.nonProxyHosts", "code.google.com");
|
||||
System.setProperty("socksNonProxyHosts", "code.google.com");
|
||||
|
||||
// clear previous values
|
||||
System.clearProperty("socksProxyHost");
|
||||
System.clearProperty("socksProxyPort");
|
||||
System.clearProperty("http.proxyHost");
|
||||
System.clearProperty("http.proxyPort");
|
||||
|
||||
switch (connection.getProxyType()) {
|
||||
case SOCKS:
|
||||
System.setProperty("socksProxyHost", connection.getProxyHost());
|
||||
System.setProperty("socksProxyPort", Integer.toString(connection.getProxyPort()));
|
||||
break;
|
||||
case HTTP:
|
||||
System.setProperty("http.proxyHost", connection.getProxyHost());
|
||||
System.setProperty("http.proxyPort", Integer.toString(connection.getProxyPort()));
|
||||
Authenticator.setDefault(new MageAuthenticator(connection.getProxyUsername(), connection.getProxyPassword()));
|
||||
break;
|
||||
}
|
||||
InvokerLocator clientLocator = new InvokerLocator(connection.getURI());
|
||||
|
||||
Map<String, String> metadata = new HashMap<>();
|
||||
/*
|
||||
5.8.3.1.1. Write timeouts
|
||||
The socket timeout facility offered by the JDK applies only to read operations on the socket. As of release 2.5.2,
|
||||
the socket and bisocket (and also sslsocket and sslbisocket) transports offer a write timeout facility. When a client
|
||||
or server is configured, in any of the usual ways, with the parameter org.jboss.remoting.transport.socket.SocketWrapper.WRITE_TIMEOUT
|
||||
(actual value "writeTimeout") set to a positive value (in milliseconds), all write operations will time out if they do
|
||||
not complete within the configured period. When a write operation times out, the socket upon which the write was invoked
|
||||
will be closed, which is likely to result in a java.net.SocketException.
|
||||
Note. A SocketException is considered to be a "retriable" exception, so, if the parameter "numberOfCallRetries" is set
|
||||
to a value greater than 1, an invocation interrupted by a write timeout can be retried.
|
||||
Note. The write timeout facility applies to writing of both invocations and responses. It applies to push callbacks as well.
|
||||
*/
|
||||
metadata.put(SocketWrapper.WRITE_TIMEOUT, "2000");
|
||||
metadata.put("generalizeSocketException", "true");
|
||||
server = (MageServer) TransporterClient.createTransporterClient(clientLocator.getLocatorURI(), MageServer.class, metadata);
|
||||
|
||||
// http://docs.jboss.org/jbossremoting/docs/guide/2.5/html_single/#d0e1057
|
||||
Map<String, String> clientMetadata = new HashMap<>();
|
||||
|
||||
clientMetadata.put(SocketWrapper.WRITE_TIMEOUT, "2000");
|
||||
/* generalizeSocketException
|
||||
* If set to false, a failed invocation will be retried in the case of
|
||||
* SocketExceptions. If set to true, a failed invocation will be retried in the case of
|
||||
* <classname>SocketException</classname>s and also any <classname>IOException</classname>
|
||||
* whose message matches the regular expression
|
||||
* <code>^.*(?:connection.*reset|connection.*closed|broken.*pipe).*$</code>.
|
||||
* See also the "numberOfCallRetries" parameter, above. The default value is false.*/
|
||||
clientMetadata.put("generalizeSocketException", "true");
|
||||
|
||||
/* A remoting server also has the capability to detect when a client is no longer available.
|
||||
* This is done by estabilishing a lease with the remoting clients that connect to a server.
|
||||
* On the client side, an org.jboss.remoting.LeasePinger periodically sends PING messages to
|
||||
* the server, and on the server side an org.jboss.remoting.Lease informs registered listeners
|
||||
* if the PING doesn't arrive withing the specified timeout period. */
|
||||
clientMetadata.put(Client.ENABLE_LEASE, "true");
|
||||
/*
|
||||
When the socket client invoker makes its first invocation, it will check to see if there is an available
|
||||
socket connection in its pool. Since is the first invocation, there will not be and will create a new socket
|
||||
connection and use it for making the invocation. Then when finished making invocation, will return the still
|
||||
active socket connection to the pool. As more client invocations are made, is possible for the number of
|
||||
socket connections to reach the maximum allowed (which is controlled by 'clientMaxPoolSize' property). At this
|
||||
point, when the next client invocation is made, it will wait up to some configured number of milliseconds, at
|
||||
which point it will throw an org.jboss.remoting.CannotConnectException. The number of milliseconds is given by
|
||||
the parameter MicroSocketClientInvoker.CONNECTION_WAIT (actual value "connectionWait"), with a default of
|
||||
30000 milliseconds. Note that if more than one call retry is configured (see next paragraph),
|
||||
the CannotConnectException will be swallowed.
|
||||
Once the socket client invoker get an available socket connection from the pool, are not out of the woods yet.
|
||||
For example, a network problem could cause a java.net.SocketException. There is also a possibility that the socket
|
||||
connection, while still appearing to be valid, has "gone stale" while sitting in the pool. For example, a ServerThread
|
||||
on the other side of the connection could time out and close its socket. If the attempt to complete an invocation
|
||||
fails, then MicroSocketClientInvoker will make a number of attempts, according to the parameter "numberOfCallRetries",
|
||||
with a default value of 3. Once the configured number of retries has been exhausted,
|
||||
an org.jboss.remoting.InvocationFailureException will be thrown.
|
||||
*/
|
||||
clientMetadata.put("numberOfCallRetries", "1");
|
||||
|
||||
/**
|
||||
* I'll explain the meaning of "secondaryBindPort" and
|
||||
* "secondaryConnectPort", and maybe that will help. The Remoting
|
||||
* bisocket transport creates two ServerSockets on the server. The
|
||||
* "primary" ServerSocket is used to create connections used for
|
||||
* ordinary invocations, e.g., a request to create a JMS consumer,
|
||||
* and the "secondary" ServerSocket is used to create "control"
|
||||
* connections for internal Remoting messages. The port for the
|
||||
* primary ServerSocket is configured by the "serverBindPort"
|
||||
* parameter, and the port for the secondary ServerSocket is, by
|
||||
* default, chosen randomly. The "secondaryBindPort" parameter can
|
||||
* be used to assign a specific port to the secondary ServerSocket.
|
||||
* Now, if there is a translating firewall between the client and
|
||||
* server, the client should be given the value of the port that is
|
||||
* translated to the actual binding port of the secondary
|
||||
* ServerSocket. For example, your configuration will tell the
|
||||
* secondary ServerSocket to bind to port 14000, and it will tell
|
||||
* the client to connect to port 14001. It assumes that there is a
|
||||
* firewall which will translate 14001 to 14000. Apparently, that's
|
||||
* not happening.
|
||||
*/
|
||||
// secondaryBindPort - the port to which the secondary server socket is to be bound. By default, an arbitrary port is selected.
|
||||
// secondaryConnectPort - the port clients are to use to connect to the secondary server socket.
|
||||
// By default, the value of secondaryBindPort is used. secondaryConnectPort is useful if the server is behind a translating firewall.
|
||||
// Indicated the max number of threads used within oneway thread pool.
|
||||
clientMetadata.put(Client.MAX_NUM_ONEWAY_THREADS, "10");
|
||||
clientMetadata.put(Remoting.USE_CLIENT_CONNECTION_IDENTITY, "true");
|
||||
callbackClient = new Client(clientLocator, "callback", clientMetadata);
|
||||
|
||||
Map<String, String> listenerMetadata = new HashMap<>();
|
||||
if (debugMode) {
|
||||
// prevent client from disconnecting while debugging
|
||||
listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_PERIOD, "1000000");
|
||||
listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_TIMEOUT, "900000");
|
||||
} else {
|
||||
listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_PERIOD, "15000");
|
||||
listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_TIMEOUT, "13000");
|
||||
}
|
||||
callbackClient.connect(new ClientConnectionListener(), listenerMetadata);
|
||||
|
||||
Map<String, String> callbackMetadata = new HashMap<>();
|
||||
callbackMetadata.put(Bisocket.IS_CALLBACK_SERVER, "true");
|
||||
if (callbackHandler == null) {
|
||||
callbackHandler = new CallbackHandler();
|
||||
}
|
||||
callbackClient.addListener(callbackHandler, callbackMetadata);
|
||||
|
||||
Set callbackConnectors = callbackClient.getCallbackConnectors(callbackHandler);
|
||||
if (callbackConnectors.size() != 1) {
|
||||
logger.warn("There should be one callback Connector (number existing = " + callbackConnectors.size() + ")");
|
||||
}
|
||||
|
||||
callbackClient.invoke(null);
|
||||
|
||||
sessionId = callbackClient.getSessionId();
|
||||
sessionState = SessionState.CONNECTED;
|
||||
logger.info("Connected to MAGE server at " + connection.getHost() + ":" + connection.getPort());
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (result) {
|
||||
return true;
|
||||
}
|
||||
disconnect(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
private void updateDatabase(boolean forceDBComparison, ServerState serverState) {
|
||||
long cardDBVersion = CardRepository.instance.getContentVersionFromDB();
|
||||
if (forceDBComparison || serverState.getCardsContentVersion() > cardDBVersion) {
|
||||
|
@ -1389,9 +1471,20 @@ public class SessionImpl implements Session {
|
|||
|
||||
@Override
|
||||
public String getUserName() {
|
||||
return connection.getUsername();
|
||||
String username = connection.getUsername();
|
||||
return username == null ? "" : username;
|
||||
}
|
||||
|
||||
private String getEmail() {
|
||||
String email = connection.getEmail();
|
||||
return email == null ? "" : email;
|
||||
}
|
||||
|
||||
private String getAuthToken() {
|
||||
String authToken = connection.getAuthToken();
|
||||
return authToken == null ? "" : authToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updatePreferencesForServer(UserData userData) {
|
||||
try {
|
||||
|
|
|
@ -34,12 +34,16 @@ import mage.remote.Connection;
|
|||
*/
|
||||
public interface Connect {
|
||||
|
||||
boolean register(Connection connection);
|
||||
|
||||
boolean emailAuthToken(Connection connection);
|
||||
|
||||
boolean resetPassword(Connection connection);
|
||||
|
||||
boolean connect(Connection connection);
|
||||
|
||||
boolean stopConnecting();
|
||||
|
||||
boolean connect();
|
||||
|
||||
void disconnect(boolean showMessage);
|
||||
|
||||
void reconnect(Throwable throwable);
|
||||
|
|
|
@ -40,7 +40,7 @@ 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 = 6;
|
||||
public final static int MAGE_VERSION_PATCH = 8;
|
||||
public final static String MAGE_VERSION_MINOR_PATCH = "v0";
|
||||
public final static String MAGE_VERSION_INFO = "";
|
||||
|
||||
|
|
|
@ -1,43 +1,42 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.view;
|
||||
|
||||
import java.io.Serializable;
|
||||
import mage.ConditionalMana;
|
||||
import mage.players.ManaPool;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class ManaPoolView implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private int red;
|
||||
|
|
|
@ -44,6 +44,7 @@ public class SeatView implements Serializable {
|
|||
private UUID playerId;
|
||||
private final String playerName;
|
||||
private final String playerType;
|
||||
private final String history;
|
||||
|
||||
public SeatView(Seat seat) {
|
||||
if (seat.getPlayer() != null) {
|
||||
|
@ -51,13 +52,16 @@ public class SeatView implements Serializable {
|
|||
this.playerName = seat.getPlayer().getName();
|
||||
if (seat.getPlayer().getUserData() == null) {
|
||||
this.flagName = UserData.getDefaultFlagName();
|
||||
this.history = "";
|
||||
} else {
|
||||
this.flagName = seat.getPlayer().getUserData().getFlagName();
|
||||
this.history = seat.getPlayer().getUserData().getHistory();
|
||||
}
|
||||
} else {
|
||||
// Empty seat
|
||||
this.playerName = "";
|
||||
this.flagName = "";
|
||||
this.history = "";
|
||||
}
|
||||
this.playerType = seat.getPlayerType();
|
||||
}
|
||||
|
@ -78,4 +82,8 @@ public class SeatView implements Serializable {
|
|||
return flagName;
|
||||
}
|
||||
|
||||
public String getHistory() {
|
||||
return history;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
*/
|
||||
package mage.view;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
@ -39,14 +39,14 @@ public class UsersView implements Serializable {
|
|||
|
||||
private final String flagName;
|
||||
private final String userName;
|
||||
private final String infoState;
|
||||
private final String history;
|
||||
private final String infoGames;
|
||||
private final String infoPing;
|
||||
|
||||
public UsersView(String flagName, String userName, String infoState, String infoGames, String infoPing) {
|
||||
public UsersView(String flagName, String userName, String history, String infoGames, String infoPing) {
|
||||
this.flagName = flagName;
|
||||
this.history = history;
|
||||
this.userName = userName;
|
||||
this.infoState = infoState;
|
||||
this.infoGames = infoGames;
|
||||
this.infoPing = infoPing;
|
||||
}
|
||||
|
@ -59,8 +59,8 @@ public class UsersView implements Serializable {
|
|||
return userName;
|
||||
}
|
||||
|
||||
public String getInfoState() {
|
||||
return infoState;
|
||||
public String getHistory() {
|
||||
return history;
|
||||
}
|
||||
|
||||
public String getInfoGames() {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-plugins</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-counter-plugin</artifactId>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-plugins</artifactId>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<groupId>org.mage</groupId>
|
||||
|
|
|
@ -413,7 +413,7 @@ public class ConnectDialog extends JDialog {
|
|||
connection = new Connection();
|
||||
connection.setHost(this.txtServer.getText());
|
||||
connection.setPort(Integer.valueOf(this.txtPort.getText()));
|
||||
connection.setPassword(new String(txtPassword.getPassword()));
|
||||
connection.setAdminPassword(new String(txtPassword.getPassword()));
|
||||
connection.setUsername("Admin");
|
||||
connection.setProxyType((ProxyType) this.cbProxyType.getSelectedItem());
|
||||
if (!this.cbProxyType.getSelectedItem().equals(ProxyType.NONE)) {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-deck-constructed</artifactId>
|
||||
|
|
|
@ -46,8 +46,8 @@ import mage.util.CardUtil;
|
|||
*/
|
||||
public class Commander extends DeckValidator {
|
||||
|
||||
protected List<String> banned = new ArrayList<>();
|
||||
protected List<String> bannedCommander = new ArrayList<>();
|
||||
protected List<String> banned = new ArrayList<>();
|
||||
protected List<String> bannedCommander = new ArrayList<>();
|
||||
|
||||
public Commander() {
|
||||
this("Commander");
|
||||
|
@ -74,6 +74,7 @@ public class Commander extends DeckValidator {
|
|||
banned.add("Painter's Servant");
|
||||
banned.add("Panoptic Mirror");
|
||||
banned.add("Primeval Titan");
|
||||
banned.add("Prophet of Kruphix");
|
||||
banned.add("Protean Hulk");
|
||||
banned.add("Recurring Nightmare");
|
||||
banned.add("Rofellos, Llanowar Emissary");
|
||||
|
@ -103,7 +104,7 @@ public class Commander extends DeckValidator {
|
|||
valid = false;
|
||||
}
|
||||
|
||||
List<String> basicLandNames = new ArrayList<>(Arrays.asList("Forest", "Island", "Mountain", "Swamp", "Plains",
|
||||
List<String> basicLandNames = new ArrayList<>(Arrays.asList("Forest", "Island", "Mountain", "Swamp", "Plains", "Wastes",
|
||||
"Snow-Covered Forest", "Snow-Covered Island", "Snow-Covered Mountain", "Snow-Covered Swamp", "Snow-Covered Plains"));
|
||||
Map<String, Integer> counts = new HashMap<>();
|
||||
countCards(counts, deck.getCards());
|
||||
|
@ -130,22 +131,22 @@ public class Commander extends DeckValidator {
|
|||
invalid.put("Commander", "Commander invalid ");
|
||||
return false;
|
||||
}
|
||||
if ((commander.getCardType().contains(CardType.CREATURE) && commander.getSupertype().contains("Legendary")) ||
|
||||
(commander.getCardType().contains(CardType.PLANESWALKER) && commander.getAbilities().contains(CanBeYourCommanderAbility.getInstance()))) {
|
||||
if ((commander.getCardType().contains(CardType.CREATURE) && commander.getSupertype().contains("Legendary"))
|
||||
|| (commander.getCardType().contains(CardType.PLANESWALKER) && commander.getAbilities().contains(CanBeYourCommanderAbility.getInstance()))) {
|
||||
if (!bannedCommander.contains(commander.getName())) {
|
||||
FilterMana color = CardUtil.getColorIdentity(commander);
|
||||
for (Card card : deck.getCards()) {
|
||||
if (!cardHasValidColor(color, card)) {
|
||||
invalid.put(card.getName(), "Invalid color (" + commander.getName() +")");
|
||||
invalid.put(card.getName(), "Invalid color (" + commander.getName() + ")");
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
invalid.put("Commander", "Commander banned (" + commander.getName() +")");
|
||||
invalid.put("Commander", "Commander banned (" + commander.getName() + ")");
|
||||
valid = false;
|
||||
}
|
||||
} else {
|
||||
invalid.put("Commander", "Commander invalid (" + commander.getName() +")");
|
||||
invalid.put("Commander", "Commander invalid (" + commander.getName() + ")");
|
||||
valid = false;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -40,7 +40,6 @@ public class DuelCommander extends Commander {
|
|||
banned.add("Balance");
|
||||
banned.add("Back to Basics");
|
||||
banned.add("Black Lotus");
|
||||
banned.add("Cataclysm");
|
||||
banned.add("Channel");
|
||||
banned.add("Entomb");
|
||||
banned.add("Fastbond");
|
||||
|
|
|
@ -27,21 +27,18 @@
|
|||
*/
|
||||
package mage.deck;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import mage.cards.ExpansionSet;
|
||||
import mage.cards.Sets;
|
||||
import mage.cards.decks.Constructed;
|
||||
import mage.constants.SetType;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
|
||||
public class Modern extends Constructed {
|
||||
public Modern() {
|
||||
super("Constructed - Modern");
|
||||
|
@ -56,14 +53,14 @@ public class Modern extends Constructed {
|
|||
|
||||
banned.add("Ancestral Vision");
|
||||
banned.add("Ancient Den");
|
||||
banned.add("Birthing Pod"); // banned effective January 23, 2015
|
||||
banned.add("Birthing Pod");
|
||||
banned.add("Blazing Shoal");
|
||||
banned.add("Bloodbraid Elf"); // (banned effective February 1, 2013)
|
||||
banned.add("Bloodbraid Elf");
|
||||
banned.add("Chrome Mox");
|
||||
banned.add("Cloudpost");
|
||||
banned.add("Dark Depths");
|
||||
banned.add("Deathrite Shaman"); // (banned effective February 7, 2014
|
||||
banned.add("Dig Through Time"); // banned effective January 23, 2015
|
||||
banned.add("Deathrite Shaman");
|
||||
banned.add("Dig Through Time");
|
||||
banned.add("Dread Return");
|
||||
banned.add("Glimpse of Nature");
|
||||
banned.add("Great Furnace");
|
||||
|
@ -76,16 +73,17 @@ public class Modern extends Constructed {
|
|||
banned.add("Punishing Fire");
|
||||
banned.add("Rite of Flame");
|
||||
banned.add("Seat of the Synod");
|
||||
banned.add("Second Sunrise"); // (banned effective May 3, 2013)
|
||||
banned.add("Seething Song"); // (banned effective February 1, 2013)
|
||||
banned.add("Second Sunrise");
|
||||
banned.add("Seething Song");
|
||||
banned.add("Sensei's Divining Top");
|
||||
banned.add("Stoneforge Mystic");
|
||||
banned.add("Skullclamp");
|
||||
banned.add("Splinter Twin");
|
||||
banned.add("Summer Bloom");
|
||||
banned.add("Sword of the Meek");
|
||||
banned.add("Treasure Cruise"); // banned effective January 23, 2015
|
||||
banned.add("Treasure Cruise");
|
||||
banned.add("Tree of Tales");
|
||||
banned.add("Umezawa's Jitte");
|
||||
banned.add("Vault of Whispers");
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,12 +27,13 @@
|
|||
*/
|
||||
package mage.deck;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.cards.decks.DeckValidator;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author nigelzor
|
||||
|
|
|
@ -23,6 +23,7 @@ public class Pauper extends Constructed {
|
|||
rarities.add(Rarity.COMMON);
|
||||
rarities.add(Rarity.LAND);
|
||||
|
||||
banned.add("Cloud of Faeries");
|
||||
banned.add("Cloudpost");
|
||||
banned.add("Cranial Plating");
|
||||
banned.add("Empty the Warrens");
|
||||
|
|
|
@ -120,7 +120,7 @@ public class TinyLeaders extends DeckValidator {
|
|||
valid = false;
|
||||
}
|
||||
|
||||
List<String> basicLandNames = new ArrayList<>(Arrays.asList("Forest", "Island", "Mountain", "Swamp", "Plains",
|
||||
List<String> basicLandNames = new ArrayList<>(Arrays.asList("Forest", "Island", "Mountain", "Swamp", "Plains", "Wastes",
|
||||
"Snow-Covered Forest", "Snow-Covered Island", "Snow-Covered Mountain", "Snow-Covered Swamp", "Snow-Covered Plains"));
|
||||
Map<String, Integer> counts = new HashMap<>();
|
||||
counts.put(deck.getName(), 1); // add the commander to the counts, so it can't be in the deck or sideboard again
|
||||
|
@ -145,19 +145,20 @@ public class TinyLeaders extends DeckValidator {
|
|||
if (deck.getSideboard().size() <= 10) {
|
||||
Card commander = GameTinyLeadersImpl.getCommanderCard(deck.getName(), null);
|
||||
/**
|
||||
* 905.5b - Each card must have a converted mana cost of three of less.
|
||||
* Cards with {X} in their mana cost count X as zero.
|
||||
* Split and double-face cards are legal only if both of their halves would be legal independently.
|
||||
* 905.5b - Each card must have a converted mana cost of three of
|
||||
* less. Cards with {X} in their mana cost count X as zero. Split
|
||||
* and double-face cards are legal only if both of their halves
|
||||
* would be legal independently.
|
||||
*/
|
||||
|
||||
if (commander == null || commander.getManaCost().convertedManaCost() > 3) {
|
||||
|
||||
if (commander == null || commander.getManaCost().convertedManaCost() > 3) {
|
||||
if (commander == null) {
|
||||
if (deck.getName() == null) {
|
||||
invalid.put("Leader", "You have to save your deck with the leader card name entered to the DECK NAME field of the DECK EDITOR (top left) so that XMage knows your leader." +
|
||||
"(You can use the \"Sultai\" for a UBG (2/2) default Commander.)");
|
||||
invalid.put("Leader", "You have to save your deck with the leader card name entered to the DECK NAME field of the DECK EDITOR (top left) so that XMage knows your leader."
|
||||
+ "(You can use the \"Sultai\" for a UBG (3/3) default Commander or \"Glass\" for a colorless 3/3 default Commander.)");
|
||||
} else {
|
||||
invalid.put("Leader", "Leader [" + deck.getName() + "] not found. You have to enter the name of the leader card into the DECK NAME field of the DECK EDITOR (top left). Check your spelling " +
|
||||
"(use the \"Sultai\" for a UBG (2/2) default Commander)");
|
||||
invalid.put("Leader", "Leader [" + deck.getName() + "] not found. You have to enter the name of the leader card into the DECK NAME field of the DECK EDITOR (top left). Check your spelling "
|
||||
+ "(use the \"Sultai\" for a UBG (3/3) default Commander or \"Glass\" for a colorless (3/3) default Commander)");
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -172,12 +173,12 @@ public class TinyLeaders extends DeckValidator {
|
|||
FilterMana color = CardUtil.getColorIdentity(commander);
|
||||
for (Card card : deck.getCards()) {
|
||||
if (!isCardFormatValid(card, commander, color)) {
|
||||
valid = false;
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
for (Card card : deck.getSideboard()) {
|
||||
if (!isCardFormatValid(card, commander, color)) {
|
||||
valid = false;
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -204,14 +205,14 @@ public class TinyLeaders extends DeckValidator {
|
|||
|
||||
//905.5b - Converted mana cost must be 3 or less
|
||||
if (card instanceof SplitCard) {
|
||||
if (((SplitCard) card).getLeftHalfCard().getManaCost().convertedManaCost() > 3) {
|
||||
if (((SplitCard) card).getLeftHalfCard().getManaCost().convertedManaCost() > 3) {
|
||||
invalid.put(card.getName(), "Invalid cost (" + ((SplitCard) card).getLeftHalfCard().getManaCost().convertedManaCost() + ")");
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
if (((SplitCard) card).getRightHalfCard().getManaCost().convertedManaCost() > 3 ) {
|
||||
if (((SplitCard) card).getRightHalfCard().getManaCost().convertedManaCost() > 3) {
|
||||
invalid.put(card.getName(), "Invalid cost (" + ((SplitCard) card).getRightHalfCard().getManaCost().convertedManaCost() + ")");
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (card.getManaCost().convertedManaCost() > 3) {
|
||||
invalid.put(card.getName(), "Invalid cost (" + card.getManaCost().convertedManaCost() + ")");
|
||||
|
@ -220,7 +221,7 @@ public class TinyLeaders extends DeckValidator {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param commander FilterMana object with Color Identity of Commander set
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-deck-limited</artifactId>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-commanderduel</artifactId>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-commanderfreeforall</artifactId>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-freeforall</artifactId>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-momirduel</artifactId>
|
||||
|
|
|
@ -27,6 +27,11 @@
|
|||
*/
|
||||
package mage.game;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.LimitedTimesPerTurnActivatedAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
|
@ -38,7 +43,13 @@ import mage.cards.Card;
|
|||
import mage.cards.repository.CardCriteria;
|
||||
import mage.cards.repository.CardInfo;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.constants.*;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.MultiplayerAttackOption;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.constants.TimingRule;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.command.Emblem;
|
||||
import mage.game.match.MatchType;
|
||||
import mage.game.permanent.token.EmptyToken;
|
||||
|
@ -46,8 +57,6 @@ import mage.game.turn.TurnMod;
|
|||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author nigelzor
|
||||
|
@ -89,7 +98,7 @@ public class MomirDuel extends GameImpl {
|
|||
@Override
|
||||
public Set<UUID> getOpponents(UUID playerId) {
|
||||
Set<UUID> opponents = new HashSet<>();
|
||||
for (UUID opponentId: this.getPlayer(playerId).getInRange()) {
|
||||
for (UUID opponentId : this.getPlayer(playerId).getInRange()) {
|
||||
if (!opponentId.equals(playerId)) {
|
||||
opponents.add(opponentId);
|
||||
}
|
||||
|
@ -114,7 +123,7 @@ class MomirEmblem extends Emblem {
|
|||
|
||||
public MomirEmblem() {
|
||||
setName("Momir Vig, Simic Visionary");
|
||||
|
||||
//TODO: setExpansionSetCodeForImage(???);
|
||||
// {X}, Discard a card: Put a token into play as a copy of a random creature card with converted mana cost X. Play this ability only any time you could play a sorcery and only once each turn.
|
||||
LimitedTimesPerTurnActivatedAbility ability = new LimitedTimesPerTurnActivatedAbility(Zone.COMMAND, new MomirEffect(), new VariableManaCost());
|
||||
ability.addCost(new DiscardCardCost());
|
||||
|
@ -153,7 +162,9 @@ class MomirEffect extends OneShotEffect {
|
|||
EmptyToken token = new EmptyToken();
|
||||
CardUtil.copyTo(token).from(card);
|
||||
token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId(), false, false);
|
||||
} else {
|
||||
game.informPlayers("No random creature card with converted mana cost of " + value + " was found.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-tinyleadersduel</artifactId>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-game-twoplayerduel</artifactId>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-player-ai-draftbot</artifactId>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-player-ai-ma</artifactId>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-player-ai</artifactId>
|
||||
|
|
|
@ -56,6 +56,7 @@ import mage.abilities.SpellAbility;
|
|||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.costs.VariableCost;
|
||||
import mage.abilities.costs.mana.ColoredManaCost;
|
||||
import mage.abilities.costs.mana.ColorlessManaCost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.costs.mana.HybridManaCost;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
|
@ -1007,7 +1008,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
if (card.getManaCost().getVariableCosts().size() > 0) {
|
||||
//don't use variable mana costs unless there is at least 3 extra mana for X
|
||||
for (Mana option : options) {
|
||||
option.add(Mana.ColorlessMana(3));
|
||||
option.add(Mana.GenericMana(3));
|
||||
}
|
||||
}
|
||||
for (Mana mana : options) {
|
||||
|
@ -1041,7 +1042,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
if (ability.getManaCosts().getVariableCosts().size() > 0) {
|
||||
//don't use variable mana costs unless there is at least 3 extra mana for X
|
||||
for (Mana option : abilityOptions) {
|
||||
option.add(Mana.ColorlessMana(3));
|
||||
option.add(Mana.GenericMana(3));
|
||||
}
|
||||
}
|
||||
if (abilityOptions.size() == 0) {
|
||||
|
@ -1167,6 +1168,18 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
}
|
||||
}
|
||||
}
|
||||
// pay colorless
|
||||
for (ManaAbility manaAbility : perm.getAbilities().getAvailableManaAbilities(Zone.BATTLEFIELD, game)) {
|
||||
if (cost instanceof ColorlessManaCost) {
|
||||
for (Mana netMana : manaAbility.getNetMana(game)) {
|
||||
if (cost.testPay(netMana) || spendAnyMana) {
|
||||
if (activateAbility(manaAbility, game)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// finally pay generic
|
||||
for (ManaAbility manaAbility : perm.getAbilities().getAvailableManaAbilities(Zone.BATTLEFIELD, game)) {
|
||||
if (cost instanceof GenericManaCost) {
|
||||
|
@ -1182,7 +1195,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
}
|
||||
// pay phyrexian life costs
|
||||
if (cost instanceof PhyrexianManaCost) {
|
||||
if (cost.pay(null, game, null, playerId, false) || spendAnyMana) {
|
||||
if (cost.pay(null, game, null, playerId, false, null) || spendAnyMana) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-player-ai-mcts</artifactId>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-player-aiminimax</artifactId>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-player-human</artifactId>
|
||||
|
|
|
@ -358,15 +358,13 @@ public class HumanPlayer extends PlayerImpl {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (target.canTarget(response.getUUID(), game)) {
|
||||
if (target.getTargets().contains(response.getUUID())) { // if already included remove it with
|
||||
target.remove(response.getUUID());
|
||||
} else {
|
||||
target.addTarget(response.getUUID(), null, game);
|
||||
if (target.doneChosing()) {
|
||||
return true;
|
||||
}
|
||||
} else if (target.canTarget(response.getUUID(), game)) {
|
||||
if (target.getTargets().contains(response.getUUID())) { // if already included remove it with
|
||||
target.remove(response.getUUID());
|
||||
} else {
|
||||
target.addTarget(response.getUUID(), null, game);
|
||||
if (target.doneChosing()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -530,12 +528,10 @@ public class HumanPlayer extends PlayerImpl {
|
|||
if (response.getUUID() != null) {
|
||||
if (target.getTargets().contains(response.getUUID())) { // if already included remove it
|
||||
target.remove(response.getUUID());
|
||||
} else {
|
||||
if (target.canTarget(response.getUUID(), cards, game)) {
|
||||
target.addTarget(response.getUUID(), source, game);
|
||||
if (target.doneChosing()) {
|
||||
return true;
|
||||
}
|
||||
} else if (target.canTarget(response.getUUID(), cards, game)) {
|
||||
target.addTarget(response.getUUID(), source, game);
|
||||
if (target.doneChosing()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -805,7 +801,7 @@ public class HumanPlayer extends PlayerImpl {
|
|||
if (cost instanceof PhyrexianManaCost) {
|
||||
PhyrexianManaCost ph = (PhyrexianManaCost) cost;
|
||||
if (ph.canPay(null, null, playerId, game)) {
|
||||
((PhyrexianManaCost) cost).pay(null, game, null, playerId, false);
|
||||
((PhyrexianManaCost) cost).pay(null, game, null, playerId, false, null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1065,10 +1061,8 @@ public class HumanPlayer extends PlayerImpl {
|
|||
// does not block yet and can block or can block more attackers
|
||||
if (filter.match(blocker, null, playerId, game)) {
|
||||
selectCombatGroup(defendingPlayerId, blocker.getId(), game);
|
||||
} else {
|
||||
if (filterBlock.match(blocker, null, playerId, game) && game.getStack().isEmpty()) {
|
||||
removeBlocker = true;
|
||||
}
|
||||
} else if (filterBlock.match(blocker, null, playerId, game) && game.getStack().isEmpty()) {
|
||||
removeBlocker = true;
|
||||
}
|
||||
|
||||
if (removeBlocker) {
|
||||
|
@ -1546,4 +1540,9 @@ public class HumanPlayer extends PlayerImpl {
|
|||
pass(game);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHistory() {
|
||||
return "no available";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-tournament-boosterdraft</artifactId>
|
||||
|
|
|
@ -34,9 +34,9 @@ import mage.game.draft.DraftCube;
|
|||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public class MTGOLegacyCube extends DraftCube {
|
||||
public class LegacyCube extends DraftCube {
|
||||
|
||||
public MTGOLegacyCube() {
|
||||
public LegacyCube() {
|
||||
super("MTGO Legacy Cube (600 cards)");
|
||||
cubeCards.add(new CardIdentity("Accorder Paladin",""));
|
||||
cubeCards.add(new CardIdentity("Abrupt Decay",""));
|
|
@ -0,0 +1,642 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.tournament.cubes;
|
||||
|
||||
import mage.game.draft.DraftCube;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fireshoes
|
||||
*/
|
||||
|
||||
public class LegacyCubeJanuary2016 extends DraftCube {
|
||||
|
||||
public LegacyCubeJanuary2016() {
|
||||
super("MTGO Legacy Cube January 2016 (600 cards)");
|
||||
cubeCards.add(new DraftCube.CardIdentity("Abbot of Keral Keep",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Abhorrent Overlord",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Abrupt Decay",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Abyssal Persecutor",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Accorder Paladin",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Acidic Slime",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Act of Aggression",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Adarkar Wastes",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ainok Survivalist",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ajani Goldmane",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ajani Vengeant",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ajani, Caller of the Pride",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Anafenza, Kin-Tree Spirit",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ancestral Vision",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ancient Tomb",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Angel of Serenity",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Anger of the Gods",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Animate Dead",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Arbor Elf",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Arc Trail",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Archangel of Thune",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Arid Mesa",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Armageddon",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ashcloud Phoenix",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ashen Rider",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ashenmoor Gouger",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ashiok, Nightmare Weaver",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Assemble the Legion",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Attrition",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Augur of Bolas",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Avacyn's Pilgrim",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Avalanche Riders",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Avenger of Zendikar",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Badlands",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Baleful Strix",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Banefire",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Baneslayer Angel",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Banisher Priest",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Banishing Light",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Batterskull",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Battlefield Forge",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Bayou",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Beast Within",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Beetleback Chief",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Birds of Paradise",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Birthing Pod",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Bitterblossom",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Blade Splicer",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Blood Artist",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Blood Crypt",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Bloodbraid Elf",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Bloodghast",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Bloodsoaked Champion",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Bloodstained Mire",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Bloodthrone Vampire",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Bogardan Hellkite",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Bone Shredder",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Bonesplitter",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Bonfire of the Damned",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Boros Charm",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Boros Reckoner",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Brago, King Eternal",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Brainstorm",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Breeding Pool",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Brimaz, King of Oreskos",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Brimstone Volley",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Brushland",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Brutal Expulsion",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Buried Alive",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Burst Lightning",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Careful Study",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Carrier Thrall",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Carrion Feeder",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Catacomb Sifter",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Caves of Koilos",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Chain Lightning",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Chainer's Edict",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Chameleon Colossus",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Champion of the Parish",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Chandra Nalaar",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Chandra, Fire of Kaladesh",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Chandra, Pyromaster",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Chandra's Phoenix",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Char",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Chasm Skulker",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Chord of Calling",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Chromatic Lantern",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("City of Brass",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Clifftop Retreat",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Cloudgoat Ranger",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Collected Company",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Compulsive Research",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Condemn",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Consecrated Sphinx",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Control Magic",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Coralhelm Commander",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Council's Judgment",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Counterspell",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Courser of Kruphix",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Crater's Claws",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Craterhoof Behemoth",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Crusade",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Crux of Fate",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Cryptic Command",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Cultivate",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Cunning Sparkmage",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Cursed Scroll",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Cyclonic Rift",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Damnation",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Dance of the Dead",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Dark Confidant",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Dark Depths",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Dark Petition",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Dark Ritual",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Day of Judgment",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Daze",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Deathrite Shaman",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Deceiver Exarch",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Deep Analysis",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Delver of Secrets",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Den Protector",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Deranged Hermit",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Desecration Demon",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Devil's Play",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Diabolic Servitude",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Dictate of Heliod",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Disciple of Bolas",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Disfigure",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Dismember",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Dismiss",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Dissipate",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Dissolve",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Divinity of Pride",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Domri Rade",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Doom Blade",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Dragon Fodder",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Dragonlord Atarka",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Dragonlord Dromoka",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Dragonlord Ojutai",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Dragonlord Silumgar",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Dragonskull Summit",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Drana, Liberator of Malakir",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Dread Return",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Dreadbore",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Dromoka's Command",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Drowned Catacomb",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Dualcaster Mage",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Dungeon Geists",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Duplicant",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Duress",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Eldrazi Monument",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Edric, Spymaster of Trest",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Electrolyze",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Elesh Norn, Grand Cenobite",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Elite Vanguard",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Elixir of Immortality",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Elspeth Tirel",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Elspeth, Knight-Errant",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Elspeth, Sun's Champion",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Elves of Deep Shadow",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Elvish Mystic",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Emeria Angel",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Emrakul, the Aeons Torn",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Entomb",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Entreat the Angels",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Erebos, God of the Dead",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Eternal Dragon",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Eternal Witness",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Eureka",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Evolutionary Leap",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Exalted Angel",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Exclude",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Exhume",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Explore",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Exquisite Firecraft",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Fact or Fiction",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Faith's Fetters",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Falkenrath Aristocrat",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Farseek",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Fauna Shaman",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Fertile Ground",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Fiend Hunter",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Fiery Confluence",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Fire // Ice",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Firebolt",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Firefist Striker",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Flame Slash",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Flametongue Kavu",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Flamewake Phoenix",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Flickerwisp",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Flooded Strand",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Forbid",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Forbidden Alchemy",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Force of Will",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Force Spike",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Forked Bolt",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Frenzied Goblin",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Freyalise, Llanowar's Fury",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("From Beyond",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Frontline Medic",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Frost Titan",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Future Sight",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Fyndhorn Elves",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Gaddock Teeg",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Gaea's Cradle",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Garruk Relentless",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Garruk Wildspeaker",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Garruk, Apex Predator",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Garruk, Caller of Beasts",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Garruk, Primal Hunter",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Gatekeeper of Malakir",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Gather the Townsfolk",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Geist of Saint Traft",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Genesis Hydra",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Genesis Wave",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Geralf's Messenger",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Gideon, Ally of Zendikar",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Gideon Jura",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Gifts Ungiven",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Gilded Lotus",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Gilt-Leaf Winnower",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Gitaxian Probe",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Glacial Fortress",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Glen Elendra Archmage",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Glorious Anthem",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Go for the Throat",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Goblin Bombardment",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Goblin Bushwhacker",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Goblin Glory Chaser",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Goblin Guide",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Goblin Rabblemaster",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Godless Shrine",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Gore-House Chainwalker",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Grafted Wargear",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Grave Titan",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Gravecrawler",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Gray Merchant of Asphodel",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Greater Gargadon",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Green Sun's Zenith",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Greenwarden of Murasa",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Grim Lavamancer",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Griselbrand",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Hall of Triumph",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Hallowed Fountain",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Hallowed Spiritkeeper",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Hangarback Walker",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Harbinger of the Tides",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Harmonize",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Hellrider",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Hero of Bladehold",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Hero's Downfall",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Hidden Dragonslayer",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("High Market",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Hinterland Harbor",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Honor of the Pure",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Hordeling Outburst",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Hornet Queen",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Huntmaster of the Fells",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Hymn to Tourach",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Hypnotic Specter",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Imperial Recruiter",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Impulse",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Incinerate",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Indrik Stomphowler",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Inferno Titan",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Inquisition of Kozilek",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Into the Roil",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ire Shaman",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Isamaru, Hound of Konda",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Isochron Scepter",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Isolated Chapel",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Izzet Charm",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Jace Beleren",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Jace, Architect of Thought",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Jace, the Mind Sculptor",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Jace, Vryn's Prodigy",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Jackal Pup",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Joraga Treespeaker",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Journey to Nowhere",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Kami of Ancient Law",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Karmic Guide",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Karn Liberated",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Karplusan Forest",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Keiga, the Tide Star",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Keranos, God of Storms",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Kiki-Jiki, Mirror Breaker",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Kiln Fiend",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Kiora, the Crashing Wave",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Kiora's Follower",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Kira, Great Glass-Spinner",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Kitchen Finks",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Kodama's Reach",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Kokusho, the Evening Star",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Kor Skyfisher",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Koth of the Hammer",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Kozilek, Butcher of Truth",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Krenko's Command",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Kytheon, Hero of Akros",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Land Tax",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Legacy's Allure",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Leonin Relic-Warder",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Lightning Bolt",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Lightning Greaves",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Lightning Helix",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Lightning Mauler",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Lightning Strike",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Liliana of the Veil",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Liliana Vess",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Liliana, Heretical Healer",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Lingering Souls",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Linvala, Keeper of Silence",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Living Death",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Llanowar Elves",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Llanowar Wastes",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Looter il-Kor",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Lotus Cobra",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Loxodon Warhammer",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Maelstrom Pulse",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Magma Jet",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Makeshift Mannequin",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Malicious Affliction",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Man-o'-War",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Mana Confluence",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Mana Tithe",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Managorger Hydra",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Manic Vandal",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Marsh Flats",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Martial Coup",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Massacre Wurm",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Master of the Wild Hunt",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Master of Waves",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Meloku the Clouded Mirror",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Mentor of the Meek",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Merfolk Looter",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Meteor Blast",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Mimic Vat",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Mirari's Wake",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Mirran Crusader",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Miscalculation",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Mishra's Factory",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Misty Rainforest",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Mizzium Mortars",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Mogg War Marshal",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Mogis's Marauder",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Monastery Mentor",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Monastery Swiftspear",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Mother of Runes",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Mulldrifter",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Murderous Cut",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Mutavault",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Myr Battlesphere",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Mystic Confluence",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Mystic Snake",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Nantuko Husk",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Natural Order",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Nature's Lore",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Necromancy",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Negate",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Nekrataal",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Nicol Bolas, Planeswalker",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Nightveil Specter",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Nissa, Vastwood Seer",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Nissa, Worldwaker",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Noble Hierarch",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Nykthos, Shrine to Nyx",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ob Nixilis Reignited",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Oblivion Ring",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Obstinate Baloth",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ohran Viper",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Old Man of the Sea",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Olivia Voldaren",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Omnath, Locus of Rage",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Oona's Prowler",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ophiomancer",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Opposition",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Oracle of Mul Daya",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Oust",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Outpost Siege",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Overgrown Battlement",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Overgrown Tomb",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Pack Rat",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Pact of Negation",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Parallax Wave",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Part the Waterveil",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Path to Exile",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Pestermite",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Phantasmal Image",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Phyrexian Arena",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Phyrexian Metamorph",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Phyrexian Obliterator",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Phyrexian Revoker",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Pia and Kiran Nalaar",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Pillar of Flame",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Plateau",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Polluted Delta",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Polukranos, World Eater",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ponder",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Porcelain Legionnaire",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Precinct Captain",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Precursor Golem",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Preordain",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Primal Command",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Primeval Titan",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Profane Command",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Progenitus",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Prophetic Flamespeaker",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Psychatog",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Purphoros, God of the Forge",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Qasali Pridemage",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Quarantine Field",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Raise the Alarm",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Rakdos's Return",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ral Zarek",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Rampaging Baloths",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Rampant Growth",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ranger of Eos",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ratchet Bomb",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ravages of War",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Read the Bones",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Reanimate",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Reclamation Sage",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Recurring Nightmare",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Reflecting Pool",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Regrowth",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Relic of Progenitus",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Remand",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Remove Soul",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Repeal",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Restoration Angel",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Reveillark",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Rift Bolt",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Riftwing Cloudskate",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Righteous Confluence",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Rishadan Port",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Roast",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Rofellos, Llanowar Emissary",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Rootbound Crag",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Rune-Scarred Demon",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Sacred Foundry",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Sakura-Tribe Elder",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Sarkhan, the Dragonspeaker",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Savannah",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Scalding Tarn",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Scavenging Ooze",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Scroll Rack",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Scrubland",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Sea Gate Oracle",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Seal of Fire",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Search for Tomorrow",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Searing Spear",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Secure the Wastes",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Seeker of the Way",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Sensei's Divining Top",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Serendib Efreet",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Serum Visions",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Shadowmage Infiltrator",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Shaman of Forgotten Ways",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Shardless Agent",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Sheoldred, Whispering One",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Shivan Reef",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Show and Tell",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Shriekmaw",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Sidisi, Undead Vizier",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Siege-Gang Commander",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Silverblade Paladin",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Sin Collector",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Skinrender",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Skullcrack",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Slagstorm",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Slaughter Pact",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Snapcaster Mage",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Sneak Attack",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Soldier of the Pantheon",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Solemn Simulacrum",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Song of the Dryads",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Sorin Markov",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Sorin, Solemn Visitor",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Soulfire Grand Master",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Sower of Temptation",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Spear of Heliod",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Spectral Procession",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Spellskite",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Spell Pierce",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Sphinx's Revelation",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Spikeshot Elder",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Splinter Twin",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Staggershock",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Steam Vents",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Stoke the Flames",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Stomping Ground",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Stormbreath Dragon",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Stormtide Leviathan",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Stratus Dancer",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Stroke of Genius",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Stromkirk Noble",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Student of Warfare",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Sublime Archangel",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Sulfur Falls",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Sulfurous Springs",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Summoning Trap",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Sun Titan",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Sundering Titan",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Sunpetal Grove",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Supreme Verdict",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Surrak, the Hunt Caller",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Swords to Plowshares",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Sylvan Caryatid",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Sylvan Library",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Taiga",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Talrand, Sky Summoner",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Tamiyo, the Moon Sage",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Tangle Wire",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Tarmogoyf",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Tasigur, the Golden Fang",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Tectonic Edge",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Teferi, Mage of Zhalfir",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Temple Garden",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Temple of Abandon",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Temple of Deceit",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Temple of Enlightenment",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Temple of Epiphany",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Temple of Malady",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Temple of Malice",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Temple of Mystery",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Temple of Plenty",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Temple of Silence",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Temple of Triumph",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Terastodon",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Terminate",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Terminus",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Thalia, Guardian of Thraben",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Thassa, God of the Sea",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Thespian's Stage",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Thoughtseize",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Thragtusk",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Threads of Disloyalty",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Through the Breach",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Thrun, the Last Troll",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Thunderbreak Regent",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Thundermaw Hellkite",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Tidehollow Sculler",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Time Warp",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Tooth and Nail",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Toxic Deluge",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Treachery",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Tropical Island",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Trygon Predator",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Tundra",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ugin, the Spirit Dragon",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ulamog, the Ceaseless Hunger",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ulamog, the Infinite Gyre",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Ultimate Price",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Unburial Rites",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Underground River",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Underground Sea",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Underworld Connections",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Unexpectedly Absent",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Upheaval",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Utopia Sprawl",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Vampire Hexmage",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Vampire Nighthawk",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Vendilion Clique",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Vengevine",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Venser, Shaper Savant",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Venser, the Sojourner",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Verdant Catacombs",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Vindicate",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Viscera Seer",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Volcanic Island",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Volrath's Stronghold",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Voyaging Satyr",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Vraska the Unseen",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Wake Thrasher",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Wall of Blossoms",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Wall of Omens",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Wall of Roots",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Warleader's Helix",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Waterfront Bouncer",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Watery Grave",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Whip of Erebos",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Whirler Rogue",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Whisperwood Elemental",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Windbrisk Heights",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Windswept Heath",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Winter Orb",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Wolfir Silverheart",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Wood Elves",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Wooded Foothills",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Woodfall Primus",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Woodland Cemetery",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Wrath of God",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Wretched Confluence",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Wurmcoil Engine",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Xenagos, the Reveler",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Yavimaya Coast",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Yavimaya Elder",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Yosei, the Morning Star",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Young Pyromancer",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Zealous Conscripts",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Zulaport Cutthroat",""));
|
||||
}
|
||||
}
|
|
@ -34,9 +34,9 @@ import mage.game.draft.DraftCube;
|
|||
* @author fireshoes
|
||||
*/
|
||||
|
||||
public class MTGOLegacyCubeMarch2015 extends DraftCube {
|
||||
public class LegacyCubeMarch2015 extends DraftCube {
|
||||
|
||||
public MTGOLegacyCubeMarch2015() {
|
||||
public LegacyCubeMarch2015() {
|
||||
super("MTGO Legacy Cube March 2015 (600 cards)");
|
||||
cubeCards.add(new DraftCube.CardIdentity("Accorder Paladin",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Abrupt Decay",""));
|
|
@ -34,9 +34,9 @@ import mage.game.draft.DraftCube;
|
|||
* @author fireshoes
|
||||
*/
|
||||
|
||||
public class MTGOLegacyCubeSeptember2015 extends DraftCube {
|
||||
public class LegacyCubeSeptember2015 extends DraftCube {
|
||||
|
||||
public MTGOLegacyCubeSeptember2015() {
|
||||
public LegacyCubeSeptember2015() {
|
||||
super("MTGO Legacy Cube September 2015 (600 cards)");
|
||||
cubeCards.add(new DraftCube.CardIdentity("Abbot of Keral Keep",""));
|
||||
cubeCards.add(new DraftCube.CardIdentity("Abhorrent Overlord",""));
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-tournament-constructed</artifactId>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-tournament-sealed</artifactId>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-server-plugins</artifactId>
|
||||
|
|
|
@ -19,6 +19,17 @@
|
|||
userNamePattern - pattern for user name validity check
|
||||
maxAiOpponents - number of allowed AI opponents on the server
|
||||
saveGameActivated - allow game save and replay options (not working correctly yet)
|
||||
authenticationActivated - "true" = user have to register to signon "false" = user need not to register
|
||||
* mail configs only needed if authentication is activated:
|
||||
* if mailUser = "" mailgun is used otherwise nativ mail server on the system
|
||||
googleAccount - not supported currently
|
||||
mailgunApiKey - key from the mailgun domain e.g. = "key-12121111..."
|
||||
mailgunDomain - domain for the mailgun message sending
|
||||
mailSmtpHost - hostname to send the mail
|
||||
mailSmtpPort - port to send the mail
|
||||
mailUser - username used to send the mail
|
||||
mailPassword - passworf of the used user to send the mail
|
||||
mailFromAddress - sender address
|
||||
-->
|
||||
<server serverAddress="0.0.0.0"
|
||||
serverName="mage-server"
|
||||
|
@ -32,9 +43,20 @@
|
|||
maxSecondsIdle="600"
|
||||
minUserNameLength="3"
|
||||
maxUserNameLength="14"
|
||||
userNamePattern="[^a-z0-9_]"
|
||||
invalidUserNamePattern="[^a-z0-9_]"
|
||||
minPasswordLength="8"
|
||||
maxPasswordLength="100"
|
||||
maxAiOpponents="15"
|
||||
saveGameActivated="false"
|
||||
authenticationActivated="true"
|
||||
googleAccount=""
|
||||
mailgunApiKey="key-d93e81f19a9c9ed243ebb7cc9381385c"
|
||||
mailgunDomain="sandbox401a433f30d445309a5e86b6c53f7812.mailgun.org"
|
||||
mailSmtpHost="smtp.1und1.de"
|
||||
mailSmtpPort="465"
|
||||
mailUser="xmageserver@online.de"
|
||||
mailPassword="24wrsfxv"
|
||||
mailFromAddress="xmageserver@online.de"
|
||||
/>
|
||||
<playerTypes>
|
||||
<playerType name="Human" jar="mage-player-human.jar" className="mage.player.human.HumanPlayer"/>
|
||||
|
@ -73,9 +95,10 @@
|
|||
<draftCube name="Jim Davis's Cube (469 cards)" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.JimDavisCube"/>
|
||||
<draftCube name="Mono Blue Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.MonoBlueCube"/>
|
||||
<draftCube name="MTGO Cube March 2014" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.MTGOMarchCube2014"/>
|
||||
<draftCube name="MTGO Legacy Cube (600 cards)" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.MTGOLegacyCube"/>
|
||||
<draftCube name="MTGO Legacy Cube March 2015 (600 cards)" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.MTGOLegacyCubeMarch2015"/>
|
||||
<draftCube name="MTGO Legacy Cube September 2015 (600 cards)" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.MTGOLegacyCubeSeptember2015"/>
|
||||
<draftCube name="MTGO Legacy Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCube"/>
|
||||
<draftCube name="MTGO Legacy Cube March 2015" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeMarch2015"/>
|
||||
<draftCube name="MTGO Legacy Cube September 2015" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeSeptember2015"/>
|
||||
<draftCube name="MTGO Legacy Cube January 2016" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeJanuary2016"/>
|
||||
<draftCube name="MTGO Legendary Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegendaryCube"/>
|
||||
<draftCube name="MTGO Vintage Cube 2013" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCube2013"/>
|
||||
<draftCube name="MTGO Vintage Cube 2014" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCube2014"/>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mage-server</artifactId>
|
||||
|
@ -148,6 +148,62 @@
|
|||
<version>${project.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-core</artifactId>
|
||||
<version>1.2.4</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.api-client</groupId>
|
||||
<artifactId>google-api-client</artifactId>
|
||||
<version>1.21.0</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.apis</groupId>
|
||||
<artifactId>google-api-services-gmail</artifactId>
|
||||
<version>v1-rev35-1.21.0</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.oauth-client</groupId>
|
||||
<artifactId>google-oauth-client-java6</artifactId>
|
||||
<version>1.19.0</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.oauth-client</groupId>
|
||||
<artifactId>google-oauth-client-jetty</artifactId>
|
||||
<version>1.19.0</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.mail</groupId>
|
||||
<artifactId>mail</artifactId>
|
||||
<version>1.4.2</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-core</artifactId>
|
||||
<version>1.19</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-client</artifactId>
|
||||
<version>1.19</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey.contribs</groupId>
|
||||
<artifactId>jersey-multipart</artifactId>
|
||||
<version>1.19</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<version>3.7.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -1,6 +1,36 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Config.xsd">
|
||||
<!--
|
||||
serverAddress - ip of the XMage server. Set it to "0.0.0.0" for local host or to the IP the server should use
|
||||
port - the port the primary server socket is bound to
|
||||
secondaryBindPort - the port to which the secondary server socket is to be bound. if "-1" is set , an arbitrary port is selected.
|
||||
backlogSize - the preferred number of unaccepted incoming connections allowed at a given time. The actual number may be greater
|
||||
than the specified backlog. When the queue is full, further connection requests are rejected. The JBoss default value is 200
|
||||
numAcceptThreads - the number of threads listening on the ServerSocket. The JBoss default value is 1
|
||||
maxPoolSize - the maximum number of ServerThreads that can exist at any given time. The JBoss default value is 300
|
||||
leasePeriod - To turn on server side connection failure detection of remoting clients, it is necessary to satisfy two criteria.
|
||||
The first is that the client lease period is set and is a value greater than 0. The value is represented in milliseconds.
|
||||
The client lease period can be set by either the 'clientLeasePeriod' attribute within the Connector configuration or by calling the Connector method
|
||||
maxGameThreads - Number of games that can be started simultanously on the server
|
||||
maxSecondsIdle - Number of seconds after that a game is auto conceded by the player that was idle for such a time
|
||||
minUserNameLength - minmal allowed length of a user name to connect to the server
|
||||
maxUserNameLength - maximal allowed length of a user name to connect to the server
|
||||
userNamePattern - pattern for user name validity check
|
||||
maxAiOpponents - number of allowed AI opponents on the server
|
||||
saveGameActivated - allow game save and replay options (not working correctly yet)
|
||||
authenticationActivated - "true" = user have to register to signon "false" = user need not to register
|
||||
* mail configs only needed if authentication is activated:
|
||||
* if mailUser = "" mailgun is used otherwise nativ mail server on the system
|
||||
googleAccount - not supported currently
|
||||
mailgunApiKey - key from the mailgun domain e.g. = "key-12121111..."
|
||||
mailgunDomain - domain for the mailgun message sending
|
||||
mailSmtpHost - hostname to send the mail
|
||||
mailSmtpPort - port to send the mail
|
||||
mailUser - username used to send the mail
|
||||
mailPassword - passworf of the used user to send the mail
|
||||
mailFromAddress - sender address
|
||||
-->
|
||||
<server serverAddress="0.0.0.0"
|
||||
serverName="mage-server"
|
||||
port="17171"
|
||||
|
@ -13,9 +43,20 @@
|
|||
maxSecondsIdle="600"
|
||||
minUserNameLength="3"
|
||||
maxUserNameLength="14"
|
||||
userNamePattern="[^a-z0-9_]"
|
||||
invalidUserNamePattern="[^a-z0-9_]"
|
||||
minPasswordLength="8"
|
||||
maxPasswordLength="100"
|
||||
maxAiOpponents="15"
|
||||
saveGameActivated="false"
|
||||
authenticationActivated="false"
|
||||
googleAccount=""
|
||||
mailgunApiKey=""
|
||||
mailgunDomain=""
|
||||
mailSmtpHost=""
|
||||
mailSmtpPort=""
|
||||
mailUser=""
|
||||
mailPassword=""
|
||||
mailFromAddress=""
|
||||
/>
|
||||
<playerTypes>
|
||||
<playerType name="Human" jar="mage-player-human-${project.version}.jar" className="mage.player.human.HumanPlayer"/>
|
||||
|
@ -52,9 +93,10 @@
|
|||
<draftCube name="Jim Davis's Cube (469 cards)" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.JimDavisCube"/>
|
||||
<draftCube name="Mono Blue Cube" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.MonoBlueCube"/>
|
||||
<draftCube name="MTGO Cube March 2014" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.MTGOMarchCube2014"/>
|
||||
<draftCube name="MTGO Legacy Cube (600 cards)" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.MTGOLegacyCube"/>
|
||||
<draftCube name="MTGO Legacy Cube March 2015 (600 cards)" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.MTGOLegacyCubeMarch2015"/>
|
||||
<draftCube name="MTGO Legacy Cube September 2015 (600 cards)" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.MTGOLegacyCubeSeptember2015"/>
|
||||
<draftCube name="MTGO Legacy Cube" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.LegacyCube"/>
|
||||
<draftCube name="MTGO Legacy Cube March 2015" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.LegacyCubeMarch2015"/>
|
||||
<draftCube name="MTGO Legacy Cube September 2015" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.LegacyCubeSeptember2015"/>
|
||||
<draftCube name="MTGO Legacy Cube January 2016" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.LegacyCubeJanuary2016"/>
|
||||
<draftCube name="MTGO Legendary Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegendaryCube"/>
|
||||
<draftCube name="MTGO Vintage Cube 2013" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.VintageCube2013"/>
|
||||
<draftCube name="MTGO Vintage Cube 2014" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.VintageCube2014"/>
|
||||
|
|
60
Mage.Server/src/main/java/mage/server/AuthorizedUser.java
Normal file
60
Mage.Server/src/main/java/mage/server/AuthorizedUser.java
Normal file
|
@ -0,0 +1,60 @@
|
|||
package mage.server;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
import org.apache.shiro.authc.AuthenticationInfo;
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
import org.apache.shiro.authc.SimpleAuthenticationInfo;
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
|
||||
import org.apache.shiro.util.ByteSource;
|
||||
import org.apache.shiro.codec.Base64;
|
||||
import org.apache.shiro.crypto.hash.Hash;
|
||||
|
||||
@DatabaseTable(tableName = "authorized_user")
|
||||
public class AuthorizedUser {
|
||||
|
||||
@DatabaseField(indexName = "name_index", unique = true)
|
||||
protected String name;
|
||||
|
||||
@DatabaseField
|
||||
protected String password;
|
||||
|
||||
@DatabaseField
|
||||
protected String salt;
|
||||
|
||||
@DatabaseField
|
||||
protected String hashAlgorithm;
|
||||
|
||||
@DatabaseField
|
||||
protected int hashIterations;
|
||||
|
||||
@DatabaseField(indexName = "email_index", unique = true)
|
||||
protected String email;
|
||||
|
||||
public AuthorizedUser() {
|
||||
}
|
||||
|
||||
public AuthorizedUser(String name, Hash hash, String email) {
|
||||
this.name = name;
|
||||
this.password = hash.toBase64();
|
||||
this.salt = hash.getSalt().toBase64();
|
||||
this.hashAlgorithm = hash.getAlgorithmName();
|
||||
this.hashIterations = hash.getIterations();
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public boolean doCredentialsMatch(String name, String password) {
|
||||
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(this.hashAlgorithm);
|
||||
matcher.setHashIterations(this.hashIterations);
|
||||
AuthenticationToken token = new UsernamePasswordToken(name, password);
|
||||
AuthenticationInfo info = new SimpleAuthenticationInfo(this.name,
|
||||
ByteSource.Util.bytes(Base64.decode(this.password)),
|
||||
ByteSource.Util.bytes(Base64.decode(this.salt)), "");
|
||||
return matcher.doCredentialsMatch(token, info);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
package mage.server;
|
||||
|
||||
import com.j256.ormlite.dao.Dao;
|
||||
import com.j256.ormlite.dao.DaoManager;
|
||||
import com.j256.ormlite.jdbc.JdbcConnectionSource;
|
||||
import com.j256.ormlite.stmt.DeleteBuilder;
|
||||
import com.j256.ormlite.stmt.QueryBuilder;
|
||||
import com.j256.ormlite.stmt.SelectArg;
|
||||
import com.j256.ormlite.support.ConnectionSource;
|
||||
import com.j256.ormlite.support.DatabaseConnection;
|
||||
import com.j256.ormlite.table.TableUtils;
|
||||
import java.io.File;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import mage.cards.repository.RepositoryUtil;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.shiro.crypto.RandomNumberGenerator;
|
||||
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
|
||||
import org.apache.shiro.crypto.hash.Hash;
|
||||
import org.apache.shiro.crypto.hash.Sha256Hash;
|
||||
import org.apache.shiro.crypto.hash.SimpleHash;
|
||||
|
||||
public enum AuthorizedUserRepository {
|
||||
|
||||
instance;
|
||||
|
||||
private static final String JDBC_URL = "jdbc:h2:file:./db/authorized_user.h2;AUTO_SERVER=TRUE";
|
||||
private static final String VERSION_ENTITY_NAME = "authorized_user";
|
||||
// raise this if db structure was changed
|
||||
private static final long DB_VERSION = 1;
|
||||
private static final RandomNumberGenerator rng = new SecureRandomNumberGenerator();
|
||||
|
||||
private Dao<AuthorizedUser, Object> dao;
|
||||
|
||||
private AuthorizedUserRepository() {
|
||||
File file = new File("db");
|
||||
if (!file.exists()) {
|
||||
file.mkdirs();
|
||||
}
|
||||
try {
|
||||
ConnectionSource connectionSource = new JdbcConnectionSource(JDBC_URL);
|
||||
boolean obsolete = RepositoryUtil.isDatabaseObsolete(connectionSource, VERSION_ENTITY_NAME, DB_VERSION);
|
||||
|
||||
if (obsolete) {
|
||||
TableUtils.dropTable(connectionSource, AuthorizedUser.class, true);
|
||||
}
|
||||
|
||||
TableUtils.createTableIfNotExists(connectionSource, AuthorizedUser.class);
|
||||
dao = DaoManager.createDao(connectionSource, AuthorizedUser.class);
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(AuthorizedUserRepository.class).error("Error creating authorized_user repository - ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void add(final String userName, final String password, final String email) {
|
||||
try {
|
||||
Hash hash = new SimpleHash(Sha256Hash.ALGORITHM_NAME, password, rng.nextBytes(), 1024);
|
||||
AuthorizedUser user = new AuthorizedUser(userName, hash, email);
|
||||
dao.create(user);
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(AuthorizedUserRepository.class).error("Error adding a user to DB - ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(final String userName) {
|
||||
try {
|
||||
DeleteBuilder<AuthorizedUser, Object> db = dao.deleteBuilder();
|
||||
db.where().eq("name", new SelectArg(userName));
|
||||
db.delete();
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(AuthorizedUserRepository.class).error("Error removing a user from DB - ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public AuthorizedUser getByName(String userName) {
|
||||
try {
|
||||
QueryBuilder<AuthorizedUser, Object> qb = dao.queryBuilder();
|
||||
qb.where().eq("name", new SelectArg(userName));
|
||||
List<AuthorizedUser> results = dao.query(qb.prepare());
|
||||
if (results.size() == 1) {
|
||||
return results.get(0);
|
||||
}
|
||||
return null;
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(AuthorizedUserRepository.class).error("Error getting a authorized_user - ", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AuthorizedUser getByEmail(String userName) {
|
||||
try {
|
||||
QueryBuilder<AuthorizedUser, Object> qb = dao.queryBuilder();
|
||||
qb.where().eq("email", new SelectArg(userName));
|
||||
List<AuthorizedUser> results = dao.query(qb.prepare());
|
||||
if (results.size() == 1) {
|
||||
return results.get(0);
|
||||
}
|
||||
return null;
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(AuthorizedUserRepository.class).error("Error getting a authorized_user - ", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void closeDB() {
|
||||
try {
|
||||
if (dao != null && dao.getConnectionSource() != null) {
|
||||
DatabaseConnection conn = dao.getConnectionSource().getReadWriteConnection();
|
||||
conn.executeStatement("shutdown compact", 0);
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(AuthorizedUserRepository.class).error("Error closing authorized_user repository - ", ex);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,8 +24,7 @@
|
|||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
*/
|
||||
package mage.server;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -44,14 +43,15 @@ import org.apache.log4j.Logger;
|
|||
public class ChatManager {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ChatManager.class);
|
||||
|
||||
|
||||
private static final ChatManager INSTANCE = new ChatManager();
|
||||
|
||||
public static ChatManager getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private ChatManager() {}
|
||||
private ChatManager() {
|
||||
}
|
||||
|
||||
private final ConcurrentHashMap<UUID, ChatSession> chatSessions = new ConcurrentHashMap<>();
|
||||
|
||||
|
@ -66,16 +66,16 @@ public class ChatManager {
|
|||
if (chatSession != null) {
|
||||
chatSession.join(userId);
|
||||
} else {
|
||||
logger.trace("Chat to join not found - chatId: " + chatId +" userId: " + userId);
|
||||
}
|
||||
|
||||
logger.trace("Chat to join not found - chatId: " + chatId + " userId: " + userId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void leaveChat(UUID chatId, UUID userId) {
|
||||
ChatSession chatSession = chatSessions.get(chatId);
|
||||
if (chatSession != null && chatSession.hasUser(userId)) {
|
||||
chatSession.kill(userId, DisconnectReason.CleaningUp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void destroyChatSession(UUID chatId) {
|
||||
|
@ -88,7 +88,7 @@ public class ChatManager {
|
|||
logger.trace("Chat removed - chatId: " + chatId);
|
||||
} else {
|
||||
logger.trace("Chat to destroy does not exist - chatId: " + chatId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ public class ChatManager {
|
|||
ChatSession chatSession = chatSessions.get(chatId);
|
||||
if (chatSession != null) {
|
||||
if (message.startsWith("\\") || message.startsWith("/")) {
|
||||
User user = UserManager.getInstance().findUser(userName);
|
||||
User user = UserManager.getInstance().getUserByName(userName);
|
||||
if (user != null && performUserCommand(user, message, chatId)) {
|
||||
return;
|
||||
}
|
||||
|
@ -119,63 +119,56 @@ public class ChatManager {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean performUserCommand(User user, String message, UUID chatId) {
|
||||
String command = message.substring(1).trim().toUpperCase(Locale.ENGLISH);
|
||||
if (command.equals("I") || command.equals("INFO")) {
|
||||
user.setInfo("");
|
||||
chatSessions.get(chatId).broadcastInfoToUser(user,message);
|
||||
return true;
|
||||
}
|
||||
if (command.startsWith("I ") || command.startsWith("INFO ")) {
|
||||
user.setInfo(message.substring(command.startsWith("I ") ? 3 : 6));
|
||||
chatSessions.get(chatId).broadcastInfoToUser(user,message);
|
||||
if (command.startsWith("H ") || command.startsWith("HISTORY ")) {
|
||||
message = UserManager.getInstance().getUserHistory(message.substring(command.startsWith("H ") ? 3 : 9));
|
||||
chatSessions.get(chatId).broadcastInfoToUser(user, message);
|
||||
return true;
|
||||
}
|
||||
if (command.startsWith("W ") || command.startsWith("WHISPER ")) {
|
||||
String rest = message.substring(command.startsWith("W ")? 3 : 9);
|
||||
String rest = message.substring(command.startsWith("W ") ? 3 : 9);
|
||||
int first = rest.indexOf(" ");
|
||||
if (first > 1) {
|
||||
String userToName = rest.substring(0,first);
|
||||
String userToName = rest.substring(0, first);
|
||||
rest = rest.substring(first + 1).trim();
|
||||
User userTo = UserManager.getInstance().findUser(userToName);
|
||||
User userTo = UserManager.getInstance().getUserByName(userToName);
|
||||
if (userTo != null) {
|
||||
if (!chatSessions.get(chatId).broadcastWhisperToUser(user, userTo, rest)) {
|
||||
message += new StringBuilder("<br/>User ").append(userToName).append(" not found").toString();
|
||||
chatSessions.get(chatId).broadcastInfoToUser(user,message);
|
||||
chatSessions.get(chatId).broadcastInfoToUser(user, message);
|
||||
}
|
||||
} else {
|
||||
message += new StringBuilder("<br/>User ").append(userToName).append(" not found").toString();
|
||||
chatSessions.get(chatId).broadcastInfoToUser(user,message);
|
||||
chatSessions.get(chatId).broadcastInfoToUser(user, message);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (command.equals("L") || command.equals("LIST")) {
|
||||
message += new StringBuilder("<br/>List of commands:")
|
||||
.append("<br/>\\info [text] - set a info text to your player")
|
||||
.append("<br/>\\list - Show a list of commands")
|
||||
.append("<br/>\\whisper [player name] [text] - whisper to the player with the given name").toString();
|
||||
chatSessions.get(chatId).broadcastInfoToUser(user,message);
|
||||
.append("<br/>\\history or \\h [username] - shows the history of a player")
|
||||
.append("<br/>\\list or \\l - Show a list of commands")
|
||||
.append("<br/>\\whisper or \\w [player name] [text] - whisper to the player with the given name").toString();
|
||||
chatSessions.get(chatId).broadcastInfoToUser(user, message);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* use mainly for announcing that a user connection was lost or that a user has reconnected
|
||||
*
|
||||
*
|
||||
* use mainly for announcing that a user connection was lost or that a user
|
||||
* has reconnected
|
||||
*
|
||||
* @param userId
|
||||
* @param message
|
||||
* @param color
|
||||
* @param color
|
||||
*/
|
||||
public void broadcast(UUID userId, String message, MessageColor color) {
|
||||
User user = UserManager.getInstance().getUser(userId);
|
||||
if (user != null) {
|
||||
for (ChatSession chat: chatSessions.values()) {
|
||||
for (ChatSession chat : chatSessions.values()) {
|
||||
if (chat.hasUser(userId)) {
|
||||
chat.broadcast(user.getName(), message, color);
|
||||
}
|
||||
|
@ -186,16 +179,16 @@ public class ChatManager {
|
|||
public void sendReconnectMessage(UUID userId) {
|
||||
User user = UserManager.getInstance().getUser(userId);
|
||||
if (user != null) {
|
||||
for (ChatSession chat: chatSessions.values()) {
|
||||
for (ChatSession chat : chatSessions.values()) {
|
||||
if (chat.hasUser(userId)) {
|
||||
chat.broadcast(null, user.getName() + " has reconnected", MessageColor.BLUE, true, MessageType.STATUS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void removeUser(UUID userId, DisconnectReason reason) {
|
||||
for (ChatSession chatSession: chatSessions.values()) {
|
||||
for (ChatSession chatSession : chatSessions.values()) {
|
||||
if (chatSession.hasUser(userId)) {
|
||||
chatSession.kill(userId, reason);
|
||||
}
|
||||
|
|
91
Mage.Server/src/main/java/mage/server/GmailClient.java
Normal file
91
Mage.Server/src/main/java/mage/server/GmailClient.java
Normal file
|
@ -0,0 +1,91 @@
|
|||
package mage.server;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
|
||||
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
|
||||
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
|
||||
import com.google.api.client.http.HttpTransport;
|
||||
import com.google.api.client.json.JsonFactory;
|
||||
import com.google.api.client.json.jackson2.JacksonFactory;
|
||||
import com.google.api.client.util.Base64;
|
||||
import com.google.api.client.util.store.FileDataStoreFactory;
|
||||
import com.google.api.services.gmail.Gmail;
|
||||
import com.google.api.services.gmail.Gmail.Builder;
|
||||
import com.google.api.services.gmail.GmailScopes;
|
||||
import com.google.api.services.gmail.model.Message;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Collections;
|
||||
import java.util.Properties;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.Session;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import mage.server.util.ConfigSettings;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
public class GmailClient {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(Main.class);
|
||||
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
|
||||
private static final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("user.home"), ".store/xmage");
|
||||
private static FileDataStoreFactory dataStoreFactory;
|
||||
private static HttpTransport httpTransport;
|
||||
private static Credential credential;
|
||||
|
||||
public static boolean initilize() {
|
||||
try {
|
||||
dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR);
|
||||
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
|
||||
|
||||
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new FileReader("client_secrets.json"));
|
||||
if (clientSecrets.getDetails().getClientId().startsWith("Enter")
|
||||
|| clientSecrets.getDetails().getClientSecret().startsWith("Enter ")) {
|
||||
logger.error("client_secrets.json not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
|
||||
httpTransport, JSON_FACTORY, clientSecrets,
|
||||
Collections.singleton(GmailScopes.GMAIL_COMPOSE)).setDataStoreFactory(
|
||||
dataStoreFactory).build();
|
||||
|
||||
credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
|
||||
return true;
|
||||
} catch (IOException | GeneralSecurityException ex) {
|
||||
logger.error("Error initializing GmailClient", ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean sendMessage(String email, String subject, String text) {
|
||||
if (email.length() == 0) {
|
||||
logger.info("Email is not sent because the address is empty");
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
Gmail gmail = new Builder(httpTransport, JSON_FACTORY, credential).setApplicationName("XMage Server").build();
|
||||
|
||||
MimeMessage mimeMessage = new MimeMessage(Session.getDefaultInstance(new Properties()));
|
||||
mimeMessage.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(email));
|
||||
mimeMessage.setSubject(subject);
|
||||
mimeMessage.setText(text);
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
mimeMessage.writeTo(baos);
|
||||
Message message = new Message();
|
||||
message.setRaw(Base64.encodeBase64URLSafeString(baos.toByteArray()));
|
||||
|
||||
gmail.users().messages().send(ConfigSettings.getInstance().getGoogleAccount()
|
||||
+ (ConfigSettings.getInstance().getGoogleAccount().endsWith("@gmail.com") ? "" : "@gmail.com"), message).execute();
|
||||
return true;
|
||||
} catch (MessagingException | IOException ex) {
|
||||
logger.error("Error sending message", ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -27,9 +27,12 @@
|
|||
*/
|
||||
package mage.server;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
@ -95,25 +98,105 @@ public class MageServerImpl implements MageServer {
|
|||
|
||||
private static final Logger logger = Logger.getLogger(MageServerImpl.class);
|
||||
private static final ExecutorService callExecutor = ThreadExecutor.getInstance().getCallExecutor();
|
||||
private static final SecureRandom RANDOM = new SecureRandom();
|
||||
|
||||
private final String password;
|
||||
private final String adminPassword;
|
||||
private final boolean testMode;
|
||||
private final LinkedHashMap<String, String> activeAuthTokens = new LinkedHashMap<String, String>() {
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
|
||||
// Keep the latest 1024 auth tokens in memory.
|
||||
return size() > 1024;
|
||||
}
|
||||
};
|
||||
|
||||
public MageServerImpl(String password, boolean testMode) {
|
||||
this.password = password;
|
||||
public MageServerImpl(String adminPassword, boolean testMode) {
|
||||
this.adminPassword = adminPassword;
|
||||
this.testMode = testMode;
|
||||
ServerMessagesUtil.getInstance().getMessages();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerUser(String sessionId, String userName, String password, String email) throws MageException {
|
||||
return SessionManager.getInstance().registerUser(sessionId, userName, password, email);
|
||||
}
|
||||
|
||||
// generateAuthToken returns a uniformly distributed 6-digits string.
|
||||
static private String generateAuthToken() {
|
||||
return String.format("%06d", RANDOM.nextInt(1000000));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean emailAuthToken(String sessionId, String email) throws MageException {
|
||||
if (!ConfigSettings.getInstance().isAuthenticationActivated()) {
|
||||
sendErrorMessageToClient(sessionId, "Registration is disabled by the server config");
|
||||
return false;
|
||||
}
|
||||
AuthorizedUser authorizedUser = AuthorizedUserRepository.instance.getByEmail(email);
|
||||
if (authorizedUser == null) {
|
||||
sendErrorMessageToClient(sessionId, "No user was found with the email address " + email);
|
||||
logger.info("Auth token is requested for " + email + " but there's no such user in DB");
|
||||
return false;
|
||||
}
|
||||
String authToken = generateAuthToken();
|
||||
activeAuthTokens.put(email, authToken);
|
||||
String subject = "XMage Password Reset Auth Token";
|
||||
String text = "Use this auth token to reset your password: " + authToken + "\n"
|
||||
+ "It's valid until the next server restart.";
|
||||
boolean success;
|
||||
if (!ConfigSettings.getInstance().getMailUser().isEmpty()) {
|
||||
success = MailClient.sendMessage(email, subject, text);
|
||||
} else {
|
||||
success = MailgunClient.sendMessage(email, subject, text);
|
||||
}
|
||||
if (!success) {
|
||||
sendErrorMessageToClient(sessionId, "There was an error inside the server while emailing an auth token");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resetPassword(String sessionId, String email, String authToken, String password) throws MageException {
|
||||
if (!ConfigSettings.getInstance().isAuthenticationActivated()) {
|
||||
sendErrorMessageToClient(sessionId, "Registration is disabled by the server config");
|
||||
return false;
|
||||
}
|
||||
String storedAuthToken = activeAuthTokens.get(email);
|
||||
if (storedAuthToken == null || !storedAuthToken.equals(authToken)) {
|
||||
sendErrorMessageToClient(sessionId, "Invalid auth token");
|
||||
logger.info("Invalid auth token " + authToken + " is sent for " + email);
|
||||
return false;
|
||||
}
|
||||
AuthorizedUser authorizedUser = AuthorizedUserRepository.instance.getByEmail(email);
|
||||
if (authorizedUser == null) {
|
||||
sendErrorMessageToClient(sessionId, "The user is no longer in the DB");
|
||||
logger.info("Auth token is valid, but the user with email address " + email + " is no longer in the DB");
|
||||
return false;
|
||||
}
|
||||
AuthorizedUserRepository.instance.remove(authorizedUser.getName());
|
||||
AuthorizedUserRepository.instance.add(authorizedUser.getName(), password, email);
|
||||
activeAuthTokens.remove(email);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerClient(String userName, String sessionId, MageVersion version) throws MageException {
|
||||
// This method is deprecated, so just inform the server version.
|
||||
logger.info("MageVersionException: userName=" + userName + ", version=" + version);
|
||||
LogServiceImpl.instance.log(LogKeys.KEY_WRONG_VERSION, userName, version.toString(), Main.getVersion().toString(), sessionId);
|
||||
throw new MageVersionException(version, Main.getVersion());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean connectUser(String userName, String password, String sessionId, MageVersion version) throws MageException {
|
||||
try {
|
||||
if (version.compareTo(Main.getVersion()) != 0) {
|
||||
logger.info("MageVersionException: userName=" + userName + ", version=" + version);
|
||||
LogServiceImpl.instance.log(LogKeys.KEY_WRONG_VERSION, userName, version.toString(), Main.getVersion().toString(), sessionId);
|
||||
throw new MageVersionException(version, Main.getVersion());
|
||||
}
|
||||
return SessionManager.getInstance().registerUser(sessionId, userName);
|
||||
return SessionManager.getInstance().connectUser(sessionId, userName, password);
|
||||
} catch (MageException ex) {
|
||||
if (ex instanceof MageVersionException) {
|
||||
throw (MageVersionException) ex;
|
||||
|
@ -134,15 +217,15 @@ public class MageServerImpl implements MageServer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean registerAdmin(String password, String sessionId, MageVersion version) throws MageException {
|
||||
public boolean connectAdmin(String adminPassword, String sessionId, MageVersion version) throws MageException {
|
||||
try {
|
||||
if (version.compareTo(Main.getVersion()) != 0) {
|
||||
throw new MageException("Wrong client version " + version + ", expecting version " + Main.getVersion());
|
||||
}
|
||||
if (!password.equals(this.password)) {
|
||||
if (!adminPassword.equals(this.adminPassword)) {
|
||||
throw new MageException("Wrong password");
|
||||
}
|
||||
return SessionManager.getInstance().registerAdmin(sessionId);
|
||||
return SessionManager.getInstance().connectAdmin(sessionId);
|
||||
} catch (Exception ex) {
|
||||
handleException(ex);
|
||||
}
|
||||
|
@ -362,7 +445,7 @@ public class MageServerImpl implements MageServer {
|
|||
// }
|
||||
@Override
|
||||
public boolean startMatch(final String sessionId, final UUID roomId, final UUID tableId) throws MageException {
|
||||
if (!TableManager.getInstance().getController(tableId).changeTableState(TableState.STARTING)) {
|
||||
if (!TableManager.getInstance().getController(tableId).changeTableStateToStarting()) {
|
||||
return false;
|
||||
}
|
||||
execute("startMatch", sessionId, new Action() {
|
||||
|
@ -387,7 +470,7 @@ public class MageServerImpl implements MageServer {
|
|||
// }
|
||||
@Override
|
||||
public boolean startTournament(final String sessionId, final UUID roomId, final UUID tableId) throws MageException {
|
||||
if (!TableManager.getInstance().getController(tableId).changeTableState(TableState.STARTING)) {
|
||||
if (!TableManager.getInstance().getController(tableId).changeTableStateToStarting()) {
|
||||
return false;
|
||||
}
|
||||
execute("startTournament", sessionId, new Action() {
|
||||
|
@ -1032,6 +1115,15 @@ public class MageServerImpl implements MageServer {
|
|||
}
|
||||
}
|
||||
|
||||
private void sendErrorMessageToClient(final String sessionId, final String message) throws MageException {
|
||||
execute("sendErrorMessageToClient", sessionId, new Action() {
|
||||
@Override
|
||||
public void execute() {
|
||||
SessionManager.getInstance().sendErrorMessageToClient(sessionId, message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void execute(final String actionName, final String sessionId, final Action action, boolean checkAdminRights) throws MageException {
|
||||
if (checkAdminRights) {
|
||||
if (!SessionManager.getInstance().isAdmin(sessionId)) {
|
||||
|
|
53
Mage.Server/src/main/java/mage/server/MailClient.java
Normal file
53
Mage.Server/src/main/java/mage/server/MailClient.java
Normal file
|
@ -0,0 +1,53 @@
|
|||
package mage.server;
|
||||
|
||||
import java.util.Properties;
|
||||
import javax.mail.Message;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.Session;
|
||||
import javax.mail.Transport;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import mage.server.util.ConfigSettings;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
public class MailClient {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(Main.class);
|
||||
|
||||
public static boolean sendMessage(String email, String subject, String text) {
|
||||
if (email.length() == 0) {
|
||||
logger.info("Email is not sent because the address is empty");
|
||||
return false;
|
||||
}
|
||||
ConfigSettings config = ConfigSettings.getInstance();
|
||||
|
||||
Properties properties = System.getProperties();
|
||||
properties.setProperty("mail.smtps.host", config.getMailSmtpHost());
|
||||
properties.setProperty("mail.smtps.port", config.getMailSmtpPort());
|
||||
properties.setProperty("mail.smtps.auth", "true");
|
||||
properties.setProperty("mail.user", config.getMailUser());
|
||||
properties.setProperty("mail.password", config.getMailPassword());
|
||||
|
||||
Session session = Session.getDefaultInstance(properties);
|
||||
|
||||
try{
|
||||
MimeMessage message = new MimeMessage(session);
|
||||
message.setFrom(new InternetAddress(config.getMailFromAddress()));
|
||||
message.addRecipient(Message.RecipientType.TO, new InternetAddress(email));
|
||||
message.setSubject(subject);
|
||||
message.setText(text);
|
||||
|
||||
Transport trnsport;
|
||||
trnsport = session.getTransport("smtps");
|
||||
trnsport.connect(null, properties.getProperty("mail.password"));
|
||||
message.saveChanges();
|
||||
trnsport.sendMessage(message, message.getAllRecipients());
|
||||
trnsport.close();
|
||||
|
||||
return true;
|
||||
}catch (MessagingException ex) {
|
||||
logger.error("Error sending message to " + email, ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
37
Mage.Server/src/main/java/mage/server/MailgunClient.java
Normal file
37
Mage.Server/src/main/java/mage/server/MailgunClient.java
Normal file
|
@ -0,0 +1,37 @@
|
|||
package mage.server;
|
||||
|
||||
import com.sun.jersey.api.client.Client;
|
||||
import com.sun.jersey.api.client.ClientResponse;
|
||||
import com.sun.jersey.api.client.WebResource;
|
||||
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
|
||||
import com.sun.jersey.core.util.MultivaluedMapImpl;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import mage.server.util.ConfigSettings;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
public class MailgunClient {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(Main.class);
|
||||
|
||||
public static boolean sendMessage(String email, String subject, String text) {
|
||||
if (email.length() == 0) {
|
||||
logger.info("Email is not sent because the address is empty");
|
||||
return false;
|
||||
}
|
||||
Client client = Client.create();
|
||||
client.addFilter(new HTTPBasicAuthFilter("api", ConfigSettings.getInstance().getMailgunApiKey()));
|
||||
String domain = ConfigSettings.getInstance().getMailgunDomain();
|
||||
WebResource webResource = client.resource("https://api.mailgun.net/v3/" + domain + "/messages");
|
||||
MultivaluedMapImpl formData = new MultivaluedMapImpl();
|
||||
formData.add("from", "XMage <postmaster@" + domain + ">");
|
||||
formData.add("to", email);
|
||||
formData.add("subject", subject);
|
||||
formData.add("text", text);
|
||||
ClientResponse response = webResource.type(MediaType.APPLICATION_FORM_URLENCODED).post(ClientResponse.class, formData);
|
||||
boolean succeeded = response.getStatus() == 200;
|
||||
if (!succeeded) {
|
||||
logger.error("Error sending message to " + email + ". Status code: " + response.getStatus());
|
||||
}
|
||||
return succeeded;
|
||||
}
|
||||
}
|
|
@ -1,33 +1,39 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.server;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.net.InetAddress;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.management.MBeanServer;
|
||||
import mage.cards.repository.CardScanner;
|
||||
import mage.game.match.MatchType;
|
||||
import mage.game.tournament.TournamentType;
|
||||
|
@ -37,6 +43,7 @@ import mage.server.draft.CubeFactory;
|
|||
import mage.server.game.DeckValidatorFactory;
|
||||
import mage.server.game.GameFactory;
|
||||
import mage.server.game.PlayerFactory;
|
||||
import mage.server.record.UserStatsRepository;
|
||||
import mage.server.tournament.TournamentFactory;
|
||||
import mage.server.util.ConfigSettings;
|
||||
import mage.server.util.PluginClassLoader;
|
||||
|
@ -46,26 +53,23 @@ import mage.server.util.config.GamePlugin;
|
|||
import mage.server.util.config.Plugin;
|
||||
import mage.utils.MageVersion;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jboss.remoting.*;
|
||||
import org.jboss.remoting.Client;
|
||||
import org.jboss.remoting.ClientDisconnectedException;
|
||||
import org.jboss.remoting.ConnectionListener;
|
||||
import org.jboss.remoting.InvocationRequest;
|
||||
import org.jboss.remoting.InvokerLocator;
|
||||
import org.jboss.remoting.Remoting;
|
||||
import org.jboss.remoting.ServerInvocationHandler;
|
||||
import org.jboss.remoting.ServerInvoker;
|
||||
import org.jboss.remoting.callback.InvokerCallbackHandler;
|
||||
import org.jboss.remoting.callback.ServerInvokerCallbackHandler;
|
||||
import org.jboss.remoting.transport.Connector;
|
||||
import org.jboss.remoting.transport.bisocket.BisocketServerInvoker;
|
||||
import org.jboss.remoting.transport.socket.SocketWrapper;
|
||||
import org.jboss.remoting.transporter.TransporterClient;
|
||||
import org.jboss.remoting.transporter.TransporterServer;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.jboss.remoting.transport.bisocket.BisocketServerInvoker;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
@ -73,14 +77,13 @@ import org.jboss.remoting.transport.bisocket.BisocketServerInvoker;
|
|||
public class Main {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(Main.class);
|
||||
private static final MageVersion version = new MageVersion(MageVersion.MAGE_VERSION_MAJOR, MageVersion.MAGE_VERSION_MINOR, MageVersion.MAGE_VERSION_PATCH, MageVersion.MAGE_VERSION_MINOR_PATCH, MageVersion.MAGE_VERSION_INFO);
|
||||
private static final MageVersion version = new MageVersion(MageVersion.MAGE_VERSION_MAJOR, MageVersion.MAGE_VERSION_MINOR, MageVersion.MAGE_VERSION_PATCH, MageVersion.MAGE_VERSION_MINOR_PATCH, MageVersion.MAGE_VERSION_INFO);
|
||||
|
||||
private static final String testModeArg = "-testMode=";
|
||||
private static final String fastDBModeArg = "-fastDbMode=";
|
||||
private static final String adminPasswordArg = "-adminPassword=";
|
||||
private static final String pluginFolder = "plugins";
|
||||
|
||||
|
||||
public static PluginClassLoader classLoader = new PluginClassLoader();
|
||||
public static TransporterServer server;
|
||||
protected static boolean testMode;
|
||||
|
@ -95,19 +98,17 @@ public class Main {
|
|||
logger.info("Logging level: " + logger.getEffectiveLevel());
|
||||
|
||||
String adminPassword = "";
|
||||
for (String arg: args) {
|
||||
for (String arg : args) {
|
||||
if (arg.startsWith(testModeArg)) {
|
||||
testMode = Boolean.valueOf(arg.replace(testModeArg, ""));
|
||||
}
|
||||
else if (arg.startsWith(adminPasswordArg)) {
|
||||
} else if (arg.startsWith(adminPasswordArg)) {
|
||||
adminPassword = arg.replace(adminPasswordArg, "");
|
||||
adminPassword = SystemUtil.sanitize(adminPassword);
|
||||
}
|
||||
else if (arg.startsWith(fastDBModeArg)) {
|
||||
} else if (arg.startsWith(fastDBModeArg)) {
|
||||
fastDbMode = Boolean.valueOf(arg.replace(fastDBModeArg, ""));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
logger.info("Loading cards...");
|
||||
if (fastDbMode) {
|
||||
CardScanner.scanned = true;
|
||||
|
@ -116,54 +117,68 @@ public class Main {
|
|||
}
|
||||
logger.info("Done.");
|
||||
|
||||
logger.info("Updating user stats DB...");
|
||||
UserStatsRepository.instance.updateUserStats();
|
||||
logger.info("Done.");
|
||||
|
||||
deleteSavedGames();
|
||||
ConfigSettings config = ConfigSettings.getInstance();
|
||||
for (GamePlugin plugin: config.getGameTypes()) {
|
||||
for (GamePlugin plugin : config.getGameTypes()) {
|
||||
GameFactory.getInstance().addGameType(plugin.getName(), loadGameType(plugin), loadPlugin(plugin));
|
||||
}
|
||||
for (GamePlugin plugin: config.getTournamentTypes()) {
|
||||
for (GamePlugin plugin : config.getTournamentTypes()) {
|
||||
TournamentFactory.getInstance().addTournamentType(plugin.getName(), loadTournamentType(plugin), loadPlugin(plugin));
|
||||
}
|
||||
for (Plugin plugin: config.getPlayerTypes()) {
|
||||
for (Plugin plugin : config.getPlayerTypes()) {
|
||||
PlayerFactory.getInstance().addPlayerType(plugin.getName(), loadPlugin(plugin));
|
||||
}
|
||||
for (Plugin plugin: config.getDraftCubes()) {
|
||||
for (Plugin plugin : config.getDraftCubes()) {
|
||||
CubeFactory.getInstance().addDraftCube(plugin.getName(), loadPlugin(plugin));
|
||||
}
|
||||
for (Plugin plugin: config.getDeckTypes()) {
|
||||
for (Plugin plugin : config.getDeckTypes()) {
|
||||
DeckValidatorFactory.getInstance().addDeckType(plugin.getName(), loadPlugin(plugin));
|
||||
}
|
||||
|
||||
logger.info("Config - max seconds idle: " + config.getMaxSecondsIdle());
|
||||
logger.info("Config - max game threads: " + config.getMaxGameThreads());
|
||||
logger.info("Config - max AI opponents: " + config.getMaxAiOpponents());
|
||||
logger.info("Config - min user name l.: " + config.getMinUserNameLength());
|
||||
logger.info("Config - max user name l.: " + config.getMaxUserNameLength());
|
||||
logger.info("Config - save game active: " + (config.isSaveGameActivated() ? "True":"false"));
|
||||
|
||||
logger.info("Config - min usr name le.: " + config.getMinUserNameLength());
|
||||
logger.info("Config - max usr name le.: " + config.getMaxUserNameLength());
|
||||
logger.info("Config - min pswrd length: " + config.getMinPasswordLength());
|
||||
logger.info("Config - max pswrd length: " + config.getMaxPasswordLength());
|
||||
logger.info("Config - inv.usr name pat: " + config.getInvalidUserNamePattern());
|
||||
logger.info("Config - save game active: " + (config.isSaveGameActivated() ? "true" : "false"));
|
||||
logger.info("Config - backlog size : " + config.getBacklogSize());
|
||||
logger.info("Config - lease period : " + config.getLeasePeriod());
|
||||
logger.info("Config - max pool size : " + config.getMaxPoolSize());
|
||||
logger.info("Config - num accp.threads: " + config.getNumAcceptThreads());
|
||||
logger.info("Config - second.bind port: " + config.getSecondaryBindPort());
|
||||
|
||||
logger.info("Config - auth. activated : " + (config.isAuthenticationActivated() ? "true" : "false"));
|
||||
logger.info("Config - mailgun api key : " + config.getMailgunApiKey());
|
||||
logger.info("Config - mailgun domain : " + config.getMailgunDomain());
|
||||
logger.info("Config - mail smtp Host : " + config.getMailSmtpHost());
|
||||
logger.info("Config - mail smtpPort : " + config.getMailSmtpPort());
|
||||
logger.info("Config - mail user : " + config.getMailUser());
|
||||
logger.info("Config - mail passw. len.: " + config.getMailPassword().length());
|
||||
logger.info("Config - mail from addre.: " + config.getMailFromAddress());
|
||||
logger.info("Config - google account : " + config.getGoogleAccount());
|
||||
|
||||
Connection connection = new Connection("&maxPoolSize=" + config.getMaxPoolSize());
|
||||
connection.setHost(config.getServerAddress());
|
||||
connection.setPort(config.getPort());
|
||||
try {
|
||||
// Parameter: serializationtype => jboss
|
||||
InvokerLocator serverLocator = new InvokerLocator(connection.getURI());
|
||||
InvokerLocator serverLocator = new InvokerLocator(connection.getURI());
|
||||
if (!isAlreadyRunning(serverLocator)) {
|
||||
server = new MageTransporterServer(serverLocator, new MageServerImpl(adminPassword, testMode), MageServer.class.getName(), new MageServerInvocationHandler());
|
||||
server.start();
|
||||
logger.info("Started MAGE server - listening on " + connection.toString());
|
||||
|
||||
|
||||
if (testMode) {
|
||||
logger.info("MAGE server running in test mode");
|
||||
}
|
||||
initStatistics();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
logger.fatal("Unable to start MAGE server - another server is already started");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
|
@ -192,6 +207,7 @@ public class Main {
|
|||
}
|
||||
|
||||
static class ClientConnectionListener implements ConnectionListener {
|
||||
|
||||
@Override
|
||||
public void handleConnectionException(Throwable throwable, Client client) {
|
||||
Session session = SessionManager.getInstance().getSession(client.getSessionId());
|
||||
|
@ -207,12 +223,12 @@ public class Main {
|
|||
if (throwable instanceof ClientDisconnectedException) {
|
||||
// Seems like the random diconnects from public server land here and should not be handled as explicit disconnects
|
||||
// So it should be possible to reconnect to server and continue games if DisconnectReason is set to LostConnection
|
||||
//SessionManager.getInstance().disconnect(client.getSessionId(), DisconnectReason.Disconnected);
|
||||
//SessionManager.getInstance().disconnect(client.getSessionId(), DisconnectReason.Disconnected);
|
||||
SessionManager.getInstance().disconnect(client.getSessionId(), DisconnectReason.LostConnection);
|
||||
logger.info("CLIENT DISCONNECTED - " + sessionInfo);
|
||||
logger.debug("Stack Trace", throwable);
|
||||
} else {
|
||||
SessionManager.getInstance().disconnect(client.getSessionId(), DisconnectReason.LostConnection);
|
||||
} else {
|
||||
SessionManager.getInstance().disconnect(client.getSessionId(), DisconnectReason.LostConnection);
|
||||
logger.info("LOST CONNECTION - " + sessionInfo);
|
||||
if (logger.isDebugEnabled()) {
|
||||
if (throwable == null) {
|
||||
|
@ -220,7 +236,7 @@ public class Main {
|
|||
} else {
|
||||
logger.debug(" - cause: " + Session.getBasicCause(throwable).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -253,13 +269,13 @@ public class Main {
|
|||
|
||||
@Override
|
||||
public void setMBeanServer(MBeanServer server) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInvoker(ServerInvoker invoker) {
|
||||
public void setInvoker(ServerInvoker invoker) {
|
||||
((BisocketServerInvoker) invoker).setSecondaryBindPort(ConfigSettings.getInstance().getSecondaryBindPort());
|
||||
((BisocketServerInvoker) invoker).setBacklog(ConfigSettings.getInstance().getBacklogSize());
|
||||
((BisocketServerInvoker) invoker).setBacklog(ConfigSettings.getInstance().getBacklogSize());
|
||||
((BisocketServerInvoker) invoker).setNumAcceptThreads(ConfigSettings.getInstance().getNumAcceptThreads());
|
||||
}
|
||||
|
||||
|
@ -330,7 +346,7 @@ public class Main {
|
|||
logger.debug("Loading tournament type: " + plugin.getClassName());
|
||||
return (TournamentType) Class.forName(plugin.getTypeName(), true, classLoader).newInstance();
|
||||
} catch (ClassNotFoundException ex) {
|
||||
logger.warn("Tournament type not found:" + plugin.getName() + " / "+ plugin.getJar() + " - check plugin folder", ex);
|
||||
logger.warn("Tournament type not found:" + plugin.getName() + " / " + plugin.getJar() + " - check plugin folder", ex);
|
||||
} catch (Exception ex) {
|
||||
logger.fatal("Error loading game type " + plugin.getJar(), ex);
|
||||
}
|
||||
|
@ -343,15 +359,14 @@ public class Main {
|
|||
directory.mkdirs();
|
||||
}
|
||||
File[] files = directory.listFiles(
|
||||
new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.endsWith(".game");
|
||||
new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.endsWith(".game");
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
for (File file : files)
|
||||
{
|
||||
for (File file : files) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,8 @@ import org.jboss.remoting.callback.InvokerCallbackHandler;
|
|||
public class Session {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(Session.class);
|
||||
private final static Pattern alphabetsPattern = Pattern.compile("[a-zA-Z]");
|
||||
private final static Pattern digitsPattern = Pattern.compile("[0-9]");
|
||||
|
||||
private final String sessionId;
|
||||
private UUID userId;
|
||||
|
@ -74,8 +76,98 @@ public class Session {
|
|||
this.lock = new ReentrantLock();
|
||||
}
|
||||
|
||||
public String registerUser(String userName) throws MageException {
|
||||
String returnMessage = registerUserHandling(userName);
|
||||
public String registerUser(String userName, String password, String email) throws MageException {
|
||||
if (!ConfigSettings.getInstance().isAuthenticationActivated()) {
|
||||
String returnMessage = "Registration is disabled by the server config";
|
||||
sendErrorMessageToClient(returnMessage);
|
||||
return returnMessage;
|
||||
}
|
||||
synchronized (AuthorizedUserRepository.instance) {
|
||||
String returnMessage = validateUserName(userName);
|
||||
if (returnMessage != null) {
|
||||
sendErrorMessageToClient(returnMessage);
|
||||
return returnMessage;
|
||||
}
|
||||
returnMessage = validatePassword(password, userName);
|
||||
if (returnMessage != null) {
|
||||
sendErrorMessageToClient(returnMessage);
|
||||
return returnMessage;
|
||||
}
|
||||
returnMessage = validateEmail(email);
|
||||
if (returnMessage != null) {
|
||||
sendErrorMessageToClient(returnMessage);
|
||||
return returnMessage;
|
||||
}
|
||||
AuthorizedUserRepository.instance.add(userName, password, email);
|
||||
String subject = "XMage Registration Completed";
|
||||
String text = "You are successfully registered as " + userName + ".";
|
||||
boolean success;
|
||||
if (!ConfigSettings.getInstance().getMailUser().isEmpty()) {
|
||||
success = MailClient.sendMessage(email, subject, text);
|
||||
} else {
|
||||
success = MailgunClient.sendMessage(email, subject, text);
|
||||
}
|
||||
if (success) {
|
||||
logger.info("Sent a registration confirmation email to " + email + " for " + userName);
|
||||
} else {
|
||||
logger.error("Failed sending a registration confirmation email to " + email + " for " + userName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static private String validateUserName(String userName) {
|
||||
if (userName.equals("Admin")) {
|
||||
return "User name Admin already in use";
|
||||
}
|
||||
ConfigSettings config = ConfigSettings.getInstance();
|
||||
if (userName.length() < config.getMinUserNameLength()) {
|
||||
return "User name may not be shorter than " + config.getMinUserNameLength() + " characters";
|
||||
}
|
||||
if (userName.length() > config.getMaxUserNameLength()) {
|
||||
return "User name may not be longer than " + config.getMaxUserNameLength() + " characters";
|
||||
}
|
||||
Pattern invalidUserNamePattern = Pattern.compile(ConfigSettings.getInstance().getInvalidUserNamePattern(), Pattern.CASE_INSENSITIVE);
|
||||
Matcher m = invalidUserNamePattern.matcher(userName);
|
||||
if (m.find()) {
|
||||
return "User name '" + userName + "' includes not allowed characters: use a-z, A-Z and 0-9";
|
||||
}
|
||||
AuthorizedUser authorizedUser = AuthorizedUserRepository.instance.getByName(userName);
|
||||
if (authorizedUser != null) {
|
||||
return "User name '" + userName + "' already in use";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static private String validatePassword(String password, String userName) {
|
||||
ConfigSettings config = ConfigSettings.getInstance();
|
||||
if (password.length() < config.getMinPasswordLength()) {
|
||||
return "Password may not be shorter than " + config.getMinPasswordLength() + " characters";
|
||||
}
|
||||
if (password.length() > config.getMaxPasswordLength()) {
|
||||
return "Password may not be longer than " + config.getMaxPasswordLength() + " characters";
|
||||
}
|
||||
if (password.equals(userName)) {
|
||||
return "Password may not be the same as your username";
|
||||
}
|
||||
Matcher alphabetsMatcher = alphabetsPattern.matcher(password);
|
||||
Matcher digitsMatcher = digitsPattern.matcher(password);
|
||||
if (!alphabetsMatcher.find() || !digitsMatcher.find()) {
|
||||
return "Password has to include at least one alphabet (a-zA-Z) and also at least one digit (0-9)";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static private String validateEmail(String email) {
|
||||
AuthorizedUser authorizedUser = AuthorizedUserRepository.instance.getByEmail(email);
|
||||
if (authorizedUser != null) {
|
||||
return "Email address '" + email + "' is associated with another user";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String connectUser(String userName, String password) throws MageException {
|
||||
String returnMessage = connectUserHandling(userName, password);
|
||||
if (returnMessage != null) {
|
||||
sendErrorMessageToClient(returnMessage);
|
||||
}
|
||||
|
@ -86,27 +178,21 @@ public class Session {
|
|||
return lock.isLocked();
|
||||
}
|
||||
|
||||
public String registerUserHandling(String userName) throws MageException {
|
||||
public String connectUserHandling(String userName, String password) throws MageException {
|
||||
this.isAdmin = false;
|
||||
if (userName.equals("Admin")) {
|
||||
return "User name Admin already in use";
|
||||
}
|
||||
if (userName.length() > ConfigSettings.getInstance().getMaxUserNameLength()) {
|
||||
return "User name may not be longer than " + ConfigSettings.getInstance().getMaxUserNameLength() + " characters";
|
||||
}
|
||||
if (userName.length() < ConfigSettings.getInstance().getMinUserNameLength()) {
|
||||
return "User name may not be shorter than " + ConfigSettings.getInstance().getMinUserNameLength() + " characters";
|
||||
}
|
||||
Pattern p = Pattern.compile(ConfigSettings.getInstance().getUserNamePattern(), Pattern.CASE_INSENSITIVE);
|
||||
Matcher m = p.matcher(userName);
|
||||
if (m.find()) {
|
||||
return "User name '" + userName + "' includes not allowed characters: use a-z, A-Z and 0-9";
|
||||
if (ConfigSettings.getInstance().isAuthenticationActivated()) {
|
||||
AuthorizedUser authorizedUser = AuthorizedUserRepository.instance.getByName(userName);
|
||||
if (authorizedUser == null || !authorizedUser.doCredentialsMatch(userName, password)) {
|
||||
return "Wrong username or password. In case you haven't, please register your account first.";
|
||||
}
|
||||
}
|
||||
|
||||
User user = UserManager.getInstance().createUser(userName, host);
|
||||
boolean reconnect = false;
|
||||
if (user == null) { // user already exists
|
||||
user = UserManager.getInstance().findUser(userName);
|
||||
if (user.getHost().equals(host)) {
|
||||
user = UserManager.getInstance().getUserByName(userName);
|
||||
// If authentication is not activated, check the identity using IP address.
|
||||
if (ConfigSettings.getInstance().isAuthenticationActivated() || user.getHost().equals(host)) {
|
||||
user.updateLastActivity(null); // minimizes possible expiration
|
||||
this.userId = user.getId();
|
||||
if (user.getSessionId().isEmpty()) {
|
||||
|
@ -135,11 +221,11 @@ public class Session {
|
|||
return null;
|
||||
}
|
||||
|
||||
public void registerAdmin() {
|
||||
public void connectAdmin() {
|
||||
this.isAdmin = true;
|
||||
User user = UserManager.getInstance().createUser("Admin", host);
|
||||
if (user == null) {
|
||||
user = UserManager.getInstance().findUser("Admin");
|
||||
user = UserManager.getInstance().getUserByName("Admin");
|
||||
}
|
||||
UserData adminUserData = UserData.getDefaultUserDataView();
|
||||
adminUserData.setGroupId(UserGroup.ADMIN.getGroupId());
|
||||
|
@ -151,7 +237,7 @@ public class Session {
|
|||
}
|
||||
|
||||
public boolean setUserData(String userName, UserData userData) {
|
||||
User user = UserManager.getInstance().findUser(userName);
|
||||
User user = UserManager.getInstance().getUserByName(userName);
|
||||
if (user != null) {
|
||||
if (user.getUserData() == null || user.getUserData().getGroupId() == UserGroup.DEFAULT.getGroupId()) {
|
||||
user.setUserData(userData);
|
||||
|
@ -279,7 +365,7 @@ public class Session {
|
|||
this.host = hostAddress;
|
||||
}
|
||||
|
||||
void sendErrorMessageToClient(String message) {
|
||||
public void sendErrorMessageToClient(String message) {
|
||||
List<String> messageData = new LinkedList<>();
|
||||
messageData.add("Error while connecting to server");
|
||||
messageData.add(message);
|
||||
|
|
|
@ -70,31 +70,51 @@ public class SessionManager {
|
|||
sessions.put(sessionId, session);
|
||||
}
|
||||
|
||||
public boolean registerUser(String sessionId, String userName) throws MageException {
|
||||
public boolean registerUser(String sessionId, String userName, String password, String email) throws MageException {
|
||||
Session session = sessions.get(sessionId);
|
||||
if (session == null) {
|
||||
logger.error(userName + " tried to register with no sessionId");
|
||||
return false;
|
||||
}
|
||||
String returnMessage = session.registerUser(userName, password, email);
|
||||
if (returnMessage != null) {
|
||||
logger.debug(userName + " not registered: " + returnMessage);
|
||||
return false;
|
||||
}
|
||||
LogServiceImpl.instance.log(LogKeys.KEY_USER_REGISTERED, userName, session.getHost(), sessionId);
|
||||
|
||||
logger.info(userName + " registered");
|
||||
logger.debug("- userId: " + session.getUserId());
|
||||
logger.debug("- sessionId: " + sessionId);
|
||||
logger.debug("- host: " + session.getHost());
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean connectUser(String sessionId, String userName, String password) throws MageException {
|
||||
Session session = sessions.get(sessionId);
|
||||
if (session != null) {
|
||||
String returnMessage = session.registerUser(userName);
|
||||
String returnMessage = session.connectUser(userName, password);
|
||||
if (returnMessage == null) {
|
||||
LogServiceImpl.instance.log(LogKeys.KEY_USER_CONNECTED, userName, session.getHost(), sessionId);
|
||||
|
||||
logger.info(userName + " joined server");
|
||||
logger.info(userName + " connected to server");
|
||||
logger.debug("- userId: " + session.getUserId());
|
||||
logger.debug("- sessionId: " + sessionId);
|
||||
logger.debug("- host: " + session.getHost());
|
||||
return true;
|
||||
} else {
|
||||
logger.debug(userName + " not registered: " + returnMessage);
|
||||
logger.debug(userName + " not connected: " + returnMessage);
|
||||
}
|
||||
} else {
|
||||
logger.error(userName + " tried to join with no sessionId");
|
||||
logger.error(userName + " tried to connect with no sessionId");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean registerAdmin(String sessionId) {
|
||||
public boolean connectAdmin(String sessionId) {
|
||||
Session session = sessions.get(sessionId);
|
||||
if (session != null) {
|
||||
session.registerAdmin();
|
||||
session.connectAdmin();
|
||||
LogServiceImpl.instance.log(LogKeys.KEY_ADMIN_CONNECTED, "Admin", session.getHost(), sessionId);
|
||||
logger.info("Admin connected from " + session.getHost());
|
||||
return true;
|
||||
|
@ -217,4 +237,13 @@ public class SessionManager {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void sendErrorMessageToClient(String sessionId, String message) {
|
||||
Session session = sessions.get(sessionId);
|
||||
if (session == null) {
|
||||
logger.error("Following error message is not delivered because session " + sessionId + " is not found: " + message);
|
||||
return;
|
||||
}
|
||||
session.sendErrorMessageToClient(message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ import mage.server.game.DeckValidatorFactory;
|
|||
import mage.server.game.GameFactory;
|
||||
import mage.server.game.GameManager;
|
||||
import mage.server.game.PlayerFactory;
|
||||
import mage.server.record.TableRecorderImpl;
|
||||
import mage.server.services.LogKeys;
|
||||
import mage.server.services.impl.LogServiceImpl;
|
||||
import mage.server.tournament.TournamentController;
|
||||
|
@ -105,7 +106,7 @@ public class TableController {
|
|||
} else {
|
||||
controllerName = "System";
|
||||
}
|
||||
table = new Table(roomId, options.getGameType(), options.getName(), controllerName, DeckValidatorFactory.getInstance().createDeckValidator(options.getDeckType()), options.getPlayerTypes(), match);
|
||||
table = new Table(roomId, options.getGameType(), options.getName(), controllerName, DeckValidatorFactory.getInstance().createDeckValidator(options.getDeckType()), options.getPlayerTypes(), TableRecorderImpl.getInstance(), match);
|
||||
chatId = ChatManager.getInstance().createChatSession("Match Table " + table.getId());
|
||||
init();
|
||||
}
|
||||
|
@ -124,7 +125,7 @@ public class TableController {
|
|||
} else {
|
||||
controllerName = "System";
|
||||
}
|
||||
table = new Table(roomId, options.getTournamentType(), options.getName(), controllerName, DeckValidatorFactory.getInstance().createDeckValidator(options.getMatchOptions().getDeckType()), options.getPlayerTypes(), tournament);
|
||||
table = new Table(roomId, options.getTournamentType(), options.getName(), controllerName, DeckValidatorFactory.getInstance().createDeckValidator(options.getMatchOptions().getDeckType()), options.getPlayerTypes(), TableRecorderImpl.getInstance(), tournament);
|
||||
chatId = ChatManager.getInstance().createChatSession("Tourn. table " + table.getId());
|
||||
}
|
||||
|
||||
|
@ -237,6 +238,7 @@ public class TableController {
|
|||
|
||||
TournamentPlayer newTournamentPlayer = tournament.getPlayer(newPlayer.getId());
|
||||
newTournamentPlayer.setState(oldTournamentPlayer.getState());
|
||||
newTournamentPlayer.setReplacedTournamentPlayer(oldTournamentPlayer);
|
||||
|
||||
DraftManager.getInstance().getController(table.getId()).replacePlayer(oldPlayer, newPlayer);
|
||||
return true;
|
||||
|
@ -957,26 +959,16 @@ public class TableController {
|
|||
return getTable().getState();
|
||||
}
|
||||
|
||||
public synchronized boolean changeTableState(TableState newTableState) {
|
||||
switch (newTableState) {
|
||||
case WAITING:
|
||||
if (getTable().getState().equals(TableState.STARTING)) {
|
||||
// tournament already started
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case STARTING:
|
||||
if (!getTable().getState().equals(TableState.READY_TO_START)) {
|
||||
// tournament is not ready, can't start
|
||||
return false;
|
||||
}
|
||||
if (!table.allSeatsAreOccupied()) {
|
||||
logger.debug("Not alle Seats are occupied: stop start tableId:" + table.getId());
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
public synchronized boolean changeTableStateToStarting() {
|
||||
if (!getTable().getState().equals(TableState.READY_TO_START)) {
|
||||
// tournament is not ready, can't start
|
||||
return false;
|
||||
}
|
||||
getTable().setState(newTableState);
|
||||
if (!table.allSeatsAreOccupied()) {
|
||||
logger.debug("Not alle Seats are occupied: stop start tableId:" + table.getId());
|
||||
return false;
|
||||
}
|
||||
getTable().setState(TableState.STARTING);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,12 +40,15 @@ import java.util.concurrent.TimeUnit;
|
|||
import mage.cards.decks.Deck;
|
||||
import mage.constants.ManaType;
|
||||
import mage.game.Table;
|
||||
import mage.game.result.ResultProtos;
|
||||
import mage.game.tournament.TournamentPlayer;
|
||||
import mage.interfaces.callback.ClientCallback;
|
||||
import mage.players.net.UserData;
|
||||
import mage.server.draft.DraftSession;
|
||||
import mage.server.game.GameManager;
|
||||
import mage.server.game.GameSessionPlayer;
|
||||
import mage.server.record.UserStats;
|
||||
import mage.server.record.UserStatsRepository;
|
||||
import mage.server.tournament.TournamentController;
|
||||
import mage.server.tournament.TournamentManager;
|
||||
import mage.server.tournament.TournamentSession;
|
||||
|
@ -59,7 +62,7 @@ import org.apache.log4j.Logger;
|
|||
*/
|
||||
public class User {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(User.class);
|
||||
private static final Logger LOGGER = Logger.getLogger(User.class);
|
||||
|
||||
public enum UserState {
|
||||
|
||||
|
@ -79,11 +82,11 @@ public class User {
|
|||
private final Map<UUID, Deck> sideboarding;
|
||||
private final List<UUID> watchedGames;
|
||||
private String sessionId;
|
||||
private String info = "";
|
||||
private String pingInfo = "";
|
||||
private Date lastActivity;
|
||||
private UserState userState;
|
||||
private UserData userData;
|
||||
private UserStats userStats;
|
||||
|
||||
public User(String userName, String host) {
|
||||
this.userId = UUID.randomUUID();
|
||||
|
@ -103,6 +106,7 @@ public class User {
|
|||
this.watchedGames = new ArrayList<>();
|
||||
this.tablesToDelete = new ArrayList<>();
|
||||
this.sessionId = "";
|
||||
this.userStats = null;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
@ -126,15 +130,15 @@ public class User {
|
|||
if (sessionId.isEmpty()) {
|
||||
userState = UserState.Disconnected;
|
||||
lostConnection();
|
||||
logger.trace("USER - lost connection: " + userName + " id: " + userId);
|
||||
LOGGER.trace("USER - lost connection: " + userName + " id: " + userId);
|
||||
|
||||
} else if (userState == UserState.Created) {
|
||||
userState = UserState.Connected;
|
||||
logger.trace("USER - created: " + userName + " id: " + userId);
|
||||
LOGGER.trace("USER - created: " + userName + " id: " + userId);
|
||||
} else {
|
||||
userState = UserState.Reconnected;
|
||||
reconnect();
|
||||
logger.trace("USER - reconnected: " + userName + " id: " + userId);
|
||||
LOGGER.trace("USER - reconnected: " + userName + " id: " + userId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -270,12 +274,13 @@ public class User {
|
|||
|
||||
public boolean isExpired(Date expired) {
|
||||
if (lastActivity.before(expired)) {
|
||||
logger.trace(userName + " is expired!");
|
||||
LOGGER.trace(userName + " is expired!");
|
||||
userState = UserState.Expired;
|
||||
return true;
|
||||
}
|
||||
logger.trace(new StringBuilder("isExpired: User ").append(userName).append(" lastActivity: ").append(lastActivity).append(" expired: ").append(expired).toString());
|
||||
return false; /*userState == UserState.Disconnected && */
|
||||
LOGGER.trace(new StringBuilder("isExpired: User ").append(userName).append(" lastActivity: ").append(lastActivity).append(" expired: ").append(expired).toString());
|
||||
return false;
|
||||
/*userState == UserState.Disconnected && */
|
||||
|
||||
}
|
||||
|
||||
|
@ -357,35 +362,35 @@ public class User {
|
|||
}
|
||||
|
||||
public void remove(DisconnectReason reason) {
|
||||
logger.trace("REMOVE " + getName() + " Draft sessions " + draftSessions.size());
|
||||
LOGGER.trace("REMOVE " + getName() + " Draft sessions " + draftSessions.size());
|
||||
for (DraftSession draftSession : draftSessions.values()) {
|
||||
draftSession.setKilled();
|
||||
}
|
||||
draftSessions.clear();
|
||||
logger.trace("REMOVE " + getName() + " Tournament sessions " + userTournaments.size());
|
||||
LOGGER.trace("REMOVE " + getName() + " Tournament sessions " + userTournaments.size());
|
||||
for (UUID tournamentId : userTournaments.values()) {
|
||||
TournamentManager.getInstance().quit(tournamentId, getId());
|
||||
}
|
||||
userTournaments.clear();
|
||||
logger.trace("REMOVE " + getName() + " Tables " + tables.size());
|
||||
LOGGER.trace("REMOVE " + getName() + " Tables " + tables.size());
|
||||
for (Entry<UUID, Table> entry : tables.entrySet()) {
|
||||
logger.debug("-- leave tableId: " + entry.getValue().getId());
|
||||
LOGGER.debug("-- leave tableId: " + entry.getValue().getId());
|
||||
TableManager.getInstance().leaveTable(userId, entry.getValue().getId());
|
||||
}
|
||||
tables.clear();
|
||||
logger.trace("REMOVE " + getName() + " Game sessions: " + gameSessions.size());
|
||||
LOGGER.trace("REMOVE " + getName() + " Game sessions: " + gameSessions.size());
|
||||
for (GameSessionPlayer gameSessionPlayer : gameSessions.values()) {
|
||||
logger.debug("-- kill game session of gameId: " + gameSessionPlayer.getGameId());
|
||||
LOGGER.debug("-- kill game session of gameId: " + gameSessionPlayer.getGameId());
|
||||
GameManager.getInstance().quitMatch(gameSessionPlayer.getGameId(), userId);
|
||||
gameSessionPlayer.quitGame();
|
||||
}
|
||||
gameSessions.clear();
|
||||
logger.trace("REMOVE " + getName() + " watched Games " + watchedGames.size());
|
||||
LOGGER.trace("REMOVE " + getName() + " watched Games " + watchedGames.size());
|
||||
for (UUID gameId : watchedGames) {
|
||||
GameManager.getInstance().stopWatching(gameId, userId);
|
||||
}
|
||||
watchedGames.clear();
|
||||
logger.trace("REMOVE " + getName() + " Chats ");
|
||||
LOGGER.trace("REMOVE " + getName() + " Chats ");
|
||||
ChatManager.getInstance().removeUser(userId, reason);
|
||||
}
|
||||
|
||||
|
@ -394,6 +399,12 @@ public class User {
|
|||
this.userData.update(userData);
|
||||
} else {
|
||||
this.userData = userData;
|
||||
this.userStats = UserStatsRepository.instance.getUser(this.userName);
|
||||
if (userStats != null) {
|
||||
this.userData.setHistory(userStatsToString(userStats.getProto()));
|
||||
} else {
|
||||
this.userData.setHistory("<new player>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -443,11 +454,11 @@ public class User {
|
|||
}
|
||||
} else {
|
||||
// can happen if tournamet has just ended
|
||||
logger.debug(getName() + " tournament player missing - tableId:" + table.getId(), null);
|
||||
LOGGER.debug(getName() + " tournament player missing - tableId:" + table.getId(), null);
|
||||
tablesToDelete.add(tableEntry.getKey());
|
||||
}
|
||||
} else {
|
||||
logger.error(getName() + " tournament key missing - tableId: " + table.getId(), null);
|
||||
LOGGER.error(getName() + " tournament key missing - tableId: " + table.getId(), null);
|
||||
}
|
||||
} else {
|
||||
switch (table.getState()) {
|
||||
|
@ -497,14 +508,6 @@ public class User {
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getInfo() {
|
||||
return info;
|
||||
}
|
||||
|
||||
public void setInfo(String Info) {
|
||||
this.info = Info;
|
||||
}
|
||||
|
||||
public void addGameWatchInfo(UUID gameId) {
|
||||
watchedGames.add(gameId);
|
||||
}
|
||||
|
@ -525,4 +528,96 @@ public class User {
|
|||
}
|
||||
}
|
||||
|
||||
// getUserStats returns the UserStats for this user. This caches the result, so if the stats is
|
||||
// updated call resetUserStats to refresh it.
|
||||
public UserStats getUserStats() {
|
||||
if (this.userStats == null) {
|
||||
resetUserStats();
|
||||
}
|
||||
return this.userStats;
|
||||
}
|
||||
|
||||
// resetUserStats loads UserStats from DB.
|
||||
public void resetUserStats() {
|
||||
this.userStats = UserStatsRepository.instance.getUser(this.userName);
|
||||
if (userData != null) {
|
||||
userData.setHistory(userStatsToString(userStats.getProto()));
|
||||
}
|
||||
}
|
||||
|
||||
public String getHistory() {
|
||||
if (userData != null) {
|
||||
return userData.getHistory();
|
||||
}
|
||||
return "<not available>";
|
||||
}
|
||||
|
||||
public static String userStatsToString(ResultProtos.UserStatsProto proto) {
|
||||
List<StringBuilder> builders = new ArrayList<>();
|
||||
if (proto.getMatches() > 0) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("Matches:");
|
||||
builder.append(proto.getMatches());
|
||||
List<String> quit = new ArrayList<>();
|
||||
if (proto.getMatchesIdleTimeout() > 0) {
|
||||
quit.add("I:" + Integer.toString(proto.getMatchesIdleTimeout()));
|
||||
}
|
||||
if (proto.getMatchesTimerTimeout() > 0) {
|
||||
quit.add("T:" + Integer.toString(proto.getMatchesTimerTimeout()));
|
||||
}
|
||||
if (proto.getMatchesQuit() > 0) {
|
||||
quit.add("Q:" + Integer.toString(proto.getMatchesQuit()));
|
||||
}
|
||||
if (quit.size() > 0) {
|
||||
builder.append(" (");
|
||||
joinStrings(builder, quit, " ");
|
||||
builder.append(")");
|
||||
}
|
||||
builders.add(builder);
|
||||
}
|
||||
if (proto.getTourneys() > 0) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("Tourneys:");
|
||||
builder.append(proto.getTourneys());
|
||||
List<String> quit = new ArrayList<>();
|
||||
if (proto.getTourneysQuitDuringDrafting() > 0) {
|
||||
quit.add("D:" + Integer.toString(proto.getTourneysQuitDuringDrafting()));
|
||||
}
|
||||
if (proto.getTourneysQuitDuringConstruction() > 0) {
|
||||
quit.add("C:" + Integer.toString(proto.getTourneysQuitDuringConstruction()));
|
||||
}
|
||||
if (proto.getTourneysQuitDuringRound() > 0) {
|
||||
quit.add("R:" + Integer.toString(proto.getTourneysQuitDuringRound()));
|
||||
}
|
||||
if (quit.size() > 0) {
|
||||
builder.append(" (");
|
||||
joinStrings(builder, quit, " ");
|
||||
builder.append(")");
|
||||
}
|
||||
builders.add(builder);
|
||||
}
|
||||
return joinBuilders(builders);
|
||||
}
|
||||
|
||||
private static String joinBuilders(List<StringBuilder> builders) {
|
||||
if (builders.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
StringBuilder builder = builders.get(0);
|
||||
for (int i = 1; i < builders.size(); ++i) {
|
||||
builder.append(" ");
|
||||
builder.append(builders.get(i));
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static void joinStrings(StringBuilder joined, List<String> strings, String separator) {
|
||||
for (int i = 0; i < strings.size(); ++i) {
|
||||
if (i > 0) {
|
||||
joined.append(separator);
|
||||
}
|
||||
joined.append(strings.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
|
@ -20,7 +20,7 @@
|
|||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
|
@ -38,6 +38,8 @@ import java.util.concurrent.Executors;
|
|||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import mage.server.User.UserState;
|
||||
import mage.server.record.UserStats;
|
||||
import mage.server.record.UserStatsRepository;
|
||||
import mage.server.util.ThreadExecutor;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
|
@ -45,7 +47,7 @@ import org.apache.log4j.Logger;
|
|||
*
|
||||
* manages users - if a user is disconnected and 10 minutes have passed with no
|
||||
* activity the user is removed
|
||||
*
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class UserManager {
|
||||
|
@ -55,7 +57,8 @@ public class UserManager {
|
|||
private static final Logger logger = Logger.getLogger(UserManager.class);
|
||||
|
||||
private final ConcurrentHashMap<UUID, User> users = new ConcurrentHashMap<>();
|
||||
|
||||
private final ConcurrentHashMap<String, User> usersByName = new ConcurrentHashMap<>();
|
||||
|
||||
private static final ExecutorService callExecutor = ThreadExecutor.getInstance().getCallExecutor();
|
||||
|
||||
private static final UserManager INSTANCE = new UserManager();
|
||||
|
@ -63,8 +66,8 @@ public class UserManager {
|
|||
public static UserManager getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private UserManager() {
|
||||
|
||||
private UserManager() {
|
||||
expireExecutor.scheduleAtFixedRate(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -74,11 +77,12 @@ public class UserManager {
|
|||
}
|
||||
|
||||
public User createUser(String userName, String host) {
|
||||
if (findUser(userName) != null) {
|
||||
if (getUserByName(userName) != null) {
|
||||
return null; //user already exists
|
||||
}
|
||||
User user = new User(userName, host);
|
||||
users.put(user.getId(), user);
|
||||
usersByName.put(userName, user);
|
||||
return user;
|
||||
}
|
||||
|
||||
|
@ -89,13 +93,8 @@ public class UserManager {
|
|||
return null;
|
||||
}
|
||||
|
||||
public User findUser(String userName) {
|
||||
for (User user: users.values()) {
|
||||
if (user.getName().equals(userName)) {
|
||||
return user;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
public User getUserByName(String userName) {
|
||||
return usersByName.get(userName);
|
||||
}
|
||||
|
||||
public Collection<User> getUsers() {
|
||||
|
@ -116,7 +115,7 @@ public class UserManager {
|
|||
public void disconnect(UUID userId, DisconnectReason reason) {
|
||||
if (userId != null) {
|
||||
User user = users.get(userId);
|
||||
if (user != null) {
|
||||
if (user != null) {
|
||||
user.setSessionId(""); // Session will be set again with new id if user reconnects
|
||||
}
|
||||
ChatManager.getInstance().removeUser(userId, reason);
|
||||
|
@ -126,43 +125,44 @@ public class UserManager {
|
|||
public boolean isAdmin(UUID userId) {
|
||||
if (userId != null) {
|
||||
User user = users.get(userId);
|
||||
if (user != null) {
|
||||
if (user != null) {
|
||||
return user.getName().equals("Admin");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void removeUser(final UUID userId, final DisconnectReason reason) {
|
||||
public void removeUser(final UUID userId, final DisconnectReason reason) {
|
||||
if (userId != null) {
|
||||
final User user = users.get(userId);
|
||||
if (user != null) {
|
||||
callExecutor.execute(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
logger.info("USER REMOVE - " + user.getName() + " (" + reason.toString() + ") userId: " + userId);
|
||||
user.remove(reason);
|
||||
logger.debug("USER REMOVE END - " + user.getName());
|
||||
} catch (Exception ex) {
|
||||
handleException(ex);
|
||||
} finally {
|
||||
users.remove(userId);
|
||||
}
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
logger.info("USER REMOVE - " + user.getName() + " (" + reason.toString() + ") userId: " + userId);
|
||||
user.remove(reason);
|
||||
logger.debug("USER REMOVE END - " + user.getName());
|
||||
} catch (Exception ex) {
|
||||
handleException(ex);
|
||||
} finally {
|
||||
users.remove(userId);
|
||||
usersByName.remove(user.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
logger.warn("Trying to remove userId: " + userId + " - but it does not exist.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean extendUserSession(UUID userId, String pingInfo) {
|
||||
if (userId != null) {
|
||||
User user = users.get(userId);
|
||||
if (user != null) {
|
||||
if (user != null) {
|
||||
user.updateLastActivity(pingInfo);
|
||||
return true;
|
||||
}
|
||||
|
@ -171,7 +171,8 @@ public class UserManager {
|
|||
}
|
||||
|
||||
/**
|
||||
* Is the connection lost for more than 3 minutes, the user will be removed (within 3 minutes the user can reconnect)
|
||||
* Is the connection lost for more than 3 minutes, the user will be removed
|
||||
* (within 3 minutes the user can reconnect)
|
||||
*/
|
||||
private void checkExpired() {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
|
@ -187,13 +188,39 @@ public class UserManager {
|
|||
|
||||
public void handleException(Exception ex) {
|
||||
if (ex != null) {
|
||||
logger.fatal("User manager exception " + (ex.getMessage() == null ? "null":ex.getMessage()));
|
||||
logger.fatal("User manager exception " + (ex.getMessage() == null ? "null" : ex.getMessage()));
|
||||
if (ex.getCause() != null) {
|
||||
logger.debug("- Cause: " + (ex.getCause().getMessage() == null ? "null":ex.getCause().getMessage()));
|
||||
logger.debug("- Cause: " + (ex.getCause().getMessage() == null ? "null" : ex.getCause().getMessage()));
|
||||
}
|
||||
ex.printStackTrace();
|
||||
}else {
|
||||
} else {
|
||||
logger.fatal("User manager exception - null");
|
||||
}
|
||||
}
|
||||
|
||||
public String getUserHistory(String userName) {
|
||||
User user = getUserByName(userName);
|
||||
if (user == null) {
|
||||
UserStats userStats = UserStatsRepository.instance.getUser(userName);
|
||||
if (userStats == null) {
|
||||
return "User " + userName + " not found";
|
||||
}
|
||||
return User.userStatsToString(userStats.getProto());
|
||||
}
|
||||
return "History of user " + userName + ": " + user.getUserData().getHistory();
|
||||
}
|
||||
|
||||
public void updateUserHistory() {
|
||||
callExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (String updatedUser : UserStatsRepository.instance.updateUserStats()) {
|
||||
User user = getUserByName(updatedUser);
|
||||
if (user != null) {
|
||||
user.resetUserStats();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,11 +100,7 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
|
|||
if (table.getState() != TableState.FINISHED) {
|
||||
tableList.add(new TableView(table));
|
||||
} else if (matchList.size() < 50) {
|
||||
if (table.isTournament()) {
|
||||
matchList.add(new MatchView(table));
|
||||
} else {
|
||||
matchList.add(new MatchView(table));
|
||||
}
|
||||
matchList.add(new MatchView(table));
|
||||
} else {
|
||||
// more since 50 matches finished since this match so remove it
|
||||
if (table.isTournament()) {
|
||||
|
@ -118,13 +114,13 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
|
|||
List<UsersView> users = new ArrayList<>();
|
||||
for (User user : UserManager.getInstance().getUsers()) {
|
||||
try {
|
||||
users.add(new UsersView(user.getUserData().getFlagName(), user.getName(), user.getInfo(), user.getGameInfo(), user.getPingInfo()));
|
||||
users.add(new UsersView(user.getUserData().getFlagName(), user.getName(), user.getHistory(), user.getGameInfo(), user.getPingInfo()));
|
||||
} catch (Exception ex) {
|
||||
logger.fatal("User update exception: " + user.getName() + " - " + ex.toString(), ex);
|
||||
users.add(new UsersView(
|
||||
(user.getUserData() != null && user.getUserData().getFlagName() != null) ? user.getUserData().getFlagName() : "world",
|
||||
user.getName() != null ? user.getName() : "<no name>",
|
||||
user.getInfo() != null ? user.getInfo() : "<no info>",
|
||||
user.getHistory() != null ? user.getHistory() : "<no history>",
|
||||
"[exception]",
|
||||
user.getPingInfo() != null ? user.getPingInfo() : "<no ping>"));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package mage.server.record;
|
||||
|
||||
import com.j256.ormlite.field.DataType;
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
import mage.game.result.ResultProtos.TableProto;
|
||||
import org.mage.mage.shaded.protobuf.InvalidProtocolBufferException;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
@DatabaseTable(tableName = "table_history")
|
||||
public class TableRecord {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(TableRecord.class);
|
||||
|
||||
@DatabaseField(dataType = DataType.BYTE_ARRAY, indexName = "proto_index", unique = true)
|
||||
protected byte[] proto;
|
||||
|
||||
@DatabaseField(indexName = "end_time_ms")
|
||||
protected long endTimeMs;
|
||||
|
||||
public TableRecord() {
|
||||
}
|
||||
|
||||
public TableRecord(TableProto proto, long endTimeMs) {
|
||||
this.proto = proto.toByteArray();
|
||||
this.endTimeMs = endTimeMs;
|
||||
}
|
||||
|
||||
public TableProto getProto() {
|
||||
try {
|
||||
return TableProto.parseFrom(this.proto);
|
||||
} catch (InvalidProtocolBufferException ex) {
|
||||
logger.error("Failed to parse serialized proto", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package mage.server.record;
|
||||
|
||||
import com.j256.ormlite.dao.Dao;
|
||||
import com.j256.ormlite.dao.DaoManager;
|
||||
import com.j256.ormlite.jdbc.JdbcConnectionSource;
|
||||
import com.j256.ormlite.stmt.QueryBuilder;
|
||||
import com.j256.ormlite.support.ConnectionSource;
|
||||
import com.j256.ormlite.support.DatabaseConnection;
|
||||
import com.j256.ormlite.table.TableUtils;
|
||||
import java.io.File;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import mage.cards.repository.RepositoryUtil;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
public enum TableRecordRepository {
|
||||
|
||||
instance;
|
||||
|
||||
private static final String JDBC_URL = "jdbc:sqlite:./db/table_record.db";
|
||||
private static final String VERSION_ENTITY_NAME = "table_record";
|
||||
// raise this if db structure was changed
|
||||
private static final long DB_VERSION = 0;
|
||||
|
||||
private Dao<TableRecord, Object> dao;
|
||||
|
||||
private TableRecordRepository() {
|
||||
File file = new File("db");
|
||||
if (!file.exists()) {
|
||||
file.mkdirs();
|
||||
}
|
||||
try {
|
||||
ConnectionSource connectionSource = new JdbcConnectionSource(JDBC_URL);
|
||||
boolean obsolete = RepositoryUtil.isDatabaseObsolete(connectionSource, VERSION_ENTITY_NAME, DB_VERSION);
|
||||
|
||||
if (obsolete) {
|
||||
TableUtils.dropTable(connectionSource, TableRecord.class, true);
|
||||
}
|
||||
|
||||
TableUtils.createTableIfNotExists(connectionSource, TableRecord.class);
|
||||
dao = DaoManager.createDao(connectionSource, TableRecord.class);
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(TableRecordRepository.class).error("Error creating table_record repository - ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void add(TableRecord tableHistory) {
|
||||
try {
|
||||
dao.create(tableHistory);
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(TableRecordRepository.class).error("Error adding a table_record to DB - ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public List<TableRecord> getAfter(long endTimeMs) {
|
||||
try {
|
||||
QueryBuilder<TableRecord, Object> qb = dao.queryBuilder();
|
||||
qb.where().gt("endTimeMs", endTimeMs);
|
||||
qb.orderBy("endTimeMs", true);
|
||||
return dao.query(qb.prepare());
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(TableRecordRepository.class).error("Error getting table_records from DB - ", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void closeDB() {
|
||||
try {
|
||||
if (dao != null && dao.getConnectionSource() != null) {
|
||||
DatabaseConnection conn = dao.getConnectionSource().getReadWriteConnection();
|
||||
conn.executeStatement("shutdown compact", 0);
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(TableRecordRepository.class).error("Error closing table_record repository - ", ex);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package mage.server.record;
|
||||
|
||||
import mage.game.Table;
|
||||
import mage.game.Table.TableRecorder;
|
||||
import mage.game.result.ResultProtos.TableProto;
|
||||
import mage.server.UserManager;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
public class TableRecorderImpl implements TableRecorder {
|
||||
|
||||
private static TableRecorderImpl INSTANCE = new TableRecorderImpl();
|
||||
private static final Logger logger = Logger.getLogger(TableRecorderImpl.class);
|
||||
|
||||
public static TableRecorderImpl getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public void record(Table table) {
|
||||
TableProto proto = table.toProto();
|
||||
TableRecordRepository.instance.add(new TableRecord(proto, proto.getEndTimeMs()));
|
||||
UserManager.getInstance().updateUserHistory();
|
||||
}
|
||||
}
|
45
Mage.Server/src/main/java/mage/server/record/UserStats.java
Normal file
45
Mage.Server/src/main/java/mage/server/record/UserStats.java
Normal file
|
@ -0,0 +1,45 @@
|
|||
package mage.server.record;
|
||||
|
||||
import com.j256.ormlite.field.DataType;
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
import mage.game.result.ResultProtos.UserStatsProto;
|
||||
import org.mage.mage.shaded.protobuf.InvalidProtocolBufferException;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
@DatabaseTable(tableName = "user_stats")
|
||||
public class UserStats {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(TableRecord.class);
|
||||
|
||||
@DatabaseField(indexName = "user_name_index", unique = true, id = true)
|
||||
protected String userName;
|
||||
|
||||
@DatabaseField(dataType = DataType.BYTE_ARRAY)
|
||||
protected byte[] proto;
|
||||
|
||||
@DatabaseField(indexName = "end_time_ms_index")
|
||||
protected long endTimeMs;
|
||||
|
||||
public UserStats() {
|
||||
}
|
||||
|
||||
public UserStats(UserStatsProto proto, long endTimeMs) {
|
||||
this.userName = proto.getName();
|
||||
this.proto = proto.toByteArray();
|
||||
this.endTimeMs = endTimeMs;
|
||||
}
|
||||
|
||||
public UserStatsProto getProto() {
|
||||
try {
|
||||
return UserStatsProto.parseFrom(this.proto);
|
||||
} catch (InvalidProtocolBufferException ex) {
|
||||
logger.error("Failed to parse serialized proto", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public long getEndTimeMs() {
|
||||
return this.endTimeMs;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,187 @@
|
|||
package mage.server.record;
|
||||
|
||||
import com.j256.ormlite.dao.Dao;
|
||||
import com.j256.ormlite.dao.DaoManager;
|
||||
import com.j256.ormlite.jdbc.JdbcConnectionSource;
|
||||
import com.j256.ormlite.stmt.QueryBuilder;
|
||||
import com.j256.ormlite.support.ConnectionSource;
|
||||
import com.j256.ormlite.support.DatabaseConnection;
|
||||
import com.j256.ormlite.table.TableUtils;
|
||||
import java.io.File;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import mage.cards.repository.RepositoryUtil;
|
||||
import mage.game.result.ResultProtos;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
public enum UserStatsRepository {
|
||||
|
||||
instance;
|
||||
|
||||
private static final String JDBC_URL = "jdbc:sqlite:./db/user_stats.db";
|
||||
private static final String VERSION_ENTITY_NAME = "user_stats";
|
||||
// raise this if db structure was changed
|
||||
private static final long DB_VERSION = 0;
|
||||
|
||||
private Dao<UserStats, Object> dao;
|
||||
|
||||
private UserStatsRepository() {
|
||||
File file = new File("db");
|
||||
if (!file.exists()) {
|
||||
file.mkdirs();
|
||||
}
|
||||
try {
|
||||
ConnectionSource connectionSource = new JdbcConnectionSource(JDBC_URL);
|
||||
boolean obsolete = RepositoryUtil.isDatabaseObsolete(connectionSource, VERSION_ENTITY_NAME, DB_VERSION);
|
||||
|
||||
if (obsolete) {
|
||||
TableUtils.dropTable(connectionSource, UserStats.class, true);
|
||||
}
|
||||
|
||||
TableUtils.createTableIfNotExists(connectionSource, UserStats.class);
|
||||
dao = DaoManager.createDao(connectionSource, UserStats.class);
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(UserStatsRepository.class).error("Error creating user_stats repository - ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void add(UserStats userStats) {
|
||||
try {
|
||||
dao.create(userStats);
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(UserStatsRepository.class).error("Error adding a user_stats to DB - ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void update(UserStats userStats) {
|
||||
try {
|
||||
dao.update(userStats);
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(UserStatsRepository.class).error("Error updating a user_stats in DB - ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public UserStats getUser(String userName) {
|
||||
try {
|
||||
QueryBuilder<UserStats, Object> qb = dao.queryBuilder();
|
||||
qb.where().eq("userName", userName);
|
||||
List<UserStats> users = dao.query(qb.prepare());
|
||||
if (users.size() == 1) {
|
||||
return users.get(0);
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(UserStatsRepository.class).error("Error getting a user from DB - ", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<UserStats> getAllUsers() {
|
||||
try {
|
||||
QueryBuilder<UserStats, Object> qb = dao.queryBuilder();
|
||||
return dao.query(qb.prepare());
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(UserStatsRepository.class).error("Error getting all users from DB - ", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public long getLatestEndTimeMs() {
|
||||
try {
|
||||
QueryBuilder<UserStats, Object> qb = dao.queryBuilder();
|
||||
qb.orderBy("endTimeMs", false).limit(1);
|
||||
List<UserStats> users = dao.query(qb.prepare());
|
||||
if (users.size() == 1) {
|
||||
return users.get(0).getEndTimeMs();
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(UserStatsRepository.class).error("Error getting the latest end time from DB - ", ex);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// updateUserStats reads tables finished after the last DB update and reflects it to the DB.
|
||||
// It returns the list of user names that are upated.
|
||||
public List<String> updateUserStats() {
|
||||
HashSet<String> updatedUsers = new HashSet();
|
||||
// Lock the DB so that no other updateUserStats runs at the same time.
|
||||
synchronized(this) {
|
||||
long latestEndTimeMs = this.getLatestEndTimeMs();
|
||||
List<TableRecord> records = TableRecordRepository.instance.getAfter(latestEndTimeMs);
|
||||
for (TableRecord record : records) {
|
||||
ResultProtos.TableProto table = record.getProto();
|
||||
if (table.getControllerName().equals("System")) {
|
||||
// This is a sub table within a tournament, so it's already handled by the main
|
||||
// tournament table.
|
||||
continue;
|
||||
}
|
||||
if (table.hasMatch()) {
|
||||
ResultProtos.MatchProto match = table.getMatch();
|
||||
for (ResultProtos.MatchPlayerProto player : match.getPlayersList()) {
|
||||
UserStats userStats = this.getUser(player.getName());
|
||||
ResultProtos.UserStatsProto proto = userStats != null ? userStats.getProto()
|
||||
: ResultProtos.UserStatsProto.newBuilder().setName(player.getName()).build();
|
||||
ResultProtos.UserStatsProto.Builder builder = ResultProtos.UserStatsProto.newBuilder(proto)
|
||||
.setMatches(proto.getMatches() + 1);
|
||||
switch (player.getQuit()) {
|
||||
case IDLE_TIMEOUT:
|
||||
builder.setMatchesIdleTimeout(proto.getMatchesIdleTimeout() + 1);
|
||||
break;
|
||||
case TIMER_TIMEOUT:
|
||||
builder.setMatchesTimerTimeout(proto.getMatchesTimerTimeout() + 1);
|
||||
break;
|
||||
case QUIT:
|
||||
builder.setMatchesQuit(proto.getMatchesQuit() + 1);
|
||||
break;
|
||||
}
|
||||
if (userStats == null) {
|
||||
this.add(new UserStats(builder.build(), table.getEndTimeMs()));
|
||||
} else {
|
||||
this.update(new UserStats(builder.build(), table.getEndTimeMs()));
|
||||
}
|
||||
updatedUsers.add(player.getName());
|
||||
}
|
||||
} else if (table.hasTourney()) {
|
||||
ResultProtos.TourneyProto tourney = table.getTourney();
|
||||
for (ResultProtos.TourneyPlayerProto player : tourney.getPlayersList()) {
|
||||
UserStats userStats = this.getUser(player.getName());
|
||||
ResultProtos.UserStatsProto proto = userStats != null ? userStats.getProto()
|
||||
: ResultProtos.UserStatsProto.newBuilder().setName(player.getName()).build();
|
||||
ResultProtos.UserStatsProto.Builder builder = ResultProtos.UserStatsProto.newBuilder(proto)
|
||||
.setTourneys(proto.getTourneys() + 1);
|
||||
switch (player.getQuit()) {
|
||||
case DURING_ROUND:
|
||||
builder.setTourneysQuitDuringRound(proto.getTourneysQuitDuringRound() + 1);
|
||||
break;
|
||||
case DURING_DRAFTING:
|
||||
builder.setTourneysQuitDuringDrafting(proto.getTourneysQuitDuringDrafting() + 1);
|
||||
break;
|
||||
case DURING_CONSTRUCTION:
|
||||
builder.setTourneysQuitDuringConstruction(proto.getTourneysQuitDuringConstruction() + 1);
|
||||
break;
|
||||
}
|
||||
if (userStats == null) {
|
||||
this.add(new UserStats(builder.build(), table.getEndTimeMs()));
|
||||
} else {
|
||||
this.update(new UserStats(builder.build(), table.getEndTimeMs()));
|
||||
}
|
||||
updatedUsers.add(player.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ArrayList(updatedUsers);
|
||||
}
|
||||
|
||||
public void closeDB() {
|
||||
try {
|
||||
if (dao != null && dao.getConnectionSource() != null) {
|
||||
DatabaseConnection conn = dao.getConnectionSource().getReadWriteConnection();
|
||||
conn.executeStatement("shutdown compact", 0);
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(UserStatsRepository.class).error("Error closing user_stats repository - ", ex);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,8 @@ public interface LogKeys {
|
|||
|
||||
String KEY_GAME_STARTED = "gameStarted";
|
||||
|
||||
String KEY_USER_REGISTERED = "userRegistered";
|
||||
|
||||
String KEY_USER_CONNECTED = "userConnected";
|
||||
|
||||
String KEY_ADMIN_CONNECTED = "adminConnected";
|
||||
|
|
|
@ -43,6 +43,7 @@ import mage.game.events.TableEvent;
|
|||
import static mage.game.events.TableEvent.EventType.CONSTRUCT;
|
||||
import mage.game.match.Match;
|
||||
import mage.game.match.MatchOptions;
|
||||
import mage.game.result.ResultProtos.TourneyQuitStatus;
|
||||
import mage.game.tournament.Tournament;
|
||||
import mage.game.tournament.TournamentPairing;
|
||||
import mage.game.tournament.TournamentPlayer;
|
||||
|
@ -351,31 +352,34 @@ public class TournamentController {
|
|||
tournamentSession.setKilled();
|
||||
if (tournamentPlayer.isInTournament()) {
|
||||
String info;
|
||||
TourneyQuitStatus status;
|
||||
if (tournament.isDoneConstructing()) {
|
||||
info = new StringBuilder("during round ").append(tournament.getRounds().size()).toString();
|
||||
// quit active matches of that tournament
|
||||
TableManager.getInstance().userQuitTournamentSubTables(tournament.getId(), userId);
|
||||
} else {
|
||||
if (tournamentPlayer.getState().equals(TournamentPlayerState.DRAFTING)) {
|
||||
info = "during Draft phase";
|
||||
if (!checkToReplaceDraftPlayerByAi(userId, tournamentPlayer)) {
|
||||
this.abortDraftTournament();
|
||||
} else {
|
||||
DraftController draftController = DraftManager.getInstance().getController(tableId);
|
||||
if (draftController != null) {
|
||||
DraftSession draftSession = draftController.getDraftSession(playerId);
|
||||
if (draftSession != null) {
|
||||
DraftManager.getInstance().kill(draftSession.getDraftId(), userId);
|
||||
}
|
||||
status = TourneyQuitStatus.DURING_ROUND;
|
||||
} else if (tournamentPlayer.getState().equals(TournamentPlayerState.DRAFTING)) {
|
||||
info = "during Draft phase";
|
||||
if (!checkToReplaceDraftPlayerByAi(userId, tournamentPlayer)) {
|
||||
this.abortDraftTournament();
|
||||
} else {
|
||||
DraftController draftController = DraftManager.getInstance().getController(tableId);
|
||||
if (draftController != null) {
|
||||
DraftSession draftSession = draftController.getDraftSession(playerId);
|
||||
if (draftSession != null) {
|
||||
DraftManager.getInstance().kill(draftSession.getDraftId(), userId);
|
||||
}
|
||||
}
|
||||
} else if (tournamentPlayer.getState().equals(TournamentPlayerState.CONSTRUCTING)) {
|
||||
info = "during Construction phase";
|
||||
} else {
|
||||
info = "";
|
||||
}
|
||||
status = TourneyQuitStatus.DURING_DRAFTING;
|
||||
} else if (tournamentPlayer.getState().equals(TournamentPlayerState.CONSTRUCTING)) {
|
||||
info = "during Construction phase";
|
||||
status = TourneyQuitStatus.DURING_CONSTRUCTION;
|
||||
} else {
|
||||
info = "";
|
||||
status = TourneyQuitStatus.NO_TOURNEY_QUIT;
|
||||
}
|
||||
tournamentPlayer.setQuit(info);
|
||||
tournamentPlayer.setQuit(info, status);
|
||||
tournament.quit(playerId);
|
||||
tournamentSession.quit();
|
||||
ChatManager.getInstance().broadcast(chatId, "", tournamentPlayer.getPlayer().getLogName() + " has quit the tournament", MessageColor.BLACK, true, MessageType.STATUS, SoundToPlay.PlayerQuitTournament);
|
||||
|
|
|
@ -94,7 +94,7 @@ public class ConfigSettings {
|
|||
public int getBacklogSize() {
|
||||
return config.getServer().getBacklogSize().intValue();
|
||||
}
|
||||
|
||||
|
||||
public int getMaxGameThreads() {
|
||||
return config.getServer().getMaxGameThreads().intValue();
|
||||
}
|
||||
|
@ -111,17 +111,61 @@ public class ConfigSettings {
|
|||
return config.getServer().getMaxUserNameLength().intValue();
|
||||
}
|
||||
|
||||
public String getUserNamePattern() {
|
||||
return config.getServer().getUserNamePattern();
|
||||
public String getInvalidUserNamePattern() {
|
||||
return config.getServer().getInvalidUserNamePattern();
|
||||
}
|
||||
|
||||
|
||||
public int getMinPasswordLength() {
|
||||
return config.getServer().getMinPasswordLength().intValue();
|
||||
}
|
||||
|
||||
public int getMaxPasswordLength() {
|
||||
return config.getServer().getMaxPasswordLength().intValue();
|
||||
}
|
||||
|
||||
public String getMaxAiOpponents() {
|
||||
return config.getServer().getMaxAiOpponents();
|
||||
}
|
||||
|
||||
public Boolean isSaveGameActivated() {
|
||||
return config.getServer().isSaveGameActivated();
|
||||
}
|
||||
return config.getServer().isSaveGameActivated();
|
||||
}
|
||||
|
||||
public Boolean isAuthenticationActivated() {
|
||||
return config.getServer().isAuthenticationActivated();
|
||||
}
|
||||
|
||||
public String getGoogleAccount() {
|
||||
return config.getServer().getGoogleAccount();
|
||||
}
|
||||
|
||||
public String getMailgunApiKey() {
|
||||
return config.getServer().getMailgunApiKey();
|
||||
}
|
||||
|
||||
public String getMailgunDomain() {
|
||||
return config.getServer().getMailgunDomain();
|
||||
}
|
||||
|
||||
public String getMailSmtpHost() {
|
||||
return config.getServer().getMailSmtpHost();
|
||||
}
|
||||
|
||||
public String getMailSmtpPort() {
|
||||
return config.getServer().getMailSmtpPort();
|
||||
}
|
||||
|
||||
public String getMailUser() {
|
||||
return config.getServer().getMailUser();
|
||||
}
|
||||
|
||||
public String getMailPassword() {
|
||||
return config.getServer().getMailPassword();
|
||||
}
|
||||
|
||||
public String getMailFromAddress() {
|
||||
return config.getServer().getMailFromAddress();
|
||||
}
|
||||
|
||||
public List<Plugin> getPlayerTypes() {
|
||||
return config.getPlayerTypes().getPlayerType();
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Config.xsd">
|
||||
<server serverAddress="0.0.0.0"
|
||||
serverName="mage-server"
|
||||
port="17171"
|
||||
secondaryBindPort="-1"
|
||||
backlogSize="200"
|
||||
numAcceptThreads="2"
|
||||
maxPoolSize="300"
|
||||
leasePeriod="5000"
|
||||
<server serverAddress="0.0.0.0"
|
||||
serverName="mage-server"
|
||||
port="17171"
|
||||
secondaryBindPort="-1"
|
||||
backlogSize="200"
|
||||
numAcceptThreads="2"
|
||||
maxPoolSize="300"
|
||||
leasePeriod="5000"
|
||||
maxGameThreads="10"
|
||||
maxSecondsIdle="600"
|
||||
minUserNameLength="3"
|
||||
|
@ -16,6 +16,8 @@
|
|||
userNamePattern="[^a-z0-9_]"
|
||||
maxAiOpponents="15"
|
||||
saveGameActivated="false"
|
||||
authenticationActivated="false"
|
||||
googleAccount=""
|
||||
/>
|
||||
<playerTypes>
|
||||
<playerType name="Human" jar="Mage.Player.Human.jar" className="mage.player.human.HumanPlayer"/>
|
||||
|
|
|
@ -2,19 +2,19 @@
|
|||
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
|
||||
<xs:element name="config">
|
||||
<xs:element name="config">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref="server"/>
|
||||
<xs:element ref="playerTypes"/>
|
||||
<xs:element ref="gameTypes"/>
|
||||
<xs:element ref="tournamentTypes"/>
|
||||
<xs:element ref="draftCubes"/>
|
||||
<xs:element ref="draftCubes"/>
|
||||
<xs:element ref="deckTypes"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
|
||||
<xs:element name="server">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="serverAddress" type="xs:string" use="required"/>
|
||||
|
@ -22,16 +22,27 @@
|
|||
<xs:attribute name="port" type="xs:positiveInteger" use="required"/>
|
||||
<xs:attribute name="maxGameThreads" type="xs:positiveInteger" use="required"/>
|
||||
<xs:attribute name="maxSecondsIdle" type="xs:positiveInteger" use="required"/>
|
||||
<xs:attribute name="secondaryBindPort" type="xs:integer" use="required"/>
|
||||
<xs:attribute name="backlogSize" type="xs:positiveInteger" use="required"/>
|
||||
<xs:attribute name="numAcceptThreads" type="xs:positiveInteger" use="required"/>
|
||||
<xs:attribute name="maxPoolSize" type="xs:positiveInteger" use="required"/>
|
||||
<xs:attribute name="leasePeriod" type="xs:positiveInteger" use="required"/>
|
||||
<xs:attribute name="minUserNameLength" type="xs:positiveInteger" use="required"/>
|
||||
<xs:attribute name="maxUserNameLength" type="xs:positiveInteger" use="required"/>
|
||||
<xs:attribute name="userNamePattern" type="xs:string" use="required"/>
|
||||
<xs:attribute name="maxAiOpponents" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="saveGameActivated" type="xs:boolean" use="optional"/>
|
||||
<xs:attribute name="secondaryBindPort" type="xs:integer" use="required"/>
|
||||
<xs:attribute name="backlogSize" type="xs:positiveInteger" use="required"/>
|
||||
<xs:attribute name="numAcceptThreads" type="xs:positiveInteger" use="required"/>
|
||||
<xs:attribute name="maxPoolSize" type="xs:positiveInteger" use="required"/>
|
||||
<xs:attribute name="leasePeriod" type="xs:positiveInteger" use="required"/>
|
||||
<xs:attribute name="minUserNameLength" type="xs:positiveInteger" use="required"/>
|
||||
<xs:attribute name="maxUserNameLength" type="xs:positiveInteger" use="required"/>
|
||||
<xs:attribute name="invalidUserNamePattern" type="xs:string" use="required"/>
|
||||
<xs:attribute name="minPasswordLength" type="xs:positiveInteger" use="required"/>
|
||||
<xs:attribute name="maxPasswordLength" type="xs:positiveInteger" use="required"/>
|
||||
<xs:attribute name="maxAiOpponents" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="saveGameActivated" type="xs:boolean" use="optional"/>
|
||||
<xs:attribute name="authenticationActivated" type="xs:boolean" use="optional"/>
|
||||
<xs:attribute name="googleAccount" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="mailgunApiKey" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="mailgunDomain" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="mailSmtpHost" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="mailSmtpPort" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="mailUser" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="mailPassword" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="mailFromAddress" type="xs:string" use="optional"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
|
@ -56,7 +67,7 @@
|
|||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
|
||||
<xs:element name="gameTypes">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-root</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>1.4.8</version>
|
||||
</parent>
|
||||
|
||||
<groupId>org.mage</groupId>
|
||||
|
|
|
@ -48,7 +48,7 @@ public class BattleForZendikar extends ExpansionSet {
|
|||
return fINSTANCE;
|
||||
}
|
||||
|
||||
List<CardInfo> savedSpecialLand = new ArrayList<>();
|
||||
protected final List<CardInfo> savedSpecialLand = new ArrayList<>();
|
||||
|
||||
private BattleForZendikar() {
|
||||
super("Battle for Zendikar", "BFZ", "mage.sets.battleforzendikar", new GregorianCalendar(2015, 10, 2).getTime(), SetType.EXPANSION);
|
||||
|
@ -56,25 +56,28 @@ public class BattleForZendikar extends ExpansionSet {
|
|||
this.hasBoosters = true;
|
||||
this.hasBasicLands = true;
|
||||
this.numBoosterLands = 1;
|
||||
this.ratioBoosterSpecialLand = 20; // Approximately as rare as opening a foil mythic = 8 * 6 = ~every 48th booster includes one
|
||||
// I set it to 20 to get it more often
|
||||
this.numBoosterCommon = 10;
|
||||
this.numBoosterUncommon = 3;
|
||||
this.numBoosterRare = 1;
|
||||
this.ratioBoosterMythic = 8;
|
||||
this.numBoosterSpecial = 0;
|
||||
|
||||
// Zendikar Expeditions 1-25
|
||||
// Approximately as rare as opening a foil mythic = 8 * 6 = ~every 48th booster includes one.
|
||||
// I set it to 20 to get it more often
|
||||
this.ratioBoosterSpecialLand = 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CardInfo> getSpecialLand() {
|
||||
List<CardInfo> specialLand = new ArrayList<>();
|
||||
if (savedSpecialLand.isEmpty()) {
|
||||
CardCriteria criteria = new CardCriteria();
|
||||
criteria.setCodes("EXP");
|
||||
specialLand.addAll(CardRepository.instance.findCards(criteria));
|
||||
criteria.minCardNumber(1);
|
||||
criteria.maxCardNumber(25);
|
||||
savedSpecialLand.addAll(CardRepository.instance.findCards(criteria));
|
||||
}
|
||||
|
||||
specialLand.addAll(savedSpecialLand);
|
||||
return specialLand;
|
||||
return new ArrayList<>(savedSpecialLand);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,14 @@
|
|||
*/
|
||||
package mage.sets;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.List;
|
||||
|
||||
import mage.cards.ExpansionSet;
|
||||
import mage.cards.repository.CardCriteria;
|
||||
import mage.cards.repository.CardInfo;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.constants.SetType;
|
||||
|
||||
/**
|
||||
|
@ -21,9 +27,12 @@ public class OathOfTheGatewatch extends ExpansionSet {
|
|||
return fINSTANCE;
|
||||
}
|
||||
|
||||
protected final List<CardInfo> savedSpecialLand = new ArrayList<>();
|
||||
|
||||
private OathOfTheGatewatch() {
|
||||
super("Oath of the Gatewatch", "OGW", "mage.sets.oathofthegatewatch", new GregorianCalendar(2016, 1, 22).getTime(), SetType.EXPANSION);
|
||||
this.blockName = "Battle for Zendikar";
|
||||
this.parentSet = BattleForZendikar.getInstance();
|
||||
this.hasBoosters = true;
|
||||
this.hasBasicLands = false;
|
||||
this.numBoosterLands = 1;
|
||||
|
@ -31,5 +40,21 @@ public class OathOfTheGatewatch extends ExpansionSet {
|
|||
this.numBoosterUncommon = 3;
|
||||
this.numBoosterRare = 1;
|
||||
this.ratioBoosterMythic = 8;
|
||||
|
||||
// Zendikar Expeditions 26-45
|
||||
this.ratioBoosterSpecialLand = 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CardInfo> getSpecialLand() {
|
||||
if (savedSpecialLand.isEmpty()) {
|
||||
CardCriteria criteria = new CardCriteria();
|
||||
criteria.setCodes("EXP");
|
||||
criteria.minCardNumber(26);
|
||||
criteria.maxCardNumber(45);
|
||||
savedSpecialLand.addAll(CardRepository.instance.findCards(criteria));
|
||||
}
|
||||
|
||||
return new ArrayList<>(savedSpecialLand);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,15 +54,11 @@ import mage.target.targetpointer.FixedTarget;
|
|||
* @author jeffwadsworth
|
||||
*/
|
||||
public class Crystallization extends CardImpl {
|
||||
|
||||
|
||||
public Crystallization(UUID ownerId) {
|
||||
super(ownerId, 144, "Crystallization", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{G/U}{W}");
|
||||
this.expansionSetCode = "ARB";
|
||||
this.subtype.add("Aura");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Enchant creature
|
||||
TargetPermanent auraTarget = new TargetCreaturePermanent();
|
||||
|
@ -77,11 +73,11 @@ public class Crystallization extends CardImpl {
|
|||
// When enchanted creature becomes the target of a spell or ability, exile that creature.
|
||||
this.addAbility(new CrystallizationTriggeredAbility());
|
||||
}
|
||||
|
||||
|
||||
public Crystallization(final Crystallization card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Crystallization copy() {
|
||||
return new Crystallization(this);
|
||||
|
@ -89,15 +85,15 @@ public class Crystallization extends CardImpl {
|
|||
}
|
||||
|
||||
class CrystallizationTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
|
||||
public CrystallizationTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new ExileTargetEffect());
|
||||
}
|
||||
|
||||
|
||||
public CrystallizationTriggeredAbility(final CrystallizationTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CrystallizationTriggeredAbility copy() {
|
||||
return new CrystallizationTriggeredAbility(this);
|
||||
|
@ -107,7 +103,7 @@ class CrystallizationTriggeredAbility extends TriggeredAbilityImpl {
|
|||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == EventType.TARGETED;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Permanent enchantment = game.getPermanent(sourceId);
|
||||
|
@ -120,7 +116,7 @@ class CrystallizationTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "When enchanted creature becomes the target of a spell or ability, exile that creature.";
|
||||
|
|
|
@ -98,10 +98,7 @@ class SlaveOfBolasEffect extends OneShotEffect {
|
|||
SacrificeTargetEffect sacrificeEffect = new SacrificeTargetEffect("sacrifice this", source.getControllerId());
|
||||
sacrificeEffect.setTargetPointer(new FixedTarget(permanent, game));
|
||||
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(sacrificeEffect);
|
||||
delayedAbility.setSourceId(source.getSourceId());
|
||||
delayedAbility.setControllerId(source.getControllerId());
|
||||
delayedAbility.setSourceObject(source.getSourceObject(game), game);
|
||||
game.addDelayedTriggeredAbility(delayedAbility);
|
||||
game.addDelayedTriggeredAbility(delayedAbility, source);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -105,7 +105,7 @@ class VectisDominatorEffect extends OneShotEffect {
|
|||
cost.clearPaid();
|
||||
final StringBuilder sb = new StringBuilder("Pay 2 life? (Otherwise ").append(targetCreature.getName()).append(" will be tapped)");
|
||||
if (player.chooseUse(Outcome.Benefit, sb.toString(), source, game)) {
|
||||
cost.pay(source, game, targetCreature.getControllerId(), targetCreature.getControllerId(), true);
|
||||
cost.pay(source, game, targetCreature.getControllerId(), targetCreature.getControllerId(), true, null);
|
||||
}
|
||||
if (!cost.isPaid()) {
|
||||
return targetCreature.tap(game);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue