msw-painter

msw-painter

当 msw-search 找不到合适的精灵 RUID 时,直接用 SVG / HTML5 Canvas / HTML 代码绘制像素风格精灵,渲染为 PNG,并通过 msw-mcp 资源上传工具上传以获取精灵 RUID(如果未连接上传工具,则引导用户通过 Maker 注册)。支持两种风格模式:chunky pixel(复古/图标/瓦片风格)和 maple cartoon(冒险岛风格角色/NPC 风格)。触发词:直接绘制精灵、创建精灵、图像生成、自定义图形、像素艺术、卡通精灵、枫叶风格、Q版角色、画家、画精灵、制作图标、直接创建 NPC 图像、画史莱姆、自定义精灵。

32Star
2Fork
更新于 2026/7/29
SKILL.md
readonly只读
name
msw-painter
description

当 msw-search 找不到合适的精灵 RUID 时,直接用 SVG / HTML5 Canvas / HTML 代码绘制像素风格精灵,渲染为 PNG,并通过 msw-mcp 资源上传工具上传以获取精灵 RUID(如果未连接上传工具,则引导用户通过 Maker 注册)。支持两种风格模式:chunky pixel(复古/图标/瓦片风格)和 maple cartoon(冒险岛风格角色/NPC 风格)。触发词:直接绘制精灵、创建精灵、图像生成、自定义图形、像素艺术、卡通精灵、枫叶风格、Q版角色、画家、画精灵、制作图标、直接创建 NPC 图像、画史莱姆、自定义精灵。

MSW Painter

一个将手绘像素精灵注册为精灵资源的工作流程。首先调用 msw-search,仅在未找到合适的 RUID 时才调用此技能。

此技能专用于精灵类别。不处理动画/音频/头像/图集。

画家支持两种像素艺术风格chunky pixel(复古,图标/瓦片风格)和 maple cartoon(冒险岛风格,角色/NPC 风格)。在编写代码前选择一种——参见下面的步骤 2。


何时调用

情况 操作
用户想要特定精灵 首先使用 msw-search(资源搜索部分,精灵类别)
msw-search 返回匹配意图的 RUID 直接使用该 RUID。不要调用画家。
无搜索结果,或所有结果都不合适 调用画家 → 直接创建
用户明确说“我需要一个手绘风格的角色/图标” 直接调用画家

工作流程

  1. 选择媒介 — SVG / Canvas / HTML 之一。参见“选择媒介”部分。
  2. 选择风格chunkymaple。参见“选择风格”部分。
  3. 决定尺寸 — 参见 references/size-guide.md。默认为 128×128。
  4. 编写代码 — 遵循所选风格的规则:
  5. 渲染为 PNG — 运行 scripts/render.cjs
  6. 上传资源 — 使用 msw-mcp 资源上传工具,两步预签名模式(§5)。如果连接的 MCP 没有上传工具,请用户通过 Maker 注册 PNG。
  7. 注册精灵属性 — 上传后立即调用 asset_update_resource_storage_infofilter_mode / wrap_mode / pivot,以及 UI 框架精灵的九宫格边框。参见下面的“步骤 4”。
  8. 报告结果 — RUID + 1–2 句描述(包括使用的风格)。实体放置/脚本应用不在画家范围内。

1. 选择媒介

媒介 推荐用途 优势
SVG 图标、标志、简单角色、基于形状的像素艺术 代码直观,易于放置 1px <rect>
Canvas 程序化图案、迭代逻辑(循环绘制的纹理/噪声) 通过 JS 编程逻辑生成复杂图案
HTML 可通过 CSS 快速设置样式的复合布局 很少使用——SVG/Canvas 通常更适合像素艺术

最小 SVG 模板

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"
     width="100%" height="100%" preserveAspectRatio="xMidYMid meet"
     style="image-rendering: pixelated;">
  <rect x="6" y="2" width="1" height="1" fill="#4A90D9"/>
  <!-- 用 1px 矩形逐个放置点 -->
