/* * 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 #include #include #include #include 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& 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& 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& 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& 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 _tiers; std::vector _tierInstances; std::unordered_map _instances; std::unordered_map _encounters; std::unordered_map _creatures; std::unordered_map _sections; std::vector _loot; // Sorted access caches (by sort_order, id). Filled at end of Load(). std::vector _instancesSorted; std::unordered_map> _encountersByInstance; std::unordered_map> _creaturesByEncounter; std::unordered_map> _lootByEncounter; std::unordered_map> _instancesByTier; }; } #define sEncounterJournalMgr ::MoonWell::EncounterJournal::Mgr::instance() #endif // MOONWELL_ENCOUNTER_JOURNAL_MGR_H