25#include <unordered_map>
26#include <unordered_set>
57 trans->Append(delStmt);
64 trans->Append(insStmt);
71 std::unordered_map<uint32, std::pair<std::vector<QuestPool>*,
uint32>> lookup;
80 QueryResult result =
WorldDatabase.Query(
"SELECT qpm.questId, qpm.poolId, qpm.poolIndex, qpt.numActive FROM quest_pool_members qpm LEFT JOIN quest_pool_template qpt ON qpm.poolId = qpt.poolId");
83 TC_LOG_INFO(
"server.loading",
">> Loaded 0 quest pools. DB table `quest_pool_members` is empty.");
89 Field* fields = result->Fetch();
90 if (fields[2].IsNull())
92 TC_LOG_ERROR(
"sql.sql",
"Table `quest_pool_members` contains reference to non-existing pool {}. Skipped.", fields[1].GetUInt32());
104 TC_LOG_ERROR(
"sql.sql",
"Table `quest_pool_members` contains reference to non-existing quest {}. Skipped.", questId);
109 TC_LOG_ERROR(
"sql.sql",
"Table `quest_pool_members` contains reference to quest {}, which is neither daily, weekly nor monthly. Skipped.", questId);
113 auto& pair = lookup[poolId];
117 pair.first->emplace_back();
118 pair.second = (pair.first->size()-1);
120 pair.first->back().poolId = poolId;
121 pair.first->back().numActive = numActive;
125 if (!(poolIndex < members.size()))
126 members.resize(poolIndex+1);
127 members[poolIndex].push_back(questId);
128 }
while (result->NextRow());
136 std::unordered_set<uint32> unknownPoolIds;
139 Field* fields = result->Fetch();
144 auto it = lookup.find(poolId);
145 if (it == lookup.end() || !it->second.first)
147 TC_LOG_ERROR(
"sql.sql",
"Table `pool_quest_save` contains reference to non-existant quest pool {}. Deleted.", poolId);
148 unknownPoolIds.insert(poolId);
152 (*it->second.first)[it->second.second].activeQuests.insert(questId);
153 }
while (result->NextRow());
156 for (
uint32 poolId : unknownPoolIds)
168 for (
auto const& pair : lookup)
170 if (!pair.second.first)
172 QuestPool& pool = (*pair.second.first)[pair.second.second];
175 TC_LOG_ERROR(
"sql.sql",
"Table `quest_pool_template` contains quest pool {} requesting {} spawns, but only has {} members. Requested spawns reduced.", pool.
poolId, pool.
numActive, pool.
members.size());
182 std::unordered_set<uint32> accountedFor;
184 for (
size_t i = pool.
members.size(); (i--);)
189 TC_LOG_ERROR(
"sql.sql",
"Table `quest_pool_members` contains no entries at index {} for quest pool {}. Index removed.", i, pool.
poolId);
201 accountedFor.insert(member[0]);
206 for (
auto it = member.begin(); (++it) != member.end();)
209 bool otherStatus = (itOther != pool.
activeQuests.end());
210 if (status != otherStatus)
211 TC_LOG_WARN(
"sql.sql",
"Table `pool_quest_save` {} quest {} (in pool {}, index {}) saved, but its index is{} active (because quest {} is{} in the table). Set quest {} to {}active.", (status ?
"does not have" :
"has"), *it, pool.
poolId, i, (status ?
"" :
" not"), member[0], (status ?
"" :
" not"), *it, (status ?
"" :
"in"));
215 accountedFor.insert(*it);
224 TC_LOG_WARN(
"sql.sql",
"Table `pool_quest_save` has saved quest {} for pool {}, but that quest is not part of the pool. Skipped.", quest, pool.
poolId);
232 TC_LOG_ERROR(
"sql.sql",
"Table `pool_quest_save` has {} active members saved for pool {}, which requests {} active members. Pool spawns re-generated.", activeCount, pool.
poolId, pool.
numActive);
244 for (
uint32 quest : member)
249 TC_LOG_ERROR(
"sql.sql",
"Table `quest_pool_members` lists quest {} as member of pool {}, but it is already a member of pool {}. Skipped.", quest, pool.
poolId, ref->
poolId);
276 auto lambda = [poolId](
QuestPool const& p) {
return (p.poolId == poolId); };
295 return (it->second->activeQuests.find(questId) != it->second->activeQuests.end());
@ CHAR_INS_POOL_QUEST_SAVE
@ CHAR_DEL_POOL_QUEST_SAVE
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
#define TC_LOG_ERROR(filterType__, message__,...)
#define TC_LOG_INFO(filterType__, message__,...)
#define TC_LOG_WARN(filterType__, message__,...)
static void RegeneratePool(QuestPool &pool)
static void SaveToDB(QuestPool const &pool, CharacterDatabaseTransaction trans)
uint32 urand(uint32 min, uint32 max)
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Class used to access individual fields of database query result.
uint32 GetUInt32() const noexcept
uint8 GetUInt8() const noexcept
void setUInt32(uint8 index, uint32 value)
std::vector< QuestPool > _dailyPools
std::vector< QuestPool > _weeklyPools
bool IsQuestActive(uint32 questId) const
std::unordered_map< uint32, QuestPool * > _poolLookup
std::vector< QuestPool > _monthlyPools
static QuestPoolMgr * instance()
void Regenerate(std::vector< QuestPool > &pools)
QuestPool const * FindQuestPool(uint32 poolId) const
bool IsDailyOrWeekly() const
std::vector< Member > Members
std::unordered_set< uint32 > activeQuests
std::vector< uint32 > Member