This commit is contained in:
2026-05-06 23:26:10 +04:00
parent 0a3d3b6afa
commit 5dcb8be3aa
16 changed files with 2622 additions and 0 deletions
@@ -0,0 +1,197 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License v2 as published by the
* Free Software Foundation.
*/
#ifndef MOONWELL_ENCOUNTER_JOURNAL_MGR_H
#define MOONWELL_ENCOUNTER_JOURNAL_MGR_H
#include "Define.h"
#include <cstddef>
#include <cstdint>
#include <string>
#include <unordered_map>
#include <vector>
namespace MoonWell::EncounterJournal
{
struct Tier
{
uint32 id = 0;
std::string name;
uint32 flags = 0;
int32 sortOrder = 0;
};
struct Instance
{
uint32 id = 0;
std::string name;
std::string description;
std::string buttonIcon;
std::string smallButtonIcon;
std::string background;
std::string loreBackground;
uint32 mapId = 0;
uint32 areaId = 0;
uint32 worldMapAreaId = 0;
uint32 flags = 0;
int32 sortOrder = 0;
};
struct TierInstance
{
uint32 tierId = 0;
uint32 instanceId = 0;
int32 sortOrder = 0;
};
struct Encounter
{
uint32 id = 0;
uint32 instanceId = 0;
std::string name;
std::string description;
float mapPositionX = 0.f;
float mapPositionY = 0.f;
uint32 floorIndex = 1;
uint32 worldMapAreaId = 0;
uint32 firstSectionId = 0;
uint32 difficultyMask = 0;
uint32 flags = 0;
int32 sortOrder = 0;
};
struct Creature
{
uint32 id = 0;
uint32 encounterId = 0;
uint32 creatureId = 0;
std::string name;
std::string description;
uint32 creatureDisplayId = 0;
std::string icon;
uint32 difficultyMask = 0;
int32 sortOrder = 0;
};
struct Section
{
uint32 id = 0;
uint32 encounterId = 0;
uint32 parentSectionId = 0;
uint32 nextSectionId = 0;
uint32 subSectionId = 0;
std::string name;
std::string description;
uint32 creatureDisplayId = 0;
uint32 descriptionSpellId = 0;
uint32 iconSpellId = 0;
std::string icon; // empty when SQL value is NULL or ''
uint32 flags = 0;
uint32 iconFlags = 0;
int32 sortOrder = 0;
uint32 type = 0;
uint32 difficultyMask = 0;
uint32 creatureId = 0;
};
struct Loot
{
uint32 id = 0;
uint32 encounterId = 0;
uint32 itemId = 0;
uint32 difficultyMask = 0;
int32 factionMask = -1;
int32 classMask = -1;
uint32 flags = 0;
int32 sortOrder = 0;
};
class Mgr
{
public:
static Mgr* instance();
// Loads all custom_ej_* tables into in-memory caches.
// Safe to call repeatedly: previous data is dropped first.
// Returns true on success (does not fail when tables are empty).
bool Load();
// Drops cached data.
void Unload();
// Writes the configured JSON file (always) and Lua file
// (when Export.LuaFile is non-empty). On success @writtenPaths
// contains the absolute paths created/overwritten.
bool Export(std::vector<std::string>& writtenPaths, std::string& error);
// Validates relational integrity. Returns the number of errors
// found and pushes one human-readable line per error into @errors.
std::size_t Validate(std::vector<std::string>& errors);
// Imports loot rows from creature_loot_template via creature_template.lootid
// for each creature card whose creature_id != 0. Reference rows are
// followed one level. Existing rows in custom_ej_loot are skipped via
// INSERT IGNORE on the unique key. Returns the number of inserted rows.
std::size_t ImportLoot(std::vector<std::string>& warnings);
// Generates skeleton EJ rows from existing AzerothCore tables:
// - custom_ej_tier from MapEntry.expansionID buckets
// - custom_ej_instance from instance_template + sMapStore (name, type)
// - custom_ej_encounter from instance_encounters (creditType=0 only)
// - custom_ej_creature from creature_template referenced by encounters
// - custom_ej_section one Overview placeholder per encounter
// Existing rows are kept (INSERT IGNORE on PK). Returns total inserted
// rows; per-table counts are reported via @counts (tier/instance/
// tier_instance/encounter/creature/section).
struct SkeletonCounts
{
std::size_t tiers = 0;
std::size_t instances = 0;
std::size_t tierInstances = 0;
std::size_t encounters = 0;
std::size_t creatures = 0;
std::size_t sections = 0;
};
std::size_t ImportSkeleton(SkeletonCounts& counts,
std::vector<std::string>& warnings);
std::size_t TierCount() const { return _tiers.size(); }
std::size_t InstanceCount() const { return _instances.size(); }
std::size_t EncounterCount() const { return _encounters.size(); }
std::size_t CreatureCount() const { return _creatures.size(); }
std::size_t SectionCount() const { return _sections.size(); }
std::size_t LootCount() const { return _loot.size(); }
private:
Mgr() = default;
std::string ResolveExportPath(std::string const& filename) const;
std::string BuildJson() const;
std::string BuildLua(std::string const& globalName) const;
std::vector<Tier> _tiers;
std::vector<TierInstance> _tierInstances;
std::unordered_map<uint32, Instance> _instances;
std::unordered_map<uint32, Encounter> _encounters;
std::unordered_map<uint32, Creature> _creatures;
std::unordered_map<uint32, Section> _sections;
std::vector<Loot> _loot;
// Sorted access caches (by sort_order, id). Filled at end of Load().
std::vector<uint32> _instancesSorted;
std::unordered_map<uint32, std::vector<uint32>> _encountersByInstance;
std::unordered_map<uint32, std::vector<uint32>> _creaturesByEncounter;
std::unordered_map<uint32, std::vector<std::size_t>> _lootByEncounter;
std::unordered_map<uint32, std::vector<uint32>> _instancesByTier;
};
}
#define sEncounterJournalMgr ::MoonWell::EncounterJournal::Mgr::instance()
#endif // MOONWELL_ENCOUNTER_JOURNAL_MGR_H