mcpField
P
proxy-printer

proxy-printer

github.com/dan-blanchard文档处理22226 次安装2 天前更新
代码仓库

关于 proxy-printer

proxy-printer 是面向 Magic: The Gathering 玩家及套牌构建工作流的技能,可将解析后的牌表生成卡牌与衍生物代理卡 PDF。它通过 Scryfall 查询确定打印内容,并提供 ASCII 插画目录。

主要功能

  1. 01生成卡牌代理 PDF
  2. 02生成去重的衍生物代理 PDF
  3. 03从 Scryfall 获取卡牌数据
  4. 04支持多种纸张尺寸与副本数
  5. 05按牌型和名称选择 ASCII 插画

适用场景

  1. 01将牌表打印为实体代理卡
  2. 02为套牌生成对应衍生物代理卡
  3. 03从 TCGPlayer CSV 或 Moxfield 文本制作打印文件

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dan-blanchard/mtg-skills --skill proxy-printer

安装后在 Claude Code 中输入/proxy-printer确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

CONTEXT.md
pyproject.toml
uv.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,会先查带署名的目录,再查本地目录。第一个匹配项优先:

  1. 解析 type_line。对于 — 之后的每个子类型,按顺序查找 (Vampire Knight → vampire,然后是 knight):
    • 尝试 attributed/<sub>.txt
    • 尝试 local/<sub>.txt
  2. 如果没有子类型匹配,则遍历卡牌类型词(跳过 Token/Legendary/Snow/Tribal/Basic 等元词)。对于每种卡牌类型:
    • 尝试 attributed/<card-type>.txt
    • 尝试 local/<card-type>.txt
  3. 最终回退: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

按名称获取的流程会按以下顺序尝试两个来源:

  1. asciiart.eu 全名搜索(/search?q=<full name>)。 会匹配完整作品标题,因此多词 MTG 名称通常能找到结果——Lightning Bolt → 闪电 ASCII 艺术,Black Lotus → 莲花,Sword of Truth and Justice → 剑。
  2. 如果 (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.

看到此警告时,请主动提出为这些卡牌手绘占位艺术图。 这是在填补目录缺口。步骤如下:

  1. 阅读 2-3 个风格参考,从 mtg-utils/src/mtg_utils/data/card_art/*.txt 中挑选主题与各张卡牌相关的文件(例如,寺庙主题的地牌可以参考 temple.txt、monument.txt 或其他建筑题材作品)。这些文件展示了现有作品的尺寸限制、ASCII 表现手法和美学风格。
  2. 为每张卡牌绘制一幅小型 ASCII 画作,宽度不超过 30 个字符 × 高度不超过 18 行。尺寸限制与抓取器相同;渲染器会自动缩放字体,以适应固定的艺术区域。保持画面感——用形状和线条描绘物体,不要用字母代替形状(参见记忆条目 feedback_ascii_art_no_labels.md)。
  3. 将每个文件写入 $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 …);署名留空即可。
  4. 重新运行 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 独立运行——代理牌用于在家打印,而非用于采购。

评论

支持 Markdown