* update gui charlist when crating a char
* implemented display correct response string in console & gui if char creation failed * fixed & simplified PlayerNameCache, load directly before world join and not at charlist receive * fixed some warnings * misc stuff * TODO: fix bug that prevents reopening char create window after creating char + implement dixplaying response strings for actions other then char creation.
This commit is contained in:
parent
585046fce2
commit
2b1d743125
@ -15,3 +15,6 @@
|
||||
0=Realmlist
|
||||
1=Create New Character
|
||||
|
||||
[3]
|
||||
0=Creating new Character...
|
||||
|
||||
|
||||
@ -36,6 +36,9 @@ LoadDB sound
|
||||
LoadDB gui_login_text
|
||||
LoadDB gui_charselect_text
|
||||
|
||||
// misc data
|
||||
LoadDB generic_text
|
||||
|
||||
|
||||
log ** Databases loaded.
|
||||
|
||||
|
||||
@ -60,10 +60,11 @@ Scene::~Scene()
|
||||
DEBUG(logdebug("Scene::~Scene()"));
|
||||
}
|
||||
|
||||
core::stringw Scene::GetStringFromDB(u32 index, u32 entry)
|
||||
core::stringw Scene::GetStringFromDB(u32 index, u32 entry, SCPDatabase *other_db /* = NULL */)
|
||||
{
|
||||
core::stringw r = "";
|
||||
if(!textdb)
|
||||
SCPDatabase *db = other_db ? other_db : textdb;
|
||||
if(!db)
|
||||
{
|
||||
r += L"<string ";
|
||||
r += index;
|
||||
@ -74,6 +75,6 @@ core::stringw Scene::GetStringFromDB(u32 index, u32 entry)
|
||||
}
|
||||
char buf[20];
|
||||
sprintf(buf,"%u",entry);
|
||||
r += textdb->GetString(index, buf);
|
||||
r += db->GetString(index, buf);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ class Scene
|
||||
public:
|
||||
Scene(PseuGUI *g);
|
||||
~Scene();
|
||||
core::stringw GetStringFromDB(u32 index, u32 entry);
|
||||
core::stringw GetStringFromDB(u32 index, u32 entry, SCPDatabase *other_db = NULL);
|
||||
inline void SetState(SceneState sc) { _scenestate = sc; }
|
||||
inline SceneState GetState(void) { return _scenestate; }
|
||||
virtual void OnUpdate(s32);
|
||||
@ -99,9 +99,12 @@ class SceneCharSelection : public Scene
|
||||
public:
|
||||
SceneCharSelection(PseuGUI *gui);
|
||||
void OnUpdate(s32);
|
||||
void OnManualUpdate(void);
|
||||
void OnDelete(void);
|
||||
void OnResize(void);
|
||||
|
||||
void FillCharlist(void);
|
||||
|
||||
private:
|
||||
GUIEventReceiver *eventrecv;
|
||||
IGUIWindow *realmwin;
|
||||
@ -112,6 +115,8 @@ private:
|
||||
IGUIComboBox *raceselect;
|
||||
IGUIComboBox *classselect;
|
||||
IGUIEditBox *charname;
|
||||
IGUIElement *msgbox; // display status/result of character creation
|
||||
uint32 msgbox_textid; // stores old textid
|
||||
std::map<u32,u32> racemap, classmap; //<comboBoxId,dbId> maps DB IDs in db to IDs in the combobox, because irrlicht does not allow custom ids in comboboxes
|
||||
};
|
||||
|
||||
|
||||
@ -50,7 +50,22 @@ SceneCharSelection::SceneCharSelection(PseuGUI *gui) : Scene(gui)
|
||||
rect<s32> clb_rect = CalcRelativeScreenPos(driver, 0.65f, 0.12f, 0.34f, 0.67f);
|
||||
charlistbox = guienv->addListBox(clb_rect);
|
||||
|
||||
mutex.acquire();
|
||||
FillCharlist();
|
||||
|
||||
if(soundengine)
|
||||
{
|
||||
ISoundSource *main_theme = soundengine->getSoundSource("data/misc/main_theme.ogg");
|
||||
if(main_theme && !soundengine->isCurrentlyPlaying(main_theme))
|
||||
{
|
||||
soundengine->play2D(main_theme,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SceneCharSelection::FillCharlist(void)
|
||||
{
|
||||
ZThread::Guard<ZThread::FastMutex> g(mutex);
|
||||
charlistbox->clear();
|
||||
WorldSession *ws = instance->GetWSession();
|
||||
if(ws)
|
||||
{
|
||||
@ -75,29 +90,19 @@ SceneCharSelection::SceneCharSelection(PseuGUI *gui) : Scene(gui)
|
||||
charlistbox->addItem(entry.c_str());
|
||||
|
||||
uint32 faction = racedb->GetInt(c.p._race, ffaction);
|
||||
|
||||
|
||||
SColor col;
|
||||
switch(faction)
|
||||
{
|
||||
case 1: col.set(0xFF, 0xFF, 0x30, 0x30); break;
|
||||
case 7: col.set(0xFF, 0x30, 0x30, 0xFF); break;
|
||||
default: col.set(0xFFFFFFFF);
|
||||
case 1: col.set(0xFF, 0xFF, 0x30, 0x30); break;
|
||||
case 7: col.set(0xFF, 0x30, 0x30, 0xFF); break;
|
||||
default: col.set(0xFFFFFFFF);
|
||||
}
|
||||
charlistbox->setItemOverrideColor(i,EGUI_LBC_TEXT,col);
|
||||
charlistbox->setItemOverrideColor(i,EGUI_LBC_TEXT_HIGHLIGHT,col);
|
||||
|
||||
}
|
||||
}
|
||||
mutex.release();
|
||||
|
||||
if(soundengine)
|
||||
{
|
||||
ISoundSource *main_theme = soundengine->getSoundSource("data/misc/main_theme.ogg");
|
||||
if(main_theme && !soundengine->isCurrentlyPlaying(main_theme))
|
||||
{
|
||||
soundengine->play2D(main_theme,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SceneCharSelection::OnUpdate(s32 timepassed)
|
||||
@ -182,10 +187,11 @@ void SceneCharSelection::OnUpdate(s32 timepassed)
|
||||
{
|
||||
guienv->addMessageBox(L"Not yet implemented!", L"Deleting a character does not yet work!");
|
||||
}
|
||||
if(eventrecv->buttons & BUTTON_NEW_CHARACTER)
|
||||
if(eventrecv->buttons & BUTTON_NEW_CHARACTER && !newcharwin)
|
||||
{
|
||||
dimension2d<s32> dim;
|
||||
rect<s32> pos;
|
||||
msgbox_textid = 0;
|
||||
newcharwin = guienv->addWindow(CalcRelativeScreenPos(driver, 0.2f, 0.2f, 0.6f, 0.6f), true,
|
||||
GetStringFromDB(ISCENE_CHARSEL_LABELS, DSCENE_CHARSEL_LABEL_NEWCHARWIN).c_str());
|
||||
pos = newcharwin->getAbsolutePosition(); // get absolute position and transform <dim> to absolute in-window position
|
||||
@ -213,7 +219,7 @@ void SceneCharSelection::OnUpdate(s32 timepassed)
|
||||
//newcharwin->addChild(classselect);
|
||||
guienv->addStaticText(L"Char Name", CalcRelativeScreenPos(dim,0.1f,0.3f,0.8f,0.05f),false,true,newcharwin);
|
||||
charname = guienv->addEditBox(L"", CalcRelativeScreenPos(dim,0.1f,0.35f,0.8f,0.05f),true, newcharwin);
|
||||
//guienv->addMessageBox(L"Not yet implemented!", L"Creating a new character does not yet work!");
|
||||
msgbox = guienv->addStaticText(L"",CalcRelativeScreenPos(dim,0.2f,0.6f,0.6f,0.1f), true, true, newcharwin);
|
||||
}
|
||||
if(eventrecv->buttons & BUTTON_SELECT_REALM || scenedata[ISCENE_CHARSEL_REALMFIRST])
|
||||
{
|
||||
@ -299,21 +305,20 @@ void SceneCharSelection::OnUpdate(s32 timepassed)
|
||||
|
||||
if(eventrecv->buttons & BUTTON_NEWCHARWIN_OK && newcharwin)
|
||||
{
|
||||
core::stringc tmp=charname->getText();
|
||||
core::stringc chname = charname->getText();
|
||||
u8 race = racemap[raceselect->getSelected()];
|
||||
u8 cclass = classmap[classselect->getSelected()];
|
||||
log("Creating character Race %i Class %i Name %s",race,cclass,tmp.c_str());
|
||||
if(tmp.size() && race && cclass)
|
||||
if(chname.size() && race && cclass)
|
||||
{
|
||||
WorldSession *ws=instance->GetWSession();
|
||||
if(ws)
|
||||
{
|
||||
WorldPacket packet(CMSG_CHAR_CREATE,(tmp.size()+1)+1+1+1+1+1+1+1+1+1);
|
||||
packet<<tmp.c_str();
|
||||
// name, race, class, gender, skin, face, hairstyle, haircolor, facialhair, outfitID
|
||||
packet << race << cclass <<(u8)0 <<(u8)0 <<(u8)0 <<(u8)0 <<(u8)0 <<(u8)0 <<(u8)0;
|
||||
ws->AddSendWorldPacket(packet);
|
||||
eventrecv->buttons |= BUTTON_NEWCHARWIN_CANCEL; // easiest way to close the window without much additional code
|
||||
ws->SendCharCreate(chname.c_str(), race, cclass);
|
||||
|
||||
msgbox->setText(GetStringFromDB(3,0).c_str());
|
||||
msgbox_textid = 0;
|
||||
|
||||
// do not close window until character created (will when getting response code 0)
|
||||
}
|
||||
else
|
||||
logerror("Trying to create new Character, but no WorldSession exists.");
|
||||
@ -323,18 +328,31 @@ void SceneCharSelection::OnUpdate(s32 timepassed)
|
||||
}
|
||||
|
||||
// realmlist window
|
||||
|
||||
if(eventrecv->buttons & BUTTON_REALMWIN_CANCEL && realmwin)
|
||||
{
|
||||
realmwin->remove();
|
||||
realmwin=NULL;
|
||||
realmwin = NULL;
|
||||
}
|
||||
|
||||
// new character window
|
||||
if(eventrecv->buttons & BUTTON_NEWCHARWIN_CANCEL && newcharwin)
|
||||
{
|
||||
newcharwin->remove();
|
||||
newcharwin=NULL;
|
||||
newcharwin = NULL;
|
||||
}
|
||||
|
||||
if(newcharwin && msgbox_textid != scenedata[ISCENE_CHARSEL_ERRMSG])
|
||||
{
|
||||
msgbox_textid = scenedata[ISCENE_CHARSEL_ERRMSG];
|
||||
if(SCPDatabase *generictext = instance->dbmgr.GetDB("generic_text"))
|
||||
{
|
||||
msgbox->setText(GetStringFromDB(0, msgbox_textid, generictext).c_str());
|
||||
}
|
||||
if(scenedata[ISCENE_CHARSEL_ERRMSG] == CHAR_CREATE_SUCCESS)
|
||||
{
|
||||
newcharwin->remove();
|
||||
newcharwin = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
eventrecv->buttons = 0;
|
||||
@ -351,3 +369,10 @@ void SceneCharSelection::OnResize(void)
|
||||
|
||||
}
|
||||
|
||||
// called when receiving SMSG_CHAR_ENUM
|
||||
void SceneCharSelection::OnManualUpdate(void)
|
||||
{
|
||||
Scene::OnManualUpdate();
|
||||
FillCharlist();
|
||||
}
|
||||
|
||||
|
||||
@ -49,6 +49,7 @@ enum SceneCharSelectDataIndexes
|
||||
{
|
||||
ISCENE_CHARSEL_BUTTONS = 1, // text
|
||||
ISCENE_CHARSEL_LABELS = 2, // text
|
||||
ISCENE_CHARSEL_ERRMSG = 3, // uint32 response code, see enum ResponseCodes in SharedDefines.h for IDs
|
||||
ISCENE_CHARSEL_REALMFIRST = 255, // flag that is set when connecting to a realm wasnt possible and the realm list must be shown first
|
||||
ISCENE_CHARSEL_END
|
||||
};
|
||||
@ -72,6 +73,7 @@ enum SceneCharSelectLabels
|
||||
DSCENE_CHARSEL_LABEL_NEWCHARWIN = 1,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@ -207,5 +207,23 @@ void WorldSession::SendQueryGameobject(uint32 entry, uint64 guid)
|
||||
SendWorldPacket(wp);
|
||||
}
|
||||
|
||||
void WorldSession::SendCharCreate(std::string name, uint8 race, uint8 class_, // below here all values default is 0
|
||||
uint8 gender, uint8 skin, uint8 face,
|
||||
uint8 hairstyle, uint8 haircolor, uint8 facial, uint8 outfit)
|
||||
{
|
||||
log("Creating Character '%s', race=%u, class=%u gender=%u", name.c_str(), race, class_, gender);
|
||||
WorldPacket wp(CMSG_CHAR_CREATE, name.length()+1 + 9);
|
||||
wp << name;
|
||||
wp << race;
|
||||
wp << class_;
|
||||
wp << gender;
|
||||
wp << skin;
|
||||
wp << face;
|
||||
wp << hairstyle;
|
||||
wp << haircolor;
|
||||
wp << facial;
|
||||
wp << outfit;
|
||||
AddSendWorldPacket(wp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -17,58 +17,44 @@ uint32 GOTEMPLATES_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);
|
||||
void PlayerNameCache::Add(uint64 guid, std::string name)
|
||||
{
|
||||
_cache.erase(guid); // drop old data if present
|
||||
_cache[guid] = name;
|
||||
}
|
||||
|
||||
bool PlayerNameCache::IsKnown(uint64 guid)
|
||||
{
|
||||
for(std::vector<PlayerNameCacheItem*>::iterator i=_cache.begin(); i!=_cache.end(); i++)
|
||||
if(guid==(*i)->_guid)
|
||||
return true;
|
||||
PlayerNameMap::iterator it = _cache.find(guid);
|
||||
if(it != _cache.end())
|
||||
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;
|
||||
PlayerNameMap::iterator it = _cache.find(guid);
|
||||
if(it != _cache.end())
|
||||
return it->second;
|
||||
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;
|
||||
for(PlayerNameMap::iterator it = _cache.begin(); it != _cache.end(); it++)
|
||||
if(it->second == name)
|
||||
return it->first;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool PlayerNameCache::SaveToFile(void)
|
||||
{
|
||||
log("Saving PlayerNameCache...");
|
||||
if(_cache.empty())
|
||||
return true; // no data to save, so we are fine
|
||||
|
||||
logdebug("Saving PlayerNameCache...");
|
||||
char *fn="./cache/playernames.cache";
|
||||
std::fstream fh;
|
||||
fh.open(fn, std::ios_base::out | std::ios_base::binary);
|
||||
@ -77,22 +63,23 @@ bool PlayerNameCache::SaveToFile(void)
|
||||
logerror("PlayerNameCache: Could not write to file '%s'!",fn);
|
||||
return false;
|
||||
}
|
||||
uint32 size=_cache.size();
|
||||
if(size==0)
|
||||
uint32 size = _cache.size();
|
||||
if(!size)
|
||||
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*)&size,sizeof(uint32));
|
||||
ByteBuffer bb;
|
||||
|
||||
bb << (uint32)_cache.size();
|
||||
for(PlayerNameMap::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()););
|
||||
bb << i->first;
|
||||
bb << (uint8)i->second.length();
|
||||
bb.append(i->second.c_str(), i->second.length()); // do not append '\0'
|
||||
}
|
||||
fh.write((char*)bb.contents(), bb.size());
|
||||
fh.close();
|
||||
log("PlayerNameCache saved successfully.");
|
||||
logdebug("PlayerNameCache saved successfully.");
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -102,49 +89,45 @@ bool PlayerNameCache::ReadFromFile(void)
|
||||
log("Loading PlayerNameCache...");
|
||||
bool success=true;
|
||||
std::fstream fh;
|
||||
fh.open(fn, std::ios_base::in | std::ios_base::binary);
|
||||
if(!fh.is_open())
|
||||
uint32 size = GetFileSize(fn);
|
||||
if(!size)
|
||||
{
|
||||
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;
|
||||
|
||||
// do NOT use MemoryDataHolder, since the file can change during runtime and may be loaded again
|
||||
fh.open(fn, std::ios_base::in | std::ios_base::binary);
|
||||
ByteBuffer bb;
|
||||
bb.resize(size);
|
||||
fh.read((char*)bb.contents(), size);
|
||||
fh.close();
|
||||
|
||||
uint8 len;
|
||||
char *nameptr=new char[13];
|
||||
for(unsigned int i=0;i<size;i++)
|
||||
uint32 count;
|
||||
uint64 guid;
|
||||
char namebuf[MAX_PLAYERNAME_LENGTH + 1];
|
||||
|
||||
bb >> count; // entries count
|
||||
|
||||
for(uint32 i = 0; i < count; 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)
|
||||
bb >> guid;
|
||||
bb >> len;
|
||||
if(len > MAX_PLAYERNAME_LENGTH || len < MIN_PLAYERNAME_LENGTH || !guid)
|
||||
{
|
||||
logerror("PlayerNameCache data seem corrupt [namelength=%d, should be <=%u]",len,MAX_PLAYERNAME_LENGTH);
|
||||
log("-> Clearing cache, creating new.");
|
||||
_cache.clear();
|
||||
success=false;
|
||||
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););
|
||||
memset(namebuf,0,MAX_PLAYERNAME_LENGTH + 1);
|
||||
bb.read((uint8*)namebuf, len);
|
||||
Add(guid, namebuf);
|
||||
}
|
||||
printf("\n");
|
||||
delete nameptr;
|
||||
fh.flush();
|
||||
fh.close();
|
||||
if(success)
|
||||
log("PlayerNameCache successfully loaded.");
|
||||
logdebug("PlayerNameCache successfully loaded.");
|
||||
return success;
|
||||
}
|
||||
|
||||
@ -215,7 +198,7 @@ void ItemProtoCache_InsertDataToSession(WorldSession *session)
|
||||
buf >> proto->Stackable;
|
||||
buf >> proto->ContainerSlots;
|
||||
buf >> proto->StatsCount;
|
||||
for(int i = 0; i < proto->StatsCount; i++)
|
||||
for(uint32 i = 0; i < proto->StatsCount; i++)
|
||||
{
|
||||
buf >> proto->ItemStat[i].ItemStatType;
|
||||
buf >> proto->ItemStat[i].ItemStatValue;
|
||||
@ -349,7 +332,7 @@ void ItemProtoCache_WriteDataToCache(WorldSession *session)
|
||||
buf << proto->Stackable;
|
||||
buf << proto->ContainerSlots;
|
||||
buf << proto->StatsCount;
|
||||
for(int i = 0; i < proto->StatsCount; i++)
|
||||
for(uint32 i = 0; i < proto->StatsCount; i++)
|
||||
{
|
||||
buf << proto->ItemStat[i].ItemStatType;
|
||||
buf << proto->ItemStat[i].ItemStatValue;
|
||||
|
||||
@ -1,25 +1,22 @@
|
||||
#ifndef _CACHEHANDLER_H
|
||||
#define _CACHEHANDLER_H
|
||||
|
||||
struct PlayerNameCacheItem {
|
||||
uint64 _guid;
|
||||
std::string _name;
|
||||
};
|
||||
typedef std::map<uint64,std::string> PlayerNameMap;
|
||||
|
||||
class PlayerNameCache {
|
||||
class PlayerNameCache
|
||||
{
|
||||
public:
|
||||
~PlayerNameCache();
|
||||
|
||||
std::string GetName(uint64);
|
||||
bool IsKnown(uint64);
|
||||
uint64 GetGuid(std::string);
|
||||
bool AddInfo(uint64 guid, std::string name);
|
||||
bool AddInfo(PlayerNameCacheItem*);
|
||||
void Add(uint64 guid, std::string name);
|
||||
bool SaveToFile(void);
|
||||
bool ReadFromFile(void);
|
||||
uint32 GetSize(void);
|
||||
private:
|
||||
std::vector<PlayerNameCacheItem*> _cache;
|
||||
PlayerNameMap _cache;
|
||||
};
|
||||
|
||||
void ItemProtoCache_InsertDataToSession(WorldSession *session);
|
||||
|
||||
@ -40,7 +40,7 @@ void WorldSession::_HandleItemQuerySingleResponseOpcode(WorldPacket& recvPacket)
|
||||
recvPacket >> proto->Stackable;
|
||||
recvPacket >> proto->ContainerSlots;
|
||||
recvPacket >> proto->StatsCount;
|
||||
for(int i = 0; i < proto->StatsCount; i++)
|
||||
for(uint32 i = 0; i < proto->StatsCount; i++)
|
||||
{
|
||||
recvPacket >> proto->ItemStat[i].ItemStatType;
|
||||
recvPacket >> proto->ItemStat[i].ItemStatValue;
|
||||
|
||||
@ -1388,6 +1388,113 @@ enum SpellCastTargetFlags
|
||||
TARGET_FLAG_UNK2 = 0x00010000 // pguid
|
||||
};
|
||||
|
||||
enum ResponseCodes
|
||||
{
|
||||
RESPONSE_SUCCESS = 0x00,
|
||||
RESPONSE_FAILURE = 0x01,
|
||||
RESPONSE_CANCELLED = 0x02,
|
||||
RESPONSE_DISCONNECTED = 0x03,
|
||||
RESPONSE_FAILED_TO_CONNECT = 0x04,
|
||||
RESPONSE_CONNECTED = 0x05,
|
||||
RESPONSE_VERSION_MISMATCH = 0x06,
|
||||
|
||||
CSTATUS_CONNECTING = 0x07,
|
||||
CSTATUS_NEGOTIATING_SECURITY = 0x08,
|
||||
CSTATUS_NEGOTIATION_COMPLETE = 0x09,
|
||||
CSTATUS_NEGOTIATION_FAILED = 0x0A,
|
||||
CSTATUS_AUTHENTICATING = 0x0B,
|
||||
|
||||
AUTH_OK = 0x0C,
|
||||
AUTH_FAILED = 0x0D,
|
||||
AUTH_REJECT = 0x0E,
|
||||
AUTH_BAD_SERVER_PROOF = 0x0F,
|
||||
AUTH_UNAVAILABLE = 0x10,
|
||||
AUTH_SYSTEM_ERROR = 0x11,
|
||||
AUTH_BILLING_ERROR = 0x12,
|
||||
AUTH_BILLING_EXPIRED = 0x13,
|
||||
AUTH_VERSION_MISMATCH = 0x14,
|
||||
AUTH_UNKNOWN_ACCOUNT = 0x15,
|
||||
AUTH_INCORRECT_PASSWORD = 0x16,
|
||||
AUTH_SESSION_EXPIRED = 0x17,
|
||||
AUTH_SERVER_SHUTTING_DOWN = 0x18,
|
||||
AUTH_ALREADY_LOGGING_IN = 0x19,
|
||||
AUTH_LOGIN_SERVER_NOT_FOUND = 0x1A,
|
||||
AUTH_WAIT_QUEUE = 0x1B,
|
||||
AUTH_BANNED = 0x1C,
|
||||
AUTH_ALREADY_ONLINE = 0x1D,
|
||||
AUTH_NO_TIME = 0x1E,
|
||||
AUTH_DB_BUSY = 0x1F,
|
||||
AUTH_SUSPENDED = 0x20,
|
||||
AUTH_PARENTAL_CONTROL = 0x21,
|
||||
AUTH_LOCKED_ENFORCED = 0x22,
|
||||
|
||||
REALM_LIST_IN_PROGRESS = 0x23,
|
||||
REALM_LIST_SUCCESS = 0x24,
|
||||
REALM_LIST_FAILED = 0x25,
|
||||
REALM_LIST_INVALID = 0x26,
|
||||
REALM_LIST_REALM_NOT_FOUND = 0x27,
|
||||
|
||||
ACCOUNT_CREATE_IN_PROGRESS = 0x28,
|
||||
ACCOUNT_CREATE_SUCCESS = 0x29,
|
||||
ACCOUNT_CREATE_FAILED = 0x2A,
|
||||
|
||||
CHAR_LIST_RETRIEVING = 0x2B,
|
||||
CHAR_LIST_RETRIEVED = 0x2C,
|
||||
CHAR_LIST_FAILED = 0x2D,
|
||||
|
||||
CHAR_CREATE_IN_PROGRESS = 0x2E,
|
||||
CHAR_CREATE_SUCCESS = 0x2F,
|
||||
CHAR_CREATE_ERROR = 0x30,
|
||||
CHAR_CREATE_FAILED = 0x31,
|
||||
CHAR_CREATE_NAME_IN_USE = 0x32,
|
||||
CHAR_CREATE_DISABLED = 0x33,
|
||||
CHAR_CREATE_PVP_TEAMS_VIOLATION = 0x34,
|
||||
CHAR_CREATE_SERVER_LIMIT = 0x35,
|
||||
CHAR_CREATE_ACCOUNT_LIMIT = 0x36,
|
||||
CHAR_CREATE_SERVER_QUEUE = 0x37,
|
||||
CHAR_CREATE_ONLY_EXISTING = 0x38,
|
||||
CHAR_CREATE_EXPANSION = 0x39,
|
||||
CHAR_CREATE_EXPANSION_CLASS = 0x3A,
|
||||
CHAR_CREATE_LEVEL_REQUIREMENT = 0x3B,
|
||||
CHAR_CREATE_UNIQUE_CLASS_LIMIT = 0x3C,
|
||||
|
||||
CHAR_DELETE_IN_PROGRESS = 0x3D,
|
||||
CHAR_DELETE_SUCCESS = 0x3E,
|
||||
CHAR_DELETE_FAILED = 0x3F,
|
||||
CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER = 0x40,
|
||||
CHAR_DELETE_FAILED_GUILD_LEADER = 0x41,
|
||||
CHAR_DELETE_FAILED_ARENA_CAPTAIN = 0x42,
|
||||
|
||||
CHAR_LOGIN_IN_PROGRESS = 0x43,
|
||||
CHAR_LOGIN_SUCCESS = 0x44,
|
||||
CHAR_LOGIN_NO_WORLD = 0x45,
|
||||
CHAR_LOGIN_DUPLICATE_CHARACTER = 0x46,
|
||||
CHAR_LOGIN_NO_INSTANCES = 0x47,
|
||||
CHAR_LOGIN_FAILED = 0x48,
|
||||
CHAR_LOGIN_DISABLED = 0x49,
|
||||
CHAR_LOGIN_NO_CHARACTER = 0x4A,
|
||||
CHAR_LOGIN_LOCKED_FOR_TRANSFER = 0x4B,
|
||||
CHAR_LOGIN_LOCKED_BY_BILLING = 0x4C,
|
||||
|
||||
CHAR_NAME_SUCCESS = 0x4D,
|
||||
CHAR_NAME_FAILURE = 0x4E,
|
||||
CHAR_NAME_NO_NAME = 0x4F,
|
||||
CHAR_NAME_TOO_SHORT = 0x50,
|
||||
CHAR_NAME_TOO_LONG = 0x51,
|
||||
CHAR_NAME_INVALID_CHARACTER = 0x52,
|
||||
CHAR_NAME_MIXED_LANGUAGES = 0x53,
|
||||
CHAR_NAME_PROFANE = 0x54,
|
||||
CHAR_NAME_RESERVED = 0x55,
|
||||
CHAR_NAME_INVALID_APOSTROPHE = 0x56,
|
||||
CHAR_NAME_MULTIPLE_APOSTROPHES = 0x57,
|
||||
CHAR_NAME_THREE_CONSECUTIVE = 0x58,
|
||||
CHAR_NAME_INVALID_SPACE = 0x59,
|
||||
CHAR_NAME_CONSECUTIVE_SPACES = 0x5A,
|
||||
CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 0x5B,
|
||||
CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 0x5C,
|
||||
CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 0x5D
|
||||
};
|
||||
|
||||
#define MAX_PLAYERNAME_LENGTH 12
|
||||
#define MIN_PLAYERNAME_LENGTH 2
|
||||
|
||||
|
||||
@ -347,6 +347,7 @@ OpcodeHandler *WorldSession::_GetOpcodeHandlerTable() const
|
||||
{SMSG_WHO, &WorldSession::_HandleWhoOpcode},
|
||||
{SMSG_CREATURE_QUERY_RESPONSE, &WorldSession::_HandleCreatureQueryResponseOpcode},
|
||||
{SMSG_GAMEOBJECT_QUERY_RESPONSE, &WorldSession::_HandleGameobjectQueryResponseOpcode},
|
||||
{SMSG_CHAR_CREATE, &WorldSession::_HandleCharCreateOpcode},
|
||||
|
||||
// table termination
|
||||
{ 0, NULL }
|
||||
@ -556,11 +557,11 @@ void WorldSession::_HandleAuthResponseOpcode(WorldPacket& recvPacket)
|
||||
recvPacket >> dummy32 >> dummy8 >> dummy32;
|
||||
recvPacket >> expansion;
|
||||
|
||||
if(errcode == 0xC)
|
||||
// TODO: add data to generic_text.scp and use the strings here
|
||||
if(errcode == AUTH_OK)
|
||||
{
|
||||
logdetail("World Authentication successful, preparing for char list request...");
|
||||
WorldPacket pkt;
|
||||
pkt.SetOpcode(CMSG_CHAR_ENUM);
|
||||
WorldPacket pkt(CMSG_CHAR_ENUM, 0);
|
||||
SendWorldPacket(pkt);
|
||||
}
|
||||
else
|
||||
@ -591,7 +592,6 @@ void WorldSession::_HandleCharEnumOpcode(WorldPacket& recvPacket)
|
||||
else
|
||||
{
|
||||
logdetail("Chars in list: %u",num);
|
||||
_LoadCache(); // we are about to login, so we need cache data
|
||||
// TODO: load cache on loadingscreen
|
||||
for(unsigned int i=0;i<num;i++)
|
||||
{
|
||||
@ -622,7 +622,7 @@ void WorldSession::_HandleCharEnumOpcode(WorldPacket& recvPacket)
|
||||
{
|
||||
recvPacket >> plr[i]._items[inv].displayId >> plr[i]._items[inv].inventorytype >> dummy32;
|
||||
}
|
||||
plrNameCache.AddInfo(plr[i]._guid, plr[i]._name); // TODO: set after loadingscreen, after loading cache
|
||||
plrNameCache.Add(plr[i]._guid, plr[i]._name); // TODO: set after loadingscreen, after loading cache
|
||||
|
||||
}
|
||||
char_found=false;
|
||||
@ -747,6 +747,7 @@ void WorldSession::EnterWorldWithCharacter(std::string name)
|
||||
void WorldSession::PreloadDataBeforeEnterWorld(PlayerEnum& pl)
|
||||
{
|
||||
log("Loading data before entering world...");
|
||||
_LoadCache(); // we are about to login, so we need cache data
|
||||
GetWorld()->GetMapMgr()->Update(pl._x, pl._y, pl._mapId); // make it load the map files
|
||||
|
||||
// preload additional map data only when the GUI is enabled
|
||||
@ -1023,12 +1024,8 @@ void WorldSession::_HandleNameQueryResponseOpcode(WorldPacket& recvPacket)
|
||||
if(pname.length()>MAX_PLAYERNAME_LENGTH || pname.length()<MIN_PLAYERNAME_LENGTH)
|
||||
return; // playernames maxlen=12, minlen=2
|
||||
// rest of the packet is not interesting for now
|
||||
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.","");
|
||||
}
|
||||
plrNameCache.Add(pguid,pname);
|
||||
logdetail("CACHE: Assigned new player name: '%s' = " I64FMTD ,pname.c_str(),pguid);
|
||||
WorldObject *wo = (WorldObject*)objmgr.GetObj(pguid);
|
||||
if(wo)
|
||||
wo->SetName(pname);
|
||||
@ -1040,7 +1037,7 @@ void WorldSession::_HandlePongOpcode(WorldPacket& recvPacket)
|
||||
recvPacket >> pong;
|
||||
_lag_ms = clock() - pong;
|
||||
if(GetInstance()->GetConf()->notifyping)
|
||||
log("Recieved Ping reply: %u ms latency.", _lag_ms);
|
||||
log("Received Ping reply: %u ms latency.", _lag_ms);
|
||||
}
|
||||
void WorldSession::_HandleTradeStatusOpcode(WorldPacket& recvPacket)
|
||||
{
|
||||
@ -1049,6 +1046,7 @@ void WorldSession::_HandleTradeStatusOpcode(WorldPacket& recvPacket)
|
||||
recvPacket >> unk;
|
||||
if(unk==1)
|
||||
{
|
||||
// TODO: Implement this!!
|
||||
SendChatMessage(CHAT_MSG_SAY,0,"It has no sense trying to trade with me, that feature is not yet implemented!","");
|
||||
WorldPacket pkt;
|
||||
pkt.SetOpcode(CMSG_CANCEL_TRADE);
|
||||
@ -1679,6 +1677,35 @@ void WorldSession::_HandleGameobjectQueryResponseOpcode(WorldPacket& recvPacket)
|
||||
objmgr.AssignNameToObj(entry, TYPEID_GAMEOBJECT, go->name);
|
||||
}
|
||||
|
||||
void WorldSession::_HandleCharCreateOpcode(WorldPacket& recvPacket)
|
||||
{
|
||||
uint8 response;
|
||||
recvPacket >> response;
|
||||
if(response == CHAR_CREATE_SUCCESS)
|
||||
{
|
||||
log("Character created successfully.");
|
||||
WorldPacket pkt(CMSG_CHAR_ENUM, 0);
|
||||
SendWorldPacket(pkt);
|
||||
logdebug("Requested new CMSG_CHAR_ENUM");
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror("Character creation error, response=%u", response);
|
||||
}
|
||||
if(SCPDatabase *db = GetInstance()->dbmgr.GetDB("generic_text"))
|
||||
{
|
||||
// convert response number to field name (simple int to string)
|
||||
char buf[20];
|
||||
sprintf(buf,"%u",response);
|
||||
std::string response_str = db->GetString(0, buf); // data are expected to be at index 0
|
||||
log("Response String: '%s'",response_str.c_str());
|
||||
}
|
||||
|
||||
if(PseuGUI *gui = GetInstance()->GetGUI())
|
||||
gui->SetSceneData(ISCENE_CHARSEL_ERRMSG, response);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TODO: delete world on LogoutComplete once implemented
|
||||
|
||||
|
||||
@ -104,6 +104,7 @@ public:
|
||||
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 SendQueryGameobject(uint32 entry, uint64 guid = 0);
|
||||
void SendCharCreate(std::string name, uint8 race, uint8 class_, uint8 gender=0, uint8 skin=0, uint8 face=0, uint8 hairstyle=0, uint8 haircolor=0, uint8 facial=0, uint8 outfit=0);
|
||||
|
||||
void HandleWorldPacket(WorldPacket*);
|
||||
|
||||
@ -161,6 +162,7 @@ private:
|
||||
void _HandleWhoOpcode(WorldPacket& recvPacket);
|
||||
void _HandleCreatureQueryResponseOpcode(WorldPacket& recvPacket);
|
||||
void _HandleGameobjectQueryResponseOpcode(WorldPacket& recvPacket);
|
||||
void _HandleCharCreateOpcode(WorldPacket& recvPacket);
|
||||
|
||||
// helper functions to keep SMSG_(COMPRESSED_)UPDATE_OBJECT easy to handle
|
||||
void _MovementUpdate(uint8 objtypeid, uint64 guid, WorldPacket& recvPacket); // Helper for _HandleUpdateObjectOpcode
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user