mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 10:48:00 +00:00
Add Net Decks support
This commit is contained in:
4
.gitattributes
vendored
4
.gitattributes
vendored
@@ -16050,6 +16050,8 @@ forge-gui/res/lists/TypeLists.txt svneol=native#text/plain
|
||||
forge-gui/res/lists/booster-images.txt svneol=native#text/plain
|
||||
forge-gui/res/lists/boosterbox-images.txt -text
|
||||
forge-gui/res/lists/fatpack-images.txt svneol=native#text/plain
|
||||
forge-gui/res/lists/net-decks-commander.txt -text
|
||||
forge-gui/res/lists/net-decks.txt -text
|
||||
forge-gui/res/lists/precon-images.txt svneol=native#text/plain
|
||||
forge-gui/res/lists/quest-opponent-icons.txt svneol=native#text/plain
|
||||
forge-gui/res/lists/quest-pet-shop-icons.txt svneol=native#text/plain
|
||||
@@ -17331,6 +17333,7 @@ forge-gui/src/main/java/forge/deck/DeckGeneratorTheme.java -text
|
||||
forge-gui/src/main/java/forge/deck/DeckProxy.java -text
|
||||
forge-gui/src/main/java/forge/deck/DeckType.java -text
|
||||
forge-gui/src/main/java/forge/deck/DeckgenUtil.java -text
|
||||
forge-gui/src/main/java/forge/deck/NetDeckCategory.java -text
|
||||
forge-gui/src/main/java/forge/deck/RandomDeckGenerator.java -text
|
||||
forge-gui/src/main/java/forge/deck/io/DeckPreferences.java -text
|
||||
forge-gui/src/main/java/forge/deck/io/OldDeckParser.java -text
|
||||
@@ -17339,6 +17342,7 @@ forge-gui/src/main/java/forge/download/GuiDownloadPrices.java -text
|
||||
forge-gui/src/main/java/forge/download/GuiDownloadQuestImages.java -text
|
||||
forge-gui/src/main/java/forge/download/GuiDownloadService.java -text
|
||||
forge-gui/src/main/java/forge/download/GuiDownloadSetPicturesLQ.java -text
|
||||
forge-gui/src/main/java/forge/download/GuiDownloadZipService.java -text
|
||||
forge-gui/src/main/java/forge/error/BugReporter.java -text
|
||||
forge-gui/src/main/java/forge/error/ExceptionHandler.java svneol=native#text/plain
|
||||
forge-gui/src/main/java/forge/error/package-info.java svneol=native#text/plain
|
||||
|
||||
@@ -23,6 +23,8 @@ import forge.assets.FSkinProp;
|
||||
import forge.assets.ISkinImage;
|
||||
import forge.control.GuiTimer;
|
||||
import forge.deck.CardPool;
|
||||
import forge.download.GuiDownloadService;
|
||||
import forge.download.GuiDownloader;
|
||||
import forge.error.BugReportDialog;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.GameEntityView;
|
||||
@@ -50,6 +52,7 @@ import forge.toolbox.FOptionPane;
|
||||
import forge.toolbox.FSkin;
|
||||
import forge.toolbox.FSkin.SkinImage;
|
||||
import forge.util.BuildInfo;
|
||||
import forge.util.Callback;
|
||||
import forge.util.FCollectionView;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.gui.SGuiChoose;
|
||||
@@ -258,6 +261,11 @@ public class GuiDesktop implements IGuiBase {
|
||||
return fc.getSelectedFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void download(GuiDownloadService service, Callback<Boolean> callback) {
|
||||
new GuiDownloader(service, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyToClipboard(String text) {
|
||||
StringSelection ss = new StringSelection(text);
|
||||
|
||||
@@ -33,13 +33,16 @@ public class DecksComboBox extends FComboBoxWrapper<DeckType> {
|
||||
return new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
MouseUtil.setCursor(Cursor.WAIT_CURSOR);
|
||||
DeckType newDeckType = (DeckType)getSelectedItem();
|
||||
if (newDeckType != selectedDeckType) {
|
||||
notifyDeckTypeSelected(newDeckType);
|
||||
selectedDeckType = newDeckType;
|
||||
Object selectedItem = getSelectedItem();
|
||||
if (selectedItem instanceof DeckType) {
|
||||
MouseUtil.setCursor(Cursor.WAIT_CURSOR);
|
||||
DeckType newDeckType = (DeckType)selectedItem;
|
||||
if (newDeckType != selectedDeckType) {
|
||||
selectedDeckType = newDeckType;
|
||||
notifyDeckTypeSelected(newDeckType);
|
||||
}
|
||||
MouseUtil.resetCursor();
|
||||
}
|
||||
MouseUtil.resetCursor();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -68,4 +71,10 @@ public class DecksComboBox extends FComboBoxWrapper<DeckType> {
|
||||
selectedDeckType = valueOf;
|
||||
setSelectedItem(selectedDeckType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(String text0) {
|
||||
selectedDeckType = null; //ensure selecting current deck type again raises event
|
||||
super.setText(text0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import forge.deck.Deck;
|
||||
import forge.deck.DeckProxy;
|
||||
import forge.deck.DeckType;
|
||||
import forge.deck.DeckgenUtil;
|
||||
import forge.deck.NetDeckCategory;
|
||||
import forge.deck.RandomDeckGenerator;
|
||||
import forge.game.GameType;
|
||||
import forge.game.player.RegisteredPlayer;
|
||||
@@ -38,6 +39,8 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener {
|
||||
private DecksComboBox decksComboBox;
|
||||
private DeckType selectedDeckType;
|
||||
private ItemManagerContainer lstDecksContainer;
|
||||
private NetDeckCategory netDeckCategory;
|
||||
private boolean refreshingDeckType;
|
||||
|
||||
private final DeckManager lstDecks = new DeckManager(GameType.Constructed);
|
||||
private final FLabel btnViewDeck = new FLabel.ButtonBuilder().text("View Deck").fontSize(14).build();
|
||||
@@ -219,6 +222,26 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener {
|
||||
});
|
||||
}
|
||||
|
||||
private void updateNetDecks() {
|
||||
if (netDeckCategory != null) {
|
||||
decksComboBox.setText(netDeckCategory.toString());
|
||||
}
|
||||
lstDecks.setAllowMultipleSelections(false);
|
||||
|
||||
lstDecks.setPool(DeckProxy.getNetDecks(netDeckCategory));
|
||||
lstDecks.setup(ItemManagerConfig.NET_DECKS);
|
||||
|
||||
btnRandom.setText("Random Deck");
|
||||
btnRandom.setCommand(new UiCommand() {
|
||||
@Override
|
||||
public void run() {
|
||||
DeckgenUtil.randomSelect(lstDecks);
|
||||
}
|
||||
});
|
||||
|
||||
lstDecks.setSelectedIndex(0);
|
||||
}
|
||||
|
||||
public Deck getDeck() {
|
||||
DeckProxy proxy = lstDecks.getSelectedItem();
|
||||
return proxy.getDeck();
|
||||
@@ -269,14 +292,36 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener {
|
||||
}
|
||||
|
||||
public void setIsAi(boolean isAiDeck) {
|
||||
this.isAi = isAiDeck;
|
||||
isAi = isAiDeck;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.gui.deckchooser.IDecksComboBoxListener#deckTypeSelected(forge.gui.deckchooser.DecksComboBoxEvent)
|
||||
*/
|
||||
@Override
|
||||
public void deckTypeSelected(DecksComboBoxEvent ev) {
|
||||
public void deckTypeSelected(final DecksComboBoxEvent ev) {
|
||||
if (ev.getDeckType() == DeckType.NET_DECK && !refreshingDeckType) {
|
||||
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
||||
@Override
|
||||
public void run() {
|
||||
final NetDeckCategory category = NetDeckCategory.selectAndLoad(lstDecks.getGameType());
|
||||
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (category == null) {
|
||||
decksComboBox.setDeckType(selectedDeckType); //restore old selection if user cancels
|
||||
if (selectedDeckType == DeckType.NET_DECK && netDeckCategory != null) {
|
||||
decksComboBox.setText(netDeckCategory.toString());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
netDeckCategory = category;
|
||||
refreshDecksList(DeckType.NET_DECK, true, ev);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
refreshDecksList(ev.getDeckType(), false, ev);
|
||||
}
|
||||
|
||||
@@ -285,7 +330,9 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener {
|
||||
selectedDeckType = deckType;
|
||||
|
||||
if (ev == null) {
|
||||
refreshingDeckType = true;
|
||||
decksComboBox.refresh(deckType);
|
||||
refreshingDeckType = false;
|
||||
}
|
||||
lstDecks.setCaption(deckType.toString());
|
||||
|
||||
@@ -308,6 +355,9 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener {
|
||||
case RANDOM_DECK:
|
||||
updateRandom();
|
||||
break;
|
||||
case NET_DECK:
|
||||
updateNetDecks();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,8 +372,15 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener {
|
||||
}
|
||||
|
||||
private String getState() {
|
||||
String deckType = decksComboBox.getDeckType().name();
|
||||
StringBuilder state = new StringBuilder(deckType);
|
||||
StringBuilder state = new StringBuilder();
|
||||
if (decksComboBox.getDeckType() == null || decksComboBox.getDeckType() == DeckType.NET_DECK) {
|
||||
//handle special case of net decks
|
||||
if (netDeckCategory == null) { return ""; }
|
||||
state.append(NetDeckCategory.PREFIX + netDeckCategory.getName());
|
||||
}
|
||||
else {
|
||||
state.append(decksComboBox.getDeckType().name());
|
||||
}
|
||||
state.append(";");
|
||||
joinSelectedDecks(state, SELECTED_DECK_DELIMITER);
|
||||
return state.toString();
|
||||
@@ -345,25 +402,20 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener {
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns a clean name from the state that can be used for labels. */
|
||||
public final String getStateForLabel() {
|
||||
String deckType = decksComboBox.getDeckType().toString();
|
||||
StringBuilder state = new StringBuilder(deckType);
|
||||
state.append(": ");
|
||||
joinSelectedDecks(state, ", ");
|
||||
return state.toString();
|
||||
}
|
||||
|
||||
private void restoreSavedState() {
|
||||
DeckType oldDeckType = selectedDeckType;
|
||||
if (stateSetting == null) {
|
||||
//if can't restore saved state, just refresh deck list
|
||||
refreshDecksList(selectedDeckType, true, null);
|
||||
refreshDecksList(oldDeckType, true, null);
|
||||
return;
|
||||
}
|
||||
|
||||
String savedState = prefs.getPref(stateSetting);
|
||||
refreshDecksList(getDeckTypeFromSavedState(savedState), true, null);
|
||||
lstDecks.setSelectedStrings(getSelectedDecksFromSavedState(savedState));
|
||||
if (!lstDecks.setSelectedStrings(getSelectedDecksFromSavedState(savedState))) {
|
||||
//if can't select old decks, just refresh deck list
|
||||
refreshDecksList(oldDeckType, true, null);
|
||||
}
|
||||
}
|
||||
|
||||
private DeckType getDeckTypeFromSavedState(String savedState) {
|
||||
@@ -372,7 +424,12 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener {
|
||||
return selectedDeckType;
|
||||
}
|
||||
else {
|
||||
return DeckType.valueOf(savedState.split(";")[0]);
|
||||
String deckType = savedState.split(";")[0];
|
||||
if (deckType.startsWith(NetDeckCategory.PREFIX)) {
|
||||
netDeckCategory = NetDeckCategory.selectAndLoad(lstDecks.getGameType(), deckType.substring(NetDeckCategory.PREFIX.length()));
|
||||
return DeckType.NET_DECK;
|
||||
}
|
||||
return DeckType.valueOf(deckType);
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
|
||||
@@ -23,6 +23,7 @@ import forge.UiCommand;
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.gui.SOverlayUtils;
|
||||
import forge.toolbox.*;
|
||||
import forge.util.Callback;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -47,6 +48,10 @@ public class GuiDownloader extends DefaultBoundedRangeModel {
|
||||
|
||||
// Kill overlay
|
||||
SOverlayUtils.hideOverlay();
|
||||
|
||||
if (callback != null) {
|
||||
callback.run(btnStart.getText() == "OK"); //determine result based on whether download finished
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -58,9 +63,14 @@ public class GuiDownloader extends DefaultBoundedRangeModel {
|
||||
private final FRadioButton radProxyHTTP = new FRadioButton("HTTP Proxy");
|
||||
|
||||
private final GuiDownloadService service;
|
||||
private final Callback<Boolean> callback;
|
||||
|
||||
public GuiDownloader(GuiDownloadService service0) {
|
||||
this(service0, null);
|
||||
}
|
||||
public GuiDownloader(GuiDownloadService service0, Callback<Boolean> callback0) {
|
||||
service = service0;
|
||||
callback = callback0;
|
||||
|
||||
String radConstraints = "w 100%!, h 30px!, gap 2% 0 0 10px";
|
||||
JXButtonPanel grpPanel = new JXButtonPanel();
|
||||
|
||||
@@ -52,7 +52,19 @@ public class FComboBox<E> extends SkinnedComboBox<E> implements IComboBox<E> {
|
||||
private Border getDefaultBorder() {
|
||||
return UIManager.getBorder("ComboBox.border");
|
||||
}
|
||||
|
||||
|
||||
public String getText() {
|
||||
Object selectedItem = getSelectedItem();
|
||||
if (selectedItem == null) {
|
||||
return "";
|
||||
}
|
||||
return selectedItem.toString();
|
||||
}
|
||||
public void setText(String text0) {
|
||||
setSelectedItem(null);
|
||||
dataModel.setSelectedItem(text0); //use this to get around inability to set selected item that's not in items
|
||||
}
|
||||
|
||||
public TextAlignment getTextAlignment() {
|
||||
return textAlignment;
|
||||
}
|
||||
@@ -60,7 +72,7 @@ public class FComboBox<E> extends SkinnedComboBox<E> implements IComboBox<E> {
|
||||
public void setTextAlignment(TextAlignment align) {
|
||||
textAlignment = align;
|
||||
}
|
||||
|
||||
|
||||
public SkinFont getSkinFont() {
|
||||
return this.skinFont;
|
||||
}
|
||||
|
||||
@@ -32,138 +32,145 @@ public class FComboBoxWrapper<E> implements IComboBox<E> {
|
||||
|
||||
public FComboBoxWrapper() {
|
||||
super();
|
||||
this.comboBox = new FComboBox<E>();
|
||||
comboBox = new FComboBox<E>();
|
||||
allWrappers.add(this);
|
||||
}
|
||||
|
||||
public FComboBoxWrapper(E[] items) {
|
||||
super();
|
||||
this.comboBox = new FComboBox<E>(items);
|
||||
comboBox = new FComboBox<E>(items);
|
||||
allWrappers.add(this);
|
||||
}
|
||||
|
||||
public FComboBoxWrapper(Vector<E> items) {
|
||||
super();
|
||||
this.comboBox = new FComboBox<E>(items);
|
||||
comboBox = new FComboBox<E>(items);
|
||||
allWrappers.add(this);
|
||||
}
|
||||
|
||||
public FComboBoxWrapper(ComboBoxModel<E> aModel) {
|
||||
super();
|
||||
this.comboBox = new FComboBox<E>(aModel);
|
||||
comboBox = new FComboBox<E>(aModel);
|
||||
allWrappers.add(this);
|
||||
}
|
||||
|
||||
public void addItem(E item) {
|
||||
this.comboBox.addItem(item);
|
||||
comboBox.addItem(item);
|
||||
}
|
||||
|
||||
public void removeItem(E item) {
|
||||
this.comboBox.removeItem(item);
|
||||
comboBox.removeItem(item);
|
||||
}
|
||||
|
||||
public void removeAllItems() {
|
||||
this.comboBox.removeAllItems();
|
||||
comboBox.removeAllItems();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public E getSelectedItem() {
|
||||
Object res = this.comboBox.getSelectedItem();
|
||||
Object res = comboBox.getSelectedItem();
|
||||
return res == null ? null : (E) res;
|
||||
}
|
||||
|
||||
public void setSelectedItem(Object item) {
|
||||
this.comboBox.setSelectedItem(item);
|
||||
comboBox.setSelectedItem(item);
|
||||
}
|
||||
|
||||
public int getSelectedIndex() {
|
||||
return this.comboBox.getSelectedIndex();
|
||||
return comboBox.getSelectedIndex();
|
||||
}
|
||||
|
||||
public void setSelectedIndex(int index) {
|
||||
this.comboBox.setSelectedIndex(index);
|
||||
comboBox.setSelectedIndex(index);
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return comboBox.getText();
|
||||
}
|
||||
public void setText(String text0) {
|
||||
comboBox.setText(text0);
|
||||
}
|
||||
|
||||
public void setMaximumRowCount(int count) {
|
||||
this.comboBox.setMaximumRowCount(count);
|
||||
comboBox.setMaximumRowCount(count);
|
||||
}
|
||||
|
||||
public int getItemCount() {
|
||||
return this.comboBox.getItemCount();
|
||||
return comboBox.getItemCount();
|
||||
}
|
||||
|
||||
public E getItemAt(int index) {
|
||||
return this.comboBox.getItemAt(index);
|
||||
return comboBox.getItemAt(index);
|
||||
}
|
||||
|
||||
public void addActionListener(ActionListener l) {
|
||||
this.comboBox.addActionListener(l);
|
||||
comboBox.addActionListener(l);
|
||||
}
|
||||
|
||||
public void addItemListener(ItemListener l) {
|
||||
this.comboBox.addItemListener(l);
|
||||
comboBox.addItemListener(l);
|
||||
}
|
||||
|
||||
public void addKeyListener(KeyListener l) {
|
||||
this.comboBox.addKeyListener(l);
|
||||
comboBox.addKeyListener(l);
|
||||
}
|
||||
|
||||
public void setRenderer(ListCellRenderer<? super E> aRenderer) {
|
||||
this.comboBox.setRenderer(aRenderer);
|
||||
comboBox.setRenderer(aRenderer);
|
||||
}
|
||||
|
||||
public void setModel(ComboBoxModel<E> aModel) {
|
||||
this.comboBox.setModel(aModel);
|
||||
comboBox.setModel(aModel);
|
||||
}
|
||||
|
||||
public void setTextAlignment(TextAlignment align) {
|
||||
this.comboBox.setTextAlignment(align);
|
||||
comboBox.setTextAlignment(align);
|
||||
}
|
||||
|
||||
public void setSkinFont(SkinFont skinFont) {
|
||||
this.comboBox.setSkinFont(skinFont);
|
||||
comboBox.setSkinFont(skinFont);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return this.comboBox.isVisible();
|
||||
return comboBox.isVisible();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean aFlag) {
|
||||
this.comboBox.setVisible(aFlag);
|
||||
comboBox.setVisible(aFlag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return this.comboBox.isEnabled();
|
||||
return comboBox.isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean aFlag) {
|
||||
this.comboBox.setEnabled(aFlag);
|
||||
comboBox.setEnabled(aFlag);
|
||||
}
|
||||
|
||||
public int getAutoSizeWidth() {
|
||||
return this.comboBox.getAutoSizeWidth();
|
||||
return comboBox.getAutoSizeWidth();
|
||||
}
|
||||
|
||||
public void addTo(Container container) {
|
||||
this.addTo(container, null);
|
||||
addTo(container, null);
|
||||
}
|
||||
public void addTo(Container container, Object constraints0) {
|
||||
container.add(this.comboBox, constraints0);
|
||||
this.constraints = constraints0;
|
||||
container.add(comboBox, constraints0);
|
||||
constraints = constraints0;
|
||||
}
|
||||
|
||||
//disguise as component for sake of rare places that need to access component in wrapper
|
||||
//use addTo instead if you want constraints remembered after refreshing skin
|
||||
public JComponent getComponent() {
|
||||
return this.comboBox;
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private void refreshSkin() {
|
||||
this.comboBox = refreshComboBoxSkin(this.comboBox, this.constraints);
|
||||
comboBox = refreshComboBoxSkin(comboBox, constraints);
|
||||
}
|
||||
|
||||
//refresh combo box skin by replacing it with a copy of itself
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package forge.toolbox;
|
||||
|
||||
import forge.FThreads;
|
||||
import forge.interfaces.IProgressBar;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -9,9 +8,6 @@ import java.util.Date;
|
||||
|
||||
/**
|
||||
* A simple progress bar component using the Forge skin.
|
||||
*
|
||||
* Can show
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class FProgressBar extends JProgressBar implements IProgressBar {
|
||||
@@ -23,20 +19,13 @@ public class FProgressBar extends JProgressBar implements IProgressBar {
|
||||
|
||||
private boolean percentMode = false;
|
||||
|
||||
/** */
|
||||
public FProgressBar() {
|
||||
super();
|
||||
reset();
|
||||
setStringPainted(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets description on bar. Must be called from EDT.
|
||||
*
|
||||
* @param s0   A description to prepend before statistics.
|
||||
*/
|
||||
public void setDescription(final String s0) {
|
||||
FThreads.assertExecutedByEdt(true);
|
||||
desc = s0;
|
||||
setString(s0);
|
||||
}
|
||||
@@ -79,9 +68,8 @@ public class FProgressBar extends JProgressBar implements IProgressBar {
|
||||
setString(sb.toString());
|
||||
}
|
||||
|
||||
/** Resets the various values required for this class. Must be called from EDT. */
|
||||
/** Resets the various values required for this class. */
|
||||
public void reset() {
|
||||
FThreads.assertExecutedByEdt(true);
|
||||
setIndeterminate(true);
|
||||
setValue(0);
|
||||
tempVal = 0;
|
||||
@@ -91,17 +79,14 @@ public class FProgressBar extends JProgressBar implements IProgressBar {
|
||||
setShowCount(true);
|
||||
}
|
||||
|
||||
/** @param b0   Boolean, show the ETA statistic or not */
|
||||
public void setShowETA(boolean b0) {
|
||||
showETA = b0;
|
||||
}
|
||||
|
||||
/** @param b0   Boolean, show the ETA statistic or not */
|
||||
public void setShowCount(boolean b0) {
|
||||
showCount = b0;
|
||||
}
|
||||
|
||||
/** */
|
||||
private void calculateETA(int v0) {
|
||||
float tempMillis = new Date().getTime();
|
||||
float timePerUnit = (tempMillis - startMillis) / v0;
|
||||
@@ -111,9 +96,7 @@ public class FProgressBar extends JProgressBar implements IProgressBar {
|
||||
public boolean isPercentMode() {
|
||||
return percentMode;
|
||||
}
|
||||
|
||||
public void setPercentMode(boolean value) {
|
||||
percentMode = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import forge.deck.CardPool;
|
||||
import forge.deck.Deck;
|
||||
import forge.deck.FDeckViewer;
|
||||
import forge.deck.FSideboardDialog;
|
||||
import forge.download.GuiDownloadService;
|
||||
import forge.error.BugReportDialog;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.GameEntityView;
|
||||
@@ -40,12 +41,14 @@ import forge.player.PlayerControllerHuman;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.screens.match.MatchController;
|
||||
import forge.screens.quest.QuestMenu;
|
||||
import forge.screens.settings.GuiDownloader;
|
||||
import forge.sound.AudioClip;
|
||||
import forge.sound.AudioMusic;
|
||||
import forge.sound.IAudioClip;
|
||||
import forge.sound.IAudioMusic;
|
||||
import forge.toolbox.FOptionPane;
|
||||
import forge.toolbox.GuiChoose;
|
||||
import forge.util.Callback;
|
||||
import forge.util.FCollectionView;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.MessageUtil;
|
||||
@@ -291,6 +294,11 @@ public class GuiMobile implements IGuiBase {
|
||||
return defaultFile; //TODO: Show dialog
|
||||
}
|
||||
|
||||
@Override
|
||||
public void download(GuiDownloadService service, Callback<Boolean> callback) {
|
||||
new GuiDownloader(service, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyToClipboard(String text) {
|
||||
Forge.getClipboard().setContents(text);
|
||||
|
||||
@@ -1,29 +1,19 @@
|
||||
package forge.assets;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.badlogic.gdx.Application.ApplicationType;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.esotericsoftware.minlog.Log;
|
||||
|
||||
import forge.FThreads;
|
||||
import forge.Forge;
|
||||
import forge.download.GuiDownloadZipService;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.screens.SplashScreen;
|
||||
import forge.toolbox.FProgressBar;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.gui.SOptionPane;
|
||||
|
||||
@@ -52,9 +42,10 @@ public class AssetsDownloader {
|
||||
message += " If so, you may want to connect to wifi first. The download is around 6.5MB.";
|
||||
}
|
||||
if (SOptionPane.showConfirmDialog(message, "New Version Available", "Update Now", "Update Later")) {
|
||||
String apkFile = downloadFile("update", "forge-android-" + version + "-signed-aligned.apk",
|
||||
"http://cardforge.org/android/releases/forge/forge-gui-android/" + version + "/",
|
||||
Forge.getDeviceAdapter().getDownloadsDir(), splashScreen.getProgressBar());
|
||||
String filename = "forge-android-" + version + "-signed-aligned.apk";
|
||||
String apkFile = new GuiDownloadZipService("", "update",
|
||||
"http://cardforge.org/android/releases/forge/forge-gui-android/" + version + "/" + filename,
|
||||
Forge.getDeviceAdapter().getDownloadsDir(), null, splashScreen.getProgressBar()).download(filename);
|
||||
if (apkFile != null) {
|
||||
Forge.getDeviceAdapter().openFile(apkFile);
|
||||
Forge.exit(true);
|
||||
@@ -136,7 +127,9 @@ public class AssetsDownloader {
|
||||
return;
|
||||
}
|
||||
|
||||
downloadAssets(splashScreen.getProgressBar());
|
||||
new GuiDownloadZipService("", "resource files",
|
||||
"http://cardforge.org/android/releases/forge/forge-gui-android/" + Forge.CURRENT_VERSION + "/" + "assets.zip",
|
||||
ForgeConstants.ASSETS_DIR, ForgeConstants.RES_DIR, splashScreen.getProgressBar()).downloadAndUnzip();
|
||||
|
||||
FSkinFont.deleteCachedFiles(); //delete cached font files in case any skin's .ttf file changed
|
||||
|
||||
@@ -153,103 +146,4 @@ public class AssetsDownloader {
|
||||
//so they don't need to be re-downloaded until you upgrade again
|
||||
FileUtil.writeFile(versionFile, Forge.CURRENT_VERSION);
|
||||
}
|
||||
|
||||
private static String downloadFile(final String desc, final String filename, final String sourceFolder, final String destFolder, final FProgressBar progressBar) {
|
||||
progressBar.reset();
|
||||
progressBar.setPercentMode(true);
|
||||
progressBar.setDescription("Downloading " + desc);
|
||||
|
||||
try {
|
||||
URL url = new URL(sourceFolder + filename);
|
||||
URLConnection conn = url.openConnection();
|
||||
conn.connect();
|
||||
|
||||
long contentLength = conn.getContentLength();
|
||||
progressBar.setMaximum(100);
|
||||
|
||||
// input stream to read file - with 8k buffer
|
||||
InputStream input = new BufferedInputStream(url.openStream(), 8192);
|
||||
|
||||
// output stream to write file
|
||||
String destFile = destFolder + filename;
|
||||
OutputStream output = new FileOutputStream(destFile);
|
||||
|
||||
int count;
|
||||
long total = 0;
|
||||
byte data[] = new byte[1024];
|
||||
|
||||
while ((count = input.read(data)) != -1) {
|
||||
total += count;
|
||||
progressBar.setValue((int)(100 * total / contentLength));
|
||||
output.write(data, 0, count);
|
||||
}
|
||||
|
||||
output.flush();
|
||||
output.close();
|
||||
input.close();
|
||||
return destFile;
|
||||
}
|
||||
catch (final Exception ex) {
|
||||
Log.error("Downloading " + desc, "Error downloading " + desc, ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void downloadAssets(final FProgressBar progressBar) {
|
||||
String assetsFile = downloadFile("resource files", "assets.zip",
|
||||
"http://cardforge.org/android/releases/forge/forge-gui-android/" + Forge.CURRENT_VERSION + "/",
|
||||
ForgeConstants.ASSETS_DIR, progressBar);
|
||||
if (assetsFile == null) { return; }
|
||||
|
||||
//if assets.zip downloaded successfully, unzip into destination folder
|
||||
try {
|
||||
File resDir = new File(ForgeConstants.RES_DIR);
|
||||
if (resDir.exists()) {
|
||||
//attempt to delete previous res directory if to be rebuilt
|
||||
progressBar.reset();
|
||||
progressBar.setDescription("Deleting old resource files...");
|
||||
FileUtil.deleteDirectory(resDir);
|
||||
}
|
||||
|
||||
ZipFile zipFile = new ZipFile(assetsFile);
|
||||
Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
||||
|
||||
progressBar.reset();
|
||||
progressBar.setPercentMode(true);
|
||||
progressBar.setDescription("Unzipping resource files");
|
||||
progressBar.setMaximum(zipFile.size());
|
||||
|
||||
int count = 0;
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipEntry entry = (ZipEntry)entries.nextElement();
|
||||
|
||||
String path = ForgeConstants.ASSETS_DIR + entry.getName();
|
||||
if (entry.isDirectory()) {
|
||||
new File(path).mkdir();
|
||||
progressBar.setValue(++count);
|
||||
continue;
|
||||
}
|
||||
copyInputStream(zipFile.getInputStream(entry), new BufferedOutputStream(new FileOutputStream(path)));
|
||||
progressBar.setValue(++count);
|
||||
}
|
||||
|
||||
zipFile.close();
|
||||
new File(assetsFile).delete();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static final void copyInputStream(InputStream in, OutputStream out) throws IOException{
|
||||
byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
|
||||
while((len = in.read(buffer)) >= 0) {
|
||||
out.write(buffer, 0, len);
|
||||
}
|
||||
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,8 @@ public class FDeckChooser extends FScreen {
|
||||
private DeckType selectedDeckType;
|
||||
private boolean needRefreshOnActivate;
|
||||
private Callback<Deck> callback;
|
||||
private NetDeckCategory netDeckCategory;
|
||||
private boolean refreshingDeckType;
|
||||
|
||||
private final DeckManager lstDecks;
|
||||
private final FButton btnNewDeck = new FButton("New Deck");
|
||||
@@ -261,6 +263,12 @@ public class FDeckChooser extends FScreen {
|
||||
cmbDeckTypes.addItem(DeckType.COLOR_DECK);
|
||||
cmbDeckTypes.addItem(DeckType.THEME_DECK);
|
||||
cmbDeckTypes.addItem(DeckType.RANDOM_DECK);
|
||||
cmbDeckTypes.addItem(DeckType.NET_DECK);
|
||||
break;
|
||||
case Commander:
|
||||
cmbDeckTypes.addItem(DeckType.CUSTOM_DECK);
|
||||
cmbDeckTypes.addItem(DeckType.RANDOM_DECK);
|
||||
cmbDeckTypes.addItem(DeckType.NET_DECK);
|
||||
break;
|
||||
default:
|
||||
cmbDeckTypes.addItem(DeckType.CUSTOM_DECK);
|
||||
@@ -271,7 +279,32 @@ public class FDeckChooser extends FScreen {
|
||||
restoreSavedState();
|
||||
cmbDeckTypes.setChangedHandler(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
public void handleEvent(final FEvent e) {
|
||||
if (cmbDeckTypes.getSelectedItem() == DeckType.NET_DECK && !refreshingDeckType) {
|
||||
FThreads.invokeInBackgroundThread(new Runnable() { //needed for loading net decks
|
||||
@Override
|
||||
public void run() {
|
||||
final NetDeckCategory category = NetDeckCategory.selectAndLoad(lstDecks.getGameType());
|
||||
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (category == null) {
|
||||
cmbDeckTypes.setSelectedItem(selectedDeckType); //restore old selection if user cancels
|
||||
if (selectedDeckType == DeckType.NET_DECK && netDeckCategory != null) {
|
||||
cmbDeckTypes.setText(netDeckCategory.toString());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
netDeckCategory = category;
|
||||
refreshDecksList(DeckType.NET_DECK, true, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
refreshDecksList(cmbDeckTypes.getSelectedItem(), false, e);
|
||||
}
|
||||
});
|
||||
@@ -493,6 +526,32 @@ public class FDeckChooser extends FScreen {
|
||||
});
|
||||
}
|
||||
|
||||
private void updateNetDecks() {
|
||||
if (netDeckCategory != null) {
|
||||
cmbDeckTypes.setText(netDeckCategory.toString());
|
||||
}
|
||||
lstDecks.setSelectionSupport(1, 1);
|
||||
|
||||
lstDecks.setPool(DeckProxy.getNetDecks(netDeckCategory));
|
||||
lstDecks.setup(ItemManagerConfig.NET_DECKS);
|
||||
|
||||
btnNewDeck.setText("New Deck");
|
||||
btnNewDeck.setWidth(btnEditDeck.getWidth());
|
||||
btnEditDeck.setVisible(true);
|
||||
|
||||
btnViewDeck.setVisible(true);
|
||||
btnRandom.setText("Random Deck");
|
||||
btnRandom.setWidth(btnNewDeck.getWidth());
|
||||
btnRandom.setLeft(getWidth() - PADDING - btnRandom.getWidth());
|
||||
btnRandom.setCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
DeckgenUtil.randomSelect(lstDecks);
|
||||
accept();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Deck getDeck() {
|
||||
DeckProxy proxy = lstDecks.getSelectedItem();
|
||||
if (proxy == null) { return null; }
|
||||
@@ -530,7 +589,9 @@ public class FDeckChooser extends FScreen {
|
||||
selectedDeckType = deckType;
|
||||
|
||||
if (e == null) {
|
||||
refreshingDeckType = true;
|
||||
cmbDeckTypes.setSelectedItem(deckType);
|
||||
refreshingDeckType = false;
|
||||
}
|
||||
if (deckType == null) { return; }
|
||||
|
||||
@@ -553,6 +614,9 @@ public class FDeckChooser extends FScreen {
|
||||
case RANDOM_DECK:
|
||||
updateRandom();
|
||||
break;
|
||||
case NET_DECK:
|
||||
updateNetDecks();
|
||||
break;
|
||||
}
|
||||
|
||||
if (e != null) { //set default list selection if from combo box change event
|
||||
@@ -577,8 +641,15 @@ public class FDeckChooser extends FScreen {
|
||||
}
|
||||
|
||||
private String getState() {
|
||||
String deckType = cmbDeckTypes.getSelectedItem().name();
|
||||
StringBuilder state = new StringBuilder(deckType);
|
||||
StringBuilder state = new StringBuilder();
|
||||
if (cmbDeckTypes.getSelectedItem() == null || cmbDeckTypes.getSelectedItem() == DeckType.NET_DECK) {
|
||||
//handle special case of net decks
|
||||
if (netDeckCategory == null) { return ""; }
|
||||
state.append(NetDeckCategory.PREFIX + netDeckCategory.getName());
|
||||
}
|
||||
else {
|
||||
state.append(cmbDeckTypes.getSelectedItem().name());
|
||||
}
|
||||
state.append(";");
|
||||
joinSelectedDecks(state, SELECTED_DECK_DELIMITER);
|
||||
return state.toString();
|
||||
@@ -600,25 +671,20 @@ public class FDeckChooser extends FScreen {
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns a clean name from the state that can be used for labels. */
|
||||
public final String getStateForLabel() {
|
||||
String deckType = cmbDeckTypes.getSelectedItem().toString();
|
||||
StringBuilder state = new StringBuilder(deckType);
|
||||
state.append(": ");
|
||||
joinSelectedDecks(state, ", ");
|
||||
return state.toString();
|
||||
}
|
||||
|
||||
private void restoreSavedState() {
|
||||
DeckType oldDeckType = selectedDeckType;
|
||||
if (stateSetting == null) {
|
||||
//if can't restore saved state, just refresh deck list
|
||||
refreshDecksList(selectedDeckType, true, null);
|
||||
refreshDecksList(oldDeckType, true, null);
|
||||
return;
|
||||
}
|
||||
|
||||
String savedState = prefs.getPref(stateSetting);
|
||||
refreshDecksList(getDeckTypeFromSavedState(savedState), true, null);
|
||||
lstDecks.setSelectedStrings(getSelectedDecksFromSavedState(savedState));
|
||||
if (!lstDecks.setSelectedStrings(getSelectedDecksFromSavedState(savedState))) {
|
||||
//if can't select old decks, just refresh deck list
|
||||
refreshDecksList(oldDeckType, true, null);
|
||||
}
|
||||
}
|
||||
|
||||
private DeckType getDeckTypeFromSavedState(String savedState) {
|
||||
@@ -627,7 +693,12 @@ public class FDeckChooser extends FScreen {
|
||||
return selectedDeckType;
|
||||
}
|
||||
else {
|
||||
return DeckType.valueOf(savedState.split(";")[0]);
|
||||
String deckType = savedState.split(";")[0];
|
||||
if (deckType.startsWith(NetDeckCategory.PREFIX)) {
|
||||
netDeckCategory = NetDeckCategory.selectAndLoad(lstDecks.getGameType(), deckType.substring(NetDeckCategory.PREFIX.length()));
|
||||
return DeckType.NET_DECK;
|
||||
}
|
||||
return DeckType.valueOf(deckType);
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
|
||||
@@ -24,9 +24,11 @@ import com.badlogic.gdx.Gdx;
|
||||
import forge.UiCommand;
|
||||
import forge.assets.FSkinFont;
|
||||
import forge.download.GuiDownloadService;
|
||||
import forge.download.GuiDownloadZipService;
|
||||
import forge.toolbox.*;
|
||||
import forge.toolbox.FEvent.FEventHandler;
|
||||
import forge.toolbox.FRadioButton.RadioButtonGroup;
|
||||
import forge.util.Callback;
|
||||
|
||||
public class GuiDownloader extends FDialog {
|
||||
public static final Proxy.Type[] TYPES = Proxy.Type.values();
|
||||
@@ -44,16 +46,25 @@ public class GuiDownloader extends FDialog {
|
||||
private final UiCommand cmdClose = new UiCommand() {
|
||||
@Override
|
||||
public void run() {
|
||||
Gdx.graphics.setContinuousRendering(false);
|
||||
service.setCancel(true);
|
||||
hide();
|
||||
if (callback != null) {
|
||||
callback.run(btnStart.getText() == "OK"); //determine result based on whether download finished
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final GuiDownloadService service;
|
||||
private final Callback<Boolean> callback;
|
||||
|
||||
public GuiDownloader(GuiDownloadService service0) {
|
||||
this(service0, null);
|
||||
}
|
||||
public GuiDownloader(GuiDownloadService service0, Callback<Boolean> callback0) {
|
||||
super(service0.getTitle());
|
||||
service = service0;
|
||||
callback = callback0;
|
||||
|
||||
txtAddress.setGhostText("Proxy Address");
|
||||
txtPort.setGhostText("Proxy Port");
|
||||
@@ -85,7 +96,9 @@ public class GuiDownloader extends FDialog {
|
||||
service.initialize(txtAddress, txtPort, progressBar, btnStart, cmdClose, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Gdx.graphics.setContinuousRendering(false);
|
||||
if (!(service instanceof GuiDownloadZipService)) { //retain continuous rendering for zip service
|
||||
Gdx.graphics.setContinuousRendering(false);
|
||||
}
|
||||
progressBar.setShowProgressTrail(false);
|
||||
}
|
||||
}, null);
|
||||
|
||||
@@ -174,10 +174,15 @@ public class FComboBox<T> extends FTextField implements IComboBox<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getRightPadding() {
|
||||
protected float getLeftPadding() {
|
||||
if (getAlignment() == HAlignment.CENTER) {
|
||||
return super.getRightPadding();
|
||||
return getRightPadding(); //match right padding if center aligned
|
||||
}
|
||||
return super.getLeftPadding();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getRightPadding() {
|
||||
return getDivotWidth() + 2 * PADDING;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@ public class FEvent {
|
||||
CHANGE,
|
||||
ACTIVATE,
|
||||
SAVE,
|
||||
DELETE
|
||||
DELETE,
|
||||
CLOSE
|
||||
}
|
||||
|
||||
private FDisplayObject source;
|
||||
|
||||
@@ -8,6 +8,12 @@ Forge Beta: 1-#-2015 ver 1.5.33
|
||||
Release Notes
|
||||
-------------
|
||||
|
||||
- Net Decks support -
|
||||
On the Constructed screen, you can now select a new Net Decks category from the drop down
|
||||
Contains all decks from gos's Forge Decks subforums, broken up by the column/event they were taken from
|
||||
Won't cause startup to be slower since they are loaded on the fly
|
||||
|
||||
|
||||
- Zoom to a XLHQ card picture -
|
||||
Forge now supports showing XLHQ (extra large high quality) card pictures when zooming in on a card if these pictures are available. Forge will look for XLHQ card art in the "XLHQ" subfolder of the "pics/cards" folder in Forge cache. XLHQ pictures should have the ".xlhq.jpg" extension instead of the ".full.jpg" one (CCGHQ XLHQ releases comply with this naming scheme). For example, while the regular 10th edition Blaze will be looked up as "pics/cards/10E/Blaze.full.jpg", the XLHQ version will be looked up as "pics/cards/XLHQ/10E/Blaze.xlhq.jpg". If the XLHQ picture is not available Forge will show you the regular card picture in the zoomed view, as usual. Please note that XLHQ versions of cards are *only* showed in the zoom view, regular card pictures are still used (LQ/HQ, depending on what you're using) on the battlefield and elsewhere in the game because XLHQ art is significantly more taxing in memory consumption even when compared to standard high quality (HQ) releases (and in addition to that, XLHQ card borders are not cropped the way Forge expects them in order to show them properly on the battlefield anyway). XLHQ tokens are also supported, but the naming scheme for them is a little different - they are looked up in "pics/tokens/XLHQ" and have their ordinary names. For example, the 1/1 red Goblin token from the Magic 2015 set is normally looked up at "pics/tokens/r_1_1_goblin_m15.jpg", while its XLHQ version is looked up at "pics/tokens/XLHQ/r_1_1_goblin_m15.jpg".
|
||||
|
||||
|
||||
10
forge-gui/res/lists/net-decks-commander.txt
Normal file
10
forge-gui/res/lists/net-decks-commander.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
The Week That Was | http://www.slightlymagic.net/forum/download/file.php?id=19986
|
||||
WotC Preconstructed | http://www.slightlymagic.net/forum/download/file.php?id=21293
|
||||
Serious Fun | http://www.slightlymagic.net/forum/download/file.php?id=21279
|
||||
ReConstructed | http://www.slightlymagic.net/forum/download/file.php?id=21275
|
||||
Latest Developments | http://www.slightlymagic.net/forum/download/file.php?id=13259
|
||||
From the Lab | http://www.slightlymagic.net/forum/download/file.php?id=21263
|
||||
Feature Article | http://www.slightlymagic.net/forum/download/file.php?id=21259
|
||||
Daily Deck List | http://www.slightlymagic.net/forum/download/file.php?id=18670
|
||||
Command Tower | http://www.slightlymagic.net/forum/download/file.php?id=21255
|
||||
Going Rogue | http://www.slightlymagic.net/forum/download/file.php?id=14064
|
||||
28
forge-gui/res/lists/net-decks.txt
Normal file
28
forge-gui/res/lists/net-decks.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
Top Decks | http://www.slightlymagic.net/forum/download/file.php?id=21296
|
||||
World Championship | http://www.slightlymagic.net/forum/download/file.php?id=21289
|
||||
The Week That Was | http://www.slightlymagic.net/forum/download/file.php?id=21285
|
||||
Single Card Strategy | http://www.slightlymagic.net/forum/download/file.php?id=21282
|
||||
WotC Preconstructed | http://www.slightlymagic.net/forum/download/file.php?id=21292
|
||||
Serious Fun | http://www.slightlymagic.net/forum/download/file.php?id=21278
|
||||
ReConstructed | http://www.slightlymagic.net/forum/download/file.php?id=21274
|
||||
Pro Tour | http://www.slightlymagic.net/forum/download/file.php?id=21272
|
||||
Perilous Research | http://www.slightlymagic.net/forum/download/file.php?id=21270
|
||||
Into the AEther | http://www.slightlymagic.net/forum/download/file.php?id=18683
|
||||
Level One | http://www.slightlymagic.net/forum/download/file.php?id=21268
|
||||
Latest Developments | http://www.slightlymagic.net/forum/download/file.php?id=21266
|
||||
From the Lab | http://www.slightlymagic.net/forum/download/file.php?id=21262
|
||||
Feature Article | http://www.slightlymagic.net/forum/download/file.php?id=21260
|
||||
Daily Deck List | http://www.slightlymagic.net/forum/download/file.php?id=21257
|
||||
Building on a Budget | http://www.slightlymagic.net/forum/download/file.php?id=21253
|
||||
Breaking Through | http://www.slightlymagic.net/forum/download/file.php?id=21251
|
||||
Woo Brews | http://www.slightlymagic.net/forum/download/file.php?id=19091
|
||||
Swimming with Sharks | http://www.slightlymagic.net/forum/download/file.php?id=17441
|
||||
Learning Curve | http://www.slightlymagic.net/forum/download/file.php?id=16447
|
||||
Squandered Resources | http://www.slightlymagic.net/forum/download/file.php?id=16074
|
||||
Deconstructing Famous | http://www.slightlymagic.net/forum/download/file.php?id=14190
|
||||
Going Rogue | http://www.slightlymagic.net/forum/download/file.php?id=13498
|
||||
Uncommon Knowledge | http://www.slightlymagic.net/forum/download/file.php?id=13877
|
||||
MagicTheGathering.Combos | http://www.slightlymagic.net/forum/download/file.php?id=9316
|
||||
Players Championship 2012 | http://www.slightlymagic.net/forum/download/file.php?id=7324
|
||||
Brewing on a Budget | http://www.slightlymagic.net/forum/download/file.php?id=6584
|
||||
Grand Prix Lincoln 2012 | http://www.slightlymagic.net/forum/download/file.php?id=5318
|
||||
@@ -445,6 +445,14 @@ public class DeckProxy implements InventoryItem {
|
||||
return decks;
|
||||
}
|
||||
|
||||
public static List<DeckProxy> getNetDecks(NetDeckCategory category) {
|
||||
ArrayList<DeckProxy> decks = new ArrayList<DeckProxy>();
|
||||
if (category != null) {
|
||||
addDecksRecursivelly("Constructed", GameType.Constructed, decks, "", category);
|
||||
}
|
||||
return decks;
|
||||
}
|
||||
|
||||
public static final Predicate<DeckProxy> IS_WHITE = new Predicate<DeckProxy>() {
|
||||
@Override
|
||||
public boolean apply(final DeckProxy deck) {
|
||||
|
||||
@@ -6,7 +6,8 @@ public enum DeckType {
|
||||
QUEST_OPPONENT_DECK ("Quest Opponent Decks"),
|
||||
COLOR_DECK ("Random Color Decks"),
|
||||
THEME_DECK ("Random Theme Decks"),
|
||||
RANDOM_DECK ("Random Decks");
|
||||
RANDOM_DECK ("Random Decks"),
|
||||
NET_DECK ("Net Decks");
|
||||
|
||||
private String value;
|
||||
private DeckType(String value) {
|
||||
|
||||
127
forge-gui/src/main/java/forge/deck/NetDeckCategory.java
Normal file
127
forge-gui/src/main/java/forge/deck/NetDeckCategory.java
Normal file
@@ -0,0 +1,127 @@
|
||||
package forge.deck;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import forge.GuiBase;
|
||||
import forge.deck.io.DeckSerializer;
|
||||
import forge.deck.io.DeckStorage;
|
||||
import forge.download.GuiDownloadZipService;
|
||||
import forge.game.GameType;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.WaitCallback;
|
||||
import forge.util.gui.SGuiChoose;
|
||||
import forge.util.storage.StorageBase;
|
||||
|
||||
public class NetDeckCategory extends StorageBase<Deck> {
|
||||
public static final String PREFIX = "NET_DECK_";
|
||||
private static Map<String, NetDeckCategory> constructed, commander;
|
||||
|
||||
private static Map<String, NetDeckCategory> loadCategories(String filename) {
|
||||
Map<String, NetDeckCategory> categories = new TreeMap<String, NetDeckCategory>();
|
||||
if (FileUtil.doesFileExist(filename)) {
|
||||
List<String> lines = FileUtil.readFile(filename);
|
||||
for (String line : lines) {
|
||||
int idx = line.indexOf('|');
|
||||
if (idx != -1) {
|
||||
String name = line.substring(0, idx).trim();
|
||||
String url = line.substring(idx + 1).trim();
|
||||
categories.put(name, new NetDeckCategory(name, url));
|
||||
}
|
||||
}
|
||||
}
|
||||
return categories;
|
||||
}
|
||||
|
||||
public static NetDeckCategory selectAndLoad(GameType gameType) {
|
||||
return selectAndLoad(gameType, null);
|
||||
}
|
||||
public static NetDeckCategory selectAndLoad(GameType gameType, String name) {
|
||||
Map<String, NetDeckCategory> categories;
|
||||
switch (gameType) {
|
||||
case Constructed:
|
||||
case Gauntlet:
|
||||
if (constructed == null) {
|
||||
constructed = loadCategories(ForgeConstants.NET_DECKS_LIST_FILE);
|
||||
}
|
||||
categories = constructed;
|
||||
break;
|
||||
case Commander:
|
||||
if (commander == null) {
|
||||
commander = loadCategories(ForgeConstants.NET_DECKS_COMMANDER_LIST_FILE);
|
||||
}
|
||||
categories = commander;
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
if (name != null) {
|
||||
NetDeckCategory category = categories.get(name);
|
||||
if (category != null && category.map.isEmpty()) {
|
||||
//if name passed in, try to load decks from current cached files
|
||||
File downloadDir = new File(category.getDownloadLocation());
|
||||
if (downloadDir.exists()) {
|
||||
for (File file : downloadDir.listFiles(DeckStorage.DCK_FILE_FILTER)) {
|
||||
Deck deck = DeckSerializer.fromFile(file);
|
||||
if (deck != null) {
|
||||
category.map.put(deck.getName(), deck);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return category;
|
||||
}
|
||||
|
||||
final NetDeckCategory c= SGuiChoose.oneOrNone("Select a Net Deck category", categories.values());
|
||||
if (c == null) { return null; }
|
||||
|
||||
if (c.map.isEmpty()) { //only download decks once per session
|
||||
WaitCallback<Boolean> callback = new WaitCallback<Boolean>() {
|
||||
@Override
|
||||
public void run() {
|
||||
String downloadLoc = c.getDownloadLocation();
|
||||
GuiBase.getInterface().download(new GuiDownloadZipService(c.getName(), "decks", c.getUrl(), downloadLoc, downloadLoc, null) {
|
||||
@Override
|
||||
protected void copyInputStream(InputStream in, String outPath) throws IOException {
|
||||
super.copyInputStream(in, outPath);
|
||||
|
||||
Deck deck = DeckSerializer.fromFile(new File(outPath));
|
||||
if (deck != null) {
|
||||
c.map.put(deck.getName(), deck);
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
};
|
||||
if (!callback.invokeAndWait()) { return null; } //wait for download to finish
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private final String url;
|
||||
|
||||
private NetDeckCategory(String name0, String downloadLocation0) {
|
||||
super(name0, new HashMap<String, Deck>());
|
||||
url = downloadLocation0;
|
||||
}
|
||||
|
||||
public String getDownloadLocation() {
|
||||
return ForgeConstants.DECK_NET_DIR + name + "/";
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Net Decks - " + name;
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ public abstract class GuiDownloadService implements Runnable {
|
||||
//Components passed from GUI component displaying download
|
||||
private ITextField txtAddress;
|
||||
private ITextField txtPort;
|
||||
private IProgressBar progressBar;
|
||||
protected IProgressBar progressBar;
|
||||
private IButton btnStart;
|
||||
private UiCommand cmdClose;
|
||||
private Runnable onUpdate;
|
||||
@@ -73,7 +73,7 @@ public abstract class GuiDownloadService implements Runnable {
|
||||
|
||||
// Progress variables
|
||||
private Map<String, String> files; // local path -> url
|
||||
private boolean cancel;
|
||||
protected boolean cancel;
|
||||
private final long[] times = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
private int tptr = 0;
|
||||
private int skipped = 0;
|
||||
@@ -90,27 +90,50 @@ public abstract class GuiDownloadService implements Runnable {
|
||||
cmdClose = cmdClose0;
|
||||
onUpdate = onUpdate0;
|
||||
|
||||
// Free up the EDT by assembling card list on a background thread
|
||||
FThreads.invokeInBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
files = getNeededFiles();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (onReadyToStart != null) {
|
||||
onReadyToStart.run();
|
||||
}
|
||||
readyToStart();
|
||||
String startOverrideDesc = getStartOverrideDesc();
|
||||
if (startOverrideDesc == null) {
|
||||
// Free up the EDT by assembling card list on a background thread
|
||||
FThreads.invokeInBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
files = getNeededFiles();
|
||||
}
|
||||
});
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (onReadyToStart != null) {
|
||||
onReadyToStart.run();
|
||||
}
|
||||
readyToStart();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
//handle special case of zip service
|
||||
if (onReadyToStart != null) {
|
||||
onReadyToStart.run();
|
||||
}
|
||||
});
|
||||
progressBar.setDescription("Click \"Start\" to download and extract " + startOverrideDesc);
|
||||
btnStart.setCommand(cmdStartDownload);
|
||||
btnStart.setEnabled(true);
|
||||
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
btnStart.requestFocusInWindow();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected String getStartOverrideDesc() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void readyToStart() {
|
||||
@@ -198,10 +221,7 @@ public abstract class GuiDownloadService implements Runnable {
|
||||
else {
|
||||
sb.append(String.format("%d of %d items finished! Skipped " + skipped + " items. Please close!",
|
||||
count, files.size()));
|
||||
btnStart.setText("OK");
|
||||
btnStart.setCommand(cmdClose);
|
||||
btnStart.setEnabled(true);
|
||||
btnStart.requestFocusInWindow();
|
||||
finish();
|
||||
}
|
||||
|
||||
progressBar.setValue(count);
|
||||
@@ -211,25 +231,18 @@ public abstract class GuiDownloadService implements Runnable {
|
||||
});
|
||||
}
|
||||
|
||||
protected void finish() {
|
||||
btnStart.setText("OK");
|
||||
btnStart.setCommand(cmdClose);
|
||||
btnStart.setEnabled(true);
|
||||
btnStart.requestFocusInWindow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run() {
|
||||
public void run() {
|
||||
final Random r = MyRandom.getRandom();
|
||||
|
||||
Proxy p = null;
|
||||
if (type == 0) {
|
||||
p = Proxy.NO_PROXY;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
p = new Proxy(TYPES[type], new InetSocketAddress(txtAddress.getText(), Integer.parseInt(txtPort.getText())));
|
||||
}
|
||||
catch (final Exception ex) {
|
||||
BugReporter.reportException(ex,
|
||||
"Proxy connection could not be established!\nProxy address: %s\nProxy port: %s",
|
||||
txtAddress.getText(), txtPort.getText());
|
||||
return;
|
||||
}
|
||||
}
|
||||
Proxy p = getProxy();
|
||||
|
||||
int bufferLength;
|
||||
int iCard = 0;
|
||||
@@ -304,6 +317,23 @@ public abstract class GuiDownloadService implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
protected Proxy getProxy() {
|
||||
if (type == 0) {
|
||||
return Proxy.NO_PROXY;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
return new Proxy(TYPES[type], new InetSocketAddress(txtAddress.getText(), Integer.parseInt(txtPort.getText())));
|
||||
}
|
||||
catch (final Exception ex) {
|
||||
BugReporter.reportException(ex,
|
||||
"Proxy connection could not be established!\nProxy address: %s\nProxy port: %s",
|
||||
txtAddress.getText(), txtPort.getText());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract String getTitle();
|
||||
protected abstract Map<String, String> getNeededFiles();
|
||||
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
package forge.download;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import com.esotericsoftware.minlog.Log;
|
||||
import com.google.common.io.Files;
|
||||
|
||||
import forge.FThreads;
|
||||
import forge.interfaces.IProgressBar;
|
||||
import forge.util.FileUtil;
|
||||
|
||||
public class GuiDownloadZipService extends GuiDownloadService {
|
||||
private final String name, desc, sourceUrl, destFolder, deleteFolder;
|
||||
private int filesDownloaded;
|
||||
|
||||
public GuiDownloadZipService(String name0, String desc0, String sourceUrl0, String destFolder0, String deleteFolder0, IProgressBar progressBar0) {
|
||||
name = name0;
|
||||
desc = desc0;
|
||||
sourceUrl = sourceUrl0;
|
||||
destFolder = destFolder0;
|
||||
deleteFolder = deleteFolder0;
|
||||
progressBar = progressBar0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "Download " + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getStartOverrideDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Map<String, String> getNeededFiles() {
|
||||
HashMap<String, String> files = new HashMap<String, String>();
|
||||
files.put("_", "_");
|
||||
return files; //not needed by zip service, so just return map of size 1
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run() {
|
||||
downloadAndUnzip();
|
||||
if (!cancel) {
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressBar.setDescription(filesDownloaded + " " + desc + " downloaded");
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void downloadAndUnzip() {
|
||||
filesDownloaded = 0;
|
||||
String zipFilename = download("temp.zip");
|
||||
if (zipFilename == null) { return; }
|
||||
|
||||
//if assets.zip downloaded successfully, unzip into destination folder
|
||||
try {
|
||||
if (deleteFolder != null) {
|
||||
File deleteDir = new File(deleteFolder);
|
||||
if (deleteDir.exists()) {
|
||||
//attempt to delete previous res directory if to be rebuilt
|
||||
progressBar.reset();
|
||||
progressBar.setDescription("Deleting old " + desc + "...");
|
||||
if (deleteFolder.equals(destFolder)) { //move zip file to prevent deleting it
|
||||
String oldZipFilename = zipFilename;
|
||||
zipFilename = deleteDir.getParentFile().getAbsolutePath() + File.separator + "temp.zip";
|
||||
Files.move(new File(oldZipFilename), new File(zipFilename));
|
||||
}
|
||||
FileUtil.deleteDirectory(deleteDir);
|
||||
}
|
||||
}
|
||||
|
||||
ZipFile zipFile = new ZipFile(zipFilename, Charset.forName("CP866")); //ensure unzip doesn't fail due to non UTF-8 chars
|
||||
Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
||||
|
||||
progressBar.reset();
|
||||
progressBar.setPercentMode(true);
|
||||
progressBar.setDescription("Extracting " + desc);
|
||||
progressBar.setMaximum(zipFile.size());
|
||||
|
||||
FileUtil.ensureDirectoryExists(destFolder);
|
||||
|
||||
int count = 0;
|
||||
while (entries.hasMoreElements()) {
|
||||
if (cancel) { break; }
|
||||
|
||||
ZipEntry entry = (ZipEntry)entries.nextElement();
|
||||
|
||||
String path = destFolder + entry.getName();
|
||||
if (entry.isDirectory()) {
|
||||
new File(path).mkdir();
|
||||
progressBar.setValue(++count);
|
||||
continue;
|
||||
}
|
||||
copyInputStream(zipFile.getInputStream(entry), path);
|
||||
progressBar.setValue(++count);
|
||||
filesDownloaded++;
|
||||
}
|
||||
|
||||
zipFile.close();
|
||||
new File(zipFilename).delete();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public String download(String filename) {
|
||||
progressBar.reset();
|
||||
progressBar.setPercentMode(true);
|
||||
progressBar.setDescription("Downloading " + desc);
|
||||
|
||||
try {
|
||||
URL url = new URL(sourceUrl);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection(getProxy());
|
||||
|
||||
if (url.getPath().endsWith(".php")) {
|
||||
//ensure file can be downloaded if returned from PHP script
|
||||
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 4.01; Windows NT)");
|
||||
}
|
||||
|
||||
conn.connect();
|
||||
|
||||
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
|
||||
return null;
|
||||
}
|
||||
|
||||
long contentLength = conn.getContentLengthLong();
|
||||
if (contentLength == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
progressBar.setMaximum(100);
|
||||
|
||||
// input stream to read file - with 8k buffer
|
||||
InputStream input = new BufferedInputStream(conn.getInputStream(), 8192);
|
||||
|
||||
FileUtil.ensureDirectoryExists(destFolder);
|
||||
|
||||
// output stream to write file
|
||||
String destFile = destFolder + filename;
|
||||
OutputStream output = new FileOutputStream(destFile);
|
||||
|
||||
int count;
|
||||
long total = 0;
|
||||
byte data[] = new byte[1024];
|
||||
|
||||
while ((count = input.read(data)) != -1) {
|
||||
if (cancel) { break; }
|
||||
|
||||
total += count;
|
||||
progressBar.setValue((int)(100 * total / contentLength));
|
||||
output.write(data, 0, count);
|
||||
}
|
||||
|
||||
output.flush();
|
||||
output.close();
|
||||
input.close();
|
||||
|
||||
if (cancel) {
|
||||
new File(destFile).delete();
|
||||
return null;
|
||||
}
|
||||
return destFile;
|
||||
}
|
||||
catch (final Exception ex) {
|
||||
Log.error("Downloading " + desc, "Error downloading " + desc, ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void copyInputStream(InputStream in, String outPath) throws IOException{
|
||||
byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(outPath));
|
||||
|
||||
while((len = in.read(buffer)) >= 0) {
|
||||
out.write(buffer, 0, len);
|
||||
}
|
||||
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import forge.LobbyPlayer;
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.assets.ISkinImage;
|
||||
import forge.deck.CardPool;
|
||||
import forge.download.GuiDownloadService;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.GameEntityView;
|
||||
import forge.game.card.CardView;
|
||||
@@ -19,6 +20,7 @@ import forge.item.PaperCard;
|
||||
import forge.player.PlayerControllerHuman;
|
||||
import forge.sound.IAudioClip;
|
||||
import forge.sound.IAudioMusic;
|
||||
import forge.util.Callback;
|
||||
import forge.util.FCollectionView;
|
||||
|
||||
public interface IGuiBase {
|
||||
@@ -45,6 +47,7 @@ public interface IGuiBase {
|
||||
GameEntityView chooseSingleEntityForEffect(String title, FCollectionView<? extends GameEntity> optionList, DelayedReveal delayedReveal, boolean isOptional, PlayerControllerHuman controller);
|
||||
String showFileDialog(String title, String defaultDir);
|
||||
File getSaveFile(File defaultFile);
|
||||
void download(GuiDownloadService service, Callback<Boolean> callback);
|
||||
void showCardList(final String title, final String message, final List<PaperCard> list);
|
||||
boolean showBoxedProduct(final String title, final String message, final List<PaperCard> list);
|
||||
void setCard(CardView card);
|
||||
|
||||
@@ -88,6 +88,8 @@ public enum ItemManagerConfig {
|
||||
null, null, 3, 0),
|
||||
QUEST_EVENT_DECKS(SColumnUtil.getDecksDefaultColumns(false, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
NET_DECKS(SColumnUtil.getDecksDefaultColumns(false, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
SIDEBOARD(SColumnUtil.getDeckEditorDefaultColumns(), false, false, true,
|
||||
GroupDef.DEFAULT, ColumnDef.CMC, 3, 0);
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ public final class ForgeConstants {
|
||||
public static final String IMAGE_LIST_QUEST_BOOSTERBOXES_FILE = LISTS_DIR + "boosterbox-images.txt";
|
||||
public static final String IMAGE_LIST_QUEST_PRECONS_FILE = LISTS_DIR + "precon-images.txt";
|
||||
public static final String IMAGE_LIST_QUEST_TOURNAMENTPACKS_FILE = LISTS_DIR + "tournamentpack-images.txt";
|
||||
public static final String NET_DECKS_LIST_FILE = LISTS_DIR + "net-decks.txt";
|
||||
public static final String NET_DECKS_COMMANDER_LIST_FILE = LISTS_DIR + "net-decks-commander.txt";
|
||||
|
||||
public static final String CHANGES_FILE = ASSETS_DIR + "CHANGES.txt";
|
||||
public static final String LICENSE_FILE = ASSETS_DIR + "LICENSE.txt";
|
||||
@@ -114,6 +116,7 @@ public final class ForgeConstants {
|
||||
public static final String DECK_SCHEME_DIR = DECK_BASE_DIR + "scheme/";
|
||||
public static final String DECK_PLANE_DIR = DECK_BASE_DIR + "planar/";
|
||||
public static final String DECK_COMMANDER_DIR = DECK_BASE_DIR + "commander/";
|
||||
public static final String DECK_NET_DIR = DECK_BASE_DIR + "net/";
|
||||
public static final String QUEST_SAVE_DIR = USER_QUEST_DIR + "saves/";
|
||||
public static final String CONQUEST_SAVE_DIR = USER_CONQUEST_DIR + "saves/";
|
||||
public static final String MAIN_PREFS_FILE = USER_PREFS_DIR + "forge.preferences";
|
||||
@@ -159,6 +162,8 @@ public final class ForgeConstants {
|
||||
DECK_SEALED_DIR,
|
||||
DECK_SCHEME_DIR,
|
||||
DECK_PLANE_DIR,
|
||||
DECK_COMMANDER_DIR,
|
||||
DECK_NET_DIR,
|
||||
QUEST_SAVE_DIR,
|
||||
CACHE_TOKEN_PICS_DIR,
|
||||
CACHE_ICON_PICS_DIR,
|
||||
|
||||
Reference in New Issue
Block a user