Ars 'n Spells 3.0.3 (Forge 1.20.1)
Curse Maven Snippet
What's new
[3.0.3] - 2026-07-16
Fixed: bound Ars spells cast but did nothing (the reported 3.0.x bug)
Root cause. Iron's casts spellbooks from the Curios spellbook slot, and
Utils.serverSideInitiateCast passes ItemStack.EMPTY to attemptInitiateCast, which stores it
verbatim via setPlayerCastingItem. So MagicData.getPlayerCastingItem() is always empty for a
spellbook cast. The proxy spell read exactly that to find the book carrying its Ars payload, found
nothing, and returned — while Iron's had already played the full cast animation, sound and
cooldown. Every bound spell cast as a no-op; the native-wheel feature could never work as
shipped.
- The proxy now resolves its book through a real chain: the recorded casting item (still correct for the Scroll/casting-implement paths), then the equipped Curios spellbook, then the hands. A candidate must actually carry that proxy's pool id, so several bound books never disambiguate wrongly.
- Spell Loom names and icons now show in the native wheel. The client-side lookup also only checked the hands, so a loom-authored name/icon never resolved and the wheel always showed the fallback.
- Proxy casts no longer count as Iron's ENDER casts. The proxy is registered under the ENDER school
as an implementation detail, and ANS's own Iron's-side handlers were treating it as a genuine
Iron's cast: ENDER affinity and progression were credited (wrong school, and double-counted
against the delegated Ars cast, which the Ars-side handlers already credit); with a Covenant
Cursed Ring, LP could be charged twice; and with
enable_cooldown_system+enable_cross_mod_cooldowns, the proxy took a MOVEMENT cooldown that then silently cancelled the Ars spell it delegates to whenever that spell was also MOVEMENT (any Blink-style spell) — a second, config-dependent "casts but does nothing". Note: existing ENDER affinity/progression accrued from proxy casts before 3.0.3 is left as-is; this release only stops further accrual. Amounts should be small, since those casts never actually resolved a spell. - Both bind paths (
/ans bind_scroll_to_irons_bookand the Spellbook Binding ritual) now refuse a carrier scroll whosears_spellpayload no longer deserializes to a castable spell (empty or unreadable recipe — e.g. data exported on a different Ars Nouveau version). Such a payload used to bind successfully and then no-op on every cast. - Cast-time safety net for duds already in the wild: an unreadable bound spell is now detected before
dispatch and tells the player to rebind instead of failing mutely. The check is deliberately made
on our side rather than delegated to Ars: Ars'
castSpellreportsSUCCESSfor an invalid spell whenever it is given a message to show, so handing it one would have marked a cast that never resolved as successful — granting the advancement, loggingsuccess=true, and leaking a cast context that overcharges the player's next ordinary Ars cast. - The proxy's remaining bail-outs now WARN in the server log (including the cast source and the
equipment slot Iron's believed the cast came from) and show an action-bar message, so a failed
cast is diagnosable from
latest.logwithoutdebug_mode. A cast the player explicitly triggered should never fail invisibly — that silence is why this bug shipped and why the original report carried no diagnostic information. - Binding is now atomic: if mirroring the proxy slot into Iron's native container fails, the sidecar
entry is rolled back (new
CrossCastNbt.removeEntryByProxyPoolId) instead of leaving a book whose sidecar and wheel disagree. /ans bind_scroll_to_irons_booknow honorsmax_ars_cross_spells_per_irons_spellbooklike the ritual (with a distinct book-full message) and carries a Spell Loom scroll's custom name/nature/icon onto the book, so op-bound books match ritual-bound ones. (Theallow_ars_spells_in_irons_spellbooksgate intentionally still does not apply to the op-level command.)- New end-to-end GameTests cast a bound spell through the real proxy path — book equipped in the Curios slot, hands empty, casting item left EMPTY exactly as Iron's leaves it — in creative and in survival with mana. A further test pins Iron's "spellbook casts record no casting item" contract, so if a future Iron's changes it we find out. The cast leg previously had no coverage at all, and the first drafts of these tests set the casting item themselves, which would have made them pass against the broken code.
Known limitation
Ars' ISpellCaster.castSpell derives the spell's caster tool from the player's hand rather than
from the book, so casting a Curios-equipped bound spell while holding a Caster Tome applies the
Tome's 50% Ars cost discount. Cosmetic to the cast itself; a follow-up release will dispatch the
resolver directly and pass the resolved book as the spell context.
This mod has no additional files

