* added support for gameobjects. in the GUI they are still visible as cubes, but that will be fixed soon.

* fixed crash when a script's #onload block was explicitly loading another script file that also had an #onload block.
* some cleanups in realm code
* fixed bug in SCP database loader that didnt strip comments (//) properly.
This commit is contained in:
false_genesis 2008-04-29 20:23:49 +00:00
parent 65a8ab523a
commit b5834846f0
12 changed files with 382 additions and 11 deletions

View File

@ -259,7 +259,7 @@ bool DefScriptPackage::LoadScriptFromFile(std::string fn){
_UpdateOrCreateScriptByName(sn);
curScript=Script[sn];
DeleteScript(SN_ONLOAD);
DeleteScript(sn + SN_ONLOAD);
while(!f.eof())
{
@ -354,13 +354,13 @@ bool DefScriptPackage::LoadScriptFromFile(std::string fn){
}
else if(line=="onload")
{
_UpdateOrCreateScriptByName(SN_ONLOAD);
curScript=Script[SN_ONLOAD];
_UpdateOrCreateScriptByName(sn + SN_ONLOAD);
curScript=Script[sn + SN_ONLOAD];
}
else if(line=="endonload" || line=="/onload")
{
RunScript(SN_ONLOAD,NULL,sn);
DeleteScript(SN_ONLOAD);
RunScript(sn + SN_ONLOAD,NULL,sn);
DeleteScript(sn + SN_ONLOAD);
curScript=Script[sn];
}
else if(line=="cs" || line=="comments-start")
@ -1118,7 +1118,7 @@ DefReturnResult DefScriptPackage::Interpret(CmdSet& Set)
// if nothing has been found its maybe an external script file to run
result=RunScript(Set.cmd, &Set);
if((!result.ok) /*&& Script[Set.cmd]->GetDebug()*/)
std::cout << "Could not execute script command '" << Set.cmd << "'\n";
PRINT_ERROR("Could not execute script command '%s'",Set.cmd.c_str());
return result;

View File

@ -516,7 +516,7 @@ void RealmSession::_HandleLogonChallenge(ByteBuffer& pkt)
void RealmSession::_HandleLogonProof(ByteBuffer& pkt)
{
PseuGUI *gui = GetInstance()->GetGUI();
logdebug("RealmSocket: Got AUTH_LOGON_PROOF [%u of %u bytes]",pkt.size(),26);
logdebug("RealmSocket: Got AUTH_LOGON_PROOF [%u of %u bytes]",pkt.size(),sizeof(sAuthLogonProof_S));
if(pkt.size() < 2)
{
logerror("AUTH_LOGON_PROOF: Recieved incorrect/unknown packet. Hexdump:");
@ -561,7 +561,7 @@ void RealmSession::_HandleLogonProof(ByteBuffer& pkt)
sAuthLogonProof_S lp;
pkt.read((uint8*)&lp, 26); // the compiler didnt like 'sizeof(sAuthLogonProof_S)', said it was 28
pkt.read((uint8*)&lp, sizeof(sAuthLogonProof_S));
//printchex((char*)&lp, sizeof(sAuthLogonProof_S),true);
if(!memcmp(lp.M2,this->_m2,20))
{

View File

@ -200,6 +200,11 @@ uint32 SCPDatabaseMgr::AutoLoadFile(char *fn)
continue;
while(line.size() && (line[0]==' ' || line[0]=='\t'))
line.erase(0,1);
if(line.size() < 2 || (line[0] == '/' && line[1] == '/'))
{
line.clear();
continue;
}
uint32 eq = line.find("=");
if(eq != std::string::npos)
{

View File

@ -192,5 +192,18 @@ void WorldSession::SendQueryCreature(uint32 entry, uint64 guid)
SendWorldPacket(wp);
}
void WorldSession::SendQueryGameobject(uint32 entry, uint64 guid)
{
if(objmgr.GONonExistent(entry))
{
logdebug("Skipped query of gameobject %u (was marked as nonexistent before)",entry);
return;
}
logdebug("Sending gameobject query, id=%u",entry);
WorldPacket wp(CMSG_GAMEOBJECT_QUERY,4+8);
wp << entry << guid;
SendWorldPacket(wp);
}

View File

@ -13,6 +13,7 @@
// increase this number whenever you change something that makes old files unusable
uint32 ITEMPROTOTYPES_CACHE_VERSION = 3;
uint32 CREATURETEMPLATES_CACHE_VERSION = 0;
uint32 GOTEMPLATES_CACHE_VERSION = 0;
PlayerNameCache::~PlayerNameCache()
{
@ -528,3 +529,113 @@ void CreatureTemplateCache_WriteDataToCache(WorldSession *session)
fh.close();
log("CreatureTemplateCache: Saved %u Creature Templates",counter);
}
void GOTemplateCache_InsertDataToSession(WorldSession *session)
{
logdetail("GOTemplateCache: Loading...");
char* fn = "./cache/GOTemplates.cache";
std::fstream fh;
fh.open(fn, std::ios_base::in | std::ios_base::binary);
if(!fh)
{
logerror("GOTemplateCache: Could not open file '%s'!",fn);
return;
}
uint32 cacheversion, total, counter = 0;
try
{
fh.read((char*)&cacheversion,4);
if(cacheversion != GOTEMPLATES_CACHE_VERSION)
{
logerror("GOTemplateCache is outdated! Creating new cache.");
fh.close();
return;
}
fh.read((char*)&total,4);
logdetail("GOTemplateCache: %u gameobject 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);
GameobjectTemplate *go = new GameobjectTemplate();
buf >> go->entry;
buf >> go->type;
buf >> go->displayId;
buf >> go->name;
buf >> go->castBarCaption;
buf >> go->faction;
buf >> go->flags;
buf >> go->size;
for(uint32 i = 0; i < GAMEOBJECT_DATA_FIELDS; i++)
buf >> go->raw.data[i];
if(go->entry)
{
session->objmgr.Add(go);
counter++;
} else
delete go;
}
}
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("GOTemplateCache: Loaded %u Gameobject Templates",counter);
}
void GOTemplateCache_WriteDataToCache(WorldSession *session)
{
if (!session->objmgr.GetGOTemplateCount())
return;
char* fn = "./cache/GOTemplates.cache";
std::fstream fh;
fh.open(fn, std::ios_base::out | std::ios_base::binary);
if(!fh)
{
logerror("GOTemplateCache: Could not write to file '%s'!",fn);
return;
}
uint32 total = session->objmgr.GetGOTemplateCount();
fh.write((char*)&GOTEMPLATES_CACHE_VERSION,4);
fh.write((char*)&total,4);
uint32 counter=0;
ByteBuffer buf;
for(GOTemplateMap::iterator it = session->objmgr.GetGOTemplateStorage()->begin(); it != session->objmgr.GetGOTemplateStorage()->end(); it++)
{
buf.clear();
GameobjectTemplate *go = new GameobjectTemplate();
buf << go->entry;
buf << go->type;
buf << go->displayId;
buf << go->name;
buf << go->castBarCaption;
buf << go->faction;
buf << go->flags;
buf << go->size;
for(uint32 i = 0; i < GAMEOBJECT_DATA_FIELDS; i++)
buf << go->raw.data[i];
uint32 size = buf.size();
fh.write((char*)&size,sizeof(uint32));
fh.write((char*)buf.contents(),buf.size());
counter++;
}
fh.flush();
fh.close();
log("GOTemplateCache: Saved %u Gameobject Templates",counter);
}

View File

@ -28,4 +28,7 @@ void ItemProtoCache_WriteDataToCache(WorldSession *session);
void CreatureTemplateCache_InsertDataToSession(WorldSession *session);
void CreatureTemplateCache_WriteDataToCache(WorldSession *session);
void GOTemplateCache_InsertDataToSession(WorldSession *session);
void GOTemplateCache_WriteDataToCache(WorldSession *session);
#endif

View File

@ -3,6 +3,149 @@
#include "Object.h"
#define GAMEOBJECT_DATA_FIELDS 24
struct GameobjectTemplate
{
uint32 entry;
uint32 type;
uint32 displayId;
std::string name;
std::string castBarCaption;
uint32 faction;
uint32 flags;
float size;
union // different GO types have different data field
{
//0 GAMEOBJECT_TYPE_DOOR
struct
{
uint32 _data0;
uint32 lockId; //1
uint16 _data2lo; //2 lower part of data2, unknown
uint16 autoCloseTime; //2 (unit16)
} door;
//1 GAMEOBJECT_TYPE_BUTTON
struct
{
uint32 _data0;
uint32 lockId; //1
uint16 _data2lo; //2 lower part of data2, unknown
uint16 autoCloseTime; //2 (unit16)
uint32 _data3;
uint32 isBattlegroundObject; //4
} button;
//3 GAMEOBJECT_TYPE_CHEST
struct
{
uint32 lockId; //0
uint32 lootId; //1
uint32 _data2[2];
uint32 minSuccessOpens; //4
uint32 maxSuccessOpens; //5
uint32 eventId; //6
uint32 linkedTrapId; //7
uint32 questId; //8 not used currently but store quest required for GO activation for player
uint32 _data9[5];
uint32 _data14; //14 something == trap.data12 == goober.data14 (openText?)
} chest;
//6 GAMEOBJECT_TYPE_TRAP
struct
{
uint32 _data0; //0 lockid???
uint32 _data1;
uint32 radius; //2 radius for trap activation
uint32 spellId; //3
uint32 isNeedDespawn; //4 (if >0)
uint32 _data5; //5
uint32 _data6[6];
uint32 _data12; //12 something == chest.data14 == goober.data14 (openText?)
} trap;
//7 GAMEOBJECT_TYPE_CHAIR
struct
{
uint32 slots; //0 not used currently
uint32 height; //1
} chair;
//8 GAMEOBJECT_TYPE_SPELL_FOCUS
struct
{
uint32 focusId; //0
uint32 dist; //1
uint32 linkedTrapId; //2
} spellFocus;
//10 GAMEOBJECT_TYPE_GOOBER
struct
{
uint32 _data0; //0 lockid ???
uint32 questId; //1
uint32 eventId; //2
uint32 _data3[4];
uint32 pageId; //7
uint32 _data8[2];
uint32 spellId; //10
uint32 _data11;
uint32 linkedTrapId; //12
uint32 _data13;
uint32 _data14; //14 something == trap.data12 == chest.data14 (openText?)
uint32 _data15;
uint32 isBattlegroundObject; //16
} goober;
//13 GAMEOBJECT_TYPE_CAMERA
struct
{
uint32 _data0;
uint32 cinematicId; //1
} camera;
//15 GAMEOBJECT_TYPE_MO_TRANSPORT
struct
{
uint32 taxiPathId; //0
} moTransport;
//17 GAMEOBJECT_TYPE_FISHINGNODE
struct
{
uint32 _data0;
uint32 lootId; //1
} fishnode;
//18 GAMEOBJECT_TYPE_SUMMONING_RITUAL
struct
{
uint32 reqParticipants; //0
uint32 spellId; //1
} summoningRitual;
//22 GAMEOBJECT_TYPE_SPELLCASTER
struct
{
uint32 spellId; //0
uint32 charges; //1
uint32 partyOnly; //2
uint32 spellId2; //3 (is it used in this way?)
} spellcaster;
//23 GAMEOBJECT_TYPE_MEETINGSTONE
struct
{
uint32 minLevel; //0
uint32 maxLevel; //1
} meetingstone;
//25 GAMEOBJECT_TYPE_FISHINGHOLE // not implemented yet
struct
{
uint32 radius; //0 how close bobber must land for sending loot
uint32 lootId; //1
uint32 minSuccessOpens; //2
uint32 maxSuccessOpens; //3
uint32 lockId; //4 possibly 1628 for all?
} fishinghole;
// not use for specific field access (only for output with loop by all filed), also this determinate max union size
struct // GAMEOBJECT_TYPE_SPELLCASTER
{
uint32 data[GAMEOBJECT_DATA_FIELDS];
} raw;
};
};
class GameObject : public WorldObject
{
public:

View File

@ -30,6 +30,10 @@ void ObjMgr::RemoveAll(void)
{
delete i->second;
}
for(GOTemplateMap::iterator i = _go_templ.begin(); i!=_go_templ.end(); i++)
{
delete i->second;
}
while(_obj.size())
{
Remove(_obj.begin()->first, true);
@ -179,6 +183,31 @@ bool ObjMgr::CreatureNonExistent(uint32 id)
return _nocreature.find(id) != _nocreature.end();
}
// -- Gameobject part --
void ObjMgr::Add(GameobjectTemplate *go)
{
_go_templ[go->entry] = go;
}
GameobjectTemplate *ObjMgr::GetGOTemplate(uint32 entry)
{
GOTemplateMap::iterator it = _go_templ.find(entry);
if(it != _go_templ.end())
return it->second;
return NULL;
}
void ObjMgr::AddNonexistentGO(uint32 id)
{
_nogameobj.insert(id);
}
bool ObjMgr::GONonExistent(uint32 id)
{
return _nogameobj.find(id) != _nogameobj.end();
}
// -- misc part --
void ObjMgr::AddRequestedPlayerGUID(uint32 loguid)

View File

@ -5,9 +5,11 @@
#include <set>
#include "Item.h"
#include "Unit.h"
#include "Gameobject.h"
typedef std::map<uint32,ItemProto*> ItemProtoMap;
typedef std::map<uint32,CreatureTemplate*> CreatureTemplateMap;
typedef std::map<uint32,GameobjectTemplate*> GOTemplateMap;
typedef std::map<uint64,Object*> ObjectMap;
class PseuInstance;
@ -40,6 +42,16 @@ public:
void AddNonexistentCreature(uint32);
bool CreatureNonExistent(uint32);
// Gameobject template functions
uint32 GetGOTemplateCount(void) { return _go_templ.size(); }
GameobjectTemplate *GetGOTemplate(uint32);
void Add(GameobjectTemplate*);
GOTemplateMap *GetGOTemplateStorage(void) { return &_go_templ; }
// nonexistent gameobjects handler
void AddNonexistentGO(uint32);
bool GONonExistent(uint32);
// player names related
void AddRequestedPlayerGUID(uint32);
bool IsRequestedPlayerGUID(uint32);
@ -58,10 +70,13 @@ public:
private:
ItemProtoMap _iproto;
CreatureTemplateMap _creature_templ;
GOTemplateMap _go_templ;
ObjectMap _obj;
std::set<uint32> _noitem;
std::set<uint32> _reqpnames;
std::set<uint32> _nocreature;
std::set<uint32> _nogameobj;
PseuInstance *_instance;
};

View File

@ -468,6 +468,15 @@ void WorldSession::_QueryObjectInfo(uint64 guid)
SendQueryCreature(obj->GetEntry(),guid);
break;
}
case TYPEID_GAMEOBJECT:
{
GameobjectTemplate *go = objmgr.GetGOTemplate(obj->GetEntry());
if(go)
obj->SetName(go->name);
else
SendQueryGameobject(obj->GetEntry(),guid);
break;
}
//case...
}
}

View File

@ -315,6 +315,7 @@ OpcodeHandler *WorldSession::_GetOpcodeHandlerTable() const
{SMSG_NOTIFICATION, &WorldSession::_HandleNotificationOpcode},
{SMSG_WHO, &WorldSession::_HandleWhoOpcode},
{SMSG_CREATURE_QUERY_RESPONSE, &WorldSession::_HandleCreatureQueryResponseOpcode},
{SMSG_GAMEOBJECT_QUERY_RESPONSE, &WorldSession::_HandleGameobjectQueryResponseOpcode},
// table termination
{ 0, NULL }
@ -700,9 +701,11 @@ void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket)
recvPacket >> target_guid >> msglen >> msg;
SCPDatabase *langdb = GetDBMgr().GetDB("language");
const char* ln = "";
const char* ln;
std::string langname;
if(langdb)
langdb->GetString(lang,"name");
langname = langdb->GetString(lang,"name");
ln = langname.c_str();
std::string name;
if(type == CHAT_MSG_MONSTER_SAY)
@ -747,7 +750,7 @@ void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket)
{
logcustom(0,WHITE,"CHAT: %s yells [%s]: %s ",name.c_str(),ln,msg.c_str());
}
else if (type==CHAT_MSG_WHISPER_INFORM )
else if (type==CHAT_MSG_REPLY )
{
logcustom(0,WHITE,"TO %s [%s]: %s",name.c_str(),ln,msg.c_str());
}
@ -1249,6 +1252,7 @@ void WorldSession::_HandleLoginVerifyWorldOpcode(WorldPacket& recvPacket)
// update the world as soon as the server confirmed that we are where we are.
_world->UpdatePos(x,y,m);
_world->Update();
_world->CreateMoveMgr();
// temp. solution to test terrain rendering
if(PseuGUI *gui = GetInstance()->GetGUI())
@ -1371,6 +1375,43 @@ void WorldSession::_HandleCreatureQueryResponseOpcode(WorldPacket& recvPacket)
objmgr.AssignNameToObj(entry, TYPEID_UNIT, ct->name);
}
void WorldSession::_HandleGameobjectQueryResponseOpcode(WorldPacket& recvPacket)
{
uint32 entry;
recvPacket >> entry;
if(entry & 0x80000000)
{
uint32 real_entry = entry & ~0x80000000;
logerror("Gameobject %u does not exist!");
objmgr.AddNonexistentGO(real_entry);
return;
}
std::string other_names, unks;
GameobjectTemplate *go = new GameobjectTemplate();
go->entry = entry;
recvPacket >> go->type;
recvPacket >> go->displayId;
recvPacket >> go->name;
recvPacket >> other_names; // name1
recvPacket >> other_names; // name2
recvPacket >> other_names; // name3 (all unused)
recvPacket >> unks;
recvPacket >> go->castBarCaption;
recvPacket >> unks;
for(uint32 i = 0; i < GAMEOBJECT_DATA_FIELDS; i++)
recvPacket >> go->raw.data[i];
std::stringstream ss;
ss << "Got info for gameobject " << entry << ":" << go->name;
ss << " type " << go->type;
ss << " displayid " << go->displayId;
logdetail("%s",ss.str().c_str());
objmgr.Add(go);
objmgr.AssignNameToObj(entry, TYPEID_GAMEOBJECT, go->name);
}
// TODO: delete world on LogoutComplete once implemented

View File

@ -85,6 +85,7 @@ public:
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 SendQueryGameobject(uint32 entry, uint64 guid = 0);
void HandleWorldPacket(WorldPacket*);
@ -139,6 +140,7 @@ private:
void _HandleNotificationOpcode(WorldPacket& recvPacket);
void _HandleWhoOpcode(WorldPacket& recvPacket);
void _HandleCreatureQueryResponseOpcode(WorldPacket& recvPacket);
void _HandleGameobjectQueryResponseOpcode(WorldPacket& recvPacket);
// helper functions to keep SMSG_(COMPRESSED_)UPDATE_OBJECT easy to handle
void _MovementUpdate(uint8 objtypeid, uint64 guid, WorldPacket& recvPacket); // Helper for _HandleUpdateObjectOpcode