* 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:
parent
40cef66995
commit
442670af16
@ -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
|
||||
|
||||
143
src/Client/MemoryDataHolder.cpp
Normal file
143
src/Client/MemoryDataHolder.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
14
src/Client/MemoryDataHolder.h
Normal file
14
src/Client/MemoryDataHolder.h
Normal 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
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
};
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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="");
|
||||
|
||||
@ -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>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user