mirror of
https://github.com/thunderbrewhq/thunderbrew
synced 2025-04-16 10:04:42 +03:00
feat(db): load achievement db
This commit is contained in:
parent
1575f6d83c
commit
c00028c214
@ -1,6 +1,7 @@
|
||||
add_subdirectory(app)
|
||||
add_subdirectory(async)
|
||||
add_subdirectory(client)
|
||||
add_subdirectory(db)
|
||||
add_subdirectory(event)
|
||||
add_subdirectory(glue)
|
||||
add_subdirectory(gx)
|
||||
|
@ -12,6 +12,7 @@ target_include_directories(client
|
||||
target_link_libraries(client
|
||||
PRIVATE
|
||||
async
|
||||
db
|
||||
event
|
||||
gx
|
||||
model
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "client/Client.hpp"
|
||||
#include "client/ClientServices.hpp"
|
||||
#include "client/Console.hpp"
|
||||
#include "db/Db.hpp"
|
||||
#include "async/AsyncFile.hpp"
|
||||
#include "glue/CGlueMgr.hpp"
|
||||
#include "gx/Device.hpp"
|
||||
@ -353,7 +354,9 @@ void WowClientInit() {
|
||||
ClientMiscInitialize();
|
||||
|
||||
// sub_401B60();
|
||||
// ClientDBInitialize();
|
||||
|
||||
ClientDBInitialize();
|
||||
|
||||
// LoadingScreenInitialize();
|
||||
|
||||
FrameScript_Initialize(0);
|
||||
|
16
src/db/CMakeLists.txt
Normal file
16
src/db/CMakeLists.txt
Normal file
@ -0,0 +1,16 @@
|
||||
file(GLOB PRIVATE_SOURCES "*.cpp" "rec/*.cpp")
|
||||
|
||||
add_library(db STATIC
|
||||
${PRIVATE_SOURCES}
|
||||
)
|
||||
|
||||
target_include_directories(db
|
||||
PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
target_link_libraries(db
|
||||
PUBLIC
|
||||
common
|
||||
storm
|
||||
)
|
20
src/db/Db.cpp
Normal file
20
src/db/Db.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
#include "db/Db.hpp"
|
||||
#include "db/WowClientDB_Base.hpp"
|
||||
|
||||
WowClientDB<AchievementRec> g_achievementDB;
|
||||
|
||||
void LoadDB(WowClientDB_Base* db, const char* filename, int32_t linenumber) {
|
||||
db->Load(filename, linenumber);
|
||||
};
|
||||
|
||||
void StaticDBLoadAll(void (*loadFn)(WowClientDB_Base*, const char*, int32_t)) {
|
||||
loadFn(&g_achievementDB, __FILE__, __LINE__);
|
||||
};
|
||||
|
||||
void ClientDBInitialize() {
|
||||
// TODO
|
||||
|
||||
StaticDBLoadAll(LoadDB);
|
||||
|
||||
// TODO
|
||||
}
|
11
src/db/Db.hpp
Normal file
11
src/db/Db.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef DB_DB_HPP
|
||||
#define DB_DB_HPP
|
||||
|
||||
#include "db/rec/AchievementRec.hpp"
|
||||
#include "db/WowClientDB.hpp"
|
||||
|
||||
extern WowClientDB<AchievementRec> g_achievementDB;
|
||||
|
||||
void ClientDBInitialize();
|
||||
|
||||
#endif
|
15
src/db/IDatabase.hpp
Normal file
15
src/db/IDatabase.hpp
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef DB_I_DATABASE_HPP
|
||||
#define DB_I_DATABASE_HPP
|
||||
|
||||
template <class T>
|
||||
class IDatabase {
|
||||
public:
|
||||
// Member variables
|
||||
T* m_records = nullptr;
|
||||
T** m_recordsById = nullptr;
|
||||
|
||||
// Virtual member functions
|
||||
virtual T* GetRecord(int32_t id) = 0;
|
||||
};
|
||||
|
||||
#endif
|
157
src/db/WowClientDB.hpp
Normal file
157
src/db/WowClientDB.hpp
Normal file
@ -0,0 +1,157 @@
|
||||
#ifndef DB_WOW_CLIENT_DB_HPP
|
||||
#define DB_WOW_CLIENT_DB_HPP
|
||||
|
||||
#include "db/IDatabase.hpp"
|
||||
#include "db/WowClientDB_Common.hpp"
|
||||
#include <cstring>
|
||||
#include <storm/Error.hpp>
|
||||
#include <storm/Memory.hpp>
|
||||
|
||||
template <class T>
|
||||
class WowClientDB : public WowClientDB_Common<T>, IDatabase<T> {
|
||||
public:
|
||||
// Virtual member functions
|
||||
virtual void Load(const char* filename, int32_t linenumber);
|
||||
virtual void LoadRecords(SFile* f, const char* filename, int32_t linenumber);
|
||||
virtual int32_t GetRecordByIndex(int32_t index, void* ptr) const;
|
||||
virtual T* GetRecord(int32_t id);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
int32_t WowClientDB<T>::GetRecordByIndex(int32_t index, void* ptr) const {
|
||||
STORM_ASSERT(this->m_numRecords >= 0);
|
||||
|
||||
if (index < 0 || index >= this->m_numRecords) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(ptr, &this->m_records[index], sizeof(T));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T* WowClientDB<T>::GetRecord(int32_t id) {
|
||||
STORM_ASSERT(this->m_numRecords >= 0);
|
||||
|
||||
if (id < this->m_minID || id > this->m_maxID) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return this->m_recordsById[id - this->m_minID];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void WowClientDB<T>::Load(const char* filename, int32_t linenumber) {
|
||||
if (this->m_loaded) {
|
||||
// TODO
|
||||
// SErrDisplayAppFatalCustom(0x85100079, "%s already loaded! Aborting to prevent memory leak!", T::GetFilename());
|
||||
return;
|
||||
}
|
||||
|
||||
SFile* f;
|
||||
if (!SFile::OpenEx(nullptr, T::GetFilename(), 0x20000, &f)) {
|
||||
// TODO
|
||||
// SErrDisplayAppFatalCustom(0x85100079, "Unable to open %s", T::GetFilename());
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t signature;
|
||||
if (!SFile::Read(f, &signature, sizeof(signature), nullptr, nullptr, nullptr)) {
|
||||
// TODO
|
||||
// SErrDisplayAppFatalCustom(0x85100079, "Unable to read signature from %s", T::GetFilename());
|
||||
return;
|
||||
}
|
||||
|
||||
if (signature != 'CBDW') {
|
||||
// TODO
|
||||
// SErrDisplayAppFatalCustom(0x85100079, "Invalid signature 0x%x from %s", signature, T::GetFilename());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SFile::Read(f, &this->m_numRecords, sizeof(this->m_numRecords), nullptr, nullptr, nullptr)) {
|
||||
// TODO
|
||||
// SErrDisplayAppFatalCustom(0x85100079, "Unable to read record count from %s", T::GetFilename());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->m_numRecords) {
|
||||
SFile::Close(f);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t columnCount;
|
||||
if (!SFile::Read(f, &columnCount, sizeof(columnCount), nullptr, nullptr, nullptr)) {
|
||||
// TODO
|
||||
// SErrDisplayAppFatalCustom(0x85100079, "Unable to read column count from %s", T::GetFilename());
|
||||
return;
|
||||
}
|
||||
|
||||
if (columnCount != T::columnCount) {
|
||||
// TODO
|
||||
// SErrDisplayAppFatalCustom(0x85100079, "%s has wrong number of columns (found %i, expected %i)", T::GetFilename(), columnCount, T::columnCount);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t rowSize;
|
||||
if (!SFile::Read(f, &rowSize, sizeof(rowSize), nullptr, nullptr, nullptr)) {
|
||||
// TODO
|
||||
// SErrDisplayAppFatalCustom(0x85100079, "Unable to read row size from %s", T::GetFilename());
|
||||
return;
|
||||
}
|
||||
|
||||
if (rowSize != T::rowSize) {
|
||||
// TODO
|
||||
// SErrDisplayAppFatalCustom(0x85100079, "%s has wrong row size (found %i, expected %i)", T::GetFilename(), rowSize, T::rowSize);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t stringSize;
|
||||
if (!SFile::Read(f, &stringSize, sizeof(stringSize), nullptr, nullptr, nullptr)) {
|
||||
// TODO
|
||||
// SErrDisplayAppFatalCustom(0x85100079, "Unable to read string size from %s", T::GetFilename());
|
||||
return;
|
||||
}
|
||||
|
||||
auto stringBuffer = SMemAlloc(stringSize, filename, linenumber, 0x0);
|
||||
this->m_strings = static_cast<const char*>(stringBuffer);
|
||||
|
||||
this->m_maxID = 0;
|
||||
this->m_minID = 0xFFFFFFF;
|
||||
|
||||
this->LoadRecords(f, filename, linenumber);
|
||||
|
||||
if (!SFile::Read(f, const_cast<char*>(this->m_strings), stringSize, nullptr, nullptr, nullptr)) {
|
||||
SErrDisplayAppFatal("%s: Cannot read string table", T::GetFilename());
|
||||
}
|
||||
|
||||
SFile::Close(f);
|
||||
|
||||
this->m_loaded = 1;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void WowClientDB<T>::LoadRecords(SFile* f, const char* filename, int32_t linenumber) {
|
||||
auto records = SMemAlloc(sizeof(T) * this->m_numRecords, filename, linenumber, 0x0);
|
||||
this->m_records = static_cast<T*>(records);
|
||||
|
||||
for (uint32_t i = 0; i < this->m_numRecords; i++) {
|
||||
auto record = &this->m_records[i];
|
||||
record->Read(f, this->m_strings);
|
||||
|
||||
this->m_maxID = record->m_ID > this->m_maxID ? record->m_ID : this->m_maxID;
|
||||
this->m_minID = record->m_ID < this->m_minID ? record->m_ID : this->m_minID;
|
||||
}
|
||||
|
||||
auto recordsById = SMemAlloc(sizeof(void*) * (this->m_maxID - this->m_minID + 1), __FILE__, __LINE__, 0x0);
|
||||
memset(recordsById, 0, sizeof(void*) * (this->m_maxID - this->m_minID + 1));
|
||||
this->m_recordsById = static_cast<T**>(recordsById);
|
||||
|
||||
for (uint32_t i = 0; i < this->m_numRecords; i++) {
|
||||
auto record = &this->m_records[i];
|
||||
auto id = record->m_ID - this->m_minID;
|
||||
this->m_recordsById[id] = record;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
22
src/db/WowClientDB_Base.hpp
Normal file
22
src/db/WowClientDB_Base.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef DB_WOW_CLIENT_DB_BASE_HPP
|
||||
#define DB_WOW_CLIENT_DB_BASE_HPP
|
||||
|
||||
#include "util/SFile.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
class WowClientDB_Base {
|
||||
public:
|
||||
// Member variables
|
||||
int32_t m_loaded = 0;
|
||||
int32_t m_numRecords = 0;
|
||||
int32_t m_maxID = -1;
|
||||
int32_t m_minID = 0xFFFFFFF;
|
||||
const char* m_strings = nullptr;
|
||||
|
||||
// Virtual member functions
|
||||
virtual void Load(const char* filename, int32_t linenumber) = 0;
|
||||
virtual void LoadRecords(SFile* f, const char* filename, int32_t linenumber) = 0;
|
||||
virtual int32_t GetRecordByIndex(int32_t index, void* ptr) const = 0;
|
||||
};
|
||||
|
||||
#endif
|
11
src/db/WowClientDB_Common.hpp
Normal file
11
src/db/WowClientDB_Common.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef DB_WOW_CLIENT_DB_COMMON_HPP
|
||||
#define DB_WOW_CLIENT_DB_COMMON_HPP
|
||||
|
||||
#include "db/WowClientDB_Base.hpp"
|
||||
|
||||
template <class T>
|
||||
class WowClientDB_Common : public WowClientDB_Base {
|
||||
public:
|
||||
};
|
||||
|
||||
#endif
|
94
src/db/rec/AchievementRec.cpp
Normal file
94
src/db/rec/AchievementRec.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
#include "db/rec/AchievementRec.hpp"
|
||||
#include "util/SFile.hpp"
|
||||
|
||||
const char* AchievementRec::GetFilename() {
|
||||
return "DBFilesClient\\Achievement.dbc";
|
||||
}
|
||||
|
||||
bool AchievementRec::Read(SFile* f, const char* stringBuffer) {
|
||||
uint32_t titleOfs[16];
|
||||
uint32_t titleMask;
|
||||
uint32_t descriptionOfs[16];
|
||||
uint32_t descriptionMask;
|
||||
uint32_t rewardOfs[16];
|
||||
uint32_t rewardMask;
|
||||
|
||||
if (
|
||||
!SFile::Read(f, &this->m_ID, sizeof(this->m_ID), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &this->m_faction, sizeof(this->m_faction), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &this->m_instanceID, sizeof(this->m_instanceID), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &this->m_supercedes, sizeof(this->m_supercedes), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &titleOfs[0], sizeof(titleOfs[0]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &titleOfs[1], sizeof(titleOfs[1]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &titleOfs[2], sizeof(titleOfs[2]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &titleOfs[3], sizeof(titleOfs[3]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &titleOfs[4], sizeof(titleOfs[4]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &titleOfs[5], sizeof(titleOfs[5]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &titleOfs[6], sizeof(titleOfs[6]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &titleOfs[7], sizeof(titleOfs[7]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &titleOfs[8], sizeof(titleOfs[8]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &titleOfs[9], sizeof(titleOfs[9]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &titleOfs[10], sizeof(titleOfs[10]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &titleOfs[11], sizeof(titleOfs[11]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &titleOfs[12], sizeof(titleOfs[12]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &titleOfs[13], sizeof(titleOfs[13]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &titleOfs[14], sizeof(titleOfs[14]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &titleOfs[15], sizeof(titleOfs[15]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &titleMask, sizeof(titleMask), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &descriptionOfs[0], sizeof(descriptionOfs[0]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &descriptionOfs[1], sizeof(descriptionOfs[1]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &descriptionOfs[2], sizeof(descriptionOfs[2]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &descriptionOfs[3], sizeof(descriptionOfs[3]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &descriptionOfs[4], sizeof(descriptionOfs[4]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &descriptionOfs[5], sizeof(descriptionOfs[5]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &descriptionOfs[6], sizeof(descriptionOfs[6]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &descriptionOfs[7], sizeof(descriptionOfs[7]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &descriptionOfs[8], sizeof(descriptionOfs[8]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &descriptionOfs[9], sizeof(descriptionOfs[9]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &descriptionOfs[10], sizeof(descriptionOfs[10]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &descriptionOfs[11], sizeof(descriptionOfs[11]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &descriptionOfs[12], sizeof(descriptionOfs[12]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &descriptionOfs[13], sizeof(descriptionOfs[13]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &descriptionOfs[14], sizeof(descriptionOfs[14]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &descriptionOfs[15], sizeof(descriptionOfs[15]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &descriptionMask, sizeof(descriptionMask), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &this->m_category, sizeof(this->m_category), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &this->m_points, sizeof(this->m_points), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &this->m_uiOrder, sizeof(this->m_uiOrder), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &this->m_flags, sizeof(this->m_flags), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &this->m_iconID, sizeof(this->m_iconID), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &rewardOfs[0], sizeof(rewardOfs[0]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &rewardOfs[1], sizeof(rewardOfs[1]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &rewardOfs[2], sizeof(rewardOfs[2]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &rewardOfs[3], sizeof(rewardOfs[3]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &rewardOfs[4], sizeof(rewardOfs[4]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &rewardOfs[5], sizeof(rewardOfs[5]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &rewardOfs[6], sizeof(rewardOfs[6]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &rewardOfs[7], sizeof(rewardOfs[7]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &rewardOfs[8], sizeof(rewardOfs[8]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &rewardOfs[9], sizeof(rewardOfs[9]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &rewardOfs[10], sizeof(rewardOfs[10]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &rewardOfs[11], sizeof(rewardOfs[11]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &rewardOfs[12], sizeof(rewardOfs[12]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &rewardOfs[13], sizeof(rewardOfs[13]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &rewardOfs[14], sizeof(rewardOfs[14]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &rewardOfs[15], sizeof(rewardOfs[15]), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &rewardMask, sizeof(rewardMask), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &this->m_minimumCriteria, sizeof(this->m_minimumCriteria), nullptr, nullptr, nullptr)
|
||||
|| !SFile::Read(f, &this->m_sharesCriteria, sizeof(this->m_sharesCriteria), nullptr, nullptr, nullptr)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stringBuffer) {
|
||||
this->m_title = &stringBuffer[titleOfs[0]];
|
||||
this->m_description = &stringBuffer[descriptionOfs[0]];
|
||||
this->m_reward = &stringBuffer[rewardOfs[0]];
|
||||
} else {
|
||||
this->m_title = "";
|
||||
this->m_description = "";
|
||||
this->m_reward = "";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
32
src/db/rec/AchievementRec.hpp
Normal file
32
src/db/rec/AchievementRec.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef DB_REC_ACHIEVEMENT_REC_HPP
|
||||
#define DB_REC_ACHIEVEMENT_REC_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class SFile;
|
||||
|
||||
class AchievementRec {
|
||||
public:
|
||||
static constexpr uint32_t columnCount = 62;
|
||||
static constexpr uint32_t rowSize = 248;
|
||||
|
||||
int32_t m_ID;
|
||||
int32_t m_faction;
|
||||
int32_t m_instanceID;
|
||||
int32_t m_supercedes;
|
||||
const char* m_title;
|
||||
const char* m_description;
|
||||
int32_t m_category;
|
||||
int32_t m_points;
|
||||
int32_t m_uiOrder;
|
||||
int32_t m_flags;
|
||||
uint32_t m_iconID;
|
||||
const char* m_reward;
|
||||
int32_t m_minimumCriteria;
|
||||
int32_t m_sharesCriteria;
|
||||
|
||||
static const char* GetFilename();
|
||||
bool Read(SFile* f, const char* stringBuffer);
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user