Skip to content

Releases: Wintersta7e/mz-plugin-studio

MZ Plugin Studio v1.6.0

19 Apr 17:16

Choose a tag to compare

Added

  • Plugin Browser panel — new 288px side panel for projects with many plugins (50+). Toggled via a List icon in the sidebar or Ctrl+Shift+E. Replaces the cramped bottom icon list that became unusable past ~10 plugins. Features: filename search, filter (All / Open / Dirty / Errors), sort (file order or A–Z), per-row status glyphs (error / warning / dirty dot), hover-to-close for open plugins, active-plugin highlight, and a footer summary (N total · X dirty · Y errors).
  • @type location support — official MZ map+coordinate picker. Added to parameter-type dropdown under "Game Data", parsed from imported plugins, and emitted with a JSON default ({"mapId":"0","x":"0","y":"0"}) in the IIFE body.
  • @requiredAssets annotation — plugin-level meta field for assets preserved during MZ's "Exclude unused files" deployment. New MetaEditor textarea (one asset path per line); generator emits one @requiredAssets line per entry; parser extracts them on import.
  • tests/templates-output.test.ts — 10 regression tests covering the six template bug fixes (save-load, input-handler, method-alias, battle-system, message-system, plugin-commands).
  • 24 new generator/validation/shortcut tests covering struct-array deep-parse, number[]/boolean[]/ID[] element coercion, nullish boolean defaults, reserved-word camelCase sanitization, identifier collision detection, @requiredAssets round-trip, @type location round-trip, comment-aware command dedup, and the Ctrl+Shift+E plugin-browser shortcut.

Fixed

  • Struct-array parser now deep-parses correctly — MZ double-encodes struct<X>[] as a JSON array of JSON strings. The generator previously emitted JSON.parse(accessor || '[]'), leaving each element as a string (so arr[0].x silently returned undefined). Now emits .map(s => JSON.parse(s)) for struct arrays.
  • Number/ID arrays now coerce their elementsnumber[], actor[], variable[], etc. now emit .map(Number) so arithmetic works; boolean[] emits .map(v => v === 'true').
  • Boolean @default true no longer silently becomes false — the previous accessor === 'true' returned false when the param key was absent from params (edge case: plugin added but never opened in Plugin Manager). Now nullish-coalesces to the declared default.
  • camelCase() no longer emits invalid JS identifiers — a parameter named class, default, return, 123abc, etc. previously produced const class = ... (strict-mode SyntaxError on plugin load). Sanitizer now suffixes _ on reserved words and prefixes _ on digit-start names.
  • validatePlugin detects post-transform identifier collisions — two differently-named parameters that camelCase to the same identifier (e.g., foo-bar and foo_bar) now surface as a hard error rather than silently producing duplicate const declarations.
  • Command dedup no longer false-matches commented-out examples — doc comments referencing registerCommand(...) previously suppressed generation of the real command body. A new stripCommentsOnly() helper masks comments while preserving string literals before the substring check.
  • save-load template warns about non-persistent storageGame_Actors and Game_Map are no longer silently offered as "just another option": dropdown labels mark them as non-persistent, and generated code includes a prominent WARNING comment explaining that properties set in initialize() will be lost on save reload / map change.
  • input-handler template no longer collides across plugins — the global-key handler method is now key-scoped (updateGlobalKeyInput_Q, updateGlobalKeyInput_Tab, etc.) so two plugins each hooking a different key don't clobber each other's Scene_Base.prototype.updateGlobalKeyInput.
  • method-alias replace-without-call emits a prominent WARNING — for predicates like Game_Battler.canMove, Game_Action.canUse, etc., silently returning undefined breaks MZ logic. The placeholder now includes a multiline warning + a TODO naming the specific method.
  • battle-system damage multiply is sign-preserving — the old Math.floor(value * m) over-healed by 1 point for healing skills (where value is negative). Now emits value >= 0 ? Math.floor(value * m) : Math.ceil(value * m).
  • message-system custom escape code regex has a word boundary — the no-parameter replace path previously emitted /\\X/gi, which would match \XY, \XX, etc. Now adds (?![A-Za-z]) so only single-character escape codes match.
  • plugin-commands async callback uses per-interpreter state — the previous module-scope let _XPending = false collided when two parallel events fired the same async command concurrently. Now stores the pending flag on the invoking Game_Interpreter instance.

Changed

  • @require 1 emission dropped — Kadokawa's MZ annotation reference marks @require as discontinued (MV-era). The UI checkbox is kept (faded) for round-tripping legacy imports, but the generator no longer emits @require 1 on file/animation parameters or command args.
  • @noteRequire 1 emission dropped — not part of the official Kadokawa note-asset spec (only @noteParam, @noteType, @noteDir, @noteData are documented). Parser still reads the legacy tag for back-compat.
  • @type text marked as MV-legacy in the parameter-type dropdown — the canonical MZ multi-line type is multiline_string (mapped to note internally). text still parses and emits for compatibility.
  • Generated command stubs drop the console.log(...) line — every generated PluginManager.registerCommand callback previously shipped a console.log('X called with:', { args }) stub that survived to production. Replaced with an inline comment naming the parsed args.
  • Sidebar plugin list moved to the new panel — the cramped icon-rail .js file list was removed (replaced by the Plugin Browser). The sidebar rail is now just: Open Project / New Plugin / [open-plugin tabs] / Plugin Browser / Project Data Browser / Settings / Shortcuts.
  • lucide-react 1.7.0 → 1.8.0 (safe minor; icon additions, no breaking changes).
  • Release-workflow retention policy: keep latest 2 releases (was 3).
  • Parameter-type count: 28 → 29 (added location).
  • Test count: 572 → 606 (+34 tests across generator, validation, mz-annotations, templates-output, and shortcuts).

