Skip to content

Replace Gridarta with the standalone MIT Rust editor #13

Description

@zoeyrose

Important

This preserved authoring issue now belongs to the fresh MIT Rust editor under the replacement program. Gameplay/content design and safe-authoring requirements remain unchanged. Legacy implementation paths below are historical evidence.

Replacement implementation contract

Keep this as the editor-delivery and classic-authoring-retirement epic. The standalone editor owns GUI/project workflow; content-toolkit owns headless lossless model/compiler/automation; renderer owns GPU/offscreen presentation; atrinik owns isolated playtests. Preserve all AI-friendly, safe-editing, preview, attribution, and parity goals.

Verified original past contributions by an approved MIT provenance grantor may be copied, migrated, translated, or relicensed under MIT only after complete Git provenance and third-party-material review is recorded. Other GPL implementation/tests must not be mechanically ported.

Required verification

  • Preserve unknown fields, comments, ordering, and untouched bytes through lossless toolkit transactions.
  • Use semantic commands with revision preconditions, dry-run/diff, undo/recovery, validation, and atomic writes.
  • Use the exact shared renderer and toolkit APIs; no duplicate parser, renderer, or pixel-selection path.
  • Test Linux/Windows, malformed/large projects, external edits, storage/device failures, and wrapper-isolated playtests as applicable.
Preserved product/design specification and historical implementation notes

Summary

Replace the unsupported Gridarta/Java map-maker workflow with two parts built around one content model:

  1. a native offline atrinik-editor executable that shares the legacy client's SDL3 asset and rendering path; and
  2. a headless atrinik-content CLI with stable JSON input/output, transactional edits, validation, and optional rendered previews for human scripts and AI agents.

The content core and CLI can begin before the SDL migration. The native editor should build on atrinik/atrinik#128 and the reusable renderer/resource boundary introduced by atrinik/renderer#17.

Why

The current editor workflow is no longer a maintainable product:

  • editor/ only contains scripts for downloading or launching AtrinikEditor.jar.
  • tools/map-maker/ packages the Java editor together with specially built client/server binaries, old Python/PyQt requirements, and platform launchers.
  • The map checker still shells out to Gridarta for editing.
  • Map/resource parsing is duplicated across the server Flex loaders, the old and Qt map checkers, mapset, worldviewer, world_content_audit.py, the bot/navigation tooling, and smaller analyzers. These implementations do not share a complete syntax or semantic model.
  • The current Qt saver reconstructs complete files. A modern editor needs a lossless representation so opening and saving a map cannot reorder or normalize unrelated content.

A web editor is tempting for UI velocity, but it is the wrong first implementation. The legacy client now has substantial rendering semantics in client/src/gui/widgets/map.c, client/src/client/lighting.c, sprite.c, and tilestretcher.c: unified cross-level painter ordering, linked physical depths, terrain elevation, floor masks, smooth structural lighting, fog/cutaways, multipart objects, animation, and minimap behavior. Reimplementing those rules in a browser would create a second renderer that drifts from the game. next/client is also an intentionally separate game implementation, not a renderer for legacy maps.

Proposed decision

Build a native companion editor, not editing code inside the connected game session:

  • atrinik and atrinik-editor link the same extracted renderer, texture/resource manager, animation support, isometric projection, lighting, and scene-draw modules.
  • The game client adapts its network-populated MapCell caches into the shared render scene.
  • The editor adapts an authored map document and local archetype/face/animation catalog into the same scene.
  • The editor owns offline authoring state, selection, tools, undo/redo, diagnostics, and repository writes. The normal client binary remains free of filesystem-authoring and editor state.
  • We may expose atrinik --editor ... as a convenience launcher later, but it should start the editor target rather than mixing editor mode into a live gameplay process.

This gives map makers the exact client view while keeping the security, dependency, startup, and state boundaries understandable.

Architecture

1. Lossless content core

Introduce one reusable content library for authored Atrinik text formats, initially maps and the nested archetype syntax they use.

It must retain:

  • original token order, comments, blank lines, line endings, multiline msg bodies, unknown keys, nested inventories, and source spans;
  • a semantic view of map headers, objects, inventories, coordinates, archetype inheritance/overrides, faces, animations, layers/sub-layers, exits, tiled neighbors, regions, and linked physical levels;
  • diagnostics with file, line/column, map coordinate, stable rule ID, severity, and suggested fix where safe; and
  • ephemeral node handles plus file-content preconditions so tools can target an inspected object without adding editor-only IDs to authored files.

Unchanged documents must serialize byte-for-byte. A targeted edit should rewrite only the affected tokens or object block. Unknown fields must survive edits even when the semantic schema does not understand them.

