msw-search
msw-git/msw-ai-coding-plugins-official
MSW 검색 통합 — (1) msw-mcp MCP 서버를 통한 API 문서 및 구현 가이드에 대한 벡터 검색 (mlua_api_retriever / mlua_document_retriever), (2) 리소스(스프라이트 / 애니메이션 / 사운드 / 리소스 팩 / 아바타)에 대한 REST API 검색. “ .d.mlua 파일에 없는 세부 정보, 예제 또는 관련 API 찾기”, “SpriteRUID 필요”, “몬스터 스프라이트”, '배경 이미지', '사운드 찾기', '아바타 아이템 조회' 등에 사용합니다. 키워드: 문서 검색, API 세부 정보, 예제, 가이드, 검색기, 리소스, 스프라이트,
...모든 것을 확장하십시오소개 msw-search
Routes는 MSW 개발 관련 쿼리를 두 개의 별도 시스템에 따라 적절한 검색 대상으로 라우팅합니다. 하나는 msw-mcp MCP 서버를 통한 API 문서 및 구현 가이드에 대한 벡터 검색이고, 다른 하나는 스프라이트, 애니메이션, 사운드, 리소스 팩, 아바타와 같은 게임 리소스를 위한 REST API입니다. 라우팅 테이블은 요청이 어떤 경로를 따를지 결정하며, ‘예제를 보여주세요’ 또는 ‘관련된 API가 무엇이 있나요?’(문서 검색)와 같은 문의와 SpriteRUID나 몬스터 스프라이트(리소스 검색)에 대한 요청을 구분합니다. RUID를 얻는 유일한 방법은 리소스 검색뿐입니다.
문서화의 경우, 이 스킬은 특정 조사 순서를 따릅니다. API 이름이 알려진 경우, 시그니처, 타입, 속성, 이벤트 매개변수 및 열거형 값을 확인하기 위해 항상 로컬 .d.mlua 타입 스텁을 먼저 참조합니다. 이러한 스텁에는 시그니처만 포함되어 있고 설명이나 예제가 없기 때문에, 벡터 검색이 이를 보완합니다: mlua_api_retriever는 지정된 API나 컴포넌트에 대한 코드 예제, 매개변수 세부 정보, 관련 API, ScriptOverridable 플래그를 반환하는 반면, mlua_document_retriever는 구현해야 할 내용에 대한 자연어 설명을 바탕으로 저작 매뉴얼과 구현 가이드를 반환합니다. 기본 요청 결과 수는 3개이며, MCP 오류가 발생하면 스킬은 오류를 표시하고 추측 대신 .d.mlua로 대체합니다.
리소스의 경우, resource_pack 유형을 먼저 검색하는 것이 강력히 권장됩니다. 팩(pack)은 하나의 에셋에 대한 모든 스프라이트, 애니메이션, 사운드를 묶어두기 때문이며, payload.elements를 자세히 살펴보면 개별 RUID를 얻을 수 있습니다. 먼저 임의의 스프라이트나 애니메이션 클립을 선택하면 프레임이 하나뿐이거나, 애니메이션이 설정되지 않았거나, 잘못된 애셋 패밀리를 가진 엔티티가 남는 경향이 있으므로, 스킬은 BGM 파일, 개별 스프라이트, 아바타 아이템과 같은 명시적인 의도만 있을 때 리소스 유형을 전환합니다. 비교 표는 .d.mlua가 제공하는 내용과 전체 검색 결과를 대조하며, 변환 표는 예제에서 사용된 Maker Editor 구문을 .mlua 파일 구문으로 변환합니다. 여기서 오버라이드는 메서드로, 중괄호를 끝으로, 에디터의 exec-space 토글을 @ExecSpace 어노테이션으로 매핑합니다. 단, 오버라이드의 @ExecSpace는 상위 선언과 바이트 단위로 일치해야 하며, 그렇지 않으면 LEA-3014 SignatureMismatch 오류가 발생한다는 점에 유의하십시오.
자주 묻는 질문
이 스킬로 검색할 수 있는 두 가지 항목은 무엇입니까?
msw-mcp 서버에서 벡터 검색을 통해 API 문서와 구현 가이드를 검색하고, REST API를 통해 게임 리소스(스프라이트, 애니메이션, 사운드, 리소스 팩, 아바타)를 검색합니다. RUID를 얻으려면 리소스 검색을 통해서만 가능합니다.
API를 찾을 때 .d.mlua를 먼저 확인해야 할까요, 아니면 벡터 검색을 먼저 해야 할까요?
API 이름을 알고 있다면 항상 .d.mlua를 먼저 읽으십시오. .d.mlua는 시그니처, 유형, 속성, 이벤트 매개변수 및 열거형 값을 정확하게 제공하기 때문입니다. 코드 예제나 매개변수별 세부 정보가 필요한 경우 등, .d.mlua의 시그니처만으로는 부족한 경우에만 벡터 검색을 사용하십시오.
이 스킬이 리소스 검색을 resource_pack부터 시작할 것을 권장하는 이유는 무엇인가요?
리소스 팩은 하나의 에셋에 포함된 모든 스프라이트, 애니메이션, 사운드를 묶어두기 때문에, 팩을 검색한 후 payload.elements로 세부 정보를 파고들면 일관된 RUID를 얻을 수 있습니다. 단독 스프라이트나 애니메이션 클립을 먼저 선택하면 대개 엔티티에 프레임이 하나만 남아 있거나, 애니메이션 세트가 없거나, 잘못된 에셋 패밀리가 지정되는 경우가 많습니다.
mlua_api_retriever와 mlua_document_retriever의 차이점은 무엇인가요?
mlua_api_retriever는 지정된 API, 클래스, 함수 또는 컴포넌트에 대한 시그니처, 매개변수, 예제 및 관련 API와 같은 API 수준의 세부 정보를 반환합니다. mlua_document_retriever는 작성 매뉴얼 및 지침과 같은 문서 형식의 자료를 반환하며, 구현하고자 하는 내용을 설명하는 자연어 문장을 입력으로 받습니다.
오버라이드가 LEA-3014 SignatureMismatch 오류로 실패하는 이유는 무엇일까요?
검색 결과 예제는 Maker Editor 구문을 사용하며, 이 구문에서는 부모의 exec 공간이 종종 숨겨져 있고 토글이 가능합니다. .mlua 파일에서 오버라이드의 @ExecSpace는 .d.mlua 파일 내 부모의 @ExecSpace와 바이트 단위로 동일해야 하며, 부모에 @ExecSpace가 없는 경우 오버라이드에서도 이를 완전히 생략해야 합니다.
모든 파일
6개파일references/resource/detail.md 3.8KB보기SKILL.md 28.2KB보기references/resource/browse.md 6.8KB보기scripts/msw_resource_api.cjs 23.6KB 보기 references/resource/avatar.md 4.5KB 보기 references/resource/search.md 11.2 KB 보기MSW has two distinct search targets:
- API docs & implementation guides — Vector search for descriptions, code examples, and related APIs missing from
.d.mlua. - Resources — REST API for sprites, animations, sounds, resource packs, and avatars. The only path for obtaining RUIDs.
Routing Table
| Request type | Go to section |
|---|---|
| "How do I implement this?", "Show me an example", "What related APIs exist?" | Document search |
| ".d.mlua only has the signature; the description is insufficient" | Document search |
| "I don't know the API name (semantic search)" | Document search |
| "Implementation guide / best practice / pattern" | Document search |
| "I need a SpriteRUID", "Find a sprite for monster / NPC / background" | Resource search → start with resource_pack |
| "Find an animation / sound / resource pack" | Resource search → start with resource_pack |
| "Details for this RUID", "Similar resources" | Resource search |
| "Avatar item / default avatar lookup" | Resource search |
| "Upload / list / update / delete my own assets" | Call msw-mcp asset_* tools directly |
| "Set sprite pivot", "set 9-slice border", "slice boundary for UI RUID", "asset properties" | Call msw-mcp asset_update_resource_storage_info directly (properties: [{ key, value }] — pivot_x/y, border_left/right/top/bottom, filter_mode, wrap_mode) |
★ Resource search default — always
resource_packfirstUnless the user explicitly asks for an individual sprite / animationclip / sound / avatar item (or names a non-pack RUID directly), pass
resourceTypeFilter: ["resource_pack"]tosearchResources. A pack bundles every sprite + animation + sound for one asset, so picking a strayspriteoranimationclipfirst usually leaves the entity with a single frame, no animation set, or the wrong asset family.Search the pack → drill into
payload.elements→ assign individual RUIDs.Switch types only on explicit intent: "BGM file", "individual sprite only", "avatar item", "animationclip similar to this RUID", etc.
Section 1 — Document Search (APIs & Guides)
Vector search via the msw-mcp MCP server. Supplies the detailed descriptions, code examples, related APIs, and implementation guides missing from .d.mlua.
Decision Flow
Need API-related information│├─ Checking signature / type / property / enum│ → Read .d.mlua first (highest priority)│ → If .d.mlua is insufficient, call msw-mcp│ (code examples, parameter details, related APIs, etc.)│├─ Implementation guide / pattern / best practice│ → mlua_document_retriever│└─ Don't know the API name (semantic search) → mlua_api_retriever (and/or mlua_document_retriever for broader scope)API Research Order
Priority 1 — .d.mlua (always first)
If you know the API name, always read .d.mlua first. Signatures, types, properties, event parameters, and enum values can be confirmed here accurately.
Path: Environment/NativeScripts/{Component,Service,Event,Enum,Logic,Misc}/Name.d.mlua
| Situation | Example |
|---|---|
| Confirm method signature | "Does TransformComponent have SetPosition?" |
| Property type / existence | "What is the type of SpriteRendererComponent.RUID?" |
| Event parameter structure | "What are the AttackEvent constructor parameters?" |
| List of enum values | "What are the BodyMoveType values?" |
| Method existence | "What methods does SpawnService have?" |
Priority 2 — Vector search (when .d.mlua is not enough)
.d.mlua contains only signatures and lacks detailed descriptions and examples. Use vector search when you need any of the following.
| Situation | MCP tool | Example query |
|---|---|---|
| Need a code example | mlua_api_retriever | AIComponent example, BehaviorTree usage |
| Parameter details | mlua_api_retriever | BadgeService GetBadgeInfosAndWait parameters |
| Related API cross-references | mlua_api_retriever | AttackComponent related, HitComponent |
| ScriptOverridable check | mlua_api_retriever | AttackComponent CalcCritical override |
| Don't know the API name | both retrievers | damage calculation, inventory save |
| "How do I …?" implementation guide | mlua_document_retriever | how to make inventory system |
| Pattern / best practice | mlua_document_retriever | collision detection best practice |
MCP Tools (msw-mcp)
| Tool | Description |
|---|---|
mlua_api_retriever | API details for Service / Component / Misc etc. (signatures, parameters, examples). Pass an API/class/function/component name. |
mlua_document_retriever | Authoring manuals, guidelines, MLua usage, and other document-style material. Pass a natural-language sentence describing what to implement. |
On failure: If a msw-mcp tool call errors out, surface the failure to the user and fall back to .d.mlua. Do not guess — state what you couldn't verify.
Default result count: request 3 results unless wider exploration is explicitly required.
.d.mlua vs Search — Information Comparison
.d.mlua is a type stub (~29 lines); Search returns the full document (254+ lines).
| Information | .d.mlua | Search |
|---|---|---|
| Method signature / types | O | O |
| Property declarations | O | O |
| Detailed method description (DetailDesc) | X | O |
| Code examples (AdditionalPageContent) | X | O |
| Per-parameter descriptions | X | O |
| Related APIs (SeeAlsoAPIs) | X | O |
| Related guides (SeeAlsoGuides) | X | O |
| ScriptOverridable flag | X | O |
| SyncDirection | Partial | O |
| Localized descriptions (Ko/Ja/Es/Zh) | X | O |
Maker Editor Syntax → .mlua Conversion Rules
Code examples in search results use Maker Editor syntax. They must be converted before being used in a local .mlua file.
| Item | Maker Editor | .mlua file | Note |
|---|---|---|---|
| Override declaration | override integer CalcDamage(...) | method integer CalcDamage(...) | override → method |
| Block | { ... } | ... end | Braces → end |
| Exec space (own method) | [server only] | @ExecSpace("ServerOnly") | Self-defined methods: annotate explicitly |
| Exec space (override) | [server only] shown / omitted in editor | Match the parent's @ExecSpace exactly — see warning below | LEA-3014 if mismatched |
| Property | Property: int32 Score = 0 | @Sync property int32 Score = 0 | Add @Sync if synced |
Type int | int | integer | C# int → mlua integer |
Type number | number | number | Same (double) |
Type float | float | float | Same (single) |
number(64-bit double) andfloat(32-bit single) are assignable to each other but remain distinct types. Follow the.d.mluadeclaration.
⚠ Override ExecSpace caveat — LEA-3014
SignatureMismatchThe Maker Editor often hides the parent's exec space and lets you toggle
[server only]freely on anoverrideblock. In.mlua, however, the override's@ExecSpacemust be byte-identical to the parent declared in.d.mlua. If the parent has no@ExecSpace(engine default =ExecSpace=All), the override must also omit@ExecSpaceentirely.Concretely, the AttackComponent / HitComponent damage hooks (
CalcDamage,CalcCritical,GetCriticalDamageRate,GetDisplayHitCount,IsAttackTarget,IsHitTarget,OnAttack) are allExecSpace=Allupstream. Adding@ExecSpace("ServerOnly")produces:[LEA-3014] SignatureMismatch : The signature of <Child>.CalcDamage[... (ExecSpace=ServerOnly)] must match the overridden <Parent>.CalcDamage.[... (ExecSpace=All)].Always look up the parent in
.d.mluafirst and copy its annotation block verbatim. Detail:msw-scripting/SKILL.md§9 "Method override → LEA-3014".
Conversion example — AttackComponent from search results:
-- Maker Editor syntax (search result)override int CalcDamage(Entity attacker, Entity defender, string attackInfo) { return 50}override boolean CalcCritical(Entity attacker, Entity defender, string attackInfo) { return _UtilLogic:RandomDouble() < 0.3}-- Converted to .mlua-- ⚠ Parent AttackComponent.CalcDamage / CalcCritical declare no @ExecSpace-- (ExecSpace=All). Adding @ExecSpace here triggers LEA-3014 SignatureMismatch.method integer CalcDamage(Entity attacker, Entity defender, string attackInfo) return 50endmethod boolean CalcCritical(Entity attacker, Entity defender, string attackInfo) return _UtilLogic:RandomDouble() < 0.3end
Section 2 — Resource Search (Sprite / Animation / Sound / Resource Pack / Avatar)
REST API for searching and browsing MSW resources.Never guess or fabricate a RUID — always obtain one through this API.
Default search type =
resource_pack— see the pack-first rule under the Routing Table above.
Access — always go through msw_resource_api.cjs
All resource-API calls in this skill are made through the Node.js wrapper
scripts/msw_resource_api.cjsDo not assemble curl commands by hand. The wrapper:
- Sends UTF-8 JSON bodies directly, so non-ASCII queries (Korean / Japanese / Chinese / emoji) avoid the
{"detail":"There was an error parsing the body"}failure mode that hits inlinecurl -d '...'. - URL-encodes slash-containing path parameters (e.g. pack IDs like
npc/1013617.img). - Zero dependencies (Node 18+ built-in
fetch/AbortController). - Uses the exact OpenAPI field names (
topK,resourceTypeFilter,categoryFilter,count, …). Legacy names likelimit/types/categoriesare silently ignored by the server.
Two ways to use it:
# 1) CLI — fire one call from a shell. Output is pretty-printed JSON.node scripts/msw_resource_api.cjs \ search "orange mushroom" --resource-type resource_pack --category npc --topK 3# Discover available subcommands:node scripts/msw_resource_api.cjs --help
// 2) require — preferred when already in a Node.js context.const { searchResources, searchAvatarItems, findSimilarResources, getResource, getResourcesBatch, getResourceTags, listResources, randomResources, findPacksContaining, listAvatars, getAvatarDefaults,} = require('./scripts/msw_resource_api.cjs');const result = await searchResources("orange mushroom", { resourceTypeFilter: ["resource_pack"], categoryFilter: ["npc"], topK: 3,});
Wrapper function ↔ endpoint map
| Wrapper function | CLI subcommand | Endpoint |
|---|---|---|
searchResources | search | POST /v3/search/resources |
searchAvatarItems | search-avatar | POST /v3/search/resources (avatar mode) |
findSimilarResources | similar | GET /v3/search/resources/similar/{ruid} |
getResource | get | GET /v3/resources/{ruid} (works for sprite / animationclip / resource_pack / avataritem) |
getResourcesBatch | batch | POST /v3/resources/batch |
getResourceTags | tags | GET /v3/resources/tags/{ruid} |
listResources | list | GET /v3/resources (Qdrant Scroll, opaque-string offset cursor) |
randomResources | random | GET /v3/resources/random |
findPacksContaining | packs | GET /v3/resources/packs/{ruid} (lists packs containing a RUID — pack id is NOT accepted here) |
listAvatars | avatars | GET /v3/avatars |
getAvatarDefaults | avatar-defaults | GET /v3/avatars/defaults |
No
/v3/avatars/{ruid}endpoint exists. To inspect an avataritem(color_hex, group members, …), callgetResource(ruid)— the/v3/resources/{ruid}endpoint returns avataritem detail just likeany other resource.
Base URL & transport (informational)
The wrapper handles all of this — you do not need to set it manually.
- Base URL:
https://maplestoryworlds-resourcesearch-new.nexon.com/api - No auth (public),
/v3/prefix, POST bodies areapplication/json; charset=utf-8 - Default timeout: 15s (override via the wrapper's
_request(method, path, { timeout }))
Result count — this skill's default is 3
Unless explicitly told otherwise, always send 3 for the result-count parameteron every search call. The wrapper defaults to 3 as well, and parameter names followthe OpenAPI spec exactly — note that limit / count / topK differ per endpoint.
| Endpoint | Server parameter | Wrapper default |
|---|---|---|
POST /v3/search/resources (resources + avatar) | topK | 3 |
GET /v3/search/resources/similar/{ruid} | topK | 3 |
GET /v3/resources (browsing) | limit | 3 |
GET /v3/resources/random | count | 3 |
GET /v3/resources/packs/{ruid} (packs containing a RUID) | limit | 3 |
The server-side default is 20 or 50, so always pass these parameters explicitly.Increase to 10+ (or 50–100 for avatar broad-browse) only when wider exploration is explicitly required.
offsetparameter caveat — forGET /v3/resourcesandGET /v3/resources/packs/{ruid},offsetis not an integer but the opaque string cursornextOffsetreturned by the previous response.Do not send it on the first page (sending integer0is interpreted as a cursor and returns empty results).
POST body rule — let msw_resource_api.cjs handle it
If you must POST without the wrapper (no HTTP client in your language), reproduce its behaviour:
- Serialize the body as UTF-8 JSON bytes (not a re-encoded shell string).
- Send
Content-Type: application/json; charset=utf-8. - POST raw bytes (e.g. curl's
--data-binary "@file"reading a UTF-8 temp file).
Otherwise, just call the wrapper.
Resource Types
type values (the type field on server responses, and the values you putinto the resourceTypeFilter array when searching):
| type | Description |
|---|---|
sprite | Static image (PNG) |
animationclip | Frame-based animation |
resource_pack | Finished asset bundling sprites + animations + sounds |
bgm | Background music (audio) |
voice | Voice clip — NPC dialogue, etc. (audio) |
effect | Sound effect (audio). Not a visual effect. For visual particles / hit / skill FX, search sprite or animationclip (categories skill / mob / etc). |
avataritem | Avatar costume item (cap, coat, pants, shoes, weapon, …) — same POST /v3/search/resources endpoint with resourceTypeFilter: ["avataritem"]. See references/resource/search.md ("Avatar Item Search") and references/resource/avatar.md. |
All search and listing endpoints use the same type-filter field name:
resourceTypeFilter(an array). Other names liketypesare silently ignored by the server.The wrapper'sresource_type_filterargument (or CLI--resource-type) maps to this field.
⚠
SpriteRendererComponent.SpriteRUIDaccepts bothspriteandanimationclip, but renders them differently:
animationclip→ all frame layers play (shadow + body + foreground)sprite→ that single Sprite renders onlySymptom of mistake: feeding an
animationclipRUID where you intended asprite(or vice-versa) leaves only the shadow layer visible — the body silently vanishes. Always checkpayload.typeof the response before assigning toSpriteRUID. Usespritefor the static idle/default frame; useanimationcliponly for fields likeStateAnimationComponent.ActionSheetvalues.
skeletonandavataritemRUIDs fail silently (no error, nothing renders) when assigned toSpriteRUID/ImageRUIDwithout thethumbnail://prefix. Conversely,CostumeManagerComponent.Custom*Equip/SkeletonRendererComponent.SkeletonRUID/StateAnimationComponent.ActionSheetdo not accept thethumbnail://prefix — pass a plain RUID there. If the search query targeted an icon / thumbnail image and returned aspriteRUID, that RUID is already renderable directly — addingthumbnail://is redundant. Full assignment rules — accepted types, slot-by-slot prefix matrix, RUID-vs-prefix usage — live inmsw-sprite-ruid/SKILL.md.
Categories
category values that actually appear on responses. Use these with categoryFilter.
General resources (sprite / animationclip / resource_pack / bgm / voice / effect)
| category | Description |
|---|---|
mob | Monster |
npc | NPC |
item | Item |
skill | Skill effect / skill resources |
object | Map object (tree, rock, decoration) |
background | Background / map tile / BGM |
foothold | Walkable platform |
rope | Rope |
ladder | Ladder |
etc | Uncategorized |
Avatar (avataritem only)
| category | Slot |
|---|---|
cap, hair, face, faceaccessory, eyeaccessory, earaccessory | Head / face |
coat, longcoat, pants, shoes, glove, cape | Body |
weapon, twohandweapon, subweapon, shield | Weapon |
map,effect,uiare not valid category values — they return zero results.
- Looking for maps / backgrounds →
category: "background"or"object".- Looking for visual effects → search
sprite/animationclipwithcategory: "skill"(ormob/etc);effectis the audio resource_type, not a category.- There is no
uiresource family in this index — UI sprites usually live assprite+category: "etc".
RUID
A 32-character hex string that uniquely identifies every resource. Example: "0017da7385e04bc4b2ddbe5949b4b462"
- The
idfield in search results is the RUID assetGuidis a separate Unity asset GUID (used inspawn_preset)- Never guess or fabricate a RUID — always obtain it from an API response
Common Response Fields
{ "id": "32-char hex RUID", "type": "sprite|animationclip|resource_pack|bgm|voice|effect|avataritem", "category": "mob|npc|item|skill|object|background|foothold|rope|ladder|etc | <avatar slot>", "names": { "ko": ["Korean name"], "en": ["English name"] }, "assetGuid": "Unity asset GUID (may or may not exist)", "payload": { "width": 64, "height": 64, "thumbnail": "https://...", "pivot": {"x": 32, "y": 32}, "frames": [], "elements": [] }}Pagination — same name, two flavors
nextOffset appears in every list-style response but means different things depending on the endpoint. Round-tripping a value into the wrong endpoint silently misbehaves.
| Endpoint | nextOffset type | Meaning | How to paginate |
|---|---|---|---|
POST /v3/search/resources (search) | integer | Item offset (0-based) | Pass it back as offset (number) |
GET /v3/search/resources/similar/{id} (similar) | integer | Item offset | Same |
GET /v3/resources (list) | opaque UUID string | Qdrant Scroll cursor | Pass the string back as offset. End-of-stream = null |
GET /v3/resources/packs/{ruid} (packs) | opaque UUID string | Same cursor | Same |
GET /v3/resources/random | n/a | No pagination | — |
Rules:
- Never feed a
listcursor into asearchcall (or vice versa) — the server ignores the wrong-shape value and returns the first page. - On the first page, omit
offsetentirely. Sending integer0tolist/packsis interpreted as a cursor and yields zero items (silent failure). - Stop paginating when the response returns
nextOffset: null(list / packs) or returns fewer items thantopK(search / similar).
Endpoint Summary
| Method | Endpoint | Purpose |
|---|---|---|
| POST | /v3/search/resources | Natural-language semantic search (incl. avatar items via resourceTypeFilter: ["avataritem"]) |
| GET | /v3/search/resources/similar/{ruid} | Find similar resources |
| GET | /v3/resources/{ruid} | Single resource details (sprite / animationclip / resource_pack with populated elements / avataritem) |
| POST | /v3/resources/batch | Batch fetch multiple resources |
| GET | /v3/resources/tags/{ruid} | AI-generated multilingual tags |
| GET | /v3/resources | List resources (Qdrant Scroll, opaque-string offset cursor) |
| GET | /v3/resources/random | Random resource recommendation |
| GET | /v3/resources/packs/{ruid} | List resource packs containing the given RUID — the path parameter is a 32-char-hex RUID, not a pack id |
| GET | /v3/avatars | List all avatar items (cached) |
| GET | /v3/avatars/defaults | Default avatar body / head RUIDs |
Single avataritem detail uses
/v3/resources/{ruid}(no/v3/avatars/{ruid}endpoint exists).
Resource Routing Guide
★ When in doubt, search
resource_packfirst. Only the rows marked with anexplicit non-pack intent below should bypass the pack-first default.
| Situation | Wrapper call (CLI subcommand) | Reference file |
|---|---|---|
| "Find a slime / orange mushroom / monster / NPC / item / background / map asset" (default — no type specified) | searchResources(query, { resourceTypeFilter: ["resource_pack"], ... }) (search ... --resource-type resource_pack) | references/resource/search.md |
| "Find an individual sprite / single image" (user explicitly asked for a sprite) | searchResources(query, { resourceTypeFilter: ["sprite"], ... }) | references/resource/search.md |
| "Find an individual animationclip" (user explicitly asked for an animation) | searchResources(query, { resourceTypeFilter: ["animationclip"], ... }) | references/resource/search.md |
| "Find a visual effect / particle / hit FX" | searchResources(query, { resourceTypeFilter: ["animationclip","sprite"], categoryFilter: ["skill","mob","etc"] }) — note: effect here would mean audio, not visual | references/resource/search.md |
| "Find a sound / BGM / voice / sound-effect" (audio) | searchResources(query, { resourceTypeFilter: ["bgm"|"voice"|"effect"], ... }) — effect resource_type = sound-effect (audio) | references/resource/search.md |
| "Find a background / map tile / scenery" | searchResources(query, { resourceTypeFilter: ["sprite","animationclip"], categoryFilter: ["background","object"] }) — there is no map category in the index | references/resource/search.md |
| "Find a costume / hat / shoes / weapon (avatar item)" | searchAvatarItems(...) (search-avatar) | references/resource/search.md (Avatar Item Search section) + references/resource/avatar.md |
| "Any more monsters like this one?" | findSimilarResources(ruid, ...) (similar) | references/resource/search.md |
| "Details for RUID abc123" (any type incl. avataritem and resource_pack) | getResource(ruid) (get) | references/resource/detail.md |
| "Show me a list of monster sprites" | listResources(...) (list) | references/resource/browse.md |
| "Which resource packs include this RUID?" | findPacksContaining(ruid, ...) (packs) | references/resource/browse.md |
| "Browse all avatar items" | listAvatars(...) (avatars) | references/resource/avatar.md |
Typical Workflow (pack-first)
1. searchResources(query, { resourceTypeFilter: ["resource_pack"], topK: 3 }) → obtain a resource_pack RUID (or pack id like "npc/9072309.img") → switch types only on explicit user intent, or fall back when 0 packs match2. getResource(id) → resource_pack: payload.elements is pre-populated with element payloads (sprite / animationclip / sound RUIDs live here) → avataritem: payload has color_hex / group meta3. Pick the element from payload.elements and assign its RUID to SpriteRendererComponent.SpriteRUID / StateAnimationComponent.ActionSheet (or assign avataritem RUIDs through the slot mapping in `msw-avatar`)Don't call
findPacksContaining(packId)to "open" a pack — that endpoint takes a 32-hex RUID and returns the packs that include that RUID, not the contents of a pack. UsegetResource(packId)for pack contents.
For detailed Request/Response of each endpoint, refer to the files under
references/resource/.
Sprite Orientation — Most Resources Face Left
Most MSW sprite / animationclip / resource_pack assets — especially mob, npc, and player-character — are authored facing left, so a freshly spawned SpriteRendererComponent renders left unless you flip it.
| Situation | What to do |
|---|---|
| Spawn an entity that should face right | Set FlipX = true on SpriteRendererComponent (default is false = left-facing as authored) |
Custom AI / chase using MovementComponent:MoveToDirection | Update FlipX on direction change: sprite.FlipX = velocity.x > 0 (right ⇒ flip) |
| Monster model / monster collider alignment | Invert TransformComponent.Scale.x instead of FlipX so the sprite and collider stay aligned; see msw-general/references/monster.md |
Native AIChaseComponent / AIWanderComponent | Engine flips automatically based on movement — do nothing |
Top-down (RectTile) movement | Decide per-axis: usually flip when dx > 0; sprites with up/down frames need the StateAnimationComponent action set instead |
_EffectService:PlayEffect(...) should face right | Pass FlipX = true in the options table |
| Player-attached effect must follow the player's facing | Use SyncFlip = true in PlayEffect options, or read PlayerControllerComponent.LookDirectionX |
| Resource is authored facing right (rare) | Inspect payload.thumbnail via GET /v3/resources/{ruid} and invert the rule for that asset |
-- Custom side-view chase: flip sprite to match movement directionlocal sprite = self.Entity.SpriteRendererComponentlocal selfX = self.Entity.TransformComponent.WorldPosition.xlocal dx = targetPos.x - selfXif dx ~= 0 then sprite.FlipX = dx > 0 -- target on the right → flipend
Sanity check — the left-facing convention is not contractual. Open
payload.thumbnailfromGET /v3/resources/{ruid}to confirm.Do not use
TransformComponent.Scale.xas a general renderer flip — for players / effects / non-monster renderers, useSpriteRendererComponent.FlipX. Monster exception: monster models should invertTransformComponent.Scale.xso the sprite and collider stay aligned. Related:msw-combat-system/SKILL.md"Direction check ★",msw-general/references/monster.md.
Shared Tips
- Keyword choice — Use the exact name if you know it; natural-language Korean/English also works.
- Adjust the page-size parameter — the name differs per endpoint (
topKfor search/similar,limitfor list/packs,countfor random). This skill's default is 3 (see the "Result count" table above). Keep it at 3 for precise lookups; increase to 10+ (or 50–100 for avatar broad-browse) only when wider exploration is required. - When search fails:
- Document search fails → read
.d.mluadirectly. - Resource search fails → retry with synonyms or a different category; browse with
listResources(...)(CLI:list) by type/category. POSTreturns{"detail":"There was an error parsing the body"}→ you bypassedthe wrapper and sent JSON inline viacurl -d '{...}'. Switch tomsw_resource_api.cjs(or replicate its UTF-8 raw-body POST pattern) asdescribed in Section 2.
- Document search fails → read
- Composite queries are allowed — e.g.
AttackComponent CalcCriticalfor docs,red slime jumpfor resources. - No guessing — Never guess API names, RUIDs, or enum values; always confirm via search or references.
모든 파일
6개 파일msw-search 설치
스킬 파일을 다운로드하여 .claude/skills/ 디렉터리에 압축을 풀어주세요.
ZIP 다운로드저장소를 클론하고 스킬 파일을 프로젝트에 복사하세요.
git clone https://github.com/MSW-Git/msw-ai-coding-plugins-official/blob/main/plugins/msw-maker-base-skill/skills/msw-search/SKILL.md # Copy SKILL.md to your .claude/skills/ directory
복사





집
