Add Net Decks support

This commit is contained in:
drdev
2015-01-25 05:10:32 +00:00
parent f3a30793c5
commit 30fbe55ac3
25 changed files with 756 additions and 251 deletions

View File

@@ -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);

View File

@@ -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();
}
}

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -7,7 +7,8 @@ public class FEvent {
CHANGE,
ACTIVATE,
SAVE,
DELETE
DELETE,
CLOSE
}
private FDisplayObject source;