Kelsidavis-WoWee/include/pipeline/wowee_addon_manifest.hpp
Kelsi 9df1fa39cd feat(pipeline): WMOD addon manifest catalog (125th open format)
Novel replacement for vanilla per-addon TOC (.toc) text files
scattered across Interface/AddOns/. Each WMOD entry binds one
addon to display metadata (name / description / version / author),
client-build gate (minClientBuild), persistence + lazy-load
flags (requiresSavedVariables / loadOnDemand), and required +
optional dependency lists.

Three presets:
  --gen-mod        4 vanilla-era addons (Recount standalone +
                   Atlas standalone + Auctioneer optional-dep
                   on Atlas + Questie standalone)
  --gen-mod-ui     3 UI-replacement chain (Bartender4 root ->
                   ElvUI required-dep on Bartender4 -> SuperOrders
                   required-dep on ElvUI). Exercises the chained
                   required-dep resolution path.
  --gen-mod-util   3 standalone utility addons (XPerl, Decursive,
                   GearVendor loadOnDemand) — empty-deps baseline.

Validator catches: id+name+version required, duplicate addonIds,
duplicate addon names (load-order ambiguity), self-dependency
(load deadlock), missing required-dep addonId, full DFS cycle
detection on required deps (deadlock at load — extracts the
back-edge path so the user can see the loop). Warns on optional
self-dep (no effect, prune) and on minClientBuild < 4500
(below vanilla floor — likely typo).

Format count 124 -> 125. CLI flag count 1319 -> 1326.
2026-05-10 03:31:21 -07:00

118 lines
4.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <cstdint>
#include <string>
#include <vector>
namespace wowee {
namespace pipeline {
// Wowee Open Addon Manifest catalog (.wmod) —
// novel replacement for the per-addon TOC (.toc) text
// files vanilla WoW scattered across Interface/AddOns/.
// Each entry is one addon manifest binding the addon
// to its display metadata (name / description /
// version / author), client-build gate
// (minClientBuild), persistence + lazy-load flags,
// and required + optional dependency lists.
//
// The variable-length dependency arrays give the
// validator something interesting to check: a DFS
// cycle detector flags require-A-which-requires-A
// loops that would deadlock the addon loader.
//
// Cross-references with previously-added formats:
// None directly — addons are a client-side concept,
// so WMOD does not reference WMS / WCDB / spell
// data. Dependencies between WMOD entries are
// internal addonId references.
//
// Binary layout (little-endian):
// magic[4] = "WMOD"
// version (uint32) = current 1
// nameLen + name (catalog label)
// entryCount (uint32)
// entries (each):
// addonId (uint32)
// nameLen + name
// descLen + description
// versionLen + version (semver "1.2.3")
// authorLen + author
// minClientBuild (uint32) — lowest
// supported
// client patch
// number; 0 = no
// gate
// requiresSavedVariables (uint8) — 0/1 bool
// loadOnDemand (uint8) — 0/1 bool — LoD
// addons skip
// initial load
// pad0 (uint16)
// dependencyCount (uint32)
// dependencies (uint32 × count) — required addonIds
// optionalDependencyCount (uint32)
// optionalDependencies (uint32 × count)
struct WoweeAddonManifest {
struct Entry {
uint32_t addonId = 0;
std::string name;
std::string description;
std::string version;
std::string author;
uint32_t minClientBuild = 0;
uint8_t requiresSavedVariables = 0;
uint8_t loadOnDemand = 0;
uint16_t pad0 = 0;
std::vector<uint32_t> dependencies;
std::vector<uint32_t> optionalDependencies;
};
std::string name;
std::vector<Entry> entries;
bool isValid() const { return !entries.empty(); }
const Entry* findById(uint32_t addonId) const;
const Entry* findByName(const std::string& name) const;
// Returns addons that depend on the given addonId
// (reverse-lookup, used by the addon-disable UI to
// warn "disabling this will also disable: X, Y").
std::vector<const Entry*> findDependents(uint32_t addonId) const;
};
class WoweeAddonManifestLoader {
public:
static bool save(const WoweeAddonManifest& cat,
const std::string& basePath);
static WoweeAddonManifest load(const std::string& basePath);
static bool exists(const std::string& basePath);
// Preset emitters used by --gen-mod* variants.
//
// makeStandardAddons — 4 vanilla-era addons
// (Recount / Atlas /
// Auctioneer / Questie)
// with realistic deps.
// Recount has no deps;
// Auctioneer optionally
// depends on Atlas for
// map links.
// makeUIReplacement — 3 full-UI replacements
// (Bartender4 / ElvUI /
// SuperOrders) with a
// chain dep where Super
// Orders requires Elv.
// makeUtility — 3 standalone utility
// addons (XPerl /
// Decursive / GearVendor)
// with no inter-deps —
// baseline for the
// empty-deps path.
static WoweeAddonManifest makeStandardAddons(const std::string& catalogName);
static WoweeAddonManifest makeUIReplacement(const std::string& catalogName);
static WoweeAddonManifest makeUtility(const std::string& catalogName);
};
} // namespace pipeline
} // namespace wowee