Skip to content

feat(admin-panel): add a terrain editor for maps and their terrain variants - #1236

Merged
sven-n merged 4 commits into
masterfrom
claude/elegant-euler-6nx3ol
Oct 18, 2026
Merged

sven-n merged 4 commits into
masterfrom
claude/elegant-euler-6nx3ol

Conversation

@sven-n

@sven-n sven-n commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

Summary

Adds a dedicated Terrain editor to the admin panel (Game configuration → Terrain editor, route /terrain-editor), next to the existing map editor.

  • Edits the default terrain (GameMapDefinition.TerrainData) and the terrain variants (GameMapTerrainVariant, e.g. Crywolf peace/occupied/war) of a map.
  • Tools: brush (adjustable size), rectangle, fill (connected tiles with equal attributes).
  • Modes: add, remove or replace the selected attributes (Safezone, Blocked, NoGround, Water). Other bits found in the files are kept and shown as "other attributes".
  • Zoom (mouse wheel or the toolbar buttons, 100%–1600%, plus reset), panning with the right mouse button, an optional tile grid, and a status line with the coordinates and attributes of the tile under the cursor.
  • Undo/redo per terrain.
  • Import of terrain files: the server *.att (65539 bytes) and the encrypted client EncTerrain*.att (byte and word-per-tile variants).
  • Download as the server *.att file and as the encrypted client EncTerrain<N>.att file, so changed terrains can be shipped to players.

Screenshots

The war terrain variant of the Crywolf fortress:

Terrain editor showing the war terrain of the Crywolf fortress

Lorencia at 600% zoom with the tile grid on. The blue area was just added as water with the rectangle tool, and the dashed frame is the preview of the next rectangle:

Zoomed terrain with tile grid while drawing a rectangle

Implementation notes

  • Painting happens in the browser (canvas + JS module) so it is instant. After each finished edit, the component pulls the 64 KB terrain through an IJSStreamReference, because it exceeds the SignalR message limit, and assigns it to the entity. Unsaved-changes detection and saving then work through the persistence context, like in the map editor.
  • TerrainFileConverter handles the server and client formats. The client encryption (map file XOR/key chain plus the 3-byte XOR key) follows the open source client (ZzzLodTerrain.h, _crypt.h in MuMain), not decompiled code.
  • The page logic of EditMap (loading maps, saving, asking before discarding changes) moved into MapEditorPageBase<TEditor>, so EditMap and the new EditTerrain are a few lines each instead of a copy.
  • The styles live in wwwroot/css/terrain-editor.css (registered in Exports), like map-editor.css. In the all-in-one startup host, the scoped CSS bundle of Web.Shared currently returns 404, so a .razor.css would not apply.
  • New UI texts are in Resources.resx with German and Chinese translations.
  • Docs: added a "Terrain editor" section with the two screenshots above to docs-website/docs/admin-panel/map-editor.md, and updated the overview row.

Testing

  • dotnet test tests/MUnique.OpenMU.Web.Tests: 252 passed. New tests:
    • TerrainFileConverterTests: server/client round trips, header, rejecting invalid files, and a known-answer check of the client encryption. The expected bytes come from compiling MuMain's own MapFileEncrypt/BuxConvert.
    • TerrainEditorTests (bUnit): variant selection, initial load, and the client file name and content on download.
  • Manual end-to-end test with Playwright against Startup -demo:
    • Painted with brush and rectangle; undo/redo, zoom buttons and mouse-wheel zoom, and Crywolf variant selection all work.
    • Saved, then checked that the map editor shows the changed terrain.
    • The downloaded server file contains the edits.
    • Decrypted the downloaded EncTerrain1.att with MuMain's own decryption code: header 0 0 255 255, size 65540, and the client's Lorencia sanity check (TerrainWall[123*256+135] == 5) passes.
    • Imported that client file into another map and downloaded it again: the result is byte-identical.
    • After the lint fixes: a fast diagonal brush stroke still paints a gap-free line.
  • Not tested: loading an exported client file in the actual game client.

Codacy

The style findings (braces, arrow parentheses, constant loop condition, docs line length) are fixed. The remaining findings are false positives or thresholds I didn't follow:

  • Sonar S3459/S4487 on the ElementReference fields and _canUndo/_canRedo: they are assigned and read by the Razor markup (@ref, disabled=).
  • S2931 on MapEditorPageBase: it does implement IDisposable and disposes _disposeCts.
  • S2339 on the public TileCount constant.
  • ESLint security/detect-object-injection on typed-array indexing.
  • ESLint complexity with a maximum of 4.
  • PMD "unnecessary block" on object literals (return { x, y }).

Noticed, not changed

🤖 Generated with Claude Code

https://claude.ai/code/session_01KESqfok2EbBMX41efgZUvw

…n variants

The new page /terrain-editor shows the terrain of a map and lets you paint
its attributes (safezone, blocked, no ground, water) with a brush, a
rectangle or a fill tool, adding, removing or replacing the selected
attributes. It edits the default terrain and the terrain variants of a map,
supports zoom, panning, a tile grid, undo and redo.

Terrain files can be imported (server *.att or client EncTerrain*.att) and
downloaded in both formats, so that the changed terrain can also be
distributed to the game client.

The page logic which loads the maps, saves and asks before discarding
changes is shared with the map editor page through a common base class.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KESqfok2EbBMX41efgZUvw
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Deploying openmudocs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 27d77d2
Status: ✅  Deploy successful!
Preview URL: https://a8f9a03e.openmudocs.pages.dev
Branch Preview URL: https://claude-elegant-euler-6nx3ol.openmudocs.pages.dev

View logs

claude and others added 3 commits October 18, 2026 09:26
Adds braces to single-line ifs and parentheses to arrow function
parameters, replaces the constant loop condition of the brush line,
and wraps over-long lines in the terrain editor documentation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KESqfok2EbBMX41efgZUvw
@sven-n
sven-n merged commit e715848 into master Oct 18, 2026
3 of 4 checks passed
@sven-n
sven-n deleted the claude/elegant-euler-6nx3ol branch October 18, 2026 14:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants