aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKingPin <none@none>2008-10-21 12:43:24 -0500
committerKingPin <none@none>2008-10-21 12:43:24 -0500
commited94fdb8bc88ed204df805ad292da5c1e2018dde (patch)
tree40a71c55053d3ccd480eba879dc916fc304f9067
parentd0325e253616e855df37a2d23414ff6b93db93bf (diff)
[svn] * Added some player info cache to the core. Thanx to Rognar for patch, visaglis for testing and bugging me to add it.
--HG-- branch : trunk
-rw-r--r--src/game/Guild.cpp16
-rw-r--r--src/game/ObjectMgr.cpp65
-rw-r--r--src/game/ObjectMgr.h21
-rw-r--r--src/game/Player.cpp51
-rw-r--r--src/game/World.cpp3
5 files changed, 156 insertions, 0 deletions
diff --git a/src/game/Guild.cpp b/src/game/Guild.cpp
index cec6507eb7c..bbf8c278ace 100644
--- a/src/game/Guild.cpp
+++ b/src/game/Guild.cpp
@@ -363,6 +363,21 @@ bool Guild::FillPlayerData(uint64 guid, MemberSlot* memslot)
}
else
{
+ PCachePlayerInfo pInfo = objmgr.GetPlayerInfoFromCache(GUID_LOPART(guid));
+ if(pInfo)
+ {
+ plName = pInfo->sPlayerName;
+ plClass = pInfo->unClass;
+ if(plClass<CLASS_WARRIOR||plClass>=MAX_CLASSES) // can be at broken `class` field
+ {
+ sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`class`.",GUID_LOPART(guid));
+ return false;
+ }
+ plLevel = pInfo->unLevel;
+ plZone = Player::GetZoneIdFromDB(guid);
+ }
+ else
+ {
if(!objmgr.GetPlayerNameByGUID(guid, plName)) // player doesn't exist
return false;
@@ -386,6 +401,7 @@ bool Guild::FillPlayerData(uint64 guid, MemberSlot* memslot)
delete result;
}
+ }
memslot->name = plName;
memslot->level = plLevel;
diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
index 9b37a3351d9..e069ed894de 100644
--- a/src/game/ObjectMgr.cpp
+++ b/src/game/ObjectMgr.cpp
@@ -167,6 +167,9 @@ ObjectMgr::~ObjectMgr()
for (GuildSet::iterator itr = mGuildSet.begin(); itr != mGuildSet.end(); ++itr)
delete (*itr);
+ for (CachePlayerInfoMap::iterator itr = m_mPlayerInfoMap.begin(); itr != m_mPlayerInfoMap.end(); ++itr)
+ delete itr->second;
+
for(ItemMap::iterator itr = mAitems.begin(); itr != mAitems.end(); ++itr)
delete itr->second;
@@ -177,6 +180,61 @@ ObjectMgr::~ObjectMgr()
itr->second.Clear();
}
+void ObjectMgr::LoadPlayerInfoInCache()
+{
+ QueryResult *result = CharacterDatabase.PQuery("SELECT guid, name, data, class FROM characters");
+ if(!result)
+ {
+ sLog.outError( "ROGNAR LoadPlayerCache");
+ return;
+ }
+
+ PCachePlayerInfo pPPlayerInfo = NULL;
+ Field *fields = NULL;
+ Tokens tdata;
+ barGoLink bar( result->GetRowCount() );
+ do
+ {
+ bar.step();
+ fields = result->Fetch();
+ pPPlayerInfo = new CachePlayerInfo();
+
+ pPPlayerInfo->sPlayerName = fields[1].GetString();
+
+ tdata.clear();
+ tdata = StrSplit(fields[2].GetCppString(), " ");
+
+ pPPlayerInfo->unLevel = (uint32)atoi(tdata[UNIT_FIELD_LEVEL].c_str());
+ pPPlayerInfo->unfield = (uint32)atoi(tdata[UNIT_FIELD_BYTES_0].c_str());
+
+ pPPlayerInfo->unArenaInfoId0 = (uint32)atoi(tdata[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (0 * 6)].c_str());
+ pPPlayerInfo->unArenaInfoId1 = (uint32)atoi(tdata[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (1 * 6)].c_str());
+ pPPlayerInfo->unArenaInfoId2 = (uint32)atoi(tdata[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (2 * 6)].c_str());
+
+ pPPlayerInfo->unArenaInfoSlot0 = (uint32)atoi(tdata[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 0 * 6 + 5].c_str());
+ pPPlayerInfo->unArenaInfoSlot1 = (uint32)atoi(tdata[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 * 6 + 5].c_str());
+ pPPlayerInfo->unArenaInfoSlot2 = (uint32)atoi(tdata[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 2 * 6 + 5].c_str());
+
+ pPPlayerInfo->unClass = (uint32)fields[3].GetUInt32();
+ m_mPlayerInfoMap[fields[0].GetUInt32()] = pPPlayerInfo;
+ }
+ while (result->NextRow());
+ delete result;
+
+ sLog.outString();
+ sLog.outString( ">> Loaded info about %d players", m_mPlayerInfoMap.size());
+}
+
+PCachePlayerInfo ObjectMgr::GetPlayerInfoFromCache(uint32 unPlayerGuid) const
+{
+ //Now m_mPlayerInfoMap is using only for search, but when dinamic inserting/removing
+ //will be implemented we should lock it to prevent simultaneous access.
+ //Inserting - when new created player is saving
+ //Removing - when player has been deleted
+ CachePlayerInfoMap::const_iterator ipos = m_mPlayerInfoMap.find(unPlayerGuid);
+ return ipos == m_mPlayerInfoMap.end() ? NULL : ipos->second;
+}
+
Group * ObjectMgr::GetGroupByLeader(const uint64 &guid) const
{
for(GroupSet::const_iterator itr = mGroupSet.begin(); itr != mGroupSet.end(); ++itr)
@@ -1261,6 +1319,13 @@ bool ObjectMgr::GetPlayerNameByGUID(const uint64 &guid, std::string &name) const
return true;
}
+ PCachePlayerInfo pInfo = GetPlayerInfoFromCache(GUID_LOPART(guid));
+ if(pInfo)
+ {
+ name = pInfo->sPlayerName.c_str();
+ return true;
+ }
+
QueryResult *result = CharacterDatabase.PQuery("SELECT name FROM characters WHERE guid = '%u'", GUID_LOPART(guid));
if(result)
diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h
index f76cc232e57..898d82ea6ff 100644
--- a/src/game/ObjectMgr.h
+++ b/src/game/ObjectMgr.h
@@ -209,6 +209,23 @@ enum ConditionType
#define MAX_CONDITION 11 // maximum value in ConditionType enum
+//Player's info
+typedef struct _tagCachePlayerInfo
+{
+ std::string sPlayerName;
+ uint32 unfield;
+ uint32 unLevel;
+ uint8 unClass;
+//Arena
+ uint32 unArenaInfoId0;
+ uint32 unArenaInfoId1;
+ uint32 unArenaInfoId2;
+ uint32 unArenaInfoSlot0;
+ uint32 unArenaInfoSlot1;
+ uint32 unArenaInfoSlot2;
+}CachePlayerInfo, *PCachePlayerInfo;
+typedef HM_NAMESPACE::hash_map<uint32, PCachePlayerInfo> CachePlayerInfoMap;
+
struct PlayerCondition
{
ConditionType condition; // additional condition type
@@ -568,6 +585,10 @@ class ObjectMgr
uint32 GenerateMailID();
uint32 GenerateItemTextID();
uint32 GeneratePetNumber();
+
+ void LoadPlayerInfoInCache();
+ PCachePlayerInfo GetPlayerInfoFromCache(uint32 unPlayerGuid) const;
+ CachePlayerInfoMap m_mPlayerInfoMap;
uint32 CreateItemText(std::string text);
std::string GetItemText( uint32 id )
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index 8e692eaccee..c082e18a149 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -13626,6 +13626,40 @@ float Player::GetFloatValueFromArray(Tokens const& data, uint16 index)
uint32 Player::GetUInt32ValueFromDB(uint16 index, uint64 guid)
{
+ //rognar optimization
+ //must be improved!! "if" and "switch" - it's very not aesthetically :)))
+ //but we should know whith data is cached
+ //PLAYER_FIELD_ARENA_TEAM_INFO* very is often using with pvp&arena patch :)
+ if( index == PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 0 * 6 + 5
+ || index == PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 * 6 + 5
+ || index == PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 2 * 6 + 5
+ || index == PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (0 * 6)
+ || index == PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (1 * 6)
+ || index == PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (2 * 6)
+ || index == UNIT_FIELD_LEVEL)
+ {
+ CachePlayerInfoMap::iterator _iter = objmgr.m_mPlayerInfoMap.find(GUID_LOPART(guid));
+ if(_iter != objmgr.m_mPlayerInfoMap.end())
+ {
+ switch(index)
+ {
+ case (PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 0 * 6 + 5):
+ return _iter->second->unArenaInfoSlot0;
+ case (PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 * 6 + 5):
+ return _iter->second->unArenaInfoSlot1;
+ case (PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 2 * 6 + 5):
+ return _iter->second->unArenaInfoSlot2;
+ case (PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (0 * 6)):
+ return _iter->second->unArenaInfoId0;
+ case (PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (1 * 6)):
+ return _iter->second->unArenaInfoId1;
+ case (PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (2 * 6)):
+ return _iter->second->unArenaInfoId2;
+ case (UNIT_FIELD_LEVEL):
+ return _iter->second->unLevel;
+ }
+ }
+ }
Tokens data;
if(!LoadValuesArrayFromDB(data,guid))
return 0;
@@ -15219,6 +15253,23 @@ void Player::SaveToDB()
// save pet (hunter pet level and experience and all type pets health/mana).
if(Pet* pet = GetPet())
pet->SavePetToDB(PET_SAVE_AS_CURRENT);
+
+ //to prevent access to DB we should cache some data, which is used very often
+ CachePlayerInfoMap::iterator _iter = objmgr.m_mPlayerInfoMap.find(GetGUIDLow());
+ if(_iter != objmgr.m_mPlayerInfoMap.end())//skip new players
+ {
+ _iter->second->unLevel = getLevel();
+
+ _iter->second->unArenaInfoSlot0 = GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 0 * 6 + 5);
+ _iter->second->unArenaInfoSlot1 = GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 * 6 + 5);
+ _iter->second->unArenaInfoSlot2 = GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 2 * 6 + 5);
+
+ _iter->second->unfield = GetUInt32Value(UNIT_FIELD_BYTES_0);
+
+ _iter->second->unArenaInfoId0 = GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (0 * 6));
+ _iter->second->unArenaInfoId1 = GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (1 * 6));
+ _iter->second->unArenaInfoId2 = GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (2 * 6));
+ }
}
// fast save function for item/money cheating preventing - save only inventory and money state
diff --git a/src/game/World.cpp b/src/game/World.cpp
index d922e10d332..9fdd9580872 100644
--- a/src/game/World.cpp
+++ b/src/game/World.cpp
@@ -988,6 +988,9 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading Page Texts..." );
objmgr.LoadPageTexts();
+ sLog.outString( "Loading Player info in cache..." );
+ objmgr.LoadPlayerInfoInCache();
+
sLog.outString( "Loading Game Object Templates..." ); // must be after LoadPageTexts
objmgr.LoadGameobjectInfo();