TrinityCore
CharacterCache.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "CharacterCache.h"
19#include "ArenaTeam.h"
20#include "DatabaseEnv.h"
21#include "Log.h"
22#include "MiscPackets.h"
23#include "Player.h"
24#include "Timer.h"
25#include "World.h"
26#include <unordered_map>
27
28namespace
29{
30 std::unordered_map<ObjectGuid, CharacterCacheEntry> _characterCacheStore;
31 std::unordered_map<std::string, CharacterCacheEntry*> _characterCacheByNameStore;
32}
33
35{
36}
37
39{
40}
41
43{
45 return &instance;
46}
47
70{
71 _characterCacheStore.clear();
72 uint32 oldMSTime = getMSTime();
73
74 QueryResult result = CharacterDatabase.Query("SELECT guid, name, account, race, gender, class, level, deleteDate FROM characters");
75 if (!result)
76 {
77 TC_LOG_INFO("server.loading", "No character name data loaded, empty query");
78 return;
79 }
80
81 do
82 {
83 Field* fields = result->Fetch();
84 AddCharacterCacheEntry(ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64()) /*guid*/, fields[2].GetUInt32() /*account*/, fields[1].GetString() /*name*/,
85 fields[4].GetUInt8() /*gender*/, fields[3].GetUInt8() /*race*/, fields[5].GetUInt8() /*class*/, fields[6].GetUInt8() /*level*/, fields[7].GetUInt32() != 0);
86 } while (result->NextRow());
87
88 TC_LOG_INFO("server.loading", "Loaded character infos for {} characters in {} ms", _characterCacheStore.size(), GetMSTimeDiffToNow(oldMSTime));
89}
90
91/*
92Modifying functions
93*/
94void CharacterCache::AddCharacterCacheEntry(ObjectGuid const& guid, uint32 accountId, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level, bool isDeleted)
95{
96 CharacterCacheEntry& data = _characterCacheStore[guid];
97 data.Guid = guid;
98 data.Name = name;
99 data.AccountId = accountId;
100 data.Race = race;
101 data.Sex = gender;
102 data.Class = playerClass;
103 data.Level = level;
104 data.GuildId = 0; // Will be set in guild loading or guild setting
105 for (uint8 i = 0; i < MAX_ARENA_SLOT; ++i)
106 data.ArenaTeamId[i] = 0; // Will be set in arena teams loading
107 data.IsDeleted = isDeleted;
108
109 // Fill Name to Guid Store
110 if (!isDeleted)
111 _characterCacheByNameStore[name] = &data;
112}
113
114void CharacterCache::DeleteCharacterCacheEntry(ObjectGuid const& guid, std::string const& name)
115{
116 _characterCacheStore.erase(guid);
117 _characterCacheByNameStore.erase(name);
118}
119
120void CharacterCache::UpdateCharacterData(ObjectGuid const& guid, std::string const& name, Optional<uint8> gender /*= {}*/, Optional<uint8> race /*= {}*/)
121{
122 auto itr = _characterCacheStore.find(guid);
123 if (itr == _characterCacheStore.end())
124 return;
125
126 std::string oldName = itr->second.Name;
127 itr->second.Name = name;
128
129 if (gender)
130 itr->second.Sex = *gender;
131
132 if (race)
133 itr->second.Race = *race;
134
136 invalidatePlayer.Guid = guid;
137 sWorld->SendGlobalMessage(invalidatePlayer.Write());
138
139 // Correct name -> pointer storage
140 _characterCacheByNameStore.erase(oldName);
141 _characterCacheByNameStore[name] = &itr->second;
142}
143
145{
146 auto itr = _characterCacheStore.find(guid);
147 if (itr == _characterCacheStore.end())
148 return;
149
150 itr->second.Sex = gender;
151}
152
154{
155 auto itr = _characterCacheStore.find(guid);
156 if (itr == _characterCacheStore.end())
157 return;
158
159 itr->second.Level = level;
160}
161
163{
164 auto itr = _characterCacheStore.find(guid);
165 if (itr == _characterCacheStore.end())
166 return;
167
168 itr->second.AccountId = accountId;
169}
170
172{
173 auto itr = _characterCacheStore.find(guid);
174 if (itr == _characterCacheStore.end())
175 return;
176
177 itr->second.GuildId = guildId;
178}
179
181{
182 auto itr = _characterCacheStore.find(guid);
183 if (itr == _characterCacheStore.end())
184 return;
185
186 ASSERT(slot < 3);
187 itr->second.ArenaTeamId[slot] = arenaTeamId;
188}
189
190void CharacterCache::UpdateCharacterInfoDeleted(ObjectGuid const& guid, bool deleted, std::string const& name /*=nullptr*/)
191{
192 auto itr = _characterCacheStore.find(guid);
193 if (itr == _characterCacheStore.end())
194 return;
195
196 if (deleted)
197 _characterCacheByNameStore.erase(itr->second.Name);
198 else
199 _characterCacheByNameStore[name] = &itr->second;
200
201 itr->second.Name = name;
202 itr->second.IsDeleted = deleted;
203}
204
205/*
206Getters
207*/
209{
210 return _characterCacheStore.find(guid) != _characterCacheStore.end();
211}
212
214{
215 auto itr = _characterCacheStore.find(guid);
216 if (itr != _characterCacheStore.end())
217 return &itr->second;
218
219 return nullptr;
220}
221
223{
224 auto itr = _characterCacheByNameStore.find(name);
225 if (itr != _characterCacheByNameStore.end())
226 return itr->second;
227
228 return nullptr;
229}
230
232{
233 auto itr = _characterCacheByNameStore.find(name);
234 if (itr != _characterCacheByNameStore.end())
235 return itr->second->Guid;
236
237 return ObjectGuid::Empty;
238}
239
240bool CharacterCache::GetCharacterNameByGuid(ObjectGuid guid, std::string& name) const
241{
242 auto itr = _characterCacheStore.find(guid);
243 if (itr == _characterCacheStore.end())
244 return false;
245
246 name = itr->second.Name;
247 return true;
248}
249
251{
252 auto itr = _characterCacheStore.find(guid);
253 if (itr == _characterCacheStore.end())
254 return TEAM_OTHER;
255
256 return Player::TeamForRace(itr->second.Race);
257}
258
260{
261 auto itr = _characterCacheStore.find(guid);
262 if (itr == _characterCacheStore.end())
263 return 0;
264
265 return itr->second.AccountId;
266}
267
269{
270 auto itr = _characterCacheByNameStore.find(name);
271 if (itr != _characterCacheByNameStore.end())
272 return itr->second->AccountId;
273
274 return 0;
275}
276
278{
279 auto itr = _characterCacheStore.find(guid);
280 if (itr == _characterCacheStore.end())
281 return 0;
282
283 return itr->second.Level;
284}
285
287{
288 auto itr = _characterCacheStore.find(guid);
289 if (itr == _characterCacheStore.end())
290 return 0;
291
292 return itr->second.GuildId;
293}
294
296{
297 auto itr = _characterCacheStore.find(guid);
298 if (itr == _characterCacheStore.end())
299 return 0;
300
301 uint8 slot = ArenaTeam::GetSlotByType(type);
302 ASSERT(slot < 3);
303 return itr->second.ArenaTeamId[slot];
304}
305
306bool CharacterCache::GetCharacterNameAndClassByGUID(ObjectGuid guid, std::string& name, uint8& _class) const
307{
308 auto itr = _characterCacheStore.find(guid);
309 if (itr == _characterCacheStore.end())
310 return false;
311
312 name = itr->second.Name;
313 _class = itr->second.Class;
314 return true;
315}
316
#define MAX_ARENA_SLOT
Definition: ArenaTeam.h:109
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
uint8_t uint8
Definition: Define.h:144
uint32_t uint32
Definition: Define.h:142
#define ASSERT
Definition: Errors.h:68
#define TC_LOG_INFO(filterType__,...)
Definition: Log.h:159
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
if(posix_memalign(&__mallocedMemory, __align, __size)) return NULL
Team
@ TEAM_OTHER
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition: Timer.h:57
uint32 getMSTime()
Definition: Timer.h:33
static uint8 GetSlotByType(uint32 type)
Definition: ArenaTeam.cpp:467
ObjectGuid GetCharacterGuidByName(std::string const &name) const
uint8 GetCharacterLevelByGuid(ObjectGuid guid) const
bool GetCharacterNameAndClassByGUID(ObjectGuid guid, std::string &name, uint8 &_class) const
void UpdateCharacterAccountId(ObjectGuid const &guid, uint32 accountId)
bool HasCharacterCacheEntry(ObjectGuid const &guid) const
void AddCharacterCacheEntry(ObjectGuid const &guid, uint32 accountId, std::string const &name, uint8 gender, uint8 race, uint8 playerClass, uint8 level, bool isDeleted)
CharacterCacheEntry const * GetCharacterCacheByName(std::string const &name) const
static CharacterCache * instance()
void UpdateCharacterGender(ObjectGuid const &guid, uint8 gender)
void DeleteCharacterCacheEntry(ObjectGuid const &guid, std::string const &name)
uint32 GetCharacterAccountIdByGuid(ObjectGuid guid) const
void UpdateCharacterData(ObjectGuid const &guid, std::string const &name, Optional< uint8 > gender={}, Optional< uint8 > race={})
Team GetCharacterTeamByGuid(ObjectGuid guid) const
uint32 GetCharacterArenaTeamIdByGuid(ObjectGuid guid, uint8 type) const
void UpdateCharacterLevel(ObjectGuid const &guid, uint8 level)
uint32 GetCharacterAccountIdByName(std::string const &name) const
void LoadCharacterCacheStorage()
Loads several pieces of information on server startup with the GUID There is no further database quer...
CharacterCacheEntry const * GetCharacterCacheByGuid(ObjectGuid const &guid) const
ObjectGuid::LowType GetCharacterGuildIdByGuid(ObjectGuid guid) const
void UpdateCharacterGuildId(ObjectGuid const &guid, ObjectGuid::LowType guildId)
void UpdateCharacterArenaTeamId(ObjectGuid const &guid, uint8 slot, uint32 arenaTeamId)
void UpdateCharacterInfoDeleted(ObjectGuid const &guid, bool deleted, std::string const &name)
bool GetCharacterNameByGuid(ObjectGuid guid, std::string &name) const
Class used to access individual fields of database query result.
Definition: Field.h:90
static ObjectGuid const Empty
Definition: ObjectGuid.h:274
uint64 LowType
Definition: ObjectGuid.h:278
static Team TeamForRace(uint8 race)
Definition: Player.cpp:6454
WorldPacket const * Write() override
Definition: MiscPackets.cpp:30
#define sWorld
Definition: World.h:931
ObjectGuid::LowType GuildId