Do not link the editor directly to the live server object model or use new_save_map(): server loading applies runtime behavior such as treasure generation, auto-apply, unique-object handling, and mutable temporary saves. Keep that runtime loader initially, and validate the new source model against it with a representative corpus. Replacing server parsing can be considered later after equivalence is demonstrated.

The field/type metadata needed by property editors and validation should have one machine-readable source of truth. Generate the server loader tables/documentation and editor schema from it where practical instead of copying the large field list into another UI.

2. Repository-aware asset catalog

Build an in-memory/project cache from authored nested files under arch/ and maps/, including archetypes, artifacts, faces, animations, treasures, regions, and attribution metadata. It should support incremental invalidation after filesystem changes and searchable/filterable catalog queries.

The authoring workflow must not require modifying top-level collected aggregates, server/lib/, server/data/, or generated region maps. Collection remains an explicit validation/playtest step.

3. Shared render scene

As part of atrinik/renderer#17, extract map rendering from client globals into a context/API that accepts a read-only scene snapshot and view parameters. The abstraction needs to preserve all invariants documented in client/AGENTS.md, including the single back-to-front queue across physical levels rather than compositing complete maps independently.

The renderer should not know whether a scene came from protocol packets or an editor document. Resource lookup should likewise be provider-based: authenticated server/cache assets in the game and local authored assets in the editor.

This is a useful design constraint for atrinik/renderer#17 even before the editor UI exists: GPU resources remain private to the renderer, while gameplay and authoring code submit renderer-owned scene/draw data.

4. Native editor shell

The map-first MVP should provide:

  • project/map open, recent files, multi-map tabs, and tiled-neighbor navigation;
  • exact isometric preview with pan/zoom, stacked-depth selection, layer/sub-layer visibility, lighting/fog/cutaway preview toggles, animation pause, grid, coordinates, and object bounds;
  • searchable archetype palette with face/animation previews and favorites/recent items;
  • select, paint, erase, eyedropper, move, rectangle, fill, copy/paste, and rotation/direction tools;
  • object/inventory tree and schema-driven property inspector with a raw lossless fallback;
  • map header, region, tiled-neighbor, exit destination, and backlink assistance;
  • command-based undo/redo, dirty state, autosave/recovery outside the source tree, and a textual/semantic diff preview before save; and
  • inline diagnostics linked to the exact map tile/object.

Archetype, animation, treasure, artifact, faction, interface, and quest authoring can follow as focused panels once the shared model and map editor are sound. Do not make the first usable map editor wait for every content class.

5. AI- and automation-friendly CLI

The CLI is a first-class interface to the same content core, not a wrapper around GUI automation. It should support operations along these lines (exact command names can be refined):

atrinik-content catalog search --kind archetype --text oak --json
atrinik-content map inspect maps/... --at 12,34 --radius 2 --json
atrinik-content map validate maps/... --json
atrinik-content apply --patch changes.json --dry-run --diff
atrinik-content apply --patch changes.json --validate --atomic
atrinik-content diff --semantic maps/...
atrinik-editor --render-map maps/... --camera 12,34 --output preview.png

Requirements:

  • documented, versioned JSON schemas for inspection results, diagnostics, patches, and errors;
  • deterministic output, bounded queries, meaningful exit codes, and no ANSI/progress text in JSON mode;
  • patch preconditions containing the inspected file digest and target-node fingerprint;
  • dry-run by default for machine-authored batches, with an explicit apply operation;
  • all-or-nothing multi-file edits using same-directory atomic replacement only after every precondition and validation step succeeds;
  • primitive operations such as add/remove/move/copy object, set/unset property, fill/replace region, edit header, connect exits, and update tiled neighbors, rather than unrestricted text replacement;
  • text and semantic diffs that make review easy;
  • refusal by default to write collected/generated outputs or mutable runtime paths; and
  • read-only operation without a configured server runtime or initialized submodules unless the requested asset specifically needs one.

A thin stdio MCP server may be added after the CLI schemas stabilize, exposing catalog, inspect, validate, patch, diff, and render tools. It must call the same core operations and safety checks; MCP should not become a second editing implementation.

Rendered preview is especially valuable for AI review, but structured inspection and validation must remain fully headless. Preview may open a hidden/offscreen editor renderer and should report clearly when the current environment has no supported render backend rather than falling back to a divergent map renderer.

6. Safe playtest workflow

After the offline editor is useful, add a one-click/one-command playtest that:

  • collects affected resources into an isolated build/runtime directory;
  • starts a disposable local server and client without overwriting server/data/ or source-generated outputs;
  • enters the selected map/coordinate using a development-only account/control path; and
  • tears down only processes and temporary state it created.

Hot reload, remote source editing, direct writes into a running server, and SFTP deployment are deliberately out of scope for the first implementation. They mix authored source with mutable runtime/deployment state and are not needed for a fast local edit/validate/playtest loop.

