mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-03 08:03:50 +00:00
Add multi-expansion support with data-driven protocol layer
Replace hardcoded WotLK protocol constants with a data-driven architecture supporting Classic 1.12.1, TBC 2.4.3, and WotLK 3.3.5a. Each expansion has JSON profiles for opcodes, update fields, and DBC layouts, plus C++ polymorphic packet parsers for binary format differences (movement flags, speed fields, transport data, spline format, char enum layout). Key components: - ExpansionRegistry: scans Data/expansions/*/expansion.json at startup - OpcodeTable: logical enum <-> wire values loaded from JSON - UpdateFieldTable: field indices loaded from JSON per expansion - DBCLayout: schema-driven DBC field lookups replacing magic numbers - PacketParsers: WotLK/TBC/Classic parsers with correct flag positions - Multi-manifest AssetManager: layered manifests with priority ordering - HDPackManager: overlay texture packs with expansion compatibility - Auth screen expansion picker replacing hardcoded version dropdown
This commit is contained in:
parent
4b24736113
commit
90a1aa8a92
51 changed files with 5258 additions and 887 deletions
|
|
@ -6,6 +6,7 @@
|
|||
#include "pipeline/loose_file_reader.hpp"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
|
||||
|
|
@ -16,6 +17,8 @@ namespace pipeline {
|
|||
* AssetManager - Unified interface for loading WoW assets
|
||||
*
|
||||
* Reads pre-extracted loose files indexed by manifest.json.
|
||||
* Supports layered manifests: overlay manifests (HD packs, mods)
|
||||
* are checked before the base manifest, with higher priority first.
|
||||
* Use the asset_extract tool to extract MPQ archives first.
|
||||
* All reads are fully parallel (no serialization mutex needed).
|
||||
*/
|
||||
|
|
@ -41,6 +44,26 @@ public:
|
|||
*/
|
||||
bool isInitialized() const { return initialized; }
|
||||
|
||||
/**
|
||||
* Add an overlay manifest (HD packs, mods) checked before the base manifest.
|
||||
* Higher priority overlays are checked first.
|
||||
* @param manifestPath Full path to the overlay's manifest.json
|
||||
* @param priority Priority level (higher = checked first)
|
||||
* @param id Unique identifier for this overlay (e.g. "hd_character")
|
||||
* @return true if overlay loaded successfully
|
||||
*/
|
||||
bool addOverlayManifest(const std::string& manifestPath, int priority, const std::string& id);
|
||||
|
||||
/**
|
||||
* Remove a previously added overlay manifest by id.
|
||||
*/
|
||||
void removeOverlay(const std::string& id);
|
||||
|
||||
/**
|
||||
* Get list of active overlay IDs.
|
||||
*/
|
||||
std::vector<std::string> getOverlayIds() const;
|
||||
|
||||
/**
|
||||
* Load a BLP texture
|
||||
* @param path Virtual path to BLP file (e.g., "Textures\\Minimap\\Background.blp")
|
||||
|
|
@ -105,10 +128,24 @@ private:
|
|||
bool initialized = false;
|
||||
std::string dataPath;
|
||||
|
||||
// Loose file backend
|
||||
// Base manifest (loaded from dataPath/manifest.json)
|
||||
AssetManifest manifest_;
|
||||
LooseFileReader looseReader_;
|
||||
|
||||
// Overlay manifests (HD packs, mods) - sorted by priority descending
|
||||
struct ManifestLayer {
|
||||
AssetManifest manifest;
|
||||
int priority;
|
||||
std::string id;
|
||||
};
|
||||
std::vector<ManifestLayer> overlayLayers_; // Sorted by priority desc
|
||||
|
||||
/**
|
||||
* Resolve filesystem path checking overlays first, then base manifest.
|
||||
* Returns empty string if not found in any layer.
|
||||
*/
|
||||
std::string resolveLayeredPath(const std::string& normalizedPath) const;
|
||||
|
||||
mutable std::mutex cacheMutex;
|
||||
std::map<std::string, std::shared_ptr<DBCFile>> dbcCache;
|
||||
|
||||
|
|
|
|||
64
include/pipeline/dbc_layout.hpp
Normal file
64
include/pipeline/dbc_layout.hpp
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace wowee {
|
||||
namespace pipeline {
|
||||
|
||||
/**
|
||||
* Maps DBC field names to column indices for a single DBC file.
|
||||
* Column indices vary between WoW expansions.
|
||||
*/
|
||||
struct DBCFieldMap {
|
||||
std::unordered_map<std::string, uint32_t> fields;
|
||||
|
||||
/** Get column index by field name. Returns 0xFFFFFFFF if unknown. */
|
||||
uint32_t field(const std::string& name) const {
|
||||
auto it = fields.find(name);
|
||||
return (it != fields.end()) ? it->second : 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/** Convenience operator for shorter syntax: layout["Name"] */
|
||||
uint32_t operator[](const std::string& name) const { return field(name); }
|
||||
};
|
||||
|
||||
/**
|
||||
* Maps DBC file names to their field layouts.
|
||||
* Loaded from JSON (e.g. Data/expansions/wotlk/dbc_layouts.json).
|
||||
*/
|
||||
class DBCLayout {
|
||||
public:
|
||||
/** Load from JSON file. Returns true if successful. */
|
||||
bool loadFromJson(const std::string& path);
|
||||
|
||||
/** Load built-in WotLK 3.3.5a defaults. */
|
||||
void loadWotlkDefaults();
|
||||
|
||||
/** Get the field map for a DBC file. Returns nullptr if unknown. */
|
||||
const DBCFieldMap* getLayout(const std::string& dbcName) const;
|
||||
|
||||
/** Number of DBC layouts loaded. */
|
||||
size_t size() const { return layouts_.size(); }
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, DBCFieldMap> layouts_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Global active DBC layout (set by Application at startup).
|
||||
*/
|
||||
void setActiveDBCLayout(const DBCLayout* layout);
|
||||
const DBCLayout* getActiveDBCLayout();
|
||||
|
||||
/** Convenience: get field index for a DBC field. */
|
||||
inline uint32_t dbcField(const std::string& dbcName, const std::string& fieldName) {
|
||||
const auto* l = getActiveDBCLayout();
|
||||
if (!l) return 0xFFFFFFFF;
|
||||
const auto* fm = l->getLayout(dbcName);
|
||||
return fm ? fm->field(fieldName) : 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
} // namespace pipeline
|
||||
} // namespace wowee
|
||||
97
include/pipeline/hd_pack_manager.hpp
Normal file
97
include/pipeline/hd_pack_manager.hpp
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace wowee {
|
||||
namespace pipeline {
|
||||
|
||||
class AssetManager;
|
||||
|
||||
/**
|
||||
* Metadata for a single HD texture pack on disk.
|
||||
*
|
||||
* Each pack lives in Data/hd/<packDir>/ and contains:
|
||||
* pack.json - metadata (id, name, group, compatible expansions, size)
|
||||
* manifest.json - standard asset manifest with HD override textures
|
||||
* assets/ - the actual HD files
|
||||
*/
|
||||
struct HDPack {
|
||||
std::string id; // Unique identifier (e.g. "character_hd")
|
||||
std::string name; // Human-readable name
|
||||
std::string group; // Grouping label (e.g. "Character", "Terrain")
|
||||
std::vector<std::string> expansions; // Compatible expansion IDs
|
||||
uint32_t totalSizeMB = 0; // Approximate total size on disk
|
||||
std::string manifestPath; // Full path to manifest.json
|
||||
std::string packDir; // Full path to pack directory
|
||||
bool enabled = false; // User-toggled enable state
|
||||
};
|
||||
|
||||
/**
|
||||
* HDPackManager - discovers, manages, and wires HD texture packs.
|
||||
*
|
||||
* Scans Data/hd/ subdirectories for pack.json files. Each pack can be
|
||||
* enabled/disabled via setPackEnabled(). Enabled packs are wired into
|
||||
* AssetManager as high-priority overlay manifests so that HD textures
|
||||
* override the base expansion assets transparently.
|
||||
*/
|
||||
class HDPackManager {
|
||||
public:
|
||||
HDPackManager() = default;
|
||||
|
||||
/**
|
||||
* Scan the HD root directory for available packs.
|
||||
* @param hdRootPath Path to Data/hd/ directory
|
||||
*/
|
||||
void initialize(const std::string& hdRootPath);
|
||||
|
||||
/**
|
||||
* Get all discovered packs.
|
||||
*/
|
||||
const std::vector<HDPack>& getAllPacks() const { return packs_; }
|
||||
|
||||
/**
|
||||
* Get packs compatible with a specific expansion.
|
||||
*/
|
||||
std::vector<const HDPack*> getPacksForExpansion(const std::string& expansionId) const;
|
||||
|
||||
/**
|
||||
* Enable or disable a pack. Persists state in enabledPacks_ map.
|
||||
*/
|
||||
void setPackEnabled(const std::string& packId, bool enabled);
|
||||
|
||||
/**
|
||||
* Check if a pack is enabled.
|
||||
*/
|
||||
bool isPackEnabled(const std::string& packId) const;
|
||||
|
||||
/**
|
||||
* Apply enabled packs as overlays to the asset manager.
|
||||
* Removes previously applied overlays and re-adds enabled ones.
|
||||
*/
|
||||
void applyToAssetManager(AssetManager* assetManager, const std::string& expansionId);
|
||||
|
||||
/**
|
||||
* Save enabled pack state to a settings file.
|
||||
*/
|
||||
void saveSettings(const std::string& settingsPath) const;
|
||||
|
||||
/**
|
||||
* Load enabled pack state from a settings file.
|
||||
*/
|
||||
void loadSettings(const std::string& settingsPath);
|
||||
|
||||
private:
|
||||
std::vector<HDPack> packs_;
|
||||
std::unordered_map<std::string, bool> enabledState_; // packId → enabled
|
||||
|
||||
// Overlay IDs currently applied to AssetManager (for removal on re-apply)
|
||||
std::vector<std::string> appliedOverlayIds_;
|
||||
|
||||
static constexpr int HD_OVERLAY_PRIORITY_BASE = 100; // High priority, above expansion base
|
||||
};
|
||||
|
||||
} // namespace pipeline
|
||||
} // namespace wowee
|
||||
Loading…
Add table
Add a link
Reference in a new issue