Core/Quests: converted SMSG_QUEST_POI_QUERY_RESPONSE to packet class and ported quest poi data for all quests from classic

This commit is contained in:
Ovahlord committed 2025-07-27 21:34:56 +02:00
1 parent faef256861
commit 3e73122965
6 files changed
+122171 -148

No files matched your search

File diff suppressed because it is too large. Load diff
+43 -91
View File
@@ -7770,96 +7770,69 @@ void ObjectMgr::LoadQuestPOI()
_questPOIStore.clear(); // need for reload case
uint32 count = 0;
// 0 1 2 3 4 5 6 7
QueryResult result = WorldDatabase.Query(
"SELECT QuestID, id, ObjectiveIndex, MapID, WorldMapAreaId, Floor, Priority, Flags FROM quest_poi order by "
"QuestID");
// 0 1 2 3 4 5 6 7 8
QueryResult result = WorldDatabase.Query("SELECT QuestID, BlobIndex, Idx1, ObjectiveIndex, MapID, WorldMapAreaID, Floor, Priority, Flags FROM quest_poi ORDER BY QuestID, Idx1");
if (!result)
{
TC_LOG_ERROR("server.loading", ">> Loaded 0 quest POI definitions. DB table `quest_poi` is empty.");
return;
}
// 0 1 2 3
QueryResult points =
WorldDatabase.Query("SELECT QuestID, Idx1, X, Y FROM quest_poi_points ORDER BY QuestID DESC, Idx2");
// 0 1 2 3
QueryResult pointsResult = WorldDatabase.Query("SELECT QuestID, Idx1, X, Y FROM quest_poi_points ORDER BY QuestID DESC, Idx1, Idx2");
std::vector<std::vector<std::vector<QuestPOIBlobPoint>>> POIs;
std::unordered_map<int32, std::map<int32, std::vector<QuestPOIBlobPoint>>> allPoints;
if (points)
if (pointsResult)
{
// The first result should have the highest questId
Field* fields = points->Fetch();
uint32 questIdMax = fields[0].GetUInt32();
POIs.resize(questIdMax + 1);
do
{
fields = points->Fetch();
Field* fields = pointsResult->Fetch();
uint32 questId = fields[0].GetUInt32();
uint32 id = fields[1].GetUInt32();
int32 x = fields[2].GetInt32();
int32 y = fields[3].GetInt32();
int32 QuestID = fields[0].GetInt32();
int32 Idx1 = fields[1].GetInt32();
int32 x = fields[2].GetInt32();
int32 y = fields[3].GetInt32();
if (POIs[questId].size() <= id + 1) POIs[questId].resize(id + 10);
QuestPOIBlobPoint point;
point.X = x;
point.Y = y;
POIs[questId][id].push_back(point);
} while (points->NextRow());
allPoints[QuestID][Idx1].emplace_back(x, y);
} while (pointsResult->NextRow());
}
do
{
Field* fields = result->Fetch();
uint32 questId = fields[0].GetUInt32();
uint32 id = fields[1].GetUInt32();
int32 objIndex = fields[2].GetInt32();
uint32 mapId = fields[3].GetUInt32();
uint32 WorldMapAreaId = fields[4].GetUInt32();
uint32 FloorId = fields[5].GetUInt32();
uint32 Priority = fields[6].GetUInt32();
uint32 Flags = fields[7].GetUInt32();
int32 questID = fields[0].GetInt32();
int32 blobIndex = fields[1].GetInt32();
int32 idx1 = fields[2].GetInt32();
int32 objectiveIndex = fields[3].GetInt32();
int32 mapID = fields[4].GetInt32();
int32 worldMapAreaID = fields[5].GetInt32();
int32 floor = fields[6].GetInt32();
int32 priority = fields[7].GetInt32();
int32 flags = fields[8].GetInt32();
QuestPOIBlobData POI;
POI.BlobIndex = id;
POI.ObjectiveIndex = objIndex;
POI.MapID = mapId;
POI.WorldMapAreaID = WorldMapAreaId;
POI.Floor = FloorId;
POI.Priority = Priority;
POI.Flags = Flags;
if (!GetQuestTemplate(questID))
TC_LOG_ERROR("sql.sql", "`quest_poi` quest id (%i) Idx1 (%i) does not exist in `quest_template`", questID, idx1);
if (questId < POIs.size() && id < POIs[questId].size())
if (std::map<int32, std::vector<QuestPOIBlobPoint>>* blobs = Trinity::Containers::MapGetValuePtr(allPoints, questID))
{
POI.QuestPOIBlobPointStats = POIs[questId][id];
auto itr = _questPOIStore.find(questId);
if (itr == _questPOIStore.end())
QuestPOIData& poiData = _questPOIStore[questID];
poiData.QuestID = questID;
if (std::vector<QuestPOIBlobPoint>* points = Trinity::Containers::MapGetValuePtr(*blobs, idx1))
poiData.Blobs.emplace_back(blobIndex, objectiveIndex, mapID, worldMapAreaID, floor, priority, flags, std::move(*points));
else
{
QuestPOIWrapper wrapper;
QuestPOIData data;
data.QuestID = questId;
wrapper.POIData = data;
_questPOIStore.emplace(questId, std::move(wrapper));
// Some POIs can reference empty blobs according to sniff data
poiData.Blobs.emplace_back(blobIndex, objectiveIndex, mapID, worldMapAreaID, floor, priority, flags, std::move(std::vector<QuestPOIBlobPoint>()));
}
_questPOIStore.at(questId).POIData.QuestPOIBlobDataStats.push_back(POI);
}
else
TC_LOG_ERROR("sql.sql", "Table quest_poi references unknown quest points for quest %u POI id %u", questId,
id);
++count;
} while (result->NextRow());
TC_LOG_INFO("server.loading", ">> Loaded %u quest POI definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
TC_LOG_INFO("server.loading", ">> Loaded %u quest POI definitions in %u ms", uint32(_questPOIStore.size()), GetMSTimeDiffToNow(oldMSTime));
}
void ObjectMgr::LoadQuestMoneyRewards()
@@ -10013,6 +9986,11 @@ CreatureTemplate const* ObjectMgr::GetCreatureTemplate(uint32 entry) const
return nullptr;
}
QuestPOIData const* ObjectMgr::GetQuestPOIData(int32 questId)
{
return Trinity::Containers::MapGetValuePtr(_questPOIStore, questId);
}
VehicleAccessoryList const* ObjectMgr::GetVehicleAccessoryList(Vehicle* veh) const
{
if (Creature* cre = veh->GetBase()->ToCreature())
@@ -10416,36 +10394,10 @@ void ObjectMgr::InitializeQueriesData(QueryDataGroup mask)
TC_LOG_INFO("server.loading", ">> Initialized query cache data in %u ms", GetMSTimeDiffToNow(oldMSTime));
}
void QuestPOIWrapper::InitializeQueryData()
void QuestPOIData::InitializeQueryData()
{
QueryDataBuffer = BuildQueryData();
}
ByteBuffer QuestPOIWrapper::BuildQueryData() const
{
ByteBuffer tempBuffer;
tempBuffer << uint32(POIData.QuestID); // quest ID
tempBuffer << uint32(POIData.QuestPOIBlobDataStats.size()); // POI count
for (QuestPOIBlobData const& questPOIBlobData : POIData.QuestPOIBlobDataStats)
{
tempBuffer << uint32(questPOIBlobData.BlobIndex); // POI index
tempBuffer << int32(questPOIBlobData.ObjectiveIndex); // objective index
tempBuffer << uint32(questPOIBlobData.MapID); // mapid
tempBuffer << uint32(questPOIBlobData.WorldMapAreaID); // areaid
tempBuffer << uint32(questPOIBlobData.Floor); // floorid
tempBuffer << uint32(questPOIBlobData.Priority); // priority
tempBuffer << uint32(questPOIBlobData.Flags); // flags
tempBuffer << uint32(questPOIBlobData.QuestPOIBlobPointStats.size()); // POI points count
for (QuestPOIBlobPoint const& questPOIBlobPoint : questPOIBlobData.QuestPOIBlobPointStats)
{
tempBuffer << int32(questPOIBlobPoint.X); // POI point x
tempBuffer << int32(questPOIBlobPoint.Y); // POI point y
}
}
return tempBuffer;
QueryDataBuffer << *this;
QueryDataBuffer.shrink_to_fit();
}
void ObjectMgr::LoadSummonPropertiesParameters()
+22 -28
View File
@@ -816,40 +816,40 @@ typedef std::pair<GossipMenuItemsContainer::iterator, GossipMenuItemsContainer::
struct QuestPOIBlobPoint
{
int32 X = 0;
int32 Y = 0;
int32 X;
int32 Y;
QuestPOIBlobPoint() : X(0), Y(0) { }
QuestPOIBlobPoint(int32 x, int32 y) : X(x), Y(y) { }
};
struct QuestPOIBlobData
{
uint32 BlobIndex = 0;
int32 ObjectiveIndex = 0;
uint32 MapID = 0;
uint32 WorldMapAreaID = 0;
uint32 Floor = 0;
uint32 Priority = 0;
uint32 Flags = 0;
std::vector<QuestPOIBlobPoint> QuestPOIBlobPointStats;
int32 BlobIndex;
int32 ObjectiveIndex;
int32 MapID;
int32 WorldMapAreaID;
int32 Floor;
int32 Priority;
int32 Flags;
std::vector<QuestPOIBlobPoint> Points;
QuestPOIBlobData():
BlobIndex(0), ObjectiveIndex(0), MapID(0), WorldMapAreaID(0), Floor(0), Priority(0), Flags(0) { }
QuestPOIBlobData(int32 blobIndex, int32 objectiveIndex, int32 mapId, int32 worldMapAreaId, int32 floor, int32 priority, int32 flags, std::vector<QuestPOIBlobPoint> points) :
BlobIndex(blobIndex), ObjectiveIndex(objectiveIndex), MapID(mapId), WorldMapAreaID(worldMapAreaId), Floor(floor), Priority(priority), Flags(flags), Points(std::move(points)) { }
};
struct QuestPOIData
{
uint32 QuestID = 0;
std::vector<QuestPOIBlobData> QuestPOIBlobDataStats;
};
struct QuestPOIWrapper
{
QuestPOIData POIData;
ByteBuffer QueryDataBuffer;
std::vector<QuestPOIBlobData> Blobs;
void InitializeQueryData();
ByteBuffer BuildQueryData() const;
QuestPOIWrapper() : QueryDataBuffer(0) { }
ByteBuffer QueryDataBuffer;
};
typedef std::unordered_map<uint32, QuestPOIWrapper> QuestPOIContainer;
typedef std::unordered_map<uint32, QuestPOIData> QuestPOIContainer;
struct QuestGreeting
{
@@ -1130,13 +1130,7 @@ class TC_GAME_API ObjectMgr
return nullptr;
}
QuestPOIWrapper const* GetQuestPOIWrapper(uint32 questId)
{
QuestPOIContainer::const_iterator itr = _questPOIStore.find(questId);
if (itr != _questPOIStore.end())
return &itr->second;
return nullptr;
}
QuestPOIData const* GetQuestPOIData(int32 questId);
VehicleAccessoryList const* GetVehicleAccessoryList(Vehicle* veh) const;
+5 -29
View File
@@ -363,37 +363,13 @@ void WorldSession::HandleQuestPOIQuery(WorldPackets::Query::QuestPOIQuery& query
for (uint32 i = 0; i < query.MissingQuestCount; ++i)
questIds.insert(query.MissingQuestPOIs[i]); // quest id
WorldPacket data(SMSG_QUEST_POI_QUERY_RESPONSE, 4 + (4 + 4 + 40) * questIds.size());
data << uint32(questIds.size()); // count
WorldPackets::Query::QuestPOIQueryResponse response;
for (uint32 questId : questIds)
{
uint16 const questSlot = _player->FindQuestSlot(questId);
if (questSlot != MAX_QUEST_LOG_SIZE && _player->GetQuestSlotQuestId(questSlot) == questId)
{
if (QuestPOIWrapper const* poiWrapper = sObjectMgr->GetQuestPOIWrapper(questId))
{
if (sWorld->getBoolConfig(CONFIG_CACHE_DATA_QUERIES))
data.append(poiWrapper->QueryDataBuffer);
else
{
ByteBuffer POIByteBuffer = poiWrapper->BuildQueryData();
data.append(POIByteBuffer);
}
}
else
{
data << uint32(questId); // quest ID
data << uint32(0); // POI count
}
}
else
{
data << uint32(questId); // quest ID
data << uint32(0); // POI count
}
}
if (_player->FindQuestSlot(questId) != MAX_QUEST_LOG_SIZE)
if (QuestPOIData const* poiData = sObjectMgr->GetQuestPOIData(questId))
response.QuestPOIDataStats.push_back(poiData);
SendPacket(&data);
SendPacket(response.Write());
}
void WorldSession::HandleDBQueryBulk(WorldPackets::Query::DBQueryBulk& packet)
@@ -16,8 +16,36 @@
*/
#include "CharacterCache.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "QueryPackets.h"
#include "World.h"
ByteBuffer& operator<<(ByteBuffer& data, QuestPOIData const& questPOIData)
{
data << int32(questPOIData.QuestID);
data << int32(questPOIData.Blobs.size());
for (QuestPOIBlobData const& questPOIBlobData : questPOIData.Blobs)
{
data << int32(questPOIBlobData.BlobIndex);
data << int32(questPOIBlobData.ObjectiveIndex);
data << int32(questPOIBlobData.MapID);
data << int32(questPOIBlobData.WorldMapAreaID);
data << int32(questPOIBlobData.Floor);
data << int32(questPOIBlobData.Priority);
data << int32(questPOIBlobData.Flags);
data << int32(questPOIBlobData.Points.size());
for (QuestPOIBlobPoint const& questPOIBlobPoint : questPOIBlobData.Points)
{
data << int32(questPOIBlobPoint.X);
data << int32(questPOIBlobPoint.Y);
}
}
return data;
}
void WorldPackets::Query::QueryCreature::Read()
{
@@ -101,6 +129,23 @@ void WorldPackets::Query::QuestPOIQuery::Read()
_worldPacket.rfinish();
}
WorldPacket const* WorldPackets::Query::QuestPOIQueryResponse::Write()
{
_worldPacket << int32(QuestPOIDataStats.size());
bool useCache = sWorld->getBoolConfig(CONFIG_CACHE_DATA_QUERIES);
for (QuestPOIData const* questPOIData : QuestPOIDataStats)
{
if (useCache)
_worldPacket.append(questPOIData->QueryDataBuffer);
else
_worldPacket << *questPOIData;
}
return &_worldPacket;
}
void WorldPackets::Query::DBQueryBulk::Read()
{
_worldPacket >> TableHash;
@@ -28,6 +28,7 @@
#include "SharedDefines.h"
class Player;
struct QuestPOIData;
namespace WorldPackets
{
@@ -124,6 +125,16 @@ namespace WorldPackets
std::array<uint32, MAX_QUEST_LOG_SIZE> MissingQuestPOIs = {};
};
class QuestPOIQueryResponse final : public ServerPacket
{
public:
explicit QuestPOIQueryResponse() : ServerPacket(SMSG_QUEST_POI_QUERY_RESPONSE, 4 + 4) { }
WorldPacket const* Write() override;
std::vector<QuestPOIData const*> QuestPOIDataStats;
};
struct DBQueryRecord
{
ObjectGuid GUID;
@@ -191,4 +202,6 @@ namespace WorldPackets
}
}
ByteBuffer& operator<<(ByteBuffer& data, QuestPOIData const& questPOIData);
#endif // QueryPackets_h__