Skip to content

Commit cee931c

Browse files
authored
Merge branch 'master' into card-art-language-exceptions
2 parents c6c0d4f + a2a834a commit cee931c

158 files changed

Lines changed: 20803 additions & 3781 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ forge-gui-android/res/*/*
5858
!forge-gui-android/res/*/ic_launcher.png
5959
!forge-gui-android/res/*/ic_launcher*.png
6060
!forge-gui-android/res/layout/main.xml
61+
# iOS app-icon asset catalog; the negation outranks any contributor-global
62+
# '*.png' excludes rule that would otherwise silently drop the icons
63+
!forge-gui-ios/resources/**
6164
forge-gui-android/*.keystore
6265
forge-gui-android/**/Thumbs.db
6366
forge-gui-mobile-dev/**/Thumbs.db

forge-core/src/main/java/forge/card/CardType.java

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -899,18 +899,20 @@ public static Set<String> getAllCardTypes() {
899899
private static List<String> sortedSubTypes;
900900
public static List<String> getSortedSubTypes() {
901901
if (sortedSubTypes == null) {
902-
sortedSubTypes = Lists.newArrayList();
903-
sortedSubTypes.addAll(Constant.BASIC_TYPES);
904-
sortedSubTypes.addAll(Constant.LAND_TYPES);
905-
sortedSubTypes.addAll(Constant.CREATURE_TYPES);
906-
sortedSubTypes.addAll(Constant.SPELL_TYPES);
907-
sortedSubTypes.addAll(Constant.ENCHANTMENT_TYPES);
908-
sortedSubTypes.addAll(Constant.ARTIFACT_TYPES);
909-
sortedSubTypes.addAll(Constant.WALKER_TYPES);
910-
sortedSubTypes.addAll(Constant.DUNGEON_TYPES);
911-
sortedSubTypes.addAll(Constant.BATTLE_TYPES);
912-
sortedSubTypes.addAll(Constant.PLANAR_TYPES);
913-
Collections.sort(sortedSubTypes);
902+
// TreeSet sorts and drops duplicates (some types appear in two sections, e.g. Spacecraft);
903+
// the immutable copy is built before publishing, so no caller can observe it mid-sort
904+
final Set<String> tmp = new TreeSet<>();
905+
tmp.addAll(Constant.BASIC_TYPES);
906+
tmp.addAll(Constant.LAND_TYPES);
907+
tmp.addAll(Constant.CREATURE_TYPES);
908+
tmp.addAll(Constant.SPELL_TYPES);
909+
tmp.addAll(Constant.ENCHANTMENT_TYPES);
910+
tmp.addAll(Constant.ARTIFACT_TYPES);
911+
tmp.addAll(Constant.WALKER_TYPES);
912+
tmp.addAll(Constant.DUNGEON_TYPES);
913+
tmp.addAll(Constant.BATTLE_TYPES);
914+
tmp.addAll(Constant.PLANAR_TYPES);
915+
sortedSubTypes = ImmutableList.copyOf(tmp);
914916
}
915917
return sortedSubTypes;
916918
}

forge-game/src/main/java/forge/game/ability/AbilityUtils.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,8 @@ public static PlayerCollection getDefinedPlayers(final Card card, final String d
11811181
next = game.getNextPlayerAfter(next, dir);
11821182
}
11831183
players.add(next);
1184+
} else if (defined.equals("ManaSpender")) {
1185+
players.addAll(((SpellAbility) sa).getPayingMana().stream().map(m -> m.getPlayer()).collect(Collectors.toList()));
11841186
} else {
11851187
// will be filtered below
11861188
players.addAll(game.getPlayersInTurnOrder());

forge-game/src/main/java/forge/game/spellability/SpellAbilityProperty.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import forge.game.mana.Mana;
1414
import forge.game.mana.ManaCostBeingPaid;
1515
import forge.game.player.Player;
16+
import forge.game.player.PlayerCollection;
1617
import forge.game.staticability.StaticAbility;
1718
import forge.game.staticability.StaticAbilityCastWithFlash;
1819
import forge.game.zone.ZoneType;
@@ -157,6 +158,10 @@ public static boolean hasProperty(SpellAbility sa, Player sourceController, Card
157158
return sa.isLastChapter();
158159
} else if (property.equals("paidPhyrexianMana")) {
159160
return sa.getSpendPhyrexianMana() > 0;
161+
} else if (property.startsWith("ManaSpentBy")) {
162+
String[] k = property.split(" ", 2);
163+
PlayerCollection spenders = AbilityUtils.getDefinedPlayers(source, k[1], spellAbility);
164+
return sa.getPayingMana().stream().anyMatch(m -> spenders.contains(m.getPlayer()));
160165
} else if (property.startsWith("ManaSpent")) {
161166
String[] k = property.split(" ", 2);
162167
String comparator = k[1].substring(0, 2);

forge-gui-desktop/src/main/java/forge/util/SwingImageFetcher.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
import java.awt.image.BufferedImage;
88
import java.io.File;
99
import java.io.IOException;
10+
import java.io.InputStream;
1011
import java.net.HttpURLConnection;
1112
import java.net.URL;
13+
import java.net.URLConnection;
1214

1315
public class SwingImageFetcher extends ImageFetcher {
1416

@@ -34,13 +36,41 @@ private boolean doFetch(String urlToDownload) throws IOException {
3436
return false;
3537
}
3638

39+
if (inScryfallCooldown(urlToDownload)) {
40+
return false;
41+
}
42+
3743
String newdespath = urlToDownload.contains(".fullborder.jpg") || urlToDownload.startsWith(ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD) ?
3844
TextUtil.fastReplace(destPath, ".full.jpg", ".fullborder.jpg") : destPath;
3945
if (!newdespath.contains(".full") && !newdespath.contains(".artcrop") && urlToDownload.startsWith(ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD) && !destPath.startsWith(ForgeConstants.CACHE_TOKEN_PICS_DIR))
4046
newdespath = newdespath.replace(".jpg", ".fullborder.jpg"); //fix planes/phenomenon for round border options
4147
URL url = new URL(urlToDownload);
4248
System.out.println("Attempting to fetch: " + url);
43-
BufferedImage image = ImageIO.read(url);
49+
paceScryfall(urlToDownload);
50+
51+
// Read through a connection rather than ImageIO.read(URL), which discards the response
52+
// code - without it a 429 is indistinguishable from any other failure and we keep asking.
53+
final URLConnection connection = url.openConnection();
54+
connection.setRequestProperty("Accept", "*/*");
55+
connection.setRequestProperty("User-Agent", BuildInfo.getUserAgent());
56+
if (connection instanceof HttpURLConnection httpConnection) {
57+
final int responseCode = httpConnection.getResponseCode();
58+
if (responseCode != HttpURLConnection.HTTP_OK) {
59+
System.err.println("Failed to fetch image. HTTP code: " + responseCode
60+
+ " (" + httpConnection.getResponseMessage() + ") for URL: " + urlToDownload);
61+
if (responseCode == 429 && isScryfall(urlToDownload)) {
62+
System.err.println("Rate limited by scryfall. Pausing image downloads.");
63+
noteScryfallRateLimited();
64+
}
65+
httpConnection.disconnect();
66+
return false;
67+
}
68+
}
69+
70+
BufferedImage image;
71+
try (InputStream is = connection.getInputStream()) {
72+
image = ImageIO.read(is);
73+
}
4474
// First, save to a temporary file so that nothing tries to read
4575
// a partial download.
4676
File destFile = new File(newdespath + ".tmp");

forge-gui-ios/Info.plist.xml

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,6 @@
4646
<string>UIInterfaceOrientationLandscapeLeft</string>
4747
<string>UIInterfaceOrientationLandscapeRight</string>
4848
</array>
49-
<key>CFBundleIcons</key>
50-
<dict>
51-
<key>CFBundlePrimaryIcon</key>
52-
<dict>
53-
<key>CFBundleIconFiles</key>
54-
<array>
55-
<string>Icon</string>
56-
<string>Icon-72</string>
57-
</array>
58-
</dict>
59-
</dict>
6049
<key>UILaunchStoryboardName</key>
6150
<string></string>
6251
<key>UIRequiresFullScreen</key>

forge-gui-ios/pipeline/ios-pipeline.sh

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -451,11 +451,33 @@ sim() {
451451
trap 'mv -f "$OSLOG_LIB.committed" "$OSLOG_LIB" 2>/dev/null || true' EXIT
452452
build_oslog sim
453453
echo "=== robovm ipad-sim build ($SIM_ARCH) ==="
454-
# On Apple Silicon (arch=arm64-simulator) this fails at the mojo's device
455-
# selection AFTER producing the binary + config.xml — expected; we assemble
456-
# the .app ourselves below. On Intel (x86_64) it produces the .app directly.
457-
(cd "$ROOT/forge-gui-ios" && mvn robovm:ipad-sim --settings "$SETTINGS" \
458-
-Dmaven.repo.local="$CLONE" -Drobovm.arch="$SIM_ARCH" -DskipTests 2>&1 | tail -8) || true
454+
if [ "$SIM_ARCH" = "arm64-simulator" ]; then
455+
# The mojo blocks in its own app launch after the AOT link (and picks its own
456+
# simulator). All we need from it is config.xml, written once the link is done:
457+
# stop it there and let assemble_arm64_sim_app rebundle with the AppCompiler
458+
# (the AOT cache is content-hashed, so nothing recompiles).
459+
local TMPD="$ROOT/forge-gui-ios/target/robovm.tmp" mvnpid
460+
# not under robovm.tmp: the mojo wipes that directory after mvn has opened the log
461+
local MVNLOG="$ROOT/forge-gui-ios/target/ipad-sim.log"
462+
mkdir -p "$TMPD"
463+
rm -f "$TMPD/config.xml"
464+
set -m
465+
(cd "$ROOT/forge-gui-ios" && mvn robovm:ipad-sim --settings "$SETTINGS" \
466+
-Dmaven.repo.local="$CLONE" -Drobovm.arch="$SIM_ARCH" -DskipTests \
467+
> "$MVNLOG" 2>&1) &
468+
mvnpid=$!
469+
set +m
470+
# -s not -f: the mojo opens config.xml before serializing into it
471+
while kill -0 "$mvnpid" 2>/dev/null && [ ! -s "$TMPD/config.xml" ]; do sleep 2; done
472+
sleep 2
473+
kill -TERM -"$mvnpid" 2>/dev/null || true
474+
wait "$mvnpid" 2>/dev/null || true
475+
[ -s "$TMPD/config.xml" ] || { echo "robovm build failed, last lines:"; tail -12 "$MVNLOG"; }
476+
else
477+
# Intel: the mojo bundles the .app itself in its launch phase — let it run.
478+
(cd "$ROOT/forge-gui-ios" && mvn robovm:ipad-sim --settings "$SETTINGS" \
479+
-Dmaven.repo.local="$CLONE" -Drobovm.arch="$SIM_ARCH" -DskipTests 2>&1 | tail -8) || true
480+
fi
459481
mv -f "$OSLOG_LIB.committed" "$OSLOG_LIB"; trap - EXIT
460482

461483
APP="$ROOT/forge-gui-ios/target/robovm.tmp/$APP_EXEC.app"
251 KB
Loading
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"images" : [
3+
{
4+
"filename" : "AppIcon-1024.png",
5+
"idiom" : "universal",
6+
"platform" : "ios",
7+
"size" : "1024x1024"
8+
}
9+
],
10+
"info" : {
11+
"author" : "xcode",
12+
"version" : 1
13+
}
14+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"info" : {
3+
"author" : "xcode",
4+
"version" : 1
5+
}
6+
}

0 commit comments

Comments
 (0)