Removed

  • uuid and @types/uuid as direct dependencies — never imported in source, tests, or tools. The project uses crypto.randomUUID() exclusively. Eliminates dead-dep attack surface and avoids a forced Node-20+ upgrade on uuid's v14 bump (which introduced breaking changes we would have had to work around for no benefit).

MZ Plugin Studio v1.5.0

29 Mar 16:19

Choose a tag to compare

Added

  • Grouped Parameter Type Dropdown — 6 logical groups (Basic, Text, Lists, Game Data, Files, Structure) with inline descriptions
  • Progressive Disclosure — advanced parameter fields collapsed by default, auto-expand when populated
  • Inline Parameter Name Validation — real-time error feedback for empty, invalid, and duplicate names
  • Drag-and-Drop Target Indicators — visual border + background highlight on drop target during parameter reorder
  • Actionable Welcome Screen — "New Plugin" card on the landing page for immediate onboarding
  • Copy ID Button — one-click ID copy on project browser items (actors, items, switches, etc.)
  • Template Category Persistence — last-selected template category remembered across opens
  • Save All (Ctrl+Shift+S) — save all dirty open plugins in parallel with toast summary
  • Toggle Preview (Ctrl+B) — collapse/expand the code preview panel
  • Command Name Collision Warning — warns when command names shadow MZ built-in commands (28 names)
  • Settings Reset to Defaults — one-click button to restore all settings
  • Export Format Descriptions — explanatory text for each export option
  • Accessibility — aria-labels on sidebar, status bar, and toast notifications; aria-live regions for dynamic content
  • Per-plugin dirty/saved/rawMode state tracking — switching tabs preserves unsaved indicators and raw mode toggles
  • generatePluginOutput() facade for unified raw/generated code switching
  • MemoizedParamRow wrapper for stable ParameterCard callback bindings
  • eslint-plugin-react-hooks with rules-of-hooks (error) and exhaustive-deps (warn)
  • consistent-type-imports ESLint rule (error) — enforces import type syntax
  • 14 new tests: plugin-store (6), ui-store (3), plugin-output (3), toast-store (2) — 411 total

Fixed

  • Security: assertSafeProjectPath() added to all 16 project IPC handlers (was missing)
  • Security: assertSafeFilename() now enforces .js extension for plugin directory writes
  • Security: Dev CSP ws: restricted to ws://localhost:* (was open to any host)
  • Security: shell.openExternal uses normalized parsed.href instead of raw URL
  • Raw mode new-parameter detection now checks both params['name'] and params["name"] (fixes duplicate declarations)
  • Raw mode new-command detection now checks all 4 quote combinations including PLUGIN_NAME + double-quote (fixes duplicate registrations)
  • History fingerprint now content-aware (parameter renames, type changes, and edits are properly captured in undo history)
  • closePlugin history cleanup race condition — cleanup now fires before state switch
  • historyStore.clear() now resets activePluginId to null
  • OptionsEditor local state now syncs on external option changes (undo, preset apply)
  • findBlockEnd escaped backslash handling (\\ before quote no longer incorrectly treated as escape)
  • scanDependencies now called explicitly after setAllGameData (removed fragile setTimeout(0) ordering)
  • setDebugLogging guarded with window.api check for test environments
  • .md and .d.ts added to ALLOWED_EXTENSIONS (README and TypeScript declaration exports were broken)
  • Toast eviction timer cleanup prevents stale timer fires
  • SettingsDialog ref capture in useEffect cleanup
  • 6 npm audit vulnerabilities resolved (flatted, minimatch, picomatch)

Changed

  • TypeScript: noImplicitAny: true enabled in both web and node tsconfigs
  • ESLint: no-unused-vars upgraded from warn to error, no-non-null-assertion added as warn, no-console added as warn
  • Status bar abbreviations expanded and font size bumped for readability
  • Raw mode toggle relabeled with clearer on/off states
  • Sidebar divider widened to 6px for easier grab targeting
  • Shared types moved to src/shared/types/ as canonical location (renderer re-exports, main/preload import directly)
  • env.d.ts imports API type from preload instead of redeclaring all interfaces
  • generateParamParser/generateArgParser unified into shared generateAccessorParser
  • parseProject reads System.json once (was 3 times per call)
  • Monaco options memoized in CodeEditor, CodePreview, and DiffView
  • Store selectors narrowed: CodeEditor subscribes to customCode only, MetaEditor to meta, StatusBar to meta.name
  • ProjectBrowser filter calls wrapped in useMemo
  • ParameterCard wrapped in React.memo with stable callback bindings
  • rawSource stripped from history entries to reduce memory retention