</svg>

⚠️ 使用 width="100%" height="100%"不是固定像素数)。SVG 元素在 render.cjs 视口中以其自身声明的尺寸绘制——如果你硬编码 128 但以 --width 1024 渲染,SVG 仅填充左上角 128px,PNG 其余部分透明。100% 使 SVG 填充 --width/--height 指定的任何画布。

最小 Canvas 模板

// `c`(canvas 元素)和 `ctx`(2D 上下文)由 render.cjs 自动暴露。
// ctx.imageSmoothingEnabled = false 也会自动应用。
// 重要:从 c.width 推导缩放比例,而不是硬编码常量——否则
// 不同的 --width 会导致画布右下角空白。
const GRID = 16;
const scale = c.width / GRID;  // 16×16 逻辑网格 → 画布大小的输出
ctx.fillStyle = '#4A90D9';
ctx.fillRect(6 * scale, 2 * scale, scale, scale);

最小 HTML 模板

<!doctype html>
<html><body style="margin:0; image-rendering: pixelated;">
  <!-- 任何你喜欢的内容 -->
</body></html>

2. 选择风格

风格 推荐用途 外观与感觉 逻辑网格 轮廓 着色
chunky 图标、按钮、瓦片、方块、简单道具 复古 / 8-bit / NES-SNES 小(16×16, 32×32) 黑色或白色,1px 2–4 阶梯级别,无抗锯齿
maple 角色、NPC、怪物、可爱吉祥物 冒险岛 / 故事书 / 卡通 较大(32×32 ~ 128×128) Selout(填充色的深色版本) 4–6 阶梯级别 + 轮廓上的选择性抗锯齿 + 可选 2×2 抖动

不确定时的默认值

  • 图标 / 按钮 / 瓦片 / 方块 → chunky
  • 角色 / NPC / 怪物 / 吉祥物 / “可爱”请求 / “画一个史莱姆” → maple
  • 用户说“复古”/“8-bit”/“NES”/“极简” → chunky
  • 用户说“冒险岛”/“可爱”/“卡通”/“Q版”/“插画” → maple

每种风格的完整规则:

两种风格共享相同的禁止 API(无曲线 API、无渐变 API、无分数坐标、无 filter: blur/drop-shadow)。它们在调色板丰富度、轮廓颜色、抗锯齿和工作网格上有所不同。


3. 尺寸指南(摘要)

用途 推荐尺寸
图标 / 按钮 48×48 ~ 64×64
角色 / 物品 / NPC / 怪物 96×96 ~ 128×128
瓦片 / 地板 / 方块 64×64 ~ 128×128
背景 / 大型物体 256×256 或更大(仅在明确要求时)

默认值为 128×128。关于风格特定的工作网格表(chunky 使用小逻辑网格如 16×16;maple 使用较大网格如 64×64)和 SD 角色比例,请参见 references/size-guide.md

如果请求的输出低于 64×64maple 风格没有足够的像素来实现 selout + 抗锯齿 + 面部特征——要么将输出尺寸提升到 64+,要么回退到 chunky


4. PNG 渲染 — render.cjs

一次性依赖安装

cd scripts && npm ci

这会从已提交的 package-lock.json 安装 puppeteer(约 200MB,包括无头 Chromium)。它与其他基础技能依赖分开,因此仅在首次使用画家时运行此命令。

🔒 使用 npm ci不要使用 npm installnpm ci 精确安装 package-lock.json 中锁定的版本,如果锁文件与 package.json 不一致则失败——这是 W012 的供应链完整性保证。切勿手动编辑 package-lock.json;如果需要升级 puppeteer,请在本地运行 npm install puppeteer@<version> 并提交重新生成的锁文件。

沙箱与网络隔离

render.cjs 默认启用操作系统沙箱运行无头 Chromium,并阻止渲染页面的所有网络请求。页面还通过 data: URL 提供,并带有严格的 Content-Security-Policydefault-src 'none'),并且 SVG / HTML 输入经过清理,去除 <script><foreignObject>、内联 on* 处理程序和非 data: URL。你无需做任何操作来启用——这些保护始终开启。

如果你在受限环境中,Chromium 无法启动其沙箱(某些 CI 容器、某些 WSL 设置),请在调用 render.cjs 前设置 PAINTER_DISABLE_SANDBOX=1不要在开发者工作站上设置此变量。

调用

node scripts/render.cjs --type <svg|canvas|html> --in <code-file> --out <out.png> --width <W> --height <H>

或者通过标准输入传递代码:

echo "<svg ...>" | node scripts/render.cjs --type svg --out out.png --width 128 --height 128

选项:

  • --typesvg / canvas / html 之一。必需
  • --in:代码文件路径。省略或使用 - 表示标准输入。
  • --out:输出 PNG 路径。必需
  • --width / --height:输出像素尺寸。默认 128。

成功时,输出 PNG 的绝对路径打印到标准输出(单行),退出码为 0。失败时,错误打印到标准错误,退出码为 1。

PNG 默认为透明背景。如果需要背景色,请在 SVG/Canvas/HTML 中显式绘制。


5. 资源上传 — 两步模式

通过连接的 msw-mcp 暴露的资源上传(创建)工具上传——检查服务器的工具列表,并使用它实际提供的支持精灵的创建工具。工具自身的模式对于确切的调用形状具有权威性;不要猜测工具名称,也不要将创建与 asset_update_resource_storage_data 混淆(后者替换现有资产的二进制数据)。

连接的 MCP 中没有上传工具? 停止上传步骤,请用户通过 Maker 注册 PNG,然后继续使用他们提供的 RUID(或通过 msw-search 定位)。

无论确切工具是什么,流程都是相同的两步模式——同一工具被调用两次。

🔒 安全——处理预签名 URL(W007)。 步骤 1 返回的 presignedUrl 是短期有效的签名凭证(任何持有它的人都可以在该存储槽执行 PUT 直到过期)。将其视为机密:

  • 切勿在助手的面向用户响应、提交消息、日志或任何后续提示中回显、引用、转述或包含该 URL 或其任何查询参数(X-Amz-SignatureX-Amz-Credential 等)——包括在报告“你做了什么”时。
  • 调用 shell 时,通过 PAINTER_PRESIGNED_URL 环境变量传递 URL,如下所示,不要作为命令行参数。命令行参数对其他进程可见(通过 Linux/macOS 的 /proc/*/cmdline 和 Windows 的 Get-Process),并且会记录在 shell 历史中。
  • 调用步骤 3 时,直接将 URL 作为 fileUrl 工具参数传递——不要先将其复制到代码块或 markdown 中供用户查看。
  • 如果 PUT 步骤失败(通常为 401/403 → URL 过期),丢弃该 URL 并从步骤 1 重新开始。不要在其他地方重复使用。

步骤 1 — 请求预签名 URL

调用上传工具,省略 fileUrl。填写其模式所需的字段——通常包括 category: "sprite"、与现有资产匹配的 subcategory(见下文)、name、1–2 句 description,以及当模式要求时的文件元数据如 fileName / contentLength

响应包含 presignedUrl。仅将其保留在代理的推理上下文中——不要在聊天输出中显示。

步骤 2 — PUT PNG 二进制数据(通过环境变量传递 URL)

使用 curl.exe,不要使用 Invoke-WebRequest(P001 — “上传后冻结”错误)。 在 Windows PowerShell 5.1 上,除非传递 -UseBasicParsing,否则 Invoke-WebRequest 会通过 Internet Explorer 引擎解析 HTTP 响应。IE 在 Windows 11 上已被移除/禁用,因此调用会在 IE“首次启动配置”上阻塞,并在字节已上传后似乎冻结很长时间(MCP 工具本身在约 45 毫秒内返回——延迟完全在此步骤中)。curl.exe(Windows 10 1803+ 和所有 Windows 11 的 System32 中附带)没有 IE 依赖,在 PowerShell 和 Git Bash 中行为一致,因此在两个 shell 中都优先使用它。

PowerShell(推荐 — curl.exe):

$env:PAINTER_PRESIGNED_URL = "<presignedUrl from step 1>"
try {
  # 通过标准输入配置 (-K -) 将 url/request/upload-file 传递给 curl,
  # 这样 URL 永远不会出现在 argv(通过 Get-Process 可见)或 shell 历史中。
  "url = `"$env:PAINTER_PRESIGNED_URL`"`nrequest = `"PUT`"`nupload-file = `"out.png`"" | curl.exe -K -
} finally {
  Remove-Item Env:\PAINTER_PRESIGNED_URL -ErrorAction SilentlyContinue
}

bash(Git for Windows / WSL — curl):

# 1) 在单独的语句中赋值(export),而不是作为内联前缀。
#    `VAR=… curl … "$VAR"` 不起作用:shell 在赋值生效前在同一命令行上展开 "$VAR",
#    因此 curl 收到空 URL 并失败,提示 "curl: option : blank argument…"。
export PAINTER_PRESIGNED_URL="<presignedUrl from step 1>"
# 2) 通过从标准输入读取的配置文件 (-K -) 将 URL 传递给 curl。
#    将其作为普通参数传递(curl … "$PAINTER_PRESIGNED_URL")会将 URL 直接展开到 argv 中,
#    通过 `ps` / /proc/<pid>/cmdline 可见——-K - 使其完全脱离参数列表。
printf 'url = "%s"\nrequest = "PUT"\nupload-file = "out.png"\n' "$PAINTER_PRESIGNED_URL" | curl -K -
unset PAINTER_PRESIGNED_URL

PUT 本身是纯二进制上传——不需要认证头(签名嵌入在预签名 URL 中)。-K -(标准输入配置)形式在两个 shell 中都将 URL 排除在 ps / Get-Process 参数列表和 shell 历史之外。

仅作为回退 — Invoke-WebRequest 如果 curl.exe 确实不可用,则必须添加 -UseBasicParsing(跳过 IE 引擎 → 无冻结)并静默进度条(PS 5.1 的另一个错误,会使传输速度降低 10–50 倍):

$env:PAINTER_PRESIGNED_URL = "<presignedUrl from step 1>"
$ProgressPreference = 'SilentlyContinue'
try {
  Invoke-WebRequest -Method PUT -InFile out.png -Uri $env:PAINTER_PRESIGNED_URL `
    -ContentType "image/png" -UseBasicParsing
} finally {
  Remove-Item Env:\PAINTER_PRESIGNED_URL -ErrorAction SilentlyContinue
}

步骤 3 — 报告上传完成

使用相同参数再次调用同一工具,添加 fileUrl 设置为步骤 1 中的预签名 URL(直接作为工具参数传递——不要回显到聊天或代码块中)。

响应包含精灵 RUID。这是最终交付物。此调用返回后,将 URL 视为已完全消耗——不要保留。

步骤 4 — 注册精灵属性

创建工具不接受 properties——步骤 3 返回 RUID 后,立即使用资产的 guid 调用 mcp__msw-mcp__asset_update_resource_storage_info。属性条目是小写的 { "key": "...", "value": "..." },值为字符串(资源响应显示 Properties: [{ "Key", "Value" }]——不要在输入中镜像该大小写)。

含义
pivot_x / pivot_y 数字字符串 精灵枢轴
border_left / border_right / border_top / border_bottom 数字字符串 九宫格边框(像素)
filter_mode Point / Bilinear / Trilinear 纹理过滤
wrap_mode Repeat / Clamp / Mirror / MirrorOnce 纹理包裹

画家默认值:filter_mode=Point(Bilinear 会模糊 chunky/maple 像素边缘),wrap_mode=Clamppivot_x=0.5;图标/UI 面板使用 pivot_y=0.5,角色和站立在地面上的道具使用 pivot_y=0.0(仅在视觉验证显示脚部偏移时调整)。仅当精灵是九宫格 UI 框架(按钮/面板/仪表)时设置非零 border_*——.ui 侧还需要 SpriteGUIRendererComponent.Type = Sliced(1)(参见 component-api.md §“SpriteGUIRenderer — ImageType Selection”)。切勿发明超出此表的属性键或枚举值。如果连接的 MCP 的工具列表中没有 asset_update_resource_storage_info,则向用户报告预期的属性值,而不是调用不同的工具。

选择子类别

首先使用 asset_search_resourcesasset_list_account_resources 检查现有精灵的子类别分布并匹配。不确定时,回退到通用值,如 object / etc


6. 报告格式

画家任务完成后,仅向用户提供以下内容:

RUID: <received RUID>
Style: <chunky | maple>
<1–2 句描述:你绘制了什么,尺寸是多少,以及注册为什么精灵>

实体创建/移动/生成、脚本编写和 UI 编辑不在画家范围内。在另一个技能或后续步骤中处理这些。


常见陷阱

  • render.cjs 之前未运行 npm ciCannot find module 'puppeteer'。仅在首次需要。使用 npm ci(不是 npm install)以安装锁文件锁定的 puppeteer 版本。
  • 省略 --width / --height → 回退到 128×128,如果用户想要不同尺寸,则必须重绘。始终指定它们。
  • SVG/Canvas 内容仅绘制在 PNG 左上角 → 绘制代码声明了自己的尺寸(例如 SVG width="128" height="128" 或 Canvas scale = 8),但 render.cjs 以更大的 --width/--height 调用。内容仅填充其声明尺寸,PNG 其余部分保持透明。修复:SVG 使用 width="100%" height="100%";Canvas 从 c.width 推导缩放比例。上面的最小模板已遵循此规则。
  • 始终在上传前读取输出 PNG → 配置错误的 SVG/Canvas 可能静默生成空白或画布外的 PNG。对输出进行一次 Read 可在几秒钟内捕获尺寸不匹配和空白画布错误;先上传意味着重做两步上传。
  • 背景变为黑色 → 你在 SVG/Canvas/HTML 内部绘制了背景。要保持透明,请移除背景形状本身。
  • 曲线看起来平滑 → 如果使用 chunky,这是违反规则;移除 arc()/bezierCurveTo()/渐变并用点重绘。如果使用 maple,平滑应来自轮廓处的选择性抗锯齿像素,而不是渐变/曲线 API——API 禁令仍然适用。
  • Maple 精灵看起来像带有额外颜色的 chunky → 你可能忘记了 selout(每个表面周围 1 像素深色轮廓)和/或轮廓边缘的选择性抗锯齿。重新检查 style-maple-cartoon.md 的 Selout 和选择性抗锯齿部分。
  • Chunky 精灵看起来模糊/朦胧 → 你在边缘添加了中间色像素。Chunky 禁止所有抗锯齿——移除过渡像素并保持边缘锐利。如果需要更柔和的外观,请改用 maple
  • Maple 精灵在小尺寸(32×32 输出)下看起来糟糕 → Maple 风格需要 ≥ 64×64 输出才能容纳 selout + 抗锯齿 + 特征。要么增大尺寸,要么切换到 chunky
  • PUT 步骤失败,返回 401/403 → 预签名 URL 已过期或错误。从步骤 1 重新开始。
  • 在完成调用中更改其他参数 → 传递与步骤 1 完全相同的参数。仅添加 fileUrl