后端与接口
在 MSW 中查找 API 文档/示例或精灵、动画、音效…
当 .d.mlua 缺少详细说明/示例,或需要获取 SpriteRUID、动画、音效、资源包、头像等资源 RUID 时,用 msw-mcp 向量检索和 msw_resource_api.cjs 资源搜索。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
在 MSW 中查找 API 文档/示例或特定
解决思路
- 先区分两类搜索目标:API 文档与实现指南用文档向量搜索;资源(sprite/animationclip/sound/resource pack/avatar)用 REST 资源搜索,资源搜索是获取 RUID 的唯一路径。
- 按路由表选择:实现方法、示例、相关 API、.d.mlua 描述不足、不知道 API 名、实现指南/最佳实践 → 文档搜索;需要 SpriteRUID、怪物/NPC/背景 sprite、动画、音效、资源包、RUID 详情、相似资源、头像物品 → 资源搜索;上传/列出/更新/删除自有资产 → 直接调用 msw-mcp 的 asset_* 工具;设置 sprite pivot、9-slice 边界、UI RUID 切片边界、asset properties → 直接调用 msw-mcp 的 asset_update_resource_storage_info,传 properties: [{ key, value }],字段包括 pivot_x/y、border_left/right/top/bottom、filter_mode、wrap_mode。
- 资源搜索默认先搜 resource_pack:除非用户明确要求单个 sprite/animationclip/sound/avataritem,或直接指定非 pack RUID,否则给 searchResources 传 resourceTypeFilter: ["resource_pack"];找到 pack 后深入 payload.elements,再分配单个 RUID;只有明确意图才切换类型。
- 文档搜索先读 .d.mlua:知道 API 名时始终先读 Environment/NativeScripts/{Component,Service,Event,Enum,Logic,Misc}/Name.d.mlua,用它确认方法签名、属性类型/存在性、事件参数结构、枚举值列表、方法存在性。
- .d.mlua 不足时用向量搜索:需要代码示例用 mlua_api_retriever(如 AIComponent example、BehaviorTree usage);需要参数细节用 mlua_api_retriever(如 BadgeService GetBadgeInfosAndWait parameters);需要相关 API 交叉引用用 mlua_api_retriever(如 AttackComponent related、HitComponent);需要 ScriptOverridable 检查用 mlua_api_retriever(如 AttackComponent CalcCritical override);不知道 API 名时同时用两个 retriever(如 damage calculation、inventory save);需要实现指南用 mlua_document_retriever(如 how to make inventory system);需要模式/最佳实践用 mlua_document_retriever(如 collision detection best practice)。
- 记住 MCP 工具用途:mlua_api_retriever 用于 Service/Component/Misc 等 API 细节(签名、参数、示例),传 API/类/函数/组件名;mlua_document_retriever 用于作者手册、指南、MLua 用法等文档型材料,传自然语言描述要实现什么。
- 处理 msw-mcp 失败:若工具调用报错,向用户暴露失败并回退到 .d.mlua;不要猜测,说明无法验证的内容。
- 文档搜索结果默认请求 3 条,除非明确需要更广探索。
- 把 Maker Editor 语法转换为 .mlua:override → method;{ ... } → ... end;自定义方法执行空间 [server only] → @ExecSpace("ServerOnly");override 的执行空间必须与父类 @ExecSpace 完全一致,父类无 @ExecSpace(引擎默认 ExecSpace=All)时 override 也必须完全省略 @ExecSpace,否则触发 LEA-3014 SignatureMismatch;Property: int32 Score = 0 → @Sync property int32 Score = 0;int → integer;number 保持 number;float 保持 float;始终遵循 .d.mlua 声明。
- 注意 override ExecSpace 具体陷阱:AttackComponent/HitComponent 的 CalcDamage、CalcCritical、GetCriticalDamageRate、GetDisplayHitCount、IsAttackTarget、IsHitTarget、OnAttack 上游都是 ExecSpace=All,添加 @ExecSpace("ServerOnly") 会 SignatureMismatch;先查 .d.mlua 并逐字复制父类注解。
- 转换示例:把 override int CalcDamage(...) { return 50 } 和 override boolean CalcCritical(...) { return _UtilLogic:RandomDouble() < 0.3 } 转成 method integer CalcDamage(...) return 50 end 和 method boolean CalcCritical(...) return _UtilLogic:RandomDouble() < 0.3 end;若父类无 @ExecSpace,不要添加。
- 资源 API 始终通过 scripts/msw_resource_api.cjs 调用,不要手写 curl;wrapper 发送 UTF-8 JSON body,避免非 ASCII 查询出现 {"detail":"There was an error parsing the body"};会 URL 编码含斜杠路径参数(如 npc/1013617.img);零依赖(Node 18+ 内置 fetch/AbortController);使用精确 OpenAPI 字段名 topK、resourceTypeFilter、categoryFilter、count,旧名 limit/types/categories 会被服务器静默忽略。
- Wrapper 已处理传输细节:Base URL https://maplestoryworlds-resourcesearch-new.nexon.com/api;无鉴权(公开);/v3/ 前缀;POST body 为 application/json; charset=utf-8;默认超时 15s(可用 wrapper 的 _request(method, path, { timeout }) 覆盖)。
- 两种 wrapper 用法:CLI 方式 node scripts/msw_resource_api.cjs search "orange mushroom" --resource-type resource_pack --category npc --topK 3,用 node scripts/msw_resource_api.cjs --help 查看子命令;Node require 方式引入 searchResources、searchAvatarItems、findSimilarResources、getResource、getResourcesBatch、getResourceTags、listResources、randomResources、findPacksContaining、listAvatars、getAvatarDefaults,并调用如 await searchResources("orange mushroom", { resourceTypeFilter: ["resource_pack"], categoryFilter: ["npc"], topK: 3 })。
- wrapper 函数 ↔ 端点映射:searchResources/search → POST /v3/search/resources;searchAvatarItems/search-avatar → POST /v3/search/resources(avatar 模式);findSimilarResources/similar → GET /v3/search/resources/similar/{ruid};getResource/get → GET /v3/resources/{ruid};getResourcesBatch/batch → POST /v3/resources/batch;getResourceTags/tags → GET /v3/resources/tags/{ruid};listResources/list → GET /v3/resources;randomResources/random → GET /v3/resources/random;findPacksContaining/packs → GET /v3/resources/packs/{ruid};listAvatars/avatars → GET /v3/avatars;getAvatarDefaults/avatar-defaults → GET /v3/avatars/defaults;没有 /v3/avatars/{ruid},avataritem 详情用 getResource(ruid)。
- 结果数量默认 3:POST /v3/search/resources 和 similar 用 topK;GET /v3/resources 用 limit;GET /v3/resources/random 用 count;GET /v3/resources/packs/{ruid} 用 limit;服务器默认是 20 或 50,所以始终显式传参;精确查找保持 3,需更广探索才增至 10+,头像广浏览用 50–100。
- 处理 offset 分页:POST /v3/search/resources 和 similar 的 nextOffset 是整数 item offset,作为数字 offset 回传;GET /v3/resources 和 GET /v3/resources/packs/{ruid} 的 nextOffset 是不透明字符串 UUID cursor,作为字符串 offset 回传,null 表示结束;不要把 list cursor 传给 search,也不要把 search offset 传给 list;第一页完全省略 offset,list/packs 传整数 0 会被当作 cursor 并返回空结果。
- 若必须绕过 wrapper 发 POST:把 body 序列化为 UTF-8 JSON 字节;设置 Content-Type: application/json; charset=utf-8;用原始字节 POST(如 curl --data-binary "@file" 读取 UTF-8 临时文件)。
- 资源类型含义:sprite 静态图(PNG);animationclip 帧动画;resource_pack 打包 sprites+animations+sounds 的成品资源;bgm 背景音乐;voice 语音(如 NPC 对话);effect 是音效(音频),不是视觉特效,视觉粒子/命中/技能 FX 要搜 sprite 或 animationclip(category 用 skill/mob/etc);avataritem 是头像时装(cap、coat、pants、shoes、weapon 等),用同一 POST /v3/search/resources 且 resourceTypeFilter: ["avataritem"];所有搜索/列表的类型过滤字段名统一为 resourceTypeFilter 数组。
- 赋值 SpriteRUID 时检查类型:SpriteRendererComponent.SpriteRUID 接受 sprite 和 animationclip 但渲染不同;animationclip 播放所有帧层(shadow+body+foreground),sprite 只渲染该单张 Sprite;错误类型可能导致只看到阴影层、body 消失;赋值前检查 payload.type;静态 idle/default 帧用 sprite;StateAnimationComponent.ActionSheet 才用 animationclip。
- 处理 RUID 前缀:skeleton 和 avataritem RUID 若不加 thumbnail:// 前缀直接赋给 SpriteRUID/ImageRUID 会静默失败(无错误、无渲染);反过来 CostumeManagerComponent.Custom*Equip、SkeletonRendererComponent.SkeletonRUID、StateAnimationComponent.ActionSheet 不接受 thumbnail://,传普通 RUID;若搜索目标是 icon/thumbnail 且返回 sprite RUID,该 RUID 已可直接渲染,不必加 thumbnail://;完整规则见 msw-sprite-ruid/SKILL.md。
- 资源分类:通用资源 category 用 mob、npc、item、skill、object、background、foothold、rope、ladder、etc;avataritem category 用 cap/hair/face/faceaccessory/eyeaccessory/earaccessory、coat/longcoat/pants/shoes/glove/cape、weapon/twohandweapon/subweapon/shield;map、effect、ui 不是有效 category,会返回 0 结果;地图/背景用 background 或 object;视觉特效搜 sprite/animationclip + skill/mob/etc;没有 ui 资源族,UI sprite 通常是 sprite + etc。
- RUID 是 32 字符十六进制字符串,唯一标识每个资源,例如 "0017da7385e04bc4b2ddbe5949b4b462";搜索结果 id 字段就是 RUID;assetGuid 是另一个 Unity asset GUID(用于 spawn_preset);绝不猜测或伪造 RUID,始终从 API 响应获取。
- 检查常见响应字段:id、type、category、names.ko/en、assetGuid、payload(width、height、thumbnail、pivot、frames、elements);用这些字段确认资源类型和内容。
- 按资源路由选择:默认无类型指定 → searchResources 搜 resource_pack;明确要单个 sprite → 搜 sprite;明确要 animationclip → 搜 animationclip;视觉特效/粒子/命中 FX → 搜 animationclip+sprite + category skill/mob/etc;音频 sound/BGM/voice/effect → 搜 bgm/voice/effect;背景/地图瓦片/景物 → 搜 sprite+animationclip + category background/object;服装/帽子/鞋/武器 → searchAvatarItems;找相似怪物 → findSimilarResources(ruid);RUID 详情 → getResource(ruid);列出怪物 sprites → listResources;哪些 resource packs 包含此 RUID → findPacksContaining(ruid);浏览所有 avatar items → listAvatars。
- 执行典型 pack-first 工作流:1) searchResources(query, { resourceTypeFilter: ["resource_pack"], topK: 3 }) 获取 resource_pack RUID(或 pack id 如 npc/9072309.img);2) getResource(id),resource_pack 的 payload.elements 预填充元素 payload(sprite/animationclip/sound RUID),avataritem 的 payload 有 color_hex/group meta;3) 从 payload.elements 选元素 RUID 赋给 SpriteRendererComponent.SpriteRUID 或 StateAnimationComponent.ActionSheet,avataritem RUID 按 msw-avatar 的槽位映射赋值。
- 不要用 findPacksContaining(packId) 打开 pack:该端点接收 32 位 hex RUID,返回包含该 RUID 的 packs,不是 pack 内容;打开 pack 内容用 getResource(packId)。
- Sprite 朝向规则:多数 MSW sprite/animationclip/resource_pack,尤其 mob、npc、玩家角色,默认朝左,新生成 SpriteRendererComponent 默认向左渲染;要朝右设 FlipX = true(默认 false = 左)。
- 按场景处理朝向:自定义侧视 AI/追踪用 MovementComponent:MoveToDirection 时方向变化更新 FlipX:sprite.FlipX = velocity.x > 0(向右则翻转);怪物模型/碰撞体对齐用反转 TransformComponent.Scale.x 而非 FlipX,见 msw-general/references/monster.md;原生 AIChaseComponent/AIWanderComponent 引擎自动翻转,什么都不做;俯视 RectTile 移动按轴决定,通常 dx > 0 时翻转,有上下帧的 sprite 用 StateAnimationComponent action set;_EffectService:PlayEffect 要朝右在 options 传 FlipX = true;玩家附着效果跟随朝向用 SyncFlip = true,或读 PlayerControllerComponent.LookDirectionX;资源本身朝右(少见)检查 payload.thumbnail 并反转规则。
- 朝向代码示例:local sprite = self.Entity.SpriteRendererComponent; local selfX = self.Entity.TransformComponent.WorldPosition.x; local dx = targetPos.x - selfX; if dx ~= 0 then sprite.FlipX = dx > 0 end。
- 朝向 sanity check:左朝向约定不是契约,打开 GET /v3/resources/{ruid} 的 payload.thumbnail 确认;不要用 TransformComponent.Scale.x 作为通用 renderer flip,玩家/效果/非怪物 renderer 用 SpriteRendererComponent.FlipX,怪物例外反转 TransformComponent.Scale.x 以保持 sprite 和 collider 对齐。
- 共享技巧:关键词优先用已知精确名,自然语言韩文/英文也可;按端点调整 page-size 参数名 topK/limit/count,本技能默认 3;文档搜索失败直接读 .d.mlua;资源搜索失败用同义词或不同 category 重试,或用 listResources 按 type/category 浏览;POST 返回 {"detail":"There was an error parsing the body"} 说明绕过 wrapper 用内联 curl -d,改用 msw_resource_api.cjs 或复刻 UTF-8 raw-body POST;允许组合查询如 docs 的 AttackComponent CalcCritical、resources 的 red slime jump;不猜 API 名、RUID、枚举值,始终通过搜索或 references 确认。
适用边界 · 注意事项
- 非 MSW/MapleStory Worlds 环境,或没有 msw-mcp MCP server 和 scripts/msw_resource_api.cjs 时,不能按本技能执行。
- 上传/列出/更新/删除自有资产、设置 pivot/9-slice/asset properties 时,应直接调用 msw-mcp 的 asset_* / asset_update_resource_storage_info,不走本技能的搜索流程。
- 只需要确认 API 签名/类型/枚举且 .d.mlua 已足够时,不必调用向量搜索或资源搜索。