Files
..
wip
2026-05-06 23:26:10 +04:00
wip
2026-05-06 23:26:10 +04:00
wip
2026-05-06 23:26:10 +04:00
2026-06-06 19:51:34 +04:00
2026-06-06 19:51:34 +04:00
wip
2026-05-06 23:26:10 +04:00
wip
2026-05-06 23:26:10 +04:00
2026-06-06 19:51:34 +04:00

mod-encounter-journal

Source-of-truth for the MoonWellClient EncounterJournal addon. Stores all data (tiers, instances, encounters, sections, creatures, loot) in acore_world under custom_ej_* tables and exports them as JSON / Lua that the client can consume directly. No DBC dependency.

Layout

mod-encounter-journal/
├── conf/                                  module configuration
├── data/sql/db-world/base/
│   ├── 01_encounter_journal_schema.sql    table definitions
│   └── 02_encounter_journal_sample.sql    sample data (Deadmines, Naxxramas)
├── data/sql/db-world/updates/             future incremental migrations
├── docs/encounter_journal_format.md       output structure reference
├── src/                                   C++ implementation (manager + commands)
└── tools/json_to_lua.py                   offline JSON → Lua fallback

Tables

Table Purpose
custom_ej_tier Top-level expansion / content bucket
custom_ej_instance Dungeon / raid header
custom_ej_tier_instance N:M tier ↔ instance
custom_ej_encounter Boss / encounter under an instance
custom_ej_creature Creature card (portrait, name, description) per encounter
custom_ej_section Tree of Overview / Abilities sections
custom_ej_loot Explicit loot table per encounter

References to standard AzerothCore tables:

  • custom_ej_instance.map_idinstance_template.map
  • custom_ej_creature.creature_idcreature_template.entry
  • custom_ej_loot.item_iditem_template.entry
  • custom_ej_creature.creature_display_id is optional and only used by the client's 3D portrait tab; pull it from creature_template.modelid1..modelid4 when populating manually.

Bitmasks

instance.flags

Bit Meaning
0x000 dungeon (default)
0x010 raid
0x040 hide difficulty
0x800 open world

encounter.difficulty_mask

For dungeons:

Bit Meaning
0x1 normal
0x2 heroic
0x4 mythic (custom)

For raids:

Bit Meaning
0x1 10 normal
0x2 25 normal
0x4 10 heroic
0x8 25 heroic

section.flags

Bit Meaning
0x1 starts open
0x2 heroic only

Console / GM commands

All commands require administrator rights, except info which is gamemaster-only. They run from the in-game chat and the worldserver console.

Command What it does
Command What it does
-------------------- ---------------------------------------------------------------------------------------------------
.ej info Print row counts of the in-memory cache.
.ej reload Re-read all custom_ej_* tables.
.ej validate Run integrity checks (see "Validation" below).
.ej importskeleton Generate instance/encounter/creature/section rows from instance_template + instance_encounters.
.ej importloot Auto-populate custom_ej_loot from creature_loot_template (skips dupes).
.ej importall Run importskeleton then importloot back-to-back.
.ej export Write EncounterJournalData.json (and .lua) to the configured path.

Configuration

conf/mod_encounter_journal.conf.dist (rename to .conf to override):

Option Default Description
EncounterJournal.Enable 1 Master switch.
EncounterJournal.Export.Path (current working dir) Output directory; must exist & be writable.
EncounterJournal.Export.JsonFile EncounterJournalData.json JSON filename.
EncounterJournal.Export.LuaFile EncounterJournalData.lua Lua filename. Empty string skips Lua generation.
EncounterJournal.Export.LuaGlobal MoonWellEncounterJournalData Name of the Lua global the addon reads.
EncounterJournal.ExportOnStart 0 When 1, exports JSON/Lua right after startup load (useful for headless docker without TTY).

Output format

The exporter writes the following top-level structure (full per-row layout in docs/encounter_journal_format.md):

{
  "tiers":         [ /* [id, name, flags, sort_order] */ ],
  "instances":     { /* "instance_id": [...] */ },
  "tierInstances": { /* "tier_id": [instance_id, ...] */ },
  "encounters":    { /* "instance_id": [[...], [...]] */ },
  "creatures":     { /* "encounter_id": [[...], [...]] */ },
  "sections":      { /* "section_id": [...] */ },
  "items":         { /* "encounter_id": [[...], [...]] */ }
}

Field order inside each row matches the layout the MoonWellClient EncounterJournal addon expects, so the Lua file can be loaded directly:

-- in your addon Init() or once on load
local data = MoonWellEncounterJournalData
for _, tier in ipairs(data.tiers) do
    -- tier[1]=id, tier[2]=name, tier[3]=flags, tier[4]=sort_order
end

Workflow

  1. Edit data — INSERT/UPDATE rows in custom_ej_* tables.
  2. Validate.ej validate (no errors expected).
  3. Export.ej export (writes JSON + Lua to Export.Path).
  4. Ship — copy EncounterJournalData.lua into the MoonWellClient EncounterJournal addon directory.

For loot, you can shortcut step 1:

  1. Insert the encounter and a custom_ej_creature row with creature_id set to the boss NPC id.
  2. Run .ej importloot — entries from creature_loot_template (and one level of reference_loot_template) are inserted into custom_ej_loot with difficulty_mask copied from the creature card. Existing rows are skipped via the unique key.
  3. Manually clean up: drop trash items, set faction_mask / class_mask / sort_order where needed.
  4. Re-run .ej validate and .ej export.

Validation

.ej validate verifies:

  • every tier_instance.tier_id and tier_instance.instance_id exists;
  • every encounter.instance_id exists;
  • every encounter.first_section_id exists or equals 0;
  • encounter.difficulty_mask only uses bits valid for the parent instance type (dungeon → 0x7, raid → 0xF);
  • every creature.encounter_id exists;
  • every creature.creature_id (if non-zero) exists in creature_template;
  • every section.encounter_id exists;
  • every section.parent_section_id / next_section_id / sub_section_id (if non-zero) exists;
  • every loot.encounter_id exists;
  • every loot.item_id exists in item_template;
  • no loot duplicates by (encounter_id, item_id, difficulty_mask, faction_mask, class_mask).

sort_order stability is enforced by the schema (column has no AUTO_INCREMENT/random default, exporter sorts on it).

Offline JSON → Lua

If you produce the JSON outside the worldserver (e.g., from a CI job that talks to MySQL directly), use the bundled converter:

python3 modules/mod-encounter-journal/tools/json_to_lua.py \
    --input  EncounterJournalData.json \
    --output EncounterJournalData.lua \
    --global MoonWellEncounterJournalData

The output uses the same field order, key sort, and global name as .ej export, so the addon does not care which path produced the file. Whitespace / float formatting may differ slightly.