Skip to content

Saga tweak#10421

Merged
tool4ever merged 1 commit intoCard-Forge:masterfrom
tool4ever:sagaagain
Apr 16, 2026
Merged

Saga tweak#10421
tool4ever merged 1 commit intoCard-Forge:masterfrom
tool4ever:sagaagain

Conversation

@tool4ever
Copy link
Copy Markdown
Contributor

No description provided.

@tool4ever tool4ever requested a review from Hanmac April 15, 2026 21:15
@tool4ever tool4ever added the Rules compliance Bringing the engine or cards closer to CR label Apr 15, 2026
@tool4ever tool4ever merged commit ebaefc8 into Card-Forge:master Apr 16, 2026
2 checks passed
@tool4ever tool4ever deleted the sagaagain branch April 19, 2026 20:16
delebedev added a commit to delebedev/forge that referenced this pull request Apr 26, 2026
)

* Create artistic_process.txt (Card-Forge#10254)

* Mapfix (Card-Forge#10252)

* Deluge Virtuoso and Splatter Technique (Card-Forge#10256)

* Fix Bronze Tablet ownership tracking using CorrectedSelf (Card-Forge#10257)

Same fix as 66b9db7 (Tempest Efreet, Timmerian Fiends) but for
Bronze Tablet, which was missed. Using Defined$ Self references a
stale card object after zone changes, so the ownership transfer
never gets tracked and the gained card is lost.

* Keyword: Increment (Card-Forge#10259)

* Edition updates: PMEI, PW26, SOA, SOC, SOS

* Update pest_summoning.txt

* Update blight_mound.txt

* Update tend_the_pests.txt

* Update pest_infestation.txt

* Update callous_bloodmage.txt

* Update containment_breach.txt

* Update hunt_for_specimens.txt

* Update valentin_dean_of_the_vein_lisette_dean_of_the_root.txt

* Update sedgemoor_witch.txt

* Update beledros_witherbloom.txt

* Update professor_of_zoomancy.txt

* Update pestilent_cauldron_restorative_burst.txt

* Momir use random land art (Card-Forge#10220)

* Generate momir deck with random lands

* Fix Momir deck being generated before block data is loaded

* Remove unused import

* Only call getBlocks() when autogenerating deck

* Move getBlocks() to before autoGenerateDeck()

* Use getCommonCards() instead of getBlockLands()

* Remove getBlockLands()

* 3 cards with Increment (and a few more) (Card-Forge#10262)

* Fix booster pack image fetching using dead CDN URL (Card-Forge#10265)

- On-demand ImageFetcher was hardcoded to downloads.cardforge.org which
  is offline, causing all in-game booster image fetches to fail silently.
  Now looks up the correct URL from booster-images.txt instead.
- Update remaining old-border sets (CHR, PO2, POR, PTK, S99) in
  booster-images.txt to use the new CDN.

* A few more SOS cards (Card-Forge#10267)

* SOS spoilers, 3rd April (Card-Forge#10266)

* Adventure-Sprites-Enemies-Bosses-v1.3 (Card-Forge#10269)

Co-authored-by: Jetz72 <Jetz722@gmail.com>

* Create daydream.txt (Card-Forge#10270)

* Aziza and her routine (Card-Forge#10273)

* Add centralised haptic feedback controls (Card-Forge#10255)

- Vibration targets controller when last input was a gamepad button or
  joystick; targets device motor when last input was touch, click, or
  keyboard. Passive mouse cursor movement is ignored to avoid
  overriding active controller use on desktop
- Device vibration path (Gdx.input.vibrate) is skipped on desktop
  where it can leak to connected controllers via OS audio routing
- Adventure call sites use unified durations (controller values:
  200-400ms encounters, 100ms rewards) since controller motors need
  longer pulses than phone vibration motors
- Axis deadzone of 0.25 filters joystick drift from counting as
  intentional controller input

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

* Some cleanup (Card-Forge#10278)

* Fix multiplayer freeze when casting spells with non-mana optional costs (Card-Forge#10277)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Realm of legends 1.024: Two small fixes (Card-Forge#10274)

* Mapfix

* Enemy rebalance

* Added lands to library (Card-Forge#10279)

Added lands to library so AI doesn't draw from empty library

* Forward setUsedToPay highlights to network clients (Card-Forge#10272)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: tool4EvEr <tool4EvEr@>

* Adventure fixes (Card-Forge#10282)

* cleanup

* Update ghaltas_presence.txt

* Realm of Legends: Enemy fix; Banlist edits (Card-Forge#10281)

* Enemy fix; Banlist edits

* Item fix

* Fix typo for Pithing Needle (Card-Forge#10283)

* Fix booster pack image selection and live refresh in adventure mode (Card-Forge#10280)

- Select booster art randomly from all available images in
  booster-images.txt instead of hardcoding art index 1-2.
  Uses exact filename prefix matching to avoid false matches.
- Enable live sprite refresh when booster images finish downloading
  so packs display on first visit, not just subsequent ones.

* Item rebalances (Card-Forge#10284)

* Placeholder Faces

* Update StaticData - forgot to commit this one

* fix(draft): prevent NPE when draft ends during pack-passing transition

* Banlist changes (Card-Forge#10286)

* Update umbral_expanse.txt

Closes Card-Forge#10285

* Update abstract_performance.txt

* Extract common computation

* tibalt tweaks (Card-Forge#10295)

* Fix ItemManagerConfigs in adventure events (Card-Forge#10296)

* Add option to include basic lands in ante selection (Card-Forge#10293)

Adds UI_ANTE_INCLUDE_BASIC_LANDS preference that, when enabled, allows
basic lands to be randomly selected for ante (matching original paper
Magic rules). When disabled (default), basic lands continue to be
excluded from ante selection, preserving the current Microprose
Shandalar behavior.

The option applies to both random and rarity-matched ante modes. In
Adventure mode settings, the sub-options are disabled (checkmarks
hidden) when ante is disabled.

* Hovering over deck name in lobby displays comment from .dck file (Card-Forge#10263)

* hover over name in deck selector displays comment from .dck

* minor regex cleanup

* Adventure: QOL improvements for "Clear All" quests (Card-Forge#10244)

* Add enemy counter feature to GameHUD and localization support for remaining enemies when in a dungeon with an active "clear all" quest.

* Add setting to draw chevrons for hidden enemies in clear all quests. Gate this behavior behind a new "Draw chevrons pointing to hidden enemies in a clear all quest" flag in settings.

* Fix casing of "Clear All" quests

* Ark of Hunger (SOS) (Card-Forge#10297)

* Realm of Legends: New quests for each capitol; numerous item buffs. (Card-Forge#10298)

* New quests for each capitol; numerous item buffs.

* Increased starting life for easy mode

* Realm of Legends: Assorted item buffs (Card-Forge#10299)

* Assorted item buffs

* Item fix to stop crash on worldgen

* itemfix (Card-Forge#10302)

* Fractal Tender and Ambitious Augmenter (SOS) (Card-Forge#10305)

* Fix Android client game events failing to deserialize in cross-platform network play (Card-Forge#10304)

JVM hardcodes serialVersionUID=0 for records, but Android's D8 desugaring
computes a different UID, causing InvalidClassException for all GameEvent
types in GameEventProxy's inner deserialization. Override readClassDescriptor()
to use the local class descriptor when UIDs mismatch, matching the existing
pattern in SaveFileData and CObjectInputStream.

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

* SOS spoilers, 6th April (Card-Forge#10306)

* Update primo_the_unbounded.txt

Closes Card-Forge#10307

* Create flow_state.txt (Card-Forge#10308)

* Realm of legends 1.030: All elite+ bosses on Easy/Normal nerfed; various fixes & upgrades (Card-Forge#10311)

* Switched red capitol quest reward

* Handful of deck edits

* Easy and Normal now have easier bosses across all maps; fix for gamebreaking item bug

* Update funny cards list (Card-Forge#10268)

* Update funny cards list

Some of the ones from the most recent unknown event, re-tiered a few others.

* Update Un‐cards,-Playtest-Cards,-and-Other-Funny-Cards.md

Rest of the missing cards

* Update Un‐cards,-Playtest-Cards,-and-Other-Funny-Cards.md

Apparently Townwalk can already be a thing

* Create geometers_arthropod.txt (Card-Forge#10309)

* Update ian_malcolm_chaotician.txt

* Edition updates: SOA, SOC, SOS

* Create social_snub.txt (Card-Forge#10315)

* Realm of legends 1.031: Overworld sprite update, item tweaks (Card-Forge#10318)

* Mapfix

* Boss item/starter edit

* New item for urza; a few item buffs

* Added new overworld map sprites

* Create brush_off.txt (Card-Forge#10321)

* Fix incorrect enemy sprite scales in Tibalt's Fortress (Card-Forge#10323)

- Demon of Tibalt: 0.6 -> 1.2 (was nearly invisible as dungeon miniboss)
- Tibalt (Specter King): 0.5 -> 1.2 (was nearly invisible as dungeon boss)
- Arcane Golem: 0.55 -> 3.0 (restore to vanilla scale)

* Create homesickness.txt (Card-Forge#10322)

* Create the_mother_slime.txt (Card-Forge#10317)

* Create the_mother_slime.txt

* Update the_mother_slime.txt

* Various Quandrix spoilers (Card-Forge#10313)

* SOS spoilers, 7th April (Card-Forge#10316)

* SOS spoilers, 8th April morning (Card-Forge#10325)

* Create inkshape_demonstrator.txt (Card-Forge#10328)

* A few more SOS spoilers (Card-Forge#10330)

* Edition updates: SOA, SOS

* Create snooping_page.txt (Card-Forge#10332)

* Clean up (Card-Forge#10333)

* Ennis and Tragedy Feaster (SOS) (Card-Forge#10337)

* Another batch of SOS Whatnot leaks (Card-Forge#10329)

* Update instrument_of_the_bards.txt (Card-Forge#10339)

* Create blech_loafing_pest.txt (Card-Forge#10340)

* Update CopySpellAbilityEffect.java

Use Keyword for removeIntrinsicKeyword

* Update CopySpellAbilityEffect.java

* Old Border Shandalar: Landscape sketchbook rebalance (Card-Forge#10336)

* Add landscape sketchbook drops to all bosses and sketchbook vendor to Bazaar of Wonders

- Add landSketchbookShop reward to 58 bosses/minibosses that were missing it
  (0.5 probability for main bosses, 0.2 for minibosses)
- Add SketchbookShop definition in shops.json with all 20 non-quest sketchbooks
- Add cost (500 gold) to all non-quest landscape sketchbook items
- Place sketchbook vendor in Bazaar of Wonders at lower row building position

* Remove Alpha, Beta, and Fourth Edition sketchbooks from vendor

* Realm of legends 1.032: Assorted mapfixes (Card-Forge#10335)

* New ulamog sprite

* Mapfix

* Mapfixes

* Updated mapfixes

* Mapfix

* Spritefixes

* Adventure-Sprites-Buildings-v1.2 (Card-Forge#10334)

Cleaner and sharper buildings edges, small fix to atlas file

* SOS spoilers, 9th April (Card-Forge#10341)

* Network multiplayer optimization (delta sync + testing) (Card-Forge#9642)

* FGameClient username fix

The constructor username parameter was being ignored - LoginEvent always read from FModel preferences.
Now the username is stored and used, with preferences as fallback.

* Implements infrastructure for running multiple network games for rapid debugging and log generation.

Add -Dforge.checksum.mode and -Dforge.deltasync system properties so
different test configurations can be run from the command line without
editing source code. Both are forwarded to child processes in
MultiProcessGameExecutor.

* fix GuiMobile.isGuiThread() threading bug

MatchController now extends NetworkGuiGame instead of AbstractGuiGame,
giving mobile clients the same delta sync protocol that desktop already
uses. NetworkGuiGame is platform-neutral (no Swing/libgdx imports) and
MatchController doesn't override any of the methods it adds (applyDelta,
fullStateSync, setGameView), so the inheritance change slots in cleanly.

The prerequisite fix: GuiMobile.isGuiThread() used negative logic
(!ThreadUtil.isGameThread()) which only distinguished "Game-*" worker
threads from everything else. Any third-party thread pool — including
Netty I/O threads used by the network protocol — was misidentified as
the GUI thread. This caused GameProtocolHandler to execute network
callbacks immediately on the Netty thread instead of dispatching to the
libgdx GL thread via Gdx.app.postRunnable().

The fix captures the GL thread reference in Forge.create() (which
libgdx guarantees runs on the GL thread) and compares by identity. This
mirrors how GuiDesktop uses SwingUtilities.isEventDispatchThread() —
positive identification of the correct thread rather than exclusion of
known background threads.

The window between getApp() and create() where glThread is null is safe:
no game logic, network connections, or UI rendering occurs before create().

* Fix mobile client crash on game start by using server's existing tracker

The client's openView handler was creating a local Match/Game just to
obtain a Tracker, discarding the server's correctly-initialized gameView
in the process. This caused duplicate PlayerView IDs when player names
were renamed by the server (e.g. "TestHost" -> "2nd TestHost"), resulting
in only 1 PlayerView in the tracker and an IndexOutOfBoundsException in
MatchScreen on mobile.

The local game creation was a workaround added in 2018 (b47d528) because
the server's gameView didn't arrive with an initialized tracker at that
time. Our ensureTrackerInitialized() mechanism (added for delta sync)
now ensures the server's gameView arrives with a correct tracker, making
the workaround unnecessary.

* Fix 4-player lobby slot assignment race causing startup failures

* Unify event delivery through DeltaPacket

Replace the separate ProtocolMethod.handleGameEvents with events-only
DeltaPackets sent via applyDelta, so both delta-sync and fallback paths
use the same delivery mechanism. Skip ackSync for events-only packets
(seq=-1) to match the existing setGameView convention.

* Game-thread-only delta production

Move all collectDeltas() calls to the game thread by registering
GameEventForwarder as an Observer on InputQueue. This flushes
buffered events on the game thread right before it blocks for
player input (e.g. host plays a land and retains priority).

* Fix CombatView desync: placeholder for fake Card(-1) combat defenders

* Fix client game log/stack showing wrong card image after zone change

When a card changes zones (e.g. Clone flickered mid-ability), the engine
creates a new Card with the same ID. On the network client, this caused
two issues:

- Stack: createObjectOnly cleared the existing CardView in-place,
  destroying the old state still referenced by StackItemView.SourceCard.
  Fixed by creating a new CardView instance, mirroring engine semantics.

- Game log: GameEventProxy serializes CardView references as ID-only
  IdRef markers. Events arriving in later packets (after the CardView
  replacement) resolved to the wrong incarnation. Fixed by detecting
  stale references via object identity on the server and serializing a
  StaleCardRef with the original image key, which the client resolves
  to a detached CardView with correct display data.

* Fix remote client hand not refreshing after delta sync zone changes

In multiplayer network games (3+ players), the remote client's hand
panel was not updating when cards moved zones (e.g. playing a land).
The event-driven updateZones() path uses getHandFor(player) which
returns null when the local player isn't at index 0 in sortedPlayers.
The non-delta path masked this by iterating VHands directly in
setGameView().

Add unconditional GUI refresh after each delta application, matching
the setGameView refresh pattern.

* Add "Open Network Logs" menu item to Online menu

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: tool4EvEr <tool4EvEr@>

* Realm of legends 1.033: Mapfixes, two new minibosses (Card-Forge#10346)

* Two new minibosses and associated items

* Mapfixes

* Mapfix

* Mapfix

* Create foolish_fate.txt (Card-Forge#10342)

* Edition updates: SOA, SOS

* Change card type from Instant to Sorcery (Card-Forge#10356)

* Fix stale Play/Draw prompt after choosing Draw in network games (Card-Forge#10358)

After choosing Draw in a network game, the buttons stayed on the
chooser's prompt with no feedback until the opponent finished
mulliganing. Two bugs stacked: InputConfirm never overrode
allowAwaitNextInput (so the "waiting for opponent" transition was
never scheduled), and AbstractGuiGame.waitingTimer had a TimerTask
race where a stale EDT tick could overwrite the new prompt text after
Timer.cancel().

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* Clean up (Card-Forge#10360)

* Documentation update for delta sync + minor testing simplification (Card-Forge#10348)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Final SOS spoiler batch, 10th April (Card-Forge#10350)

* Secrets draft (Card-Forge#10357)

* SOS draft info

* SOS draft info

* SOS draft rankings

* - Add planeswalker achievements for SOS/SOC by Marek14. (Card-Forge#10364)

* Clean up (Card-Forge#10365)

* Fix sendAndWait() timeout NPE for idle network players  (Card-Forge#10354)

ReplyPool.get() had a hardcoded 5-minute timeout that silently returned
null when a human player was slow to respond, causing NPEs in callers
that don't handle null (e.g. getAbilityToPlay, assignCombatDamage).

* Add AFK timeout for priority passes in network host games

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: tool4EvEr <tool4EvEr@>

* Network play: auto-close server URL dialog, document AFK timer (Card-Forge#10366)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* Add mobile Settings buttons to export game and network logs (Card-Forge#10367)

Adds Export Game Log and Export Network Logs items under Settings >
Files > Data Management. Each bundles the matching log files into a
timestamped zip in the Downloads folder, so Android users can share
logs when reporting bugs without needing a third-party file manager.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* Fix card loading crash (Card-Forge#10368)

Co-authored-by: autumnmyst <209156905+autumnmyst@users.noreply.github.com>

* Update throne_of_the_grim_captain_the_grim_captain.txt (Card-Forge#10369)

* Edition updates: SLD, SOC, SOS

* Add SOS, SOC, SOA to formats

* Update deluge_virtuoso.txt (Card-Forge#10373)

* Some fixes

* Fix tinylog "network log" writer not found in packaged builds (Card-Forge#10377)

The maven-assembly-plugin's built-in jar-with-dependencies descriptor
overwrites META-INF/services files instead of merging them, so
NetworkLogWriter was lost in the fat JAR. Replace the built-in
descriptor with a custom one using the metaInf-services handler
for desktop and mobile-dev. Also add NetworkLogWriter to Android's
hardcoded service file.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* Clean up (Card-Forge#10378)

* some Epic cleanup with removeIntrinsicKeyword

* Keyword: Paradigm

* Increase power and toughness of Mica, Reader of Ruins

* Update impractical_joke.txt

* Paradigm spells (Card-Forge#10389)

* Adventure: graceful map load failure and fix merfolkpool teleport case (Card-Forge#10387)

Teleport to a missing map file infinite-looped in TileMapScene.act():
nextMap was cleared after load(), so an exception left nextMap populated
and the same failed load retried every frame with no way out. Clear
nextMap before load(), wrap in try/catch, and call MapStage.exitDungeon
on failure to return the player to the world map. Mirrors the existing
pattern in WorldStage.loadPOI.

Fix merfolkpool_6.tmx teleport referencing merfolkpool_6b.tmx when the
actual file is merfolkpool_6B.tmx. Works on macOS/Windows but breaks on
Linux case-sensitive filesystems, triggering the infinite-loop bug above.
Applied to both the common copy and the Shandalar Old Border copy.

* Ai doesn't activate ability of deadeye duelist (Card-Forge#10375)

* Fix Android crash: guard ProcessHandle in NetworkLogWriter (Card-Forge#10392)

* Realm of legends: minor mapfixes (Card-Forge#10394)

* Enemy visual fix

* Mapfix

* Add Deathtouch ability to Arnyn, Deathbloom Botanist (Card-Forge#10395)

* Fix Arnyn, Deathbloom Botanist missing Deathtouch keyword (Card-Forge#10396)

* Add fetch item checks to quest stage event handling. This fixes "Dungeon Master" quest soft-lock when an objective involves defeating a boss you've already defeated as part of another quest. (Card-Forge#10386)

Co-authored-by: Agetian <stavdev@mail.ru>

* Update Forest_Capital.tmx to give Green rares/mythics for arena rewards (Card-Forge#10390)

Forest Capital Arena did not give color-specific rares/mythics as rewards, like the other capitals do. This brings the Forest Capital in line with the other Capitals

* Update in_the_trenches.txt (Card-Forge#10382)

* Only write network logs for network games and tests (Card-Forge#10393)

Returning to the lobby between games keeps the same key since neither teardown
fires until the session ends.
Does not affect test mode which uses a separate code path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Book Oracle update (Card-Forge#10400)

* Add plane-scoped adventure data overrides (blocks + editions) (Card-Forge#10398)

* Add adventure mod data overrides for blocks.txt and edition files

Adventure mods can drop partial blockdata/blocks.txt and editions/*.txt
files in their adventure folder, layered on top of the upstream data at
session start. Absent files fall through; vanilla Forge outside Adventure
mode is unaffected.

Block overlays are full lines keyed by name and replace the upstream
entry. Edition overlays are parsed by the normal edition reader and
currently propagate the Booster= field; other fields fall through.

The name(...) booster slot operator now accepts "Card Name|SET" syntax
to pin a specific printing, mirroring the | delimiter already used in
custom print sheets.

Demonstrates the mechanism with two Shandalar Old Border overlays:
one drops Coldsnap from the Ice Age block and locks the draft order
to ICE/ICE/ALL, the other replaces a common slot in the Ice Age
booster with a guaranteed snow-covered basic land pinned to the ICE
printing, keeping the pack at 15 cards.

* Apply adventure data overrides in loadResources instead of Config ctor

Config.instance() is built from GameLauncher before FModel.initialize()
runs, so calling FModel.getBlocks() / FModel.getMagicDb() in the Config
constructor crashed with NullPointerException on startup. Move the
block / edition overlay pass into Config.loadResources(), which is
invoked from Forge.loadAdventureResources() after the model is ready.

* Remove redundant |SET split in BoosterGenerator name(...) operator

CardDb.getCard(String) already routes through CardRequest.fromString(),
which parses the "Card Name|SET" syntax natively. Splitting on the
pipe and recomposing via getCard(name, setCode) produced the same
request; drop the split and keep the original single-line call.

Noticed during review of Card-Forge#10398 by Jetz72.

* Move adventure data overrides off the shared upstream singletons

The previous shape mutated CardEdition.boosterTemplates and the block
StorageBase in place, so any classic-mode screen accessed mid-Adventure
(deck editor, booster shop, simulate sealed) would read the plane-local
overrides instead of upstream data.

Replace that with a plane-scoped AdventureOverrides registry:

  - Overlay files are parsed the same way (CardBlock.Reader and
    CardEdition.Reader) but the results are held in an adventure-local
    map keyed by name / set code.
  - CardBlock gains a neutral setBoosterResolver hook; overlay blocks
    install a resolver that reads the registry, so BoosterDraft.setupPacks
    picks up the plane-local booster template without touching
    StaticData.getBoosters().
  - Adventure consumers (AdventureEventData, AdventureEventController)
    query the registry with upstream fallback; non-adventure callers keep
    reading the unmodified upstream data.

Drops the mutation helpers: StorageBase.replace, CardBlock /
CardEdition.applyAdventureOverrides.

* Make adventure block overrides additive via restrictedBlocks config

Per PR Card-Forge#10398 review: the Adventure Registry now adds overlay blocks
rather than shadowing upstream ones by name. Blocks that collide with
upstream names are skipped with a warning; to replace an upstream
block, the mod ships an overlay with a distinct name and lists the
upstream block in the plane's restrictedBlocks config entry.

ConfigData gains a restrictedBlocks array alongside the existing
restrictedCards / restrictedEditions fields, and AdventureOverrides
filters upstream blocks through it before iterating.

Shandalar Old Border is updated to the new shape: the overlay block
is renamed to "Ice Age (Old Border)" and the plane's config.json
restricts the upstream "Ice Age" block. The edition overlay for ICE
also gains the Date= field the upstream reader requires; without it
the overlay parser threw an NPE that was caught and logged, so the
snow-basic booster slot was never actually applied in earlier runs.

* Trim verbose comments in Old Border overlay data files

* Update nogi_draco_zealot.txt (Card-Forge#10402)

* Archetype.toString

* Refactoring

* Set basicLandEdition before adding basic lands

* Realm of legends 1.035: More life for normal; new capitol shop items (Card-Forge#10404)

* Mapfix

* Increased starting life total on normal

* New shop items

* Update improvisation_capstone.txt (Card-Forge#10403)

* Alchemy Books update (Card-Forge#10409)

* Update tome_of_the_infinite.txt

* Update tome_of_gadwick.txt

* Update unsubtle_mockery.txt

Closes Card-Forge#10412

* Clean up (Card-Forge#10414)

* Realm of legends 1.036: 100+ item buffs, 11 new items (Card-Forge#10419)

* Huge item rebalance; new items

* A few missed item tweaks added

* Balance tweaks

* Update spry_and_mighty.txt (Card-Forge#10420)

* Saga tweak (Card-Forge#10421)

* Change card type from Sorcery to Instant (Card-Forge#10425)

* Change card type from Instant to Sorcery (Card-Forge#10424)

* Realm of legends 1.037: Additional item tweaks (Card-Forge#10422)

* Minor item tweaks

* Cleaned up duplicated restricted list entry

* Added extra drop to urza dungeon

* Changed a shop item

* Restricted list edit

* Town fixes

* Enemy reward updates

* Fixed additional town issues

* Some more key card enhancements (Card-Forge#10405)

* Some more key card enhancements

* Don't double wrap keycards

* Update ChangeZoneAi.java

---------

Co-authored-by: tool4ever <therealtoolkit@hotmail.com>

* Working card image downloader (Card-Forge#10413)

* Working card image downloader

* Update i18n

---------

Co-authored-by: Hugh Kaznowski <hughkaznowski@Hughs-MacBook-Pro.local>

* Fix commander CardView desync on remote client (Card-Forge#10423)

copyChangedProps in TrackableCollectionType unconditionally copied
properties from incoming CardViews onto tracker instances. Cross-zone
reference lists (Commander, Flashback) hold stale CardView copies that
share IDs with zone collections. Processing Commander (ordinal 210)
before Battlefield (ordinal 216) overwrote the canonical instance with
stale zone/sickness/tap state, corrupting the client display.

Restore the pre-Card-Forge#9642 skip for CardViewCollectionType and
StackItemViewListType: swap to the tracker instance for identity
consistency (required by delta sync) but skip per-item property copying.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* Add network sync for auto-yield and trigger accept/decline (Card-Forge#10355)

Each human player now owns independent yield preferences. In local
multiplayer, Player A auto-yielding to an ability no longer affects
Player B.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: tool4EvEr <tool4EvEr@>

* Realm of legends 1.038: Assorted fixes and tweaks (Card-Forge#10428)

* Townfixes

* Item Update

* Item adjustments

* Fix to boss drop

* Mapfix

* Mapfixes

* Enemy visual fix

* Enemy visual fix

* Mapfix

* Boss drop fix

* Item tweak

* Update paradox_surveyor.txt (Card-Forge#10431)

* Post-match lobby cleanup and network concede fixes (Card-Forge#10410)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* Prepared spell (Card-Forge#10432)

* Prepared: add SplitMode and CardStateName

* Card: add prepared property

* Fix Meld CN (Card-Forge#10418)

* More preparing

* Add durations

* Support unpreparing

* Clean up

* Avoid Pull from Eternity

* Fix rollback

* Realm of legends 1.039: Added shops to roughly 30 dungeons (Card-Forge#10434)

* Item change

* Item change

* Added a ton of new shops

* Deckfix

* More added shops

* Edition updates: FDN, PF26, PW26, SCH, SLD, SOA, SOS

* missed artist

* Network wiki cleanup (Card-Forge#10436)

* Fix Token previewer (Card-Forge#10444)

* Update net-decks-commander.txt

* Update net-decks-commander.txt

* LangKorean: add South-Korean Support (Card-Forge#10441)

* Fix malformed Forge card file lines (Card-Forge#10449)

* ROL: Merchant fix (Card-Forge#10446)

* Merchant fix

* Merchant fix

* Mapfix

* Scripts for cards with prepare spells (Card-Forge#10408)

* Fix NPE and lobby spam on unregistered peer disconnects (Card-Forge#10453)

Any TCP connection that drops on the game-server port before completing
Forge's registration handshake (probes, crashed handshakes, failed
rejoins) triggered an NPE in ServerGameLobby.disconnectPlayer and
broadcast "null left the lobby." to real users.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Support prepared rendering on desktop  (Card-Forge#10459)

* feat(net): show all network interfaces when hosting a match (Card-Forge#10445)

* Realm of legends 1.041: A few small fixes (Card-Forge#10457)

* Fixed boss update that got lost at some point

* Mapfix

* Mapfix

* Restore mobile auto-yield persistence across matches (Card-Forge#10448)

Adds two new scope tiers to the auto-yield mode dropdown. AutoYieldStore
(per-LobbyPlayerHuman) holds Game/Match/Session buckets; PersistentYieldStore
(file-backed singleton at <userDir>/auto-yields.dat) holds the Install tier.
Moving storage off PlayerControllerHuman onto LobbyPlayerHuman makes
Per Ability (Each Match) yields actually survive between games of a match.

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

* Fix mobile network-client freeze on blocking dialog prompts (Card-Forge#10461)

`GameProtocolHandler` now dispatches protocol invocations to the libgdx
GL thread, so return-value methods like `order` run
`WaitCallback.invokeAndWait()` there. The `lock.wait()` blocks the thread
that needs to drain the posted dialog Runnable, silently freezing the
client.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Fix mobile "Always No" stack-menu item ending the turn (Card-Forge#10435)

Restores the InputConfirm guard lost in the 2014 GUI refactor
(b608d7e -> 3538823). Always Yes/No now fires immediately
only when the matching InputConfirm is active; otherwise just sets
the preference flag.

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Update emeritus_of_truce_swords_to_plowshares.txt

* Update gadwicks_first_duel.txt

Closes Card-Forge#10469

* Guard against redundant GameView sends in non-delta protocol (Card-Forge#10452)

Many RemoteClientGuiGame protocol methods prepend a setGameView that's
redundant when an event batch is about to flush — the flush already
carries a full GameView. The delta path guards against this via
!delta.isEmpty(); mirror that guard in the non-delta branch so all
20 callers of updateGameView() benefit, including the 11 that pre-date
the delta PR.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* Update Historic bans

* Old Border Shandalar: use fromSets() to pin ICE snow basics (Card-Forge#10472)

The ICE booster overlay pinned the snow-covered basic slot via |SET
suffix inside name(...), which the booster generator does not parse:
buildExtraPredicate routes name(...) through
PaperCardPredicates.names(...), comparing against card.getName() which
never carries the |SET suffix, so the slot dropped and packs opened
with 14 cards.

Switch to the existing fromSets("ICE") predicate chained after
name(...) with the : operator separator; both predicates AND together
to select ICE-printed snow basics. Packs now open with the intended
10C + 3U + 1R + 1 snow basic.

* - Add support for Prepared to AlterAttributeAi (don't prepare something that's already prepared) (Card-Forge#10481)

* Update surge_of_salvation.txt

Fixes Hexproof Problem

* SOC Commander Precons (Card-Forge#10455)

* Update Turtle Power! [TMC] [2026].dck

* Add files via upload

* Update nahiris_resolve.txt

* AiPreference for SoulBond allowing Deadeye navigator to ignore tokens (Card-Forge#10473)

* Update HumanCostDecision.java (Card-Forge#10468)

* Update HumanCostDecision.java

Adds a UI filter to HumanCostDecision that prevents incompatible cards from being selected when paying the exile cost if the +withSharedCardType condition is met.

* Use sharesCardTypeWith in HumanCostDecision

* Update HumanCostDecision.java

* Update HumanCostDecision.java

Format

---------

Co-authored-by: Hans Mackowiak <hanmac@gmx.de>

* Server URL button: route to interface-picker dialog with memory (Card-Forge#10475)

Remember the last-copied URL in a new NET_LAST_COPIED_URL pref. On open,
auto-copy and star the remembered row (fallback: first row); an italic
notice at the bottom confirms what was copied. Mobile continues to use
NetConnectUtil.copyHostedServerUrl — the new dialog is desktop-only Swing.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Highlight server warnings in multiplayer chat (Card-Forge#10437)

Adds a WARNING ChatMessage.MessageType, rendered as amber foreground
text on desktop (FNetOverlay) and an amber bubble background on mobile
(ChatMessageBubble), distinct from the existing blue system and default
player styles.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Realm of legends 1.042: Secrets of Strixhaven Precons + minor fixes (Card-Forge#10485)

* Mapfixes

* Secrets of strixhaven commander precons

* Paradigm: use Unique Name for Effect (Card-Forge#10486)

* Match PortAllocator probe to Netty wildcard bind (Card-Forge#10489)

Potential fix for <!-- -->Card-Forge#10488

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Adjust booster configuration and rarity replacements

* Update CostExile.java (Card-Forge#10467)

Fixes CostExile validation for +withSharedCardType so the cost works correctly when selecting three or more cards that share a common card type.

* Increment: make Trigger Secondary

* Replace funny fast // furious with comment (Card-Forge#10493)

Co-authored-by: Autumn Wind <209156905+autumnmyst@users.noreply.github.com>

* Old Border Shandalar: fix ICE snow basic distribution to all 5 colors (Card-Forge#10496)

Previously only Snow-Covered Plains appeared because BoosterGenerator's
name(...) parser does not trim whitespace after commas, so " Snow-Covered
Island" etc. never matched card.getName(). Remove the spaces after commas
in the booster slot list so all five snow basics are eligible.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Update kinetic_ooze.txt

Closes Card-Forge#10497

* Clean up (Card-Forge#10500)

* Update mutant_chain_reaction.txt

Closes Card-Forge#10501

* Update Doctor Who Commander.txt

* [maven-release-plugin] prepare release forge-2.0.12

* [maven-release-plugin] prepare for next development iteration

* Restore POM files for preparation of next release

* Extend IdRef serialization from game events to protocol method args (Card-Forge#10343)

Protocol methods were serializing the entire CardView/PlayerView object
graph for each argument. Add IdRef replacement at the Netty encoder/decoder
level: the server encoder swaps CardView/PlayerView with lightweight
IdRef(typeTag, id) markers, and the client decoder resolves them from the
Tracker. setGameView and openView are excluded (they carry the full state).

Testing revealed that after a zone change (e.g. playing a land from
hand), the server tracker holds a stale CardView with the old zone,
causing Game.findByView to search the wrong zone and return null. Added
a fallback global search in findByView when the zone-specific search
misses, rather than modifying tracker update behavior which has wide
blast radius.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* SOS prerelease placeholder

* Fix AI target selection for Saskia curse ability (Card-Forge#10487)

* Update finale_of_promise.txt

Closes Card-Forge#10494

* Change CastTrigger mode from SpellAbilityCast to SpellCast

Closes Card-Forge#10509

* [RoL] Fixed Winter Boots (Card-Forge#10513)

Fixed Winter Boots being a body slot item

* Change power/toughness of Spirit of Resilience

* Change type from Artifact to Legendary Artifact

* Fix scripts

* Migrate upcoming cards

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

* Fix Unglued token collector numbers to match Scryfall TUGL

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>

* Crop rounded-border fringe on token images

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>

* Filter token edition selection by adventure allowedEditions/restrictedEditions

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>

* Pin token edition per game so same-type tokens share art

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>

* Refine fallback token edition selection: restrict entries and prefer 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>

* Consult token-images.txt URL map at runtime for token downloads

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>

* Add Magic Player Rewards 2002 and Duelist Magazine edition files

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>

* Add Duelist token URL map entries hosted on oldborder-shandalar.net

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>

* Old Border Shandalar: expand token edition pool and block modern-frame 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>

* Old Border Shandalar: register 55 new token renders

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>

* Old Border Shandalar: drop dead one-arg fallbackToken/getTokenFromEditions 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>

* Old Border Shandalar: switch token CDN URLs to .jpg to match resized renders

The hosted tokens are now 488x680 JPEG (Scryfall normal size), so the URL
map points to .jpg instead of .png. Local cache key (left side, .jpg) is
unchanged.

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Realm of legends 1.043: Small fixes (Card-Forge#10527)

* Item adjustment

* Mapfix

* Fix for Maze of Ith in multiplayer (Card-Forge#10504)

* Player: refactor extra playLand ability (Card-Forge#10528)

* KeywordCollection: remove View for now (Card-Forge#10516)

* KeywordCollection: remove View for now

* KeywordCollection implements ICardTraitChanges

---------

Co-authored-by: Fulgur14 <54345051+Fulgur14@users.noreply.github.com>
Co-authored-by: Serafina <serafina2880@gmail.com>
Co-authored-by: Vanja <56617195+vanja-ivancevic@users.noreply.github.com>
Co-authored-by: Hans Mackowiak <hanmac@gmx.de>
Co-authored-by: Paul Hammerton <paulhammerton1@hotmail.co.uk>
Co-authored-by: Paul Hammerton <18243520+paulsnoops@users.noreply.github.com>
Co-authored-by: Clair Marchesani <clair.chiara@gmail.com>
Co-authored-by: Jetz72 <Jetz722@gmail.com>
Co-authored-by: AlexandreCMF <alexandre.cmf2000@gmail.com>
Co-authored-by: MostCromulent <201167372+MostCromulent@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: tool4ever <therealtoolkit@hotmail.com>
Co-authored-by: AncoronDS <xancoronx@gmail.com>
Co-authored-by: Simisays <67333662+Simisays@users.noreply.github.com>
Co-authored-by: Chris H <zenchristo@gmail.com>
Co-authored-by: billyhewlett <billy.hewlett@gmail.com>
Co-authored-by: agylesox <92274624+agylesox@users.noreply.github.com>
Co-authored-by: Jackie Ng <jumpinjackie@gmail.com>
Co-authored-by: Agetian <stavdev@mail.ru>
Co-authored-by: autumnmyst <autumnonthewind@gmail.com>
Co-authored-by: autumnmyst <209156905+autumnmyst@users.noreply.github.com>
Co-authored-by: tool4EvEr <tool4EvEr@>
Co-authored-by: NathanRoy1 <145686674+NathanRoy1@users.noreply.github.com>
Co-authored-by: langus132 <langus@kismicro.com>
Co-authored-by: GroundThing <68763301+GroundThing@users.noreply.github.com>
Co-authored-by: Klisz <kennercat@gmail.com>
Co-authored-by: Przemyslaw Hugh Kaznowski <hughkaznowski@protonmail.com>
Co-authored-by: Hugh Kaznowski <hughkaznowski@Hughs-MacBook-Pro.local>
Co-authored-by: Felix <10831300+flxai@users.noreply.github.com>
Co-authored-by: Rafael Henrique <rafael.h.g.oliveira@gmail.com>
Co-authored-by: Tomáš Beneda <tomas.beneda@gmail.com>
Co-authored-by: Akse1ot <krekrti@gmail.com>
Co-authored-by: GitHub Actions <actions@github.com>
Co-authored-by: Madwand99 <Madwand99@gmail.com>
Co-authored-by: drast35 <44370391+drast35@users.noreply.github.com>
Co-authored-by: TRT <>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Rules compliance Bringing the engine or cards closer to CR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants