Merge branch 'master' into 'deprecation-cleanup'

Master

See merge request core-developers/forge!1430
This commit is contained in:
Rob Schnautz
2019-02-28 01:06:47 +00:00
26 changed files with 332 additions and 79 deletions

View File

@@ -121,13 +121,17 @@ The Proguard included with the Android SDK Build-tools is outdated and does not
The Eclipse plug-ins do NOT support building things for Android. They do however allow you to use the debugger so you can still set breakpoints and trace The Eclipse plug-ins do NOT support building things for Android. They do however allow you to use the debugger so you can still set breakpoints and trace
things out. The steps below show how to generate a debug Android build. things out. The steps below show how to generate a debug Android build.
Right-click on the forge-gui-android project. Run as.. > Maven build... 1) Create a Maven build for the forge top-level project. Right-click on the forge project. Run as.. > Maven build...
- On the Main tab, set Goals: clean install
On the Main tab, set Goals: install, Profiles: android-debug 2) Run forge Maven build. If everything built, you should see "BUILD SUCCESS" in the Console View.
On the Environment tab, you may need to define the variable ANDROID_HOME with the value containing the path to your Android SDK installation.
For example, Variable: ANDROID_HOME, Value: Your Android SDK install path here.
You should now be able to "run" the forge-gui-android Maven build. This may take a few minutes. If everything worked, you should see "BUILD SUCCESS" in the Console View. 3) Right-click on the forge-gui-android project. Run as.. > Maven build...
- On the Main tab, set Goals: install, Profiles: android-debug
- On the Environment tab, you may need to define the variable ANDROID_HOME with the value containing the path to your Android SDK installation. For example, Variable: ANDROID_HOME, Value: Your Android SDK install path here.
4) Run the forge-gui-android Maven build. This may take a few minutes. If everything worked, you should see "BUILD SUCCESS" in the Console View.
Assuming you got this far, you should have an Android forge-android-[version].apk in the forge-gui-android/target path. Assuming you got this far, you should have an Android forge-android-[version].apk in the forge-gui-android/target path.
@@ -152,6 +156,17 @@ Assuming the apk is installed, launch it from the device.
In Eclipse, launch the DDMS. Window > Perspective > Open Perspective > Other... > DDMS. You should see the forge app in the list. Highlight the app, click on the green debug button and a In Eclipse, launch the DDMS. Window > Perspective > Open Perspective > Other... > DDMS. You should see the forge app in the list. Highlight the app, click on the green debug button and a
green debug button should appear next to the app's name. You can now set breakpoints and step through the source code. green debug button should appear next to the app's name. You can now set breakpoints and step through the source code.
## Windows / Linux SNAPSHOT build
SNAPSHOT builds can be built via the Maven integration in Eclipse.
1) Create a Maven build for the forge top-level project. Right-click on the forge project. Run as.. > Maven build...
- On the Main tab, set Goals: clean install, set Profiles: windows-linux
2) Run forge Maven build. If everything built, you should see "BUILD SUCCESS" in the Console View.
The resulting snapshot will be found at: forge-gui-desktop/target/forge-gui-desktop-1.6.22-SNAPSHOT
# IntelliJ # IntelliJ
TBD TBD

View File

@@ -72,6 +72,12 @@ public class StaticAbilityCantBeCast {
return false; return false;
} }
if (params.containsKey("cmcGT") && (activator != null)
&& (card.getCMC() <= CardLists.getType(activator.getCardsIn(ZoneType.Battlefield),
params.get("cmcGT")).size())) {
return false;
}
if (params.containsKey("NumLimitEachTurn") && activator != null) { if (params.containsKey("NumLimitEachTurn") && activator != null) {
int limit = Integer.parseInt(params.get("NumLimitEachTurn")); int limit = Integer.parseInt(params.get("NumLimitEachTurn"));
String valid = params.containsKey("ValidCard") ? params.get("ValidCard") : "Card"; String valid = params.containsKey("ValidCard") ? params.get("ValidCard") : "Card";

View File

@@ -113,7 +113,8 @@ public class TriggerChangesZone extends Trigger {
} }
// if it is a die trigger, and the hostcard is the moved one, but it doesn't has the trigger // if it is a die trigger, and the hostcard is the moved one, but it doesn't has the trigger
if (leavesBattlefield && moved.equals(getHostCard()) && !moved.hasTrigger(this)) { // only for non-static
if (!isStatic() && leavesBattlefield && moved.equals(getHostCard()) && !moved.hasTrigger(this)) {
return false; return false;
} }
} }

View File

