Msw Scripting
Authoring MSW scripts (.mlua) plus integrated playtest and debugging. Covers mlua syntax, annotations (@Component/@Logic/@ExecSpace/@Sync), lifecycle, exec spaces, property sync, event system, file workflow, build-log inspection, error classification, and the test/debug loop. Keywords: script, mlua, lua, Component, Logic, annotation, ExecSpace, Sync, event, play, test, debug, lifecycle.
- Skill ID
- msw-git/msw-ai-coding-plugins-official/msw-scripting
- Publisher
- msw-git
- Repository
- msw-ai-coding-plugins-official
- Installs
- 0
- Files
- 3
- Synced
- Sep 23, 2026
Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.
msw-git/msw-ai-coding-plugins-official/msw-scriptingInstalls these files- SKILL.md
- references/datastorage.md
- references/verify-checklist.md
What this skill tells the agent
MSW Scripting (.mlua) — Framework + File Workflow + Playtest & Debugging
mlua is Lua-based, but it has MSW-specific annotations, a lifecycle, and an execution-space model. General Lua knowledge alone will not produce working code. All work is done by editing files in the workspace directly, and code is validated in the order build logs → runtime logs.
1. Core Principles (must follow)
1.1 Existing Script First
Before creating a new .mlua, glob/keyword-search under ./RootDesk/MyDesk/ for an existing script with the same purpose — extending an existing file is always the first choice. Duplicate implementations raise maintenance cost and conflict risk.
1.2 Folder Structure for New Scripts — Never Dump Files Flat
When a new .mlua is unavoidable, place it under a feature/category subfolder. Required path shape: ./RootDesk/MyDesk/<FeatureFolder>/<ScriptName>.mlua.
- Reuse an existing subfolder if it fits (
Player/,UI/,Combat/,Inventory/, …); glob./RootDesk/MyDesk/first. - Otherwise create one named for the feature (PascalCase). All related scripts of one feature (Component/Logic/Event/Struct) stay together. Even a single-file feature gets its own folder.
- Forbidden: catch-all folders like
Scripts/,Misc/,Common/,New/,temp/. A flat root makes rule §1.1 (search before creating) impossible.
Examples: Inventory/InventoryManager.mlua, Combat/MeleeAttackComponent.mlua, UI/Popup/RewardPopupLogic.mlua.
1.3 Never Guess APIs — Verify Before Writing
Guessing an MSW API name/param/return type silently fails at runtime. Required order: `.d.mlua` for signature → `msw-search` for semantics/examples if needed → write → LSP diagnose (auto-run).
The engine API lives under ./Environment/NativeScripts/:
| Folder | Contents | Count |
|---|---|---|
Component/ | Engine components | 104 |
Service/ | System services | 46 |
Event/ | Event types | 202 |
Logic/ | Built-in logic | 9 |
Enum/ | Enumerations | 118 |
Misc/ | Utility types (Vector2, …) | 140 |
Known name → Read ./Environment/NativeScripts/{folder}/{name}.d.mlua. Unknown name → Grep keywords there.
1.4 Lint (LSP diagnostics)
mlua-diagnose hook runs LSP diagnose automatically after every .mlua create/modify. Iterate fix → re-edit until error-severity diagnostics reach zero.
1.5 .codeblock & Refresh
.codeblockfiles are generated by Maker Refresh — never create/edit/delete manually.- After any
.mluacreate/modify/rename/delete, call Maker MCP `refresh`. Refresh requires edit mode —stopfirst if playing.
1.6 MSW ≠ Unity — Do Not Reason From Intuition
Applying Unity/generic patterns directly compiles fine but silently fails at runtime. Common misconceptions:
| Unity intuition | MSW reality / Where it's covered |
|---|---|
gameObject / transform from a global manager | @Logic has no self.Entity — see §3.2 (use property injection / _EntityService) |
OnMouseDown / BoxCollider2D for clicks | Physics colliders never emit TouchEvent — World uses TouchReceiveComponent (§10); UI uses ButtonComponent/UITouchReceiveComponent |
OnCollisionEnter + Rigidbody | Entity↔entity collisions need TriggerComponent + TriggerEnter/Leave/Stay event |
UI field names (interactable/text/color) | MSW-specific names — check `msw-ui-system/references/component-api.md`. Common mappings: disable→Enable, text→Text, text color→FontColor, tint→Color. ButtonComponent.Interactable doesn't exist. |
| Attach multiple Rigidbody/Collider freely | One Body per map type — see `msw-general/references/platform.md` §4 |
| Touch UI from server code | UI is client-only — server→UI goes via @ExecSpace("Client") RPC. Hosting Server/ServerOnly/Multicast/@Sync on a UI-attached Component silently no-ops with runtime warning. See `msw-ui-system/references/runtime-patterns.md` |
Instantiate(prefab) callable anywhere | _SpawnService:SpawnByModelId(id, name, pos, parent) — parent required, server-only — see §11 |
static classes / hand-rolled singletons | @Logic is itself the singleton — call as _ScriptName:Method(), never instantiate — see §3.2 |
Rule: when tempted to apply a Unity pattern, stop and verify against Environment/NativeScripts/*.d.mlua first.
1.7 Builder Protocol Preflight — MUST
If this turn touches .map / .model / .ui (directly, or via spawn/entity-placement/UI-binding code in .mlua), [`../msw-general/references/builder-protocol.md`](../msw-general/references/builder-protocol.md) (core) plus the per-builder file for each type touched ([`builder-protocol-map.md`](../msw-general/references/builder-protocol-map.md) / [`builder-protocol-model.md`](../msw-general/references/builder-protocol-model.md) / [`builder-protocol-ui.md`](../msw-general/references/builder-protocol-ui.md)) must be fully in context first (Read the full files only if never loaded this session or lost to compaction — a memorized summary does not count as in context). The core carries the shared write-side contract and cross-flow; each per-builder file carries that builder's API, typeKey metadata, auto-lint, child-entity invariants, and placeModel mirroring; knowing one builder doesn't cover another.
Triggers (broad on purpose): _SpawnService / SpawnByModelId / SpawnByEntity; any .map/.model/.ui change; calling msw_map_builder.cjs / msw_model_builder.cjs / msw_ui_builder.cjs; any "new monster/NPC/popup/map object" request; §11 or §16 work.
1.8 Method Documentation Comments — Inside the Body
Every method (lifecycle, RPC, event handler, user-defined) must have a description comment as the first line inside the body, never above the declaration. mlua's parser binds leading comments to the previous declaration, so an "above" comment is unreliable.
-- ✅ Correct
method void ApplyDamage(Entity target, number amount)
-- Applies damage and triggers hit VFX.
target:TakeDamage(amount)
end
-- ❌ Wrong — comment above the method
-- Applies damage...
method void ApplyDamage(Entity target, number amount)
target:TakeDamage(amount)
end2. Paths and File Roles
| Target | Path | Agent action |
|---|---|---|
| User scripts | ./RootDesk/MyDesk/**/*.mlua | Create / read / modify / delete directly |
| Auto-generated artifacts | *.codeblock | Do not touch (Refresh manages them) |
| Engine API definitions | ./Environment/NativeScripts/** | Read-only (do not modify) |
| Models (component lists) | ./RootDesk/MyDesk/**/*.model plus existing ./Global/*.model files in place | Edit Components when attaching scripts |
| Map instances | ./map/*.map | Edit when attaching scripts to entities that exist only inside a map |
3. Script Types and Declarations
3.1 Component scripts (@Component)
Scripts attached to an Entity. Use self.Entity to access the owning entity.
@Component
script MyScript extends Component
property number Speed = 5.0
@ExecSpace("ServerOnly")
method void OnBeginPlay()
-- initialization (also: OnUpdate(delta), OnEndPlay)
end
endAllowed parents:
Component— generic componentAttackComponent— attack system (Shape, AttackFast, OnAttack)HitComponent— hit system (OnHit, HandleHitEvent)
3.2 Logic scripts (@Logic)
Global singletons. Run independently without an Entity. Use for game managers, UI managers, utilities, etc.
@Logic
script GameManager extends Logic
@Sync property integer Score = 0
@ExecSpace("ServerOnly")
method void OnBeginPlay()
-- global initialization (also: OnUpdate, OnEndPlay)
end
end- One per world (singleton)
More from msw-git
Use this skill in a project
Open any RiverX project, search the Skills panel for msw-git/msw-ai-coding-plugins-official/msw-scripting, and install it in one click.
