* added creature query & cache
* fixed crash when transforming irr to world coord, when maptile was not loaded * fixed possible bugs wtih corpse object type * removed name2-4 fields from item protos, they are useless * added IsPlayer(), IsCreature(), etc functions to Object class. TypeID check sucks. * changed item proto storage in ObjMgr to std::map instead of vector for faster lookup. * added exception handling to ByteBuffer class to prevent possible crashes on invalid read access. this also fixes possible startup crashes with corrupted item/creature cache files. * CHAT_MSG_MONSTER_SAY should work now (monster yell handled differently by MaNGOS?!) * forgot last rev: no more stair effect on terrain. thx bLuma for patch!
This commit is contained in:
parent
38cbcb026c
commit
fe86400f60
@ -98,19 +98,24 @@ DefReturnResult DefScriptPackage::SCSendChatMessage(CmdSet& Set){
|
||||
|
||||
DefReturnResult DefScriptPackage::SCsavecache(CmdSet& Set){
|
||||
((PseuInstance*)parentMethod)->SaveAllCache();
|
||||
std::stringstream str;
|
||||
if(((PseuInstance*)parentMethod)->GetWSession())
|
||||
{
|
||||
str << "Cache saved. [ ";
|
||||
str << ((PseuInstance*)parentMethod)->GetWSession()->plrNameCache.GetSize();
|
||||
str << " Playernames, ";
|
||||
str << ((PseuInstance*)parentMethod)->GetWSession()->objmgr.GetItemProtoCount();
|
||||
str << " Item Prototypes";
|
||||
str << " ]";
|
||||
if(DefScriptTools::isTrue(Set.defaultarg))
|
||||
{
|
||||
std::stringstream str;
|
||||
if(((PseuInstance*)parentMethod)->GetWSession())
|
||||
{
|
||||
str << "Cache saved. [ ";
|
||||
str << ((PseuInstance*)parentMethod)->GetWSession()->plrNameCache.GetSize();
|
||||
str << " Playernames, ";
|
||||
str << ((PseuInstance*)parentMethod)->GetWSession()->objmgr.GetItemProtoCount();
|
||||
str << " Item Prototypes, ";
|
||||
str << ((PseuInstance*)parentMethod)->GetWSession()->objmgr.GetCreatureTemplateCount();
|
||||
str << " Creature Templates";
|
||||
str << " ]";
|
||||
|
||||
((PseuInstance*)parentMethod)->GetWSession()->SendChatMessage(CHAT_MSG_SAY,0,str.str(),"");
|
||||
}
|
||||
return true;
|
||||
((PseuInstance*)parentMethod)->GetWSession()->SendChatMessage(CHAT_MSG_SAY,0,str.str(),"");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
DefReturnResult DefScriptPackage::SCemote(CmdSet& Set){
|
||||
|
||||
@ -327,6 +327,12 @@ WorldPosition SceneWorld::GetWorldPosition(void)
|
||||
|
||||
// get the current maptile and use the coords of the top-left corner as relative positions
|
||||
MapTile *tile = mapmgr->GetCurrentTile();
|
||||
if(!tile)
|
||||
{
|
||||
logerror("SceneWorld::GetWorldPosition failed, MapTile not loaded!");
|
||||
return WorldPosition();
|
||||
}
|
||||
|
||||
float mapx = tile->GetBaseX();
|
||||
float mapy = tile->GetBaseY();
|
||||
|
||||
|
||||
@ -359,6 +359,7 @@ void PseuInstance::SaveAllCache(void)
|
||||
{
|
||||
GetWSession()->plrNameCache.SaveToFile();
|
||||
ItemProtoCache_WriteDataToCache(GetWSession());
|
||||
CreatureTemplateCache_WriteDataToCache(GetWSession());
|
||||
//...
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,16 +63,16 @@ void WorldSession::SendEmote(uint32 id)
|
||||
SendWorldPacket(packet);
|
||||
}
|
||||
|
||||
void WorldSession::SendQueryItem(uint32 id, uint64 guid) // is it a guid? not sure
|
||||
void WorldSession::SendQueryItem(uint32 entry, uint64 guid) // is it a guid? not sure
|
||||
{
|
||||
if(objmgr.ItemNonExistent(id))
|
||||
if(objmgr.ItemNonExistent(entry))
|
||||
{
|
||||
logdebug("Skipped query of item %u (was marked as nonexistent before)",id);
|
||||
logdebug("Skipped query of item %u (was marked as nonexistent before)",entry);
|
||||
return;
|
||||
}
|
||||
logdebug("Sending Item query, id=%u",id);
|
||||
logdebug("Sending Item query, id=%u",entry);
|
||||
WorldPacket packet;
|
||||
packet << id << guid;
|
||||
packet << entry << guid;
|
||||
packet.SetOpcode(CMSG_ITEM_QUERY_SINGLE);
|
||||
SendWorldPacket(packet);
|
||||
}
|
||||
@ -179,7 +179,18 @@ void WorldSession::SendWhoListRequest(uint32 minlvl, uint32 maxlvl, uint32 racem
|
||||
SendWorldPacket(pkt);
|
||||
}
|
||||
|
||||
|
||||
void WorldSession::SendQueryCreature(uint32 entry, uint64 guid)
|
||||
{
|
||||
if(objmgr.CreatureNonExistent(entry))
|
||||
{
|
||||
logdebug("Skipped query of creature %u (was marked as nonexistent before)",entry);
|
||||
return;
|
||||
}
|
||||
logdebug("Sending creature query, id=%u",entry);
|
||||
WorldPacket wp(CMSG_CREATURE_QUERY,4+8);
|
||||
wp << entry << guid;
|
||||
SendWorldPacket(wp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -11,7 +11,8 @@
|
||||
#include "Item.h"
|
||||
|
||||
// increase this number whenever you change something that makes old files unusable
|
||||
uint32 ITEMPROTOTYPES_CACHE_VERSION = 0x00000002;
|
||||
uint32 ITEMPROTOTYPES_CACHE_VERSION = 3;
|
||||
uint32 CREATURETEMPLATES_CACHE_VERSION = 0;
|
||||
|
||||
PlayerNameCache::~PlayerNameCache()
|
||||
{
|
||||
@ -162,7 +163,11 @@ void ItemProtoCache_InsertDataToSession(WorldSession *session)
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 cacheversion;
|
||||
uint32 cacheversion, total;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
fh.read((char*)&cacheversion,4);
|
||||
if(cacheversion != ITEMPROTOTYPES_CACHE_VERSION)
|
||||
{
|
||||
@ -170,27 +175,24 @@ void ItemProtoCache_InsertDataToSession(WorldSession *session)
|
||||
fh.close();
|
||||
return;
|
||||
}
|
||||
fh.read((char*)&total,4);
|
||||
logdetail("ItemProtoCache: %u item prototypes stored",total);
|
||||
|
||||
uint32 datasize,counter=0,unk;
|
||||
uint32 datasize,unk, counter = 0;
|
||||
ByteBuffer buf;
|
||||
while(!fh.eof())
|
||||
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);
|
||||
if(buf.size() < datasize)
|
||||
{
|
||||
logerror("ItemProtoCache: Failed to resize ByteBuffer!");
|
||||
return;
|
||||
}
|
||||
fh.read((char*)buf.contents(),datasize);
|
||||
ItemProto *proto = new ItemProto;
|
||||
ItemProto *proto = new ItemProto();
|
||||
buf >> proto->Id;
|
||||
buf >> proto->Class;
|
||||
buf >> proto->SubClass;
|
||||
buf >> unk;
|
||||
for(uint8 i=0;i<4;i++)
|
||||
buf >> proto->Name[i];
|
||||
buf >> proto->Name;
|
||||
buf >> proto->DisplayInfoID;
|
||||
buf >> proto->Quality;
|
||||
buf >> proto->Flags;
|
||||
@ -280,13 +282,21 @@ void ItemProtoCache_InsertDataToSession(WorldSession *session)
|
||||
} 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",counter);
|
||||
logdetail("ItemProtoCache: Loaded %u Item Prototypes",total);
|
||||
}
|
||||
|
||||
void ItemProtoCache_WriteDataToCache(WorldSession *session)
|
||||
{
|
||||
if (session->objmgr.GetItemProtoCount() <= 0)
|
||||
if (!session->objmgr.GetItemProtoCount())
|
||||
return;
|
||||
|
||||
char* fn = "./cache/ItemPrototypes.cache";
|
||||
@ -297,18 +307,21 @@ void ItemProtoCache_WriteDataToCache(WorldSession *session)
|
||||
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(uint32 i=0;i<session->objmgr.GetItemProtoCount();i++)
|
||||
for(ItemProtoMap::iterator it = session->objmgr.GetItemProtoStorage()->begin(); it != session->objmgr.GetItemProtoStorage()->end(); it++)
|
||||
{
|
||||
buf.clear();
|
||||
ItemProto *proto = session->objmgr.GetItemProtoByPos(i);
|
||||
ItemProto *proto = it->second;
|
||||
buf << proto->Id;
|
||||
buf << proto->Class;
|
||||
buf << proto->SubClass;
|
||||
for(uint8 i=0;i<4;i++)
|
||||
buf << proto->Name[i];
|
||||
buf << proto->Name;
|
||||
buf << proto->DisplayInfoID;
|
||||
buf << proto->Quality;
|
||||
buf << proto->Flags;
|
||||
@ -399,3 +412,117 @@ void ItemProtoCache_WriteDataToCache(WorldSession *session)
|
||||
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.close();
|
||||
log("CreatureTemplateCache: Saved %u Creature Templates",counter);
|
||||
}
|
||||
|
||||
@ -25,4 +25,7 @@ private:
|
||||
void ItemProtoCache_InsertDataToSession(WorldSession *session);
|
||||
void ItemProtoCache_WriteDataToCache(WorldSession *session);
|
||||
|
||||
void CreatureTemplateCache_InsertDataToSession(WorldSession *session);
|
||||
void CreatureTemplateCache_WriteDataToCache(WorldSession *session);
|
||||
|
||||
#endif
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
Corpse::Corpse()
|
||||
{
|
||||
_uint32values=NULL;
|
||||
_type=TYPE_CORPSE;
|
||||
_typeid=TYPEID_CORPSE;
|
||||
_valuescount=CORPSE_END;
|
||||
|
||||
@ -6,18 +6,19 @@
|
||||
|
||||
void WorldSession::_HandleItemQuerySingleResponseOpcode(WorldPacket& recvPacket)
|
||||
{
|
||||
ItemProto *proto = new ItemProto;
|
||||
ItemProto *proto = new ItemProto();
|
||||
recvPacket >> proto->Id;
|
||||
uint8 field[64];
|
||||
uint32 unk;
|
||||
std::string s;
|
||||
memset(field,0,64);
|
||||
if(memcmp(recvPacket.contents()+sizeof(uint32),field,64))
|
||||
{
|
||||
recvPacket >> proto->Class;
|
||||
recvPacket >> proto->SubClass;
|
||||
recvPacket >> unk; // dont need that value?
|
||||
for(uint8 i=0;i<4;i++)
|
||||
recvPacket >> proto->Name[i];
|
||||
recvPacket >> proto->Name;
|
||||
recvPacket >> s >> s >> s; // strip name1-4
|
||||
recvPacket >> proto->DisplayInfoID;
|
||||
recvPacket >> proto->Quality;
|
||||
recvPacket >> proto->Flags;
|
||||
@ -98,8 +99,10 @@ void WorldSession::_HandleItemQuerySingleResponseOpcode(WorldPacket& recvPacket)
|
||||
recvPacket >> proto->ArmorDamageModifier;
|
||||
|
||||
logdetail("Got Item Info: Id=%u Name='%s' ReqLevel=%u Armor=%u Desc='%s'",
|
||||
proto->Id, proto->Name[0].c_str(), proto->RequiredLevel, proto->Armor, proto->Description.c_str());
|
||||
proto->Id, proto->Name.c_str(), proto->RequiredLevel, proto->Armor, proto->Description.c_str());
|
||||
objmgr.Add(proto);
|
||||
objmgr.AssignNameToObj(proto->Id, TYPEID_ITEM, proto->Name);
|
||||
objmgr.AssignNameToObj(proto->Id, TYPEID_CONTAINER, proto->Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -354,7 +354,7 @@ struct ItemProto
|
||||
uint32 Id;
|
||||
uint32 Class;
|
||||
uint32 SubClass;
|
||||
std::string Name[4];
|
||||
std::string Name;
|
||||
uint32 DisplayInfoID;
|
||||
uint32 Quality;
|
||||
uint32 Flags;
|
||||
|
||||
@ -22,9 +22,13 @@ void ObjMgr::SetInstance(PseuInstance *i)
|
||||
|
||||
void ObjMgr::RemoveAll(void)
|
||||
{
|
||||
for(ItemProtoList::iterator i = _iproto.begin(); i!=_iproto.end(); i++)
|
||||
for(ItemProtoMap::iterator i = _iproto.begin(); i!=_iproto.end(); i++)
|
||||
{
|
||||
delete *i;
|
||||
delete i->second;
|
||||
}
|
||||
for(CreatureTemplateMap::iterator i = _creature_templ.begin(); i!=_creature_templ.end(); i++)
|
||||
{
|
||||
delete i->second;
|
||||
}
|
||||
while(_obj.size())
|
||||
{
|
||||
@ -45,6 +49,8 @@ void ObjMgr::Remove(uint64 guid)
|
||||
}
|
||||
}
|
||||
|
||||
// -- Object part --
|
||||
|
||||
void ObjMgr::Add(Object *o)
|
||||
{
|
||||
_obj[o->GetGUID()] = o;
|
||||
@ -64,24 +70,35 @@ Object *ObjMgr::GetObj(uint64 guid)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// iterate over all objects and assign a name to all matching the entry and typemask
|
||||
uint32 ObjMgr::AssignNameToObj(uint32 entry, uint8 type, std::string name)
|
||||
{
|
||||
uint32 changed = 0;
|
||||
for(ObjectMap::iterator it = _obj.begin(); it != _obj.end(); it++)
|
||||
{
|
||||
if(it->second->GetEntry() && (it->second->GetTypeId() == type))
|
||||
{
|
||||
it->second->SetName(name);
|
||||
changed++;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
// -- Item part --
|
||||
|
||||
void ObjMgr::Add(ItemProto *proto)
|
||||
{
|
||||
_iproto.push_back(proto);
|
||||
_iproto[proto->Id] = proto;
|
||||
}
|
||||
|
||||
ItemProto *ObjMgr::GetItemProto(uint32 entry)
|
||||
{
|
||||
for(ItemProtoList::iterator i = _iproto.begin(); i!=_iproto.end(); i++)
|
||||
if((*i)->Id == entry)
|
||||
return *i;
|
||||
if(_iproto.find(entry) != _iproto.end())
|
||||
return _iproto[entry];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ItemProto *ObjMgr::GetItemProtoByPos(uint32 pos)
|
||||
{
|
||||
return _iproto[pos];
|
||||
}
|
||||
|
||||
void ObjMgr::AddNonexistentItem(uint32 id)
|
||||
{
|
||||
_noitem.insert(id);
|
||||
@ -92,6 +109,32 @@ bool ObjMgr::ItemNonExistent(uint32 id)
|
||||
return _noitem.find(id) != _noitem.end();
|
||||
}
|
||||
|
||||
// -- Creature part --
|
||||
|
||||
void ObjMgr::Add(CreatureTemplate *cr)
|
||||
{
|
||||
_creature_templ[cr->entry] = cr;
|
||||
}
|
||||
|
||||
CreatureTemplate *ObjMgr::GetCreatureTemplate(uint32 entry)
|
||||
{
|
||||
if(_creature_templ.find(entry) != _creature_templ.end())
|
||||
return _creature_templ[entry];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ObjMgr::AddNonexistentCreature(uint32 id)
|
||||
{
|
||||
_nocreature.insert(id);
|
||||
}
|
||||
|
||||
bool ObjMgr::CreatureNonExistent(uint32 id)
|
||||
{
|
||||
return _nocreature.find(id) != _nocreature.end();
|
||||
}
|
||||
|
||||
// -- misc part --
|
||||
|
||||
void ObjMgr::AddRequestedPlayerGUID(uint32 loguid)
|
||||
{
|
||||
_reqpnames.insert(loguid);
|
||||
|
||||
@ -3,10 +3,11 @@
|
||||
|
||||
#include "common.h"
|
||||
#include <set>
|
||||
#include "Object.h"
|
||||
#include "Item.h"
|
||||
#include "Unit.h"
|
||||
|
||||
typedef std::vector<ItemProto*> ItemProtoList;
|
||||
typedef std::map<uint32,ItemProto*> ItemProtoMap;
|
||||
typedef std::map<uint32,CreatureTemplate*> CreatureTemplateMap;
|
||||
typedef std::map<uint64,Object*> ObjectMap;
|
||||
|
||||
class PseuInstance;
|
||||
@ -22,13 +23,23 @@ public:
|
||||
// Item Prototype functions
|
||||
uint32 GetItemProtoCount(void) { return _iproto.size(); }
|
||||
ItemProto *GetItemProto(uint32);
|
||||
ItemProto *GetItemProtoByPos(uint32);
|
||||
void Add(ItemProto*);
|
||||
ItemProtoMap *GetItemProtoStorage(void) { return &_iproto; }
|
||||
|
||||
// nonexistent items handler
|
||||
void AddNonexistentItem(uint32);
|
||||
bool ItemNonExistent(uint32);
|
||||
|
||||
// Creature template functions
|
||||
uint32 GetCreatureTemplateCount(void) { return _creature_templ.size(); }
|
||||
CreatureTemplate *GetCreatureTemplate(uint32);
|
||||
void Add(CreatureTemplate*);
|
||||
CreatureTemplateMap *GetCreatureTemplateStorage(void) { return &_creature_templ; }
|
||||
|
||||
// nonexistent creatures handler
|
||||
void AddNonexistentCreature(uint32);
|
||||
bool CreatureNonExistent(uint32);
|
||||
|
||||
// player names related
|
||||
void AddRequestedPlayerGUID(uint32);
|
||||
bool IsRequestedPlayerGUID(uint32);
|
||||
@ -41,12 +52,15 @@ public:
|
||||
void Remove(uint64); // remove all objects with that guid (should be only 1 object in total anyway)
|
||||
Object *GetObj(uint64 guid);
|
||||
inline uint32 GetObjectCount(void) { return _obj.size(); }
|
||||
uint32 AssignNameToObj(uint32 entry, uint8 type, std::string name);
|
||||
|
||||
private:
|
||||
ItemProtoList _iproto;
|
||||
ItemProtoMap _iproto;
|
||||
CreatureTemplateMap _creature_templ;
|
||||
ObjectMap _obj;
|
||||
std::set<uint32> _noitem;
|
||||
std::set<uint32> _reqpnames;
|
||||
std::set<uint32> _nocreature;
|
||||
PseuInstance *_instance;
|
||||
|
||||
};
|
||||
|
||||
@ -8,7 +8,7 @@ Object::Object()
|
||||
_uint32values=NULL;
|
||||
_type=TYPE_OBJECT;
|
||||
_typeid=TYPEID_OBJECT;
|
||||
_valuescount=0; // base class. this value will be set by derived classes
|
||||
_valuescount=OBJECT_END; // base class. this value will be set by derived classes
|
||||
}
|
||||
|
||||
Object::~Object()
|
||||
|
||||
@ -9,7 +9,7 @@ enum TYPE
|
||||
{
|
||||
TYPE_OBJECT = 1,
|
||||
TYPE_ITEM = 2,
|
||||
TYPE_CONTAINER = 6,
|
||||
TYPE_CONTAINER = 6, // a container is ALWAYS an item!
|
||||
TYPE_UNIT = 8,
|
||||
TYPE_PLAYER = 16,
|
||||
TYPE_GAMEOBJECT = 32,
|
||||
@ -45,7 +45,14 @@ public:
|
||||
|
||||
inline const uint8 GetTypeId() { return _typeid; }
|
||||
inline const uint8 GetTypeMask() { return _type; }
|
||||
inline bool isType(uint8 mask) { return (mask & _type) ? true : false; }
|
||||
inline bool IsType(uint8 mask) { return (mask & _type) ? true : false; }
|
||||
inline bool IsPlayer(void) { return _typeid == TYPEID_PLAYER; } // specific
|
||||
inline bool IsUnit(void) { return _type & TYPE_UNIT; } // generic (unit = creature or player)
|
||||
inline bool IsCreature(void) { return IsUnit() && !IsPlayer(); } // specific
|
||||
inline bool IsItem(void) { return _type & TYPE_ITEM; } // generic (item or container)
|
||||
inline bool IsContainer(void) { return _typeid == TYPEID_CONTAINER; } // specific
|
||||
inline bool IsCorpse(void) { return _typeid == TYPEID_CORPSE; } // specific
|
||||
inline bool IsDynObject(void) { return _typeid == TYPEID_DYNAMICOBJECT; } // specific
|
||||
inline const uint32 GetUInt32Value( uint16 index ) const
|
||||
{
|
||||
return _uint32values[ index ];
|
||||
@ -73,6 +80,9 @@ public:
|
||||
_uint32values[ index ] = value;
|
||||
}
|
||||
|
||||
inline void SetName(std::string name) { _name = name; }
|
||||
inline std::string GetName(void) { return _name; }
|
||||
|
||||
void Create(uint64 guid);
|
||||
|
||||
protected:
|
||||
@ -87,6 +97,7 @@ protected:
|
||||
};
|
||||
uint8 _type;
|
||||
uint8 _typeid;
|
||||
std::string _name;
|
||||
};
|
||||
|
||||
class WorldObject : public Object
|
||||
@ -99,13 +110,11 @@ public:
|
||||
inline float GetY(void) { return _y; }
|
||||
inline float GetZ(void) { return _z; }
|
||||
inline float GetO(void) { return _o; }
|
||||
inline void SetName(std::string name) { _name = name; }
|
||||
inline std::string GetName(void) { return _name; }
|
||||
|
||||
protected:
|
||||
WorldObject();
|
||||
float _x,_y,_z,_o; // coords, orientation
|
||||
uint16 _m; // map
|
||||
std::string _name;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -41,6 +41,28 @@ enum UnitFlags
|
||||
UNIT_FLAG_SHEATHE = 0x40000000
|
||||
};
|
||||
|
||||
struct CreatureTemplate
|
||||
{
|
||||
uint32 entry;
|
||||
std::string name;
|
||||
std::string subname;
|
||||
std::string directions;
|
||||
uint32 flag1;
|
||||
uint32 type;
|
||||
uint32 family;
|
||||
uint32 rank;
|
||||
//uint32 unk1;
|
||||
uint32 SpellDataId;
|
||||
uint32 displayid_A;
|
||||
uint32 displayid_H;
|
||||
uint32 displayid_AF;
|
||||
uint32 displayid_HF;
|
||||
//float unkf1;
|
||||
//float unkf2;
|
||||
uint8 RacialLeader;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class Unit : public WorldObject
|
||||
|
||||
@ -366,10 +366,14 @@ void WorldSession::_QueryObjectInfo(uint64 guid)
|
||||
case TYPEID_CONTAINER:
|
||||
{
|
||||
ItemProto *proto = objmgr.GetItemProto(obj->GetEntry());
|
||||
if(!proto)
|
||||
if(proto)
|
||||
{
|
||||
obj->SetName(proto->Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
logdebug("Found unknown item: GUID="I64FMT" entry=%u",obj->GetGUID(),obj->GetEntry());
|
||||
SendQueryItem(obj->GetEntry(),obj->GetGUID()); // not sure if sending GUID is correct
|
||||
SendQueryItem(obj->GetEntry(),guid); // not sure if sending GUID is correct
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -378,11 +382,20 @@ void WorldSession::_QueryObjectInfo(uint64 guid)
|
||||
std::string name = GetOrRequestPlayerName(obj->GetGUID());
|
||||
if(!name.empty())
|
||||
{
|
||||
((WorldObject*)obj)->SetName(name);
|
||||
obj->SetName(name);
|
||||
}
|
||||
// else: name will be set when server answers (_HandleNameQueryResponseOpcode)
|
||||
break;
|
||||
}
|
||||
case TYPEID_UNIT: // checked after player; this one here should cover creatures only
|
||||
{
|
||||
CreatureTemplate *ct = objmgr.GetCreatureTemplate(obj->GetEntry());
|
||||
if(ct)
|
||||
obj->SetName(ct->name);
|
||||
else
|
||||
SendQueryCreature(obj->GetEntry(),guid);
|
||||
break;
|
||||
}
|
||||
//case...
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,6 +88,7 @@ void WorldSession::_LoadCache(void)
|
||||
logdetail("Loading Cache...");
|
||||
plrNameCache.ReadFromFile(); // load names/guids of known players
|
||||
ItemProtoCache_InsertDataToSession(this);
|
||||
CreatureTemplateCache_InsertDataToSession(this);
|
||||
//...
|
||||
}
|
||||
|
||||
@ -190,6 +191,13 @@ void WorldSession::HandleWorldPacket(WorldPacket *packet)
|
||||
}
|
||||
|
||||
}
|
||||
catch (ByteBufferException bbe)
|
||||
{
|
||||
logerror("WorldSession: ByteBufferException");
|
||||
logerror("ByteBuffer reported: 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);
|
||||
throw;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
logerror("Exception while handling opcode %u!",packet->GetOpcode());
|
||||
@ -253,6 +261,7 @@ OpcodeHandler *WorldSession::_GetOpcodeHandlerTable() const
|
||||
{SMSG_MOTD, &WorldSession::_HandleMotdOpcode},
|
||||
{SMSG_NOTIFICATION, &WorldSession::_HandleNotificationOpcode},
|
||||
{SMSG_WHO, &WorldSession::_HandleWhoOpcode},
|
||||
{SMSG_CREATURE_QUERY_RESPONSE, &WorldSession::_HandleCreatureQueryResponseOpcode},
|
||||
|
||||
// table termination
|
||||
{ 0, NULL }
|
||||
@ -532,13 +541,24 @@ void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket)
|
||||
uint32 lang=0;
|
||||
uint64 source_guid=0;
|
||||
uint64 target_guid=0;
|
||||
uint64 npc_guid=0; // for CHAT_MSG_MONSTER_SAY
|
||||
uint32 msglen=0;
|
||||
uint32 unk=0;
|
||||
uint32 npc_name_len;
|
||||
std::string npc_name;
|
||||
std::string msg,channel="";
|
||||
bool isCmd=false;
|
||||
|
||||
recvPacket >> type >> lang;
|
||||
|
||||
if(lang == CHAT_MSG_MONSTER_SAY)
|
||||
{
|
||||
recvPacket >> npc_guid;
|
||||
recvPacket >> unk;
|
||||
recvPacket >> npc_name_len;
|
||||
recvPacket >> npc_name;
|
||||
}
|
||||
|
||||
if(lang == LANG_ADDON && GetInstance()->GetConf()->skipaddonchat)
|
||||
return;
|
||||
|
||||
@ -551,18 +571,24 @@ void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket)
|
||||
|
||||
std::string langname = GetDBMgr().GetLangName(lang);
|
||||
const char* ln = langname.c_str();
|
||||
std::string name;
|
||||
|
||||
std::string plrname;
|
||||
if(source_guid)
|
||||
if(type == CHAT_MSG_MONSTER_SAY)
|
||||
{
|
||||
plrname = GetOrRequestPlayerName(source_guid);
|
||||
if(plrname.empty())
|
||||
name = npc_name;
|
||||
source_guid = npc_guid;
|
||||
}
|
||||
|
||||
if(source_guid && IS_PLAYER_GUID(source_guid))
|
||||
{
|
||||
name = GetOrRequestPlayerName(source_guid);
|
||||
if(name.empty())
|
||||
{
|
||||
_DelayWorldPacket(recvPacket, GetLagMS() * 1.2f); // guess time how long it will take until we got player name from the server
|
||||
return; // handle later
|
||||
}
|
||||
}
|
||||
GetInstance()->GetScripts()->variables.Set("@thismsg_name",plrname);
|
||||
GetInstance()->GetScripts()->variables.Set("@thismsg_name",name);
|
||||
GetInstance()->GetScripts()->variables.Set("@thismsg",toString(target_guid));
|
||||
|
||||
|
||||
@ -575,39 +601,43 @@ void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket)
|
||||
}
|
||||
else if (type==CHAT_MSG_WHISPER )
|
||||
{
|
||||
logcustom(0,WHITE,"WHISP: %s [%s]: %s",plrname.c_str(),ln,msg.c_str());
|
||||
logcustom(0,WHITE,"WHISP: %s [%s]: %s",name.c_str(),ln,msg.c_str());
|
||||
}
|
||||
else if (type==CHAT_MSG_CHANNEL )
|
||||
{
|
||||
logcustom(0,WHITE,"CHANNEL: [%s]: %s [%s]: %s",channel.c_str(),plrname.c_str(),ln,msg.c_str());
|
||||
logcustom(0,WHITE,"CHANNEL: [%s]: %s [%s]: %s",channel.c_str(),name.c_str(),ln,msg.c_str());
|
||||
}
|
||||
else if (type==CHAT_MSG_SAY )
|
||||
{
|
||||
logcustom(0,WHITE,"CHAT: %s [%s]: %s",plrname.c_str(),ln,msg.c_str());
|
||||
logcustom(0,WHITE,"CHAT: %s [%s]: %s",name.c_str(),ln,msg.c_str());
|
||||
}
|
||||
else if (type==CHAT_MSG_YELL )
|
||||
{
|
||||
logcustom(0,WHITE,"CHAT: %s yells [%s]: %s ",plrname.c_str(),ln,msg.c_str());
|
||||
logcustom(0,WHITE,"CHAT: %s yells [%s]: %s ",name.c_str(),ln,msg.c_str());
|
||||
}
|
||||
else if (type==CHAT_MSG_WHISPER_INFORM )
|
||||
{
|
||||
logcustom(0,WHITE,"TO %s [%s]: %s",plrname.c_str(),ln,msg.c_str());
|
||||
logcustom(0,WHITE,"TO %s [%s]: %s",name.c_str(),ln,msg.c_str());
|
||||
}
|
||||
else if (type==CHAT_MSG_GUILD )
|
||||
{
|
||||
logcustom(0,WHITE,"GUILD: %s [%s]: %s",plrname.c_str(),ln,msg.c_str());
|
||||
logcustom(0,WHITE,"GUILD: %s [%s]: %s",name.c_str(),ln,msg.c_str());
|
||||
}
|
||||
else if (type==CHAT_MSG_PARTY )
|
||||
{
|
||||
logcustom(0,WHITE,"PARTY: %s [%s]: %s",plrname.c_str(),ln,msg.c_str());
|
||||
logcustom(0,WHITE,"PARTY: %s [%s]: %s",name.c_str(),ln,msg.c_str());
|
||||
}
|
||||
else if (type==CHAT_MSG_EMOTE )
|
||||
{
|
||||
logcustom(0,WHITE,"EMOTE [%s]: %s %s",ln,plrname.c_str(),msg.c_str());
|
||||
logcustom(0,WHITE,"EMOTE [%s]: %s %s",ln,name.c_str(),msg.c_str());
|
||||
}
|
||||
else if (type==CHAT_MSG_MONSTER_SAY)
|
||||
{
|
||||
logcustom(0,WHITE,"NPC: %s [%s]: %s",name.c_str(),ln,msg.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
logcustom(0,WHITE,"UNK CHAT TYPE (%u): %s [%s]: %s",type,plrname.c_str(),ln,msg.c_str());
|
||||
logcustom(0,WHITE,"UNK CHAT TYPE (%u): %s [%s]: %s",type,name.c_str(),ln,msg.c_str());
|
||||
}
|
||||
|
||||
if(target_guid!=GetGuid() && msg.length()>1 && msg.at(0)=='-' && GetInstance()->GetConf()->allowgamecmd)
|
||||
@ -652,12 +682,12 @@ void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket)
|
||||
|
||||
if(isCmd)
|
||||
{
|
||||
GetInstance()->GetScripts()->variables.Set("@thiscmd_name",plrname);
|
||||
GetInstance()->GetScripts()->variables.Set("@thiscmd_name",name);
|
||||
GetInstance()->GetScripts()->variables.Set("@thiscmd",toString(target_guid));
|
||||
std::string lin=msg.substr(1,msg.length()-1);
|
||||
try
|
||||
{
|
||||
GetInstance()->GetScripts()->My_Run(lin,plrname);
|
||||
GetInstance()->GetScripts()->My_Run(lin,name);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@ -669,7 +699,7 @@ void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket)
|
||||
// TODO: remove this block soon, its obsoelete and has to be done via scripting!
|
||||
if(type==CHAT_MSG_WHISPER && (!isCmd) && target_guid!=GetGuid())
|
||||
{
|
||||
GetInstance()->GetScripts()->variables.Set("@thiswhisper_name",plrname);
|
||||
GetInstance()->GetScripts()->variables.Set("@thiswhisper_name",name);
|
||||
GetInstance()->GetScripts()->variables.Set("@thiswhisper",toString(target_guid));
|
||||
GetInstance()->GetScripts()->variables.Set("@thiswhisper_lang",toString((uint64)lang));
|
||||
GetInstance()->GetScripts()->RunScript("_onwhisper",NULL);
|
||||
@ -860,11 +890,11 @@ void WorldSession::_HandleChannelNotifyOpcode(WorldPacket& recvPacket)
|
||||
void WorldSession::_HandleCastResultOpcode(WorldPacket& recvPacket)
|
||||
{
|
||||
uint32 spellid,otherr = 0;
|
||||
uint8 result;
|
||||
recvPacket >> spellid >> result;
|
||||
if (recvPacket.rpos()+1 < recvPacket.size())
|
||||
uint8 result, castCount;
|
||||
recvPacket >> spellid >> result >> castCount;
|
||||
if (recvPacket.rpos()+sizeof(uint32) <= recvPacket.size())
|
||||
recvPacket >> otherr;
|
||||
logdetail("Cast of spell %u failed. result=%u, additional info=%u",spellid,result,otherr);
|
||||
logdetail("Cast of spell %u failed. result=%u, cast count=%u, additional info=%u",spellid,result,castCount,otherr);
|
||||
}
|
||||
|
||||
void WorldSession::_HandleCastSuccessOpcode(WorldPacket& recvPacket)
|
||||
@ -873,9 +903,18 @@ void WorldSession::_HandleCastSuccessOpcode(WorldPacket& recvPacket)
|
||||
uint64 casterGuid;
|
||||
|
||||
casterGuid = recvPacket.GetPackedGuid();
|
||||
|
||||
recvPacket >> spellId;
|
||||
logdetail("Cast of spell %u successful.",spellId);
|
||||
|
||||
if (GetMyChar()->GetGUID() == casterGuid)
|
||||
logdetail("Cast of spell %u successful.",spellId);
|
||||
else
|
||||
{
|
||||
Object *caster = objmgr.GetObj(casterGuid);
|
||||
if(caster)
|
||||
logdetail("%s casted spell %u", caster->GetName(), spellId);
|
||||
else
|
||||
logerror("Caster of spell %u (GUID "I64FMT") is unknown object!");
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::_HandleInitialSpellsOpcode(WorldPacket& recvPacket)
|
||||
@ -916,24 +955,33 @@ void WorldSession::_HandleChannelListOpcode(WorldPacket& recvPacket)
|
||||
|
||||
void WorldSession::_HandleEmoteOpcode(WorldPacket& recvPacket)
|
||||
{
|
||||
std::string plrname;
|
||||
std::string name;
|
||||
uint32 anim; // animation id?
|
||||
uint64 guid; // guid of the unit performing the emote
|
||||
recvPacket >> anim >> guid;
|
||||
|
||||
// TODO: check if the emote came from a player or a mob, and query mob name if it was a mob
|
||||
if(guid)
|
||||
{
|
||||
plrname = GetOrRequestPlayerName(guid);
|
||||
if(plrname.empty())
|
||||
Object *o = objmgr.GetObj(guid);
|
||||
if(o)
|
||||
{
|
||||
_DelayWorldPacket(recvPacket, GetLagMS() * 1.2f);
|
||||
return;
|
||||
name = o->GetName();
|
||||
}
|
||||
if(name.empty())
|
||||
{
|
||||
if(o->IsPlayer())
|
||||
{
|
||||
name = GetOrRequestPlayerName(guid);
|
||||
if(name.empty())
|
||||
{
|
||||
_DelayWorldPacket(recvPacket, GetLagMS() * 1.2f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: check for mobs
|
||||
logdebug(I64FMT " / %s performing emote; anim=%u",guid,plrname.c_str(),anim);
|
||||
logdebug(I64FMT " / %s performing emote; anim=%u",guid,name.c_str(),anim);
|
||||
|
||||
// TODO: show emote in GUI :P
|
||||
}
|
||||
@ -1110,8 +1158,60 @@ void WorldSession::_HandleWhoOpcode(WorldPacket& recvPacket)
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::_HandleCreatureQueryResponseOpcode(WorldPacket& recvPacket)
|
||||
{
|
||||
uint32 entry;
|
||||
recvPacket >> entry;
|
||||
if( (!entry) || (entry & 0x80000000) ) // last bit marks that entry is invalid / does not exist on server side
|
||||
{
|
||||
uint32 real_entry = entry & ~0x80000000;
|
||||
logerror("Creature %u does not exist!", real_entry);
|
||||
objmgr.AddNonexistentCreature(real_entry);
|
||||
return;
|
||||
}
|
||||
|
||||
CreatureTemplate *ct = new CreatureTemplate();
|
||||
std::string s;
|
||||
uint32 unk;
|
||||
float unkf;
|
||||
ct->entry = entry;
|
||||
recvPacket >> ct->name;
|
||||
recvPacket >> s;
|
||||
recvPacket >> s;
|
||||
recvPacket >> s;
|
||||
recvPacket >> ct->subname;
|
||||
recvPacket >> ct->directions;
|
||||
recvPacket >> ct->flag1;
|
||||
recvPacket >> ct->type;
|
||||
recvPacket >> ct->family;
|
||||
recvPacket >> ct->rank;
|
||||
recvPacket >> unk;
|
||||
recvPacket >> ct->SpellDataId;
|
||||
recvPacket >> ct->displayid_A;
|
||||
recvPacket >> ct->displayid_H;
|
||||
recvPacket >> ct->displayid_AF;
|
||||
recvPacket >> ct->displayid_HF;
|
||||
recvPacket >> unkf;
|
||||
recvPacket >> unkf;
|
||||
recvPacket >> ct->RacialLeader;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "Got info for creature " << entry << ":" << ct->name;
|
||||
if(!ct->subname.empty())
|
||||
ss << " <" << ct->subname << ">";
|
||||
ss << " type " << ct->type;
|
||||
ss << " flags " << ct->flag1;
|
||||
ss << " models " << ct->displayid_A << "/" << ct->displayid_H;
|
||||
logdetail("%s",ss.str().c_str());
|
||||
|
||||
objmgr.Add(ct);
|
||||
objmgr.AssignNameToObj(entry, TYPEID_UNIT, ct->name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TODO: delete world on LogoutComplete once implemented
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -76,10 +76,11 @@ public:
|
||||
void SendQueryPlayerName(uint64 guid);
|
||||
void SendPing(uint32);
|
||||
void SendEmote(uint32);
|
||||
void SendQueryItem(uint32, uint64);
|
||||
void SendQueryItem(uint32 id, uint64 guid = 0);
|
||||
void SendSetSelection(uint64);
|
||||
void SendCastSpell(uint32 spellid, bool nocheck=false);
|
||||
void SendWhoListRequest(uint32 minlvl=0, uint32 maxlvl=100, uint32 racemask=-1, uint32 classmask=-1, std::string name="", std::string guildname="", std::vector<uint32> *zonelist=NULL, std::vector<std::string> *strlist=NULL);
|
||||
void SendQueryCreature(uint32 entry, uint64 guid = 0);
|
||||
|
||||
void HandleWorldPacket(WorldPacket*);
|
||||
|
||||
@ -127,6 +128,7 @@ private:
|
||||
void _HandleMotdOpcode(WorldPacket& recvPacket);
|
||||
void _HandleNotificationOpcode(WorldPacket& recvPacket);
|
||||
void _HandleWhoOpcode(WorldPacket& recvPacket);
|
||||
void _HandleCreatureQueryResponseOpcode(WorldPacket& recvPacket);
|
||||
|
||||
// helper functions to keep SMSG_(COMPRESSED_)UPDATE_OBJECT easy to handle
|
||||
void _MovementUpdate(uint8 objtypeid, uint64 guid, WorldPacket& recvPacket); // Helper for _HandleUpdateObjectOpcode
|
||||
|
||||
@ -23,6 +23,21 @@
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
class ByteBufferException
|
||||
{
|
||||
public:
|
||||
ByteBufferException(const char *act, uint32 rp, uint32 wp, uint32 rs, uint32 cs)
|
||||
{
|
||||
action = act;
|
||||
rpos = rp;
|
||||
wpos = wp;
|
||||
readsize = rs;
|
||||
cursize = cs;
|
||||
}
|
||||
uint32 rpos, wpos, readsize, cursize;
|
||||
const char *action;
|
||||
};
|
||||
|
||||
class ByteBuffer
|
||||
{
|
||||
public:
|
||||
@ -188,6 +203,8 @@ class ByteBuffer
|
||||
};
|
||||
template <typename T> T read(size_t pos) const
|
||||
{
|
||||
if(pos + sizeof(T) > size())
|
||||
throw ByteBufferException("read", pos, _wpos, sizeof(T), size());
|
||||
return *((T*)&_storage[pos]);
|
||||
}
|
||||
|
||||
@ -199,7 +216,7 @@ class ByteBuffer
|
||||
}
|
||||
else
|
||||
{
|
||||
throw error();
|
||||
throw ByteBufferException("read-into", _rpos, _wpos, len, size());
|
||||
}
|
||||
_rpos += len;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user