[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
This commit is contained in:
@@ -362,6 +362,21 @@ bool Guild::FillPlayerData(uint64 guid, MemberSlot* memslot)
|
||||
plZone = pl->GetZoneId();
|
||||
}
|
||||
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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -569,6 +586,10 @@ class ObjectMgr
|
||||
uint32 GenerateItemTextID();
|
||||
uint32 GeneratePetNumber();
|
||||
|
||||
void LoadPlayerInfoInCache();
|
||||
PCachePlayerInfo GetPlayerInfoFromCache(uint32 unPlayerGuid) const;
|
||||
CachePlayerInfoMap m_mPlayerInfoMap;
|
||||
|
||||
uint32 CreateItemText(std::string text);
|
||||
std::string GetItemText( uint32 id )
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user