Files
AdamuSw/docs/superpowers/specs/2026-07-19-new-maps-import-design.md
Acentech Dev 3b2e26b27c docs: design spec for new maps import (pilot: Arkania/World83)
End-to-end import of one pilot map across server (OpenMU C# map
initializer + Terrain83.att resource + DB update-plugin), PC client
(World83/Object83 assets), and web (no changes; MapEditor renders
seeded terrain, user adds spawns/NPCs). Other 4 maps + mobile are
follow-up from the proven template.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 13:21:40 +03:00

7.7 KiB

New Maps Import — Design (Pilot: Arkania / World 83)

Date: 2026-07-19 Status: Approved (design), pending implementation plan Scope of this spec: Import ONE pilot map (Arkania, world index 83) end-to-end across server (OpenMU), PC client, and web admin panel. The other four maps (Acheron 84, Debenter 85, Uruk 86, Ferea 87) and the mobile client are explicitly out of scope for the pilot and will be replicated from the proven pilot template in follow-up work.

Background

A third-party map pack provides 5 maps with both client and server assets:

  • Source: C:\Users\efpa\Downloads\Arkania Acheron Debenter Uruk Ferea\Arkania Acheron Debenter Uruk Ferea
  • Client Side/Data: World83-87 (terrain: EncTerrain8N.att/.map/.obj, TerrainHeight.OZB, TerrainLight.OZJ, tile textures, minimap.map), Object83-87 (object BMD models + textures), Local/Eng (ImgsMapName/*.OZT map-name images, Minimap/*.bmd, movereq_eng.bmd).
  • Server Side/Data: MapManager.txt (classic C++ MuServer map config — reference only), Move/Gate.txt, Move.txt, MoveSummon.txt (warp gates — reference only), Terrain/Terrain83-87.att (walkability/safezone attributes).

The server-side files are classic C++ MuServer format and are NOT consumed by OpenMU — except the .att terrain files, which match OpenMU's terrain resource format exactly.

Key technical findings (verified)

  1. Terrain is a drop-in for OpenMU. OpenMU loads map terrain via GameMapDefinition.TerrainData, populated by _mapDefinition.UpdateTerrainFromResources(TerrainVersionPrefix) in BaseMapInitializer, from an embedded resource Resources/Terrain{Number}.att. The pack's server Terrain83.att is 65539 bytes, header 00 ff ff 04 — byte-for-byte the same format as OpenMU's existing Resources/Terrain1.att (65539, 00 ff ff 04). The client's EncTerrain83.att (65540, encrypted) is NOT what the server wants; the server-side .att is.
  2. Indices 82-87 are free in the current OpenMU (AdamuSw) map set — no collision at 83.
  3. Web admin panel needs no code changes. Once a GameMapDefinition (number 83) exists in the DB, it appears automatically in:
    • /edit-config-grid/GameMapDefinition (GameMaps CRUD)
    • /map-editor → visual MapEditor (renders terrain from TerrainData; CreateNewSpawnArea, CreateNewEnterGate, CreateNewExitGate, duplicate/remove/undo/save)
    • /edit-config-grid/WarpInfo (/move warp list), /edit-config-grid/MonsterDefinition (monsters)
  4. Monster spawns / NPCs are NOT in the pack. The seeded map is intentionally EMPTY (scenery + walkable + safezone only). Spawns, NPCs and gates are added by the user via the web MapEditor.
  5. Index→name ambiguity. Pack folders are World83-87 (no World82). MapManager.txt labels 82=Arkania,83=Acheron,…,87=TeamvsTeam (off-by-one / stock reference). The pack's own title order ("Arkania Acheron Debenter Uruk Ferea") + available folders (83-87) imply 83=Arkania, 84=Acheron, 85=Debenter, 86=Uruk, 87=Ferea. Pilot uses World83 = Arkania, to be confirmed against the pack screenshots during implementation.

Chosen approach

Approach A — OpenMU-native C# map initializer + terrain resource + DB update-plugin. This mirrors every existing OpenMU map and the proven Imperial-items dual-path pattern (see android-add-new-weapon-item). Rejected alternatives: (B) pure-panel creation — not viable, the 65KB TerrainData byte[] cannot be entered via a web form; (C) build a C++→OpenMU map converter to use the MapEditor Import — unnecessary work for a pilot.

Components / changes

Server repo: AdamuSw (Gitea, branch off main).

  1. Terrain resource — copy pack Server Side/Data/Terrain/Terrain83.attsrc/Persistence/Initialization/Resources/Terrain83.att. Verify it is included as an embedded resource by the .csproj (the Resources/*.att glob); add explicitly if not globbed.
  2. Map initializersrc/Persistence/Initialization/VersionSeasonSix/Maps/Arkania.cs:
    • Number => 83
    • Name => "Arkania"
    • TerrainVersionPrefix => string.Empty
    • Safezone / spawn gate as required by BaseMapInitializer (minimal; a single safe spawn gate so players don't spawn on a blocked tile).
    • Empty CreateMonsterSpawns / NPC init (spawns added later via panel).
    • Follow the existing map-class pattern (many inherit a Version075.Maps.* base; Arkania is new so it derives from BaseMapInitializer directly, like other SeasonSix-only maps).
  3. Registration (fresh seed) — add Arkania to the map initializer list so a zero DB seeds it (alongside Weapons.Initialize()-style wiring in the SeasonSix data-initialization).
  4. DB update-plugin (existing DB)src/Persistence/Initialization/Updates/AddArkaniaMapUpdateSeason6.cs:
    • UpdateVersion = next free number (after the Imperial 95).
    • Idempotency guard: if a map with Number == 83 already exists, skip.
    • Creates the map by invoking the same logic as the initializer.
    • Applied at runtime only via AdminPanel → Updates (per the Imperial finding; DataUpdateService is only triggered there). Do NOT call SaveChanges inside the plugin.
  5. Access / warp (for testing) — a WarpInfo entry ("Arkania", target map 83, coordinates on a safe tile, level/zen cost) so the map is reachable via /move Arkania, plus an entrance ExitGate. May be seeded or added via panel; seeding it keeps the pilot self-contained for verification.
  6. PC client — copy World83, Object83, and the Local/Eng additions (ImgsMapName/Arkania.OZT, Minimap/Minimap_World83_eng.bmd if present, merge movereq_eng.bmd) into D:\AdaMu\AdaMu\Data. Verify the MUnique engine supports world index 83 (terrain/object loading is generic; if a world-index cap or per-index table blocks it, add support in vendor/MuMain source and rebuild Main.exe per pc-munique-client-build).

Data flow

Server loads map 83 from GameConfigurationUpdateTerrainFromResources decodes Terrain83.att into walkable/safezone grid → player issues /move Arkania (or uses the entrance gate) → server places them on the safe spawn tile of map 83 → PC client renders Data/World83 (terrain + objects) → empty but walkable map. In the web panel, MapEditor renders the same terrain from TerrainData; the user places MonsterSpawnArea/gates/NPCs and saves → they take effect on the live server.

Verification

  1. Server build: docker build -f Startup/Dockerfile -t adamu-openmu:dev . succeeds; map 83 present in built config (symbol/log check). Local dotnet build is expected to fail at the source-gen pre-step (normal, per Imperial notes).
  2. Web: map "Arkania" appears in /edit-config-grid/GameMapDefinition; /map-editor renders its terrain (not blank).
  3. PC client: /move Arkania enters the map; terrain and objects render; no crash; safezone correct; player can walk.
  4. Only after all three pass is the pilot considered done.

Out of scope (follow-up, after pilot proven)

  • Maps 84-87 (Acheron/Debenter/Uruk/Ferea) — same template, replicated.
  • Mobile client asset import + APK considerations.
  • Authoring actual monster spawns / NPCs / drops (done by the user via panel; not part of the seed).
  • Any C++→OpenMU map converter.

Risks

  • Index/name mismatch → wrong map name shown. Mitigation: confirm World83 identity against pack screenshots before finalizing Name.
  • Engine world-index support on the MUnique client for index 83 → if unsupported, requires a vendor/MuMain change + rebuild. Low likelihood (loading is data-driven) but flagged.
  • Terrain resource not globbed by the csproj → map loads with empty terrain. Mitigation: verify embedded-resource inclusion during step 1.