* delay more packets with missing names

* fixed problem with player name request looping
* cleaned up channels in _enterworld.def
* added MemoryDataHolder namespace, but not using it for now. will come handy in future (multi-instancing). UNTESTED yet!
This commit is contained in:
false_genesis 2008-01-05 17:58:43 +00:00
parent 40cef66995
commit 442670af16
10 changed files with 249 additions and 46 deletions

View File

@ -21,11 +21,10 @@ SAY [${@version_short}] login successful.
EMOTE 126
// join some channels...
//JOINCHANNEL generalchat
//JOINCHANNEL help
//JOINCHANNEL tradee
//listchannel generalchat
// ...
JOINCHANNEL General
JOINCHANNEL LookingForGroup
// and a custom channel
JOINCHANNEL generlachat
// Spell 836 = LoginEffect
CASTSPELL 836

View File

@ -0,0 +1,143 @@
#include <fstream>
#include "MemoryDataHolder.h"
#include "DefScript/TypeStorage.h"
namespace MemoryDataHolder
{
class DataLoaderRunnable;
ZThread::FastMutex mutex;
TypeStorage<uint8*> storage;
TypeStorage<DataLoaderRunnable> loaders;
// instances of this class MUST be created with new-operator, or Destroy() will cause a crash!
class DataLoaderRunnable : public ZThread::Runnable
{
public:
DataLoaderRunnable()
{
_buf = NULL;
_threaded = false;
}
// the threaded part
void run()
{
uint32 size = GetFileSize(_name.c_str());
// couldnt open file if size is 0
if(!size)
{
logerror("DataLoaderRunnable: Error opening file: '%s'",_name.c_str());
DoCallbacks(false); // call callback func, 'false' to indicate file coulsnt be loaded
Destroy();
return;
}
_buf = new uint8[size];
std::ifstream fh;
fh.open(_name.c_str(), std::ios_base::in | std::ios_base::binary);
if(!fh.is_open())
{
logerror("DataLoaderRunnable: Error opening file: '%s'",_name.c_str());
delete _buf;
_buf = NULL;
DoCallbacks(false);
Destroy();
return;
}
fh.read((char*)_buf,size);
fh.close();
storage.Assign(_name,&_buf);
loaders.UnlinkByPtr(this); // must be unlinked after the file is fully loaded, but before the callbacks are processed!
DoCallbacks(true);
Destroy();
}
inline void AddCallback(callback_func func, void *ptr = NULL)
{
_callbacks[func] = ptr;
}
inline void SetName(std::string name)
{
_name = name;
}
// if this class has done its work, delete self
inline void Destroy(void)
{
delete this;
}
inline uint8 *GetBuf(void)
{
return _buf;
}
inline void DoCallbacks(bool success = true)
{
for(std::map<callback_func,void*>::iterator it = _callbacks.begin(); it != _callbacks.end(); it++)
{
(*(it->first))(it->second,success);
}
}
inline void SetThreaded(bool t)
{
_threaded = t;
}
inline bool IsThreaded(void)
{
return _threaded;
}
inline bool HasCallbackFunc(callback_func f)
{
return _callbacks.find(f) != _callbacks.end();
}
private:
std::string _name;
std::map<callback_func, void*> _callbacks;
uint8 *_buf;
bool _threaded;
};
uint8 *GetFile(std::string s, bool threaded = false, callback_func func = NULL,void *ptr = NULL)
{
mutex.acquire(); // we need excusive access, other threads might unload the requested file during checking
if(uint8 **buf = storage.GetNoCreate(s))
{
// the file was requested some other time, is still present in memory and the pointer can simply be returned
mutex.release(); // everything ok, mutex can be unloaded safely before returning
return *buf;
}
else
{
DataLoaderRunnable *r = loaders.GetNoCreate(s);
if(r == NULL)
{
// no loader thread is working on that file...
r = new DataLoaderRunnable();
loaders.Assign(s,r);
r->AddCallback(func,ptr); // not threadsafe!
// after assigning/registering a new loader to the file, the mutex can be released safely
mutex.release();
r->SetName(s);
r->SetThreaded(threaded);
if(threaded)
{
ZThread::Thread t(r); // start thread
}
else
{
r->run(); // will exit after the whole file is loaded and the (one) callback is run
return r->GetBuf();
}
}
else // if a loader is already existing, add callbacks to that loader.
{
r->AddCallback(func,ptr);
mutex.release();
}
}
return NULL;
}
};

View File

@ -0,0 +1,14 @@
#ifndef MEMORYDATAHOLDER_H
#define MEMORYDATAHOLDER_H
#include "common.h"
namespace MemoryDataHolder
{
typedef void (*callback_func)(void*,bool);
uint8 *GetFile(std::string&,bool,callback_func,void*);
};
#endif

View File

@ -137,12 +137,13 @@ void Channel::HandleNotifyOpcode(WorldPacket &packet)
// Player joined channel you are on
case JOINED:
packet >> guid;
if(guid){
name = _worldSession->plrNameCache.GetName(guid);
if(guid)
{
name = _worldSession->GetOrRequestPlayerName(guid);
if (name.empty())
{
_worldSession->SendQueryPlayerName(guid);
name = "Unknown Entity";
_worldSession->_DelayWorldPacket(packet,_worldSession->GetLagMS() * 1.2f);
return;
}
}
@ -152,12 +153,13 @@ void Channel::HandleNotifyOpcode(WorldPacket &packet)
// Player leaved channel you are on
case LEFT:
packet >> guid;
if(guid){
name = _worldSession->plrNameCache.GetName(guid);
if(guid)
{
name = _worldSession->GetOrRequestPlayerName(guid);
if (name.empty())
{
_worldSession->SendQueryPlayerName(guid);
name = "Unknown Entity";
_worldSession->_DelayWorldPacket(packet,_worldSession->GetLagMS() * 1.2f);
return;
}
}
@ -222,28 +224,32 @@ void Channel::HandleListRequest(WorldPacket& recvPacket)
std::string name;
recvPacket >> unk >> name >> flags >> size;
// store list of GUIDs in: @ChannelList
DefList *l = _worldSession->GetInstance()->GetScripts()->lists.Get("@ChannelList");
l->clear();
for(uint32 i = 0; i < size; i++)
{
recvPacket >> guid >> mode;
cpl[guid] = mode;
l->push_back(DefScriptTools::toString(guid));
// all player names in this packet must be known before
if(_worldSession->GetOrRequestPlayerName(guid).empty())
{
_worldSession->_DelayWorldPacket(recvPacket, _worldSession->GetLagMS() * 1.2f);
return;
}
cpl[guid] = mode;
}
// store list of GUIDs in: @ChannelList - see below
DefList *l = _worldSession->GetInstance()->GetScripts()->lists.Get("@ChannelList");
l->clear();
std::string pname;
bool muted,mod;
logcustom(0,WHITE,"Player channel list, %u players:",size);
for(ChannelPlayerList::iterator i = cpl.begin(); i != cpl.end(); i++)
{
pname = _worldSession->plrNameCache.GetName(i->first);
pname = _worldSession->GetOrRequestPlayerName(i->first); // all names should be known now
mode = i->second;
if(pname.empty())
{
pname = "<unknown>";
_worldSession->SendQueryPlayerName(i->first);
}
muted = mode & MEMBER_FLAG_MUTED;
mod = mode & MEMBER_FLAG_MODERATOR;
@ -251,6 +257,9 @@ void Channel::HandleListRequest(WorldPacket& recvPacket)
pname += " "; // for better formatting
logcustom(0,WHITE,"%s ["I64FMT"] %s %s",pname.c_str(),i->first,muted?"(muted)":"",mod?"(moderator)":"");
// DefScript binding
l->push_back(DefScriptTools::toString(guid));
}
}

View File

@ -84,15 +84,20 @@ ItemProto *ObjMgr::GetItemProtoByPos(uint32 pos)
void ObjMgr::AddNonexistentItem(uint32 id)
{
_noitem.push_back(id);
_noitem.insert(id);
}
bool ObjMgr::ItemNonExistent(uint32 id)
{
for(std::vector<uint32>::iterator i=_noitem.begin(); i != _noitem.end(); i++)
return _noitem.find(id) == _noitem.end();
}
void ObjMgr::AddRequestedPlayerGUID(uint32 loguid)
{
if(*i == id)
return true;
_reqpnames.insert(loguid);
}
return false;
bool ObjMgr::IsRequestedPlayerGUID(uint32 loguid)
{
return _reqpnames.find(loguid) != _reqpnames.end();
}

View File

@ -2,7 +2,7 @@
#define _OBJMGR_H
#include "common.h"
#include <list>
#include <set>
#include "Object.h"
#include "Item.h"
@ -29,6 +29,13 @@ public:
void AddNonexistentItem(uint32);
bool ItemNonExistent(uint32);
// player names related
void AddRequestedPlayerGUID(uint32);
bool IsRequestedPlayerGUID(uint32);
inline void AddRequestedPlayerGUID(uint64 guid) { AddRequestedPlayerGUID(GUID_LOPART(guid)); }
inline bool IsRequestedPlayerGUID(uint64 guid) { return IsRequestedPlayerGUID(GUID_LOPART(guid)); }
// Object functions
void Add(Object*);
void Remove(uint64); // remove all objects with that guid (should be only 1 object in total anyway)
@ -38,7 +45,8 @@ public:
private:
ItemProtoList _iproto;
ObjectMap _obj;
std::vector<uint32> _noitem;
std::set<uint32> _noitem;
std::set<uint32> _reqpnames;
PseuInstance *_instance;
};

