33constexpr int32 WORLDSTATE_ANY_MAP = -1;
36 std::unordered_map<int32, WorldStateTemplate> WorldStateTemplates;
37 std::mutex RealmWorldStateValuesMutex;
39 std::unordered_set<WorldStateValueContainer::value_type const*> ChangedRealmWorldStates;
40 std::vector<WorldPackets::WorldState::InitWorldStates::WorldStateInfo> RealmWorldStatePacketCache;
41 std::unordered_map<int32, WorldStateValueContainer> WorldStatesByMap;
60 Data& data = GetData();
64 Field* fields = result->Fetch();
77 TC_LOG_ERROR(
"sql.sql",
"Table `world_state` contains a world state {} with non-integer MapID ({}), map ignored",
82 if (!
sMapStore.LookupEntry(*mapId) && mapId != WORLDSTATE_ANY_MAP)
84 TC_LOG_ERROR(
"sql.sql",
"Table `world_state` contains a world state {} with invalid MapID ({}), map ignored",
89 worldState.
MapIds.insert(*mapId);
92 if (!mapIds.empty() && worldState.
MapIds.empty())
94 TC_LOG_ERROR(
"sql.sql",
"Table `world_state` contains a world state {} with nonempty MapIDs ({}) but no valid map id was found, ignored",
100 if (!worldState.
MapIds.empty())
107 TC_LOG_ERROR(
"sql.sql",
"Table `world_state` contains a world state {} with non-integer AreaID ({}), area ignored",
115 TC_LOG_ERROR(
"sql.sql",
"Table `world_state` contains a world state {} with invalid AreaID ({}), area ignored",
122 TC_LOG_ERROR(
"sql.sql",
"Table `world_state` contains a world state {} with AreaID ({}) not on any of required maps, area ignored",
127 worldState.
AreaIds.insert(*areaId);
130 if (!areaIds.empty() && worldState.
AreaIds.empty())
132 TC_LOG_ERROR(
"sql.sql",
"Table `world_state` contains a world state {} with nonempty AreaIDs ({}) but no valid area id was found, ignored",
137 else if (!areaIds.empty())
139 TC_LOG_ERROR(
"sql.sql",
"Table `world_state` contains a world state {} with nonempty AreaIDs ({}) but is a realm wide world state, area requirement ignored",
145 if (!worldState.
MapIds.empty())
148 data.WorldStatesByMap[mapId][
id] = worldState.
DefaultValue;
151 data.RealmWorldStateValues[id] = worldState.
DefaultValue;
153 }
while (result->NextRow());
160 uint32 savedValueCount = 0;
165 Field* fields = result->Fetch();
170 TC_LOG_ERROR(
"sql.sql",
"Table `world_state_value` contains a value for unknown world state {}, ignored", worldStateId);
176 if (!worldState->
MapIds.empty())
179 data.WorldStatesByMap[mapId][worldStateId] = value;
182 data.RealmWorldStateValues[worldStateId] = value;
186 while (result->NextRow());
194 Data& data = GetData();
195 if (!data.ChangedRealmWorldStates.empty())
197 data.RealmWorldStatePacketCache.clear();
198 for (
auto const& [worldStateId, value] : data.RealmWorldStateValues)
199 data.RealmWorldStatePacketCache.emplace_back(worldStateId, value);
202 for (WorldStateValueContainer::value_type
const* changedRealmWorldState : data.ChangedRealmWorldStates)
205 updateWorldState.
VariableID = changedRealmWorldState->first;
206 updateWorldState.
Value = changedRealmWorldState->second;
207 updateWorldState.
Hidden =
false;
208 sWorld->SendGlobalMessage(updateWorldState.
Write());
211 data.ChangedRealmWorldStates.clear();
223 if (!worldStateTemplate || worldStateTemplate->
MapIds.empty())
225 Data& data = GetData();
226 std::scoped_lock lock(data.RealmWorldStateValuesMutex);
233 if (!map || (!worldStateTemplate->
MapIds.contains(map->
GetId()) && !worldStateTemplate->
MapIds.contains(WORLDSTATE_ANY_MAP)))
242 if (!worldStateTemplate || worldStateTemplate->
MapIds.empty())
246 Data& data = GetData();
247 std::scoped_lock lock(data.RealmWorldStateValuesMutex);
248 auto [itr, inserted] = data.RealmWorldStateValues.try_emplace(worldStateId, 0);
249 oldValue = itr->second;
250 if (oldValue == value && !inserted)
254 data.ChangedRealmWorldStates.insert(&*itr);
257 if (worldStateTemplate)
258 sScriptMgr->OnWorldStateValueChange(worldStateTemplate, oldValue, value,
nullptr);
263 if (!map || (!worldStateTemplate->
MapIds.contains(map->
GetId()) && !worldStateTemplate->
MapIds.contains(WORLDSTATE_ANY_MAP)))
282 SetValue(worldStateId, value, hidden, map);
289 Data& data = GetData();
291 initialValues.insert(valuesTemplate->begin(), valuesTemplate->end());
294 initialValues.insert(valuesTemplate->begin(), valuesTemplate->end());
296 return initialValues;
301 Data& data = GetData();
302 initWorldStates.
Worldstates.insert(initWorldStates.
Worldstates.end(), data.RealmWorldStatePacketCache.begin(), data.RealmWorldStatePacketCache.end());
307 if (worldStateTemplate && !worldStateTemplate->
AreaIds.empty())
309 bool isInAllowedArea = std::ranges::any_of(worldStateTemplate->
AreaIds,
310 [=](
uint32 requiredAreaId) { return DB2Manager::IsInArea(playerAreaId, requiredAreaId); });
311 if (!isInAllowedArea)
315 initWorldStates.
Worldstates.emplace_back(worldStateId, value);
DB2Storage< MapEntry > sMapStore("Map.db2", &MapLoadInfo::Instance)
DB2Storage< AreaTableEntry > sAreaTableStore("AreaTable.db2", &AreaTableLoadInfo::Instance)
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__,...)
std::optional< T > Optional
Optional helper class to wrap optional values within.
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
std::unordered_map< int32, int32 > WorldStateValueContainer
Class used to access individual fields of database query result.
std::string_view GetStringView() const noexcept
int32 GetInt32() const noexcept
WorldStateValueContainer const & GetWorldStateValues() const
void SetWorldStateValue(int32 worldStateId, int32 value, bool hidden)
int32 GetWorldStateValue(int32 worldStateId) const
void setInt32(uint8 index, int32 value)
std::vector< WorldStateInfo > Worldstates
WorldPacket const * Write() override
auto MapGetValuePtr(M &map, typename M::key_type const &key)
TC_COMMON_API std::vector< std::string_view > Tokenize(std::string_view str, char sep, bool keepEmpty)
TC_GAME_API void SetValue(int32 worldStateId, int32 value, bool hidden, Map *map)
TC_GAME_API void SetValueAndSaveInDb(int32 worldStateId, int32 value, bool hidden, Map *map)
TC_GAME_API void SaveValueInDb(int32 worldStateId, int32 value)
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates &initWorldStates, Map const *map, uint32 playerAreaId)
TC_GAME_API WorldStateTemplate const * GetWorldStateTemplate(int32 worldStateId)
TC_GAME_API int32 GetValue(int32 worldStateId, Map const *map)
WorldStateValueContainer GetInitialWorldStatesForMap(Map const *map)
std::unordered_set< uint32 > AreaIds
std::unordered_set< uint32 > MapIds