Skip to content

Token edition selection improvements (filter, era-match, per-game pinning) and 55 new token registrations#10518

Open
vanja-ivancevic wants to merge 11 commits intoCard-Forge:masterfrom
vanja-ivancevic:token-bugfixes
Open

Token edition selection improvements (filter, era-match, per-game pinning) and 55 new token registrations#10518
vanja-ivancevic wants to merge 11 commits intoCard-Forge:masterfrom
vanja-ivancevic:token-bugfixes

Conversation

@vanja-ivancevic
Copy link
Copy Markdown
Contributor

  • Adds adventure-mode token edition filter respecting per-plane allowedEditions and restrictedEditions, with optional restrictedTokens for blocking specific EDITION/script pairs
  • Adds per-user setting "pick token art from edition closest to producing card's release date" (off by default, no impact on vanilla Forge)
  • Pins token edition per game so duplicates of the same script share art within a single match
  • Adds runtime consultation of token-images.txt URL map for hosted token downloads
  • Crops rounded-border fringe on token images via ImageCache (parity with regular cards)
  • Fixes Unglued token collector numbers to match Scryfall TUGL
  • Adds Magic Player Rewards 2002 (PR2) and Duelist Magazine (TDLS) edition files
  • Adds 6 MicroProse 1997 tokens to PAST (Astral Cards): Wasp, Djinn, Tetravite, Poison Snake, Spawn of Azar, Rukh
  • Adds Old Border Custom (OBC) edition with 49 Card Conjurer renders covering token coverage gaps for Old Border legal cards
  • Wires Shandalar Old Border config to use the filter, allow PAST/UGL/MPR/PR2/P03/TDLS/OBC, and block 2 modern-frame P03 entries

vanja-ivancevic and others added 11 commits April 25, 2026 07:25
Unglued tokens in the edition file were numbered 1-6, but Scryfall
indexes them under the TUGL set at collector numbers 89-94. Forge builds
token image URLs as {tokensCode}/{collectorNumber}/en, so tugl/1..6 was
404ing and Unglued token art was silently unreachable.

Renumber the six [tokens] entries (Pegasus, Soldier, Zombie, Goblin,
Sheep, Squirrel) to their real TUGL collector numbers so Scryfall
lookups resolve.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
croppedBorderImage gated the 0.96x scale-crop on filenames containing
.fullborder., which is how regular card images are named. Token images
live under pics/tokens/ and do not carry that substring, so in Crop UI
mask they were drawn at full extent and the printed card's rounded
corners bled through as white fringes at all four corners.

Extend the condition to also trigger the crop when the image path
contains "tokens", matching the same marker ImageCache already uses to
treat token art as fullborder for border-color and radius tracking.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…dEditions

Add a Predicate<CardEdition> slot on TokenDb with a setter
(setDefaultEditionFilter), mirroring CardDb.setCardArtPreference. Expose
the filter via a new ITokenDatabase method getTokenFromEditions(name,
Predicate<CardEdition>) that parallels the existing
getCardFromEditions(name, ..., Predicate<PaperCard>) on the card side.
fallbackToken delegates to it.

With no filter installed, fallbackToken keeps its historical behavior
(first alphabetical edition that registers the token wins). With a
filter, it picks a random legal edition, or returns null if none of
them register the token, letting Forge's no-art placeholder path handle
rendering rather than quietly falling back to a non-legal printing.

Adventure Config.loadResources pushes a filter built from the plane's
allowedEditions and restrictedEditions on plane entry, so token art in
Old Border is limited to the same set pool that already gates cards.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When the edition filter yields multiple legal editions for a token
script, fallbackToken rolls a random one on each call, so two summons
of the same token type in one game could land on different arts. Add
a WeakHashMap<Game, Map<script, edition>> on TokenInfo so the first
resolution pins the edition and later calls in the same game reuse it.
Weak keys let finished games be garbage-collected.

No effect when the filter is unset, since unfiltered fallbackToken is
already deterministic.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…era-matched art

Two related refinements to TokenDb.getTokenFromEditions / fallbackToken:

1. restrictedTokenEntries: a set of "{EDITION_CODE}/{tokenScript}" pairs
   that are skipped during fallback, so a plane can block individual
   printings within an otherwise-legal edition. Adventure planes populate
   it from a new restrictedTokens field on ConfigData, alongside the
   existing allowedEditions / restrictedEditions.

2. preferEraMatchedArt: when true and the host card's edition release
   date is known, fallback picks the legal edition whose release date is
   closest to the host's, deterministically. fallbackToken now accepts
   the host edition code so TokenDb can look up the date. Exposed as a
   user-level adventure setting (SettingData.preferEraMatchedTokenArt)
   with a checkbox in SettingsScene; default off, so vanilla behavior is
   preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The same "filename URL" list the bulk image downloader reads
(token-images.txt) is now consulted by ImageFetcher's token branch, so
modders can route token art to hosted URLs without a new mechanism
(parallel to how booster-images.txt works). The override URL is added
to the download list; if none matches, falls through to the existing
Scryfall path. For custom or unknown editions (no Scryfall record),
a hit in the override list is enough to trigger the download.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PR2 (Magic Player Rewards 2002): 6 old-frame paper tokens (Squirrel,
Zombie, Elephant, Wurm, Dragon, Soldier) registered at Scryfall
collector numbers 3-8. Scryfall-fetchable via the standard token URL
path, no image hosting needed.

TDLS (Duelist Magazine Tokens): 5 custom renders of the 1995 Duelist Card-Forge#4
token insert (Thrull, Saproling, Citizen, Camarid, Goblin). Not on
Scryfall; images are hosted separately and routed via token-images.txt.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Five lines mapping the Forge local-cache filenames for Duelist Magazine
tokens (TDLS/N_{script}.jpg) to their hosted URLs on oldborder-shandalar.net.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…e P03 entries

Add MPR, PR2, P03, TDLS to allowedEditions so the token filter can pick
Magic Player Rewards 2001-2003 and Duelist Magazine prints in addition
to Unglued.

Block P03/r_4_4_bird_flying (Rukh) and P03/b_x_x_demon_flying (Demon)
via the new restrictedTokens field: both are post-2003 modern-frame
tokens that happen to share the P03 Scryfall set code with the genuinely
old-frame P03 tokens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PAST (Astral Cards, MicroProse Shandalar 1997) gains 6 token entries
(cnums 13-18): Wasp, Djinn of the Bottle, Tetravite, Poison Snake,
Spawn of Azar, and Rukh. These cover tokens produced by The Hive,
Bottle of Suleiman, Whimsy, Tetravus, Serpent Generator, Necropolis
of Azar, and Rukh Egg (replacing the restricted modern-frame P03
Rukh).

OBC (Old Border Custom Tokens) is a new edition holding 49 Card
Conjurer TokenOld renders for scripts with no legal old-border
printing. Dated 2003-05-26 (end of Old Border era) since most of
these scripts only appear here. Added to allowedEditions.

Images are hosted on oldborder-shandalar.net and wired via
token-images.txt URL overrides.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tions overloads

The single-arg `fallbackToken(name)` and `getTokenFromEditions(name, filter)`
overloads were added by earlier commits on this branch but ended up with no
callers — `getToken` always uses the two-arg `fallbackToken(name, edition)`,
which routes through the three-arg `getTokenFromEditions(name, filter, hostDate)`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant