Merge remote-tracking branch 'upstream/master'
@@ -981,14 +981,27 @@ public abstract class GameState {
|
||||
spellDef = spellDef.substring(0, spellDef.indexOf("->")).trim();
|
||||
}
|
||||
|
||||
PaperCard pc = StaticData.instance().getCommonCards().getCard(spellDef);
|
||||
Card c = null;
|
||||
|
||||
if (pc == null) {
|
||||
System.err.println("ERROR: Could not find a card with name " + spellDef + " to precast!");
|
||||
return;
|
||||
if (StringUtils.isNumeric(spellDef)) {
|
||||
// Precast from a specific host
|
||||
c = idToCard.get(Integer.parseInt(spellDef));
|
||||
if (c == null) {
|
||||
System.err.println("ERROR: Could not find a card with ID " + spellDef + " to precast!");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Precast from a card by name
|
||||
PaperCard pc = StaticData.instance().getCommonCards().getCard(spellDef);
|
||||
|
||||
if (pc == null) {
|
||||
System.err.println("ERROR: Could not find a card with name " + spellDef + " to precast!");
|
||||
return;
|
||||
}
|
||||
|
||||
c = Card.fromPaperCard(pc, activator);
|
||||
}
|
||||
|
||||
Card c = Card.fromPaperCard(pc, activator);
|
||||
SpellAbility sa = null;
|
||||
|
||||
if (!scriptID.isEmpty()) {
|
||||
|
||||
@@ -274,14 +274,24 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
|
||||
it should also match the Un-set and older alternate art cards
|
||||
like Merseine from FEM (should the editions files ever be updated)
|
||||
*/
|
||||
"(^(?<cnum>[0-9]+.?) )?((?<rarity>[SCURML]) )?(?<name>.*)$"
|
||||
//"(^(?<cnum>[0-9]+.?) )?((?<rarity>[SCURML]) )?(?<name>.*)$"
|
||||
/* Ideally we'd use the named group above, but Android 6 and
|
||||
earlier don't appear to support named groups.
|
||||
So, untill support for those devices is officially dropped,
|
||||
we'll have to suffice with numbered groups.
|
||||
We are looking for:
|
||||
* cnum - grouping #2
|
||||
* rarity - grouping #4
|
||||
* name - grouping #5
|
||||
*/
|
||||
"(^([0-9]+.?) )?(([SCURML]) )?(.*)$"
|
||||
);
|
||||
for(String line : contents.get("cards")) {
|
||||
Matcher matcher = pattern.matcher(line);
|
||||
if (matcher.matches()) {
|
||||
String collectorNumber = matcher.group("cnum");
|
||||
CardRarity r = CardRarity.smartValueOf(matcher.group("rarity"));
|
||||
String cardName = matcher.group("name");
|
||||
String collectorNumber = matcher.group(2);
|
||||
CardRarity r = CardRarity.smartValueOf(matcher.group(4));
|
||||
String cardName = matcher.group(5);
|
||||
CardInSet cis = new CardInSet(cardName, collectorNumber, r);
|
||||
processedCards.add(cis);
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#f0f0f0</color>
|
||||
<color name="ic_launcher_background">#ffffff</color>
|
||||
</resources>
|
||||
@@ -23,6 +23,13 @@ public enum CSubmenuDownloaders implements ICDoc {
|
||||
VSubmenuDownloaders.SINGLETON_INSTANCE.showLicensing();
|
||||
}
|
||||
};
|
||||
private final UiCommand cmdCheckForUpdates = new UiCommand() {
|
||||
@Override
|
||||
public void run() {
|
||||
new AutoUpdater(false).attemptToUpdate();
|
||||
}
|
||||
};
|
||||
|
||||
private final UiCommand cmdPicDownload = new UiCommand() {
|
||||
@Override public void run() {
|
||||
new GuiDownloader(new GuiDownloadPicturesLQ()).show();
|
||||
@@ -84,6 +91,7 @@ public enum CSubmenuDownloaders implements ICDoc {
|
||||
@Override
|
||||
public void initialize() {
|
||||
final VSubmenuDownloaders view = VSubmenuDownloaders.SINGLETON_INSTANCE;
|
||||
view.setCheckForUpdatesCommand(cmdCheckForUpdates);
|
||||
view.setDownloadPicsCommand(cmdPicDownload);
|
||||
view.setDownloadPicsHQCommand(cmdPicDownloadHQ);
|
||||
view.setDownloadSetPicsCommand(cmdSetDownload);
|
||||
|
||||
@@ -3,6 +3,7 @@ package forge.screens.home.settings;
|
||||
import forge.*;
|
||||
import forge.ai.AiProfileUtil;
|
||||
import forge.control.FControl.CloseAction;
|
||||
import forge.download.AutoUpdater;
|
||||
import forge.game.GameLogEntryType;
|
||||
import forge.gui.framework.FScreen;
|
||||
import forge.gui.framework.ICDoc;
|
||||
@@ -225,6 +226,7 @@ public enum CSubmenuPreferences implements ICDoc {
|
||||
initializeGameLogVerbosityComboBox();
|
||||
initializeCloseActionComboBox();
|
||||
initializeDefaultFontSizeComboBox();
|
||||
initializeAutoUpdaterComboBox();
|
||||
initializeMulliganRuleComboBox();
|
||||
initializeAiProfilesComboBox();
|
||||
initializeStackAdditionsComboBox();
|
||||
@@ -378,6 +380,16 @@ public enum CSubmenuPreferences implements ICDoc {
|
||||
panel.setComboBox(comboBox, selectedItem);
|
||||
}
|
||||
|
||||
private void initializeAutoUpdaterComboBox() {
|
||||
// TODO: Ideally we would filter out update paths based on the type of Forge people have
|
||||
final String[] updatePaths = AutoUpdater.updateChannels;
|
||||
final FPref updatePreference = FPref.AUTO_UPDATE;
|
||||
final FComboBoxPanel<String> panel = this.view.getCbpAutoUpdater();
|
||||
final FComboBox<String> comboBox = createComboBox(updatePaths, updatePreference);
|
||||
final String selectedItem = this.prefs.getPref(updatePreference);
|
||||
panel.setComboBox(comboBox, selectedItem);
|
||||
}
|
||||
|
||||
private void initializeMulliganRuleComboBox() {
|
||||
final String [] choices = MulliganDefs.getMulliganRuleNames();
|
||||
final FPref userSetting = FPref.MULLIGAN_RULE;
|
||||
|
||||
@@ -55,6 +55,7 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
||||
private final JPanel pnlContent = new JPanel(new MigLayout("insets 0, gap 0, wrap, ay center"));
|
||||
private final FScrollPane scrContent = new FScrollPane(pnlContent, false);
|
||||
|
||||
private final FLabel btnCheckForUpdates = _makeButton(localizer.getMessage("btnCheckForUpdates"));
|
||||
private final FLabel btnDownloadSetPics = _makeButton(localizer.getMessage("btnDownloadSetPics"));
|
||||
private final FLabel btnDownloadPics = _makeButton(localizer.getMessage("btnDownloadPics"));
|
||||
private final FLabel btnDownloadPicsHQ = _makeButton(localizer.getMessage("btnDownloadPicsHQ"));
|
||||
@@ -80,6 +81,9 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
||||
|
||||
if (javaRecentEnough()) {
|
||||
|
||||
pnlContent.add(btnCheckForUpdates, constraintsBTN);
|
||||
pnlContent.add(_makeLabel(localizer.getMessage("lblCheckForUpdates")), constraintsLBL);
|
||||
|
||||
pnlContent.add(btnDownloadPics, constraintsBTN);
|
||||
pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadPics")), constraintsLBL);
|
||||
|
||||
@@ -162,6 +166,7 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
||||
return EMenuGroup.SETTINGS;
|
||||
}
|
||||
|
||||
public void setCheckForUpdatesCommand(UiCommand command) { btnCheckForUpdates.setCommand(command); }
|
||||
public void setDownloadPicsCommand(UiCommand command) { btnDownloadPics.setCommand(command); }
|
||||
public void setDownloadPicsHQCommand(UiCommand command) { btnDownloadPicsHQ.setCommand(command); }
|
||||
public void setDownloadSetPicsCommand(UiCommand command) { btnDownloadSetPics.setCommand(command); }
|
||||
|
||||
@@ -25,8 +25,8 @@ import java.awt.event.FocusAdapter;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
@@ -123,6 +123,7 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
||||
private final FComboBoxPanel<String> cbpCounterDisplayLocation =new FComboBoxPanel<>(localizer.getMessage("cbpCounterDisplayLocation")+":");
|
||||
private final FComboBoxPanel<String> cbpGraveyardOrdering = new FComboBoxPanel<>(localizer.getMessage("cbpGraveyardOrdering")+":");
|
||||
private final FComboBoxPanel<String> cbpDefaultLanguage = new FComboBoxPanel<>(localizer.getMessage("cbpSelectLanguage")+":");
|
||||
private final FComboBoxPanel<String> cbpAutoUpdater = new FComboBoxPanel<>(localizer.getMessage("cbpAutoUpdater")+":");
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -157,6 +158,10 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
||||
pnlPrefs.add(new SectionLabel(localizer.getMessage("GeneralConfiguration")), sectionConstraints);
|
||||
|
||||
// language
|
||||
|
||||
pnlPrefs.add(cbpAutoUpdater, comboBoxConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlAutoUpdater")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbpDefaultLanguage, comboBoxConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlSelectLanguage")), descriptionConstraints);
|
||||
|
||||
@@ -531,6 +536,10 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
||||
}
|
||||
}
|
||||
|
||||
public final FComboBoxPanel<String> getCbpAutoUpdater() {
|
||||
return cbpAutoUpdater;
|
||||
}
|
||||
|
||||
/** @return {@link javax.swing.JCheckBox} */
|
||||
public final JCheckBox getCbCompactMainMenu() {
|
||||
return cbCompactMainMenu;
|
||||
|
||||
@@ -81,7 +81,7 @@ public final class Main {
|
||||
break;
|
||||
|
||||
default:
|
||||
System.out.println("Unknown mode.\nKnown mode is 'sim' ");
|
||||
System.out.println("Unknown mode.\nKnown mode is 'sim', 'parse' ");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -209,7 +209,7 @@ public class FSkin {
|
||||
textures.put(f6.path(), textures.get(f3.path()));
|
||||
}
|
||||
if (f7.exists()){
|
||||
Texture t = new Texture(f7, false);
|
||||
Texture t = new Texture(f7, true);
|
||||
//t.setFilter(Texture.TextureFilter.MipMapLinearLinear, Texture.TextureFilter.Linear);
|
||||
textures.put(f7.path(), t);
|
||||
}
|
||||
|
||||
@@ -193,6 +193,15 @@ public enum FSkinImage implements FImage {
|
||||
QUEST_BIG_SWORD (FSkinProp.ICO_QUEST_BIG_SWORD, SourceFile.ICONS),
|
||||
QUEST_BIG_BAG (FSkinProp.ICO_QUEST_BIG_BAG, SourceFile.ICONS),
|
||||
|
||||
//menu icon
|
||||
MENU_GALAXY (FSkinProp.ICO_MENU_GALAXY, SourceFile.ICONS),
|
||||
MENU_STATS (FSkinProp.ICO_MENU_STATS, SourceFile.ICONS),
|
||||
MENU_PUZZLE (FSkinProp.ICO_MENU_PUZZLE, SourceFile.ICONS),
|
||||
MENU_GAUNTLET (FSkinProp.ICO_MENU_GAUNTLET, SourceFile.ICONS),
|
||||
MENU_SEALED (FSkinProp.ICO_MENU_SEALED, SourceFile.ICONS),
|
||||
MENU_DRAFT (FSkinProp.ICO_MENU_DRAFT, SourceFile.ICONS),
|
||||
MENU_CONSTRUCTED (FSkinProp.ICO_MENU_CONSTRUCTED, SourceFile.ICONS),
|
||||
|
||||
//Interface icons
|
||||
QUESTION (FSkinProp.ICO_QUESTION, SourceFile.ICONS),
|
||||
INFORMATION (FSkinProp.ICO_INFORMATION, SourceFile.ICONS),
|
||||
|
||||
@@ -20,11 +20,11 @@ import forge.util.Localizer;
|
||||
|
||||
public class LoadGameMenu extends FPopupMenu {
|
||||
public enum LoadGameScreen {
|
||||
BoosterDraft("lblBoosterDraft", FSkinImage.HAND, LoadDraftScreen.class),
|
||||
SealedDeck("lblSealedDeck", FSkinImage.PACK, LoadSealedScreen.class),
|
||||
BoosterDraft("lblBoosterDraft", FSkinImage.MENU_DRAFT, LoadDraftScreen.class),
|
||||
SealedDeck("lblSealedDeck", FSkinImage.MENU_SEALED, LoadSealedScreen.class),
|
||||
QuestMode("lblQuestMode", FSkinImage.QUEST_ZEP, LoadQuestScreen.class),
|
||||
PlanarConquest("lblPlanarConquest", FSkinImage.MULTIVERSE, LoadConquestScreen.class),
|
||||
Gauntlet("lblGauntlet", FSkinImage.ALPHASTRIKE, LoadGauntletScreen.class);
|
||||
PlanarConquest("lblPlanarConquest", FSkinImage.MENU_GALAXY, LoadConquestScreen.class),
|
||||
Gauntlet("lblGauntlet", FSkinImage.MENU_GAUNTLET, LoadGauntletScreen.class);
|
||||
|
||||
private final FMenuItem item;
|
||||
private final Class<? extends FScreen> screenClass;
|
||||
|
||||
@@ -24,13 +24,13 @@ public class NewGameMenu extends FPopupMenu {
|
||||
final static Localizer localizer = Localizer.getInstance();
|
||||
|
||||
public enum NewGameScreen {
|
||||
Constructed(localizer.getMessage("lblConstructed"), FSkinImage.DECKLIST, ConstructedScreen.class),
|
||||
BoosterDraft(localizer.getMessage("lblBoosterDraft"), FSkinImage.HAND, NewDraftScreen.class),
|
||||
SealedDeck(localizer.getMessage("lblSealedDeck"), FSkinImage.PACK, NewSealedScreen.class),
|
||||
Constructed(localizer.getMessage("lblConstructed"), FSkinImage.MENU_CONSTRUCTED, ConstructedScreen.class),
|
||||
BoosterDraft(localizer.getMessage("lblBoosterDraft"), FSkinImage.MENU_DRAFT, NewDraftScreen.class),
|
||||
SealedDeck(localizer.getMessage("lblSealedDeck"), FSkinImage.MENU_SEALED, NewSealedScreen.class),
|
||||
QuestMode(localizer.getMessage("lblQuestMode"), FSkinImage.QUEST_ZEP, NewQuestScreen.class),
|
||||
PuzzleMode(localizer.getMessage("lblPuzzleMode"), FSkinImage.QUEST_BOOK, PuzzleScreen.class),
|
||||
PlanarConquest(localizer.getMessage("lblPlanarConquest"), FSkinImage.MULTIVERSE, NewConquestScreen.class),
|
||||
Gauntlet(localizer.getMessage("lblGauntlet"), FSkinImage.ALPHASTRIKE, NewGauntletScreen.class);
|
||||
PuzzleMode(localizer.getMessage("lblPuzzleMode"), FSkinImage.MENU_PUZZLE, PuzzleScreen.class),
|
||||
PlanarConquest(localizer.getMessage("lblPlanarConquest"), FSkinImage.MENU_GALAXY, NewConquestScreen.class),
|
||||
Gauntlet(localizer.getMessage("lblGauntlet"), FSkinImage.MENU_GAUNTLET, NewGauntletScreen.class);
|
||||
|
||||
private final FMenuItem item;
|
||||
private final Class<? extends FScreen> screenClass;
|
||||
|
||||
@@ -54,43 +54,45 @@ public class PuzzleScreen extends LaunchScreen {
|
||||
final ArrayList<Puzzle> puzzles = PuzzleIO.loadPuzzles();
|
||||
Collections.sort(puzzles);
|
||||
|
||||
GuiChoose.one(Localizer.getInstance().getMessage("lblChooseAPuzzle"), puzzles, new Callback<Puzzle>() {
|
||||
GuiChoose.oneOrNone(Localizer.getInstance().getMessage("lblChooseAPuzzle"), puzzles, new Callback<Puzzle>() {
|
||||
@Override
|
||||
public void run(final Puzzle chosen) {
|
||||
LoadingOverlay.show(Localizer.getInstance().getMessage("lblLoadingThePuzzle"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Load selected puzzle
|
||||
final HostedMatch hostedMatch = GuiBase.getInterface().hostMatch();
|
||||
hostedMatch.setStartGameHook(new Runnable() {
|
||||
@Override
|
||||
public final void run() {
|
||||
chosen.applyToGame(hostedMatch.getGame());
|
||||
}
|
||||
});
|
||||
if (chosen != null) {
|
||||
LoadingOverlay.show(Localizer.getInstance().getMessage("lblLoadingThePuzzle"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Load selected puzzle
|
||||
final HostedMatch hostedMatch = GuiBase.getInterface().hostMatch();
|
||||
hostedMatch.setStartGameHook(new Runnable() {
|
||||
@Override
|
||||
public final void run() {
|
||||
chosen.applyToGame(hostedMatch.getGame());
|
||||
}
|
||||
});
|
||||
|
||||
hostedMatch.setEndGameHook((new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
chosen.savePuzzleSolve(hostedMatch.getGame().getOutcome().isWinner(GamePlayerUtil.getGuiPlayer()));
|
||||
}
|
||||
}));
|
||||
hostedMatch.setEndGameHook((new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
chosen.savePuzzleSolve(hostedMatch.getGame().getOutcome().isWinner(GamePlayerUtil.getGuiPlayer()));
|
||||
}
|
||||
}));
|
||||
|
||||
final List<RegisteredPlayer> players = new ArrayList<>();
|
||||
final RegisteredPlayer human = new RegisteredPlayer(new Deck()).setPlayer(GamePlayerUtil.getGuiPlayer());
|
||||
human.setStartingHand(0);
|
||||
players.add(human);
|
||||
final List<RegisteredPlayer> players = new ArrayList<>();
|
||||
final RegisteredPlayer human = new RegisteredPlayer(new Deck()).setPlayer(GamePlayerUtil.getGuiPlayer());
|
||||
human.setStartingHand(0);
|
||||
players.add(human);
|
||||
|
||||
final RegisteredPlayer ai = new RegisteredPlayer(new Deck()).setPlayer(GamePlayerUtil.createAiPlayer());
|
||||
ai.setStartingHand(0);
|
||||
players.add(ai);
|
||||
final RegisteredPlayer ai = new RegisteredPlayer(new Deck()).setPlayer(GamePlayerUtil.createAiPlayer());
|
||||
ai.setStartingHand(0);
|
||||
players.add(ai);
|
||||
|
||||
GameRules rules = new GameRules(GameType.Puzzle);
|
||||
rules.setGamesPerMatch(1);
|
||||
hostedMatch.startMatch(rules, null, players, human, GuiBase.getInterface().getNewGuiGame());
|
||||
FOptionPane.showMessageDialog(chosen.getGoalDescription(), chosen.getName());
|
||||
}
|
||||
});
|
||||
GameRules rules = new GameRules(GameType.Puzzle);
|
||||
rules.setGamesPerMatch(1);
|
||||
hostedMatch.startMatch(rules, null, players, human, GuiBase.getInterface().getNewGuiGame());
|
||||
FOptionPane.showMessageDialog(chosen.getGoalDescription(), chosen.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ public class ConquestMenu extends FPopupMenu {
|
||||
setCurrentScreen(collectionScreen);
|
||||
}
|
||||
});
|
||||
private static final FMenuItem statsItem = new FMenuItem(Localizer.getInstance().getMessage("lblStatistics"), FSkinImage.HDMULTI, new FEventHandler() {
|
||||
private static final FMenuItem statsItem = new FMenuItem(Localizer.getInstance().getMessage("lblStatistics"), FSkinImage.MENU_STATS, new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
setCurrentScreen(statsScreen);
|
||||
|
||||
@@ -79,7 +79,7 @@ public class QuestMenu extends FPopupMenu implements IVQuestStats {
|
||||
setCurrentScreen(bazaarScreen);
|
||||
}
|
||||
});
|
||||
private static final FMenuItem statsItem = new FMenuItem(Localizer.getInstance().getMessage("lblStatistics"), FSkinImage.HDMULTI, new FEventHandler() {
|
||||
private static final FMenuItem statsItem = new FMenuItem(Localizer.getInstance().getMessage("lblStatistics"), FSkinImage.MENU_STATS, new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
setCurrentScreen(statsScreen);
|
||||
|
||||
@@ -1909,7 +1909,6 @@ Knight of Sorrows
|
||||
Knight of the Skyward Eye
|
||||
Knight of the Tusk
|
||||
Kor Bladewhirl
|
||||
Kor Chant
|
||||
Kor Firewalker
|
||||
Kor Hookmaster
|
||||
Kor Sky Climber
|
||||
@@ -2028,6 +2027,7 @@ Zealous Strike
|
||||
[MB1 Blue CommonUncommon]
|
||||
Academy Journeymage
|
||||
Aethersnipe
|
||||
Aether Spellbomb
|
||||
Aether Tradewinds
|
||||
Amass the Components
|
||||
Amphin Pathmage
|
||||
@@ -2739,7 +2739,6 @@ Tibalt's Rager
|
||||
Torch Courier
|
||||
Uncaged Fury
|
||||
Undying Rage
|
||||
Urza's Rage
|
||||
Valakut Invoker
|
||||
Valakut Predator
|
||||
Valley Dasher
|
||||
@@ -3615,3 +3614,21 @@ Minamo, School at Water's Edge+|FMB1
|
||||
Mirrodin's Core+|FMB1
|
||||
Shizo, Death's Storehouse+|FMB1
|
||||
Stalking Stones+|FMB1
|
||||
|
||||
[CN2 Not In Normal Slots]
|
||||
Adriana's Valor
|
||||
#Assemble the Rank and Vile
|
||||
Echoing Boon
|
||||
#Emissary's Ploy
|
||||
Hired Heist
|
||||
#Hold the Permiter
|
||||
Hymn of the Wilds
|
||||
Incendiary Dissent
|
||||
Natural Unity
|
||||
#Sovereign's Realm
|
||||
#Summoner's Bond
|
||||
Weight Advantage
|
||||
Kaya, Ghost Assassin|CN2|2
|
||||
|
||||
[CN2 Foil Kaya]
|
||||
Kaya, Ghost Assassin|CN2|2
|
||||
|
||||
@@ -6,7 +6,8 @@ Code2=CN2
|
||||
MciCode=cn2
|
||||
Type=Other
|
||||
BoosterCovers=3
|
||||
Booster=10 Common:!fromSheet("CN2 Draft Matters"), 3 Uncommon:!fromSheet("CN2 Draft Matters"), 1 RareMythic:!fromSheet("CN2 Draft Matters"), 1 fromSheet("CN2 Draft Matters")
|
||||
Booster=10 Common:!fromSheet("CN2 Not In Normal Slots"), 3 Uncommon:!fromSheet("CN2 Not In Normal Slots"), 1 RareMythic:!fromSheet("CN2 Not In Normal Slots"), 1 fromSheet("CN2 Draft Matters")
|
||||
AdditionalSheetForFoils=fromSheet("CN2 Foil Kaya")
|
||||
|
||||
[cards]
|
||||
1 C Adriana's Valor
|
||||
@@ -243,4 +244,4 @@ r_1_1_goblin_noblock
|
||||
r_8_8_lizard
|
||||
g_3_3_beast
|
||||
g_1_1_insect
|
||||
c_1_1_a_construct_defender
|
||||
c_1_1_a_construct_defender
|
||||
|
||||
@@ -52,6 +52,8 @@ btnResetJavaFutureCompatibilityWarnings=Reset Java Compatibility Warnings
|
||||
btnClearImageCache=Clear Image Cache
|
||||
btnTokenPreviewer=Token Previewer
|
||||
btnCopyToClipboard=Copy to Clipboard
|
||||
cbpAutoUpdater=Auto updater
|
||||
nlAutoUpdater=Select the release channel to use for updating Forge
|
||||
cbpSelectLanguage=Language
|
||||
nlSelectLanguage=Select Language (Excluded Game part. Still a work in progress) (RESTART REQUIRED)
|
||||
cbRemoveSmall=Remove Small Creatures
|
||||
@@ -182,6 +184,7 @@ KeyboardShortcuts=Keyboard Shortcuts
|
||||
#VSubmenuAchievements.java
|
||||
lblAchievements=Achievements
|
||||
#VSubmenuDownloaders.java
|
||||
btnCheckForUpdates=Check for Updates
|
||||
btnDownloadSetPics=Download LQ Set Pictures
|
||||
btnDownloadPicsHQ=Download HQ Card Pictures (Very Slow!)
|
||||
btnDownloadPics=Download LQ Card Pictures
|
||||
@@ -194,6 +197,7 @@ btnImportPictures=Import Data
|
||||
btnHowToPlay=How To Play
|
||||
btnDownloadPrices=Download Card Prices
|
||||
btnLicensing=License Details
|
||||
lblCheckForUpdates=Check Forge server to see if there's a more recent release
|
||||
lblDownloadPics=Download default card picture for each card.
|
||||
lblDownloadPicsHQ=Download default card HQ picture for each card.
|
||||
lblDownloadSetPics=Download all pictures of each card (one for each set the card appeared in)
|
||||
|
||||
18
forge-gui/res/puzzle/PS_THB6.pzl
Normal file
@@ -0,0 +1,18 @@
|
||||
[metadata]
|
||||
Name:Possibility Storm - Theros Beyond Death #06
|
||||
URL:https://i0.wp.com/www.possibilitystorm.com/wp-content/uploads/2020/02/149.-THB6-1-scaled.jpg
|
||||
Goal:Win
|
||||
Turns:1
|
||||
Difficulty:Uncommon
|
||||
Description:Win this turn. Assume any unknown cards drawn by either player are not relevant to solving the puzzle. Your opponent starts with 13 cards in their library. Your opponent has a Pollenbright Druid on top of their library, and twelve other unknown cards in it.
|
||||
[state]
|
||||
humanlife=20
|
||||
ailife=18
|
||||
turn=1
|
||||
activeplayer=human
|
||||
activephase=MAIN1
|
||||
humanhand=Assassin's Trophy;Unmoored Ego;Applied Biomancy;Underworld Dreams;Tyrant's Scorn
|
||||
humanlibrary=Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt
|
||||
humanbattlefield=Ob Nixilis, the Hate-Twisted|Counters:LOYALTY=2;Nessian Boar;Thief of Sanity;Thief of Sanity;Watery Grave|NoETBTrigs;Watery Grave|NoETBTrigs;Watery Grave|NoETBTrigs;Watery Grave|NoETBTrigs;Breeding Pool|NoETBTrigs;Breeding Pool|NoETBTrigs;Breeding Pool|NoETBTrigs
|
||||
ailibrary=Pollenbright Druid;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt;Opt
|
||||
aibattlefield=Silhana Wayfinder;Silhana Wayfinder;Blightbeetle;Wavebreak Hippocamp
|
||||
17
forge-gui/res/puzzle/PS_THB7.pzl
Normal file
@@ -0,0 +1,17 @@
|
||||
[metadata]
|
||||
Name:Possibility Storm - Theros Beyond Death #07
|
||||
URL:https://i2.wp.com/www.possibilitystorm.com/wp-content/uploads/2020/03/150.-THB7-scaled.jpg
|
||||
Goal:Win
|
||||
Turns:100
|
||||
Difficulty:Mythic
|
||||
Description:It's your OPPONENT'S turn (first main phase), and you need to win before you lose. Can you do it? Your opponent has no cards in hand and no available mana (assume they just tapped out to cast Goblin Assault Team). You control your opponent's Dreadhorde Butcher with The Akroan War's first chapter ability. Assume the puzzle starts with no cards in either player's graveyard.
|
||||
[state]
|
||||
humanlife=3
|
||||
ailife=11
|
||||
turn=1
|
||||
activeplayer=ai
|
||||
activephase=MAIN1
|
||||
humanhand=Lazotep Plating;Slaying Fire;So Tiny;Shock;Gideon's Triumph;Aspect of Manticore
|
||||
humanbattlefield=The Akroan War|Counters:LORE=2|Id:2;Blood Aspirant;Flux Channeler;Naiad of Hidden Coves;Temple of Enlightenment|NoETBTrigs;Temple of Enlightenment|NoETBTrigs;Sacred Foundry|NoETBTrigs;Sacred Foundry|NoETBTrigs
|
||||
aibattlefield=Underworld Dreams;Underworld Dreams;Underworld Dreams;Ferocity of the Wilds;Goblin Assault Team;Temple Thief;Mire Triton;Dreadhorde Butcher|Id:1
|
||||
humanprecast=2:DBGainControl->1
|
||||
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 163 KiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 534 KiB After Width: | Height: | Size: 533 KiB |
@@ -230,6 +230,15 @@ public enum FSkinProp {
|
||||
ICO_QUEST_BIG_SWORD (new int[] {320, 1360, 160, 160}, PropType.ICON),
|
||||
ICO_QUEST_BIG_BAG (new int[] {480, 1360, 160, 160}, PropType.ICON),
|
||||
|
||||
//menu icon
|
||||
ICO_MENU_GALAXY (new int[] {0, 1520, 80, 80}, PropType.ICON),
|
||||
ICO_MENU_STATS (new int[] {80, 1520, 80, 80}, PropType.ICON),
|
||||
ICO_MENU_PUZZLE (new int[] {160, 1520, 80, 80}, PropType.ICON),
|
||||
ICO_MENU_GAUNTLET (new int[] {240, 1520, 80, 80}, PropType.ICON),
|
||||
ICO_MENU_SEALED (new int[] {320, 1520, 80, 80}, PropType.ICON),
|
||||
ICO_MENU_DRAFT (new int[] {400, 1520, 80, 80}, PropType.ICON),
|
||||
ICO_MENU_CONSTRUCTED (new int[] {480, 1520, 80, 80}, PropType.ICON),
|
||||
|
||||
//interface icons
|
||||
ICO_QUESTION (new int[] {560, 800, 32, 32}, PropType.ICON),
|
||||
ICO_INFORMATION (new int[] {592, 800, 32, 32}, PropType.ICON),
|
||||
|
||||
247
forge-gui/src/main/java/forge/download/AutoUpdater.java
Normal file
@@ -0,0 +1,247 @@
|
||||
package forge.download;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import forge.GuiBase;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgePreferences;
|
||||
import forge.util.BuildInfo;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.WaitCallback;
|
||||
import forge.util.gui.SOptionPane;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class AutoUpdater {
|
||||
private final String SNAPSHOT_VERSION_INDEX = "https://snapshots.cardforge.org/";
|
||||
private final String SNAPSHOT_VERSION_URL = "https://snapshots.cardforge.org/version.txt";
|
||||
private final String SNAPSHOT_PACKAGE = "https://snapshots.cardforge.org/latest/";
|
||||
private final String RELEASE_VERSION_URL = "https://releases.cardforge.org/forge/forge-gui-desktop/version.txt";
|
||||
private final String RELEASE_PACKAGE = "https://releases.cardforge.org/latest/";
|
||||
private final String RELEASE_MAVEN_METADATA = "https://releases.cardforge.org/forge/forge-gui-desktop/maven-metadata.xml";
|
||||
private static final boolean VERSION_FROM_METADATA = true;
|
||||
private static final String TMP_DIR = "tmp/";
|
||||
|
||||
public static String[] updateChannels = new String[]{ "none", "snapshot", "release"};
|
||||
|
||||
private boolean isLoading;
|
||||
private String updateChannel;
|
||||
private String version;
|
||||
private String buildVersion;
|
||||
private String versionUrlString;
|
||||
private String packageUrl;
|
||||
private String packagePath;
|
||||
|
||||
public AutoUpdater(boolean loading) {
|
||||
// What do I need? Preferences? Splashscreen? UI? Skins?
|
||||
isLoading = loading;
|
||||
updateChannel = FModel.getPreferences().getPref(ForgePreferences.FPref.AUTO_UPDATE);
|
||||
buildVersion = BuildInfo.getVersionString();
|
||||
}
|
||||
|
||||
public boolean attemptToUpdate() {
|
||||
if (!verifyUpdateable()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
if (downloadUpdate()) {
|
||||
extractAndRestart();
|
||||
}
|
||||
} catch(IOException | URISyntaxException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void extractAndRestart() {
|
||||
extractUpdate();
|
||||
restartForge();
|
||||
}
|
||||
|
||||
private boolean verifyUpdateable() {
|
||||
if (buildVersion.contains("GIT")) {
|
||||
//return false;
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
// TODO This doesn't work yet, because FSkin isn't loaded at the time.
|
||||
return false;
|
||||
} else if (updateChannel.equals("none")) {
|
||||
String message = "You haven't set an update channel. Do you want to check a channel now?";
|
||||
List<String> options = ImmutableList.of("Cancel", "release", "snapshot");
|
||||
int option = SOptionPane.showOptionDialog(message, "Manual Check", null, options, 0);
|
||||
if (option == 0) {
|
||||
return false;
|
||||
} else {
|
||||
updateChannel = options.get(option);
|
||||
}
|
||||
}
|
||||
|
||||
if (buildVersion.contains("SNAPSHOT")) {
|
||||
if (!updateChannel.equals("snapshot")) {
|
||||
System.out.println("Snapshot build versions must use snapshot update channel to work");
|
||||
return false;
|
||||
}
|
||||
|
||||
versionUrlString = SNAPSHOT_VERSION_URL;
|
||||
packageUrl = SNAPSHOT_PACKAGE;
|
||||
} else {
|
||||
versionUrlString = RELEASE_VERSION_URL;
|
||||
packageUrl = RELEASE_PACKAGE;
|
||||
}
|
||||
|
||||
// Check the internet connection
|
||||
if (!testNetConnection()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Download appropriate version file
|
||||
return compareBuildWithLatestChannelVersion();
|
||||
}
|
||||
|
||||
private boolean testNetConnection() {
|
||||
try (Socket socket = new Socket()) {
|
||||
InetSocketAddress address = new InetSocketAddress("releases.cardforge.org", 443);
|
||||
socket.connect(address, 1000);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
return false; // Either timeout or unreachable or failed DNS lookup.
|
||||
}
|
||||
}
|
||||
|
||||
private boolean compareBuildWithLatestChannelVersion() {
|
||||
try {
|
||||
retrieveVersion();
|
||||
|
||||
if (StringUtils.isEmpty(version) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buildVersion.equals(version)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
// If version doesn't match, it's assummably newer.
|
||||
return true;
|
||||
}
|
||||
|
||||
private void retrieveVersion() throws MalformedURLException {
|
||||
if (VERSION_FROM_METADATA) {
|
||||
if (updateChannel.equals("release")) {
|
||||
extractVersionFromMavenRelease();
|
||||
} else {
|
||||
extractVersionFromSnapshotIndex();
|
||||
}
|
||||
} else {
|
||||
URL versionUrl = new URL(versionUrlString);
|
||||
version = FileUtil.readFileToString(versionUrl);
|
||||
}
|
||||
}
|
||||
|
||||
private void extractVersionFromSnapshotIndex() throws MalformedURLException {
|
||||
URL metadataUrl = new URL(SNAPSHOT_VERSION_INDEX);
|
||||
String index = FileUtil.readFileToString(metadataUrl);
|
||||
|
||||
System.out.println(index);
|
||||
Pattern p = Pattern.compile(">forge-(.*SNAPSHOT)");
|
||||
Matcher m = p.matcher(index);
|
||||
while(m.find()){
|
||||
version = m.group(1);
|
||||
}
|
||||
}
|
||||
|
||||
private void extractVersionFromMavenRelease() throws MalformedURLException {
|
||||
URL metadataUrl = new URL(RELEASE_MAVEN_METADATA);
|
||||
String xml = FileUtil.readFileToString(metadataUrl);
|
||||
|
||||
Pattern p = Pattern.compile("<release>(.*)</release>");
|
||||
Matcher m = p.matcher(xml);
|
||||
while(m.find()){
|
||||
version = m.group(1);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean downloadUpdate() throws URISyntaxException, IOException {
|
||||
// TODO Change the "auto" to be more auto.
|
||||
if (isLoading) {
|
||||
// We need to preload enough of a Skins to show a dialog and a button if we're in loading
|
||||
// splashScreen.prepareForDialogs();
|
||||
return downloadFromBrowser();
|
||||
}
|
||||
|
||||
String message = "A new version of Forge is available (" + version + ").\n" +
|
||||
"You are currently on version (" + buildVersion + ").\n\n" +
|
||||
"Would you like to update to the new version now?";
|
||||
|
||||
final List<String> options = ImmutableList.of("Update Now", "Update Later");
|
||||
if (SOptionPane.showOptionDialog(message, "New Version Available", null, options, 0) == 0) {
|
||||
return downloadFromForge();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean downloadFromBrowser() throws URISyntaxException, IOException {
|
||||
final Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
|
||||
if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
|
||||
// Linking directly there will auto download, but won't auto-update
|
||||
desktop.browse(new URI(packageUrl));
|
||||
return true;
|
||||
} else {
|
||||
System.out.println("Download latest version: " + packageUrl);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean downloadFromForge() {
|
||||
WaitCallback<Boolean> callback = new WaitCallback<Boolean>() {
|
||||
@Override
|
||||
public void run() {
|
||||
GuiBase.getInterface().download(new GuiDownloadZipService("Auto Updater", "Download the new version..", packageUrl, "tmp/", null, null) {
|
||||
@Override
|
||||
public void downloadAndUnzip() {
|
||||
packagePath = download(version + "-upgrade.tar.bz2");
|
||||
if (packagePath != null) {
|
||||
extractAndRestart();
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
};
|
||||
|
||||
SwingUtilities.invokeLater(callback);
|
||||
//
|
||||
return false;
|
||||
}
|
||||
|
||||
private void extractUpdate() {
|
||||
// TODOD Something like https://stackoverflow.com/questions/315618/how-do-i-extract-a-tar-file-in-java
|
||||
final Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
|
||||
if (desktop != null) {
|
||||
try {
|
||||
desktop.open(new File(packagePath).getParentFile());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
System.out.println(packagePath);
|
||||
}
|
||||
}
|
||||
|
||||
private void restartForge() {
|
||||
if (isLoading || SOptionPane.showConfirmDialog("Forge has been downloaded. You should extract the package and restart Forge for the new version.", "Exit now?")) {
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,72 +73,7 @@ public class GuiDownloadZipService extends GuiDownloadService {
|
||||
String zipFilename = download("temp.zip");
|
||||
if (zipFilename == null) { return; }
|
||||
|
||||
//if assets.zip downloaded successfully, unzip into destination folder
|
||||
try {
|
||||
GuiBase.getInterface().preventSystemSleep(true); //prevent system from going into sleep mode while unzipping
|
||||
|
||||
if (deleteFolder != null) {
|
||||
final 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
|
||||
final String oldZipFilename = zipFilename;
|
||||
zipFilename = deleteDir.getParentFile().getAbsolutePath() + File.separator + "temp.zip";
|
||||
Files.move(new File(oldZipFilename), new File(zipFilename));
|
||||
}
|
||||
FileUtil.deleteDirectory(deleteDir);
|
||||
}
|
||||
}
|
||||
|
||||
final ZipFile zipFile = new ZipFile(zipFilename);
|
||||
final 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;
|
||||
int failedCount = 0;
|
||||
while (entries.hasMoreElements()) {
|
||||
if (cancel) { break; }
|
||||
|
||||
try {
|
||||
final ZipEntry entry = entries.nextElement();
|
||||
|
||||
final String path = destFolder + File.separator + entry.getName();
|
||||
if (entry.isDirectory()) {
|
||||
new File(path).mkdir();
|
||||
progressBar.setValue(++count);
|
||||
continue;
|
||||
}
|
||||
copyInputStream(zipFile.getInputStream(entry), path);
|
||||
progressBar.setValue(++count);
|
||||
filesExtracted++;
|
||||
}
|
||||
catch (final Exception e) { //don't quit out completely if an entry is not UTF-8
|
||||
progressBar.setValue(++count);
|
||||
failedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (failedCount > 0) {
|
||||
Log.error("Downloading " + desc, failedCount + " " + desc + " could not be extracted");
|
||||
}
|
||||
|
||||
zipFile.close();
|
||||
new File(zipFilename).delete();
|
||||
}
|
||||
catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally {
|
||||
GuiBase.getInterface().preventSystemSleep(false);
|
||||
}
|
||||
extract(zipFilename);
|
||||
}
|
||||
|
||||
public String download(final String filename) {
|
||||
@@ -211,6 +146,75 @@ public class GuiDownloadZipService extends GuiDownloadService {
|
||||
}
|
||||
}
|
||||
|
||||
public void extract(String zipFilename) {
|
||||
//if assets.zip downloaded successfully, unzip into destination folder
|
||||
try {
|
||||
GuiBase.getInterface().preventSystemSleep(true); //prevent system from going into sleep mode while unzipping
|
||||
|
||||
if (deleteFolder != null) {
|
||||
final 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
|
||||
final String oldZipFilename = zipFilename;
|
||||
zipFilename = deleteDir.getParentFile().getAbsolutePath() + File.separator + "temp.zip";
|
||||
Files.move(new File(oldZipFilename), new File(zipFilename));
|
||||
}
|
||||
FileUtil.deleteDirectory(deleteDir);
|
||||
}
|
||||
}
|
||||
|
||||
final ZipFile zipFile = new ZipFile(zipFilename);
|
||||
final 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;
|
||||
int failedCount = 0;
|
||||
while (entries.hasMoreElements()) {
|
||||
if (cancel) { break; }
|
||||
|
||||
try {
|
||||
final ZipEntry entry = entries.nextElement();
|
||||
|
||||
final String path = destFolder + File.separator + entry.getName();
|
||||
if (entry.isDirectory()) {
|
||||
new File(path).mkdir();
|
||||
progressBar.setValue(++count);
|
||||
continue;
|
||||
}
|
||||
copyInputStream(zipFile.getInputStream(entry), path);
|
||||
progressBar.setValue(++count);
|
||||
filesExtracted++;
|
||||
}
|
||||
catch (final Exception e) { //don't quit out completely if an entry is not UTF-8
|
||||
progressBar.setValue(++count);
|
||||
failedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (failedCount > 0) {
|
||||
Log.error("Downloading " + desc, failedCount + " " + desc + " could not be extracted");
|
||||
}
|
||||
|
||||
zipFile.close();
|
||||
new File(zipFilename).delete();
|
||||
}
|
||||
catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally {
|
||||
GuiBase.getInterface().preventSystemSleep(false);
|
||||
}
|
||||
}
|
||||
|
||||
protected void copyInputStream(final InputStream in, final String outPath) throws IOException {
|
||||
final byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
|
||||
@@ -28,6 +28,7 @@ import forge.card.CardType;
|
||||
import forge.deck.CardArchetypeLDAGenerator;
|
||||
import forge.deck.CardRelationMatrixGenerator;
|
||||
import forge.deck.io.DeckPreferences;
|
||||
import forge.download.AutoUpdater;
|
||||
import forge.game.GameFormat;
|
||||
import forge.game.GameType;
|
||||
import forge.game.card.CardUtil;
|
||||
@@ -117,7 +118,6 @@ public final class FModel {
|
||||
|
||||
Localizer.getInstance().initialize(FModel.getPreferences().getPref(FPref.UI_LANGUAGE), ForgeConstants.LANG_DIR);
|
||||
|
||||
//load card database
|
||||
final ProgressObserver progressBarBridge = (progressBar == null) ?
|
||||
ProgressObserver.emptyObserver : new ProgressObserver() {
|
||||
@Override
|
||||
@@ -143,6 +143,11 @@ public final class FModel {
|
||||
}
|
||||
};
|
||||
|
||||
if (new AutoUpdater(true).attemptToUpdate()) {
|
||||
//
|
||||
}
|
||||
|
||||
//load card database
|
||||
final CardStorageReader reader = new CardStorageReader(ForgeConstants.CARD_DATA_DIR, progressBarBridge,
|
||||
FModel.getPreferences().getPrefBoolean(FPref.LOAD_CARD_SCRIPTS_LAZILY));
|
||||
final CardStorageReader tokenReader = new CardStorageReader(ForgeConstants.TOKEN_DATA_DIR, progressBarBridge,
|
||||
@@ -220,8 +225,6 @@ public final class FModel {
|
||||
achievements.put(GameType.Quest, new QuestAchievements());
|
||||
achievements.put(GameType.PlanarConquest, new PlanarConquestAchievements());
|
||||
achievements.put(GameType.Puzzle, new PuzzleAchievements());
|
||||
|
||||
|
||||
|
||||
//preload AI profiles
|
||||
AiProfileUtil.loadAllProfiles(ForgeConstants.AI_PROFILE_DIR);
|
||||
|
||||
@@ -153,6 +153,7 @@ public class ForgePreferences extends PreferencesStore<ForgePreferences.FPref> {
|
||||
//TODO This should be removed after the update that requires Java 8.
|
||||
DISABLE_DISPLAY_JAVA_8_UPDATE_WARNING("false"),
|
||||
|
||||
AUTO_UPDATE("none"),
|
||||
USE_SENTRY("false"), // this controls whether automated bug reporting is done or not
|
||||
|
||||
MATCH_HOT_SEAT_MODE("false"), //this only applies to mobile game
|
||||
|
||||