View File

@ -378,12 +378,8 @@ void WorldSession::_QueryObjectInfo(uint64 guid)
}
case TYPEID_PLAYER:
{
std::string name = plrNameCache.GetName(guid);
if(name.empty())
{
SendQueryPlayerName(guid);
}
else
std::string name = GetOrRequestPlayerName(obj->GetGUID());
if(!name.empty())
{
((WorldObject*)obj)->SetName(name);
}

View File

@ -335,6 +335,27 @@ void WorldSession::_DoTimedActions(void)
}
}
std::string WorldSession::GetOrRequestPlayerName(uint64 guid)
{
if(!guid || GUID_HIPART(guid) != HIGHGUID_PLAYER)
{
logerror("WorldSession::GetOrRequestObjectName: "I64FMT" is not player",guid);
return "<ERR: OBJECT>"; // TODO: temporary, to find bugs with this, if there are any
}
std::string name = plrNameCache.GetName(guid);
if(name.empty())
{
if(!objmgr.IsRequestedPlayerGUID(guid))
{
objmgr.AddRequestedPlayerGUID(guid);
SendQueryPlayerName(guid);
}
}
return name;
}
///////////////////////////////////////////////////////////////
@ -530,10 +551,9 @@ void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket)
std::string plrname;
if(source_guid)
{
plrname=plrNameCache.GetName(source_guid);
plrname = GetOrRequestPlayerName(source_guid);
if(plrname.empty())
{
SendQueryPlayerName(source_guid);
_DelayWorldPacket(recvPacket, GetLagMS() * 1.2f); // guess time how long it will take until we got player name from the server
return; // handle later
}
@ -709,8 +729,8 @@ void WorldSession::_HandleNameQueryResponseOpcode(WorldPacket& recvPacket)
if(plrNameCache.AddInfo(pguid,pname))
{
logdetail("CACHE: Assigned new player name: '%s' = " I64FMTD ,pname.c_str(),pguid);
if(GetInstance()->GetConf()->debug > 1)
SendChatMessage(CHAT_MSG_SAY,0,"Player "+pname+" added to cache.","");
//if(GetInstance()->GetConf()->debug > 1)
// SendChatMessage(CHAT_MSG_SAY,0,"Player "+pname+" added to cache.","");
}
WorldObject *wo = (WorldObject*)objmgr.GetObj(pguid);
if(wo)
@ -893,10 +913,9 @@ void WorldSession::_HandleEmoteOpcode(WorldPacket& recvPacket)
// TODO: check if the emote came from a player or a mob, and query mob name if it was a mob
if(guid)
{
plrname=plrNameCache.GetName(guid);
plrname = GetOrRequestPlayerName(guid);
if(plrname.empty())
{
SendQueryPlayerName(guid);
_DelayWorldPacket(recvPacket, GetLagMS() * 1.2f);
return;
}

View File

@ -42,6 +42,8 @@ typedef std::queue<DelayedWorldPacket> DelayedPacketQueue;
class WorldSession
{
friend class Channel;
public:
WorldSession(PseuInstance *i);
~WorldSession();
@ -66,6 +68,8 @@ public:
inline MyCharacter *GetMyChar(void) { ASSERT(_myGUID > 0); return (MyCharacter*)objmgr.GetObj(_myGUID); }
inline World *GetWorld(void) { return _world; }
std::string GetOrRequestPlayerName(uint64);
// CMSGConstructor
void SendChatMessage(uint32 type, uint32 lang, std::string msg, std::string to="");

View File

@ -183,6 +183,12 @@
<File
RelativePath=".\Client\main.h">
</File>
<File
RelativePath=".\Client\MemoryDataHolder.cpp">
</File>
<File
RelativePath=".\Client\MemoryDataHolder.h">
</File>
<File
RelativePath=".\Client\PseuWoW.cpp">
</File>