mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
Core/DataStores: Implement optional data in hotfix packets
Closes #25738
This commit is contained in:
15
sql/updates/hotfixes/master/2020_12_20_00_hotfixes.sql
Normal file
15
sql/updates/hotfixes/master/2020_12_20_00_hotfixes.sql
Normal file
@@ -0,0 +1,15 @@
|
||||
--
|
||||
-- Table structure for table `hotfix_optional_data`
|
||||
--
|
||||
DROP TABLE IF EXISTS `hotfix_optional_data`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!50503 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `hotfix_optional_data` (
|
||||
`TableHash` int(10) unsigned NOT NULL,
|
||||
`RecordId` int(10) unsigned NOT NULL,
|
||||
`locale` varchar(4) NOT NULL,
|
||||
`Key` int(10) unsigned NOT NULL,
|
||||
`Data` blob NOT NULL,
|
||||
`VerifiedBuild` int(11) NOT NULL DEFAULT '0'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
@@ -361,6 +361,7 @@ typedef std::tuple<uint16, uint8, int32> WMOAreaTableKey;
|
||||
typedef std::map<WMOAreaTableKey, WMOAreaTableEntry const*> WMOAreaTableLookupContainer;
|
||||
typedef std::pair<uint32 /*tableHash*/, int32 /*recordId*/> HotfixBlobKey;
|
||||
typedef std::map<HotfixBlobKey, std::vector<uint8>> HotfixBlobMap;
|
||||
using AllowedHotfixOptionalData = std::pair<uint32 /*optional data key*/, bool(*)(std::vector<uint8> const& data) /*validator*/>;
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -375,6 +376,8 @@ namespace
|
||||
StorageMap _stores;
|
||||
DB2Manager::HotfixContainer _hotfixData;
|
||||
std::array<HotfixBlobMap, TOTAL_LOCALES> _hotfixBlob;
|
||||
std::unordered_multimap<uint32 /*tableHash*/, AllowedHotfixOptionalData> _allowedHotfixOptionalData;
|
||||
std::array<std::map<HotfixBlobKey, std::vector<DB2Manager::HotfixOptionalData>>, TOTAL_LOCALES> _hotfixOptionalData;
|
||||
|
||||
AreaGroupMemberContainer _areaGroupMembers;
|
||||
ArtifactPowersContainer _artifactPowers;
|
||||
@@ -1513,7 +1516,7 @@ void DB2Manager::LoadHotfixBlob(uint32 localeMask)
|
||||
auto storeItr = _stores.find(tableHash);
|
||||
if (storeItr != _stores.end())
|
||||
{
|
||||
TC_LOG_ERROR("server.loading", "Table hash 0x%X points to a loaded DB2 store %s, fill related table instead of hotfix_blob",
|
||||
TC_LOG_ERROR("sql.sql", "Table hash 0x%X points to a loaded DB2 store %s, fill related table instead of hotfix_blob",
|
||||
tableHash, storeItr->second->GetFileName().c_str());
|
||||
continue;
|
||||
}
|
||||
@@ -1524,7 +1527,7 @@ void DB2Manager::LoadHotfixBlob(uint32 localeMask)
|
||||
|
||||
if (!IsValidLocale(locale))
|
||||
{
|
||||
TC_LOG_ERROR("server.loading", "`hotfix_blob` contains invalid locale: %s at TableHash: 0x%X and RecordID: %d", localeName.c_str(), tableHash, recordId);
|
||||
TC_LOG_ERROR("sql.sql", "`hotfix_blob` contains invalid locale: %s at TableHash: 0x%X and RecordID: %d", localeName.c_str(), tableHash, recordId);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1538,6 +1541,88 @@ void DB2Manager::LoadHotfixBlob(uint32 localeMask)
|
||||
TC_LOG_INFO("server.loading", ">> Loaded %d hotfix blob records in %u ms", hotfixBlobCount, GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
bool ValidateBroadcastTextTactKeyOptionalData(std::vector<uint8> const& data)
|
||||
{
|
||||
return data.size() == 8 + 16;
|
||||
}
|
||||
|
||||
void DB2Manager::LoadHotfixOptionalData(uint32 localeMask)
|
||||
{
|
||||
// Register allowed optional data keys
|
||||
_allowedHotfixOptionalData.emplace(sBroadcastTextStore.GetTableHash(), std::make_pair(sTactKeyStore.GetTableHash(), &ValidateBroadcastTextTactKeyOptionalData));
|
||||
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
QueryResult result = HotfixDatabase.Query("SELECT TableHash, RecordId, locale, `Key`, `Data` FROM hotfix_optional_data ORDER BY TableHash");
|
||||
|
||||
if (!result)
|
||||
{
|
||||
TC_LOG_INFO("server.loading", ">> Loaded 0 hotfix optional data records.");
|
||||
return;
|
||||
}
|
||||
|
||||
std::bitset<TOTAL_LOCALES> availableDb2Locales = localeMask;
|
||||
uint32 hotfixOptionalDataCount = 0;
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
uint32 tableHash = fields[0].GetUInt32();
|
||||
auto allowedHotfixes = Trinity::Containers::MapEqualRange(_allowedHotfixOptionalData, tableHash);
|
||||
if (allowedHotfixes.begin() == allowedHotfixes.end())
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Table `hotfix_optional_data` references DB2 store by hash 0x%X that is not allowed to have optional data", tableHash);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32 recordId = fields[1].GetInt32();
|
||||
auto storeItr = _stores.find(tableHash);
|
||||
if (storeItr == _stores.end())
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Table `hotfix_optional_data` references unknown DB2 store by hash 0x%X with RecordID: %u", tableHash, recordId);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string localeName = fields[2].GetString();
|
||||
LocaleConstant locale = GetLocaleByName(localeName);
|
||||
|
||||
if (!IsValidLocale(locale))
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "`hotfix_optional_data` contains invalid locale: %s at TableHash: 0x%X and RecordID: %u", localeName.c_str(), tableHash, recordId);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!availableDb2Locales[locale])
|
||||
continue;
|
||||
|
||||
DB2Manager::HotfixOptionalData optionalData;
|
||||
optionalData.Key = fields[3].GetUInt32();
|
||||
auto allowedHotfixItr = std::find_if(allowedHotfixes.begin(), allowedHotfixes.end(), [&](std::pair<uint32 const, AllowedHotfixOptionalData> const& v)
|
||||
{
|
||||
return v.second.first == optionalData.Key;
|
||||
});
|
||||
if (allowedHotfixItr == allowedHotfixes.end())
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Table `hotfix_optional_data` references non-allowed optional data key 0x%X for DB2 store by hash 0x%X and RecordID: %u",
|
||||
optionalData.Key, tableHash, recordId);
|
||||
continue;
|
||||
}
|
||||
|
||||
optionalData.Data = fields[4].GetBinary();
|
||||
if (!allowedHotfixItr->second.second(optionalData.Data))
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Table `hotfix_optional_data` contains invalid data for DB2 store 0x%X, RecordID: %u and Key: 0x%X",
|
||||
tableHash, recordId, optionalData.Key);
|
||||
continue;
|
||||
}
|
||||
|
||||
_hotfixOptionalData[locale][std::make_pair(tableHash, recordId)].push_back(std::move(optionalData));
|
||||
hotfixOptionalDataCount++;
|
||||
} while (result->NextRow());
|
||||
|
||||
TC_LOG_INFO("server.loading", ">> Loaded %d hotfix optional data records in %u ms", hotfixOptionalDataCount, GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
uint32 DB2Manager::GetHotfixCount() const
|
||||
{
|
||||
return _hotfixData.size();
|
||||
@@ -1548,13 +1633,20 @@ DB2Manager::HotfixContainer const& DB2Manager::GetHotfixData() const
|
||||
return _hotfixData;
|
||||
}
|
||||
|
||||
std::vector<uint8> const* DB2Manager::GetHotfixBlobData(uint32 tableHash, int32 recordId, LocaleConstant locale)
|
||||
std::vector<uint8> const* DB2Manager::GetHotfixBlobData(uint32 tableHash, int32 recordId, LocaleConstant locale) const
|
||||
{
|
||||
ASSERT(IsValidLocale(locale), "Locale %u is invalid locale", uint32(locale));
|
||||
|
||||
return Trinity::Containers::MapGetValuePtr(_hotfixBlob[locale], std::make_pair(tableHash, recordId));
|
||||
}
|
||||
|
||||
std::vector<DB2Manager::HotfixOptionalData> const* DB2Manager::GetHotfixOptionalData(uint32 tableHash, int32 recordId, LocaleConstant locale) const
|
||||
{
|
||||
ASSERT(IsValidLocale(locale), "Locale %u is invalid locale", uint32(locale));
|
||||
|
||||
return Trinity::Containers::MapGetValuePtr(_hotfixOptionalData[locale], std::make_pair(tableHash, recordId));
|
||||
}
|
||||
|
||||
uint32 DB2Manager::GetEmptyAnimStateID() const
|
||||
{
|
||||
return sAnimationDataStore.GetNumRows();
|
||||
|
||||
@@ -287,6 +287,12 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct HotfixOptionalData
|
||||
{
|
||||
uint32 Key;
|
||||
std::vector<uint8> Data;
|
||||
};
|
||||
|
||||
using HotfixContainer = std::set<HotfixRecord>;
|
||||
|
||||
using ItemBonusList = std::vector<ItemBonusEntry const*>;
|
||||
@@ -301,9 +307,11 @@ public:
|
||||
|
||||
void LoadHotfixData();
|
||||
void LoadHotfixBlob(uint32 localeMask);
|
||||
void LoadHotfixOptionalData(uint32 localeMask);
|
||||
uint32 GetHotfixCount() const;
|
||||
HotfixContainer const& GetHotfixData() const;
|
||||
std::vector<uint8> const* GetHotfixBlobData(uint32 tableHash, int32 recordId, LocaleConstant locale);
|
||||
std::vector<uint8> const* GetHotfixBlobData(uint32 tableHash, int32 recordId, LocaleConstant locale) const;
|
||||
std::vector<HotfixOptionalData> const* GetHotfixOptionalData(uint32 tableHash, int32 recordId, LocaleConstant locale) const;
|
||||
|
||||
uint32 GetEmptyAnimStateID() const;
|
||||
std::vector<uint32> GetAreasForGroup(uint32 areaGroupId) const;
|
||||
|
||||
@@ -28,23 +28,26 @@
|
||||
void WorldSession::HandleDBQueryBulk(WorldPackets::Hotfix::DBQueryBulk& dbQuery)
|
||||
{
|
||||
DB2StorageBase const* store = sDB2Manager.GetStorage(dbQuery.TableHash);
|
||||
if (!store)
|
||||
{
|
||||
TC_LOG_ERROR("network", "CMSG_DB_QUERY_BULK: %s requested unsupported unknown hotfix type: %u", GetPlayerInfo().c_str(), dbQuery.TableHash);
|
||||
return;
|
||||
}
|
||||
|
||||
for (WorldPackets::Hotfix::DBQueryBulk::DBQueryRecord const& record : dbQuery.Queries)
|
||||
{
|
||||
WorldPackets::Hotfix::DBReply dbReply;
|
||||
dbReply.TableHash = dbQuery.TableHash;
|
||||
dbReply.RecordID = record.RecordID;
|
||||
|
||||
if (store->HasRecord(record.RecordID))
|
||||
if (store && store->HasRecord(record.RecordID))
|
||||
{
|
||||
dbReply.Status = 1;
|
||||
dbReply.Timestamp = GameTime::GetGameTime();
|
||||
store->WriteRecord(record.RecordID, GetSessionDbcLocale(), dbReply.Data);
|
||||
|
||||
if (std::vector<DB2Manager::HotfixOptionalData> const* optionalDataEntries = sDB2Manager.GetHotfixOptionalData(dbQuery.TableHash, record.RecordID, GetSessionDbcLocale()))
|
||||
{
|
||||
for (DB2Manager::HotfixOptionalData const& optionalData : *optionalDataEntries)
|
||||
{
|
||||
dbReply.Data << uint32(optionalData.Key);
|
||||
dbReply.Data.append(optionalData.Data.data(), optionalData.Data.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -78,6 +81,16 @@ void WorldSession::HandleHotfixRequest(WorldPackets::Hotfix::HotfixRequest& hotf
|
||||
{
|
||||
std::size_t pos = hotfixQueryResponse.HotfixContent.size();
|
||||
storage->WriteRecord(uint32(hotfixRecord.RecordID), GetSessionDbcLocale(), hotfixQueryResponse.HotfixContent);
|
||||
|
||||
if (std::vector<DB2Manager::HotfixOptionalData> const* optionalDataEntries = sDB2Manager.GetHotfixOptionalData(hotfixRecord.TableHash, hotfixRecord.RecordID, GetSessionDbcLocale()))
|
||||
{
|
||||
for (DB2Manager::HotfixOptionalData const& optionalData : *optionalDataEntries)
|
||||
{
|
||||
hotfixQueryResponse.HotfixContent << uint32(optionalData.Key);
|
||||
hotfixQueryResponse.HotfixContent.append(optionalData.Data.data(), optionalData.Data.size());
|
||||
}
|
||||
}
|
||||
|
||||
hotfixData.Size = hotfixQueryResponse.HotfixContent.size() - pos;
|
||||
}
|
||||
else if (std::vector<uint8> const* blobData = sDB2Manager.GetHotfixBlobData(hotfixRecord.TableHash, hotfixRecord.RecordID, GetSessionDbcLocale()))
|
||||
|
||||
@@ -1667,6 +1667,8 @@ void World::SetInitialWorldSettings()
|
||||
sDB2Manager.LoadHotfixBlob(m_availableDbcLocaleMask);
|
||||
TC_LOG_INFO("misc", "Loading hotfix info...");
|
||||
sDB2Manager.LoadHotfixData();
|
||||
TC_LOG_INFO("misc", "Loading hotfix optional data...");
|
||||
sDB2Manager.LoadHotfixOptionalData(m_availableDbcLocaleMask);
|
||||
///- Close hotfix database - it is only used during DB2 loading
|
||||
HotfixDatabase.Close();
|
||||
///- Load M2 fly by cameras
|
||||
|
||||
Reference in New Issue
Block a user