@@ -17,6 +17,24 @@
*/ */
package forge; package forge;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader.InvalidCacheLoadException;
import com.google.common.cache.LoadingCache;
import com.mortennobel.imagescaling.ResampleOp;
import forge.assets.FSkinProp;
import forge.game.card.CardView;
import forge.game.player.PlayerView;
import forge.item.InventoryItem;
import forge.model.FModel;
import forge.properties.ForgeConstants;
import forge.properties.ForgePreferences;
import forge.properties.ForgePreferences.FPref;
import forge.toolbox.FSkin;
import forge.toolbox.FSkin.SkinIcon;
import forge.util.ImageUtil;
import org.apache.commons.lang3.StringUtils;
import javax.imageio.ImageIO;
import java.awt.*; import java.awt.*;
import java.awt.geom.RoundRectangle2D; import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
@@ -24,27 +42,7 @@ import java.io.File;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import javax.imageio.ImageIO;
import forge.properties.ForgePreferences;
import org.apache.commons.lang3.StringUtils;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader.InvalidCacheLoadException;
import com.google.common.cache.LoadingCache;
import com.mortennobel.imagescaling.ResampleOp;
import forge.assets.FSkinProp;
import forge.game.card.CardView;
import forge.game.player.PlayerView;
import forge.item.InventoryItem;
import forge.model.FModel;
import forge.properties.ForgeConstants;
import forge.properties.ForgePreferences.FPref;
import forge.toolbox.FSkin;
import forge.toolbox.FSkin.SkinIcon;
import forge.util.ImageUtil;
/** /**
* This class stores ALL card images in a cache with soft values. this means * This class stores ALL card images in a cache with soft values. this means
@@ -64,7 +62,10 @@ public class ImageCache {
// short prefixes to save memory // short prefixes to save memory
private static final Set<String> _missingIconKeys = new HashSet<String>(); private static final Set<String> _missingIconKeys = new HashSet<String>();
private static final LoadingCache<String, BufferedImage> _CACHE = CacheBuilder.newBuilder().softValues().build(new ImageLoader()); private static final LoadingCache<String, BufferedImage> _CACHE = CacheBuilder.newBuilder()
.maximumSize(FModel.getPreferences().getPrefInt((FPref.UI_IMAGE_CACHE_MAXIMUM)))
.expireAfterAccess(15, TimeUnit.MINUTES)
.build(new ImageLoader());
private static final BufferedImage _defaultImage; private static final BufferedImage _defaultImage;
static { static {
BufferedImage defImage = null; BufferedImage defImage = null;

View File

@@ -95,18 +95,17 @@ public class CardManager extends ItemManager<PaperCard> {
GuiUtils.addMenuItem(menu, "Formats...", null, new Runnable() { GuiUtils.addMenuItem(menu, "Formats...", null, new Runnable() {
@Override public void run() { @Override public void run() {
final CardSetFilter existingFilter = itemManager.getFilter(CardSetFilter.class); final CardFormatFilter existingFilter = itemManager.getFilter(CardFormatFilter.class);
if (existingFilter != null) { if (existingFilter != null) {
existingFilter.edit(); existingFilter.edit(itemManager);
} else { } else {
final DialogChooseFormats dialog = new DialogChooseFormats(); final DialogChooseFormats dialog = new DialogChooseFormats();
dialog.setWantReprintsCB(true); // assume user wants things permissive...
dialog.setOkCallback(new Runnable() { dialog.setOkCallback(new Runnable() {
@Override public void run() { @Override public void run() {
final List<GameFormat> formats = dialog.getSelectedFormats(); final List<GameFormat> formats = dialog.getSelectedFormats();
if (!formats.isEmpty()) { if (!formats.isEmpty()) {
for(GameFormat format: formats) { itemManager.addFilter(new CardFormatFilter(itemManager,formats,dialog.getWantReprints()));
itemManager.addFilter(new CardFormatFilter(itemManager, format));
}
} }
} }
}); });
@@ -119,7 +118,7 @@ public class CardManager extends ItemManager<PaperCard> {
public void run() { public void run() {
CardSetFilter existingFilter = itemManager.getFilter(CardSetFilter.class); CardSetFilter existingFilter = itemManager.getFilter(CardSetFilter.class);
if (existingFilter != null) { if (existingFilter != null) {
existingFilter.edit(); existingFilter.edit(itemManager);
} }
else { else {
final DialogChooseSets dialog = new DialogChooseSets(null, null, true); final DialogChooseSets dialog = new DialogChooseSets(null, null, true);

View File

@@ -250,7 +250,7 @@ public abstract class ItemManager<T extends InventoryItem> extends JPanel implem
if (hideFilters) { if (hideFilters) {
GuiUtils.addMenuItem(menu, "Show Filters", null, cmdHideFilters); GuiUtils.addMenuItem(menu, "Show Filters", null, cmdHideFilters);
} else { } else {
final JMenu addMenu = GuiUtils.createMenu("Add Filter"); final JMenu addMenu = GuiUtils.createMenu("Add/Edit Filter");
GuiUtils.addMenuItem(addMenu, "Current text search", GuiUtils.addMenuItem(addMenu, "Current text search",
KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
cmdAddCurrentSearch, !mainSearchFilter.isEmpty()); cmdAddCurrentSearch, !mainSearchFilter.isEmpty());

View File

@@ -1,21 +1,29 @@
package forge.itemmanager.filters; package forge.itemmanager.filters;
import java.util.List;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import forge.game.GameFormat; import forge.game.GameFormat;
import forge.item.PaperCard; import forge.item.PaperCard;
import forge.itemmanager.ItemManager; import forge.itemmanager.ItemManager;
import forge.itemmanager.SFilterUtil; import forge.itemmanager.SFilterUtil;
import forge.screens.home.quest.DialogChooseFormats;
public class CardFormatFilter extends FormatFilter<PaperCard> { public class CardFormatFilter extends FormatFilter<PaperCard> {
public CardFormatFilter(ItemManager<? super PaperCard> itemManager0) { public CardFormatFilter(ItemManager<? super PaperCard> itemManager0) {
super(itemManager0); super(itemManager0);
} }
public CardFormatFilter(ItemManager<? super PaperCard> itemManager0, GameFormat format0) { public CardFormatFilter(ItemManager<? super PaperCard> itemManager0, GameFormat format0) {
super(itemManager0, format0); super(itemManager0, format0);
} }
public CardFormatFilter(ItemManager<? super PaperCard> itemManager0, List<GameFormat> formats0,boolean allowReprints0) {
super(itemManager0);
this.formats.addAll(formats0);
this.allowReprints = allowReprints0;
}
@Override @Override
public ItemFilter<PaperCard> createCopy() { public ItemFilter<PaperCard> createCopy() {
CardFormatFilter copy = new CardFormatFilter(itemManager); CardFormatFilter copy = new CardFormatFilter(itemManager);
@@ -27,4 +35,20 @@ public class CardFormatFilter extends FormatFilter<PaperCard> {
protected final Predicate<PaperCard> buildPredicate() { protected final Predicate<PaperCard> buildPredicate() {
return SFilterUtil.buildFormatFilter(this.formats, this.allowReprints); return SFilterUtil.buildFormatFilter(this.formats, this.allowReprints);
} }
public void edit(final ItemManager<? super PaperCard> itemManager) {
final DialogChooseFormats dialog = new DialogChooseFormats(this.formats);
final CardFormatFilter itemFilter = this;
dialog.setWantReprintsCB(allowReprints);
dialog.setOkCallback(new Runnable() {
@Override
public void run() {
formats.clear();
formats.addAll(dialog.getSelectedFormats());
allowReprints = dialog.getWantReprints();
itemManager.addFilter(itemFilter); // this adds/updates the current filter...
}
});
}
} }

View File

@@ -49,16 +49,18 @@ public class CardSetFilter extends CardFormatFilter {
return true; return true;
} }
public void edit() { public void edit(final ItemManager<? super PaperCard> itemManager) {
final DialogChooseSets dialog = new DialogChooseSets(this.sets, null, true); final DialogChooseSets dialog = new DialogChooseSets(this.sets, null, true);
final CardSetFilter itemFilter = this;
dialog.setWantReprintsCB(allowReprints);
dialog.setOkCallback(new Runnable() { dialog.setOkCallback(new Runnable() {
@Override @Override
public void run() { public void run() {
sets.clear(); sets.clear();
sets.addAll(dialog.getSelectedSets()); sets.addAll(dialog.getSelectedSets());
allowReprints = dialog.getWantReprints(); allowReprints = dialog.getWantReprints();
formats.clear(); itemManager.addFilter(itemFilter); // this adds/updates the current filter
formats.add(new GameFormat(null, sets, null));
} }
}); });
} }

View File

@@ -116,6 +116,10 @@ public class DialogChooseFormats {
return wantReprints; return wantReprints;
} }
public void setWantReprintsCB(boolean isSet) {
cbWantReprints.setSelected(isSet);
}
private JPanel makeCheckBoxList(List<FCheckBox> formats, String title, boolean focused) { private JPanel makeCheckBoxList(List<FCheckBox> formats, String title, boolean focused) {
choices.addAll(formats); choices.addAll(formats);

View File

@@ -24,7 +24,7 @@ public class DialogChooseSets {
private Runnable okCallback; private Runnable okCallback;
private final List<FCheckBox> choices = new ArrayList<>(); private final List<FCheckBox> choices = new ArrayList<>();
private final FCheckBox cbWantReprints = new FCheckBox("Allow compatible reprints from other sets"); private final FCheckBox cbWantReprints = new FCheckBox("Display compatible reprints from more recent sets");
// lists are of set codes (e.g. "2ED") // lists are of set codes (e.g. "2ED")
public DialogChooseSets(Collection<String> preselectedSets, Collection<String> unselectableSets, boolean showWantReprintsCheckbox) { public DialogChooseSets(Collection<String> preselectedSets, Collection<String> unselectableSets, boolean showWantReprintsCheckbox) {
@@ -129,6 +129,10 @@ public class DialogChooseSets {
public boolean getWantReprints() { public boolean getWantReprints() {
return wantReprints; return wantReprints;
} }
public void setWantReprintsCB(boolean isSet) {
cbWantReprints.setSelected(isSet);
}
private JPanel makeCheckBoxList(List<FCheckBox> sets, String title, boolean focused) { private JPanel makeCheckBoxList(List<FCheckBox> sets, String title, boolean focused) {

View File

@@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment; import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment;
import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Rectangle;
@@ -220,11 +221,24 @@ public class CardZoom extends FOverlay {
float maxCardHeight = h - 2 * messageHeight; float maxCardHeight = h - 2 * messageHeight;
float cardWidth, cardHeight, y; float cardWidth, cardHeight, y;
if (oneCardView && !Forge.isLandscapeMode()) { if (oneCardView && !Forge.isLandscapeMode()) {
cardWidth = w; cardWidth = w;
cardHeight = FCardPanel.ASPECT_RATIO * cardWidth; cardHeight = FCardPanel.ASPECT_RATIO * cardWidth;
boolean rotateSplit = FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_ROTATE_SPLIT_CARDS);
if (currentCard.isSplitCard() && rotateSplit) {
// card will be rotated. Make sure that the height does not exceed the width of the view
if (cardHeight > Gdx.graphics.getWidth())
{
cardHeight = Gdx.graphics.getWidth();
cardWidth = cardHeight / FCardPanel.ASPECT_RATIO;
}
}
} }
else { else {
cardWidth = w * 0.5f; cardWidth = w * 0.5f;
cardHeight = FCardPanel.ASPECT_RATIO * cardWidth; cardHeight = FCardPanel.ASPECT_RATIO * cardWidth;
@@ -240,7 +254,7 @@ public class CardZoom extends FOverlay {
if (nextCard != null) { if (nextCard != null) {
CardImageRenderer.drawZoom(g, nextCard, gameView, false, w - cardWidth, y, cardWidth, cardHeight, getWidth(), getHeight(), false); CardImageRenderer.drawZoom(g, nextCard, gameView, false, w - cardWidth, y, cardWidth, cardHeight, getWidth(), getHeight(), false);
} }
cardWidth = w * 0.7f; cardWidth = w * 0.7f;
cardHeight = FCardPanel.ASPECT_RATIO * cardWidth; cardHeight = FCardPanel.ASPECT_RATIO * cardWidth;
} }

View File

@@ -2,6 +2,6 @@ Name:Keeper of the Lens
ManaCost:1 ManaCost:1
Types:Artifact Creature Golem Types:Artifact Creature Golem
PT:1/2 PT:1/2
S:Mode$ Continuous | Affected$ Creature.faceDown+YouDontCtrl | AffectedZone$ Battlefield | MayLookAt$ You | Description$ You may look at face-down creatures you don't control. S:Mode$ Continuous | Affected$ Creature.faceDown+YouDontCtrl | AffectedZone$ Battlefield | MayLookAt$ You | Description$ You may look at face-down creatures you don't control any time.
SVar:Picture:http://www.wizards.com/global/images/magic/general/keeper_of_the_lens.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/keeper_of_the_lens.jpg
Oracle:You may look at face-down creatures you don't control. (You may do this at any time.) Oracle:You may look at face-down creatures you don't control any time.

View File

@@ -2,8 +2,7 @@ Name:Lavinia, Azorius Renegade
ManaCost:W U ManaCost:W U
Types:Legendary Creature Human Soldier Types:Legendary Creature Human Soldier
PT:2/2 PT:2/2
S:Mode$ CantBeCast | ValidCard$ Card.nonCreature+nonLand+cmcGTX | Caster$ Opponent | Description$ Each opponent can't cast noncreature spells with converted mana cost greater than the number of lands that player controls. S:Mode$ CantBeCast | ValidCard$ Card.nonCreature+nonLand | Caster$ Opponent | cmcGT$ Land | Description$ Each opponent can't cast noncreature spells with converted mana cost greater than the number of lands that player controls.
SVar:X:Count$Valid Land.OppCtrl
T:Mode$ SpellCast | ValidCard$ Card | ValidActivatingPlayer$ Opponent | TriggerZones$ Battlefield | Execute$ TrigCounter | ManaSpent$ EQ0 | TriggerDescription$ Whenever an opponent casts a spell, if no mana was spent to cast it, counter that spell. T:Mode$ SpellCast | ValidCard$ Card | ValidActivatingPlayer$ Opponent | TriggerZones$ Battlefield | Execute$ TrigCounter | ManaSpent$ EQ0 | TriggerDescription$ Whenever an opponent casts a spell, if no mana was spent to cast it, counter that spell.
SVar:TrigCounter:DB$ Counter | Defined$ TriggeredSpellAbility SVar:TrigCounter:DB$ Counter | Defined$ TriggeredSpellAbility
SVar:RemRandomDeck:True SVar:RemRandomDeck:True

View File

@@ -1,8 +1,8 @@
Name:Lens of Clarity Name:Lens of Clarity
ManaCost:1 ManaCost:1
Types:Artifact Types:Artifact
S:Mode$ Continuous | Affected$ Card.TopLibrary+YouCtrl,Creature.faceDown+YouDontCtrl | AffectedZone$ Library,Battlefield | MayLookAt$ You | Description$ You may look at the top card of your library and at face-down creatures you don't control. S:Mode$ Continuous | Affected$ Card.TopLibrary+YouCtrl,Creature.faceDown+YouDontCtrl | AffectedZone$ Library,Battlefield | MayLookAt$ You | Description$ You may look at the top card of your library and at face-down creatures you don't control any time.
AI:RemoveDeck:All AI:RemoveDeck:All
AI:RemoveDeck:Random AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/lens_of_clarity.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/lens_of_clarity.jpg
Oracle:You may look at the top card of your library and at face-down creatures you don't control. (You may do this at any time.) Oracle:You may look at the top card of your library and at face-down creatures you don't control any time.

View File

@@ -1,7 +1,7 @@
Name:Precognition Field Name:Precognition Field
ManaCost:3 U ManaCost:3 U
Types:Enchantment Types:Enchantment
S:Mode$ Continuous | Affected$ Card.TopLibrary+YouCtrl | AffectedZone$ Library | MayLookAt$ You | Description$ You may look at the top card of your library. (You may do this at any time.) S:Mode$ Continuous | Affected$ Card.TopLibrary+YouCtrl | AffectedZone$ Library | MayLookAt$ You | Description$ You may look at the top card of your library any time.
S:Mode$ Continuous | Affected$ Instant.TopLibrary+YouCtrl+nonLand,Sorcery.TopLibrary+YouCtrl+nonLand | AffectedZone$ Library | MayPlay$ True | Description$ You may cast the top card of your library if it's an instant or sorcery card. S:Mode$ Continuous | Affected$ Instant.TopLibrary+YouCtrl+nonLand,Sorcery.TopLibrary+YouCtrl+nonLand | AffectedZone$ Library | MayPlay$ True | Description$ You may cast the top card of your library if it's an instant or sorcery card.
A:AB$ Mill | Cost$ 3 | Defined$ You | NumCards$ 1 | Destination$ Exile | SpellDescription$ Exile the top card of your library. A:AB$ Mill | Cost$ 3 | Defined$ You | NumCards$ 1 | Destination$ Exile | SpellDescription$ Exile the top card of your library.
Oracle:You may look at the top card of your library. (You may do this at any time.)\nYou may cast the top card of your library if it's an instant or sorcery card.\n{3}: Exile the top card of your library. Oracle:You may look at the top card of your librar any time.\nYou may cast the top card of your library if it's an instant or sorcery card.\n{3}: Exile the top card of your library.

View File

@@ -9,4 +9,4 @@ AI:RemoveDeck:Random
SVar:AttachAi:AITgts$ Creature.Green SVar:AttachAi:AITgts$ Creature.Green
DeckNeeds:Color$Green DeckNeeds:Color$Green
SVar:Picture:http://www.wizards.com/global/images/magic/general/ring_of_kalonia.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/ring_of_kalonia.jpg
Oracle:Equipped creature has trample. (If it would assign enough damage to its blockers to destroy them, you may have it assign the rest of its damage to the player or planeswalker it's attacking.)\nAt the beginning of your upkeep, put a +1/+1 counter on equipped creature if it's green.\nEquip {1} ({1}: Attach to target creature you control. Equip only as a sorcery.) Oracle:Equipped creature has trample. (It can deal excess combat damage to the player or planeswalker its attacking.)\nAt the beginning of your upkeep, put a +1/+1 counter on equipped creature if it's green.\nEquip {1} ({1}: Attach to target creature you control. Equip only as a sorcery.)

View File

@@ -4,6 +4,6 @@ Types:Creature Sphinx
PT:5/5 PT:5/5
K:Flying K:Flying
K:Shroud K:Shroud
S:Mode$ Continuous | Affected$ Card.TopLibrary+YouCtrl | AffectedZone$ Library | MayLookAt$ You | Description$ You may look at the top card of your library. S:Mode$ Continuous | Affected$ Card.TopLibrary+YouCtrl | AffectedZone$ Library | MayLookAt$ You | Description$ You may look at the top card of your library any time.
SVar:Picture:http://www.wizards.com/global/images/magic/general/sphinx_of_jwar_isle.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/sphinx_of_jwar_isle.jpg
Oracle:Flying\nShroud (This creature can't be the target of spells or abilities.)\nYou may look at the top card of your library. (You may do this at any time.) Oracle:Flying\nShroud (This creature can't be the target of spells or abilities.)\nYou may look at the top card of your library any time.

View File

@@ -2,7 +2,7 @@ Name:Vizier of the Menagerie
ManaCost:3 G ManaCost:3 G
Types:Creature Naga Cleric Types:Creature Naga Cleric
PT:3/4 PT:3/4
S:Mode$ Continuous | Affected$ Card.TopLibrary+YouCtrl | AffectedZone$ Library | MayLookAt$ You | Description$ You may look at the top card of your library. (You may do this at any time.) S:Mode$ Continuous | Affected$ Card.TopLibrary+YouCtrl | AffectedZone$ Library | MayLookAt$ You | Description$ You may look at the top card of your library any time.
S:Mode$ Continuous | Affected$ Creature.TopLibrary+YouCtrl+nonLand | AffectedZone$ Library | MayPlay$ True | Description$ You may cast the top card of your library if it's a creature card. S:Mode$ Continuous | Affected$ Creature.TopLibrary+YouCtrl+nonLand | AffectedZone$ Library | MayPlay$ True | Description$ You may cast the top card of your library if it's a creature card.
S:Mode$ Continuous | AddHiddenKeyword$ May spend mana as though it were mana of any type to cast CARDNAME | Affected$ Card.Creature+nonLand | AffectedZone$ Library,Hand,Graveyard,Exile | Description$ You may spend mana as though it were mana of any type to cast creature spells. S:Mode$ Continuous | AddHiddenKeyword$ May spend mana as though it were mana of any type to cast CARDNAME | Affected$ Card.Creature+nonLand | AffectedZone$ Library,Hand,Graveyard,Exile | Description$ You may spend mana as though it were mana of any type to cast creature spells.
Oracle:You may look at the top card of your library. (You may do this at any time.)\nYou may cast the top card of your library if it's a creature card.\nYou may spend mana as though it were mana of any type to cast creature spells. Oracle:You may look at the top card of your library any time.\nYou may cast the top card of your library if it's a creature card.\nYou may spend mana as though it were mana of any type to cast creature spells.

View File

@@ -8,4 +8,4 @@ SVar:TrigWarp:DB$ Phases | UnlessCost$ 2 G U | UnlessPayer$ You | Defined$ Self
T:Mode$ PhaseIn | ValidCard$ Card.Self | Execute$ TrigBuff | TriggerDescription$ Whenever CARDNAME phases in, put a +1/+1 counter on it. T:Mode$ PhaseIn | ValidCard$ Card.Self | Execute$ TrigBuff | TriggerDescription$ Whenever CARDNAME phases in, put a +1/+1 counter on it.
SVar:TrigBuff:DB$ PutCounter | Defined$ Valid Card.Self | CounterType$ P1P1 | CounterNum$ 1 SVar:TrigBuff:DB$ PutCounter | Defined$ Valid Card.Self | CounterType$ P1P1 | CounterNum$ 1
SVar:Picture:http://www.wizards.com/global/images/magic/general/warping_wurm.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/warping_wurm.jpg
Oracle:Phasing (This phases in or out before you untap during each of your untap steps. While it's phased out, it's treated as though it doesn't exist.)\nAt the beginning of your upkeep, Warping Wurm phases out unless you pay {2}{G}{U}.\nWhen Warping Wurm phases in, put a +1/+1 counter on it. Oracle:Phasing (This phases in or out before you untap during each of your untap steps. While it's phased out, it's treated as though it doesn't exist.)\nAt the beginning of your upkeep, Warping Wurm phases out unless you pay {2}{G}{U}.\nWhenever Warping Wurm phases in, put a +1/+1 counter on it.

View File

@@ -0,0 +1,153 @@
[metadata]
Code=GK2
Date=2018-02-15
Name=Ravnica Allegiance Guild Kit
MciCode=gk2
Type=Other
[cards]
1 M Isperia, Supreme Judge
2 U Azorius Herald
3 U Azorius Justiciar
4 U Stoic Ephemera
5 U Court Hussar
6 U Hover Barrier
7 R Archon of the Triumvirate
8 U Azorius Charm
9 U Azorius Guildmage
10 R Detention Sphere
11 R Dovescape
12 C Dramatic Rescue
13 R Isperia the Inscrutable
14 U Judge's Familiar
15 R Lavinia of the Tenth
16 U Lyev Skyknight
17 R Pride of the Clouds
18 R Render Silent
19 U Sky Hussar
20 U Skymark Roc
21 M Sphinx's Revelation
22 R Windreaver
23 U Azorius Keyrune
24 U Azorius Signet
25 U Azorius Chancery
26 L Plains
27 L Island
28 R Teysa, Orzhov Scion
29 U Belfry Spirit
30 U Martyred Rusalka
31 U Keening Banshee
32 U Plagued Rusalka
33 R Pontiff of Blight
34 R Skeletal Vampire
35 U Stab Wound
36 U Ultimate Price
37 R Angel of Despair
38 M Deathpact Angel
39 R Debtors' Knell
40 R Ghost Council of Orzhova
41 U One Thousand Lashes
42 U Orzhov Charm
43 R Orzhov Pontiff
44 U Pillory of the Sleepless
45 U Sin Collector
46 R Treasury Thrull
47 U Vizkopa Guildmage
48 C Orzhov Signet
49 C Orzhov Basilica
50 L Plains
51 L Swamp
52 M Rakdos, Lord of Riots
53 U Crypt Champion
54 U Thrill-Kill Assassin
55 C Cackling Flames
56 R Demonfire
57 R Rakdos Pit Dragon
58 C Splatter Thug
59 M Utvara Hellkite
60 C Auger Spree
61 R Avatar of Discord
62 R Carnival Hellsteed
63 R Dreadbore
64 U Jagged Poppet
65 R Lyzolda, the Blood Witch
66 M Master of Cruelties
67 U Rakdos Cackler
68 U Rakdos Charm
69 U Rakdos Guildmage
70 C Rakdos Shred-Freak
71 R Rakdos the Defiler
72 M Rakdos's Return
73 C Riot Spikes
74 C Wrecking Ball
75 U Rakdos Keyrune
76 U Rakdos Signet
77 C Rakdos Carnarium
78 L Swamp
79 L Mountain
80 R Ruric Thar, the Unbowed
81 R Skarrgan Firebird
82 R Birds of Paradise
83 R Protean Hulk
84 C Skarrgan Pit-Skulk
85 U Wasteland Viper
86 R Wurmweaver Coil
87 R Borborygmos
88 U Burning-Tree Emissary
89 R Burning-Tree Shaman
90 U Ghor-Clan Rampager
91 R Giant Solifuge
92 U Gruul Charm
93 C Pit Fight
94 R Rubblebelt Raiders
95 R Rubblehulk
96 R Rumbling Slum
97 U Savage Twister
98 M Savageborn Hydra
99 C Scab-Clan Mauler
100 R Ulasht, the Hate Seed
101 C Zhur-Taa Druid
102 C Zhur-Taa Swine
103 U Gruul Signet
104 C Gruul Turf
105 L Mountain
106 L Forest
107 R Zegana, Utopian Speaker
108 C Cloudfin Raptor
109 U Rapid Hybridization
110 R Cytoplast Root-Kin
111 U Experiment One
112 R Gyre Sage
113 C Miming Slime
114 R Vinelasher Kudzu
115 C Coiling Oracle
116 U Elusive Krasis
117 R Experiment Kraj
118 R Fathom Mage
119 R Momir Vig, Simic Visionary
120 U Nimbus Swimmer
121 R Omnibian
122 U Plaxcaster Frogling
123 M Progenitor Mimic
124 R Simic Sky Swallower
125 U Trygon Predator
126 U Urban Evolution
127 R Voidslime
128 R Vorel of the Hull Clade
129 U Zameck Guildmage
130 U Simic Signet
131 U Simic Growth Chamber
132 L Island
133 L Forest
[tokens]
w_1_1_spirit_flying
b_1_1_bat_flying
r_6_6_dragon_flying
r_2_1_goblin_haste
g_3_3_frog_lizard
g_x_x_ooze
g_1_1_saproling
g_6_6_wurm
wu_1_1_bird_flying
wb_1_1_cleric_deathpact

View File

@@ -242,7 +242,7 @@ https://downloads.cardforge.org/images/icons/Einstein.jpg
https://downloads.cardforge.org/images/icons/Ekolo.jpg https://downloads.cardforge.org/images/icons/Ekolo.jpg
https://downloads.cardforge.org/images/icons/Elashub.jpg https://downloads.cardforge.org/images/icons/Elashub.jpg
https://downloads.cardforge.org/images/icons/Eldrazi.jpg https://downloads.cardforge.org/images/icons/Eldrazi.jpg
https://downloads.cardforge.org/images/icons/Eldritch Onslaught.jpg https://downloads.cardforge.org/images/icons/Eldritch%20Onslaught.jpg
https://downloads.cardforge.org/images/icons/Electro.jpg https://downloads.cardforge.org/images/icons/Electro.jpg
https://downloads.cardforge.org/images/icons/Elegua.jpg https://downloads.cardforge.org/images/icons/Elegua.jpg
https://downloads.cardforge.org/images/icons/Elementalist.jpg https://downloads.cardforge.org/images/icons/Elementalist.jpg

View File

@@ -268,7 +268,6 @@ rg_1_1_goblin_warrior.jpg https://downloads.cardforge.org/images/to
rg_2_2_satyr.jpg https://downloads.cardforge.org/images/tokens/rg_2_2_satyr.jpg rg_2_2_satyr.jpg https://downloads.cardforge.org/images/tokens/rg_2_2_satyr.jpg
rg_3_4_stangg_twin.jpg https://downloads.cardforge.org/images/tokens/rg_3_4_stangg_twin.jpg rg_3_4_stangg_twin.jpg https://downloads.cardforge.org/images/tokens/rg_3_4_stangg_twin.jpg
rg_4_4_giant_warrior.jpg https://downloads.cardforge.org/images/tokens/rg_4_4_giant_warrior.jpg rg_4_4_giant_warrior.jpg https://downloads.cardforge.org/images/tokens/rg_4_4_giant_warrior.jpg
rg_4_4_beast_trample_rna.jpg https://downloads.cardforge.org/images/tokens/rg_4_4_beast_trample.jpg
rg_5_5_elemental.jpg https://downloads.cardforge.org/images/tokens/rg_5_5_elemental.jpg rg_5_5_elemental.jpg https://downloads.cardforge.org/images/tokens/rg_5_5_elemental.jpg
rw_1_1_goblin_soldier.jpg https://downloads.cardforge.org/images/tokens/rw_1_1_goblin_soldier.jpg rw_1_1_goblin_soldier.jpg https://downloads.cardforge.org/images/tokens/rw_1_1_goblin_soldier.jpg
rw_1_1_goblin_soldier_eve.jpg https://downloads.cardforge.org/images/tokens/rw_1_1_goblin_soldier_eve.jpg rw_1_1_goblin_soldier_eve.jpg https://downloads.cardforge.org/images/tokens/rw_1_1_goblin_soldier_eve.jpg
@@ -376,7 +375,6 @@ w_x_x_reflection.jpg https://downloads.cardforge.org/images/to
wb_1_1_cleric.jpg https://downloads.cardforge.org/images/tokens/wb_1_1_cleric.jpg wb_1_1_cleric.jpg https://downloads.cardforge.org/images/tokens/wb_1_1_cleric.jpg
wb_1_1_spirit.jpg https://downloads.cardforge.org/images/tokens/wb_1_1_spirit.jpg wb_1_1_spirit.jpg https://downloads.cardforge.org/images/tokens/wb_1_1_spirit.jpg
wb_1_1_spirit_gtc.jpg https://downloads.cardforge.org/images/tokens/wb_1_1_spirit_gtc.jpg wb_1_1_spirit_gtc.jpg https://downloads.cardforge.org/images/tokens/wb_1_1_spirit_gtc.jpg
wb_1_1_spirit_rna.jpg https://downloads.cardforge.org/images/tokens/wb_1_1_spirit_rna.jpg
wrg_8_8_beast.jpg https://downloads.cardforge.org/images/tokens/wrg_8_8_beast.jpg wrg_8_8_beast.jpg https://downloads.cardforge.org/images/tokens/wrg_8_8_beast.jpg
wu_1_1_bird.jpg https://downloads.cardforge.org/images/tokens/wu_1_1_bird.jpg wu_1_1_bird.jpg https://downloads.cardforge.org/images/tokens/wu_1_1_bird.jpg
wu_4_4_sphinx_flying_vigilance_rna.jpg https://downloads.cardforge.org/images/tokens/wu_4_4_sphinx_flying_vigilance_rna.jpg wu_4_4_sphinx_flying_vigilance_rna.jpg https://downloads.cardforge.org/images/tokens/wu_4_4_sphinx_flying_vigilance_rna.jpg

View File

@@ -17,7 +17,28 @@
*/ */
package forge.download; package forge.download;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URL;
import java.net.URLDecoder;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.tuple.Pair;
import com.esotericsoftware.minlog.Log; import com.esotericsoftware.minlog.Log;
import forge.FThreads; import forge.FThreads;
import forge.GuiBase; import forge.GuiBase;
import forge.UiCommand; import forge.UiCommand;
@@ -28,13 +49,6 @@ import forge.interfaces.ITextField;
import forge.properties.ForgeConstants; import forge.properties.ForgeConstants;
import forge.util.FileUtil; import forge.util.FileUtil;
import forge.util.HttpUtil; import forge.util.HttpUtil;
import org.apache.commons.lang3.tuple.Pair;
import java.io.*;
import java.net.*;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
@SuppressWarnings("serial") @SuppressWarnings("serial")
public abstract class GuiDownloadService implements Runnable { public abstract class GuiDownloadService implements Runnable {
@@ -260,6 +274,19 @@ public abstract class GuiDownloadService implements Runnable {
// don't allow redirections here -- they indicate 'file not found' on the server // don't allow redirections here -- they indicate 'file not found' on the server
conn.setInstanceFollowRedirects(false); conn.setInstanceFollowRedirects(false);
conn.connect(); conn.connect();
// if file is not found and this is a JPG, give PNG a shot...
if ((conn.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) && (url.endsWith(".jpg")))
{
conn.disconnect();
System.out.println(" File not found: " + url);
url = url.substring(0,url.length() - 4) + ".png";
imageUrl = new URL(url);
conn = (HttpURLConnection) imageUrl.openConnection(p);
conn.setInstanceFollowRedirects(false);
conn.connect();
}
switch (conn.getResponseCode()) { switch (conn.getResponseCode()) {
case HttpURLConnection.HTTP_OK: case HttpURLConnection.HTTP_OK:
fos = new FileOutputStream(fileDest); fos = new FileOutputStream(fileDest);
@@ -353,15 +380,16 @@ public abstract class GuiDownloadService implements Runnable {
if (response == null) return null; if (response == null) return null;
String[] strings = response.split("<a href=\""); String[] strings = response.split("<a href=\"");
// Use regex to find all directory paths and capture things using groups...
Pattern pattern = Pattern.compile(">([A-Z0-9_]+)/<");
Matcher matcher;
for (String s : strings) { for (String s : strings) {
int idx = s.indexOf('/'); matcher = pattern.matcher(s);
if (!Character.isLetterOrDigit(s.charAt(0)) || idx > 4 || idx == -1) { if (matcher.find()) {
continue; existingSets.add(matcher.group(1));
} }
String set = s.substring(0, idx);
existingSets.add(set);
} }
return existingSets; return existingSets;

View File

@@ -126,15 +126,15 @@ public enum GroupDef {
if (type.isCreature()) { if (type.isCreature()) {
return 1; return 1;
} }
if (type.isSorcery()) {
return 2;
}
if (type.isTribal() && type.isInstant()) { if (type.isTribal() && type.isInstant()) {
return 7; return 7;
} }
if (type.isInstant()) { if (type.isInstant()) {
return 3; return 3;
} }
if (type.isSorcery()) {
return 2;
}
if (type.isArtifact()) { if (type.isArtifact()) {
return 4; return 4;
} }

View File

@@ -70,6 +70,7 @@ public class ForgePreferences extends PreferencesStore<ForgePreferences.FPref> {
UI_OVERLAY_CARD_MANA_COST ("true"), UI_OVERLAY_CARD_MANA_COST ("true"),
UI_OVERLAY_CARD_ID ("true"), UI_OVERLAY_CARD_ID ("true"),
UI_ENABLE_ONLINE_IMAGE_FETCHER ("false"), UI_ENABLE_ONLINE_IMAGE_FETCHER ("false"),
UI_IMAGE_CACHE_MAXIMUM("400"),
UI_OVERLAY_FOIL_EFFECT ("true"), UI_OVERLAY_FOIL_EFFECT ("true"),
UI_HIDE_REMINDER_TEXT ("false"), UI_HIDE_REMINDER_TEXT ("false"),
UI_OPEN_PACKS_INDIV ("false"), UI_OPEN_PACKS_INDIV ("false"),
@@ -125,7 +126,7 @@ public class ForgePreferences extends PreferencesStore<ForgePreferences.FPref> {
UI_DISABLE_IMAGES_EFFECT_CARDS("false"), UI_DISABLE_IMAGES_EFFECT_CARDS("false"),
UI_ALLOW_ORDER_GRAVEYARD_WHEN_NEEDED ("Never"), UI_ALLOW_ORDER_GRAVEYARD_WHEN_NEEDED ("Never"),
UI_DEFAULT_FONT_SIZE("12"), UI_DEFAULT_FONT_SIZE("12"),
UI_SELECT_FROM_CARD_DISPLAYS("true"), UI_SELECT_FROM_CARD_DISPLAYS("true"),
UI_FOR_TOUCHSCREN("false"), UI_FOR_TOUCHSCREN("false"),
UI_VIBRATE_ON_LIFE_LOSS("true"), UI_VIBRATE_ON_LIFE_LOSS("true"),

View File

@@ -17,6 +17,8 @@
*/ */
package forge.properties; package forge.properties;
import forge.util.FileUtil;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
@@ -24,8 +26,6 @@ import java.util.EnumMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import forge.util.FileUtil;
/** /**
* Holds default preference values in an enum. * Holds default preference values in an enum.
* Loads preferred values when instantiated. * Loads preferred values when instantiated.
@@ -109,7 +109,11 @@ public abstract class PreferencesStore<T extends Enum<T>> {
} }
public final int getPrefInt(final T fp0) { public final int getPrefInt(final T fp0) {
return Integer.parseInt(getPref(fp0)); try{
return Integer.parseInt(getPref(fp0));
} catch(NumberFormatException e) {
return Integer.parseInt(getPrefDefault(fp0));
}
} }
public final boolean getPrefBoolean(final T fp0) { public final boolean getPrefBoolean(final T fp0) {