关于 proxy-printer
proxy-printer 是面向 Magic: The Gathering 玩家及套牌构建工作流的技能,可将解析后的牌表生成卡牌与衍生物代理卡 PDF。它通过 Scryfall 查询确定打印内容,并提供 ASCII 插画目录。
主要功能
- 01生成卡牌代理 PDF
- 02生成去重的衍生物代理 PDF
- 03从 Scryfall 获取卡牌数据
- 04支持多种纸张尺寸与副本数
- 05按牌型和名称选择 ASCII 插画
适用场景
- 01将牌表打印为实体代理卡
- 02为套牌生成对应衍生物代理卡
- 03从 TCGPlayer CSV 或 Moxfield 文本制作打印文件
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ dan-blanchard/ mtg-skills --skill proxy-printer安装后在 Claude Code 中输入/proxy-printer确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
CONTEXT.mdpyproject.tomluv.lock详细介绍
代理牌打印器
将解析后的 MTG 牌组列表转换为可打印的代理牌 PDF。此技能会生成
两个文件:cards.pdf(牌组中每张牌的每个副本各一张代理牌)和
tokens.pdf(牌组中任意牌产生的每种不同衍生物各一张代理牌,按 Scryfall oracle_id 去重)。两者使用相同的渲染模板:
名称横幅、按牌张副类别显示的 ASCII 艺术、类别横幅、Oracle 文本、力量/防御力。
此技能既可独立调用(用户提供牌表,由 Agent 打印 PDF),也可由其他向导调用——deck-wizard 和 cube-wizard 都会生成 此技能所需的已解析牌组 JSON 架构。
铁律
绝不使用训练数据中的 Oracle 文本来渲染代理牌。 生成的 PDF 上每张牌的名称、法术力费用、类别行、Oracle 文本、力量/防御力和衍生物一侧的属性,都必须来自 proxy-print 执行的 Scryfall 查询。CLI 是权威的渲染器;Agent 不得“修正”任何打印出来的内容。
何时使用此技能
- 用户提供牌组列表并要求打印代理牌。
- 用户提供 TCGPlayer 订单 CSV、Moxfield txt 或纯文本牌表,并想要实体打印这些牌。
- 更高级别的技能(deck-wizard、cube-wizard)希望在构筑流程结束时生成可打印的文件。
工作流
[raw deck list] → parse-deck → deck.json → proxy-print --kind cards → cards.pdf
\→ proxy-print --kind tokens → tokens.pdf
步骤 1 — 解析输入
如果用户提供的不是已解析的牌组 JSON,先运行
parse-deck 以生成规范架构。parse-deck 已支持 Moxfield、MTGO、纯文本和 CSV(包括
TCGPlayer 订单 CSV 格式)。
parse-deck input.txt > /tmp/deck.json
步骤 2 — 按需刷新批量数据
proxy-print 从 Scryfall 批量 JSON 读取数据。如果缓存文件
已超过 7 天,CLI 会以代码 1 退出,并提示查看此处。
运行:
download-mtgjson
仅需执行一次左右:如果想在代理牌上注明艺术家,请先填充 带署名的目录(通常运行
fetch-art --from-deck deck.json即可;约需 15 秒,而完整扫描约需 108 秒)。参见下文的 ASCII 艺术目录。
步骤 3 — 渲染牌张
proxy-print --kind cards \
--deck /tmp/deck.json \
--bulk-data /tmp/scryfall-bulk/default-cards.json \
--out /tmp/cards.pdf
步骤 4 — 渲染衍生物
proxy-print --kind tokens \
--deck /tmp/deck.json \
--bulk-data /tmp/scryfall-bulk/default-cards.json \
--out /tmp/tokens.pdf
这两个渲染步骤有意分开,这样如果牌组变更只影响牌张(或只影响衍生物列表),用户就能只重新打印其中一部分。
CLI 参考
proxy-print --kind {cards,tokens} --deck DECK.json --out OUT.pdf [options]
| 标志 | 必需 | 默认值 | 说明 |
|---|---|---|---|
--kind | 是 | — | cards 或 tokens |
--deck PATH | 是 | — | 已解析的牌组 JSON |
--out PATH | 是 | — | 输出 PDF 路径 |
--bulk-data PATH | 否 | 自动 | Scryfall 批量 JSON;自动解析缓存的默认文件 |
--page-size letter|a4 | 否 | letter | 页面尺寸 |
--copies N | 否 | 1 | 每张牌 / 衍生物额外打印的副本数 |
--include-sideboard | 否 | 开启 | 牌张模式;使用 --no-sideboard 切换 |
--no-sideboard | 否 | 关闭 | 牌张模式 |
--report-art-coverage | 否 | 关闭 | 衍生物模式;将每种衍生物的 JSON 输出到 stderr |
退出代码:0 成功,1 批量数据缺失或过期,2 牌组 JSON 无效,3 输出路径不可写,4 渲染错误。
布局
牌张和衍生物共用一个渲染模板;版面比例会根据牌张的 Oracle 文本长度进行调整。
┌───────────────────────────────┐
│ ╔══════════════════════════╗ │ name banner
│ ║ NAME {COST} ║ │ (cost omitted for tokens)
├─╚══════════════════════════╝──┤
│ (ASCII art) │ art region (proportional)
├───────────────────────────────┤
│ ╔══════════════════════════╗ │ type banner
│ ║ Type — Subtype {C} ║ │
├─╚══════════════════════════╝──┤
│ oracle text │ oracle region (proportional)
│ ┌─────┐ │
│ │ P/T │ │
└───────────────────────┴─────┴─┘
牌张尺寸:2.5″ × 3.5″。网格:Letter 或 A4 页面上每页 3 × 3 = 9 张。
ASCII 艺术目录
艺术来自两个层级,其中带署名的目录建立在手工整理的本地目录之上:
- 本地目录 — 随仓库一同提供,位于
mtg-utils/src/mtg_utils/data/card_art/。每种卡牌子类型对应一个.txt文件 (生物/神器/结界/地类别),另有卡牌类型回退文件(creature.txt、artifact.txt、enchantment.txt、land.txt、sorcery.txt、instant.txt、planeswalker.txt)以及最终回退文件_generic.txt。手工整理的 ASCII 艺术,不带署名。 - 带署名的目录 — 用户填充的缓存,位于
$MTG_SKILLS_CACHE_DIR/attributed-art/(默认路径为~/.cache/mtg-skills/attributed-art/)。文件包含 3 行标头,注明标题、来源和许可证。艺术来自此目录时,代理会在左下角页脚显示art by <Name>,与力量/防御力位于同一行(真实万智牌卡牌上的画师署名位置)。
查找链
对于每张卡牌,查找会按顺序遍历 slug——先子类型,再卡牌类型,最后是 _generic。对于每个 slug,会先查带署名的目录,再查本地目录。第一个匹配项优先:
- 解析
type_line。对于—之后的每个子类型,按顺序查找 (Vampire Knight→vampire,然后是knight):- 尝试
attributed/<sub>.txt - 尝试
local/<sub>.txt
- 尝试
- 如果没有子类型匹配,则遍历卡牌类型词(跳过 Token/Legendary/Snow/Tribal/Basic 等元词)。对于每种卡牌类型:
- 尝试
attributed/<card-type>.txt - 尝试
local/<card-type>.txt
- 尝试
- 最终回退:
local/_generic.txt。
这种按 slug 交错查找的方式(而非先遍历署名层级、再遍历本地层级)意味着,手工整理的本地 Vampire 会优先于通用的带署名 Creature,这通常正是你想要的效果。请参阅
docs/adr/0006-attributed-art-catalog.md。
艺术设计上不受力量/防御力影响——每个 Soldier 衍生物都共用
soldier.txt;力量/防御力会以文本形式显示在代理上。
填充带归属信息的目录(大致只需一次)
带归属信息的目录初始为空。使用 fetch-art 填充,它会从 Scryfall 的目录端点获取每个 MTG 子类型,从两个 ASCII 艺术来源中挖掘候选作品(asciiart.eu 分类页面,以及 Christopher Johnson 在 asciiart.website 上的作品集;从其 browse.php?show=tags 自动发现约 1148 个标签——当分类将 MTG 概念与系列作品混为一谈时,标签会直接映射到 MTG 概念),按目标尺寸 20×10 评分(硬性上限为 30×18),并写入带归属信息的 .txt 文件,其中包含 proxy-print 能读取的 3 行许可声明。每个文件的声明都指向对应来源的归属条款;asciiart.website 的声明会如实注明“个人用途代理卡”,而不会声称该网站并未授予的许可。
对于每副牌组的工作流(建议用于日常代理卡打印),将获取范围缩小到牌组实际使用的子类型(以及牌组通过 Scryfall 的 all_parts 生成的每个衍生物的子类型):
fetch-art --from-deck /tmp/deck.json
一副典型的 Commander 牌组大约有 30 种不同子类型 → 大约 30 次标签获取,每次约 0.4 秒(冷缓存约 15 秒,有 7 天缓存时几乎瞬间完成)。完整扫描(不加 --from-deck)在冷缓存时约需 108 秒,只有在打算为许多不同牌组打印代理卡时才值得运行。
添加 --by-name,还可以获取单张卡牌名称对应的作品——这些作品用于 proxy-print 中的差异化处理(因此,如果有可用作品,共享同一子类型作品的多张不同名称卡牌也会各自获得一幅作品):
fetch-art --from-deck /tmp/deck.json --by-name
按名称获取的流程会按以下顺序尝试两个来源:
- asciiart.eu 全名搜索(
/search?q=<full name>)。 会匹配完整作品标题,因此多词 MTG 名称通常能找到结果——Lightning Bolt → 闪电 ASCII 艺术,Black Lotus → 莲花,Sword of Truth and Justice → 剑。 - 如果 (1) 没有返回结果,则回退到 asciiart.website 逐词搜索。 该网站的搜索匹配的是标签名称,而不是标题,因此我们会拆分卡牌名称,并在其 API 上逐一尝试每个单词(至少 4 个字符;底层会使用 CSRF 和表单 POST)。例如,“Brain Maggot” → “Brain” → 一幅大脑作品;“Llanowar Elves” → “Elves” → 一幅精灵作品(如果有符合 30×18 尺寸限制的作品)。
在预算范围内找不到任何匹配作品的卡牌,会在渲染时回退到按类型匹配的作品。
fetch-art
HTTP 响应会在磁盘上缓存 7 天,缓存路径为
$MTG_SKILLS_CACHE_DIR/ascii-art-fetcher/,因此重复运行的成本很低。添加
--report-missing 可查看所有没有合适候选作品的子类型——这些子类型会在渲染时回退到本地目录。
仅限 MTG 的机制或系列/时空名称子类型(Treasure、Saga、Innistrad 等)会有意跳过;这些由本地目录处理。
差异化处理找不到唯一艺术图时,手动创作
差异化处理会在同一类型分组中,按名称查找卡牌,但只能换用目录中实际存在的艺术图。对于 Mana Confluence 或 Temple of Malady 这类 MTG 特有的概念名称,asciiart.eu 和 asciiart.website 通常没有符合预算的素材。遇到这种情况时,proxy-print 会输出
WARN: 3 cards share land.txt (Mana Confluence, Temple of Abandon, Temple of Malady). Consider hand-curating name-keyed art.
看到此警告时,请主动提出为这些卡牌手绘占位艺术图。 这是在填补目录缺口。步骤如下:
- 阅读 2-3 个风格参考,从
mtg-utils/src/mtg_utils/data/card_art/*.txt中挑选主题与各张卡牌相关的文件(例如,寺庙主题的地牌可以参考temple.txt、monument.txt或其他建筑题材作品)。这些文件展示了现有作品的尺寸限制、ASCII 表现手法和美学风格。 - 为每张卡牌绘制一幅小型 ASCII 画作,宽度不超过 30 个字符 × 高度不超过 18 行。尺寸限制与抓取器相同;渲染器会自动缩放字体,以适应固定的艺术区域。保持画面感——用形状和线条描绘物体,不要用字母代替形状(参见记忆条目
feedback_ascii_art_no_labels.md)。 - 将每个文件写入
$MTG_SKILLS_CACHE_DIR/attributed-art/<name-slug>.txt(默认路径为~/.cache/mtg-skills/attributed-art/<name-slug>.txt),并使用三行的署名艺术图标头:
渲染器会通过# <Title> (hand-drawn for proxy run) # Source: hand-drawn ASCII # Personal-use proxy <blank line> <art body>lookup_art_by_name载入(name-slug).txt,将解析标记为tier="name",并在页脚位置显示署名(取自(by <name>)括号内容)。手绘作品的标头可以省略(by …);署名留空即可。 - 重新运行
proxy-print——使用相同的命令,不更改标志。差异化处理会自动载入新文件;无需重新抓取。
这是最后的手段。快速路径是 fetch-art --from-deck deck.json --by-name;只有搜索不到的卡牌才需要手动创作。
页脚位置
类型栏下方左侧的条带预留给艺术家署名(art by <Name>),有署名艺术图时会显示。Token 不会渲染 from: <source> 行——玩家知道是哪张咒语创建了 Token,因为他们刚刚施放了该咒语;牌组列表也包含相同信息。将该位置留给艺术家署名,可让 Token 与真实 MTG 卡牌一样,在左下方显示署名。
艺术图内部的签名(嵌入 ASCII 图中的艺术家姓名首字母)会在抓取时原样保留,并且已独立满足 asciiart.eu 的常见问题中的署名要求,无需依赖页脚。
类型栏位置
对于非 Token卡牌,类型栏的底边固定在 y + CARD_H / 3——即从卡牌底部向上 1/3 处,与真实 MTG 卡牌的类别行位置一致。所有卡牌的艺术区域高度相同(约 128 pt,足以容纳高度约为 9 pt 的 14 行画作);神谕文本填充类型栏下方的所有空间。神谕文本较短时,其下方会留白,而不是移动类型栏(这也与真实 MTG 卡牌一致)。
Token 保留旧版动态布局——它们很少有神谕文本,因此类型栏靠近底部、紧贴力量/防御力的外观更接近真实 MTG Token 框架。
解读 WARN: 输出
proxy-print 会将警告写入 stderr,但退出码为 0。需要识别以下两种情况:
WARN: missing from bulk: <name>——Scryfall 的缓存 bulk 数据中没有这张卡。最常见的原因是卡牌使用了异名,例如 “Paradise Chocobo”(即 “Birds of Paradise” 的 FIC 印刷版本)。用户应检查源列表并修正名称;如果是全新系列,则应刷新 bulk 数据。WARN: token id <id> from <source>——某张卡牌的all_parts引用了本地 bulk 数据中不存在的 Token ID。这种情况应该很少见,可以放心忽略。
不要自动升级处理任何一种情况。告知用户跳过了哪些卡牌,然后继续。
常见陷阱
- 不要改写 Oracle 文本。 如果生成的 PDF 中 Oracle 文本被截断,请调整布局(渲染器会自动将字号从 9.5pt 缩小到 6.5pt)——不要编辑文本内容。
- 不要手动添加衍生物。 如果某张牌「应该」生成一个衍生物,但它没有出现在生成的 tokens.pdf 中,这是因为 Scryfall 的
all_parts没有将它关联起来。自定义/自制衍生物不在范围内。 - 不要动辄运行
download-mtgjson。 它会下载约 500MB。只有当proxy-print以代码 1 退出并提示你刷新时,才进行刷新。 - 不要合并这两个 PDF。 它们本来就是分开的——游戏过程中,衍生物放在一旁,牌放在牌库里。用户几乎总是希望分别打印或替换它们。
限制
- Scryfall 中没有的自定义/自制衍生物会被静默跳过。
- v1 不支持基于图像的代理牌(Scryfall 插画)。
- 不会绘制裁切辅助线/裁切标记。
- 不会渲染双面牌的背面(代理牌上只显示正面;两面的 Oracle 文本会合并)。
- 不在范围内支持符号字体的法术力费用渲染;法术力费用使用 Scryfall 花括号格式(例如
{2}{B}{R})。
跨技能使用
- deck-wizard 可在调校牌组后调用
proxy-print,将可打印文件与牌组 JSON 一并交付。 - cube-wizard 使用解析后的立方体 JSON;就
proxy-print而言,其结构与解析后的牌组 JSON 兼容(包含指挥官和牌张列表,不含备牌)。 - lgs-search 独立运行——代理牌用于在家打印,而非用于采购。