C++ library for reading "World of Warcraft" database files.
- Reads DBC and DB2 Files.
- Accepts multiple filesystems (MPQ, CASC, + more)
- Usable with WOWDBDefs
- Record structure determined at compile time or runtime.
Currently only tested with client versions: 1.12, 2.4, 3.3, 4.3, 8.3, 10.2 & 11.0
However should be able to work with any using WDBC, WDB2, WDC3, WDC4 or WDC5 formats.
- Build with CMake
- Optionally use
vcpkg - Optionally link to StormLib & CascLib
Available filesystems / sources:
class NativeFileSystem; // native file system access.
class MemoryFileSource; // direct memory source.
class CASCFilesystem; // CASC
class MPQFilesystem; // MPQ
auto filesystem = FilesystemType(...);
auto source = filesystem.open(name);DBC file reading:
//depending on RecordType, a third param 'locale' may be needed.
auto dbc = DBCFile<SchemaType, RecordType, FileSourceType>(Schema, DBCVersion);
//shorthand helpers
auto dbc = makeDBCFile<SourceType>(RuntimeSchema, DBCVersion, DBCLocale);
auto dbc = makeDBCFile<StaticRecordType, FileSourceType>(DBCVersion);DB2 file read:
//Single format DB2 loader
auto db2 = DB2File<DB2Format, SchemaType, RecordType, FileSourceType>(Schema);
//shorthand helpers (accepts multiple db2 formats, open and load get automatically called.)
auto db2 = makeDB2File<SchemaType, RecordType, FileSourceType>(Schema, Source);
auto db2 = makeDB2File(RuntimeSchema, Source);
auto db2 = makeDB2File<StaticRecordType>(Source);DB usage (applies to both DBC & DB2):
auto db = ...;
db.open(source);
db.load();
// ...
db.size();
db.format(); //signature & hashes.
auto record = db[record_index];
for(const auto& rec : db) {
if(rec.encryptionState != RecordEncryption::ENCRYPTED) {
// rec.data safe.
} else {
// rec.data unsafe.
}
}Fixed DB records (compile time):
struct RecordType : public FixedRecord<RecordType> {
struct Data {
//...
} data;
size_t recordIndex;
RecordEncryption encryptionState;
constexpr static Schema schema = Schema(
//...
);
};
RecordType rec = db[index];
rec.recordIndex;
rec.encryptionState;
rec.data.{field_name};Runtime DB records (run time):
class RuntimeRecord;
class RuntimeSchema;
RuntimeSchema schema = ...;
RuntimeRecord rec = db[index];
rec.recordIndex;
rec.encryptionState;
auto accessor = schema(rec);
for(const auto& element : accessor) {
element.name;
element.value;
for(const auto& val : element.value) {
std::visit([](auto v) {
//...
}, val);
}
}
accessor["name"];
auto [val1, val2,...] = accessor.get<T1, T2, T..>("name1", "name2", "name"...);Schema type examples:
// Fixed / static schema (modelfiledata)
constexpr static Schema schema = Schema(
Field::value<decltype(data.fileDataId)>(Annotation().Id()),
Field::value<decltype(data.flags)>(),
Field::value<decltype(data.loadCount)>(),
Field::value<decltype(data.modelResourcesId)>(Annotation().Relation())
);
// Runtime schema (guildtabardemblem)
RuntimeSchema({
Field::value<uint32_t>(Annotation().Id().NonInline()),
Field::value<uint32_t>(),
Field::value<uint32_t>(),
Field::value<uint32_t>(),
Field::value<uint32_t>(Annotation().Relation().NonInline())
},{
"id",
"component",
"color",
"fileDataId",
"emblemId"
})Record structures can be created at runtime with .dbd files. See the demo app:
demo.exe {wow_dir} {db_file_uri} {dbd_defs_name}Specifically:
auto definition = DBDReader::read(stream);
auto schema = makeSchema(definition, client.version);Records and schema structures can be created with schema_gen, this creates C++ classes in the format expected for WDBReader fixed records. Usage as:
schema_gen.exe {version} {db_defs_name} {db_format} {output_path}Detect installed client info for a specific path using supplied stratagies, built-in strategies include checking the .build.info file and exe file attributes.
auto detected = Detector::all().detect(path);
detected.size();
detected[0].name;
detected[0].locale;
detected[0].version;