Merge branch 'master' into copy_constructor_watchers

This commit is contained in:
Oleg Agafonov 2019-05-18 09:13:42 +04:00
commit 85c6528d2d
724 changed files with 23423 additions and 5250 deletions

1
.gitignore vendored
View file

@ -49,6 +49,7 @@ Mage.Server.Plugins/Mage.Game.FreeForAll/target
Mage.Server.Plugins/Mage.Game.MomirDuel/target
Mage.Server.Plugins/Mage.Game.MomirGame/target/
Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/target
Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/target/
Mage.Server.Plugins/Mage.Game.FreeformCommanderFreeForAll/target/
Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/target
Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/target

View file

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

View file

@ -16,6 +16,14 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="menuDebugTestModalDialogActionPerformed"/>
</Events>
</MenuItem>
<MenuItem class="javax.swing.JMenuItem" name="menuDebugTestCardRenderModesDialog">
<Properties>
<Property name="text" type="java.lang.String" value="Test Card Render Modes"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="menuDebugTestCardRenderModesDialogActionPerformed"/>
</Events>
</MenuItem>
</SubComponents>
</Container>
</NonVisualComponents>

View file

@ -20,6 +20,7 @@ import mage.client.draft.DraftPane;
import mage.client.draft.DraftPanel;
import mage.client.game.GamePane;
import mage.client.game.GamePanel;
import mage.client.game.PlayAreaPanel;
import mage.client.plugins.adapters.MageActionCallback;
import mage.client.plugins.impl.Plugins;
import mage.client.preference.MagePreferences;
@ -72,7 +73,7 @@ import java.util.concurrent.TimeUnit;
import java.util.prefs.Preferences;
/**
* @author BetaSteward_at_googlemail.com
* @author BetaSteward_at_googlemail.com, JayDi85
*/
public class MageFrame extends javax.swing.JFrame implements MageClient {
@ -246,8 +247,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
SessionHandler.startSession(this);
callbackClient = new CallbackClientImpl(this);
connectDialog = new ConnectDialog();
try
{
try {
whatsNewDialog = new WhatsNewDialog();
} catch (NoClassDefFoundError e) {
// JavaFX is not supported on old MacOS with OpenJDK
@ -320,10 +320,6 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
setConnectButtonText(NOT_CONNECTED_TEXT);
SwingUtilities.invokeLater(() -> {
disableButtons();
if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_CHECK, "false").equals("true")) {
checkForNewImages();
}
updateMemUsageTask.execute();
LOGGER.info("Client start up time: " + ((System.currentTimeMillis() - startTime) / 1000 + " seconds"));
if (autoConnect()) {
@ -332,7 +328,6 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
connectDialog.showDialog();
}
setWindowTitle();
});
if (SystemUtil.isMacOSX()) {
@ -354,61 +349,76 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
+ ((SessionHandler.getSession() != null && SessionHandler.isConnected()) ? SessionHandler.getVersionInfo() : NOT_CONNECTED_TEXT));
}
private void updateTooltipContainerSizes() {
JPanel cardPreviewContainer;
BigCard bigCard;
JPanel cardPreviewContainerRotated;
BigCard bigCardRotated;
try {
cardPreviewContainer = (JPanel) UI.getComponent(MageComponents.CARD_PREVIEW_CONTAINER);
bigCard = (BigCard) UI.getComponent(MageComponents.CARD_PREVIEW_PANE);
cardPreviewContainerRotated = (JPanel) UI.getComponent(MageComponents.CARD_PREVIEW_CONTAINER_ROTATED);
bigCardRotated = (BigCard) UI.getComponent(MageComponents.CARD_PREVIEW_PANE_ROTATED);
} catch (InterruptedException e) {
LOGGER.fatal("Can't update tooltip panel sizes");
Thread.currentThread().interrupt();
return;
}
int height = GUISizeHelper.enlargedImageHeight;
int width = (int) ((float) height * (float) 0.64);
bigCard.setSize(width, height);
cardPreviewContainer.setBounds(0, 0, width + 80, height + 30);
bigCardRotated.setSize(height, width + 30);
cardPreviewContainerRotated.setBounds(0, 0, height + 80, width + 100 + 30);
}
private void addTooltipContainer() {
final JEditorPane cardInfoPane = (JEditorPane) Plugins.instance.getCardInfoPane();
JEditorPane cardInfoPane = (JEditorPane) Plugins.instance.getCardInfoPane();
if (cardInfoPane == null) {
LOGGER.fatal("Can't find card tooltip plugin");
return;
}
cardInfoPane.setLocation(40, 40);
cardInfoPane.setBackground(new Color(0, 0, 0, 0));
UI.addComponent(MageComponents.CARD_INFO_PANE, cardInfoPane);
MageRoundPane popupContainer = new MageRoundPane();
popupContainer.setLayout(null);
popupContainer.add(cardInfoPane);
popupContainer.setVisible(false);
desktopPane.add(popupContainer, JLayeredPane.POPUP_LAYER);
UI.addComponent(MageComponents.CARD_INFO_PANE, cardInfoPane);
UI.addComponent(MageComponents.POPUP_CONTAINER, popupContainer);
// preview panel normal
JPanel cardPreviewContainer = new JPanel();
cardPreviewContainer.setOpaque(false);
cardPreviewContainer.setLayout(null);
BigCard bigCard = new BigCard();
int height = GUISizeHelper.enlargedImageHeight;
int width = (int) ((float) height * (float) 0.64);
bigCard.setSize(width, height);
bigCard.setLocation(40, 40);
bigCard.setBackground(new Color(0, 0, 0, 0));
cardPreviewContainer.add(bigCard);
cardPreviewContainer.setVisible(false);
cardPreviewContainer.setBounds(0, 0, width + 80, height + 30);
UI.addComponent(MageComponents.CARD_PREVIEW_PANE, bigCard);
desktopPane.add(cardPreviewContainer, JLayeredPane.POPUP_LAYER);
UI.addComponent(MageComponents.CARD_PREVIEW_CONTAINER, cardPreviewContainer);
desktopPane.add(cardPreviewContainer, JLayeredPane.POPUP_LAYER);
BigCard bigCard = new BigCard();
bigCard.setLocation(40, 40);
bigCard.setBackground(new Color(0, 0, 0, 0));
cardPreviewContainer.add(bigCard);
UI.addComponent(MageComponents.CARD_PREVIEW_PANE, bigCard);
// preview panel rotated
JPanel cardPreviewContainerRotated = new JPanel();
cardPreviewContainerRotated.setOpaque(false);
cardPreviewContainerRotated.setLayout(null);
bigCard = new BigCard(true);
bigCard.setSize(height, width + 30);
bigCard.setLocation(40, 40);
bigCard.setBackground(new Color(0, 0, 0, 0));
cardPreviewContainerRotated.add(bigCard);
cardPreviewContainerRotated.setVisible(false);
cardPreviewContainerRotated.setBounds(0, 0, height + 80, width + 100 + 30);
UI.addComponent(MageComponents.CARD_PREVIEW_PANE_ROTATED, bigCard);
desktopPane.add(cardPreviewContainerRotated, JLayeredPane.POPUP_LAYER);
UI.addComponent(MageComponents.CARD_PREVIEW_CONTAINER_ROTATED, cardPreviewContainerRotated);
desktopPane.add(cardPreviewContainerRotated, JLayeredPane.POPUP_LAYER);
BigCard bigCardRotated = new BigCard(true);
bigCardRotated.setLocation(40, 40);
bigCardRotated.setBackground(new Color(0, 0, 0, 0));
cardPreviewContainerRotated.add(bigCardRotated);
UI.addComponent(MageComponents.CARD_PREVIEW_PANE_ROTATED, bigCardRotated);
updateTooltipContainerSizes();
}
private void setGUISizeTooltipContainer() {
@ -563,10 +573,6 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
menu.show(component, 0, component.getHeight());
}
private void checkForNewImages() {
// Removed TODO: Remove related pref code
}
public static void setActive(MagePane frame) {
// Always hide not hidden popup window or enlarged card view if a frame is set to active
try {
@ -580,8 +586,10 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
container.repaint();
}
} catch (InterruptedException e) {
LOGGER.fatal("MageFrame error", e);
Thread.currentThread().interrupt();
}
// Nothing to do
if (activeFrame == frame) {
return;
@ -758,10 +766,10 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
private boolean performConnect(boolean reconnect) {
if (currentConnection == null || !reconnect) {
String server = MagePreferences.getServerAddress();
int port = MagePreferences.getServerPort();
String userName = MagePreferences.getUserName(server);
String password = MagePreferences.getPassword(server);
String server = MagePreferences.getLastServerAddress();
int port = MagePreferences.getLastServerPort();
String userName = MagePreferences.getLastServerUser();
String password = MagePreferences.getLastServerPassword();
String proxyServer = PREFS.get("proxyAddress", "");
int proxyPort = Integer.parseInt(PREFS.get("proxyPort", "0"));
ProxyType proxyType = ProxyType.valueByText(PREFS.get("proxyType", "None"));
@ -820,6 +828,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
popupDebug = new javax.swing.JPopupMenu();
menuDebugTestModalDialog = new javax.swing.JMenuItem();
menuDebugTestCardRenderModesDialog = new javax.swing.JMenuItem();
desktopPane = new MageJDesktop();
mageToolbar = new javax.swing.JToolBar();
btnPreferences = new javax.swing.JButton();
@ -850,6 +859,14 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
});
popupDebug.add(menuDebugTestModalDialog);
menuDebugTestCardRenderModesDialog.setText("Test Card Render Modes");
menuDebugTestCardRenderModesDialog.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
menuDebugTestCardRenderModesDialogActionPerformed(evt);
}
});
popupDebug.add(menuDebugTestCardRenderModesDialog);
setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
setMinimumSize(new java.awt.Dimension(1024, 768));
@ -1072,6 +1089,11 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
popupDebug.show(evt.getComponent(), 0, evt.getComponent().getHeight());
}//GEN-LAST:event_btnDebugMouseClicked
private void menuDebugTestCardRenderModesDialogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuDebugTestCardRenderModesDialogActionPerformed
final TestCardRenderDialog dialog = new TestCardRenderDialog();
dialog.showDialog();
}//GEN-LAST:event_menuDebugTestCardRenderModesDialogActionPerformed
public void downloadImages() {
DownloadPicturesService.startDownload();
}
@ -1321,6 +1343,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
private javax.swing.JToolBar.Separator jSeparatorImages;
private javax.swing.JToolBar.Separator jSeparatorSymbols;
private javax.swing.JToolBar mageToolbar;
private javax.swing.JMenuItem menuDebugTestCardRenderModesDialog;
private javax.swing.JMenuItem menuDebugTestModalDialog;
private javax.swing.JPopupMenu popupDebug;
private javax.swing.JToolBar.Separator separatorDebug;
@ -1365,6 +1388,11 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
return GAMES.get(gameId);
}
public static Map<UUID, PlayAreaPanel> getGamePlayers(UUID gameId) {
GamePanel p = GAMES.get(gameId);
return p != null ? p.getPlayers() : new HashMap<>();
}
public static void removeGame(UUID gameId) {
GAMES.remove(gameId);
}
@ -1403,23 +1431,25 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
}
@Override
public void disconnected(final boolean errorCall) {
public void disconnected(final boolean askToReconnect) {
if (SwingUtilities.isEventDispatchThread()) { // Returns true if the current thread is an AWT event dispatching thread.
LOGGER.info("DISCONNECTED (Event Dispatch Thread)");
// REMOTE task, e.g. connecting
LOGGER.info("Disconnected from remote task");
setConnectButtonText(NOT_CONNECTED_TEXT);
disableButtons();
hideGames();
hideTables();
} else {
LOGGER.info("DISCONNECTED (NO Event Dispatch Thread)");
// USER mode, e.g. user plays and got disconnect
LOGGER.info("Disconnected from user mode");
SwingUtilities.invokeLater(() -> {
SessionHandler.disconnect(false); // user already disconnected, can't do any online actions like quite chat
setConnectButtonText(NOT_CONNECTED_TEXT);
disableButtons();
hideGames();
hideTables();
SessionHandler.disconnect(false);
if (errorCall) {
UserRequestMessage message = new UserRequestMessage("Connection lost", "The connection to server was lost. Reconnect?");
if (askToReconnect) {
UserRequestMessage message = new UserRequestMessage("Connection lost", "The connection to server was lost. Reconnect to " + MagePreferences.getLastServerAddress() + "?");
message.setButton1("No", null);
message.setButton2("Yes", PlayerAction.CLIENT_RECONNECT);
showUserRequestDialog(message);
@ -1583,7 +1613,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
}
balloonTip.setFont(GUISizeHelper.balloonTooltipFont);
addTooltipContainer();
updateTooltipContainerSizes();
}
public void showWhatsNewDialog(boolean forceToShowPage) {

View file

@ -1,10 +1,3 @@
/*
* Card.java
*
* Created on 17-Dec-2009, 9:20:50 PM
*/
package mage.client.cards;
import mage.cards.CardDimensions;
@ -37,7 +30,6 @@ import java.util.UUID;
import static mage.client.constants.Constants.*;
/**
*
* @author BetaSteward_at_googlemail.com
*/
@SuppressWarnings("serial")
@ -132,7 +124,7 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis
gSmall.drawImage(ImageHelper.scaleImage(image, Config.dimensions.getFrameWidth(), Config.dimensions.getFrameHeight()), 0, 0, this);
gImage.setFont(new Font("Arial", Font.PLAIN, NAME_FONT_MAX_SIZE));
gImage.drawString(card.getName()+"TEST", CONTENT_MAX_XOFFSET, NAME_MAX_YOFFSET);
gImage.drawString(card.getName() + "TEST", CONTENT_MAX_XOFFSET, NAME_MAX_YOFFSET);
if (card.isCreature()) {
gImage.drawString(card.getPower() + '/' + card.getToughness(), POWBOX_TEXT_MAX_LEFT, POWBOX_TEXT_MAX_TOP);
} else if (card.isPlanesWalker()) {
@ -146,7 +138,7 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis
gImage.dispose();
gSmall.setFont(new Font("Arial", Font.PLAIN, Config.dimensions.getNameFontSize()));
gSmall.drawString(card.getName()+"TEST2", Config.dimensions.getContentXOffset(), Config.dimensions.getNameYOffset());
gSmall.drawString(card.getName() + "TEST2", Config.dimensions.getContentXOffset(), Config.dimensions.getNameYOffset());
if (card.isCreature()) {
gSmall.drawString(card.getPower() + "/-/" + card.getToughness(), Config.dimensions.getPowBoxTextLeft(), Config.dimensions.getPowBoxTextTop());
} else if (card.isPlanesWalker()) {
@ -259,12 +251,12 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis
return sbType.toString();
}
protected void drawDetailed(Graphics2D g) {
// Get the size of the card
int width = getWidth();
int height = getHeight();
g.setColor(Color.black);
g.drawRoundRect(0, 0, width, height, 4, 4);
g.setColor(Color.white);
@ -309,7 +301,7 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis
@Override
public void paintComponent(Graphics graphics) {
drawDetailed((Graphics2D)graphics);
drawDetailed((Graphics2D) graphics);
/*
Graphics2D g2 = (Graphics2D) graphics;
g2.drawImage(small, 0, 0, this);
@ -367,13 +359,13 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis
List<UUID> targets = card.getTargets();
if (targets != null) {
for (UUID uuid : targets) {
PlayAreaPanel playAreaPanel = MageFrame.getGame(gameId).getPlayers().get(uuid);
PlayAreaPanel playAreaPanel = MageFrame.getGamePlayers(gameId).get(uuid);
if (playAreaPanel != null) {
Point target = playAreaPanel.getLocationOnScreen();
Point me = this.getLocationOnScreen();
ArrowBuilder.getBuilder().addArrow(gameId, (int) me.getX() + 35, (int) me.getY(), (int) target.getX() + 40, (int) target.getY() - 40, Color.red, ArrowBuilder.Type.TARGET);
} else {
for (PlayAreaPanel pa : MageFrame.getGame(gameId).getPlayers().values()) {
for (PlayAreaPanel pa : MageFrame.getGamePlayers(gameId).values()) {
MagePermanent permanent = pa.getBattlefieldPanel().getPermanents().get(uuid);
if (permanent != null) {
Point target = permanent.getLocationOnScreen();

View file

@ -1,6 +1,7 @@
package mage.client.cards;
import mage.cards.MageCard;
import mage.client.dialog.PreferencesDialog;
import mage.client.plugins.impl.Plugins;
import mage.client.util.ClientEventType;
import mage.client.util.Event;
@ -30,6 +31,9 @@ public class CardArea extends JPanel implements MouseListener {
private Dimension cardDimension;
private int verticalCardOffset;
private int customRenderMode = -1; // custom render mode tests
private Dimension customCardSize = null; // custom size for tests
/**
* Create the panel.
*/
@ -62,7 +66,11 @@ public class CardArea extends JPanel implements MouseListener {
}
private void setGUISize() {
setCardDimension(GUISizeHelper.otherZonesCardDimension, GUISizeHelper.otherZonesCardVerticalOffset);
if (customCardSize != null) {
setCardDimension(customCardSize, GUISizeHelper.otherZonesCardVerticalOffset);
} else {
setCardDimension(GUISizeHelper.otherZonesCardDimension, GUISizeHelper.otherZonesCardVerticalOffset);
}
}
public void setCardDimension(Dimension dimension, int verticalCardOffset) {
@ -129,7 +137,8 @@ public class CardArea extends JPanel implements MouseListener {
tmp.setAbility(card); // cross-reference, required for ability picker
card = tmp;
}
MageCard cardPanel = Plugins.instance.getMageCard(card, bigCard, cardDimension, gameId, true, true);
MageCard cardPanel = Plugins.instance.getMageCard(card, bigCard, cardDimension, gameId, true, true,
customRenderMode != -1 ? customRenderMode : PreferencesDialog.getRenderMode());
cardPanel.setBounds(rectangle);
cardPanel.addMouseListener(this);
@ -265,6 +274,14 @@ public class CardArea extends JPanel implements MouseListener {
}
}
public void setCustomRenderMode(int customRenderMode) {
this.customRenderMode = customRenderMode;
}
public void setCustomCardSize(Dimension customCardSize) {
this.customCardSize = customCardSize;
}
@Override
public void mouseEntered(MouseEvent e) {
}

View file

@ -2,6 +2,7 @@ package mage.client.cards;
import mage.cards.MageCard;
import mage.client.MagePane;
import mage.client.dialog.PreferencesDialog;
import mage.client.plugins.impl.Plugins;
import mage.view.CardView;
@ -45,7 +46,7 @@ public class CardDraggerGlassPane implements MouseListener, MouseMotionListener
currentRoot = SwingUtilities.getRootPane(c);
// Pane
glassPane = (JComponent)currentRoot.getGlassPane();
glassPane = (JComponent) currentRoot.getGlassPane();
glassPane.setLayout(null);
glassPane.setOpaque(false);
glassPane.setVisible(true);
@ -58,7 +59,7 @@ public class CardDraggerGlassPane implements MouseListener, MouseMotionListener
if (rootMagePane == null) {
throw new RuntimeException("CardDraggerGlassPane::beginDrag not in a MagePane?");
} else {
currentEventRootMagePane = (MagePane)rootMagePane;
currentEventRootMagePane = (MagePane) rootMagePane;
}
// Hook up events
@ -72,8 +73,8 @@ public class CardDraggerGlassPane implements MouseListener, MouseMotionListener
currentCards = new ArrayList<>(source.dragCardList());
// Make a view for the first one and add it to us
dragView = Plugins.instance.getMageCard(currentCards.get(0), null, new Dimension(100, 140), null, true, false);
for (MouseListener l: dragView.getMouseListeners()) {
dragView = Plugins.instance.getMageCard(currentCards.get(0), null, new Dimension(100, 140), null, true, false, PreferencesDialog.getRenderMode());
for (MouseListener l : dragView.getMouseListeners()) {
dragView.removeMouseListener(l);
}
for (MouseMotionListener l : dragView.getMouseMotionListeners()) {
@ -95,7 +96,7 @@ public class CardDraggerGlassPane implements MouseListener, MouseMotionListener
Component mouseOver = SwingUtilities.getDeepestComponentAt(currentEventRootMagePane, e.getX(), e.getY());
while (mouseOver != null) {
if (mouseOver instanceof DragCardTarget) {
DragCardTarget target = (DragCardTarget)mouseOver;
DragCardTarget target = (DragCardTarget) mouseOver;
MouseEvent targetEvent = SwingUtilities.convertMouseEvent(currentEventRootMagePane, e, mouseOver);
if (target != currentDragTarget) {
if (currentDragTarget != null) {
@ -116,7 +117,7 @@ public class CardDraggerGlassPane implements MouseListener, MouseMotionListener
mouseOver = mouseOver.getParent();
}
if (currentDragTarget != null) {
MouseEvent oldTargetEvent = SwingUtilities.convertMouseEvent(currentEventRootMagePane, e, (Component)currentDragTarget);
MouseEvent oldTargetEvent = SwingUtilities.convertMouseEvent(currentEventRootMagePane, e, (Component) currentDragTarget);
currentDragTarget.dragCardExit(oldTargetEvent);
}
currentDragTarget = null;
@ -164,13 +165,22 @@ public class CardDraggerGlassPane implements MouseListener, MouseMotionListener
}
@Override
public void mouseClicked(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {}
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {}
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseMoved(MouseEvent e) {}
public void mouseMoved(MouseEvent e) {
}
}

View file

@ -1,430 +1,430 @@
/*
* CardGrid.java
*
* Created on 30-Mar-2010, 9:25:40 PM
*/
package mage.client.cards;
* CardGrid.java
*
* Created on 30-Mar-2010, 9:25:40 PM
*/
package mage.client.cards;
import mage.cards.MageCard;
import mage.client.deckeditor.SortSetting;
import mage.client.plugins.impl.Plugins;
import mage.client.util.ClientEventType;
import mage.client.util.Event;
import mage.client.util.GUISizeHelper;
import mage.client.util.Listener;
import mage.utils.CardColorUtil;
import mage.view.CardView;
import mage.view.CardsView;
import org.mage.card.arcane.CardPanel;
import mage.cards.MageCard;
import mage.client.deckeditor.SortSetting;
import mage.client.dialog.PreferencesDialog;
import mage.client.plugins.impl.Plugins;
import mage.client.util.ClientEventType;
import mage.client.util.Event;
import mage.client.util.GUISizeHelper;
import mage.client.util.Listener;
import mage.utils.CardColorUtil;
import mage.view.CardView;
import mage.view.CardsView;
import org.mage.card.arcane.CardPanel;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.*;
import java.util.List;
import java.util.Map.Entry;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.List;
import java.util.*;
import java.util.Map.Entry;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class CardGrid extends javax.swing.JLayeredPane implements MouseListener, ICardGrid {
/**
* @author BetaSteward_at_googlemail.com
*/
public class CardGrid extends javax.swing.JLayeredPane implements MouseListener, ICardGrid {
protected final CardEventSource cardEventSource = new CardEventSource();
protected BigCard bigCard;
protected UUID gameId;
private final Map<UUID, MageCard> cards = new HashMap<>();
private Dimension cardDimension;
protected final CardEventSource cardEventSource = new CardEventSource();
protected BigCard bigCard;
protected UUID gameId;
private final Map<UUID, MageCard> cards = new HashMap<>();
private Dimension cardDimension;
/**
* Max amount of cards in card grid for which card images will be drawn.
* Done so to solve issue with memory for big piles of cards.
*/
public static final int MAX_IMAGES = 350;
/**
* Max amount of cards in card grid for which card images will be drawn.
* Done so to solve issue with memory for big piles of cards.
*/
public static final int MAX_IMAGES = 350;
public CardGrid() {
initComponents();
setGUISize();
setOpaque(false);
}
public CardGrid() {
initComponents();
setGUISize();
setOpaque(false);
}
public void clear() {
for (MouseListener ml : this.getMouseListeners()) {
this.removeMouseListener(ml);
}
this.clearCardEventListeners();
this.clearCards();
this.bigCard = null;
}
public void clear() {
for (MouseListener ml : this.getMouseListeners()) {
this.removeMouseListener(ml);
}
this.clearCardEventListeners();
this.clearCards();
this.bigCard = null;
}
public void changeGUISize() {
setGUISize();
}
public void changeGUISize() {
setGUISize();
}
private void setGUISize() {
cardDimension = GUISizeHelper.editorCardDimension;
}
private void setGUISize() {
cardDimension = GUISizeHelper.editorCardDimension;
}
@Override
public void loadCards(CardsView showCards, SortSetting sortSetting, BigCard bigCard, UUID gameId) {
this.loadCards(showCards, sortSetting, bigCard, gameId, true);
}
@Override
public void loadCards(CardsView showCards, SortSetting sortSetting, BigCard bigCard, UUID gameId) {
this.loadCards(showCards, sortSetting, bigCard, gameId, true);
}
@Override
public void loadCards(CardsView showCards, SortSetting sortSetting, BigCard bigCard, UUID gameId, boolean merge) {
boolean drawImage = showCards.size() <= MAX_IMAGES;
this.bigCard = bigCard;
this.gameId = gameId;
if (merge) {
for (CardView card : showCards.values()) {
if (!cards.containsKey(card.getId())) {
addCard(card, bigCard, gameId, drawImage);
}
}
for (Iterator<Entry<UUID, MageCard>> i = cards.entrySet().iterator(); i.hasNext();) {
Entry<UUID, MageCard> entry = i.next();
if (!showCards.containsKey(entry.getKey())) {
removeCardImg(entry.getKey());
i.remove();
}
}
} else {
this.clearCards();
for (CardView card : showCards.values()) {
addCard(card, bigCard, gameId, drawImage);
}
}
drawCards(sortSetting);
this.setVisible(true);
}
@Override
public void loadCards(CardsView showCards, SortSetting sortSetting, BigCard bigCard, UUID gameId, boolean merge) {
boolean drawImage = showCards.size() <= MAX_IMAGES;
this.bigCard = bigCard;
this.gameId = gameId;
if (merge) {
for (CardView card : showCards.values()) {
if (!cards.containsKey(card.getId())) {
addCard(card, bigCard, gameId, drawImage);
}
}
for (Iterator<Entry<UUID, MageCard>> i = cards.entrySet().iterator(); i.hasNext(); ) {
Entry<UUID, MageCard> entry = i.next();
if (!showCards.containsKey(entry.getKey())) {
removeCardImg(entry.getKey());
i.remove();
}
}
} else {
this.clearCards();
for (CardView card : showCards.values()) {
addCard(card, bigCard, gameId, drawImage);
}
}
drawCards(sortSetting);
this.setVisible(true);
}
private void addCard(CardView card, BigCard bigCard, UUID gameId, boolean drawImage) {
MageCard cardImg = Plugins.instance.getMageCard(card, bigCard, cardDimension, gameId, drawImage, true);
cards.put(card.getId(), cardImg);
cardImg.addMouseListener(this);
add(cardImg);
cardImg.update(card);
cards.put(card.getId(), cardImg);
}
private void addCard(CardView card, BigCard bigCard, UUID gameId, boolean drawImage) {
MageCard cardImg = Plugins.instance.getMageCard(card, bigCard, cardDimension, gameId, drawImage, true, PreferencesDialog.getRenderMode());
cards.put(card.getId(), cardImg);
cardImg.addMouseListener(this);
add(cardImg);
cardImg.update(card);
cards.put(card.getId(), cardImg);
}
@Override
public void drawCards(SortSetting sortSetting) {
int maxWidth = this.getParent().getWidth();
int cardVerticalOffset = GUISizeHelper.editorCardOffsetSize;
int numColumns = maxWidth / cardDimension.width;
int curColumn = 0;
int curRow = 0;
if (!cards.isEmpty()) {
Rectangle rectangle = new Rectangle(cardDimension.width, cardDimension.height);
List<MageCard> sortedCards = new ArrayList<>(cards.values());
switch (sortSetting.getSortBy()) {
case NAME:
sortedCards.sort(new CardNameComparator());
break;
case CARD_TYPE:
sortedCards.sort(new CardTypeComparator());
break;
case RARITY:
sortedCards.sort(new CardRarityComparator());
break;
case COLOR:
sortedCards.sort(new CardColorComparator());
break;
case COLOR_IDENTITY:
sortedCards.sort(new CardColorDetailedIdentity());
break;
case CASTING_COST:
sortedCards.sort(new CardCostComparator());
break;
@Override
public void drawCards(SortSetting sortSetting) {
int maxWidth = this.getParent().getWidth();
int cardVerticalOffset = GUISizeHelper.editorCardOffsetSize;
int numColumns = maxWidth / cardDimension.width;
int curColumn = 0;
int curRow = 0;
if (!cards.isEmpty()) {
Rectangle rectangle = new Rectangle(cardDimension.width, cardDimension.height);
List<MageCard> sortedCards = new ArrayList<>(cards.values());
switch (sortSetting.getSortBy()) {
case NAME:
sortedCards.sort(new CardNameComparator());
break;
case CARD_TYPE:
sortedCards.sort(new CardTypeComparator());
break;
case RARITY:
sortedCards.sort(new CardRarityComparator());
break;
case COLOR:
sortedCards.sort(new CardColorComparator());
break;
case COLOR_IDENTITY:
sortedCards.sort(new CardColorDetailedIdentity());
break;
case CASTING_COST:
sortedCards.sort(new CardCostComparator());
break;
}
MageCard lastCard = null;
for (MageCard cardImg : sortedCards) {
if (sortSetting.isPilesToggle()) {
if (lastCard == null) {
lastCard = cardImg;
}
switch (sortSetting.getSortBy()) {
case NAME:
if (!cardImg.getOriginal().getName().equals(lastCard.getOriginal().getName())) {
curColumn++;
curRow = 0;
}
break;
case CARD_TYPE:
if (!cardImg.getOriginal().getCardTypes().equals(lastCard.getOriginal().getCardTypes())) {
curColumn++;
curRow = 0;
}
break;
case RARITY:
if (cardImg.getOriginal().getRarity() != lastCard.getOriginal().getRarity()) {
curColumn++;
curRow = 0;
}
break;
case COLOR:
if (cardImg.getOriginal().getColor().compareTo(lastCard.getOriginal().getColor()) != 0) {
curColumn++;
curRow = 0;
}
break;
case COLOR_IDENTITY:
if (CardColorUtil.getColorIdentitySortValue(cardImg.getOriginal().getManaCost(), cardImg.getOriginal().getColor(), cardImg.getOriginal().getRules())
!= CardColorUtil.getColorIdentitySortValue(lastCard.getOriginal().getManaCost(), lastCard.getOriginal().getColor(), lastCard.getOriginal().getRules())) {
curColumn++;
curRow = 0;
}
break;
case CASTING_COST:
if (cardImg.getOriginal().getConvertedManaCost() != lastCard.getOriginal().getConvertedManaCost()) {
curColumn++;
curRow = 0;
}
break;
}
rectangle.setLocation(curColumn * cardDimension.width, curRow * cardVerticalOffset);
cardImg.setBounds(rectangle);
cardImg.setCardBounds(rectangle.x, rectangle.y, cardDimension.width, cardDimension.height);
moveToFront(cardImg);
curRow++;
lastCard = cardImg;
} else {
rectangle.setLocation(curColumn * cardDimension.width, curRow * cardVerticalOffset);
cardImg.setBounds(rectangle);
cardImg.setCardBounds(rectangle.x, rectangle.y, cardDimension.width, cardDimension.height);
moveToFront(cardImg);
curColumn++;
if (curColumn == numColumns) {
curColumn = 0;
curRow++;
}
}
}
}
resizeArea();
revalidate();
repaint();
}
}
MageCard lastCard = null;
for (MageCard cardImg : sortedCards) {
if (sortSetting.isPilesToggle()) {
if (lastCard == null) {
lastCard = cardImg;
}
switch (sortSetting.getSortBy()) {
case NAME:
if (!cardImg.getOriginal().getName().equals(lastCard.getOriginal().getName())) {
curColumn++;
curRow = 0;
}
break;
case CARD_TYPE:
if (!cardImg.getOriginal().getCardTypes().equals(lastCard.getOriginal().getCardTypes())) {
curColumn++;
curRow = 0;
}
break;
case RARITY:
if (cardImg.getOriginal().getRarity() != lastCard.getOriginal().getRarity()) {
curColumn++;
curRow = 0;
}
break;
case COLOR:
if (cardImg.getOriginal().getColor().compareTo(lastCard.getOriginal().getColor()) != 0) {
curColumn++;
curRow = 0;
}
break;
case COLOR_IDENTITY:
if (CardColorUtil.getColorIdentitySortValue(cardImg.getOriginal().getManaCost(), cardImg.getOriginal().getColor(), cardImg.getOriginal().getRules())
!= CardColorUtil.getColorIdentitySortValue(lastCard.getOriginal().getManaCost(), lastCard.getOriginal().getColor(), lastCard.getOriginal().getRules())) {
curColumn++;
curRow = 0;
}
break;
case CASTING_COST:
if (cardImg.getOriginal().getConvertedManaCost() != lastCard.getOriginal().getConvertedManaCost()) {
curColumn++;
curRow = 0;
}
break;
}
rectangle.setLocation(curColumn * cardDimension.width, curRow * cardVerticalOffset);
cardImg.setBounds(rectangle);
cardImg.setCardBounds(rectangle.x, rectangle.y, cardDimension.width, cardDimension.height);
moveToFront(cardImg);
curRow++;
lastCard = cardImg;
} else {
rectangle.setLocation(curColumn * cardDimension.width, curRow * cardVerticalOffset);
cardImg.setBounds(rectangle);
cardImg.setCardBounds(rectangle.x, rectangle.y, cardDimension.width, cardDimension.height);
moveToFront(cardImg);
curColumn++;
if (curColumn == numColumns) {
curColumn = 0;
curRow++;
}
}
}
}
resizeArea();
revalidate();
repaint();
}
private void clearCards() {
// remove possible mouse listeners, preventing gc
for (MageCard mageCard : cards.values()) {
if (mageCard instanceof CardPanel) {
((CardPanel) mageCard).cleanUp();
}
}
this.cards.clear();
removeAllCardImg();
}
private void clearCards() {
// remove possible mouse listeners, preventing gc
for (MageCard mageCard : cards.values()) {
if (mageCard instanceof CardPanel) {
((CardPanel) mageCard).cleanUp();
}
}
this.cards.clear();
removeAllCardImg();
}
private void removeAllCardImg() {
for (Component comp : getComponents()) {
if (comp instanceof Card || comp instanceof MageCard) {
remove(comp);
}
}
}
private void removeAllCardImg() {
for (Component comp : getComponents()) {
if (comp instanceof Card || comp instanceof MageCard) {
remove(comp);
}
}
}
private void removeCardImg(UUID cardId) {
for (Component comp : getComponents()) {
if (comp instanceof Card) {
if (((Card) comp).getCardId().equals(cardId)) {
remove(comp);
comp = null;
}
} else if (comp instanceof MageCard) {
if (((MageCard) comp).getOriginal().getId().equals(cardId)) {
remove(comp);
comp = null;
}
}
}
}
private void removeCardImg(UUID cardId) {
for (Component comp : getComponents()) {
if (comp instanceof Card) {
if (((Card) comp).getCardId().equals(cardId)) {
remove(comp);
comp = null;
}
} else if (comp instanceof MageCard) {
if (((MageCard) comp).getOriginal().getId().equals(cardId)) {
remove(comp);
comp = null;
}
}
}
}
public void removeCard(UUID cardId) {
removeCardImg(cardId);
cards.remove(cardId);
}
public void removeCard(UUID cardId) {
removeCardImg(cardId);
cards.remove(cardId);
}
@Override
public void addCardEventListener(Listener<Event> listener) {
cardEventSource.addListener(listener);
}
@Override
public void addCardEventListener(Listener<Event> listener) {
cardEventSource.addListener(listener);
}
@Override
public void clearCardEventListeners() {
cardEventSource.clearListeners();
}
@Override
public void clearCardEventListeners() {
cardEventSource.clearListeners();
}
/**
* 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() {
/**
* 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() {
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 294, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 197, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 294, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 197, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
// End of variables declaration//GEN-END:variables
@Override
public void mouseClicked(MouseEvent e) {
if ((e.getClickCount() & 1) == 0 && (e.getClickCount() > 0) && !e.isConsumed()) { // double clicks and repeated double clicks
e.consume();
Object obj = e.getSource();
if (obj instanceof Card) {
if (e.isAltDown()) {
cardEventSource.fireEvent(((Card) obj).getOriginal(), ClientEventType.ALT_DOUBLE_CLICK);
} else {
cardEventSource.fireEvent(((Card) obj).getOriginal(), ClientEventType.DOUBLE_CLICK);
}
} else if (obj instanceof MageCard) {
if (e.isAltDown()) {
cardEventSource.fireEvent(((MageCard) obj).getOriginal(), ClientEventType.ALT_DOUBLE_CLICK);
} else {
cardEventSource.fireEvent(((MageCard) obj).getOriginal(), ClientEventType.DOUBLE_CLICK);
}
}
}
}
// Variables declaration - do not modify//GEN-BEGIN:variables
// End of variables declaration//GEN-END:variables
@Override
public void mouseClicked(MouseEvent e) {
if ((e.getClickCount() & 1) == 0 && (e.getClickCount() > 0) && !e.isConsumed()) { // double clicks and repeated double clicks
e.consume();
Object obj = e.getSource();
if (obj instanceof Card) {
if (e.isAltDown()) {
cardEventSource.fireEvent(((Card) obj).getOriginal(), ClientEventType.ALT_DOUBLE_CLICK);
} else {
cardEventSource.fireEvent(((Card) obj).getOriginal(), ClientEventType.DOUBLE_CLICK);
}
} else if (obj instanceof MageCard) {
if (e.isAltDown()) {
cardEventSource.fireEvent(((MageCard) obj).getOriginal(), ClientEventType.ALT_DOUBLE_CLICK);
} else {
cardEventSource.fireEvent(((MageCard) obj).getOriginal(), ClientEventType.DOUBLE_CLICK);
}
}
}
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
private void resizeArea() {
Dimension area = new Dimension(0, 0);
Dimension size = getPreferredSize();
private void resizeArea() {
Dimension area = new Dimension(0, 0);
Dimension size = getPreferredSize();
for (Component comp : getComponents()) {
Rectangle r = comp.getBounds();
if (r.x + r.width > area.width) {
area.width = r.x + r.width;
}
if (r.y + r.height > area.height) {
area.height = r.y + r.height;
}
}
if (size.height != area.height || size.width != area.width) {
setPreferredSize(area);
}
}
for (Component comp : getComponents()) {
Rectangle r = comp.getBounds();
if (r.x + r.width > area.width) {
area.width = r.x + r.width;
}
if (r.y + r.height > area.height) {
area.height = r.y + r.height;
}
}
if (size.height != area.height || size.width != area.width) {
setPreferredSize(area);
}
}
@Override
public void refresh() {
revalidate();
repaint();
}
@Override
public void refresh() {
revalidate();
repaint();
}
@Override
public int cardsSize() {
return cards.size();
}
}
@Override
public int cardsSize() {
return cards.size();
}
}
class CardNameComparator implements Comparator<MageCard> {
class CardNameComparator implements Comparator<MageCard> {
@Override
public int compare(MageCard o1, MageCard o2) {
return o1.getOriginal().getName().compareTo(o2.getOriginal().getName());
}
@Override
public int compare(MageCard o1, MageCard o2) {
return o1.getOriginal().getName().compareTo(o2.getOriginal().getName());
}
}
}
class CardRarityComparator implements Comparator<MageCard> {
class CardRarityComparator implements Comparator<MageCard> {
@Override
public int compare(MageCard o1, MageCard o2) {
int val = o1.getOriginal().getRarity().compareTo(o2.getOriginal().getRarity());
if (val == 0) {
return o1.getOriginal().getName().compareTo(o2.getOriginal().getName());
} else {
return val;
}
}
@Override
public int compare(MageCard o1, MageCard o2) {
int val = o1.getOriginal().getRarity().compareTo(o2.getOriginal().getRarity());
if (val == 0) {
return o1.getOriginal().getName().compareTo(o2.getOriginal().getName());
} else {
return val;
}
}
}
}
class CardCostComparator implements Comparator<MageCard> {
class CardCostComparator implements Comparator<MageCard> {
@Override
public int compare(MageCard o1, MageCard o2) {
int val = Integer.valueOf(o1.getOriginal().getConvertedManaCost()).compareTo(o2.getOriginal().getConvertedManaCost());
if (val == 0) {
return o1.getOriginal().getName().compareTo(o2.getOriginal().getName());
} else {
return val;
}
}
@Override
public int compare(MageCard o1, MageCard o2) {
int val = Integer.valueOf(o1.getOriginal().getConvertedManaCost()).compareTo(o2.getOriginal().getConvertedManaCost());
if (val == 0) {
return o1.getOriginal().getName().compareTo(o2.getOriginal().getName());
} else {
return val;
}
}
}
}
class CardColorComparator implements Comparator<MageCard> {
class CardColorComparator implements Comparator<MageCard> {
@Override
public int compare(MageCard o1, MageCard o2) {
int val = o1.getOriginal().getColor().compareTo(o2.getOriginal().getColor());
if (val == 0) {
return o1.getOriginal().getName().compareTo(o2.getOriginal().getName());
} else {
return val;
}
}
@Override
public int compare(MageCard o1, MageCard o2) {
int val = o1.getOriginal().getColor().compareTo(o2.getOriginal().getColor());
if (val == 0) {
return o1.getOriginal().getName().compareTo(o2.getOriginal().getName());
} else {
return val;
}
}
}
}
class CardColorDetailedIdentity implements Comparator<MageCard> {
class CardColorDetailedIdentity implements Comparator<MageCard> {
@Override
public int compare(MageCard o1, MageCard o2) {
int val = CardColorUtil.getColorIdentitySortValue(o1.getOriginal().getManaCost(), o1.getOriginal().getColor(), o1.getOriginal().getRules())
- CardColorUtil.getColorIdentitySortValue(o2.getOriginal().getManaCost(), o2.getOriginal().getColor(), o2.getOriginal().getRules());
if (val == 0) {
return o1.getOriginal().getName().compareTo(o2.getOriginal().getName());
} else {
return val;
}
}
@Override
public int compare(MageCard o1, MageCard o2) {
int val = CardColorUtil.getColorIdentitySortValue(o1.getOriginal().getManaCost(), o1.getOriginal().getColor(), o1.getOriginal().getRules())
- CardColorUtil.getColorIdentitySortValue(o2.getOriginal().getManaCost(), o2.getOriginal().getColor(), o2.getOriginal().getRules());
if (val == 0) {
return o1.getOriginal().getName().compareTo(o2.getOriginal().getName());
} else {
return val;
}
}
}
}
class CardTypeComparator implements Comparator<MageCard> {
class CardTypeComparator implements Comparator<MageCard> {
@Override
public int compare(MageCard o1, MageCard o2) {
int val = o1.getOriginal().getCardTypes().toString().compareTo(o2.getOriginal().getCardTypes().toString());
if (val == 0) {
return o1.getOriginal().getName().compareTo(o2.getOriginal().getName());
} else {
return val;
}
}
@Override
public int compare(MageCard o1, MageCard o2) {
int val = o1.getOriginal().getCardTypes().toString().compareTo(o2.getOriginal().getCardTypes().toString());
if (val == 0) {
return o1.getOriginal().getName().compareTo(o2.getOriginal().getName());
} else {
return val;
}
}
}
}

View file

@ -8,6 +8,7 @@
package mage.client.cards;
import mage.cards.MageCard;
import mage.client.dialog.PreferencesDialog;
import mage.client.plugins.impl.Plugins;
import mage.client.util.CardsViewUtil;
import mage.client.util.Config;
@ -227,7 +228,7 @@
}
private void addCard(CardView card, BigCard bigCard, UUID gameId) {
MageCard mageCard = Plugins.instance.getMageCard(card, bigCard, getCardDimension(), gameId, true, true);
MageCard mageCard = Plugins.instance.getMageCard(card, bigCard, getCardDimension(), gameId, true, true, PreferencesDialog.getRenderMode());
if (zone != null) {
mageCard.setZone(zone);
}

File diff suppressed because it is too large Load diff

View file

@ -10,6 +10,7 @@ package mage.client.cards;
import mage.cards.CardDimensions;
import mage.cards.MageCard;
import mage.client.dialog.PreferencesDialog;
import mage.client.plugins.impl.Plugins;
import mage.client.util.CardViewRarityComparator;
import mage.client.util.ClientEventType;
@ -28,7 +29,6 @@ import java.util.ArrayList;
import java.util.List;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class DraftGrid extends javax.swing.JPanel implements MouseListener {
@ -40,17 +40,19 @@ public class DraftGrid extends javax.swing.JPanel implements MouseListener {
protected MageCard markedCard;
protected boolean emptyGrid;
/** Creates new form DraftGrid */
/**
* Creates new form DraftGrid
*/
public DraftGrid() {
initComponents();
markedCard = null;
emptyGrid= true;
emptyGrid = true;
}
public void clear() {
markedCard = null;
this.clearCardEventListeners();
for (Component comp: getComponents()) {
for (Component comp : getComponents()) {
if (comp instanceof Card || comp instanceof MageCard) {
this.remove(comp);
}
@ -79,10 +81,10 @@ public class DraftGrid extends javax.swing.JPanel implements MouseListener {
CardDimensions cardDimension = null;
int maxCards;
double scale ;
double scale;
for (int i = 1; i < maxRows; i++) {
scale = (double) (this.getHeight()/i) / Constants.FRAME_MAX_HEIGHT;
scale = (double) (this.getHeight() / i) / Constants.FRAME_MAX_HEIGHT;
cardDimension = new CardDimensions(scale);
maxCards = this.getWidth() / (cardDimension.getFrameWidth() + offsetX);
if ((maxCards * i) >= booster.size()) {
@ -100,8 +102,8 @@ public class DraftGrid extends javax.swing.JPanel implements MouseListener {
List<CardView> sortedCards = new ArrayList<>(booster.values());
sortedCards.sort(new CardViewRarityComparator());
for (CardView card: sortedCards) {
MageCard cardImg = Plugins.instance.getMageCard(card, bigCard, dimension, null, true, true);
for (CardView card : sortedCards) {
MageCard cardImg = Plugins.instance.getMageCard(card, bigCard, dimension, null, true, true, PreferencesDialog.getRenderMode());
cardImg.addMouseListener(this);
add(cardImg);
cardImg.update(card);
@ -133,7 +135,8 @@ public class DraftGrid extends javax.swing.JPanel implements MouseListener {
Plugins.instance.getActionCallback().mouseExited(null, null);
}
/** This method is called from within the constructor to
/**
* 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.
@ -145,12 +148,12 @@ public class DraftGrid extends javax.swing.JPanel implements MouseListener {
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 400, Short.MAX_VALUE)
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 300, Short.MAX_VALUE)
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 300, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents
@ -160,7 +163,7 @@ public class DraftGrid extends javax.swing.JPanel implements MouseListener {
if (e.getButton() == MouseEvent.BUTTON1) {
Object obj = e.getSource();
if (obj instanceof MageCard) {
this.cardEventSource.fireEvent(((MageCard)obj).getOriginal(), ClientEventType.PICK_A_CARD);
this.cardEventSource.fireEvent(((MageCard) obj).getOriginal(), ClientEventType.PICK_A_CARD);
this.hidePopup();
AudioManager.playOnDraftSelect();
}
@ -177,8 +180,8 @@ public class DraftGrid extends javax.swing.JPanel implements MouseListener {
if (this.markedCard != null) {
markedCard.setSelected(false);
}
this.cardEventSource.fireEvent(((MageCard)obj).getOriginal(), ClientEventType.MARK_A_CARD);
markedCard = ((MageCard)obj);
this.cardEventSource.fireEvent(((MageCard) obj).getOriginal(), ClientEventType.MARK_A_CARD);
markedCard = ((MageCard) obj);
markedCard.setSelected(true);
repaint();
}

View file

@ -1,16 +1,5 @@
package mage.client.cards;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.swing.*;
import mage.cards.Card;
import mage.cards.MageCard;
import mage.cards.decks.DeckCardInfo;
@ -31,6 +20,18 @@ import mage.view.CardsView;
import org.apache.log4j.Logger;
import org.mage.card.arcane.CardRenderer;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* Created by StravantUser on 2016-09-20.
*/
@ -456,6 +457,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
--count;
}
}
private int count = 0;
}
@ -511,14 +513,14 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
};
private final CardTypeCounter[] allCounters = {
creatureCounter,
landCounter,
artifactCounter,
enchantmentCounter,
instantCounter,
planeswalkerCounter,
sorceryCounter,
tribalCounter
creatureCounter,
landCounter,
artifactCounter,
enchantmentCounter,
instantCounter,
planeswalkerCounter,
sorceryCounter,
tribalCounter
};
// Listener
@ -659,7 +661,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
@Override
public String toString() {
return '(' + sort.toString() + ',' + Boolean.toString(separateCreatures) + ',' + Integer.toString(cardSize) + ')';
return '(' + sort.toString() + ',' + separateCreatures + ',' + cardSize + ')';
}
}
@ -1767,7 +1769,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
updateCounts();
// Create the card view
final MageCard cardPanel = Plugins.instance.getMageCard(card, lastBigCard, new Dimension(getCardWidth(), getCardHeight()), null, true, true);
final MageCard cardPanel = Plugins.instance.getMageCard(card, lastBigCard, new Dimension(getCardWidth(), getCardHeight()), null, true, true, PreferencesDialog.getRenderMode());
cardPanel.update(card);
cardPanel.setCardCaptionTopOffset(0);

View file

@ -3,8 +3,8 @@ package mage.client.combat;
import mage.cards.MagePermanent;
import mage.client.MageFrame;
import mage.client.game.PlayAreaPanel;
import mage.client.util.audio.AudioManager;
import mage.client.util.SettingsManager;
import mage.client.util.audio.AudioManager;
import mage.client.util.gui.ArrowBuilder;
import mage.view.CardView;
import mage.view.CombatGroupView;
@ -67,7 +67,7 @@ public enum CombatManager {
}
private void drawAttacker(CombatGroupView group, CardView attacker, UUID gameId) {
for (PlayAreaPanel pa2 : MageFrame.getGame(gameId).getPlayers().values()) {
for (PlayAreaPanel pa2 : MageFrame.getGamePlayers(gameId).values()) {
MagePermanent attackerCard = pa2.getBattlefieldPanel().getPermanents().get(attacker.getId());
if (attackerCard != null) {
drawDefender(group, attackerCard, gameId);
@ -80,7 +80,7 @@ public enum CombatManager {
UUID defenderId = group.getDefenderId();
if (defenderId != null) {
parentPoint = getParentPoint(attackerCard);
PlayAreaPanel p = MageFrame.getGame(gameId).getPlayers().get(defenderId);
PlayAreaPanel p = MageFrame.getGamePlayers(gameId).get(defenderId);
if (p != null) {
Point target = p.getLocationOnScreen();
target.translate(-parentPoint.x, -parentPoint.y);
@ -88,7 +88,7 @@ public enum CombatManager {
attackerPoint.translate(-parentPoint.x, -parentPoint.y);
ArrowBuilder.getBuilder().addArrow(gameId, (int) attackerPoint.getX() + 45, (int) attackerPoint.getY() + 25, (int) target.getX() + 40, (int) target.getY() - 20, Color.red, ArrowBuilder.Type.COMBAT);
} else {
for (PlayAreaPanel pa : MageFrame.getGame(gameId).getPlayers().values()) {
for (PlayAreaPanel pa : MageFrame.getGamePlayers(gameId).values()) {
MagePermanent permanent = pa.getBattlefieldPanel().getPermanents().get(defenderId);
if (permanent != null) {
Point target = permanent.getLocationOnScreen();
@ -104,7 +104,7 @@ public enum CombatManager {
private void drawBlockers(CombatGroupView group, MagePermanent attackerCard, UUID gameId) {
for (CardView blocker : group.getBlockers().values()) {
for (PlayAreaPanel pa : MageFrame.getGame(gameId).getPlayers().values()) {
for (PlayAreaPanel pa : MageFrame.getGamePlayers(gameId).values()) {
MagePermanent blockerCard = pa.getBattlefieldPanel().getPermanents().get(blocker.getId());
if (blockerCard != null) {
parentPoint = getParentPoint(blockerCard);

View file

@ -8,6 +8,7 @@ import mage.client.components.ext.dlg.DialogContainer;
import mage.client.components.ext.dlg.DialogManager;
import mage.client.components.ext.dlg.DlgParams;
import mage.client.components.ext.dlg.IDialogPanel;
import mage.client.dialog.PreferencesDialog;
import mage.client.plugins.impl.Plugins;
import mage.client.util.Command;
import mage.client.util.SettingsManager;
@ -162,7 +163,7 @@ public class ChoiceDialog extends IDialogPanel {
}
CardView card = cardList.get(i);
MageCard cardImg = Plugins.instance.getMageCard(card, bigCard, getCardDimension(), gameId, true, true);
MageCard cardImg = Plugins.instance.getMageCard(card, bigCard, getCardDimension(), gameId, true, true, PreferencesDialog.getRenderMode());
cardImg.setLocation(dx, dy + j * (height + 30));
add(cardImg);

View file

@ -7,6 +7,7 @@ import mage.client.components.ext.dlg.DialogContainer;
import mage.client.components.ext.dlg.DialogManager;
import mage.client.components.ext.dlg.DlgParams;
import mage.client.components.ext.dlg.IDialogPanel;
import mage.client.dialog.PreferencesDialog;
import mage.client.game.FeedbackPanel;
import mage.client.plugins.impl.Plugins;
import mage.client.util.Command;
@ -33,14 +34,14 @@ public class StackDialog extends IDialogPanel {
private JLayeredPane jLayeredPane;
private final FeedbackPanel feedbackPanel;
private final UUID gameId;
private static class CustomLabel extends JLabel {
@Override
public void paintComponent(Graphics g) {
Graphics2D g2D = (Graphics2D)g;
Graphics2D g2D = (Graphics2D) g;
g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
@ -66,7 +67,7 @@ public class StackDialog extends IDialogPanel {
/**
* This method initializes this
*
*
* @return void
*/
private void initialize() {
@ -111,7 +112,7 @@ public class StackDialog extends IDialogPanel {
for (CardView card : cards.values()) {
if (card instanceof StackAbilityView) {
CardView tmp = ((StackAbilityView)card).getSourceCard();
CardView tmp = ((StackAbilityView) card).getSourceCard();
tmp.overrideRules(card.getRules());
tmp.setIsAbility(true);
tmp.overrideTargets(card.getTargets());
@ -119,7 +120,7 @@ public class StackDialog extends IDialogPanel {
card = tmp;
}
MageCard cardImg = Plugins.instance.getMageCard(card, bigCard, getCardDimension(), gameId, true, true);
MageCard cardImg = Plugins.instance.getMageCard(card, bigCard, getCardDimension(), gameId, true, true, PreferencesDialog.getRenderMode());
//cardImg.setBorder(BorderFactory.createLineBorder(Color.red));
cardImg.setLocation(dx, dy);
@ -143,10 +144,11 @@ public class StackDialog extends IDialogPanel {
jButtonAccept.setObserver(new Command() {
@Override
public void execute() {
DialogManager.getManager(gameId).fadeOut((DialogContainer)getParent());
DialogManager.getManager(gameId).fadeOut((DialogContainer) getParent());
//GameManager.getInputControl().getInput().selectButtonOK();
StackDialog.this.feedbackPanel.doClick();
}
private static final long serialVersionUID = 1L;
});
}
@ -166,11 +168,12 @@ public class StackDialog extends IDialogPanel {
jButtonResponse.setObserver(new Command() {
@Override
public void execute() {
DialogManager.getManager(gameId).fadeOut((DialogContainer)getParent());
DialogManager.getManager(gameId).fadeOut((DialogContainer) getParent());
}
private static final long serialVersionUID = 1L;
});
}
return jButtonResponse;
}
}
}

View file

@ -136,7 +136,7 @@ public class DeckGeneratorPool
int cardCount = getCardCount((card.getName()));
// No need to check if the land is valid for the colors chosen
// They are all filtered before searching for lands to include in the deck.
return (cardCount < 4);
return (cardCount < (isSingleton ? 1 : 4));
}

View file

@ -447,7 +447,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
}
}
});
refreshDeck();
refreshDeck(true);
if (mode == DeckEditorMode.FREE_BUILDING) {
setDropTarget(new DropTarget(this, new DnDDeckTargetListener() {
@ -1414,14 +1414,15 @@ class ImportFilter extends FileFilter {
|| ext.equalsIgnoreCase("txt")
|| ext.equalsIgnoreCase("dek")
|| ext.equalsIgnoreCase("cod")
|| ext.equalsIgnoreCase("o8d");
|| ext.equalsIgnoreCase("o8d")
|| ext.equalsIgnoreCase("draft");
}
return false;
}
@Override
public String getDescription() {
return "All formats (*.dec; *.mwDeck; *.txt; *.dek; *.cod; *.o8d)";
return "All formats (*.dec; *.mwDeck; *.txt; *.dek; *.cod; *.o8d; *.draft)";
}
}

View file

@ -8,6 +8,7 @@ import mage.cards.repository.ExpansionRepository;
import mage.client.MageFrame;
import mage.client.cards.BigCard;
import mage.client.components.HoverButton;
import mage.client.dialog.PreferencesDialog;
import mage.client.plugins.impl.Plugins;
import mage.client.util.Config;
import mage.client.util.ImageHelper;
@ -406,7 +407,7 @@ public class MageBook extends JComponent {
if (cardDimension == null) {
cardDimension = new Dimension(Config.dimensions.getFrameWidth(), Config.dimensions.getFrameHeight());
}
final MageCard cardImg = Plugins.instance.getMageCard(card, bigCard, cardDimension, gameId, true, true);
final MageCard cardImg = Plugins.instance.getMageCard(card, bigCard, cardDimension, gameId, true, true, PreferencesDialog.getRenderMode());
cardImg.setBounds(rectangle);
jLayeredPane.add(cardImg, JLayeredPane.DEFAULT_LAYER, 10);
cardImg.update(card);
@ -447,7 +448,7 @@ public class MageBook extends JComponent {
newToken.removeSummoningSickness();
PermanentView theToken = new PermanentView(newToken, null, null, null);
theToken.setInViewerOnly(true);
final MageCard cardImg = Plugins.instance.getMagePermanent(theToken, bigCard, cardDimension, gameId, true);
final MageCard cardImg = Plugins.instance.getMagePermanent(theToken, bigCard, cardDimension, gameId, true, PreferencesDialog.getRenderMode());
cardImg.setBounds(rectangle);
jLayeredPane.add(cardImg, JLayeredPane.DEFAULT_LAYER, 10);
cardImg.update(theToken);

View file

@ -23,26 +23,26 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="jLabel3" alignment="0" max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="scrollDevs" max="32767" attributes="0"/>
<Group type="102" alignment="1" attributes="0">
<Component id="btnWhatsNew" min="-2" pref="100" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="btnOk" min="-2" pref="100" max="-2" attributes="0"/>
</Group>
<Component id="jLabel4" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="1" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblVersion" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="labelDevs" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<EmptySpace min="0" pref="80" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
@ -60,10 +60,10 @@
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel3" min="-2" pref="21" max="-2" attributes="0"/>
<Component id="labelDevs" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="scrollDevs" pref="161" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel4" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="68" max="32767" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="btnOk" alignment="3" min="-2" pref="30" max="-2" attributes="0"/>
<Component id="btnWhatsNew" alignment="3" min="-2" pref="30" max="-2" attributes="0"/>
@ -94,17 +94,7 @@
</Component>
<Component class="javax.swing.JLabel" name="jLabel2">
<Properties>
<Property name="text" type="java.lang.String" value="Courtesy: BetaSteward@googlemail.com. Site: http://XMage.de/"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel3">
<Properties>
<Property name="text" type="java.lang.String" value="Devs: BetaSteward, Noxx, Eugen.Rivniy, North, LevelX2, Jeff, Plopman, dustinconrad, emerald000.,"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel4">
<Properties>
<Property name="text" type="java.lang.String" value="fireshoes, lunaskyrise, mnapoleon, jgod, LoneFox."/>
<Property name="text" type="java.lang.String" value="Courtesy: BetaSteward@googlemail.com. Site: http://xmage.de/"/>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="btnWhatsNew">
@ -115,5 +105,26 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnWhatsNewActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JScrollPane" name="scrollDevs">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="null"/>
</Property>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextPane" name="panelDevs">
<Properties>
<Property name="editable" type="boolean" value="false"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="labelDevs">
<Properties>
<Property name="text" type="java.lang.String" value="Developers:"/>
</Properties>
</Component>
</SubComponents>
</Form>

View file

@ -6,15 +6,20 @@ import mage.utils.MageVersion;
import javax.swing.*;
import java.awt.event.KeyEvent;
/**
* @author JayDi85
*/
public class AboutDialog extends MageDialog {
private static String devsList = "BetaSteward, Noxx, Eugen.Rivniy, North, LevelX2, "
+ "Jeff, Plopman, dustinconrad, emerald000, fireshoes, lunaskyrise, "
+ "mnapoleon, jgod, LoneFox, drmDev, spjspj, TheElk801, L_J, JayDi85, "
+ "jmharmon, Ketsuban, hitch17";
public AboutDialog() {
initComponents();
this.modal = false;
panelDevs.setText(devsList + " and hundreds of other developers from https://github.com/magefree/mage/graphs/contributors");
}
public void showDialog(MageVersion version) {
@ -54,9 +59,10 @@ public class AboutDialog extends MageDialog {
jLabel1 = new javax.swing.JLabel();
lblVersion = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
jLabel3 = new javax.swing.JLabel();
jLabel4 = new javax.swing.JLabel();
btnWhatsNew = new javax.swing.JButton();
scrollDevs = new javax.swing.JScrollPane();
panelDevs = new javax.swing.JTextPane();
labelDevs = new javax.swing.JLabel();
setMaximizable(true);
setTitle("About XMage");
@ -72,11 +78,7 @@ public class AboutDialog extends MageDialog {
lblVersion.setText("0.0.0");
jLabel2.setText("Courtesy: BetaSteward@googlemail.com. Site: http://XMage.de/");
jLabel3.setText("Devs: BetaSteward, Noxx, Eugen.Rivniy, North, LevelX2, Jeff, Plopman, dustinconrad, emerald000.,");
jLabel4.setText("fireshoes, lunaskyrise, mnapoleon, jgod, LoneFox.");
jLabel2.setText("Courtesy: BetaSteward@googlemail.com. Site: http://xmage.de/");
btnWhatsNew.setText("What's new");
btnWhatsNew.addActionListener(new java.awt.event.ActionListener() {
@ -85,27 +87,34 @@ public class AboutDialog extends MageDialog {
}
});
scrollDevs.setBorder(null);
panelDevs.setEditable(false);
scrollDevs.setViewportView(panelDevs);
labelDevs.setText("Developers:");
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()
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jLabel3, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(scrollDevs)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(btnWhatsNew, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnOk, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(jLabel4, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblVersion))
.addComponent(jLabel2, javax.swing.GroupLayout.Alignment.LEADING))
.addGap(0, 0, Short.MAX_VALUE)))
.addComponent(jLabel2)
.addComponent(labelDevs))
.addGap(0, 80, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
@ -118,10 +127,10 @@ public class AboutDialog extends MageDialog {
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel3, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(labelDevs)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(scrollDevs, javax.swing.GroupLayout.DEFAULT_SIZE, 161, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel4)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 68, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnOk, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnWhatsNew, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE))
@ -144,9 +153,10 @@ public class AboutDialog extends MageDialog {
private javax.swing.JButton btnWhatsNew;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JLabel labelDevs;
private javax.swing.JLabel lblVersion;
private javax.swing.JTextPane panelDevs;
private javax.swing.JScrollPane scrollDevs;
// End of variables declaration//GEN-END:variables
}

View file

@ -88,6 +88,9 @@ public class ConnectDialog extends MageDialog {
MagePreferences.setUserName(serverAddress, txtUserName.getText().trim());
MagePreferences.setPassword(serverAddress, String.valueOf(txtPassword.getPassword()).trim());
MageFrame.getPreferences().put(KEY_CONNECT_AUTO_CONNECT, Boolean.toString(chkAutoConnect.isSelected()));
// last settings for reconnect
MagePreferences.saveLastServer();
}
/**
@ -517,7 +520,6 @@ public class ConnectDialog extends MageDialog {
char[] input = new char[0];
try {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
connection = new Connection();
connection.setHost(this.txtServer.getText().trim());
connection.setPort(Integer.valueOf(this.txtPort.getText().trim()));
@ -545,6 +547,12 @@ public class ConnectDialog extends MageDialog {
}//GEN-LAST:event_btnConnectActionPerformed
private void setConnectButtonsState(boolean enable) {
btnConnect.setEnabled(enable);
btnRegister.setEnabled(enable);
btnForgotPassword.setEnabled(enable);
}
private class ConnectTask extends SwingWorker<Boolean, Void> {
private boolean result = false;
@ -555,7 +563,7 @@ public class ConnectDialog extends MageDialog {
@Override
protected Boolean doInBackground() throws Exception {
lblStatus.setText("Connecting...");
btnConnect.setEnabled(false);
setConnectButtonsState(false);
result = MageFrame.connect(connection);
lastConnectError = SessionHandler.getLastConnectError();
return result;
@ -565,7 +573,6 @@ public class ConnectDialog extends MageDialog {
protected void done() {
try {
get(CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS);
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
if (result) {
lblStatus.setText("");
connected();
@ -578,13 +585,13 @@ public class ConnectDialog extends MageDialog {
} catch (ExecutionException ex) {
logger.fatal("Update Players Task error", ex);
} catch (CancellationException ex) {
logger.info("Connect was canceled");
logger.info("Connect: canceled");
lblStatus.setText("Connect was canceled");
} catch (TimeoutException ex) {
logger.fatal("Connection timeout: ", ex);
} finally {
MageFrame.stopConnecting();
btnConnect.setEnabled(true);
setConnectButtonsState(true);
}
}
}

View file

@ -109,6 +109,7 @@ public class MageDialog extends javax.swing.JInternalFrame {
SwingUtilities.invokeAndWait(() -> stopModal());
} catch (InterruptedException ex) {
LOGGER.fatal("MageDialog error", ex);
Thread.currentThread().interrupt();
} catch (InvocationTargetException ex) {
LOGGER.fatal("MageDialog error", ex);
}
@ -184,9 +185,10 @@ public class MageDialog extends javax.swing.JInternalFrame {
wait();
}
}
} catch (InterruptedException ignored) {
} catch (InterruptedException e) {
LOGGER.fatal("MageDialog error", e);
Thread.currentThread().interrupt();
}
}
private synchronized void stopModal() {

View file

@ -637,13 +637,18 @@ public class NewTableDialog extends MageDialog {
case "Variant Magic - Commander":
case "Variant Magic - Duel Commander":
case "Variant Magic - MTGO 1v1 Commander":
case "Variant Magic - Freeform Commander":
case "Variant Magic - Penny Dreadful Commander":
if (!options.getGameType().startsWith("Commander")) {
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Deck type Commander needs also a Commander game type", "Error", JOptionPane.ERROR_MESSAGE);
return false;
}
break;
case "Variant Magic - Freeform Commander":
if (!options.getGameType().startsWith("Freeform Commander")) {
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Deck type Freeform Commander needs also a Freeform Commander game type", "Error", JOptionPane.ERROR_MESSAGE);
return false;
}
break;
case "Variant Magic - Brawl":
case "Variant Magic - Duel Brawl":
if (!options.getGameType().startsWith("Brawl")) {
@ -678,6 +683,13 @@ public class NewTableDialog extends MageDialog {
return false;
}
break;
case "Freeform Commander Two Player Duel":
case "Freeform Commander Free For All":
if (!options.getDeckType().equals("Variant Magic - Freeform Commander")) {
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Deck type Freeform Commander needs also a Freeform Commander game type", "Error", JOptionPane.ERROR_MESSAGE);
return false;
}
break;
case "Brawl Two Player Duel":
case "Brawl Free For All":
if (!options.getDeckType().equals("Variant Magic - Brawl")

View file

@ -31,6 +31,7 @@ import java.awt.*;
import java.io.File;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author BetaSteward_at_googlemail.com, JayDi85
@ -655,7 +656,7 @@ public class NewTournamentDialog extends MageDialog {
}// </editor-fold>//GEN-END:initComponents
private void cbTournamentTypeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbTournamentTypeActionPerformed
setTournamentOptions((Integer) this.spnNumPlayers.getValue());
prepareTourneyView((Integer) this.spnNumPlayers.getValue());
}//GEN-LAST:event_cbTournamentTypeActionPerformed
private void btnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOkActionPerformed
@ -663,6 +664,15 @@ public class NewTournamentDialog extends MageDialog {
// get settings
TournamentOptions tOptions = getTournamentOptions();
// CHECKS
TournamentTypeView tournamentType = (TournamentTypeView) cbTournamentType.getSelectedItem();
if (tournamentType.isRandom() || tournamentType.isRichMan()) {
if (tOptions.getLimitedOptions().getSetCodes().isEmpty()) {
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Warning, you must select packs for the pool", "Warning", JOptionPane.WARNING_MESSAGE);
return;
}
}
// save last settings
onSaveSettings(0, tOptions);
@ -837,19 +847,25 @@ public class NewTournamentDialog extends MageDialog {
createPlayers((Integer) spnNumPlayers.getValue() - 1);
}
private void setTournamentOptions(int numPlayers) {
private void prepareTourneyView(int numPlayers) {
TournamentTypeView tournamentType = (TournamentTypeView) cbTournamentType.getSelectedItem();
activatePanelElements(tournamentType);
// players
if (numPlayers < tournamentType.getMinPlayers() || numPlayers > tournamentType.getMaxPlayers()) {
numPlayers = tournamentType.getMinPlayers();
createPlayers(numPlayers - 1);
createPlayers(numPlayers - 1); // ?
}
this.spnNumPlayers.setModel(new SpinnerNumberModel(numPlayers, tournamentType.getMinPlayers(), tournamentType.getMaxPlayers(), 1));
this.spnNumPlayers.setEnabled(tournamentType.getMinPlayers() != tournamentType.getMaxPlayers());
createPlayers((Integer) spnNumPlayers.getValue() - 1);
this.spnNumSeats.setModel(new SpinnerNumberModel(2, 2, tournamentType.getMaxPlayers(), 1));
// packs
preparePacksView(tournamentType);
}
private void preparePacksView(TournamentTypeView tournamentType) {
if (tournamentType.isLimited()) {
this.isRandom = tournamentType.isRandom();
this.isRichMan = tournamentType.isRichMan();
@ -859,7 +875,6 @@ public class NewTournamentDialog extends MageDialog {
createPacks(tournamentType.getNumBoosters());
}
}
}
private void setNumberOfSwissRoundsMin(int numPlayers) {
@ -921,6 +936,43 @@ public class NewTournamentDialog extends MageDialog {
}
}
private String prepareVersionStr(int version, boolean saveMode) {
// version: 0, 1, 2... to save/load
// version: -1 to reset (load from empty record)
switch (version) {
case -1:
return saveMode ? "" : "-1"; // can't save to -1 version
case 1:
return "1";
case 2:
return "2";
default:
return "";
}
}
private void loadRandomPacks(int version) {
String versionStr = prepareVersionStr(version, false);
ArrayList<String> packList;
String packNames;
String randomPrefs = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_PACKS_RANDOM_DRAFT + versionStr, "");
if (!randomPrefs.isEmpty()) {
packList = new ArrayList<>(Arrays.asList(randomPrefs.split(";")));
packNames = randomPrefs;
} else {
ExpansionInfo[] allExpansions = ExpansionRepository.instance.getWithBoostersSortedByReleaseDate();
packList = Arrays.stream(allExpansions).map(ExpansionInfo::getCode).collect(Collectors.toCollection(ArrayList::new));
packNames = Arrays.stream(allExpansions).map(ExpansionInfo::getCode).collect(Collectors.joining(";"));
}
randomPackSelector.setSelectedPacks(packList);
txtRandomPacks.setText(packNames);
// workaround to apply field's auto-size
this.pack();
this.revalidate();
this.repaint();
}
private void createRandomPacks() {
if (pnlRandomPacks.getComponentCount() == 0) {
if (randomPackSelector == null) {
@ -930,20 +982,9 @@ public class NewTournamentDialog extends MageDialog {
txtRandomPacks = new JTextArea();
txtRandomPacks.setEnabled(false);
txtRandomPacks.setLineWrap(true);
String randomPrefs = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_PACKS_RANDOM_DRAFT, "");
if (!randomPrefs.isEmpty()) {
txtRandomPacks.setText(randomPrefs);
ArrayList<String> theList = new ArrayList<>(Arrays.asList(randomPrefs.split(";")));
randomPackSelector.setSelectedPacks(theList);
} else {
ExpansionInfo[] allExpansions = ExpansionRepository.instance.getWithBoostersSortedByReleaseDate();
StringBuilder packList = new StringBuilder();
for (ExpansionInfo exp : allExpansions) {
packList.append(exp.getCode());
packList.append(';');
}
txtRandomPacks.setText(packList.toString());
}
loadRandomPacks(-1); // load default packs
txtRandomPacks.setAlignmentX(Component.LEFT_ALIGNMENT);
pnlRandomPacks.add(txtRandomPacks);
JButton btnSelectRandomPacks = new JButton();
@ -953,6 +994,7 @@ public class NewTournamentDialog extends MageDialog {
btnSelectRandomPacks.addActionListener(evt -> showRandomPackSelectorDialog());
pnlRandomPacks.add(btnSelectRandomPacks);
}
txtRandomPacks.setText(txtRandomPacks.getText()); // workaround to apply field's auto-size
this.pack();
this.revalidate();
this.repaint();
@ -961,12 +1003,7 @@ public class NewTournamentDialog extends MageDialog {
private void showRandomPackSelectorDialog() {
randomPackSelector.setType(isRandom, isRichMan);
randomPackSelector.showDialog();
StringBuilder packList = new StringBuilder();
for (String str : randomPackSelector.getSelectedPacks()) {
packList.append(str);
packList.append(';');
}
this.txtRandomPacks.setText(packList.toString());
this.txtRandomPacks.setText(String.join(";", randomPackSelector.getSelectedPacks()));
this.pack();
this.revalidate();
this.repaint();
@ -1169,6 +1206,7 @@ public class NewTournamentDialog extends MageDialog {
if (tournamentType.isLimited()) {
tOptions.getLimitedOptions().setConstructionTime((Integer) this.spnConstructTime.getValue() * 60);
tOptions.getLimitedOptions().setIsRandom(tournamentType.isRandom());
tOptions.getLimitedOptions().setIsRichMan(tournamentType.isRichMan());
if (tournamentType.isCubeBooster()) {
tOptions.getLimitedOptions().setDraftCubeName(this.cbDraftCube.getSelectedItem().toString());
if (!(cubeFromDeckFilename.isEmpty())) {
@ -1188,6 +1226,7 @@ public class NewTournamentDialog extends MageDialog {
this.isRichMan = tournamentType.isRichMan();
tOptions.getLimitedOptions().getSetCodes().clear();
ArrayList<String> selected = randomPackSelector.getSelectedPacks();
Collections.shuffle(selected);
int maxPacks = 3 * (players.size() + 1);
if (tournamentType.isRichMan()) {
maxPacks = 36;
@ -1197,7 +1236,6 @@ public class NewTournamentDialog extends MageDialog {
infoString.append(maxPacks);
infoString.append(" sets will be randomly chosen.");
JOptionPane.showMessageDialog(MageFrame.getDesktop(), infoString, "Information", JOptionPane.INFORMATION_MESSAGE);
Collections.shuffle(selected);
tOptions.getLimitedOptions().getSetCodes().addAll(selected.subList(0, maxPacks));
} else {
tOptions.getLimitedOptions().getSetCodes().addAll(selected);
@ -1242,23 +1280,7 @@ public class NewTournamentDialog extends MageDialog {
}
private void onLoadSettings(int version) {
String versionStr = "";
switch (version) {
case -1:
versionStr = "-1"; // default (empty)
break;
case 1:
versionStr = "1";
break;
case 2:
versionStr = "2";
break;
default:
versionStr = "";
break;
}
String versionStr = prepareVersionStr(version, false);
int numPlayers;
txtName.setText(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_NAME + versionStr, "Tournament"));
txtPassword.setText(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_PASSWORD + versionStr, ""));
@ -1298,16 +1320,13 @@ public class NewTournamentDialog extends MageDialog {
activatePanelElements(tournamentType);
if (tournamentType.isLimited()) {
if (!tournamentType.isDraft()) {
numPlayers = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_PLAYERS_SEALED + versionStr, "2"));
setTournamentOptions(numPlayers);
loadBoosterPacks(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_PACKS_SEALED + versionStr, ""));
}
if (tournamentType.isDraft()) {
numPlayers = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_PLAYERS_DRAFT + versionStr, "4"));
setTournamentOptions(numPlayers);
if (!(tournamentType.isRandom() || tournamentType.isRichMan())) {
prepareTourneyView(numPlayers);
if (tournamentType.isRandom() || tournamentType.isRichMan()) {
loadRandomPacks(version);
} else {
loadBoosterPacks(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_PACKS_DRAFT + versionStr, ""));
}
@ -1318,6 +1337,10 @@ public class NewTournamentDialog extends MageDialog {
break;
}
}
} else {
numPlayers = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_PLAYERS_SEALED + versionStr, "2"));
prepareTourneyView(numPlayers);
loadBoosterPacks(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_PACKS_SEALED + versionStr, ""));
}
}
this.cbAllowSpectators.setSelected(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_ALLOW_SPECTATORS + versionStr, "Yes").equals("Yes"));
@ -1332,20 +1355,7 @@ public class NewTournamentDialog extends MageDialog {
}
private void onSaveSettings(int version, TournamentOptions tOptions) {
String versionStr = "";
switch (version) {
case 1:
versionStr = "1";
break;
case 2:
versionStr = "2";
break;
default:
versionStr = "";
break;
}
String versionStr = prepareVersionStr(version, true);
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_NAME + versionStr, tOptions.getName());
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_PASSWORD + versionStr, tOptions.getPassword());
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_TIME_LIMIT + versionStr, Integer.toString(tOptions.getMatchOptions().getPriorityTime()));
@ -1375,15 +1385,8 @@ public class NewTournamentDialog extends MageDialog {
if (deckFile != null && !deckFile.isEmpty()) {
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_DECK_FILE + versionStr, deckFile);
}
if (tOptions.getLimitedOptions().getIsRandom()) {
// save random boosters to prefs
StringBuilder packlist = new StringBuilder();
for (String pack : this.randomPackSelector.getSelectedPacks()) {
packlist.append(pack);
packlist.append(';');
}
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_PACKS_RANDOM_DRAFT + versionStr, packlist.toString());
if (tOptions.getLimitedOptions().getIsRandom() || tOptions.getLimitedOptions().getIsRichMan()) {
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_PACKS_RANDOM_DRAFT + versionStr, String.join(";", this.randomPackSelector.getSelectedPacks()));
}
}
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_ALLOW_SPECTATORS + versionStr, (tOptions.isWatchingAllowed() ? "Yes" : "No"));

View file

@ -24,7 +24,7 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="tabsPanel" alignment="0" max="32767" attributes="0"/>
@ -42,7 +42,7 @@
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="tabsPanel" max="32767" attributes="0"/>
<Component id="tabsPanel" min="-2" pref="554" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="saveButton" alignment="3" min="-2" pref="30" max="-2" attributes="0"/>
@ -98,7 +98,7 @@
<Component id="main_gamelog" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="main_battlefield" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<EmptySpace pref="39" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -4071,7 +4071,7 @@
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="phases_stopSettings" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="160" max="32767" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -4296,12 +4296,12 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="panelCardImages" max="32767" attributes="0"/>
<Component id="jPanel1" max="32767" attributes="0"/>
<Component id="panelBackgroundImages" max="32767" attributes="0"/>
<Component id="panelBackgroundImages" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
@ -4316,7 +4316,7 @@
<Component id="panelCardImages" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="panelBackgroundImages" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="133" max="32767" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -4341,6 +4341,7 @@
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="cbUseDefaultImageFolder" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtImageFolderPath" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
@ -4348,34 +4349,24 @@
</Group>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
<Group type="102" attributes="0">
<Component id="cbCheckForNewImages" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="147" max="-2" attributes="0"/>
<Component id="cbSaveToZipFiles" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="labelNumberOfDownloadThreads" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="labelPreferedImageLanguage" alignment="0" max="-2" attributes="0"/>
</Group>
<Group type="103" alignment="0" groupAlignment="1" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="1" max="-2" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="labelPreferedImageLanguage" max="-2" attributes="0"/>
</Group>
<Component id="cbSaveToZipFiles" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="20" max="-2" attributes="0"/>
<Component id="cbPreferedImageLanguage" min="-2" pref="153" max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="labelNumberOfDownloadThreads" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="cbPreferedImageLanguage" min="-2" pref="153" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="cbNumberOfDownloadThreads" min="-2" pref="153" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="labelHint1" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
<Component id="cbUseDefaultImageFolder" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="391" max="32767" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
@ -4385,25 +4376,23 @@
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="cbUseDefaultImageFolder" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="cbUseDefaultImageFolder" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtImageFolderPath" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnBrowseImageLocation" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
<Component id="cbCheckForNewImages" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="cbSaveToZipFiles" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="labelNumberOfDownloadThreads" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="cbNumberOfDownloadThreads" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="labelHint1" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="cbPreferedImageLanguage" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="labelPreferedImageLanguage" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="cbPreferedImageLanguage" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
@ -4431,14 +4420,6 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnBrowseImageLocationActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="cbCheckForNewImages">
<Properties>
<Property name="text" type="java.lang.String" value="Check for new images on startup"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbCheckForNewImagesActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="cbSaveToZipFiles">
<Properties>
<Property name="text" type="java.lang.String" value="Store images in zip files"/>
@ -4465,7 +4446,7 @@
</Component>
<Component class="javax.swing.JLabel" name="labelPreferedImageLanguage">
<Properties>
<Property name="text" type="java.lang.String" value="Prefered image language:"/>
<Property name="text" type="java.lang.String" value="Default images language:"/>
<Property name="focusable" type="boolean" value="false"/>
</Properties>
</Component>
@ -4487,145 +4468,9 @@
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="panelBackgroundImages">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="Background images">
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
<EtchetBorder/>
</Border>
</TitledBorder>
</Border>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" pref="19" max="-2" attributes="0"/>
<Component id="jLabel14" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<EmptySpace min="-2" pref="25" max="-2" attributes="0"/>
<Component id="jLabel15" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="txtBackgroundImagePath" max="32767" attributes="0"/>
<Component id="txtBattlefieldImagePath" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="btnBrowseBackgroundImage" alignment="1" min="-2" max="-2" attributes="0"/>
<Component id="btnBrowseBattlefieldImage" alignment="1" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="cbUseRandomBattleImage" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="cbUseDefaultBattleImage" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="cbUseDefaultBackground" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="32767" 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">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="cbUseDefaultBackground" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="txtBackgroundImagePath" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnBrowseBackgroundImage" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel14" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="cbUseDefaultBattleImage" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="cbUseRandomBattleImage" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="txtBattlefieldImagePath" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnBrowseBattlefieldImage" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel15" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JCheckBox" name="cbUseDefaultBackground">
<Component class="javax.swing.JLabel" name="labelHint1">
<Properties>
<Property name="text" type="java.lang.String" value="Use default image"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbUseDefaultBackgroundActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JTextField" name="txtBackgroundImagePath">
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtBackgroundImagePathActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnBrowseBackgroundImage">
<Properties>
<Property name="text" type="java.lang.String" value="Browse..."/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnBrowseBackgroundImageActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JTextField" name="txtBattlefieldImagePath">
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtBattlefieldImagePathActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnBrowseBattlefieldImage">
<Properties>
<Property name="text" type="java.lang.String" value="Browse..."/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnBrowseBattlefieldImageActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="cbUseDefaultBattleImage">
<Properties>
<Property name="text" type="java.lang.String" value="Use default battlefield image"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbUseDefaultBattleImageActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="cbUseRandomBattleImage">
<Properties>
<Property name="text" type="java.lang.String" value="Select random battlefield image"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbUseRandomBattleImageActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabel14">
<Properties>
<Property name="text" type="java.lang.String" value="Background:"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel15">
<Properties>
<Property name="text" type="java.lang.String" value="Battlefield:"/>
<Property name="text" type="java.lang.String" value="(change it to 1-3 if image source bans your IP for too many connections)"/>
</Properties>
</Component>
</SubComponents>
@ -4696,6 +4541,121 @@
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="panelBackgroundImages">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="Background images">
<Border PropertyName="innerBorder" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
<EtchetBorder/>
</Border>
</TitledBorder>
</Border>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="cbUseDefaultBackground" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="txtBackgroundImagePath" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnBrowseBackgroundImage" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="cbUseRandomBattleImage" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="txtBattlefieldImagePath" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnBrowseBattlefieldImage" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Component id="cbUseDefaultBattleImage" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" 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="cbUseDefaultBattleImage" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="cbUseDefaultBackground" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtBackgroundImagePath" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnBrowseBackgroundImage" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="cbUseRandomBattleImage" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtBattlefieldImagePath" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnBrowseBattlefieldImage" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JCheckBox" name="cbUseDefaultBackground">
<Properties>
<Property name="text" type="java.lang.String" value="Use default location for backgrounds"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbUseDefaultBackgroundActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JTextField" name="txtBackgroundImagePath">
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtBackgroundImagePathActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnBrowseBackgroundImage">
<Properties>
<Property name="text" type="java.lang.String" value="Browse..."/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnBrowseBackgroundImageActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JTextField" name="txtBattlefieldImagePath">
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtBattlefieldImagePathActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnBrowseBattlefieldImage">
<Properties>
<Property name="text" type="java.lang.String" value="Browse..."/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnBrowseBattlefieldImageActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="cbUseDefaultBattleImage">
<Properties>
<Property name="text" type="java.lang.String" value="Use default battlefield image"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbUseDefaultBattleImageActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="cbUseRandomBattleImage">
<Properties>
<Property name="text" type="java.lang.String" value="Use random background"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbUseRandomBattleImageActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="tabSounds">
@ -4891,7 +4851,7 @@
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="avatarPane" pref="620" max="32767" attributes="0"/>
<Component id="avatarPane" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
@ -5802,7 +5762,7 @@
<Component id="jLabel17" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace pref="251" max="32767" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -5811,7 +5771,7 @@
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="lblURLServerList" max="32767" attributes="0"/>
<Component id="txtURLServerList" pref="28" max="32767" attributes="0"/>
<Component id="txtURLServerList" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel17" min="-2" max="-2" attributes="0"/>
@ -6068,7 +6028,7 @@
</Group>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="controlsDescriptionLabel" pref="481" max="32767" attributes="0"/>
<Component id="controlsDescriptionLabel" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>

View file

@ -78,7 +78,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
public static final String KEY_CARD_IMAGES_USE_DEFAULT = "cardImagesUseDefault";
public static final String KEY_CARD_IMAGES_PATH = "cardImagesPath";
public static final String KEY_CARD_IMAGES_THREADS = "cardImagesThreads";
public static final String KEY_CARD_IMAGES_CHECK = "cardImagesCheck";
public static final String KEY_CARD_IMAGES_SAVE_TO_ZIP = "cardImagesSaveToZip";
public static final String KEY_CARD_IMAGES_PREF_LANGUAGE = "cardImagesPreferedImageLaguage";
@ -468,12 +467,16 @@ public class PreferencesDialog extends javax.swing.JDialog {
cbUseDefaultImageFolder = new javax.swing.JCheckBox();
txtImageFolderPath = new javax.swing.JTextField();
btnBrowseImageLocation = new javax.swing.JButton();
cbCheckForNewImages = new javax.swing.JCheckBox();
cbSaveToZipFiles = new javax.swing.JCheckBox();
cbPreferedImageLanguage = new javax.swing.JComboBox<>();
labelPreferedImageLanguage = new javax.swing.JLabel();
labelNumberOfDownloadThreads = new javax.swing.JLabel();
cbNumberOfDownloadThreads = new javax.swing.JComboBox();
labelHint1 = new javax.swing.JLabel();
jPanel1 = new javax.swing.JPanel();
cbCardRenderImageFallback = new javax.swing.JCheckBox();
cbCardRenderShowReminderText = new javax.swing.JCheckBox();
cbCardRenderHideSetSymbol = new javax.swing.JCheckBox();
panelBackgroundImages = new javax.swing.JPanel();
cbUseDefaultBackground = new javax.swing.JCheckBox();
txtBackgroundImagePath = new javax.swing.JTextField();
@ -482,12 +485,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
btnBrowseBattlefieldImage = new javax.swing.JButton();
cbUseDefaultBattleImage = new javax.swing.JCheckBox();
cbUseRandomBattleImage = new javax.swing.JCheckBox();
jLabel14 = new javax.swing.JLabel();
jLabel15 = new javax.swing.JLabel();
jPanel1 = new javax.swing.JPanel();
cbCardRenderImageFallback = new javax.swing.JCheckBox();
cbCardRenderShowReminderText = new javax.swing.JCheckBox();
cbCardRenderHideSetSymbol = new javax.swing.JCheckBox();
tabSounds = new javax.swing.JPanel();
sounds_clips = new javax.swing.JPanel();
cbEnableGameSounds = new javax.swing.JCheckBox();
@ -872,7 +869,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
.add(main_gamelog, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(main_battlefield, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap(39, Short.MAX_VALUE))
);
main_card.getAccessibleContext().setAccessibleName("Game panel");
@ -1535,7 +1532,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
.add(checkBoxEndTurnOthers))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
.add(phases_stopSettings, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addContainerGap(160, Short.MAX_VALUE))
.addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
tabsPanel.addTab("Phases & Priority", tabPhases);
@ -1558,13 +1555,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
}
});
cbCheckForNewImages.setText("Check for new images on startup");
cbCheckForNewImages.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cbCheckForNewImagesActionPerformed(evt);
}
});
cbSaveToZipFiles.setText("Store images in zip files");
cbSaveToZipFiles.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
@ -1575,7 +1565,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
cbPreferedImageLanguage.setMaximumRowCount(20);
cbPreferedImageLanguage.setModel(new javax.swing.DefaultComboBoxModel<>(new String[]{"Item 1", "Item 2", "Item 3", "Item 4"}));
labelPreferedImageLanguage.setText("Prefered image language:");
labelPreferedImageLanguage.setText("Default images language:");
labelPreferedImageLanguage.setFocusable(false);
labelNumberOfDownloadThreads.setText("Number of download threads:");
@ -1583,6 +1573,8 @@ public class PreferencesDialog extends javax.swing.JDialog {
cbNumberOfDownloadThreads.setMaximumRowCount(20);
cbNumberOfDownloadThreads.setModel(new javax.swing.DefaultComboBoxModel(new String[]{"Item 1", "Item 2", "Item 3", "Item 4"}));
labelHint1.setText("(change it to 1-3 if image source bans your IP for too many connections)");
org.jdesktop.layout.GroupLayout panelCardImagesLayout = new org.jdesktop.layout.GroupLayout(panelCardImages);
panelCardImages.setLayout(panelCardImagesLayout);
panelCardImagesLayout.setHorizontalGroup(
@ -1590,158 +1582,46 @@ public class PreferencesDialog extends javax.swing.JDialog {
.add(panelCardImagesLayout.createSequentialGroup()
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(panelCardImagesLayout.createSequentialGroup()
.addContainerGap()
.add(cbUseDefaultImageFolder)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(txtImageFolderPath)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(btnBrowseImageLocation))
.add(panelCardImagesLayout.createSequentialGroup()
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
.add(panelCardImagesLayout.createSequentialGroup()
.add(cbCheckForNewImages)
.add(147, 147, 147))
.add(org.jdesktop.layout.GroupLayout.LEADING, panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
.add(cbSaveToZipFiles)
.add(panelCardImagesLayout.createSequentialGroup()
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(labelNumberOfDownloadThreads)
.add(labelPreferedImageLanguage))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(cbPreferedImageLanguage, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 153, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(panelCardImagesLayout.createSequentialGroup()
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
.add(org.jdesktop.layout.GroupLayout.LEADING, panelCardImagesLayout.createSequentialGroup()
.addContainerGap()
.add(labelPreferedImageLanguage))
.add(org.jdesktop.layout.GroupLayout.LEADING, cbSaveToZipFiles))
.add(20, 20, 20)
.add(cbPreferedImageLanguage, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 153, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
.add(panelCardImagesLayout.createSequentialGroup()
.addContainerGap()
.add(labelNumberOfDownloadThreads)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(cbNumberOfDownloadThreads, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 153, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))))
.add(cbUseDefaultImageFolder))
.add(0, 391, Short.MAX_VALUE)))
.add(cbNumberOfDownloadThreads, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 153, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
.add(labelHint1)))))
.add(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
panelCardImagesLayout.setVerticalGroup(
panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(panelCardImagesLayout.createSequentialGroup()
.add(cbUseDefaultImageFolder)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(cbUseDefaultImageFolder)
.add(txtImageFolderPath, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(btnBrowseImageLocation))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(cbCheckForNewImages)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
.add(cbSaveToZipFiles)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(labelNumberOfDownloadThreads)
.add(cbNumberOfDownloadThreads, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(cbNumberOfDownloadThreads, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(labelHint1))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
.add(panelCardImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(cbPreferedImageLanguage, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(labelPreferedImageLanguage)))
);
panelBackgroundImages.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Background images"));
cbUseDefaultBackground.setText("Use default image");
cbUseDefaultBackground.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cbUseDefaultBackgroundActionPerformed(evt);
}
});
txtBackgroundImagePath.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtBackgroundImagePathActionPerformed(evt);
}
});
btnBrowseBackgroundImage.setText("Browse...");
btnBrowseBackgroundImage.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnBrowseBackgroundImageActionPerformed(evt);
}
});
txtBattlefieldImagePath.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtBattlefieldImagePathActionPerformed(evt);
}
});
btnBrowseBattlefieldImage.setText("Browse...");
btnBrowseBattlefieldImage.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnBrowseBattlefieldImageActionPerformed(evt);
}
});
cbUseDefaultBattleImage.setText("Use default battlefield image");
cbUseDefaultBattleImage.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cbUseDefaultBattleImageActionPerformed(evt);
}
});
cbUseRandomBattleImage.setText("Select random battlefield image");
cbUseRandomBattleImage.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cbUseRandomBattleImageActionPerformed(evt);
}
});
jLabel14.setText("Background:");
jLabel15.setText("Battlefield:");
org.jdesktop.layout.GroupLayout panelBackgroundImagesLayout = new org.jdesktop.layout.GroupLayout(panelBackgroundImages);
panelBackgroundImages.setLayout(panelBackgroundImagesLayout);
panelBackgroundImagesLayout.setHorizontalGroup(
panelBackgroundImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(panelBackgroundImagesLayout.createSequentialGroup()
.add(panelBackgroundImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(panelBackgroundImagesLayout.createSequentialGroup()
.add(panelBackgroundImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(panelBackgroundImagesLayout.createSequentialGroup()
.add(19, 19, 19)
.add(jLabel14))
.add(panelBackgroundImagesLayout.createSequentialGroup()
.add(25, 25, 25)
.add(jLabel15)))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(panelBackgroundImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(txtBackgroundImagePath)
.add(txtBattlefieldImagePath))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(panelBackgroundImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(org.jdesktop.layout.GroupLayout.TRAILING, btnBrowseBackgroundImage)
.add(org.jdesktop.layout.GroupLayout.TRAILING, btnBrowseBattlefieldImage)))
.add(panelBackgroundImagesLayout.createSequentialGroup()
.add(panelBackgroundImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(cbUseRandomBattleImage)
.add(cbUseDefaultBattleImage)
.add(cbUseDefaultBackground))
.add(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
panelBackgroundImagesLayout.setVerticalGroup(
panelBackgroundImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(panelBackgroundImagesLayout.createSequentialGroup()
.addContainerGap()
.add(cbUseDefaultBackground)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(panelBackgroundImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(txtBackgroundImagePath, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(btnBrowseBackgroundImage)
.add(jLabel14))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
.add(cbUseDefaultBattleImage)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
.add(cbUseRandomBattleImage)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
.add(panelBackgroundImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(txtBattlefieldImagePath, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(btnBrowseBattlefieldImage)
.add(jLabel15)))
.add(labelPreferedImageLanguage)
.add(cbPreferedImageLanguage, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
);
jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Card styles (restart xmage to apply new settings)"));
@ -1789,6 +1669,95 @@ public class PreferencesDialog extends javax.swing.JDialog {
.add(0, 0, Short.MAX_VALUE))
);
panelBackgroundImages.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Background images"));
cbUseDefaultBackground.setText("Use default location for backgrounds");
cbUseDefaultBackground.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cbUseDefaultBackgroundActionPerformed(evt);
}
});
txtBackgroundImagePath.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtBackgroundImagePathActionPerformed(evt);
}
});
btnBrowseBackgroundImage.setText("Browse...");
btnBrowseBackgroundImage.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnBrowseBackgroundImageActionPerformed(evt);
}
});
txtBattlefieldImagePath.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtBattlefieldImagePathActionPerformed(evt);
}
});
btnBrowseBattlefieldImage.setText("Browse...");
btnBrowseBattlefieldImage.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnBrowseBattlefieldImageActionPerformed(evt);
}
});
cbUseDefaultBattleImage.setText("Use default battlefield image");
cbUseDefaultBattleImage.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cbUseDefaultBattleImageActionPerformed(evt);
}
});
cbUseRandomBattleImage.setText("Use random background");
cbUseRandomBattleImage.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cbUseRandomBattleImageActionPerformed(evt);
}
});
org.jdesktop.layout.GroupLayout panelBackgroundImagesLayout = new org.jdesktop.layout.GroupLayout(panelBackgroundImages);
panelBackgroundImages.setLayout(panelBackgroundImagesLayout);
panelBackgroundImagesLayout.setHorizontalGroup(
panelBackgroundImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(panelBackgroundImagesLayout.createSequentialGroup()
.add(panelBackgroundImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(panelBackgroundImagesLayout.createSequentialGroup()
.add(cbUseDefaultBackground)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
.add(txtBackgroundImagePath)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(btnBrowseBackgroundImage))
.add(panelBackgroundImagesLayout.createSequentialGroup()
.add(cbUseRandomBattleImage)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
.add(txtBattlefieldImagePath)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(btnBrowseBattlefieldImage))
.add(panelBackgroundImagesLayout.createSequentialGroup()
.add(cbUseDefaultBattleImage)
.add(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
panelBackgroundImagesLayout.setVerticalGroup(
panelBackgroundImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(panelBackgroundImagesLayout.createSequentialGroup()
.add(cbUseDefaultBattleImage)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(panelBackgroundImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(cbUseDefaultBackground)
.add(txtBackgroundImagePath, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(btnBrowseBackgroundImage))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(panelBackgroundImagesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(cbUseRandomBattleImage)
.add(txtBattlefieldImagePath, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(btnBrowseBattlefieldImage))
.addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
org.jdesktop.layout.GroupLayout tabImagesLayout = new org.jdesktop.layout.GroupLayout(tabImages);
tabImages.setLayout(tabImagesLayout);
tabImagesLayout.setHorizontalGroup(
@ -1810,7 +1779,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
.add(panelCardImages, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(panelBackgroundImages, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addContainerGap(133, Short.MAX_VALUE))
.addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
tabsPanel.addTab("Images", tabImages);
@ -2385,7 +2354,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
tabAvatarsLayout.setVerticalGroup(
tabAvatarsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(tabAvatarsLayout.createSequentialGroup()
.add(avatarPane, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 620, Short.MAX_VALUE)
.add(avatarPane, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
@ -2420,14 +2389,14 @@ public class PreferencesDialog extends javax.swing.JDialog {
.add(connection_serversLayout.createSequentialGroup()
.add(141, 141, 141)
.add(jLabel17)))
.addContainerGap(251, Short.MAX_VALUE))
.addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
connection_serversLayout.setVerticalGroup(
connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(connection_serversLayout.createSequentialGroup()
.add(connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
.add(lblURLServerList, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(txtURLServerList, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 28, Short.MAX_VALUE))
.add(txtURLServerList, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(jLabel17))
);
@ -2663,7 +2632,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
.add(keyToggleRecordMacro, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 100, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(keySwitchChat, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 100, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
.add(controlsDescriptionLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 481, Short.MAX_VALUE)
.add(controlsDescriptionLabel)
.addContainerGap())
);
tabControlsLayout.setVerticalGroup(
@ -2749,7 +2718,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
.add(layout.createSequentialGroup()
.addContainerGap()
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
.add(org.jdesktop.layout.GroupLayout.LEADING, tabsPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
@ -2763,7 +2732,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
layout.setVerticalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(layout.createSequentialGroup()
.add(tabsPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(tabsPanel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 554, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(saveButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 30, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
@ -2892,7 +2861,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
// images
save(prefs, dialog.cbUseDefaultImageFolder, KEY_CARD_IMAGES_USE_DEFAULT, "true", "false", UPDATE_CACHE_POLICY);
saveImagesPath(prefs);
save(prefs, dialog.cbCheckForNewImages, KEY_CARD_IMAGES_CHECK, "true", "false", UPDATE_CACHE_POLICY);
save(prefs, dialog.cbSaveToZipFiles, KEY_CARD_IMAGES_SAVE_TO_ZIP, "true", "false", UPDATE_CACHE_POLICY);
save(prefs, dialog.cbNumberOfDownloadThreads, KEY_CARD_IMAGES_THREADS);
save(prefs, dialog.cbPreferedImageLanguage, KEY_CARD_IMAGES_PREF_LANGUAGE);
@ -3198,31 +3166,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
// TODO add your handling code here:
}//GEN-LAST:event_cbCardRenderShowReminderTextActionPerformed
private void cbSaveToZipFilesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbSaveToZipFilesActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_cbSaveToZipFilesActionPerformed
private void cbCheckForNewImagesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbCheckForNewImagesActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_cbCheckForNewImagesActionPerformed
private void btnBrowseImageLocationActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnBrowseImageLocationActionPerformed
int returnVal = fc.showOpenDialog(PreferencesDialog.this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
txtImageFolderPath.setText(file.getAbsolutePath());
}
}//GEN-LAST:event_btnBrowseImageLocationActionPerformed
private void cbUseDefaultImageFolderActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbUseDefaultImageFolderActionPerformed
if (cbUseDefaultImageFolder.isSelected()) {
useDefaultPath();
} else {
useConfigurablePath();
}
}//GEN-LAST:event_cbUseDefaultImageFolderActionPerformed
private void cbCardRenderHideSetSymbolActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbCardRenderHideSetSymbolActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_cbCardRenderHideSetSymbolActionPerformed
@ -3263,6 +3206,27 @@ public class PreferencesDialog extends javax.swing.JDialog {
// TODO add your handling code here:
}//GEN-LAST:event_cbStopBlockWithZeroActionPerformed
private void cbSaveToZipFilesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbSaveToZipFilesActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_cbSaveToZipFilesActionPerformed
private void btnBrowseImageLocationActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnBrowseImageLocationActionPerformed
int returnVal = fc.showOpenDialog(PreferencesDialog.this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
txtImageFolderPath.setText(file.getAbsolutePath());
}
}//GEN-LAST:event_btnBrowseImageLocationActionPerformed
private void cbUseDefaultImageFolderActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbUseDefaultImageFolderActionPerformed
if (cbUseDefaultImageFolder.isSelected()) {
useDefaultPath();
} else {
useConfigurablePath();
}
}//GEN-LAST:event_cbUseDefaultImageFolderActionPerformed
private void showProxySettings() {
Connection.ProxyType proxyType = (Connection.ProxyType) cbProxyType.getSelectedItem();
switch (proxyType) {
@ -3446,7 +3410,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
dialog.txtImageFolderPath.setText(path);
updateCache(KEY_CARD_IMAGES_PATH, path);
}
load(prefs, dialog.cbCheckForNewImages, KEY_CARD_IMAGES_CHECK, "true");
load(prefs, dialog.cbSaveToZipFiles, KEY_CARD_IMAGES_SAVE_TO_ZIP, "true");
dialog.cbNumberOfDownloadThreads.setSelectedItem(MageFrame.getPreferences().get(KEY_CARD_IMAGES_THREADS, "10"));
dialog.cbPreferedImageLanguage.setSelectedItem(MageFrame.getPreferences().get(KEY_CARD_IMAGES_PREF_LANGUAGE, CardLanguage.ENGLISH.getCode()));
@ -3751,6 +3714,14 @@ public class PreferencesDialog extends javax.swing.JDialog {
}
}
public static int getRenderMode() {
if (getCachedValue(PreferencesDialog.KEY_CARD_RENDERING_FALLBACK, "false").equals("false")) {
return 0; // mtgo
} else {
return 1; // image
}
}
private static int getDefaultControlMofier(String key) {
switch (key) {
default:
@ -3964,7 +3935,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
private javax.swing.JCheckBox cbCardRenderHideSetSymbol;
private javax.swing.JCheckBox cbCardRenderImageFallback;
private javax.swing.JCheckBox cbCardRenderShowReminderText;
private javax.swing.JCheckBox cbCheckForNewImages;
private javax.swing.JCheckBox cbConfirmEmptyManaPool;
private javax.swing.JCheckBox cbDraftLogAutoSave;
private javax.swing.JCheckBox cbEnableBattlefieldBGM;
@ -4014,8 +3984,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
private javax.swing.JPanel guiSizeBasic;
private javax.swing.JPanel guiSizeGame;
private javax.swing.JLabel jLabel11;
private javax.swing.JLabel jLabel14;
private javax.swing.JLabel jLabel15;
private javax.swing.JLabel jLabel16;
private javax.swing.JLabel jLabel17;
private javax.swing.JLabel jLabelBeforeCombat;
@ -4076,6 +4044,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
private javax.swing.JLabel labelEndStep;
private javax.swing.JLabel labelEnlargedImageSize;
private javax.swing.JLabel labelGameFeedback;
private javax.swing.JLabel labelHint1;
private javax.swing.JLabel labelMainStep;
private javax.swing.JLabel labelNextTurn;
private javax.swing.JLabel labelNumberOfDownloadThreads;

View file

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JInternalFrameFormInfo">
<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" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="0" pref="578" max="32767" attributes="0"/>
<Component id="buttonCancel" min="-2" pref="100" max="-2" attributes="0"/>
</Group>
<Component id="cardsPanel" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="buttonReloadCards" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="labelRenderMode" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="comboRenderMode" min="-2" pref="131" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="labelSize" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="sliderSize" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" 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="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Group type="103" groupAlignment="3" attributes="0">
<Component id="buttonReloadCards" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="labelRenderMode" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="comboRenderMode" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="labelSize" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="sliderSize" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="cardsPanel" pref="421" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="buttonCancel" min="-2" pref="30" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JButton" name="buttonCancel">
<Properties>
<Property name="text" type="java.lang.String" value="Close"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonCancelActionPerformed"/>
</Events>
</Component>
<Component class="mage.client.cards.CardArea" name="cardsPanel">
</Component>
<Component class="javax.swing.JButton" name="buttonReloadCards">
<Properties>
<Property name="text" type="java.lang.String" value="Reload cards"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonReloadCardsActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="labelRenderMode">
<Properties>
<Property name="text" type="java.lang.String" value="Render mode:"/>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="comboRenderMode">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="2">
<StringItem index="0" value="MTGO"/>
<StringItem index="1" value="Image"/>
</StringArray>
</Property>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="comboRenderModeItemStateChanged"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
</AuxValues>
</Component>
<Component class="javax.swing.JSlider" name="sliderSize">
<Events>
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="sliderSizeStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="labelSize">
<Properties>
<Property name="text" type="java.lang.String" value="Card size:"/>
</Properties>
</Component>
</SubComponents>
</Form>

View file

@ -0,0 +1,336 @@
package mage.client.dialog;
import mage.cards.Card;
import mage.cards.CardGraphicInfo;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.decks.Deck;
import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
import mage.cards.repository.ExpansionInfo;
import mage.cards.repository.ExpansionRepository;
import mage.client.MageFrame;
import mage.client.cards.BigCard;
import mage.client.util.GUISizeHelper;
import mage.constants.MultiplayerAttackOption;
import mage.constants.RangeOfInfluence;
import mage.game.Game;
import mage.game.GameImpl;
import mage.game.command.Emblem;
import mage.game.command.Plane;
import mage.game.command.emblems.AjaniAdversaryOfTyrantsEmblem;
import mage.game.command.planes.AkoumPlane;
import mage.game.match.MatchType;
import mage.game.mulligan.Mulligan;
import mage.game.mulligan.VancouverMulligan;
import mage.game.permanent.PermanentCard;
import mage.players.Player;
import mage.players.StubPlayer;
import mage.view.*;
import org.apache.log4j.Logger;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/**
* @author JayDi85
*/
public class TestCardRenderDialog extends MageDialog {
private static final Logger logger = Logger.getLogger(TestCardRenderDialog.class);
float cardSizeMod = 1.0f;
public TestCardRenderDialog() {
initComponents();
}
public void showDialog() {
this.setModal(false);
getRootPane().setDefaultButton(buttonCancel);
reloadCards();
// windows settings
MageFrame.getDesktop().remove(this);
if (this.isModal()) {
MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER);
} else {
MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER);
}
this.makeWindowCentered();
// Close on "ESC"
registerKeyboardAction(e -> onCancel(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
this.setVisible(true);
}
private void onCancel() {
this.removeDialog();
}
private PermanentView createCard(Game game, UUID controllerId, String code, String cardNumber, int power, int toughness, int damage) {
CardInfo cardInfo = CardRepository.instance.findCard(code, cardNumber);
ExpansionInfo setInfo = ExpansionRepository.instance.getSetByCode(code);
CardSetInfo testSet = new CardSetInfo(cardInfo.getName(), setInfo.getCode(), cardNumber, cardInfo.getRarity(),
new CardGraphicInfo(cardInfo.getFrameStyle(), cardInfo.usesVariousArt()));
Card card = CardImpl.createCard(cardInfo.getClassName(), testSet);
Set<Card> cardsList = new HashSet<>();
cardsList.add(card);
game.loadCards(cardsList, controllerId);
PermanentCard perm = new PermanentCard(card, controllerId, game);
if (damage > 0) perm.damage(damage, controllerId, game);
if (power > 0) perm.getPower().setValue(power);
if (toughness > 0) perm.getToughness().setValue(toughness);
perm.removeSummoningSickness();
if (perm.isTransformable()) {
perm.setTransformed(true);
}
PermanentView cardView = new PermanentView(perm, card, controllerId, game);
cardView.setInViewerOnly(true);
return cardView;
}
private AbilityView createEmblem(Emblem emblem) {
AbilityView emblemView = new AbilityView(emblem.getAbilities().get(0), emblem.getName(), new CardView(new EmblemView(emblem)));
emblemView.setName(emblem.getName());
return emblemView;
}
private AbilityView createPlane(Plane plane) {
AbilityView planeView = new AbilityView(plane.getAbilities().get(0), plane.getName(), new CardView(new PlaneView(plane)));
planeView.setName(plane.getName());
return planeView;
}
private void reloadCards() {
cardsPanel.cleanUp();
cardsPanel.setCustomRenderMode(comboRenderMode.getSelectedIndex());
Game game = new TestGame(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ALL, new VancouverMulligan(0), 20);
Player player = new StubPlayer("player1", RangeOfInfluence.ALL);
Deck deck = new Deck();
game.addPlayer(player, deck);
BigCard big = new BigCard();
CardsView view = new CardsView();
CardView card;
card = createCard(game, player.getId(), "RNA", "263", 0, 0, 0); // mountain
view.put(card.getId(), card);
card = createCard(game, player.getId(), "RNA", "185", 0, 0, 0); // Judith, the Scourge Diva
view.put(card.getId(), card);
card = createCard(game, player.getId(), "RNA", "78", 125, 89, 0); // Noxious Groodion
view.put(card.getId(), card);
card = createCard(game, player.getId(), "RNA", "14", 3, 5, 2); // Knight of Sorrows
view.put(card.getId(), card);
card = createCard(game, player.getId(), "DKA", "140", 5, 2, 2); // Huntmaster of the Fells, transforms
view.put(card.getId(), card);
card = createCard(game, player.getId(), "RNA", "221", 0, 0, 0); // Bedeck // Bedazzle
view.put(card.getId(), card);
card = createCard(game, player.getId(), "XLN", "234", 0, 0, 0); // Conqueror's Galleon
view.put(card.getId(), card);
card = createEmblem(new AjaniAdversaryOfTyrantsEmblem()); // Emblem Ajani
view.put(card.getId(), card);
card = createPlane(new AkoumPlane()); // Plane - Akoum
view.put(card.getId(), card);
cardsPanel.setCustomCardSize(new Dimension(getCardWidth(), getCardHeight()));
cardsPanel.changeGUISize();
cardsPanel.loadCards(view, big, game.getId());
}
private int getCardWidth() {
if (GUISizeHelper.editorCardDimension == null) {
return 200;
}
return (int) (GUISizeHelper.editorCardDimension.width * cardSizeMod);
}
private int getCardHeight() {
return (int) (1.4 * getCardWidth());
}
/**
* 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() {
buttonCancel = new javax.swing.JButton();
cardsPanel = new mage.client.cards.CardArea();
buttonReloadCards = new javax.swing.JButton();
labelRenderMode = new javax.swing.JLabel();
comboRenderMode = new javax.swing.JComboBox<>();
sliderSize = new javax.swing.JSlider();
labelSize = new javax.swing.JLabel();
buttonCancel.setText("Close");
buttonCancel.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
buttonCancelActionPerformed(evt);
}
});
buttonReloadCards.setText("Reload cards");
buttonReloadCards.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
buttonReloadCardsActionPerformed(evt);
}
});
labelRenderMode.setText("Render mode:");
comboRenderMode.setModel(new javax.swing.DefaultComboBoxModel<>(new String[]{"MTGO", "Image"}));
comboRenderMode.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
comboRenderModeItemStateChanged(evt);
}
});
sliderSize.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
sliderSizeStateChanged(evt);
}
});
labelSize.setText("Card size:");
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)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 578, Short.MAX_VALUE)
.addComponent(buttonCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(cardsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(buttonReloadCards)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(labelRenderMode)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(comboRenderMode, javax.swing.GroupLayout.PREFERRED_SIZE, 131, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(labelSize)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(sliderSize, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(buttonReloadCards)
.addComponent(labelRenderMode)
.addComponent(comboRenderMode, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(labelSize))
.addComponent(sliderSize, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cardsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 421, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(buttonCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void buttonCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonCancelActionPerformed
onCancel();
}//GEN-LAST:event_buttonCancelActionPerformed
private void buttonReloadCardsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonReloadCardsActionPerformed
reloadCards();
}//GEN-LAST:event_buttonReloadCardsActionPerformed
private void comboRenderModeItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_comboRenderModeItemStateChanged
reloadCards();
}//GEN-LAST:event_comboRenderModeItemStateChanged
private void sliderSizeStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_sliderSizeStateChanged
// from DragCardGrid
// Fraction in [-1, 1]
float sliderFrac = ((float) (sliderSize.getValue() - 50)) / 50;
// Convert to frac in [0.5, 2.0] exponentially
cardSizeMod = (float) Math.pow(2, sliderFrac);
reloadCards();
}//GEN-LAST:event_sliderSizeStateChanged
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton buttonCancel;
private javax.swing.JButton buttonReloadCards;
private mage.client.cards.CardArea cardsPanel;
private javax.swing.JComboBox<String> comboRenderMode;
private javax.swing.JLabel labelRenderMode;
private javax.swing.JLabel labelSize;
private javax.swing.JSlider sliderSize;
// End of variables declaration//GEN-END:variables
}
class TestGame extends GameImpl {
private int numPlayers;
public TestGame(MultiplayerAttackOption attackOption, RangeOfInfluence range, Mulligan mulligan, int startLife) {
super(attackOption, range, mulligan, startLife);
}
public TestGame(final TestGame game) {
super(game);
this.numPlayers = game.numPlayers;
}
@Override
public MatchType getGameType() {
return new TestGameType();
}
@Override
public int getNumPlayers() {
return numPlayers;
}
@Override
public TestGame copy() {
return new TestGame(this);
}
}
class TestGameType extends MatchType {
public TestGameType() {
this.name = "Test Game Type";
this.maxPlayers = 10;
this.minPlayers = 3;
this.numTeams = 0;
this.useAttackOption = true;
this.useRange = true;
this.sideboardingAllowed = true;
}
protected TestGameType(final TestGameType matchType) {
super(matchType);
}
@Override
public TestGameType copy() {
return new TestGameType(this);
}
}

View file

@ -200,8 +200,10 @@ public class WhatsNewDialog extends MageDialog {
}.getType();
try {
httpCookies = gson.fromJson(sourceValue, type);
for (HttpCookie cookie : httpCookies) {
store.add(URI.create(cookie.getDomain()), cookie);
if (httpCookies != null) {
for (HttpCookie cookie : httpCookies) {
store.add(URI.create(cookie.getDomain()), cookie);
}
}
} catch (Exception e) {
logger.error("Wrong news page cookies", e);

View file

@ -136,7 +136,7 @@ public class DraftPanel extends javax.swing.JPanel {
if (isLogging()) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
String logFilename = "Draft_" + sdf.format(new Date()) + '_' + draftId + ".txt";
String logFilename = "Draft_" + sdf.format(new Date()) + '_' + draftId + ".draft";
draftLogger = new DraftPickLogger(new File("gamelogs"), logFilename);
} else {
draftLogger = new DraftPickLogger();

View file

@ -1,254 +1,245 @@
/*
* BattlefieldPanel.java
*
* Created on 10-Jan-2010, 10:43:14 PM
*/
package mage.client.game;
* BattlefieldPanel.java
*
* Created on 10-Jan-2010, 10:43:14 PM
*/
package mage.client.game;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import javax.swing.JComponent;
import javax.swing.JLayeredPane;
import javax.swing.JScrollPane;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import mage.cards.MagePermanent;
import mage.client.cards.BigCard;
import mage.client.cards.Permanent;
import mage.client.plugins.impl.Plugins;
import mage.client.util.Config;
import mage.client.util.GUISizeHelper;
import mage.client.util.audio.AudioManager;
import mage.client.util.layout.CardLayoutStrategy;
import mage.client.util.layout.impl.OldCardLayoutStrategy;
import mage.view.CounterView;
import mage.view.PermanentView;
import mage.cards.MagePermanent;
import mage.client.cards.BigCard;
import mage.client.cards.Permanent;
import mage.client.dialog.PreferencesDialog;
import mage.client.plugins.impl.Plugins;
import mage.client.util.Config;
import mage.client.util.GUISizeHelper;
import mage.client.util.audio.AudioManager;
import mage.client.util.layout.CardLayoutStrategy;
import mage.client.util.layout.impl.OldCardLayoutStrategy;
import mage.view.CounterView;
import mage.view.PermanentView;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class BattlefieldPanel extends javax.swing.JLayeredPane {
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.List;
import java.util.*;
import java.util.Map.Entry;
private final Map<UUID, MagePermanent> permanents = new LinkedHashMap<>();
private UUID gameId;
private BigCard bigCard;
private final Map<String, JComponent> uiComponentsList = new HashMap<>();
/**
* @author BetaSteward_at_googlemail.com
*/
public class BattlefieldPanel extends javax.swing.JLayeredPane {
protected Map<UUID, PermanentView> battlefield;
private Dimension cardDimension;
private final Map<UUID, MagePermanent> permanents = new LinkedHashMap<>();
private UUID gameId;
private BigCard bigCard;
private final Map<String, JComponent> uiComponentsList = new HashMap<>();
private JLayeredPane jPanel;
private JScrollPane jScrollPane;
private int width;
protected Map<UUID, PermanentView> battlefield;
private Dimension cardDimension;
private final CardLayoutStrategy layoutStrategy = new OldCardLayoutStrategy();
private JLayeredPane jPanel;
private JScrollPane jScrollPane;
private int width;
//private static int iCounter = 0;
private boolean addedPermanent;
private boolean addedArtifact;
private boolean addedCreature;
private final CardLayoutStrategy layoutStrategy = new OldCardLayoutStrategy();
private boolean removedCreature;
// defines if the battlefield is within a top (means top row of player panels) or a bottom player panel
private boolean topPanelBattlefield;
//private static int iCounter = 0;
private boolean addedPermanent;
private boolean addedArtifact;
private boolean addedCreature;
/**
* Creates new form BattlefieldPanel
*/
public BattlefieldPanel() {
uiComponentsList.put("battlefieldPanel", this);
initComponents();
uiComponentsList.put("jPanel", jPanel);
setGUISize();
private boolean removedCreature;
// defines if the battlefield is within a top (means top row of player panels) or a bottom player panel
private boolean topPanelBattlefield;
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
int width = e.getComponent().getWidth();
int height = e.getComponent().getHeight();
BattlefieldPanel.this.jScrollPane.setSize(width, height);
BattlefieldPanel.this.width = width;
sortLayout();
}
});
}
/**
* Creates new form BattlefieldPanel
*/
public BattlefieldPanel() {
uiComponentsList.put("battlefieldPanel", this);
initComponents();
uiComponentsList.put("jPanel", jPanel);
setGUISize();
public void init(UUID gameId, BigCard bigCard) {
this.gameId = gameId;
this.bigCard = bigCard;
}
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
int width = e.getComponent().getWidth();
int height = e.getComponent().getHeight();
BattlefieldPanel.this.jScrollPane.setSize(width, height);
BattlefieldPanel.this.width = width;
sortLayout();
}
});
}
public void cleanUp() {
for (Component c : this.jPanel.getComponents()) {
if (c instanceof Permanent || c instanceof MagePermanent) {
this.jPanel.remove(c);
}
}
permanents.clear();
// Plugins.getInstance().sortPermanents(uiComponentsList, permanents.values());
this.bigCard = null;
}
public void init(UUID gameId, BigCard bigCard) {
this.gameId = gameId;
this.bigCard = bigCard;
}
public void changeGUISize() {
setGUISize();
sortLayout();
}
public void cleanUp() {
for (Component c : this.jPanel.getComponents()) {
if (c instanceof Permanent || c instanceof MagePermanent) {
this.jPanel.remove(c);
}
}
permanents.clear();
// Plugins.getInstance().sortPermanents(uiComponentsList, permanents.values());
this.bigCard = null;
}
private void setGUISize() {
jScrollPane.getVerticalScrollBar().setPreferredSize(new Dimension(GUISizeHelper.scrollBarSize, 0));
jScrollPane.getHorizontalScrollBar().setPreferredSize(new Dimension(0, GUISizeHelper.scrollBarSize));
cardDimension = GUISizeHelper.battlefieldCardMaxDimension;
}
public void changeGUISize() {
setGUISize();
sortLayout();
}
public boolean isTopPanelBattlefield() {
return topPanelBattlefield;
}
private void setGUISize() {
jScrollPane.getVerticalScrollBar().setPreferredSize(new Dimension(GUISizeHelper.scrollBarSize, 0));
jScrollPane.getHorizontalScrollBar().setPreferredSize(new Dimension(0, GUISizeHelper.scrollBarSize));
cardDimension = GUISizeHelper.battlefieldCardMaxDimension;
}
public void setTopPanelBattlefield(boolean topPanelBattlefield) {
this.topPanelBattlefield = topPanelBattlefield;
}
public boolean isTopPanelBattlefield() {
return topPanelBattlefield;
}
public void update(Map<UUID, PermanentView> battlefield) {
boolean changed = false;
public void setTopPanelBattlefield(boolean topPanelBattlefield) {
this.topPanelBattlefield = topPanelBattlefield;
}
List<PermanentView> permanentsToAdd = new ArrayList<>();
for (PermanentView permanent : battlefield.values()) {
if (!permanent.isPhasedIn()) {
continue;
}
MagePermanent oldMagePermanent = permanents.get(permanent.getId());
if (oldMagePermanent == null) {
permanentsToAdd.add(permanent);
changed = true;
} else {
if (!changed) {
changed = oldMagePermanent.getOriginalPermanent().isCreature() != permanent.isCreature();
// Check if there was a chnage in the permanets that are the permanent attached to
if (!changed) {
int attachments = permanent.getAttachments() == null ? 0 : permanent.getAttachments().size();
int attachmentsBefore = oldMagePermanent.getLinks().size();
if (attachments != attachmentsBefore) {
changed = true;
} else if (attachments > 0) {
Set<UUID> attachmentIds = new HashSet<>(permanent.getAttachments());
for (MagePermanent magePermanent : oldMagePermanent.getLinks()) {
if (!attachmentIds.contains(magePermanent.getOriginalPermanent().getId())) {
// that means that the amount of attachments is the same
// but they are different:
// we've just found an attachment on previous view
// that doesn't exist anymore on current view
changed = true;
break;
}
}
}
}
// Check if permanents it now attached to another or no permanent
if (!changed) {
UUID attachedToIdBefore = oldMagePermanent.getOriginalPermanent().getAttachedTo();
UUID attachedToId = permanent.getAttachedTo();
if (attachedToIdBefore == null && attachedToId != null || attachedToId == null && attachedToIdBefore != null
|| (attachedToIdBefore != null && !attachedToIdBefore.equals(attachedToId))) {
changed = true;
}
}
// Check for changes in the counters of the permanent
if (!changed) {
List<CounterView> counters1 = oldMagePermanent.getOriginalPermanent().getCounters();
List<CounterView> counters2 = permanent.getCounters();
if (counters1 == null && counters2 != null || counters1 != null && counters2 == null) {
changed = true;
} else if (counters1 != null && counters2 != null && counters1.size() != counters2.size()) {
changed = true;
}
}
public void update(Map<UUID, PermanentView> battlefield) {
boolean changed = false;
}
oldMagePermanent.update(permanent);
}
}
List<PermanentView> permanentsToAdd = new ArrayList<>();
for (PermanentView permanent : battlefield.values()) {
if (!permanent.isPhasedIn()) {
continue;
}
MagePermanent oldMagePermanent = permanents.get(permanent.getId());
if (oldMagePermanent == null) {
permanentsToAdd.add(permanent);
changed = true;
} else {
if (!changed) {
changed = oldMagePermanent.getOriginalPermanent().isCreature() != permanent.isCreature();
// Check if there was a chnage in the permanets that are the permanent attached to
if (!changed) {
int attachments = permanent.getAttachments() == null ? 0 : permanent.getAttachments().size();
int attachmentsBefore = oldMagePermanent.getLinks().size();
if (attachments != attachmentsBefore) {
changed = true;
} else if (attachments > 0) {
Set<UUID> attachmentIds = new HashSet<>(permanent.getAttachments());
for (MagePermanent magePermanent : oldMagePermanent.getLinks()) {
if (!attachmentIds.contains(magePermanent.getOriginalPermanent().getId())) {
// that means that the amount of attachments is the same
// but they are different:
// we've just found an attachment on previous view
// that doesn't exist anymore on current view
changed = true;
break;
}
}
}
}
// Check if permanents it now attached to another or no permanent
if (!changed) {
UUID attachedToIdBefore = oldMagePermanent.getOriginalPermanent().getAttachedTo();
UUID attachedToId = permanent.getAttachedTo();
if (attachedToIdBefore == null && attachedToId != null || attachedToId == null && attachedToIdBefore != null
|| (attachedToIdBefore != null && !attachedToIdBefore.equals(attachedToId))) {
changed = true;
}
}
// Check for changes in the counters of the permanent
if (!changed) {
List<CounterView> counters1 = oldMagePermanent.getOriginalPermanent().getCounters();
List<CounterView> counters2 = permanent.getCounters();
if (counters1 == null && counters2 != null || counters1 != null && counters2 == null) {
changed = true;
} else if (counters1 != null && counters2 != null && counters1.size() != counters2.size()) {
changed = true;
}
}
addedArtifact = addedCreature = addedPermanent = false;
}
oldMagePermanent.update(permanent);
}
}
int count = permanentsToAdd.size();
for (PermanentView permanent : permanentsToAdd) {
addPermanent(permanent, count);
}
addedArtifact = addedCreature = addedPermanent = false;
if (addedArtifact) {
AudioManager.playAddArtifact();
} else if (addedCreature) {
AudioManager.playSummon();
} else if (addedPermanent) {
AudioManager.playAddPermanent();
}
int count = permanentsToAdd.size();
for (PermanentView permanent : permanentsToAdd) {
addPermanent(permanent, count);
}
removedCreature = false;
if (addedArtifact) {
AudioManager.playAddArtifact();
} else if (addedCreature) {
AudioManager.playSummon();
} else if (addedPermanent) {
AudioManager.playAddPermanent();
}
for (Iterator<Entry<UUID, MagePermanent>> iterator = permanents.entrySet().iterator(); iterator.hasNext();) {
Entry<UUID, MagePermanent> entry = iterator.next();
if (!battlefield.containsKey(entry.getKey()) || !battlefield.get(entry.getKey()).isPhasedIn()) {
removePermanent(entry.getKey(), 1);
iterator.remove();
changed = true;
}
}
removedCreature = false;
if (removedCreature) {
AudioManager.playDiedCreature();
}
for (Iterator<Entry<UUID, MagePermanent>> iterator = permanents.entrySet().iterator(); iterator.hasNext(); ) {
Entry<UUID, MagePermanent> entry = iterator.next();
if (!battlefield.containsKey(entry.getKey()) || !battlefield.get(entry.getKey()).isPhasedIn()) {
removePermanent(entry.getKey(), 1);
iterator.remove();
changed = true;
}
}
if (changed) {
this.battlefield = battlefield;
sortLayout();
}
}
if (removedCreature) {
AudioManager.playDiedCreature();
}
public void sortLayout() {
if (battlefield == null || this.getWidth() < 1) { // Can't do layout when panel is not sized yet
return;
}
if (changed) {
this.battlefield = battlefield;
sortLayout();
}
}
layoutStrategy.doLayout(this, width);
public void sortLayout() {
if (battlefield == null || this.getWidth() < 1) { // Can't do layout when panel is not sized yet
return;
}
this.jScrollPane.repaint();
this.jScrollPane.revalidate();
layoutStrategy.doLayout(this, width);
invalidate();
repaint();
}
this.jScrollPane.repaint();
this.jScrollPane.revalidate();
private void addPermanent(PermanentView permanent, final int count) {
if (cardDimension == null) {
cardDimension = new Dimension(Config.dimensions.getFrameWidth(), Config.dimensions.getFrameHeight());
}
final MagePermanent perm = Plugins.instance.getMagePermanent(permanent, bigCard, cardDimension, gameId, true);
invalidate();
repaint();
}
permanents.put(permanent.getId(), perm);
private void addPermanent(PermanentView permanent, final int count) {
if (cardDimension == null) {
cardDimension = new Dimension(Config.dimensions.getFrameWidth(), Config.dimensions.getFrameHeight());
}
final MagePermanent perm = Plugins.instance.getMagePermanent(permanent, bigCard, cardDimension, gameId, true, PreferencesDialog.getRenderMode());
BattlefieldPanel.this.jPanel.add(perm, 10);
//this.jPanel.add(perm);
if (!Plugins.instance.isCardPluginLoaded()) {
moveToFront(perm);
perm.update(permanent);
} else {
moveToFront(jPanel);
Plugins.instance.onAddCard(perm, 1);
permanents.put(permanent.getId(), perm);
BattlefieldPanel.this.jPanel.add(perm, 10);
//this.jPanel.add(perm);
if (!Plugins.instance.isCardPluginLoaded()) {
moveToFront(perm);
perm.update(permanent);
} else {
moveToFront(jPanel);
Plugins.instance.onAddCard(perm, 1);
/*Thread t = new Thread(new Runnable() {
@Override
public void run() {
@ -258,76 +249,76 @@ public class BattlefieldPanel extends javax.swing.JLayeredPane {
synchronized (this) {
threads.add(t);
}*/
}
}
if (permanent.isArtifact()) {
addedArtifact = true;
} else if (permanent.isCreature()) {
addedCreature = true;
} else {
addedPermanent = true;
}
}
if (permanent.isArtifact()) {
addedArtifact = true;
} else if (permanent.isCreature()) {
addedCreature = true;
} else {
addedPermanent = true;
}
}
private void removePermanent(UUID permanentId, final int count) {
for (Component c : this.jPanel.getComponents()) {
final Component comp = c;
if (comp instanceof Permanent) {
if (((Permanent) comp).getPermanentId().equals(permanentId)) {
comp.setVisible(false);
this.jPanel.remove(comp);
}
} else if (comp instanceof MagePermanent) {
if (((MagePermanent) comp).getOriginal().getId().equals(permanentId)) {
Thread t = new Thread(() -> {
Plugins.instance.onRemoveCard((MagePermanent) comp, count);
comp.setVisible(false);
BattlefieldPanel.this.jPanel.remove(comp);
});
t.start();
}
if (((MagePermanent) comp).getOriginal().isCreature()) {
removedCreature = true;
}
}
}
}
private void removePermanent(UUID permanentId, final int count) {
for (Component c : this.jPanel.getComponents()) {
final Component comp = c;
if (comp instanceof Permanent) {
if (((Permanent) comp).getPermanentId().equals(permanentId)) {
comp.setVisible(false);
this.jPanel.remove(comp);
}
} else if (comp instanceof MagePermanent) {
if (((MagePermanent) comp).getOriginal().getId().equals(permanentId)) {
Thread t = new Thread(() -> {
Plugins.instance.onRemoveCard((MagePermanent) comp, count);
comp.setVisible(false);
BattlefieldPanel.this.jPanel.remove(comp);
});
t.start();
}
if (((MagePermanent) comp).getOriginal().isCreature()) {
removedCreature = true;
}
}
}
}
@Override
public boolean isOptimizedDrawingEnabled() {
return false;
}
@Override
public boolean isOptimizedDrawingEnabled() {
return false;
}
public Map<UUID, MagePermanent> getPermanents() {
return permanents;
}
public Map<UUID, MagePermanent> getPermanents() {
return permanents;
}
private void initComponents() {
setOpaque(false);
private void initComponents() {
setOpaque(false);
jPanel = new JLayeredPane();
jPanel.setLayout(null);
jPanel.setOpaque(false);
jScrollPane = new JScrollPane(jPanel);
jPanel = new JLayeredPane();
jPanel.setLayout(null);
jPanel.setOpaque(false);
jScrollPane = new JScrollPane(jPanel);
Border empty = new EmptyBorder(0, 0, 0, 0);
jScrollPane.setBorder(empty);
jScrollPane.setViewportBorder(empty);
jScrollPane.setOpaque(false);
jScrollPane.getViewport().setOpaque(false);
Border empty = new EmptyBorder(0, 0, 0, 0);
jScrollPane.setBorder(empty);
jScrollPane.setViewportBorder(empty);
jScrollPane.setOpaque(false);
jScrollPane.getViewport().setOpaque(false);
this.add(jScrollPane);
}
this.add(jScrollPane);
}
public JLayeredPane getMainPanel() {
return jPanel;
}
public JLayeredPane getMainPanel() {
return jPanel;
}
public Map<UUID, PermanentView> getBattlefield() {
return battlefield;
}
public Map<UUID, PermanentView> getBattlefield() {
return battlefield;
}
public Map<String, JComponent> getUiComponentsList() {
return uiComponentsList;
}
}
public Map<String, JComponent> getUiComponentsList() {
return uiComponentsList;
}
}

View file

@ -1,10 +1,5 @@
package mage.client.plugins;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Map;
import java.util.UUID;
import javax.swing.*;
import mage.cards.MageCard;
import mage.cards.MagePermanent;
import mage.cards.action.ActionCallback;
@ -12,6 +7,12 @@ import mage.client.cards.BigCard;
import mage.view.CardView;
import mage.view.PermanentView;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Map;
import java.util.UUID;
public interface MagePlugins {
void loadPlugins();
@ -22,9 +23,9 @@ public interface MagePlugins {
JComponent updateTablePanel(Map<String, JComponent> ui);
MagePermanent getMagePermanent(PermanentView card, BigCard bigCard, Dimension dimension, UUID gameId, boolean loadImage);
MagePermanent getMagePermanent(PermanentView card, BigCard bigCard, Dimension dimension, UUID gameId, boolean loadImage, int renderMode);
MageCard getMageCard(CardView card, BigCard bigCard, Dimension dimension, UUID gameId, boolean loadImage, boolean previewable);
MageCard getMageCard(CardView card, BigCard bigCard, Dimension dimension, UUID gameId, boolean loadImage, boolean previewable, int renderMode);
boolean isThemePluginLoaded();

View file

@ -30,8 +30,8 @@ import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.image.BufferedImage;
import java.util.*;
import java.util.List;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
@ -154,24 +154,22 @@ public class MageActionCallback implements ActionCallback {
try {
final Component popupContainer = MageFrame.getUI().getComponent(MageComponents.POPUP_CONTAINER);
Component popup2 = MageFrame.getUI().getComponent(MageComponents.CARD_INFO_PANE);
((CardInfoPane) popup2).setCard(data.getCard(), popupContainer);
showPopup(popupContainer, popup2);
Component popupInfo = MageFrame.getUI().getComponent(MageComponents.CARD_INFO_PANE);
((CardInfoPane) popupInfo).setCard(data.getCard(), popupContainer);
showPopup(popupContainer, popupInfo);
} catch (InterruptedException e) {
LOGGER.warn(e.getMessage());
LOGGER.error("Can't show card tooltip", e);
Thread.currentThread().interrupt();
}
}
public void showPopup(final Component popupContainer, final Component infoPane) throws InterruptedException {
final Component c = MageFrame.getUI().getComponent(MageComponents.DESKTOP_PANE);
SwingUtilities.invokeLater(() -> {
if (!popupTextWindowOpen
|| enlargedWindowState != EnlargedWindowState.CLOSED) {
if (!popupTextWindowOpen || enlargedWindowState != EnlargedWindowState.CLOSED) {
return;
}
if (data.getLocationOnScreen() == null) {
data.setLocationOnScreen(data.getComponent().getLocationOnScreen());
}
@ -365,8 +363,6 @@ public class MageActionCallback implements ActionCallback {
if (!((GamePane) topPane).getGameId().equals(data.getGameId())) {
return;
}
} else if (data.getGameId() != null) {
return;
}
hideTooltipPopup();
@ -383,6 +379,7 @@ public class MageActionCallback implements ActionCallback {
ArrowUtil.drawArrowsForPairedCards(data, parentPoint);
ArrowUtil.drawArrowsForBandedCards(data, parentPoint);
ArrowUtil.drawArrowsForEnchantPlayers(data, parentPoint);
tooltipCard = data.getCard();
showTooltipPopup(data, parentComponent, parentPoint);
}
@ -414,13 +411,9 @@ public class MageActionCallback implements ActionCallback {
@Override
public void hideOpenComponents() {
this.hideTooltipPopup();
this.hideEnlargedCard();
hideAll(null);
}
/**
* Hides the text popup window
*/
public void hideTooltipPopup() {
this.tooltipCard = null;
if (tooltipPopup != null) {
@ -433,11 +426,11 @@ public class MageActionCallback implements ActionCallback {
if (SessionHandler.getSession() == null) {
return;
}
// set enlarged card display to visible = false
Component popupContainer = MageFrame.getUI().getComponent(MageComponents.POPUP_CONTAINER);
popupContainer.setVisible(false);
} catch (Exception e2) {
LOGGER.warn("Can't set tooltip to visible = false", e2);
} catch (InterruptedException e) {
LOGGER.error("Can't hide card tooltip", e);
Thread.currentThread().interrupt();
}
}

View file

@ -1,12 +1,5 @@
package mage.client.plugins.impl;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.swing.JComponent;
import mage.cards.MageCard;
import mage.cards.MagePermanent;
import mage.cards.action.ActionCallback;
@ -27,12 +20,20 @@ import mage.view.PermanentView;
import net.xeoh.plugins.base.PluginManager;
import net.xeoh.plugins.base.impl.PluginManagerFactory;
import net.xeoh.plugins.base.util.uri.ClassURI;
import org.apache.log4j.Logger;
import org.mage.plugins.card.CardPluginImpl;
import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir;
import org.mage.plugins.theme.ThemePluginImpl;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir;
public enum Plugins implements MagePlugins {
instance;
public static final String PLUGINS_DIRECTORY = "plugins";
@ -92,24 +93,24 @@ public enum Plugins implements MagePlugins {
}
@Override
public MagePermanent getMagePermanent(PermanentView card, BigCard bigCard, Dimension dimension, UUID gameId, boolean loadImage) {
public MagePermanent getMagePermanent(PermanentView card, BigCard bigCard, Dimension dimension, UUID gameId, boolean loadImage, int renderMode) {
if (cardPlugin != null) {
mageActionCallback.refreshSession();
mageActionCallback.setCardPreviewComponent(bigCard);
return cardPlugin.getMagePermanent(card, dimension, gameId, mageActionCallback, false, !MageFrame.isLite() && loadImage);
return cardPlugin.getMagePermanent(card, dimension, gameId, mageActionCallback, false, !MageFrame.isLite() && loadImage, renderMode);
} else {
return new Permanent(card, bigCard, Config.dimensions, gameId);
}
}
@Override
public MageCard getMageCard(CardView card, BigCard bigCard, Dimension dimension, UUID gameId, boolean loadImage, boolean previewable) {
public MageCard getMageCard(CardView card, BigCard bigCard, Dimension dimension, UUID gameId, boolean loadImage, boolean previewable, int renderMode) {
if (cardPlugin != null) {
if (previewable) {
mageActionCallback.refreshSession();
mageActionCallback.setCardPreviewComponent(bigCard);
}
return cardPlugin.getMageCard(card, dimension, gameId, mageActionCallback, false, !MageFrame.isLite() && loadImage);
return cardPlugin.getMageCard(card, dimension, gameId, mageActionCallback, false, !MageFrame.isLite() && loadImage, renderMode);
} else {
return new Card(card, bigCard, Config.dimensions, gameId);
}

View file

@ -2,6 +2,7 @@ package mage.client.preference;
import com.google.common.collect.Sets;
import mage.client.MageFrame;
import mage.client.util.Config;
import java.util.Set;
import java.util.prefs.BackingStoreException;
@ -16,9 +17,13 @@ public final class MagePreferences {
private static final String KEY_PASSWORD = "password";
private static final String KEY_EMAIL = "email";
private static final String KEY_AUTO_CONNECT = "autoConnect";
private static final String NODE_KEY_IGNORE_LIST = "ignoreListString";
private static String lastServerAddress = "";
private static int lastServerPort = 0;
private static String lastServerUser = "";
private static String lastServerPassword = "";
private static Preferences prefs() {
// TODO: Move MageFrame.prefs to this class.
return MageFrame.getPreferences();
@ -138,4 +143,26 @@ public final class MagePreferences {
return prefs().node(NODE_KEY_IGNORE_LIST).node(serverAddress);
}
public static void saveLastServer() {
lastServerAddress = getServerAddressWithDefault(Config.serverName);
lastServerPort = getServerPortWithDefault(Config.port);
lastServerUser = getUserName(lastServerAddress);
lastServerPassword = getPassword(lastServerAddress);
}
public static String getLastServerAddress() {
return lastServerAddress.isEmpty() ? getServerAddress() : lastServerAddress;
}
public static int getLastServerPort() {
return lastServerPort == 0 ? getServerPort() : lastServerPort;
}
public static String getLastServerUser() {
return lastServerUser.isEmpty() ? getUserName(getLastServerAddress()) : lastServerUser;
}
public static String getLastServerPassword() {
return lastServerPassword.isEmpty() ? getPassword(getLastServerAddress()) : lastServerPassword;
}
}

View file

@ -105,7 +105,7 @@ public class TablesPane extends MagePane {
@Override
public void activated() {
tablesPanel.startTasks();
tablesPanel.startUpdateTasks(false);
}
@Override

View file

@ -43,8 +43,11 @@
<Component id="filterBar2" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnQuickStart" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="792" max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="btnQuickStartDuel" min="-2" max="-2" attributes="0"/>
<Component id="btnQuickStartCommander" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="734" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -60,10 +63,16 @@
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="filterBar1" max="32767" attributes="0"/>
<Component id="btnQuickStart" min="-2" max="-2" attributes="0"/>
<Component id="btnQuickStartDuel" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="filterBar2" max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="filterBar2" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Component id="btnQuickStartCommander" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
@ -506,15 +515,26 @@
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="btnQuickStart">
<Component class="javax.swing.JButton" name="btnQuickStartDuel">
<Properties>
<Property name="text" type="java.lang.String" value="Quick Start"/>
<Property name="text" type="java.lang.String" value="Quick start duel"/>
<Property name="focusable" type="boolean" value="false"/>
<Property name="horizontalTextPosition" type="int" value="0"/>
<Property name="verticalTextPosition" type="int" value="3"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnQuickStartActionPerformed"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnQuickStartDuelActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnQuickStartCommander">
<Properties>
<Property name="text" type="java.lang.String" value="Quick start commander"/>
<Property name="focusable" type="boolean" value="false"/>
<Property name="horizontalTextPosition" type="int" value="0"/>
<Property name="verticalTextPosition" type="int" value="3"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnQuickStartCommanderActionPerformed"/>
</Events>
</Component>
</SubComponents>

View file

@ -1,5 +1,6 @@
package mage.client.table;
import mage.cards.decks.DeckCardLists;
import mage.cards.decks.importer.DeckImporter;
import mage.client.MageFrame;
import mage.client.SessionHandler;
@ -16,6 +17,8 @@ import mage.constants.*;
import mage.game.match.MatchOptions;
import mage.players.PlayerType;
import mage.remote.MageRemoteException;
import mage.util.DeckUtil;
import mage.util.RandomUtil;
import mage.view.MatchView;
import mage.view.RoomUsersView;
import mage.view.TableView;
@ -65,6 +68,7 @@ public class TablesPanel extends javax.swing.JPanel {
public static final int REFRESH_ACTIVE_TABLES_SECS = 5;
public static final int REFRESH_FINISHED_TABLES_SECS = 30;
public static final int REFRESH_PLAYERS_SECS = 10;
public static final double REFRESH_TIMEOUTS_INCREASE_FACTOR = 0.8; // can increase timeouts by 80% (0.8)
private final TablesTableModel tableModel;
private final MatchesTableModel matchesModel;
@ -211,6 +215,12 @@ public class TablesPanel extends javax.swing.JPanel {
return res;
}
public static int randomizeTimout(int minTimout) {
// randomize timeouts to fix calls waves -- slow server can creates queue and moves all clients to same call window
int increase = (int) (minTimout * REFRESH_TIMEOUTS_INCREASE_FACTOR);
return minTimout + RandomUtil.nextInt(increase);
}
/**
* Creates new form TablesPanel
@ -513,6 +523,7 @@ public class TablesPanel extends javax.swing.JPanel {
public void cleanUp() {
saveGuiSettings();
chatPanelMain.cleanUp();
stopTasks();
}
public void changeGUISize() {
@ -632,23 +643,31 @@ public class TablesPanel extends javax.swing.JPanel {
}
}
public void startTasks() {
public void startUpdateTasks(boolean refreshImmediately) {
if (SessionHandler.getSession() != null) {
if (updateTablesTask == null || updateTablesTask.isDone()) {
// active tables and server messages
if (updateTablesTask == null || updateTablesTask.isDone() || refreshImmediately) {
if (updateTablesTask != null) updateTablesTask.cancel(true);
updateTablesTask = new UpdateTablesTask(roomId, this);
updateTablesTask.execute();
}
if (updatePlayersTask == null || updatePlayersTask.isDone()) {
updatePlayersTask = new UpdatePlayersTask(roomId, this.chatPanelMain);
updatePlayersTask.execute();
}
// finished tables
if (this.btnStateFinished.isSelected()) {
if (updateMatchesTask == null || updateMatchesTask.isDone()) {
if (updateMatchesTask == null || updateMatchesTask.isDone() || refreshImmediately) {
if (updateMatchesTask != null) updateMatchesTask.cancel(true);
updateMatchesTask = new UpdateMatchesTask(roomId, this);
updateMatchesTask.execute();
}
} else if (updateMatchesTask != null) {
updateMatchesTask.cancel(true);
} else {
if (updateMatchesTask != null) updateMatchesTask.cancel(true);
}
// players list
if (updatePlayersTask == null || updatePlayersTask.isDone() || refreshImmediately) {
if (updatePlayersTask != null) updatePlayersTask.cancel(true);
updatePlayersTask = new UpdatePlayersTask(roomId, this.chatPanelMain);
updatePlayersTask.execute();
}
}
}
@ -669,7 +688,8 @@ public class TablesPanel extends javax.swing.JPanel {
this.roomId = roomId;
UUID chatRoomId = null;
if (SessionHandler.getSession() != null) {
btnQuickStart.setVisible(SessionHandler.isTestMode());
btnQuickStartDuel.setVisible(SessionHandler.isTestMode());
btnQuickStartCommander.setVisible(SessionHandler.isTestMode());
gameChooser.init();
chatRoomId = SessionHandler.getRoomChatId(roomId).orElse(null);
}
@ -687,7 +707,7 @@ public class TablesPanel extends javax.swing.JPanel {
}
if (chatRoomId != null) {
this.chatPanelMain.getUserChatPanel().connect(chatRoomId);
startTasks();
startUpdateTasks(true);
this.setVisible(true);
this.repaint();
} else {
@ -695,7 +715,7 @@ public class TablesPanel extends javax.swing.JPanel {
}
//tableModel.setSession(session);
reloadMessages();
reloadServerMessages();
MageFrame.getUI().addButton(MageComponents.NEW_GAME_BUTTON, btnNewTable);
@ -704,7 +724,7 @@ public class TablesPanel extends javax.swing.JPanel {
}
protected void reloadMessages() {
protected void reloadServerMessages() {
// reload server messages
java.util.List<String> serverMessages = SessionHandler.getServerMessages();
synchronized (this) {
@ -954,7 +974,8 @@ public class TablesPanel extends javax.swing.JPanel {
jSeparator5 = new javax.swing.JToolBar.Separator();
btnOpen = new javax.swing.JToggleButton();
btnPassword = new javax.swing.JToggleButton();
btnQuickStart = new javax.swing.JButton();
btnQuickStartDuel = new javax.swing.JButton();
btnQuickStartCommander = new javax.swing.JButton();
jSplitPane1 = new javax.swing.JSplitPane();
jPanelTables = new javax.swing.JPanel();
jSplitPaneTables = new javax.swing.JSplitPane();
@ -1374,13 +1395,23 @@ public class TablesPanel extends javax.swing.JPanel {
});
filterBar2.add(btnPassword);
btnQuickStart.setText("Quick Start");
btnQuickStart.setFocusable(false);
btnQuickStart.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
btnQuickStart.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
btnQuickStart.addActionListener(new java.awt.event.ActionListener() {
btnQuickStartDuel.setText("Quick start duel");
btnQuickStartDuel.setFocusable(false);
btnQuickStartDuel.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
btnQuickStartDuel.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
btnQuickStartDuel.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnQuickStartActionPerformed(evt);
btnQuickStartDuelActionPerformed(evt);
}
});
btnQuickStartCommander.setText("Quick start commander");
btnQuickStartCommander.setFocusable(false);
btnQuickStartCommander.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
btnQuickStartCommander.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
btnQuickStartCommander.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnQuickStartCommanderActionPerformed(evt);
}
});
@ -1398,8 +1429,10 @@ public class TablesPanel extends javax.swing.JPanel {
.addComponent(filterBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(filterBar2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnQuickStart)
.addContainerGap(792, Short.MAX_VALUE))
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(btnQuickStartDuel)
.addComponent(btnQuickStartCommander))
.addContainerGap(734, Short.MAX_VALUE))
);
jPanelTopLayout.setVerticalGroup(
jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -1412,9 +1445,13 @@ public class TablesPanel extends javax.swing.JPanel {
.addGroup(jPanelTopLayout.createSequentialGroup()
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(filterBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnQuickStart))
.addComponent(btnQuickStartDuel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(filterBar2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(filterBar2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanelTopLayout.createSequentialGroup()
.addComponent(btnQuickStartCommander)
.addGap(0, 0, Short.MAX_VALUE)))))
.addContainerGap())
);
@ -1518,16 +1555,23 @@ public class TablesPanel extends javax.swing.JPanel {
newTournamentDialog.showDialog(roomId);
}//GEN-LAST:event_btnNewTournamentActionPerformed
private void btnQuickStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnQuickStartActionPerformed
private void createTestGame(String gameName, String gameType) {
TableView table;
try {
File f = new File("test.dck");
String testDeckFile = "test.dck";
File f = new File(testDeckFile);
if (!f.exists()) {
JOptionPane.showMessageDialog(null, "Couldn't find test.dck file for quick game start", "Error", JOptionPane.ERROR_MESSAGE);
return;
// default test deck
testDeckFile = DeckUtil.writeTextToTempFile(""
+ "5 Swamp" + System.lineSeparator()
+ "5 Forest" + System.lineSeparator()
+ "5 Island" + System.lineSeparator()
+ "5 Mountain" + System.lineSeparator()
+ "5 Plains");
}
DeckCardLists testDeck = DeckImporter.importDeckFromFile(testDeckFile);
MatchOptions options = new MatchOptions("1", "Two Player Duel", false, 2);
MatchOptions options = new MatchOptions(gameName, gameType, false, 2);
options.getPlayerTypes().add(PlayerType.HUMAN);
options.getPlayerTypes().add(PlayerType.COMPUTER_MAD);
options.setDeckType("Limited");
@ -1544,13 +1588,17 @@ public class TablesPanel extends javax.swing.JPanel {
options.setBannedUsers(IgnoreList.ignoreList(serverAddress));
table = SessionHandler.createTable(roomId, options);
SessionHandler.joinTable(roomId, table.getTableId(), "Human", PlayerType.HUMAN, 1, DeckImporter.importDeckFromFile("test.dck"), "");
SessionHandler.joinTable(roomId, table.getTableId(), "Computer", PlayerType.COMPUTER_MAD, 5, DeckImporter.importDeckFromFile("test.dck"), "");
SessionHandler.joinTable(roomId, table.getTableId(), "Human", PlayerType.HUMAN, 1, testDeck, "");
SessionHandler.joinTable(roomId, table.getTableId(), "Computer", PlayerType.COMPUTER_MAD, 5, testDeck, "");
SessionHandler.startMatch(roomId, table.getTableId());
} catch (HeadlessException ex) {
handleError(ex);
}
}//GEN-LAST:event_btnQuickStartActionPerformed
}
private void btnQuickStartDuelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnQuickStartDuelActionPerformed
createTestGame("Test duel", "Two Player Duel");
}//GEN-LAST:event_btnQuickStartDuelActionPerformed
private void btnNewTableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnNewTableActionPerformed
newTableDialog.showDialog(roomId);
@ -1580,7 +1628,7 @@ public class TablesPanel extends javax.swing.JPanel {
} else {
this.jSplitPaneTables.setDividerLocation(this.jPanelTables.getHeight());
}
this.startTasks();
this.startUpdateTasks(true);
}//GEN-LAST:event_btnStateFinishedActionPerformed
private void btnRatedbtnFilterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRatedbtnFilterActionPerformed
@ -1603,6 +1651,10 @@ public class TablesPanel extends javax.swing.JPanel {
MageFrame.getInstance().showWhatsNewDialog(true);
}//GEN-LAST:event_buttonWhatsNewActionPerformed
private void btnQuickStartCommanderActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnQuickStartCommanderActionPerformed
createTestGame("Test commander", "Commander Two Player Duel");
}//GEN-LAST:event_btnQuickStartCommanderActionPerformed
private void handleError(Exception ex) {
LOGGER.fatal("Error loading deck: ", ex);
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Error loading deck.", "Error", JOptionPane.ERROR_MESSAGE);
@ -1623,7 +1675,8 @@ public class TablesPanel extends javax.swing.JPanel {
private javax.swing.JButton btnNewTournament;
private javax.swing.JToggleButton btnOpen;
private javax.swing.JToggleButton btnPassword;
private javax.swing.JButton btnQuickStart;
private javax.swing.JButton btnQuickStartCommander;
private javax.swing.JButton btnQuickStartDuel;
private javax.swing.JToggleButton btnRated;
private javax.swing.JToggleButton btnSkillBeginner;
private javax.swing.JToggleButton btnSkillCasual;
@ -1665,6 +1718,7 @@ class UpdateTablesTask extends SwingWorker<Void, Collection<TableView>> {
private final UUID roomId;
private final TablesPanel panel;
private boolean isFirstRun = true;
private static final Logger logger = Logger.getLogger(UpdateTablesTask.class);
@ -1683,8 +1737,7 @@ class UpdateTablesTask extends SwingWorker<Void, Collection<TableView>> {
if (tables != null) {
this.publish(tables);
}
TimeUnit.SECONDS.sleep(TablesPanel.REFRESH_ACTIVE_TABLES_SECS);
TimeUnit.SECONDS.sleep(TablesPanel.randomizeTimout(TablesPanel.REFRESH_ACTIVE_TABLES_SECS));
}
return null;
}
@ -1692,10 +1745,13 @@ class UpdateTablesTask extends SwingWorker<Void, Collection<TableView>> {
@Override
protected void process(java.util.List<Collection<TableView>> view) {
panel.updateTables(view.get(0));
// update server messages
count++;
if (count > 60) {
if (isFirstRun || count > 60) {
count = 0;
panel.reloadMessages();
isFirstRun = false;
panel.reloadServerMessages();
}
}
@ -1728,7 +1784,7 @@ class UpdatePlayersTask extends SwingWorker<Void, Collection<RoomUsersView>> {
protected Void doInBackground() throws Exception {
while (!isCancelled()) {
this.publish(SessionHandler.getRoomUsers(roomId));
TimeUnit.SECONDS.sleep(TablesPanel.REFRESH_PLAYERS_SECS);
TimeUnit.SECONDS.sleep(TablesPanel.randomizeTimout(TablesPanel.REFRESH_PLAYERS_SECS));
}
return null;
}
@ -1765,11 +1821,8 @@ class UpdateMatchesTask extends SwingWorker<Void, Collection<MatchView>> {
@Override
protected Void doInBackground() throws Exception {
while (!isCancelled()) {
Collection<MatchView> matches = SessionHandler.getFinishedMatches(roomId);
if (!matches.isEmpty()) {
this.publish(matches);
}
TimeUnit.SECONDS.sleep(TablesPanel.REFRESH_FINISHED_TABLES_SECS);
this.publish(SessionHandler.getFinishedMatches(roomId));
TimeUnit.SECONDS.sleep(TablesPanel.randomizeTimout(TablesPanel.REFRESH_FINISHED_TABLES_SECS));
}
return null;
}

View file

@ -16,14 +16,15 @@ import java.util.UUID;
*/
public final class ArrowUtil {
private ArrowUtil() {}
private ArrowUtil() {
}
public static void drawArrowsForPairedCards(TransferData data, Point parentPoint) {
if (data.getCard().getPairedCard() != null) {
Point me = new Point(data.getLocationOnScreen());
me.translate(-parentPoint.x, -parentPoint.y);
UUID uuid = data.getCard().getPairedCard();
for (PlayAreaPanel pa : MageFrame.getGame(data.getGameId()).getPlayers().values()) {
for (PlayAreaPanel pa : MageFrame.getGamePlayers(data.getGameId()).values()) {
MagePermanent permanent = pa.getBattlefieldPanel().getPermanents().get(uuid);
if (permanent != null) {
Point target = permanent.getLocationOnScreen();
@ -38,7 +39,7 @@ public final class ArrowUtil {
if (data.getCard().getBandedCards() != null && !data.getCard().getBandedCards().isEmpty()) {
Point me = new Point(data.getLocationOnScreen());
me.translate(-parentPoint.x, -parentPoint.y);
for (PlayAreaPanel pa : MageFrame.getGame(data.getGameId()).getPlayers().values()) {
for (PlayAreaPanel pa : MageFrame.getGamePlayers(data.getGameId()).values()) {
for (UUID uuid : data.getCard().getBandedCards()) {
MagePermanent permanent = pa.getBattlefieldPanel().getPermanents().get(uuid);
if (permanent != null) {
@ -53,7 +54,7 @@ public final class ArrowUtil {
public static void drawArrowsForEnchantPlayers(TransferData data, Point parentPoint) {
if (data.getGameId() != null && MageFrame.getGame(data.getGameId()) != null) {
for (PlayAreaPanel pa : MageFrame.getGame(data.getGameId()).getPlayers().values()) {
for (PlayAreaPanel pa : MageFrame.getGamePlayers(data.getGameId()).values()) {
PlayerPanelExt playAreaPanel = pa.getPlayerPanel();
if (playAreaPanel != null && playAreaPanel.getPlayer() != null && playAreaPanel.getPlayer().hasAttachments()) {
Point me = new Point(data.getLocationOnScreen());
@ -62,7 +63,7 @@ public final class ArrowUtil {
if (attachmentId.equals(data.getCard().getId())) {
Point player = pa.getLocationOnScreen();
player.translate(-parentPoint.x, -parentPoint.y);
ArrowBuilder.getBuilder().addArrow(data.getGameId(),(int) me.getX() + 35, (int) me.getY(), (int) player.getX() + 40, (int) player.getY() - 40, Color.magenta, ArrowBuilder.Type.ENCHANT_PLAYERS);
ArrowBuilder.getBuilder().addArrow(data.getGameId(), (int) me.getX() + 35, (int) me.getY(), (int) player.getX() + 40, (int) player.getY() - 40, Color.magenta, ArrowBuilder.Type.ENCHANT_PLAYERS);
}
}
}
@ -75,7 +76,7 @@ public final class ArrowUtil {
Point me = new Point(data.getLocationOnScreen());
me.translate(-parentPoint.x, -parentPoint.y);
UUID uuid = data.getCard().getParentId();
for (PlayAreaPanel pa : MageFrame.getGame(data.getGameId()).getPlayers().values()) {
for (PlayAreaPanel pa : MageFrame.getGamePlayers(data.getGameId()).values()) {
MagePermanent permanent = pa.getBattlefieldPanel().getPermanents().get(uuid);
if (permanent != null) {
Point source = permanent.getLocationOnScreen();
@ -96,7 +97,7 @@ public final class ArrowUtil {
me.translate(-parentPoint.x, -parentPoint.y);
for (UUID uuid : targets) {
PlayAreaPanel p = MageFrame.getGame(data.getGameId()).getPlayers().get(uuid);
PlayAreaPanel p = MageFrame.getGamePlayers(data.getGameId()).get(uuid);
if (p != null) {
Point target = p.getLocationOnScreen();
target.translate(-parentPoint.x, -parentPoint.y);
@ -104,7 +105,7 @@ public final class ArrowUtil {
continue;
}
for (PlayAreaPanel panel : MageFrame.getGame(data.getGameId()).getPlayers().values()) {
for (PlayAreaPanel panel : MageFrame.getGamePlayers(data.getGameId()).values()) {
MagePermanent permanent = panel.getBattlefieldPanel().getPermanents().get(uuid);
if (permanent != null) {
Point target = permanent.getLocationOnScreen();
@ -117,7 +118,7 @@ public final class ArrowUtil {
if (view != null) {
CardsView graveyard = view.getGraveyard();
if (graveyard.containsKey(uuid)) {
p = MageFrame.getGame(data.getGameId()).getPlayers().get(view.getPlayerId());
p = MageFrame.getGamePlayers(data.getGameId()).get(view.getPlayerId());
if (p != null) {
Point target = p.getLocationOnScreen();
target.translate(-parentPoint.x, -parentPoint.y);

View file

@ -181,10 +181,14 @@ public final class GuiDisplayUtil {
public static TextLines getTextLinesfromCardView(CardView card) {
TextLines textLines = new TextLines();
// rules
textLines.setLines(new ArrayList<>(card.getRules()));
for (String rule : card.getRules()) {
textLines.setBasicTextLength(textLines.getBasicTextLength() + rule.length());
}
// counters
if (card.getMageObjectType().canHaveCounters()) {
ArrayList<CounterView> counters = new ArrayList<>();
if (card instanceof PermanentView) {
@ -212,6 +216,8 @@ public final class GuiDisplayUtil {
textLines.setBasicTextLength(textLines.getBasicTextLength() + 50);
}
}
// damage
if (card.getMageObjectType().isPermanent() && card instanceof PermanentView) {
int damage = ((PermanentView) card).getDamage();
if (damage > 0) {

View file

@ -1,5 +1,6 @@
package org.mage.card.arcane;
import mage.MageInt;
import mage.cards.action.ActionCallback;
import mage.client.constants.Constants;
import mage.client.dialog.PreferencesDialog;
@ -9,6 +10,7 @@ import mage.client.util.SoftValuesLoadingCache;
import mage.components.ImagePanel;
import mage.components.ImagePanelStyle;
import mage.constants.AbilityType;
import mage.constants.SubType;
import mage.view.CardView;
import mage.view.CounterView;
import mage.view.PermanentView;
@ -49,11 +51,16 @@ public class CardPanelComponentImpl extends CardPanel {
private static final int CARD_MIN_SIZE_FOR_ICONS = 60;
private static final int CARD_MAX_SIZE_FOR_ICONS = 200;
// text min size for image render mode
private static final int CARD_TITLE_FONT_MIN_SIZE = 13;
private static final int CARD_PT_FONT_MIN_SIZE = 17;
public final ScaledImagePanel imagePanel;
private ImagePanel overlayPanel;
private JPanel iconPanel;
private JButton typeButton;
private JPanel ptPanel;
private JPanel counterPanel;
private JLabel loyaltyCounterLabel;
@ -67,7 +74,9 @@ public class CardPanelComponentImpl extends CardPanel {
private int lastCardWidth;
private final GlowText titleText;
private final GlowText ptText;
private final GlowText ptText1;
private final GlowText ptText2;
private final GlowText ptText3;
private final JLabel fullImageText;
private String fullImagePath = null;
@ -280,7 +289,7 @@ public class CardPanelComponentImpl extends CardPanel {
// Title Text
titleText = new GlowText();
setText(getGameCard());
setTitle(getGameCard());
// int fontSize = (int) cardHeight / 11;
// titleText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
titleText.setForeground(Color.white);
@ -295,16 +304,19 @@ public class CardPanelComponentImpl extends CardPanel {
add(fullImageText);
// PT Text
ptText = new GlowText();
if (getGameCard().isCreature()) {
ptText.setText(getGameCard().getPower() + '/' + getGameCard().getToughness());
} else if (getGameCard().isPlanesWalker()) {
ptText.setText(getGameCard().getLoyalty());
}
// ptText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
ptText.setForeground(Color.white);
ptText.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY);
add(ptText);
ptPanel = new JPanel();
ptPanel.setOpaque(false);
ptPanel.setLayout(new BoxLayout(ptPanel, BoxLayout.X_AXIS));
ptPanel.add(new Box.Filler(new Dimension(0, 0), new Dimension(0, 0), new Dimension(Integer.MAX_VALUE, 0)));
ptText1 = new GlowText();
ptText2 = new GlowText();
ptText3 = new GlowText();
updatePTTexts(getGameCard());
ptPanel.add(ptText1);
ptPanel.add(ptText2);
ptPanel.add(ptText3);
//
add(ptPanel);
// Sickness overlay
BufferedImage sickness = ImageManagerImpl.instance.getSicknessImage();
@ -349,7 +361,7 @@ public class CardPanelComponentImpl extends CardPanel {
this.setCounterPanel(null);
}
private void setText(CardView card) {
private void setTitle(CardView card) {
titleText.setText(!displayTitleAnyway && hasImage ? "" : card.getName());
}
@ -585,12 +597,14 @@ public class CardPanelComponentImpl extends CardPanel {
boolean showText = !isAnimationPanel() && canShowCardIcons(cardWidth, hasImage);
titleText.setVisible(showText);
ptText.setVisible(showText);
ptText1.setVisible(showText && !ptText1.getText().isEmpty());
ptText2.setVisible(showText && !ptText2.getText().isEmpty());
ptText3.setVisible(showText && !ptText3.getText().isEmpty());
fullImageText.setVisible(fullImagePath != null);
if (showText) {
int fontSize = cardHeight / 13; // startup font size (it same size on all zoom levels)
titleText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
titleText.setFont(getFont().deriveFont(Font.BOLD, Math.max(CARD_TITLE_FONT_MIN_SIZE, fontSize)));
// margins from card black border to text, not need? text show up good without margins
int titleMarginLeft = 0; //Math.round(28f / 672f * cardWidth);
@ -607,24 +621,60 @@ public class CardPanelComponentImpl extends CardPanel {
fullImageText.setFont(getFont().deriveFont(Font.PLAIN, 10));
fullImageText.setBounds(titleText.getX(), titleText.getY(), titleText.getBounds().width, titleText.getBounds().height);
// life points location (font as title)
ptText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
Dimension ptSize = ptText.getPreferredSize();
ptText.setSize(ptSize.width, ptSize.height);
// PT (font as title)
if (getGameCard().getOriginalCard() != null) {
prepareGlowFont(ptText1, Math.max(CARD_PT_FONT_MIN_SIZE, fontSize), getGameCard().getOriginalCard().getPower(), false);
prepareGlowFont(ptText2, Math.max(CARD_PT_FONT_MIN_SIZE, fontSize), null, false);
prepareGlowFont(ptText3, Math.max(CARD_PT_FONT_MIN_SIZE, fontSize), getGameCard().getOriginalCard().getToughness(), CardRendererUtils.isCardWithDamage(getGameCard()));
// right bottom corner with margin (sizes from any sample card)
int ptMarginRight = Math.round(64f / 672f * cardWidth);
int ptMarginBottom = Math.round(62f / 936f * cardHeight);
// right bottom corner with margin (sizes from any sample card)
int ptMarginRight = Math.round(64f / 672f * cardWidth);
int ptMarginBottom = Math.round(62f / 936f * cardHeight);
int ptX = cardXOffset + cardWidth - ptMarginRight - ptSize.width;
int ptY = cardYOffset + cardHeight - ptMarginBottom - ptSize.height;
ptText.setLocation(ptX, ptY);
int ptWidth = cardWidth - ptMarginRight * 2;
int ptHeight = ptText2.getHeight();
int ptX = cardXOffset + ptMarginRight;
int ptY = cardYOffset + cardHeight - ptMarginBottom - ptHeight;
ptPanel.setBounds(ptX, ptY, ptWidth, ptHeight);
}
// old version was with TEXT_GLOW_SIZE
//ptText.setLocation(cardXOffset + ptX - TEXT_GLOW_SIZE / 2 - offsetX, cardYOffset + ptY - TEXT_GLOW_SIZE / 2);
}
}
private void prepareGlowFont(GlowText label, int fontSize, MageInt value, boolean drawAsDamaged) {
label.setFont(getFont().deriveFont(Font.BOLD, fontSize));
label.setForeground(CardRendererUtils.getCardTextColor(value, drawAsDamaged, titleText.getForeground(), true));
Dimension ptSize = label.getPreferredSize();
label.setSize(ptSize.width, ptSize.height);
}
private void updatePTTexts(CardView card) {
if (card.isCreature() || card.getSubTypes().contains(SubType.VEHICLE)) {
ptText1.setText(getGameCard().getPower());
ptText2.setText("/");
ptText3.setText(CardRendererUtils.getCardLifeWithDamage(getGameCard()));
} else if (card.isPlanesWalker()) {
ptText1.setText("");
ptText2.setText("");
ptText3.setText(getGameCard().getLoyalty());
} else {
ptText1.setText("");
ptText2.setText("");
ptText3.setText("");
}
ptText1.setForeground(Color.white);
ptText1.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY);
ptText2.setForeground(Color.white);
ptText2.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY);
ptText3.setForeground(Color.white);
ptText3.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY);
}
@Override
public String toString() {
return getGameCard().toString();
@ -647,10 +697,14 @@ public class CardPanelComponentImpl extends CardPanel {
// Update components
if (alpha == 0) {
this.ptText.setVisible(false);
this.ptText1.setVisible(false);
this.ptText2.setVisible(false);
this.ptText3.setVisible(false);
this.titleText.setVisible(false);
} else if (alpha == 1.0f) {
this.ptText.setVisible(true);
this.ptText1.setVisible(true);
this.ptText2.setVisible(true);
this.ptText3.setVisible(true);
this.titleText.setVisible(true);
}
}
@ -683,7 +737,7 @@ public class CardPanelComponentImpl extends CardPanel {
UI.invokeLater(() -> {
if (stamp == updateArtImageStamp) {
hasImage = srcImage != null;
setText(getGameCard());
setTitle(getGameCard());
setImage(srcImage);
}
});
@ -712,7 +766,7 @@ public class CardPanelComponentImpl extends CardPanel {
@Override
public void showCardTitle() {
displayTitleAnyway = true;
setText(getGameCard());
setTitle(getGameCard());
}
@Override
@ -720,17 +774,8 @@ public class CardPanelComponentImpl extends CardPanel {
// Super
super.update(card);
// Update card text
if (card.isCreature() && card.isPlanesWalker()) {
ptText.setText(card.getPower() + '/' + card.getToughness() + " (" + card.getLoyalty() + ')');
} else if (card.isCreature()) {
ptText.setText(card.getPower() + '/' + card.getToughness());
} else if (card.isPlanesWalker()) {
ptText.setText(card.getLoyalty());
} else {
ptText.setText("");
}
setText(card);
updatePTTexts(card);
setTitle(card);
// Summoning Sickness overlay
if (hasSickness() && card.isCreature() && isPermanent()) {

View file

@ -297,6 +297,8 @@ public class CardPanelRenderImpl extends CardPanel {
// Render with Antialialsing
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
// Attributes
CardPanelAttributes attribs

View file

@ -1,5 +1,9 @@
package org.mage.card.arcane;
import mage.MageInt;
import mage.view.CardView;
import mage.view.PermanentView;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.HashMap;
@ -10,12 +14,18 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author stravant@gmail.com
* @author stravant@gmail.com, JayDi85
* <p>
* Various static utilities for use in the card renderer
*/
public final class CardRendererUtils {
// text colors for PT (mtgo and image render modes)
private static final Color CARD_TEXT_COLOR_GOOD_LIGHT = new Color(182, 235, 168);
private static final Color CARD_TEXT_COLOR_GOOD_DARK = new Color(52, 135, 88);
private static final Color CARD_TEXT_COLOR_BAD_LIGHT = new Color(234, 153, 153);
private static final Color CARD_TEXT_COLOR_BAD_DARK = new Color(200, 33, 33);
/**
* Convert an abstract image, whose underlying implementation may or may not
* be a BufferedImage into a BufferedImage by creating one and coping the
@ -53,9 +63,9 @@ public final class CardRendererUtils {
int b = c.getBlue();
int alpha = c.getAlpha();
int plus_r = (int) ((255 - r) / 2);
int plus_g = (int) ((255 - g) / 2);
int plus_b = (int) ((255 - b) / 2);
int plus_r = (255 - r) / 2;
int plus_g = (255 - g) / 2;
int plus_b = (255 - b) / 2;
return new Color(r + plus_r,
g + plus_g,
@ -69,9 +79,9 @@ public final class CardRendererUtils {
int b = c.getBlue();
int alpha = c.getAlpha();
int plus_r = (int) (Math.min(255 - r, r) / 2);
int plus_g = (int) (Math.min(255 - g, g) / 2);
int plus_b = (int) (Math.min(255 - b, b) / 2);
int plus_r = Math.min(255 - r, r) / 2;
int plus_g = Math.min(255 - g, g) / 2;
int plus_b = Math.min(255 - b, b) / 2;
return new Color(r - plus_r,
g - plus_g,
@ -195,4 +205,52 @@ public final class CardRendererUtils {
return null;
}
}
public static String getCardLifeWithDamage(CardView cardView) {
// life with damage
String originLife = cardView.getToughness();
if (cardView instanceof PermanentView) {
int damage = ((PermanentView) cardView).getDamage();
int life;
try {
life = Integer.parseInt(originLife);
originLife = String.valueOf(Math.max(0, life - damage));
} catch (NumberFormatException e) {
//
}
}
return originLife;
}
public static boolean isCardWithDamage(CardView cardView) {
boolean haveDamage = false;
if (cardView instanceof PermanentView) {
haveDamage = ((PermanentView) cardView).getDamage() > 0;
}
return haveDamage;
}
public static Color getCardTextColor(MageInt value, boolean drawAsDamaged, Color defaultColor, boolean textLight) {
if (drawAsDamaged) {
return textLight ? CARD_TEXT_COLOR_BAD_LIGHT : CARD_TEXT_COLOR_BAD_DARK;
}
// boost colorizing
if (value != null) {
int current = value.getValue();
int origin = value.getBaseValue();
if (origin != 0) {
if (current < origin) {
return textLight ? CARD_TEXT_COLOR_BAD_LIGHT : CARD_TEXT_COLOR_BAD_DARK;
} else if (current > origin) {
return textLight ? CARD_TEXT_COLOR_GOOD_LIGHT : CARD_TEXT_COLOR_GOOD_DARK;
} else {
return defaultColor;
}
}
}
return defaultColor;
}
}

View file

@ -1,5 +1,10 @@
package org.mage.card.arcane;
import mage.client.util.ImageCaches;
import mage.client.util.SoftValuesLoadingCache;
import org.jdesktop.swingx.graphics.GraphicsUtilities;
import javax.swing.*;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer;
@ -14,17 +19,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import javax.swing.*;
import org.jdesktop.swingx.graphics.GraphicsUtilities;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import mage.client.util.ImageCaches;
import mage.client.util.SoftValuesLoadingCache;
public class GlowText extends JLabel {
private static final long serialVersionUID = 1827677946939348001L;
@ -123,10 +117,7 @@ public class GlowText extends JLabel {
if (!Objects.equals(this.color, other.color)) {
return false;
}
if (!Objects.equals(this.glowColor, other.glowColor)) {
return false;
}
return true;
return Objects.equals(this.glowColor, other.glowColor);
}
}
@ -158,7 +149,11 @@ public class GlowText extends JLabel {
return;
}
g.drawImage(IMAGE_CACHE.getOrThrow(new Key(getWidth(), getHeight(), getText(), getFont(), getForeground(), glowSize, glowIntensity, glowColor, wrap)), 0, 0, null);
g.drawImage(getGlowImage(), 0, 0, null);
}
public BufferedImage getGlowImage() {
return IMAGE_CACHE.getOrThrow(new Key(getWidth(), getHeight(), getText(), getFont(), getForeground(), glowSize, glowIntensity, glowColor, wrap));
}
private static BufferedImage createGlowImage(Key key) {

View file

@ -1,8 +1,3 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.mage.card.arcane;
import mage.ObjectColor;
@ -56,13 +51,14 @@ import static org.mage.card.arcane.ManaSymbols.getSizedManaSymbol;
*/
/**
* @author stravant@gmail.com
* @author stravant@gmail.com, JayDi85
* <p>
* Base rendering class for new border cards
*/
public class ModernCardRenderer extends CardRenderer {
private static final Logger LOGGER = Logger.getLogger(ModernCardRenderer.class);
private static final GlowText glowTextRenderer = new GlowText();
///////////////////////////////////////////////////////////////////////////
// Textures for modern frame cards
@ -98,7 +94,7 @@ public class ModernCardRenderer extends CardRenderer {
return new Font("Arial", Font.PLAIN, 1);
}
public static final Font BASE_BELEREN_FONT = loadFont("beleren-bold");
// public static final Font BASE_BELEREN_FONT = loadFont("beleren-bold");
public static final Paint BG_TEXTURE_WHITE = loadBackgroundTexture("white");
public static final Paint BG_TEXTURE_BLUE = loadBackgroundTexture("blue");
@ -252,16 +248,13 @@ public class ModernCardRenderer extends CardRenderer {
// Box text height
boxTextHeight = getTextHeightForBoxHeight(boxHeight);
boxTextOffset = (boxHeight - boxTextHeight) / 2;
// Not using Beleren for now because it looks bad at small font sizes. Maybe we want to in the future?
//boxTextFont = BASE_BELEREN_FONT.deriveFont(Font.PLAIN, boxTextHeight);
boxTextFont = new Font("Arial", Font.PLAIN, boxTextHeight);
boxTextFontNarrow = new Font("Arial Narrow", Font.PLAIN, boxTextHeight);
// Box text height
ptTextHeight = getPTTextHeightForLineHeight(boxHeight);
ptTextOffset = (boxHeight - ptTextHeight) / 2;
// Beleren font does work well for numbers though
ptTextFont = BASE_BELEREN_FONT.deriveFont(Font.PLAIN, ptTextHeight);
ptTextFont = new Font("Arial", Font.BOLD, ptTextHeight);
}
@Override
@ -482,7 +475,7 @@ public class ModernCardRenderer extends CardRenderer {
g.setPaint(borderPaint);
if (cardView.getFrameStyle() == FrameStyle.KLD_INVENTION) {
g.drawImage(FRAME_INVENTION, 0, 0, cardWidth, cardHeight, null);
g.drawImage(FRAME_INVENTION, 3, 3, cardWidth - 6, cardHeight - 6, null);
g.drawRect(
totalContentInset, typeLineY,
contentWidth - 1, cardHeight - borderWidth * 3 - typeLineY - 1);
@ -933,6 +926,51 @@ public class ModernCardRenderer extends CardRenderer {
}
}
public void paintOutlineTextByGlow(Graphics2D g, String text, Color color, int x, int y) {
GlowText label = new GlowText();
label.setGlow(Color.black, 6, 3);
label.setText(text);
label.setFont(g.getFont().deriveFont(Font.BOLD));
label.setForeground(color);
Dimension ptSize = label.getPreferredSize();
label.setSize(ptSize.width, ptSize.height);
g.drawImage(label.getGlowImage(), x, y, null);
}
public void paintOutlineTextByStroke(Graphics2D g, String text, Color color, int x, int y) {
// https://stackoverflow.com/a/35222059/1276632
Color outlineColor = Color.black;
Color fillColor = color;
BasicStroke outlineStroke = new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
// remember original settings
Color originalColor = g.getColor();
Stroke originalStroke = g.getStroke();
RenderingHints originalHints = g.getRenderingHints();
// create a glyph vector from your text
GlyphVector glyphVector = g.getFont().createGlyphVector(g.getFontRenderContext(), text);
// get the shape object
Shape textShape = glyphVector.getOutline(x, y);
// activate anti aliasing for text rendering (if you want it to look nice)
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.setColor(outlineColor);
g.setStroke(outlineStroke);
g.draw(textShape); // draw outline
g.setColor(fillColor);
g.fill(textShape); // fill the shape
// reset to original settings after painting
g.setColor(originalColor);
g.setStroke(originalStroke);
g.setRenderingHints(originalHints);
}
// Draw the P/T and/or Loyalty boxes
protected void drawBottomRight(Graphics2D g, Paint borderPaint, Color fill) {
// No bottom right for abilities
@ -944,17 +982,31 @@ public class ModernCardRenderer extends CardRenderer {
int curY = cardHeight - (int) (0.03f * cardHeight);
// Width of the boxes
int partWidth = (int) Math.max(30, 0.20f * cardWidth);
int partBoxWidth = (int) Math.max(30, 0.20f * cardWidth);
// Is it a creature?
boolean isVehicle = cardView.getSubTypes().contains(SubType.VEHICLE);
if (cardView.isCreature() || isVehicle) {
int x = cardWidth - borderWidth - partWidth;
// draws p/t by parts
int ptDeviderSpace = 1; // Arial font is too narrow for devider (2/2) and needs extra space
String ptText1 = cardView.getPower();
String ptText2 = "/";
String ptText3 = CardRendererUtils.getCardLifeWithDamage(cardView);
int ptTextWidth1 = g.getFontMetrics(ptTextFont).stringWidth(ptText1);
int ptTextWidth2 = g.getFontMetrics(ptTextFont).stringWidth(ptText2) + 2 * ptDeviderSpace;
int ptTextWidth3 = g.getFontMetrics(ptTextFont).stringWidth(ptText3);
// PT max size
int ptContentWidth = contentInset + ptTextWidth1 + ptDeviderSpace + ptTextWidth2 + ptDeviderSpace + ptTextWidth3 + contentInset;
partBoxWidth = Math.max(ptContentWidth, partBoxWidth);
int x = cardWidth - borderWidth - partBoxWidth;
// Draw PT box
CardRendererUtils.drawRoundedBox(g,
x, curY - boxHeight,
partWidth, boxHeight,
partBoxWidth, boxHeight,
contentInset,
borderPaint,
isVehicle ? BOX_VEHICLE : fill);
@ -963,27 +1015,42 @@ public class ModernCardRenderer extends CardRenderer {
g.setColor(new Color(0, 0, 0, 150));
g.fillRect(
x + contentInset, curY - boxHeight - 1,
partWidth - 2 * contentInset, 1);
partBoxWidth - 2 * contentInset, 1);
// Draw text
Color textColor;
Color defaultTextColor;
boolean defaultTextLight;
if (isVehicle) {
boolean isAnimated = !(cardView instanceof PermanentView) || cardView.isCreature();
if (isAnimated) {
textColor = Color.white;
defaultTextColor = Color.white;
} else {
textColor = new Color(180, 180, 180);
defaultTextColor = new Color(180, 180, 180);
}
defaultTextLight = true;
} else {
textColor = getBoxTextColor();
defaultTextColor = getBoxTextColor();
defaultTextLight = !defaultTextColor.equals(Color.black);
}
g.setColor(textColor);
g.setColor(defaultTextColor);
g.setFont(ptTextFont);
String ptText = cardView.getPower() + '/' + cardView.getToughness();
int ptTextWidth = g.getFontMetrics().stringWidth(ptText);
g.drawString(ptText,
x + (partWidth - ptTextWidth) / 2, curY - ptTextOffset - 1);
// draws
int ptEmptySpace = (partBoxWidth - ptContentWidth) / 2;
int ptPosStart1 = x + contentInset + ptEmptySpace;
int ptPosStart2 = ptPosStart1 + ptTextWidth1 + ptDeviderSpace;
int ptPosStart3 = ptPosStart2 + ptTextWidth2 + ptDeviderSpace;
// p
g.setColor(CardRendererUtils.getCardTextColor(cardView.getOriginalCard().getPower(), false, defaultTextColor, defaultTextLight));
g.drawString(ptText1, ptPosStart1, curY - ptTextOffset - 1); // left
// /
g.setColor(defaultTextColor);
g.drawString(ptText2, ptPosStart2, curY - ptTextOffset - 1); // center
// t
g.setColor(CardRendererUtils.getCardTextColor(cardView.getOriginalCard().getPower(), CardRendererUtils.isCardWithDamage(cardView), defaultTextColor, defaultTextLight));
g.drawString(ptText3, ptPosStart3, curY - ptTextOffset - 1); // right
//
g.setColor(defaultTextColor);
// Advance
curY -= boxHeight;
@ -994,9 +1061,9 @@ public class ModernCardRenderer extends CardRenderer {
if (cardView.isPlanesWalker()
&& (cardView instanceof PermanentView || !cardView.getStartingLoyalty().equals("0"))) {
// Draw the PW loyalty box
int w = partWidth;
int h = partWidth / 2;
int x = cardWidth - partWidth - borderWidth;
int w = partBoxWidth;
int h = partBoxWidth / 2;
int x = cardWidth - partBoxWidth - borderWidth;
int y = curY - h;
Polygon symbol = new Polygon(
@ -1047,16 +1114,16 @@ public class ModernCardRenderer extends CardRenderer {
// does it have damage on it?
if ((cardView instanceof PermanentView) && ((PermanentView) cardView).getDamage() > 0) {
int x = cardWidth - partWidth - borderWidth;
int x = cardWidth - partBoxWidth - borderWidth;
int y = curY - boxHeight;
String damage = String.valueOf(((PermanentView) cardView).getDamage());
g.setFont(ptTextFont);
int txWidth = g.getFontMetrics().stringWidth(damage);
g.setColor(Color.red);
g.fillRect(x, y, partWidth, boxHeight);
g.fillRect(x, y, partBoxWidth, boxHeight);
g.setColor(Color.white);
g.drawRect(x, y, partWidth, boxHeight);
g.drawString(damage, x + (partWidth - txWidth) / 2, curY - 1);
g.drawRect(x, y, partBoxWidth, boxHeight);
g.drawString(damage, x + (partBoxWidth - txWidth) / 2, curY - 1);
}
}

View file

@ -2,7 +2,6 @@ package org.mage.plugins.card;
import mage.cards.MagePermanent;
import mage.cards.action.ActionCallback;
import mage.client.dialog.PreferencesDialog;
import mage.client.util.GUISizeHelper;
import mage.interfaces.plugin.CardPlugin;
import mage.view.CardView;
@ -99,25 +98,28 @@ public class CardPluginImpl implements CardPlugin {
* Temporary card rendering shim. Split card rendering isn't implemented
* yet, so use old component based rendering for the split cards.
*/
private CardPanel makePanel(CardView view, UUID gameId, boolean loadImage, ActionCallback callback, boolean isFoil, Dimension dimension) {
String fallback = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_RENDERING_FALLBACK, "false");
if (fallback.equals("true")) {
return new CardPanelComponentImpl(view, gameId, loadImage, callback, isFoil, dimension);
} else {
return new CardPanelRenderImpl(view, gameId, loadImage, callback, isFoil, dimension);
private CardPanel makePanel(CardView view, UUID gameId, boolean loadImage, ActionCallback callback, boolean isFoil, Dimension dimension, int renderMode) {
switch (renderMode) {
case 0:
return new CardPanelRenderImpl(view, gameId, loadImage, callback, isFoil, dimension);
case 1:
return new CardPanelComponentImpl(view, gameId, loadImage, callback, isFoil, dimension);
default:
throw new IllegalStateException("Unknown render mode " + renderMode);
}
}
@Override
public MagePermanent getMagePermanent(PermanentView permanent, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage) {
CardPanel cardPanel = makePanel(permanent, gameId, loadImage, callback, false, dimension);
public MagePermanent getMagePermanent(PermanentView permanent, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage, int renderMode) {
CardPanel cardPanel = makePanel(permanent, gameId, loadImage, callback, false, dimension, renderMode);
cardPanel.setShowCastingCost(true);
return cardPanel;
}
@Override
public MagePermanent getMageCard(CardView cardView, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage) {
CardPanel cardPanel = makePanel(cardView, gameId, loadImage, callback, false, dimension);
public MagePermanent getMageCard(CardView cardView, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage, int renderMode) {
CardPanel cardPanel = makePanel(cardView, gameId, loadImage, callback, false, dimension, renderMode);
cardPanel.setShowCastingCost(true);
return cardPanel;
}

View file

@ -50,8 +50,25 @@ public class ScryfallImageSupportTokens {
put("RNA/Zombie", "https://api.scryfall.com/cards/trna/3/en?format=image");
// WAR
put("WAR/Zombie Army", "https://api.scryfall.com/cards/twar/8/en?format=image");
put("WAR/Angel", "https://api.scryfall.com/cards/twar/2/en?format=image");
put("WAR/Assassin", "https://api.scryfall.com/cards/twar/6/en?format=image");
put("WAR/Citizen", "https://api.scryfall.com/cards/twar/16/en?format=image");
put("WAR/Devil", "https://api.scryfall.com/cards/twar/12/en?format=image");
put("WAR/Dragon", "https://api.scryfall.com/cards/twar/13/en?format=image");
put("WAR/Goblin", "https://api.scryfall.com/cards/twar/14/en?format=image");
put("WAR/Emblem Nissa, Who Shakes the World", "https://api.scryfall.com/cards/twar/19/en?format=image");
put("WAR/Servo", "https://api.scryfall.com/cards/twar/18/en?format=image");
put("WAR/Soldier", "https://api.scryfall.com/cards/twar/3/en?format=image");
put("WAR/Spirit", "https://api.scryfall.com/cards/twar/1/en?format=image");
put("WAR/Voja, Friend to Elves", "https://api.scryfall.com/cards/twar/17/en?format=image");
put("WAR/Wall", "https://api.scryfall.com/cards/twar/4/en?format=image");
put("WAR/Wizard", "https://api.scryfall.com/cards/twar/5/en?format=image");
put("WAR/Wolf", "https://api.scryfall.com/cards/twar/15/en?format=image");
put("WAR/Zombie Army/1", "https://api.scryfall.com/cards/twar/10/en?format=image");
put("WAR/Zombie Army/2", "https://api.scryfall.com/cards/twar/8/en?format=image");
put("WAR/Zombie Army/3", "https://api.scryfall.com/cards/twar/9/en?format=image");
put("WAR/Zombie Warrior", "https://api.scryfall.com/cards/twar/11/en?format=image");
put("WAR/Zombie", "https://api.scryfall.com/cards/twar/7/en?format=image");
// generate supported sets
supportedSets.clear();

View file

@ -52,7 +52,7 @@ public final class CardImageUtils {
return filePath;
}
log.warn("Token image file not found. Set: " + card.getSet() + " Token Set Code: " + card.getTokenSetCode() + " Name: " + card.getName() + " File path: " + getTokenImagePath(card));
//log.warn("Token image file not found. Set: " + card.getSet() + " Token Set Code: " + card.getTokenSetCode() + " Name: " + card.getName() + " File path: " + getTokenImagePath(card));
} else {
log.warn("Trying to get token path for non token card. Set: " + card.getSet() + " Set Code: " + card.getTokenSetCode() + " Name: " + card.getName());
}

View file

@ -87,6 +87,7 @@
|Generate|EMBLEM:SWS|Obi-Wan Kenobi||Emblem Obi-Wan Kenobi|ObiWanKenobiEmblem|
|Generate|EMBLEM:RIX|Huatli, Radiant Champion||Emblem Huatli|HuatliRadiantChampionEmblem|
|Generate|EMBLEM:RNA|Domri, Chaos Bringer||Emblem Domri|DomriChaosBringerEmblem|
|Generate|EMBLEM:WAR|Nissa, Who Shakes the World||Emblem Nissa|NissaWhoShakesTheWorldEmblem|
|Generate|PLANE:PCA|Plane - Academy At Tolaria West|||AcademyAtTolariaWestPlane|
|Generate|PLANE:PCA|Plane - Agyrem|||AgyremPlane|
|Generate|PLANE:PCA|Plane - Akoum|||AkoumPlane|
@ -1198,4 +1199,27 @@
|Generate|TOK:RNA|Thopter|||ThopterToken|
|Generate|TOK:RNA|Treasure|||TreasureToken|
|Generate|TOK:RNA|Zombie|||ZombieToken|
|Generate|TOK:WAR|Zombie Army|||ZombieArmyToken|
|Generate|TOK:WAR|Angel|||AngelVigilanceToken|
|Generate|TOK:WAR|Assassin|||AssassinToken2|
|Generate|TOK:WAR|Devil|||DevilToken|
|Generate|TOK:WAR|Dragon|||DragonToken|
|Generate|TOK:WAR|Goblin|||GoblinToken|
|Generate|TOK:WAR|Servo|||ServoToken|
|Generate|TOK:WAR|Soldier|||SoldierVigilanceToken|
|Generate|TOK:WAR|Spirit|||UginTheIneffableToken|
|Generate|TOK:WAR|Voja, Friend to Elves|||VojaFriendToElvesToken|
|Generate|TOK:WAR|Wall|||TeyoToken|
|Generate|TOK:WAR|Wizard|||WizardToken|
|Generate|TOK:WAR|Wolf|||WolfToken|
|Generate|TOK:WAR|Zombie|||ZombieToken|
|Generate|TOK:WAR|Zombie Warrior|||GodEternalOketraToken|
|Generate|TOK:WAR|Zombie Army|1||ZombieArmyToken|
|Generate|TOK:WAR|Zombie Army|2||ZombieArmyToken|
|Generate|TOK:WAR|Zombie Army|3||ZombieArmyToken|

View file

@ -71,7 +71,7 @@ public class MultiConnectTest {
}
@Override
public void disconnected(boolean errorCall) {
public void disconnected(boolean askToReconnect) {
logger.info("disconnected");
}

View file

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

View file

@ -1,11 +1,9 @@
package mage.interfaces;
import mage.interfaces.callback.CallbackClient;
import mage.utils.MageVersion;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public interface MageClient extends CallbackClient {
@ -14,7 +12,7 @@ public interface MageClient extends CallbackClient {
void connected(String message);
void disconnected(boolean errorCall);
void disconnected(boolean askToReconnect);
void showMessage(String message);

View file

@ -1,30 +1,28 @@
package mage.interfaces.plugin;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Map;
import java.util.UUID;
import javax.swing.*;
import mage.cards.MagePermanent;
import mage.cards.action.ActionCallback;
import mage.view.CardView;
import mage.view.PermanentView;
import net.xeoh.plugins.base.Plugin;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Map;
import java.util.UUID;
/**
* Interface for card plugins
*
* @version 0.6 17.07.2011 added options to #sortPermanents
* @version 0.3 21.11.2010 #getMageCard
* @version 0.2 07.11.2010 #downloadImages
* @version 0.1 31.10.2010 #getMagePermanent, #sortPermanents
* @author nantuko
* @version 0.1 31.10.2010 #getMagePermanent, #sortPermanents
*/
public interface CardPlugin extends Plugin {
MagePermanent getMagePermanent(PermanentView permanent, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage);
MagePermanent getMagePermanent(PermanentView permanent, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage, int renderMode);
MagePermanent getMageCard(CardView permanent, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage);
MagePermanent getMageCard(CardView permanent, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage, int renderMode);
int sortPermanents(Map<String, JComponent> ui, Map<UUID, MagePermanent> cards, boolean nonPermanentsOwnRow, boolean topPanel);

View file

@ -28,14 +28,16 @@ import org.jboss.remoting.transport.bisocket.Bisocket;
import org.jboss.remoting.transport.socket.SocketWrapper;
import org.jboss.remoting.transporter.TransporterClient;
import javax.swing.*;
import java.io.*;
import java.lang.reflect.UndeclaredThrowableException;
import java.net.*;
import java.util.*;
import java.util.concurrent.CancellationException;
import java.util.concurrent.TimeUnit;
/**
* @author BetaSteward_at_googlemail.com
* @author BetaSteward_at_googlemail.com, JayDi85
*/
public class SessionImpl implements Session {
@ -54,6 +56,7 @@ public class SessionImpl implements Session {
private ServerState serverState;
private SessionState sessionState = SessionState.DISCONNECTED;
private Connection connection;
private RemotingTask lastRemotingTask = null;
private static final int PING_CYCLES = 10;
private final LinkedList<Long> pingTime = new LinkedList<>();
private String pingInfo = "";
@ -76,22 +79,56 @@ public class SessionImpl implements Session {
return sessionId;
}
// 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 {
// RemotingTask - do server side works in background and return result, can be canceled at any time
public abstract class RemotingTask {
boolean run() throws Throwable;
SwingWorker<Boolean, Object> worker = null;
Throwable lastError = null;
abstract public boolean work() throws Throwable;
boolean doWork() throws Throwable {
worker = new SwingWorker<Boolean, Object>() {
@Override
protected Boolean doInBackground() {
try {
return work();
} catch (Throwable t) {
lastError = t;
return false;
}
}
};
worker.execute();
boolean res = worker.get();
if (lastError != null) {
throw lastError;
}
return res;
}
public void cancel() {
if (worker != null) {
worker.cancel(true);
}
}
}
// handleRemotingTaskExceptions runs the given task and handles exceptions appropriately. This
// way we can share the common exception handling.
private boolean handleRemotingTaskExceptions(RemotingTask remoting) {
private void showMessageToUser(String message) {
client.showMessage("Remote task error. " + message);
}
private boolean doRemoteWorkAndHandleErrors(RemotingTask remoting) {
// execute remote task and wait result, can be canceled
lastRemotingTask = remoting;
try {
return remoting.run();
return remoting.doWork();
} catch (InterruptedException | CancellationException t) {
// was canceled by user, nothing to show
} catch (MalformedURLException ex) {
logger.fatal("", ex);
client.showMessage("Unable connect to server. " + ex.getMessage());
logger.fatal("Connect: wrong server address", ex);
showMessageToUser(ex.getMessage());
} catch (UndeclaredThrowableException ex) {
String addMessage = "";
Throwable cause = ex.getCause();
@ -103,7 +140,7 @@ public class SessionImpl implements Session {
addMessage = "Probably the server version is not compatible with the client. ";
}
} else {
logger.error("Unknown server error", exep.getCause());
logger.error("Connect: unknown server error", exep.getCause());
}
} else if (cause instanceof NoSuchMethodException) {
// NoSuchMethodException is thrown on an invocation of an unknow JBoss remoting
@ -112,66 +149,59 @@ public class SessionImpl implements Session {
+ "server version is not compatible with the client: " + cause.getMessage();
}
if (addMessage.isEmpty()) {
logger.fatal("", ex);
logger.fatal("Connect: unknown error", ex);
}
client.showMessage("Unable connect to server. " + addMessage + (ex.getMessage() != null ? ex.getMessage() : ""));
showMessageToUser(addMessage + (ex.getMessage() != null ? ex.getMessage() : ""));
} catch (IOException ex) {
logger.fatal("", ex);
logger.fatal("Connect: unknown IO error", ex);
String addMessage = "";
if (ex.getMessage() != null && ex.getMessage().startsWith("Unable to perform invocation")) {
addMessage = "Maybe the server version is not compatible. ";
}
client.showMessage("Unable connect to server. " + addMessage + (ex.getMessage() != null ? ex.getMessage() : ""));
showMessageToUser(addMessage + (ex.getMessage() != null ? ex.getMessage() : ""));
} catch (MageVersionException ex) {
if (!canceled) {
client.showMessage("Unable connect to server. " + ex.getMessage());
}
logger.warn("Connect: wrong versions");
disconnect(false);
if (!canceled) {
showMessageToUser(ex.getMessage());
}
} catch (CannotConnectException ex) {
if (!canceled) {
handleCannotConnectException(ex);
}
} catch (Throwable t) {
logger.fatal("Unable connect to server - ", t);
logger.fatal("Connect: FAIL", t);
disconnect(false);
if (!canceled) {
disconnect(false);
StringBuilder sb = new StringBuilder();
sb.append("Unable connect to server.\n");
for (StackTraceElement element : t.getStackTrace()) {
sb.append(element.toString()).append('\n');
}
client.showMessage(sb.toString());
showMessageToUser(t.getMessage());
}
} finally {
lastRemotingTask = null;
}
return false;
}
@Override
public synchronized boolean register(final Connection connection) {
return establishJBossRemotingConnection(connection) && handleRemotingTaskExceptions(new RemotingTask() {
return doRemoteConnection(connection) && doRemoteWorkAndHandleErrors(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;
public boolean work() throws Throwable {
logger.info("Registration: username " + getUserName() + " for email " + getEmail());
boolean result = server.registerUser(sessionId, connection.getUsername(), connection.getPassword(), connection.getEmail());
logger.info("Registration: " + (result ? "DONE, check your email for new password" : "FAIL"));
return result;
}
});
}
@Override
public synchronized boolean emailAuthToken(final Connection connection) {
return establishJBossRemotingConnection(connection) && handleRemotingTaskExceptions(new RemotingTask() {
return doRemoteConnection(connection) && doRemoteWorkAndHandleErrors(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());
public boolean work() throws Throwable {
logger.info("Auth request: requesting auth token for username " + getUserName() + " to email " + getEmail());
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());
}
logger.info("Auth request: " + (result ? "DONE, check your email for auth token" : "FAIL"));
return result;
}
});
@ -179,14 +209,12 @@ public class SessionImpl implements Session {
@Override
public synchronized boolean resetPassword(final Connection connection) {
return establishJBossRemotingConnection(connection) && handleRemotingTaskExceptions(new RemotingTask() {
return doRemoteConnection(connection) && doRemoteWorkAndHandleErrors(new RemotingTask() {
@Override
public boolean run() throws Throwable {
logger.info("Trying reset the password in XMAGE server at " + connection.getHost() + ':' + connection.getPort());
public boolean work() throws Throwable {
logger.info("Password reset: reseting password for username " + getUserName());
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());
}
logger.info("Password reset: " + (result ? "DONE, check your email for new password" : "FAIL"));
return result;
}
});
@ -194,39 +222,39 @@ public class SessionImpl implements Session {
@Override
public synchronized boolean connect(final Connection connection) {
return establishJBossRemotingConnection(connection)
&& handleRemotingTaskExceptions(new RemotingTask() {
return doRemoteConnection(connection) && doRemoteWorkAndHandleErrors(new RemotingTask() {
@Override
public boolean run() throws Throwable {
public boolean work() throws Throwable {
setLastError("");
logger.info("Trying to log-in as " + getUserName() + " to XMAGE server at " + connection.getHost() + ':' + connection.getPort());
boolean registerResult;
logger.info("Logging: as username " + getUserName() + " to server " + connection.getHost() + ':' + connection.getPort());
boolean result;
if (connection.getAdminPassword() == null) {
// for backward compatibility. don't remove twice call - first one does nothing but for version checking
registerResult = server.connectUser(connection.getUsername(), connection.getPassword(), sessionId, client.getVersion(), connection.getUserIdStr());
result = server.connectUser(connection.getUsername(), connection.getPassword(), sessionId, client.getVersion(), connection.getUserIdStr());
} else {
registerResult = server.connectAdmin(connection.getAdminPassword(), sessionId, client.getVersion());
result = server.connectAdmin(connection.getAdminPassword(), sessionId, client.getVersion());
}
if (registerResult) {
if (result) {
serverState = server.getServerState();
// client side check for incompatible versions
if (client.getVersion().compareTo(serverState.getVersion()) != 0) {
String err = "Client and server versions are incompatible.";
setLastError(err);
logger.info(err);
disconnect(false);
return false;
throw new MageVersionException(client.getVersion(), serverState.getVersion());
}
if (!connection.getUsername().equals("Admin")) {
server.setUserData(connection.getUsername(), sessionId, connection.getUserData(), client.getVersion().toString(), connection.getUserIdStr());
updateDatabase(connection.isForceDBComparison(), serverState);
}
logger.info("Logged-in as " + getUserName() + " to MAGE server at " + connection.getHost() + ':' + connection.getPort());
logger.info("Logging: DONE");
client.connected(getUserName() + '@' + connection.getHost() + ':' + connection.getPort() + ' ');
return true;
}
logger.info("Logging: FAIL");
disconnect(false);
return false;
}
@ -241,20 +269,24 @@ public class SessionImpl implements Session {
@Override
public boolean stopConnecting() {
canceled = true;
if (lastRemotingTask != null) {
lastRemotingTask.cancel();
}
return true;
}
private boolean establishJBossRemotingConnection(final Connection connection) {
private boolean doRemoteConnection(final Connection connection) {
// connect to server and setup all data, can be canceled
if (isConnected()) {
disconnect(true);
}
this.connection = connection;
this.canceled = false;
sessionState = SessionState.CONNECTING;
boolean result = handleRemotingTaskExceptions(new RemotingTask() {
lastRemotingTask = new RemotingTask() {
@Override
public boolean run() throws Throwable {
logger.info("Trying to connect to XMAGE server at " + connection.getHost() + ':' + connection.getPort());
public boolean work() throws Throwable {
logger.info("Connect: connecting to server " + connection.getHost() + ':' + connection.getPort());
System.setProperty("http.nonProxyHosts", "code.google.com");
System.setProperty("socksNonProxyHosts", "code.google.com");
@ -265,6 +297,9 @@ public class SessionImpl implements Session {
System.clearProperty("http.proxyHost");
System.clearProperty("http.proxyPort");
if (connection.getProxyType() != Connection.ProxyType.NONE) {
logger.info("Connect: using proxy " + connection.getProxyHost() + ":" + connection.getProxyPort());
}
switch (connection.getProxyType()) {
case SOCKS:
System.setProperty("socksProxyHost", connection.getProxyHost());
@ -392,15 +427,24 @@ public class SessionImpl implements Session {
sessionId = callbackClient.getSessionId();
sessionState = SessionState.CONNECTED;
logger.info("Connected to MAGE server at " + connection.getHost() + ':' + connection.getPort());
logger.info("Connect: DONE");
return true;
}
});
};
boolean result;
try {
result = doRemoteWorkAndHandleErrors(lastRemotingTask);
} finally {
lastRemotingTask = null;
}
if (result) {
return true;
} else {
disconnect(false);
return false;
}
disconnect(false);
return false;
}
private void updateDatabase(boolean forceDBComparison, ServerState serverState) {
@ -463,7 +507,7 @@ public class SessionImpl implements Session {
@Override
public synchronized void disconnect(boolean askForReconnect) {
if (isConnected()) {
logger.info("DISCONNECT (still connected)");
logger.info("Disconnecting...");
sessionState = SessionState.DISCONNECTING;
}
if (connection == null || sessionState == SessionState.DISCONNECTED) {
@ -471,18 +515,20 @@ public class SessionImpl implements Session {
}
try {
callbackClient.removeListener(callbackHandler);
callbackClient.disconnect();
if (callbackClient.isConnected()) {
callbackClient.removeListener(callbackHandler);
callbackClient.disconnect();
}
TransporterClient.destroyTransporterClient(server);
} catch (Throwable ex) {
logger.fatal("Error disconnecting ...", ex);
logger.fatal("Disconnecting FAIL", ex);
}
if (sessionState == SessionState.DISCONNECTING || sessionState == SessionState.CONNECTING) {
sessionState = SessionState.DISCONNECTED;
logger.info("Disconnected ... ");
logger.info("Disconnecting DONE");
if (askForReconnect) {
client.showError("Network error. You have been disconnected from " + connection.getHost());
client.showError("Network error. You have been disconnected from " + connection.getHost());
}
client.disconnected(askForReconnect); // MageFrame with check to reconnect
pingTime.clear();
@ -491,7 +537,6 @@ public class SessionImpl implements Session {
@Override
public synchronized void reconnect(Throwable throwable) {
logger.info("RECONNECT - Connected: " + isConnected());
client.disconnected(true);
}
@ -522,7 +567,7 @@ public class SessionImpl implements Session {
@Override
public void handleConnectionException(Throwable throwable, Client client) {
logger.info("connection to server lost - " + throwable.getMessage(), throwable);
logger.info("Connect: lost connection to server.", throwable);
reconnect(throwable);
}
}
@ -1538,14 +1583,24 @@ public class SessionImpl implements Session {
}
private void handleThrowable(Throwable t) {
logger.fatal("Communication error", t);
// ignore interrupted exceptions -- it's connection problem or user's close
if (t instanceof InterruptedException) {
logger.error("Was interrupted", new Throwable());
//logger.error("Connection error: was interrupted", t);
Thread.currentThread().interrupt();
return;
}
// Probably this can cause hanging the client under certain circumstances as the disconnect method is synchronized
// so check if it's needed
// disconnect(true);
if (t instanceof RuntimeException) {
RuntimeException re = (RuntimeException) t;
if (t.getCause() instanceof InterruptedException) {
//logger.error("Connection error: was interrupted by runtime exception", t.getCause());
Thread.currentThread().interrupt();
return;
}
}
logger.fatal("Connection error: other", t);
}
private void handleMageException(MageException ex) {
@ -1592,7 +1647,7 @@ public class SessionImpl implements Session {
@Override
public boolean ping() {
try {
if (isConnected()) {
if (isConnected() && sessionId != null) {
long startTime = System.nanoTime();
if (!server.ping(sessionId, pingInfo)) {
logger.error("Ping failed: " + this.getUserName() + " Session: " + sessionId + " to MAGE server at " + connection.getHost() + ':' + connection.getPort());

View file

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

View file

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

View file

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

View file

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

View file

@ -174,7 +174,7 @@ public class ConsoleFrame extends javax.swing.JFrame implements MageClient {
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
public static void main(String[] args) {
logger.info("Starting MAGE server console version " + version);
logger.info("Logging level: " + logger.getEffectiveLevel());
@ -210,7 +210,7 @@ public class ConsoleFrame extends javax.swing.JFrame implements MageClient {
}
@Override
public void disconnected(boolean errorCall) {
public void disconnected(boolean askToReconnect) {
if (SwingUtilities.isEventDispatchThread()) {
consolePanel1.stop();
setStatusText("Not connected");

View file

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

View file

@ -60,7 +60,7 @@ public class FreeformCommander extends Constructed {
for (Map.Entry<String, Integer> entry : counts.entrySet()) {
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey())) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,50 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.35</version>
</parent>
<artifactId>mage-game-freeformcommanderduel</artifactId>
<packaging>jar</packaging>
<name>Mage Game Freeform Commander Two Player</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mage</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
<finalName>mage-game-freeformcommanderduel</finalName>
</build>
<properties/>
</project>

View file

@ -0,0 +1,36 @@
package mage.game;
import mage.constants.MultiplayerAttackOption;
import mage.constants.RangeOfInfluence;
import mage.game.match.MatchType;
import mage.game.mulligan.Mulligan;
/**
* @author JayDi85
*/
public class FreeformCommanderDuel extends GameCommanderImpl {
public FreeformCommanderDuel(MultiplayerAttackOption attackOption, RangeOfInfluence range, Mulligan mulligan, int startLife) {
super(attackOption, range, mulligan, startLife);
}
public FreeformCommanderDuel(final FreeformCommanderDuel game) {
super(game);
}
@Override
public MatchType getGameType() {
return new FreeformCommanderDuelType();
}
@Override
public int getNumPlayers() {
return 2;
}
@Override
public FreeformCommanderDuel copy() {
return new FreeformCommanderDuel(this);
}
}

View file

@ -0,0 +1,31 @@
package mage.game;
import mage.game.match.MatchImpl;
import mage.game.match.MatchOptions;
import mage.game.mulligan.Mulligan;
/**
* @author JayDi85
*/
public class FreeformCommanderDuelMatch extends MatchImpl {
public FreeformCommanderDuelMatch(MatchOptions options) {
super(options);
}
@Override
public void startGame() throws GameException {
int startLife = 20;
boolean alsoHand = true;
boolean checkCommanderDamage = true;
Mulligan mulligan = options.getMulliganType().getMulligan(options.getFreeMulligans());
FreeformCommanderDuel game = new FreeformCommanderDuel(options.getAttackOption(), options.getRange(), mulligan, startLife);
game.setCheckCommanderDamage(checkCommanderDamage);
game.setStartMessage(this.createGameStartMessage());
game.setAlsoHand(alsoHand);
game.setAlsoLibrary(true);
initGame(game);
games.add(game);
}
}

View file

@ -0,0 +1,29 @@
package mage.game;
import mage.game.match.MatchType;
/**
* @author JayDi85
*/
public class FreeformCommanderDuelType extends MatchType {
public FreeformCommanderDuelType() {
this.name = "Freeform Commander Two Player Duel";
this.maxPlayers = 2;
this.minPlayers = 2;
this.numTeams = 0;
this.useAttackOption = false;
this.useRange = false;
this.sideboardingAllowed = false;
}
protected FreeformCommanderDuelType(final FreeformCommanderDuelType matchType) {
super(matchType);
}
@Override
public FreeformCommanderDuelType copy() {
return new FreeformCommanderDuelType(this);
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -150,6 +150,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (target.getOriginalTarget() instanceof TargetPlayer) {
return setTargetPlayer(outcome, target, null, sourceId, abilityControllerId, randomOpponentId, game);
}
if (target.getOriginalTarget() instanceof TargetDiscard) {
findPlayables(game);
if (!unplayable.isEmpty()) {
@ -174,38 +175,43 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return false;
}
if (target.getOriginalTarget() instanceof TargetControlledPermanent) {
List<Permanent> targets;
targets = threats(abilityControllerId, sourceId, ((TargetControlledPermanent) target).getFilter(), game, target.getTargets());
TargetControlledPermanent origTarget = (TargetControlledPermanent) target.getOriginalTarget();
targets = threats(abilityControllerId, sourceId, origTarget.getFilter(), game, target.getTargets());
if (!outcome.isGood()) {
Collections.reverse(targets);
}
for (Permanent permanent : targets) {
if (((TargetControlledPermanent) target).canTarget(abilityControllerId, permanent.getId(), sourceId, game, false) && !target.getTargets().contains(permanent.getId())) {
if (origTarget.canTarget(abilityControllerId, permanent.getId(), sourceId, game, false) && !target.getTargets().contains(permanent.getId())) {
target.add(permanent.getId(), game);
return true;
}
}
return false;
}
if (target.getOriginalTarget() instanceof TargetPermanent) {
TargetPermanent origTarget = (TargetPermanent) target.getOriginalTarget();
List<Permanent> targets;
if (outcome.isCanTargetAll()) {
targets = threats(null, sourceId, ((TargetPermanent) target).getFilter(), game, target.getTargets());
targets = threats(null, sourceId, origTarget.getFilter(), game, target.getTargets());
} else {
if (outcome.isGood()) {
targets = threats(abilityControllerId, sourceId, ((TargetPermanent) target).getFilter(), game, target.getTargets());
targets = threats(abilityControllerId, sourceId, origTarget.getFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, sourceId, ((TargetPermanent) target).getFilter(), game, target.getTargets());
targets = threats(randomOpponentId, sourceId, origTarget.getFilter(), game, target.getTargets());
}
if (targets.isEmpty() && target.isRequired()) {
if (!outcome.isGood()) {
targets = threats(abilityControllerId, sourceId, ((TargetPermanent) target).getFilter(), game, target.getTargets());
targets = threats(abilityControllerId, sourceId, origTarget.getFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, sourceId, ((TargetPermanent) target).getFilter(), game, target.getTargets());
targets = threats(randomOpponentId, sourceId, origTarget.getFilter(), game, target.getTargets());
}
}
}
for (Permanent permanent : targets) {
if (target.canTarget(abilityControllerId, permanent.getId(), null, game) && !target.getTargets().contains(permanent.getId())) {
// stop to add targets if not needed and outcome is no advantage for AI player
@ -246,17 +252,18 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return target.isChosen();
}
if (target.getOriginalTarget() instanceof TargetAnyTarget) {
List<Permanent> targets;
TargetAnyTarget t = ((TargetAnyTarget) target);
TargetAnyTarget origTarget = (TargetAnyTarget) target.getOriginalTarget();
if (outcome.isGood()) {
targets = threats(abilityControllerId, sourceId, ((FilterCreaturePlayerOrPlaneswalker) t.getFilter()).getCreatureFilter(), game, target.getTargets());
targets = threats(abilityControllerId, sourceId, ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, sourceId, ((FilterCreaturePlayerOrPlaneswalker) t.getFilter()).getCreatureFilter(), game, target.getTargets());
targets = threats(randomOpponentId, sourceId, ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
}
for (Permanent permanent : targets) {
List<UUID> alreadyTargetted = target.getTargets();
if (t.canTarget(abilityControllerId, permanent.getId(), null, game)) {
if (target.canTarget(abilityControllerId, permanent.getId(), null, game)) {
if (alreadyTargetted != null && !alreadyTargetted.contains(permanent.getId())) {
target.add(permanent.getId(), game);
return true;
@ -276,17 +283,18 @@ public class ComputerPlayer extends PlayerImpl implements Player {
return false;
}
}
if (target.getOriginalTarget() instanceof TargetCreatureOrPlayer) {
List<Permanent> targets;
TargetCreatureOrPlayer t = ((TargetCreatureOrPlayer) target);
TargetCreatureOrPlayer origTarget = (TargetCreatureOrPlayer) target.getOriginalTarget();
if (outcome.isGood()) {
targets = threats(abilityControllerId, sourceId, ((FilterCreatureOrPlayer) t.getFilter()).getCreatureFilter(), game, target.getTargets());
targets = threats(abilityControllerId, sourceId, ((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, sourceId, ((FilterCreatureOrPlayer) t.getFilter()).getCreatureFilter(), game, target.getTargets());
targets = threats(randomOpponentId, sourceId, ((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
}
for (Permanent permanent : targets) {
List<UUID> alreadyTargeted = target.getTargets();
if (t.canTarget(abilityControllerId, permanent.getId(), null, game)) {
if (target.canTarget(abilityControllerId, permanent.getId(), null, game)) {
if (alreadyTargeted != null && !alreadyTargeted.contains(permanent.getId())) {
target.add(permanent.getId(), game);
return true;
@ -309,9 +317,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (target.getOriginalTarget() instanceof TargetPermanentOrPlayer) {
List<Permanent> targets;
TargetPermanentOrPlayer t = ((TargetPermanentOrPlayer) target);
List<Permanent> ownedTargets = threats(abilityControllerId, sourceId, ((FilterPermanentOrPlayer) t.getFilter()).getPermanentFilter(), game, target.getTargets());
List<Permanent> opponentTargets = threats(randomOpponentId, sourceId, ((FilterPermanentOrPlayer) t.getFilter()).getPermanentFilter(), game, target.getTargets());
TargetPermanentOrPlayer origTarget = (TargetPermanentOrPlayer) target.getOriginalTarget();
List<Permanent> ownedTargets = threats(abilityControllerId, sourceId, ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
List<Permanent> opponentTargets = threats(randomOpponentId, sourceId, ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
if (outcome.isGood()) {
targets = ownedTargets;
} else {
@ -319,7 +327,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
for (Permanent permanent : targets) {
List<UUID> alreadyTargeted = target.getTargets();
if (t.canTarget(permanent.getId(), game)) {
if (target.canTarget(permanent.getId(), game)) {
if (alreadyTargeted != null && !alreadyTargeted.contains(permanent.getId())) {
target.add(permanent.getId(), game);
return true;
@ -353,7 +361,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
for (Permanent permanent : targets) {
List<UUID> alreadyTargeted = target.getTargets();
if (t.canTarget(permanent.getId(), game)) {
if (target.canTarget(permanent.getId(), game)) {
if (alreadyTargeted != null && !alreadyTargeted.contains(permanent.getId())) {
target.add(permanent.getId(), game);
return true;
@ -362,6 +370,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return false;
}
if (target.getOriginalTarget() instanceof TargetCardInGraveyard) {
List<Card> cards = new ArrayList<>();
for (Player player : game.getPlayers().values()) {
@ -395,15 +404,15 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return false;
}
if (target.getOriginalTarget() instanceof TargetSource) {
Set<UUID> targets;
TargetSource t = ((TargetSource) target);
targets = t.possibleTargets(sourceId, abilityControllerId, game);
targets = target.possibleTargets(sourceId, abilityControllerId, game);
for (UUID targetId : targets) {
MageObject targetObject = game.getObject(targetId);
if (targetObject != null) {
List<UUID> alreadyTargeted = target.getTargets();
if (t.canTarget(targetObject.getId(), game)) {
if (target.canTarget(targetObject.getId(), game)) {
if (alreadyTargeted != null && !alreadyTargeted.contains(targetObject.getId())) {
target.add(targetObject.getId(), game);
return true;
@ -444,8 +453,10 @@ public class ComputerPlayer extends PlayerImpl implements Player {
return setTargetPlayer(outcome, target, source, source.getSourceId(), abilityControllerId, randomOpponentId, game);
}
if (target.getOriginalTarget() instanceof TargetDiscard || target.getOriginalTarget() instanceof TargetCardInHand) {
if (target.getOriginalTarget() instanceof TargetDiscard
|| target.getOriginalTarget() instanceof TargetCardInHand) {
if (outcome.isGood()) {
// good
Cards cards = new CardsImpl(target.possibleTargets(source.getSourceId(), getId(), game));
ArrayList<Card> cardsInHand = new ArrayList<>(cards.getCards(game));
while (!target.isChosen()
@ -463,6 +474,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
}
} else {
// bad
findPlayables(game);
if (!unplayable.isEmpty()) {
for (int i = unplayable.size() - 1; i >= 0; i--) {
@ -487,9 +499,11 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return false;
}
if (target.getOriginalTarget() instanceof TargetControlledPermanent) {
TargetControlledPermanent origTarget = (TargetControlledPermanent) target.getOriginalTarget();
List<Permanent> targets;
targets = threats(abilityControllerId, source.getSourceId(), ((TargetControlledPermanent) target).getFilter(), game, target.getTargets());
targets = threats(abilityControllerId, source.getSourceId(), origTarget.getFilter(), game, target.getTargets());
if (!outcome.isGood()) {
Collections.reverse(targets);
}
@ -504,9 +518,10 @@ public class ComputerPlayer extends PlayerImpl implements Player {
return target.isChosen();
}
if (target.getOriginalTarget() instanceof TargetPermanent) {
List<Permanent> targets;
TargetPermanent t = (TargetPermanent) target.getOriginalTarget();
TargetPermanent origTarget = (TargetPermanent) target.getOriginalTarget();
boolean outcomeTargets = true;
if (outcome.isGood()) {
targets = threats(abilityControllerId, source == null ? null : source.getSourceId(), ((TargetPermanent) target).getFilter(), game, target.getTargets());
@ -520,7 +535,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
//targets = game.getBattlefield().getActivePermanents(((TargetPermanent)target).getFilter(), playerId, game);
}
if (targets.isEmpty() && target.isRequired()) {
targets = game.getBattlefield().getActivePermanents(t.getFilter(), playerId, game);
targets = game.getBattlefield().getActivePermanents(origTarget.getFilter(), playerId, game);
}
for (Permanent permanent : targets) {
if (target.canTarget(abilityControllerId, permanent.getId(), source, game)) {
@ -532,13 +547,14 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return target.isChosen();
}
if (target.getOriginalTarget() instanceof TargetCreatureOrPlayer) {
List<Permanent> targets;
TargetCreatureOrPlayer t = ((TargetCreatureOrPlayer) target);
TargetCreatureOrPlayer origTarget = ((TargetCreatureOrPlayer) target);
if (outcome.isGood()) {
targets = threats(abilityControllerId, source.getSourceId(), ((FilterCreatureOrPlayer) t.getFilter()).getCreatureFilter(), game, target.getTargets());
targets = threats(abilityControllerId, source.getSourceId(), ((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, source.getSourceId(), ((FilterCreatureOrPlayer) t.getFilter()).getCreatureFilter(), game, target.getTargets());
targets = threats(randomOpponentId, source.getSourceId(), ((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
}
if (targets.isEmpty()) {
@ -552,11 +568,11 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
if (targets.isEmpty() && target.isRequired(source)) {
targets = game.getBattlefield().getActivePermanents(((FilterCreatureOrPlayer) t.getFilter()).getCreatureFilter(), playerId, game);
targets = game.getBattlefield().getActivePermanents(((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), playerId, game);
}
for (Permanent permanent : targets) {
List<UUID> alreadyTargeted = target.getTargets();
if (t.canTarget(abilityControllerId, permanent.getId(), source, game)) {
if (target.canTarget(abilityControllerId, permanent.getId(), source, game)) {
if (alreadyTargeted != null && !alreadyTargeted.contains(permanent.getId())) {
return tryAddTarget(target, permanent.getId(), source, game);
}
@ -574,13 +590,14 @@ public class ComputerPlayer extends PlayerImpl implements Player {
//if (!target.isRequired())
return false;
}
if (target.getOriginalTarget() instanceof TargetAnyTarget) {
List<Permanent> targets;
TargetAnyTarget t = ((TargetAnyTarget) target);
TargetAnyTarget origTarget = ((TargetAnyTarget) target);
if (outcome.isGood()) {
targets = threats(abilityControllerId, source.getSourceId(), ((FilterCreaturePlayerOrPlaneswalker) t.getFilter()).getCreatureFilter(), game, target.getTargets());
targets = threats(abilityControllerId, source.getSourceId(), ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, source.getSourceId(), ((FilterCreaturePlayerOrPlaneswalker) t.getFilter()).getCreatureFilter(), game, target.getTargets());
targets = threats(randomOpponentId, source.getSourceId(), ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
}
if (targets.isEmpty()) {
@ -594,11 +611,11 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
if (targets.isEmpty() && target.isRequired(source)) {
targets = game.getBattlefield().getActivePermanents(((FilterCreaturePlayerOrPlaneswalker) t.getFilter()).getCreatureFilter(), playerId, game);
targets = game.getBattlefield().getActivePermanents(((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getCreatureFilter(), playerId, game);
}
for (Permanent permanent : targets) {
List<UUID> alreadyTargeted = target.getTargets();
if (t.canTarget(abilityControllerId, permanent.getId(), source, game)) {
if (target.canTarget(abilityControllerId, permanent.getId(), source, game)) {
if (alreadyTargeted != null && !alreadyTargeted.contains(permanent.getId())) {
tryAddTarget(target, permanent.getId(), source, game);
}
@ -616,13 +633,14 @@ public class ComputerPlayer extends PlayerImpl implements Player {
//if (!target.isRequired())
return false;
}
if (target.getOriginalTarget() instanceof TargetPermanentOrPlayer) {
List<Permanent> targets;
TargetPermanentOrPlayer t = ((TargetPermanentOrPlayer) target);
TargetPermanentOrPlayer origTarget = ((TargetPermanentOrPlayer) target);
if (outcome.isGood()) {
targets = threats(abilityControllerId, source.getSourceId(), ((FilterPermanentOrPlayer) t.getFilter()).getPermanentFilter(), game, target.getTargets());
targets = threats(abilityControllerId, source.getSourceId(), ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, source.getSourceId(), ((FilterPermanentOrPlayer) t.getFilter()).getPermanentFilter(), game, target.getTargets());
targets = threats(randomOpponentId, source.getSourceId(), ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
}
if (targets.isEmpty()) {
@ -636,11 +654,11 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
if (targets.isEmpty() && target.isRequired(source)) {
targets = game.getBattlefield().getActivePermanents(((FilterPermanentOrPlayer) t.getFilter()).getPermanentFilter(), playerId, game);
targets = game.getBattlefield().getActivePermanents(((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), playerId, game);
}
for (Permanent permanent : targets) {
List<UUID> alreadyTargeted = target.getTargets();
if (t.canTarget(abilityControllerId, permanent.getId(), source, game)) {
if (target.canTarget(abilityControllerId, permanent.getId(), source, game)) {
if (alreadyTargeted != null && !alreadyTargeted.contains(permanent.getId())) {
return tryAddTarget(target, permanent.getId(), source, game);
}
@ -650,13 +668,27 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (target.getOriginalTarget() instanceof TargetPlayerOrPlaneswalker) {
List<Permanent> targets;
TargetPlayerOrPlaneswalker t = ((TargetPlayerOrPlaneswalker) target);
TargetPlayerOrPlaneswalker origTarget = ((TargetPlayerOrPlaneswalker) target);
// TODO: if effect is bad and no opponent's targets available then AI can't target yourself but must by rules
/*
battlefield:Computer:Mountain:5
hand:Computer:Viashino Pyromancer:3
battlefield:Human:Shalai, Voice of Plenty:1
*/
// TODO: in multiplayer game there many opponents - if random opponents don't have targets then AI must use next opponent, but it skips
// (e.g. you randomOpponentId must be replaced by List<UUID> randomOpponents)
// normal cycle (good for you, bad for opponents)
// possible good/bad permanents
if (outcome.isGood()) {
targets = threats(abilityControllerId, source.getSourceId(), ((FilterPermanentOrPlayer) t.getFilter()).getPermanentFilter(), game, target.getTargets());
targets = threats(abilityControllerId, source.getSourceId(), ((FilterPermanentOrPlayer) target.getFilter()).getPermanentFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, source.getSourceId(), ((FilterPermanentOrPlayer) t.getFilter()).getPermanentFilter(), game, target.getTargets());
targets = threats(randomOpponentId, source.getSourceId(), ((FilterPermanentOrPlayer) target.getFilter()).getPermanentFilter(), game, target.getTargets());
}
// possible good/bad players
if (targets.isEmpty()) {
if (outcome.isGood()) {
if (target.canTarget(getId(), abilityControllerId, source, game)) {
@ -667,18 +699,22 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
}
// can't find targets (e.g. effect is bad, but you need take targets from yourself)
if (targets.isEmpty() && target.isRequired(source)) {
targets = game.getBattlefield().getActivePermanents(((TargetPlayerOrPlaneswalker) t.getFilter()).getFilterPermanent(), playerId, game);
targets = game.getBattlefield().getActivePermanents(origTarget.getFilterPermanent(), playerId, game);
}
// try target permanent
for (Permanent permanent : targets) {
List<UUID> alreadyTargeted = target.getTargets();
if (t.canTarget(abilityControllerId, permanent.getId(), source, game)) {
if (target.canTarget(abilityControllerId, permanent.getId(), source, game)) {
if (alreadyTargeted != null && !alreadyTargeted.contains(permanent.getId())) {
return tryAddTarget(target, permanent.getId(), source, game);
}
}
}
// try target player as normal
if (outcome.isGood()) {
if (target.canTarget(getId(), abilityControllerId, source, game)) {
return tryAddTarget(target, abilityControllerId, source, game);
@ -703,6 +739,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
//if (!target.isRequired())
return false;
}
if (target.getOriginalTarget() instanceof TargetCardInLibrary) {
List<Card> cards = new ArrayList<>(game.getPlayer(abilityControllerId).getLibrary().getCards(game));
Card card = pickTarget(cards, outcome, target, source, game);
@ -711,6 +748,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return false;
}
if (target.getOriginalTarget() instanceof TargetCardInYourGraveyard) {
List<Card> cards = new ArrayList<>(game.getPlayer(abilityControllerId).getGraveyard().getCards((FilterCard) target.getFilter(), game));
while (!target.isChosen() && !cards.isEmpty()) {
@ -722,6 +760,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return target.isChosen();
}
if (target.getOriginalTarget() instanceof TargetSpell) {
if (!game.getStack().isEmpty()) {
for (StackObject o : game.getStack()) {
@ -732,17 +771,19 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return false;
}
if (target.getOriginalTarget() instanceof TargetSpellOrPermanent) {
// TODO: Also check if a spell should be selected
TargetSpellOrPermanent origTarget = (TargetSpellOrPermanent) target.getOriginalTarget();
List<Permanent> targets;
boolean outcomeTargets = true;
if (outcome.isGood()) {
targets = threats(abilityControllerId, source == null ? null : source.getSourceId(), ((TargetSpellOrPermanent) target).getPermanentFilter(), game, target.getTargets());
targets = threats(abilityControllerId, source == null ? null : source.getSourceId(), origTarget.getPermanentFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, source == null ? null : source.getSourceId(), ((TargetSpellOrPermanent) target).getPermanentFilter(), game, target.getTargets());
targets = threats(randomOpponentId, source == null ? null : source.getSourceId(), origTarget.getPermanentFilter(), game, target.getTargets());
}
if (targets.isEmpty() && target.isRequired(source)) {
targets = threats(null, source == null ? null : source.getSourceId(), ((TargetSpellOrPermanent) target).getPermanentFilter(), game, target.getTargets());
targets = threats(null, source == null ? null : source.getSourceId(), origTarget.getPermanentFilter(), game, target.getTargets());
Collections.reverse(targets);
outcomeTargets = false;
}
@ -765,6 +806,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return false;
}
if (target.getOriginalTarget() instanceof TargetCardInOpponentsGraveyard) {
List<Card> cards = new ArrayList<>();
for (UUID uuid : game.getOpponents(abilityControllerId)) {
@ -780,6 +822,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
//if (!target.isRequired())
return false;
}
if (target.getOriginalTarget() instanceof TargetDefender) {
// TODO: Improve, now planeswalker is always chosen if it exits
List<Permanent> targets;
@ -834,6 +877,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return target.isChosen();
}
if (target.getOriginalTarget() instanceof TargetActivatedAbility) {
List<StackObject> stackObjects = new ArrayList<>();
for (UUID uuid : target.possibleTargets(source.getSourceId(), source.getControllerId(), game)) {
@ -924,6 +968,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
return false;
}
if (target.getOriginalTarget() instanceof TargetCreatureOrPlaneswalkerAmount) {
List<Permanent> targets;
if (outcome.isGood()) {
@ -965,6 +1010,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
}
}
log.warn("No proper AI target handling: " + target.getClass().getName());
return false;
}

View file

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

View file

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

View file

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

View file

@ -934,24 +934,27 @@ public class HumanPlayer extends PlayerImpl {
if (object != null) {
Zone zone = game.getState().getZone(object.getId());
if (zone != null) {
// look at card or try to cast/activate abilities
Player actingPlayer = null;
LinkedHashMap<UUID, ActivatedAbility> useableAbilities = null;
if (playerId.equals(game.getPriorityPlayerId())) {
actingPlayer = this;
} else if (getPlayersUnderYourControl().contains(game.getPriorityPlayerId())) {
actingPlayer = game.getPlayer(game.getPriorityPlayerId());
}
if (actingPlayer != null) {
useableAbilities = actingPlayer.getUseableActivatedAbilities(object, zone, game);
}
if (object instanceof Card
&& ((Card) object).isFaceDown(game)
&& lookAtFaceDownCard((Card) object, game)) {
&& lookAtFaceDownCard((Card) object, game, useableAbilities == null ? 0 : useableAbilities.size())) {
result = true;
} else {
Player actingPlayer = null;
if (playerId.equals(game.getPriorityPlayerId())) {
actingPlayer = this;
} else if (getPlayersUnderYourControl().contains(game.getPriorityPlayerId())) {
actingPlayer = game.getPlayer(game.getPriorityPlayerId());
}
if (actingPlayer != null) {
LinkedHashMap<UUID, ActivatedAbility> useableAbilities = actingPlayer.getUseableActivatedAbilities(object, zone, game);
if (useableAbilities != null
&& !useableAbilities.isEmpty()) {
activateAbility(useableAbilities, object, game);
result = true;
}
if (useableAbilities != null
&& !useableAbilities.isEmpty()) {
activateAbility(useableAbilities, object, game);
result = true;
}
}
}

View file

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

View file

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

View file

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

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.34</version>
<version>1.4.35</version>
</parent>
<artifactId>mage-server-plugins</artifactId>
@ -25,8 +25,9 @@
<module>Mage.Game.TinyLeadersDuel</module>
<module>Mage.Game.CanadianHighlanderDuel</module>
<module>Mage.Game.PennyDreadfulCommanderFreeForAll</module>
<module>Mage.Game.FreeformCommanderFreeForAll</module>
<module>Mage.Game.BrawlDuel</module>
<module>Mage.Game.FreeformCommanderDuel</module>
<module>Mage.Game.FreeformCommanderFreeForAll</module>
<module>Mage.Game.BrawlDuel</module>
<module>Mage.Game.BrawlFreeForAll</module>
<module>Mage.Game.TwoPlayerDuel</module>
<module>Mage.Player.AI</module>

View file

@ -79,6 +79,7 @@
<gameType name="Tiny Leaders Two Player Duel" jar="mage-game-tinyleadersduel.jar" className="mage.game.TinyLeadersDuelMatch" typeName="mage.game.TinyLeadersDuelType"/>
<gameType name="Canadian Highlander Two Player Duel" jar="mage-game-canadianhighlanderduel.jar" className="mage.game.CanadianHighlanderDuelMatch" typeName="mage.game.CanadianHighlanderDuelType"/>
<gameType name="Penny Dreadful Commander Free For All" jar="mage-game-pennydreadfulcommanderfreeforall.jar" className="mage.game.PennyDreadfulCommanderFreeForAllMatch" typeName="mage.game.PennyDreadfulCommanderFreeForAllType"/>
<gameType name="Freeform Commander Two Player Duel" jar="mage-game-freeformcommanderduel.jar" className="mage.game.FreeformCommanderDuelMatch" typeName="mage.game.FreeformCommanderDuelType"/>
<gameType name="Freeform Commander Free For All" jar="mage-game-freeformcommanderfreeforall.jar" className="mage.game.FreeformCommanderFreeForAllMatch" typeName="mage.game.FreeformCommanderFreeForAllType"/>
<gameType name="Brawl Two Player Duel" jar="mage-game-brawlduel.jar" className="mage.game.BrawlDuelMatch" typeName="mage.game.BrawlDuelType"/>
<gameType name="Brawl Free For All" jar="mage-game-brawlfreeforall.jar" className="mage.game.BrawlFreeForAllMatch" typeName="mage.game.BrawlFreeForAllType"/>

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.34</version>
<version>1.4.35</version>
</parent>
<artifactId>mage-server</artifactId>
@ -184,6 +184,12 @@
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mage-game-freeformcommanderduel</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>

View file

@ -73,6 +73,7 @@
<gameType name="Tiny Leaders Two Player Duel" jar="mage-game-tinyleadersduel-${project.version}.jar" className="mage.game.TinyLeadersDuelMatch" typeName="mage.game.TinyLeadersDuelType"/>
<gameType name="Canadian Highlander Two Player Duel" jar="mage-game-canadianhighlanderduel-${project.version}.jar" className="mage.game.CanadianHighlanderDuelMatch" typeName="mage.game.CanadianHighlanderDuelType"/>
<gameType name="Penny Dreadful Commander Free For All" jar="mage-game-pennydreadfulcommanderfreeforall-${project.version}.jar" className="mage.game.PennyDreadfulCommanderFreeForAllMatch" typeName="mage.game.PennyDreadfulCommanderFreeForAllType"/>
<gameType name="Freeform Commander Two Player Duel" jar="mage-game-freeformcommanderduel-${project.version}.jar" className="mage.game.FreeformCommanderDuelMatch" typeName="mage.game.FreeformCommanderDuelType"/>
<gameType name="Freeform Commander Free For All" jar="mage-game-freeformcommanderfreeforall-${project.version}.jar" className="mage.game.FreeformCommanderFreeForAllMatch" typeName="mage.game.FreeformCommanderFreeForAllType"/>
<gameType name="Brawl Two Player Duel" jar="mage-game-brawlduel-${project.version}.jar" className="mage.game.BrawlDuelMatch" typeName="mage.game.BrawlDuelType"/>
<gameType name="Brawl Free For All" jar="mage-game-brawlfreeforall-${project.version}.jar" className="mage.game.BrawlFreeForAllMatch" typeName="mage.game.BrawlFreeForAllType"/>

View file

@ -1,11 +1,5 @@
package mage.server;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import mage.server.User.UserState;
import mage.server.record.UserStats;
import mage.server.record.UserStatsRepository;
@ -13,6 +7,12 @@ import mage.server.util.ThreadExecutor;
import mage.view.UserView;
import org.apache.log4j.Logger;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* manages users - if a user is disconnected and 10 minutes have passed with no
* activity the user is removed
@ -22,6 +22,9 @@ import org.apache.log4j.Logger;
public enum UserManager {
instance;
private static final int SERVER_TIMEOUTS_USER_DISCONNECT_FROM_SERVER_AFTER_SECS = 3 * 60; // removes from all games and chats too (can be seen in users list with disconnected status)
private static final int SERVER_TIMEOUTS_USER_REMOVE_FROM_SERVER_AFTER_SECS = 8 * 60; // removes from users list
private static final Logger logger = Logger.getLogger(UserManager.class);
protected final ScheduledExecutorService expireExecutor = Executors.newSingleThreadScheduledExecutor();
@ -58,7 +61,7 @@ public enum UserManager {
public Optional<User> getUser(UUID userId) {
if (!users.containsKey(userId)) {
logger.warn(String.format("User with id %s could not be found", userId), new Throwable()); // TODO: remove after session freezes fixed
//logger.warn(String.format("User with id %s could not be found", userId), new Throwable()); // TODO: remove after session freezes fixed
return Optional.empty();
} else {
return Optional.of(users.get(userId));
@ -127,17 +130,17 @@ public enum UserManager {
if (userId != null) {
getUser(userId).ifPresent(user
-> USER_EXECUTOR.execute(
() -> {
try {
logger.info("USER REMOVE - " + user.getName() + " (" + reason.toString() + ") userId: " + userId + " [" + user.getGameInfo() + ']');
user.removeUserFromAllTables(reason);
ChatManager.instance.removeUser(user.getId(), reason);
logger.debug("USER REMOVE END - " + user.getName());
} catch (Exception ex) {
handleException(ex);
}
}
));
() -> {
try {
logger.info("USER REMOVE - " + user.getName() + " (" + reason.toString() + ") userId: " + userId + " [" + user.getGameInfo() + ']');
user.removeUserFromAllTables(reason);
ChatManager.instance.removeUser(user.getId(), reason);
logger.debug("USER REMOVE END - " + user.getName());
} catch (Exception ex) {
handleException(ex);
}
}
));
}
}
@ -155,16 +158,15 @@ public enum UserManager {
/**
* Is the connection lost for more than 3 minutes, the user will be set to
* offline status. The user will be removed in validity check after 15
* offline status. The user will be removed in validity check after 8
* minutes of no activities
*
*/
private void checkExpired() {
try {
Calendar calendarExp = Calendar.getInstance();
calendarExp.add(Calendar.MINUTE, -3);
calendarExp.add(Calendar.SECOND, -1 * SERVER_TIMEOUTS_USER_DISCONNECT_FROM_SERVER_AFTER_SECS);
Calendar calendarRemove = Calendar.getInstance();
calendarRemove.add(Calendar.MINUTE, -8);
calendarRemove.add(Calendar.SECOND, -1 * SERVER_TIMEOUTS_USER_REMOVE_FROM_SERVER_AFTER_SECS);
List<User> toRemove = new ArrayList<>();
logger.debug("Start Check Expired");
ArrayList<User> userList = new ArrayList<>();
@ -179,18 +181,18 @@ public enum UserManager {
try {
if (user.getUserState() == UserState.Offline) {
if (user.isExpired(calendarRemove.getTime())) {
// removes from users list
toRemove.add(user);
}
} else {
if (user.isExpired(calendarExp.getTime())) {
// set disconnected status and removes from all activities (tourney/tables/games/drafts/chats)
if (user.getUserState() == UserState.Connected) {
user.lostConnection();
disconnect(user.getId(), DisconnectReason.BecameInactive);
}
removeUserFromAllTablesAndChat(user.getId(), DisconnectReason.SessionExpired);
user.setUserState(UserState.Offline);
// Remove the user from all tournaments
}
}
} catch (Exception ex) {
@ -215,7 +217,6 @@ public enum UserManager {
/**
* This method recreated the user list that will be send to all clients
*
*/
private void updateUserInfoList() {
try {

View file

@ -49,6 +49,9 @@ import java.util.zip.GZIPOutputStream;
*/
public class GameController implements GameCallback {
private static final int GAME_TIMEOUTS_CHECK_JOINING_STATUS_EVERY_SECS = 15; // checks and inform players about joining status
private static final int GAME_TIMEOUTS_CANCEL_PLAYER_GAME_JOINING_AFTER_INACTIVE_SECS = 4 * 60; // leave player from game if it don't join and inactive on server
private static final ExecutorService gameExecutor = ThreadExecutor.instance.getGameExecutor();
private static final Logger logger = Logger.getLogger(GameController.class);
@ -226,7 +229,7 @@ public class GameController implements GameCallback {
} catch (Exception ex) {
logger.fatal("Send info about player not joined yet:", ex);
}
}, 15, 15, TimeUnit.SECONDS);
}, GAME_TIMEOUTS_CHECK_JOINING_STATUS_EVERY_SECS, GAME_TIMEOUTS_CHECK_JOINING_STATUS_EVERY_SECS, TimeUnit.SECONDS);
checkStart();
}
@ -320,6 +323,7 @@ public class GameController implements GameCallback {
}
private void sendInfoAboutPlayersNotJoinedYet() {
// runs every 15 secs untill all players join
for (Player player : game.getPlayers().values()) {
if (!player.hasLeft() && player.isHuman()) {
Optional<User> requestedUser = getUserByPlayerId(player.getId());
@ -333,12 +337,12 @@ public class GameController implements GameCallback {
logger.debug("Player " + player.getName() + " (disconnected) has joined gameId: " + game.getId());
}
ChatManager.instance.broadcast(chatId, player.getName(), user.getPingInfo() + " is pending to join the game", MessageColor.BLUE, true, ChatMessage.MessageType.STATUS, null);
if (user.getSecondsDisconnected() > 240) {
if (user.getSecondsDisconnected() > GAME_TIMEOUTS_CANCEL_PLAYER_GAME_JOINING_AFTER_INACTIVE_SECS) {
// TODO: 2019.04.22 - if user playing another game on server but not joining (that's the reason?), then that's check will never trigger
// Cancel player join possibility lately after 4 minutes
logger.debug("Player " + player.getName() + " - canceled game (after 240 seconds) gameId: " + game.getId());
player.leave();
}
}
} else if (!player.hasLeft()) {
logger.debug("Player " + player.getName() + " canceled game (no user) gameId: " + game.getId());

View file

@ -12,6 +12,7 @@ import mage.constants.Outcome;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.GameCommanderImpl;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.util.RandomUtil;
@ -31,7 +32,8 @@ import java.util.stream.Collectors;
*/
public final class SystemUtil {
private SystemUtil(){}
private SystemUtil() {
}
public static final DateFormat dateFormat = new SimpleDateFormat("yy-M-dd HH:mm:ss");
@ -485,6 +487,8 @@ public final class SystemUtil {
gameZone = Zone.COMMAND;
} else if ("plane".equalsIgnoreCase(command.zone)) {
gameZone = Zone.COMMAND;
} else if ("commander".equalsIgnoreCase(command.zone)) {
gameZone = Zone.COMMAND;
} else {
logger.warn("Unknown zone [" + command.zone + "]: " + line);
continue;
@ -513,8 +517,23 @@ public final class SystemUtil {
}
}
game.loadCards(cardsToLoad, player.getId());
for (Card card : cardsToLoad) {
swapWithAnyCard(game, player, card, gameZone);
if ("commander".equalsIgnoreCase(command.zone) && cardsToLoad.size() > 0) {
// as commander (only commander games, look at init code in GameCommanderImpl)
if (game instanceof GameCommanderImpl) {
GameCommanderImpl gameCommander = (GameCommanderImpl) game;
for (Card card : cardsToLoad) {
player.addCommanderId(card.getId());
gameCommander.initCommander(card, player);
}
} else {
logger.fatal("Commander card can be used in commander game only: " + command.cardName);
}
} else {
// as other card
for (Card card : cardsToLoad) {
swapWithAnyCard(game, player, card, gameZone);
}
}
}
} catch (Exception e) {

View file

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

View file

@ -81,7 +81,7 @@ class AchHansRunEffect extends OneShotEffect {
FilterCard nameFilter = new FilterCard();
nameFilter.add(new NamePredicate(cardName));
TargetCardInLibrary target = new TargetCardInLibrary(1, 1, nameFilter);
if (!controller.searchLibrary(target, game)) {
if (!controller.searchLibrary(target, source, game)) {
return false;
}
Card card = controller.getLibrary().remove(target.getFirstTarget(), game);

View file

@ -63,7 +63,7 @@ class AcquireEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
if (opponent != null && controller != null) {
TargetCardInLibrary target = new TargetCardInLibrary(filter);
controller.searchLibrary(target, game, opponent.getId());
controller.searchLibrary(target, source, game, opponent.getId());
Card targetCard = game.getCard(target.getFirstTarget());
if (targetCard != null) {
controller.moveCards(targetCard, Zone.BATTLEFIELD, source, game);

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