mojo_client/src/Client/World/CacheHandler.cpp
false_genesis 4dce611346 * fixed wrong reading of cached item protos
* fixed+cleanup GetName and GetEntry script funcs
2008-02-20 22:48:16 +00:00

531 lines
16 KiB
C++

#include <vector>
#include <fstream>
#include "common.h"
#include "PseuWoW.h"
#include "Opcodes.h"
#include "SharedDefines.h"
#include "Player.h"
#include "DefScript/DefScript.h"
#include "WorldSession.h"
#include "CacheHandler.h"
#include "Item.h"
// increase this number whenever you change something that makes old files unusable
uint32 ITEMPROTOTYPES_CACHE_VERSION = 3;
uint32 CREATURETEMPLATES_CACHE_VERSION = 0;
PlayerNameCache::~PlayerNameCache()
{
for(std::vector<PlayerNameCacheItem*>::iterator i=_cache.begin(); i!=_cache.end(); i++)
{
delete *i;
}
}
bool PlayerNameCache::AddInfo(uint64 guid, std::string name){
PlayerNameCacheItem *cacheItem=new PlayerNameCacheItem;
cacheItem->_name=name;
cacheItem->_guid=guid;
return AddInfo(cacheItem);
}
bool PlayerNameCache::IsKnown(uint64 guid)
{
for(std::vector<PlayerNameCacheItem*>::iterator i=_cache.begin(); i!=_cache.end(); i++)
if(guid==(*i)->_guid)
return true;
return false;
}
bool PlayerNameCache::AddInfo(PlayerNameCacheItem* cacheItem)
{
for(std::vector<PlayerNameCacheItem*>::iterator i=_cache.begin(); i!=_cache.end(); i++)
if(cacheItem->_guid==(*i)->_guid)
{
delete cacheItem;
return false;
}
_cache.push_back(cacheItem);
return true;
}
std::string PlayerNameCache::GetName(uint64 guid)
{
for(std::vector<PlayerNameCacheItem*>::iterator i=_cache.begin(); i!=_cache.end(); i++)
if(guid==(*i)->_guid)
return (*i)->_name;
return "";
}
uint64 PlayerNameCache::GetGuid(std::string name)
{
for(std::vector<PlayerNameCacheItem*>::iterator i=_cache.begin(); i!=_cache.end(); i++)
if(name==(*i)->_name)
return (*i)->_guid;
return 0;
}
bool PlayerNameCache::SaveToFile(void)
{
log("Saving PlayerNameCache...");
char *fn="./cache/playernames.cache";
std::fstream fh;
fh.open(fn, std::ios_base::out | std::ios_base::binary);
if(!fh)
{
logerror("PlayerNameCache: Could not write to file '%s'!",fn);
return false;
}
uint32 size=_cache.size();
if(size==0)
return false;
uint8 len;
fh.write((char*)&size,sizeof(uint32));
for(std::vector<PlayerNameCacheItem*>::iterator i=_cache.begin(); i!=_cache.end(); i++)
{
fh.write( (char*)&((*i)->_guid),sizeof(uint64) );
len=(*i)->_name.length();
fh.write( (char*)&len,sizeof(uint8) );
fh.write( (char*)(*i)->_name.c_str(),len );
DEBUG(log( "PlayerNameCache << " I64FMT " -> %s", (*i)->_guid, (*i)->_name.c_str()););
}
fh.close();
log("PlayerNameCache saved successfully.");
return true;
}
bool PlayerNameCache::ReadFromFile(void)
{
char *fn="./cache/playernames.cache";
log("Loading PlayerNameCache...");
bool success=true;
std::fstream fh;
fh.open(fn, std::ios_base::in | std::ios_base::binary);
if(!fh.is_open())
{
logerror("PlayerNameCache: Could not open file '%s'!",fn);
return false;
}
if(fh.eof())
{
logdetail("PlayerNameCache: Can't load empty file '%s'",fn);
return false;
}
uint32 size;
fh.read((char*)&size,sizeof(uint32));
std::string tmp;
uint8 len;
char *nameptr=new char[13];
for(unsigned int i=0;i<size;i++)
{
len=255;
memset(nameptr,0,13);
PlayerNameCacheItem *cacheItem=new PlayerNameCacheItem;
fh.read((char*)&(cacheItem->_guid),sizeof(uint64));
fh.read((char*)&len,sizeof(uint8));
if(len > MAX_PLAYERNAME_LENGTH || len < MIN_PLAYERNAME_LENGTH)
{
logerror("PlayerNameCache data seem corrupt [namelength=%d, should be <=%u]",len,MAX_PLAYERNAME_LENGTH);
log("-> Clearing cache, creating new.");
_cache.clear();
success=false;
break;
}
fh.read(nameptr,len);
cacheItem->_name=nameptr;
AddInfo(cacheItem);
printf("\rPlayerNameCache [ %u / %u ] items loaded",i+1,size);
DEBUG(printf( " >> " I64FMT " -> %s\n", cacheItem->_guid, nameptr););
}
printf("\n");
delete nameptr;
fh.flush();
fh.close();
if(success)
log("PlayerNameCache successfully loaded.");
return success;
}
uint32 PlayerNameCache::GetSize(void)
{
return _cache.size();
}
void ItemProtoCache_InsertDataToSession(WorldSession *session)
{
logdetail("ItemProtoCache: Loading...");
char* fn = "./cache/ItemPrototypes.cache";
std::fstream fh;
fh.open(fn, std::ios_base::in | std::ios_base::binary);
if(!fh)
{
logerror("ItemProtoCache: Could not open file '%s'!",fn);
return;
}
uint32 cacheversion, total;
try
{
fh.read((char*)&cacheversion,4);
if(cacheversion != ITEMPROTOTYPES_CACHE_VERSION)
{
logerror("ItemProtoCache is outdated! Creating new cache.");
fh.close();
return;
}
fh.read((char*)&total,4);
logdetail("ItemProtoCache: %u item prototypes stored",total);
uint32 datasize, counter = 0;
ByteBuffer buf;
for(uint32 i = 0; i < total && !fh.eof(); i++)
{
buf.clear();
fh.read((char*)&datasize,sizeof(uint32));
DEBUG(logdebug("ItemProtoCache: (%u/%u) - datasize=%u",i,total,datasize));
buf.resize(datasize);
fh.read((char*)buf.contents(),datasize);
ItemProto *proto = new ItemProto();
buf >> proto->Id;
buf >> proto->Class;
buf >> proto->SubClass;
buf >> proto->Name;
buf >> proto->DisplayInfoID;
buf >> proto->Quality;
buf >> proto->Flags;
buf >> proto->BuyPrice;
buf >> proto->SellPrice;
buf >> proto->InventoryType;
buf >> proto->AllowableClass;
buf >> proto->AllowableRace;
buf >> proto->ItemLevel;
buf >> proto->RequiredLevel;
buf >> proto->RequiredSkill;
buf >> proto->RequiredSkillRank;
buf >> proto->RequiredSpell;
buf >> proto->RequiredHonorRank;
buf >> proto->RequiredCityRank;
buf >> proto->RequiredReputationFaction;
buf >> proto->RequiredReputationRank;
buf >> proto->MaxCount;
buf >> proto->Stackable;
buf >> proto->ContainerSlots;
for(int i = 0; i < 10; i++)
{
buf >> proto->ItemStat[i].ItemStatType;
buf >> proto->ItemStat[i].ItemStatValue;
}
for(int i = 0; i < 5; i++)
{
buf >> proto->Damage[i].DamageMin;
buf >> proto->Damage[i].DamageMax;
buf >> proto->Damage[i].DamageType;
}
buf >> proto->Armor;
buf >> proto->HolyRes;
buf >> proto->FireRes;
buf >> proto->NatureRes;
buf >> proto->FrostRes;
buf >> proto->ShadowRes;
buf >> proto->ArcaneRes;
buf >> proto->Delay;
buf >> proto->Ammo_type;
buf >> (float)proto->RangedModRange;
for(int s = 0; s < 5; s++)
{
buf >> proto->Spells[s].SpellId;
buf >> proto->Spells[s].SpellTrigger;
buf >> proto->Spells[s].SpellCharges;
buf >> proto->Spells[s].SpellCooldown;
buf >> proto->Spells[s].SpellCategory;
buf >> proto->Spells[s].SpellCategoryCooldown;
}
buf >> proto->Bonding;
buf >> proto->Description;
buf >> proto->PageText;
buf >> proto->LanguageID;
buf >> proto->PageMaterial;
buf >> proto->StartQuest;
buf >> proto->LockID;
buf >> proto->Material;
buf >> proto->Sheath;
buf >> proto->Extra;
buf >> proto->Unk1; // added in 2.0.3
buf >> proto->Block;
buf >> proto->ItemSet;
buf >> proto->MaxDurability;
buf >> proto->Area;
buf >> proto->Map;
buf >> proto->BagFamily;
buf >> proto->TotemCategory; // Added in 1.12.x client branch
for(uint32 s = 0; s < 3; s++)
{
buf >> proto->Socket[s].Color;
buf >> proto->Socket[s].Content;
}
buf >> proto->socketBonus;
buf >> proto->GemProperties;
buf >> proto->ExtendedCost;
buf >> proto->RequiredArenaRank;
buf >> proto->RequiredDisenchantSkill;
buf >> proto->ArmorDamageModifier;
if(proto->Id)
{
//DEBUG(logdebug("ItemProtoCache: Loaded %u [%s]",proto->Id, proto->Name[0].c_str()));
session->objmgr.Add(proto);
counter++;
} else
delete proto;
}
}
catch (ByteBufferException bbe)
{
logerror("ByteBuffer exception: attempt to \"%s\" %u bytes at position %u out of total %u bytes. (wpos=%u)",
bbe.action, bbe.readsize, bbe.rpos, bbe.cursize, bbe.wpos);
}
fh.close();
logdetail("ItemProtoCache: Loaded %u Item Prototypes",total);
}
void ItemProtoCache_WriteDataToCache(WorldSession *session)
{
if (!session->objmgr.GetItemProtoCount())
return;
char* fn = "./cache/ItemPrototypes.cache";
std::fstream fh;
fh.open(fn, std::ios_base::out | std::ios_base::binary);
if(!fh)
{
logerror("ItemProtoCache: Could not write to file '%s'!",fn);
return;
}
uint32 total = session->objmgr.GetItemProtoCount();
fh.write((char*)&(uint32)ITEMPROTOTYPES_CACHE_VERSION,4);
fh.write((char*)&total,4);
uint32 counter=0;
ByteBuffer buf;
for(ItemProtoMap::iterator it = session->objmgr.GetItemProtoStorage()->begin(); it != session->objmgr.GetItemProtoStorage()->end(); it++)
{
buf.clear();
ItemProto *proto = it->second;
buf << proto->Id;
buf << proto->Class;
buf << proto->SubClass;
buf << proto->Name;
buf << proto->DisplayInfoID;
buf << proto->Quality;
buf << proto->Flags;
buf << proto->BuyPrice;
buf << proto->SellPrice;
buf << proto->InventoryType;
buf << proto->AllowableClass;
buf << proto->AllowableRace;
buf << proto->ItemLevel;
buf << proto->RequiredLevel;
buf << proto->RequiredSkill;
buf << proto->RequiredSkillRank;
buf << proto->RequiredSpell;
buf << proto->RequiredHonorRank;
buf << proto->RequiredCityRank;
buf << proto->RequiredReputationFaction;
buf << proto->RequiredReputationRank;
buf << proto->MaxCount;
buf << proto->Stackable;
buf << proto->ContainerSlots;
for(int i = 0; i < 10; i++)
{
buf << proto->ItemStat[i].ItemStatType;
buf << proto->ItemStat[i].ItemStatValue;
}
for(int i = 0; i < 5; i++)
{
buf << proto->Damage[i].DamageMin;
buf << proto->Damage[i].DamageMax;
buf << proto->Damage[i].DamageType;
}
buf << proto->Armor;
buf << proto->HolyRes;
buf << proto->FireRes;
buf << proto->NatureRes;
buf << proto->FrostRes;
buf << proto->ShadowRes;
buf << proto->ArcaneRes;
buf << proto->Delay;
buf << proto->Ammo_type;
buf << (float)proto->RangedModRange;
for(int s = 0; s < 5; s++)
{
buf << proto->Spells[s].SpellId;
buf << proto->Spells[s].SpellTrigger;
buf << proto->Spells[s].SpellCharges;
buf << proto->Spells[s].SpellCooldown;
buf << proto->Spells[s].SpellCategory;
buf << proto->Spells[s].SpellCategoryCooldown;
}
buf << proto->Bonding;
buf << proto->Description;
buf << proto->PageText;
buf << proto->LanguageID;
buf << proto->PageMaterial;
buf << proto->StartQuest;
buf << proto->LockID;
buf << proto->Material;
buf << proto->Sheath;
buf << proto->Extra;
buf << proto->Unk1; // added in 2.0.3
buf << proto->Block;
buf << proto->ItemSet;
buf << proto->MaxDurability;
buf << proto->Area;
buf << proto->Map;
buf << proto->BagFamily;
buf << proto->TotemCategory; // Added in 1.12.x client branch
for(uint32 s = 0; s < 3; s++)
{
buf << proto->Socket[s].Color;
buf << proto->Socket[s].Content;
}
buf << proto->socketBonus;
buf << proto->GemProperties;
buf << proto->ExtendedCost;
buf << proto->RequiredArenaRank;
buf << proto->RequiredDisenchantSkill;
buf << proto->ArmorDamageModifier;
//DEBUG(logdebug("ItemProtoCache: Saved %u [%s]",proto->Id, proto->Name[0].c_str()));
uint32 size = buf.size();
fh.write((char*)&size,sizeof(uint32));
fh.write((char*)buf.contents(),buf.size());
counter++;
}
fh.flush();
fh.close();
log("ItemProtoCache: Saved %u Item Prototypes",counter);
}
void CreatureTemplateCache_InsertDataToSession(WorldSession *session)
{
logdetail("CreatureTemplateCache: Loading...");
char* fn = "./cache/CreatureTemplates.cache";
std::fstream fh;
fh.open(fn, std::ios_base::in | std::ios_base::binary);
if(!fh)
{
logerror("CreatureTemplateCache: Could not open file '%s'!",fn);
return;
}
uint32 cacheversion, total, counter = 0;
try
{
fh.read((char*)&cacheversion,4);
if(cacheversion != CREATURETEMPLATES_CACHE_VERSION)
{
logerror("CreatureTemplateCache is outdated! Creating new cache.");
fh.close();
return;
}
fh.read((char*)&total,4);
logdetail("CreatureTemplateCache: %u creature templates stored",total);
uint32 datasize;
ByteBuffer buf;
for(uint32 i = 0; i < total && !fh.eof(); i++)
{
buf.clear();
fh.read((char*)&datasize,sizeof(uint32));
buf.resize(datasize);
fh.read((char*)buf.contents(),datasize);
CreatureTemplate *ct = new CreatureTemplate();
buf >> ct->entry;
buf >> ct->name;
buf >> ct->subname;
buf >> ct->flag1;
buf >> ct->type;
buf >> ct->family;
buf >> ct->rank;
buf >> ct->SpellDataId;
buf >> ct->displayid_A;
buf >> ct->displayid_H;
buf >> ct->displayid_AF;
buf >> ct->displayid_HF;
buf >> ct->RacialLeader;
if(ct->entry)
{
session->objmgr.Add(ct);
counter++;
} else
delete ct;
}
}
catch (ByteBufferException bbe)
{
logerror("ByteBuffer exception: attempt to \"%s\" %u bytes at position %u out of total %u bytes. (wpos=%u)",
bbe.action, bbe.readsize, bbe.rpos, bbe.cursize, bbe.wpos);
}
fh.close();
logdetail("CreatureTemplateCache: Loaded %u Creature Templates",counter);
}
void CreatureTemplateCache_WriteDataToCache(WorldSession *session)
{
if (!session->objmgr.GetCreatureTemplateCount())
return;
char* fn = "./cache/CreatureTemplates.cache";
std::fstream fh;
fh.open(fn, std::ios_base::out | std::ios_base::binary);
if(!fh)
{
logerror("CreatureTemplateCache: Could not write to file '%s'!",fn);
return;
}
uint32 total = session->objmgr.GetCreatureTemplateCount();
fh.write((char*)&(uint32)CREATURETEMPLATES_CACHE_VERSION,4);
fh.write((char*)&total,4);
uint32 counter=0;
ByteBuffer buf;
for(CreatureTemplateMap::iterator it = session->objmgr.GetCreatureTemplateStorage()->begin(); it != session->objmgr.GetCreatureTemplateStorage()->end(); it++)
{
buf.clear();
CreatureTemplate *ct = it->second;
buf << ct->entry;
buf << ct->name;
buf << ct->subname;
buf << ct->flag1;
buf << ct->type;
buf << ct->family;
buf << ct->rank;
buf << ct->SpellDataId;
buf << ct->displayid_A;
buf << ct->displayid_H;
buf << ct->displayid_AF;
buf << ct->displayid_HF;
buf << ct->RacialLeader;
uint32 size = buf.size();
fh.write((char*)&size,sizeof(uint32));
fh.write((char*)buf.contents(),buf.size());
counter++;
}
fh.flush();
fh.close();
log("CreatureTemplateCache: Saved %u Creature Templates",counter);
}