Phased delivery

Phase 0: contracts and corpus (can start now)

  • Inventory the complete map/archetype grammar and current consumers.
  • Build a representative corpus covering comments, messages, nested inventories, multipart objects, custom fields, tiled/stacked maps, exits, and malformed inputs.
  • Define versioned diagnostic, inspect, and patch JSON schemas.
  • Add byte-identical no-op round-trip tests and semantic comparison tests against server loading/checker behavior.

Phase 1: content core and CLI (can start before SDL3)

  • Implement lossless parsing/targeted serialization, project indexing, schema/catalog lookup, diagnostics, atomic transactions, dry-run, and diffs.
  • Implement safe map inspection and primitive patch operations.
  • Integrate current map-checker/world-audit rules behind the common diagnostic format, then migrate duplicated parsers incrementally once parity tests pass.

Phase 2: renderer/resource extraction (alongside/after atrinik/atrinik#128 and atrinik/renderer#17)

  • Make the SDL3 renderer and resource lookup reusable by both executables.
  • Introduce live-client and authored-document scene adapters.
  • Add representative client/editor visual equivalence fixtures and renderer lifecycle tests.

Phase 3: native map editor MVP

  • Add the atrinik-editor Linux and Windows targets and project discovery.
  • Implement core viewport, palette, selection/editing tools, inspector, layers/depths, undo/redo, diagnostics, and minimal-diff save.
  • Package it without Java, Gridarta, or a bundled server/client copy.

Phase 4: workflow completion

  • Add tiled/exit graph assistance, advanced bulk tools, preview rendering, isolated playtest, recovery, and performance work.
  • Add focused editors for other authored content based on actual map-maker needs.
  • Optionally add the stdio MCP facade.

Phase 5: retire superseded tooling

  • Remove editor/AtrinikEditor.jar download/launcher assumptions and the legacy map-maker packaging flow.
  • Remove old GUI/checker/parser paths only after their required validation rules and workflows are covered.
  • Update README.md, INSTALL, architecture docs, content skills, and attribution guidance.
  • Close or supersede Simplify Map Maker Package atrinik#33 when the supported replacement workflow lands.

Acceptance criteria

  • Opening and saving an unchanged representative authored file produces no byte changes; targeted edits do not churn unrelated lines or objects.
  • Unknown fields, comments, multiline text, nesting, and object order survive every supported edit.
  • CLI inspection/diagnostics/patches conform to versioned JSON schemas and are deterministic across Linux and Windows.
  • Stale/conflicting patches fail before writing; a failed multi-file transaction leaves every source file unchanged.
  • The CLI/editor refuse generated and runtime write targets by default and never require authoring directly in server/lib/ or server/data/.
  • The editor and connected client use the same renderer/resource modules; visual fixtures cover ordinary maps, multipart objects, linked depths, lighting, fog/cutaways, animation, and tiled edges.
  • Linux and MinGW builds pass with warnings as errors, and editor startup/open/edit/save/reopen/undo/redo are covered by automated model tests plus smoke tests.
  • A map maker can install/build the supported tools, edit and validate a map, preview it in the exact client renderer, and launch an isolated playtest without Java/Gridarta or the old map-maker package.
  • An AI agent can inspect a bounded map area, search the catalog, propose a preconditioned dry-run patch, validate it, apply it atomically, and receive a reviewable diff without GUI automation.

Non-goals for the first release

  • A browser renderer that independently recreates legacy visuals.
  • Editing a production/remote server or mutable player/runtime state.
  • Collaborative multi-user editing.
  • A new map file format solely for the editor.
  • Replacing every content tool before a useful map editor ships.

This proposal supersedes the direction of atrinik/atrinik#33 while retaining its goal of making map development substantially easier; deployment and remote editing should be considered separately after the safe local workflow exists.

Child issues

These GitHub sub-issues are the executable delivery units tracked by atrinik/atrinik#168. Each belongs to one roadmap milestone; this parent remains open until all are complete.

M1

M2

  • atrinik/content#13 — Content editor: integrate authored documents with the shared renderer

M3

M4

Program parity and milestone sequencing

  • #15 owns the M1 machine-readable inventory of every supported classic authoring behavior and fixture.
  • #17 owns only the bounded M3 open/render/edit/save/reopen/playtest vertical slice required by atrinik#271; it is extended, not discarded, by the M4 MVP issues.
  • #16 burns the inventory down across the complete supported baseline content pack in M5 and publishes the editor report consumed by atrinik#280.
  • This parent remains M6 because package hardening, documentation/default changes, Gridarta retirement, and final archive evidence happen only after M5 parity. Do not make the M5 gate depend on completion of M6 retirement work.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Fields

    No fields configured for Initiative.

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions