Skip to content

Use any card's art as a deck sleeve#10994

Open
MostCromulent wants to merge 1 commit into
Card-Forge:masterfrom
MostCromulent:CardArtSleeves
Open

Use any card's art as a deck sleeve#10994
MostCromulent wants to merge 1 commit into
Card-Forge:masterfrom
MostCromulent:CardArtSleeves

Conversation

@MostCromulent

@MostCromulent MostCromulent commented Jun 14, 2026

Copy link
Copy Markdown
Contributor
Screenshot 2026-06-14 094055 Screenshot 2026-06-14 094120 Screenshot 2026-06-14 112138

What it does

Select any card's art as a deck sleeve. You pick a card from a dialog; chosen art renders in the lobby and in-match exactly where the built-in sleeves do, styled to match them, on both desktop and mobile.

How it works

A player's sleeve is stored as either a built-in sleeve index or a card image key, carried on LobbyPlayer/Player/PlayerView and exposed as a TrackableProperty so opponents see the choice; it travels over the wire in UpdateLobbyPlayerEvent.

Two preferences persist the choice across sessions: UI_SLEEVE_ART_LIBRARY holds the saved "Card Art Sleeves" library, and UI_SLEEVE_ART_KEYS holds the per-lobby-slot selection — sitting parallel to the existing UI_SLEEVES (built-in index per slot), so a slot using card art stores its key here while choosing a built-in sleeve clears it. Both are stored as comma-joined, URL-safe-base64-encoded image keys so card identifiers stay valid in the KEY=VALUE preference format.

The art itself comes from Scryfall's art_crop:

  • When a card-art sleeve is needed, the existing Scryfall image fetcher is reused but forced to the art_crop variant (Scryfall's tightly-cropped artwork), regardless of the user's UI_CARD_ART_FORMAT preference. It's gated behind the online-image-fetcher preference and skips cards with no usable art_crop (custom cards, or those missing an artist / collector number).
  • The download is cached under a dedicated sleeves cache (CACHE_SLEEVE_PICS_DIR), keyed by a hash of the image key with an .artcrop.jpg filename — chosen so the fetcher's Scryfall URL rewriting leaves it as the art_crop image.
  • At render time the cached art_crop is centre-cropped to the built-in sleeve aspect and framed. The fetch is async — until the art lands, the built-in sleeve shows in its place.

Safety

The only thing sent over the network is a card image key (a card identifier) — never a URL or an image file. Each client independently derives the Scryfall art_crop from that key through its own preference-gated fetch path, so a player cannot point opponents at an arbitrary URL or push image bytes to them; an unrecognised key simply falls back to the built-in sleeve.


🤖 Generated with Claude Code

Let a player use any card's art as their deck-back sleeve, alongside the
built-in sleeves. A picker dialog chooses the card; chosen art is saved to
a per-user library (the UI_SLEEVE_ART_LIBRARY preference). Card-art sleeves
show in the lobby and in-match wherever the built-in sleeves do, on desktop
and mobile.

The sleeve is stored as either a built-in index or a card image key on
LobbyPlayer/Player/PlayerView, exposed as a TrackableProperty and sent in
UpdateLobbyPlayerEvent so opponents see it. Only the image key travels over
the network -- never a URL or image file; each client derives the art
itself, and an unresolved key falls back to the built-in sleeve.

The art is Scryfall's art_crop: the existing image fetcher is reused but
forced to the art_crop variant (regardless of UI_CARD_ART_FORMAT), gated by
the online-image-fetcher preference, cached under CACHE_SLEEVE_PICS_DIR by a
hash of the image key. At render time it is centre-cropped to the built-in
sleeve aspect and framed to match them -- a charcoal border plus a diagonal
bevel on desktop, a charcoal border on mobile.

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

MostCromulent commented Jun 14, 2026

Copy link
Copy Markdown
Contributor Author

Since this just uses a card identifier to fetch the relevant scryfall art, it opens up some fun design space for future development: e.g. Adventure Mode enemies could have an optional field to use a specific card's art as their sleeve / player decks could designate sleeve art as metadata.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant