last changes before 2.1.3:

* added script to support /me-like emotes (scriptname is "me")
* changed the permission system: now a script cant be used as game command f no permission is explicitly set
* implemented threadsafe CLI queue to solve crashes with short-intervalled events that ran on 2 threads
* fixed name return at "getitemprotovalue" script
* iplemented DrawObject class and a Mgr for those objects; they will ease object drawing once implemented. the Mgr works under control of the GUI thread and is threadsafe.
* implemented auto-loading of SCP files if a name-tag is present somewhere in the file ("#dbname=...") and no explicit db name was passed to "loadscp" script.
* changed internal ObjMgr storage to std::map (instead of list) for faster access
* fixed call of "_enterworld" script
* fixed handling of MyCharacter(), which could cause crashes after newly changes
* fixed GetFileList() func in tools.cpp (this fixes also related "lgetfiles" script func). now it will only parse files, not directories. might still need some fixing for linux.
This commit is contained in:
False.Genesis 2007-08-01 19:09:17 +00:00
parent 15e24961ce
commit 3100f68a30
31 changed files with 1315 additions and 824 deletions

View File

@ -1,25 +1,31 @@
#permission=255
// PSEUWOW DEF_SCRIPT STARTUP FILE // PSEUWOW DEF_SCRIPT STARTUP FILE
LOG * DefScript StartUp [${@version_short}]... // this is for debugging which scripts are loaded
// set to false to disable output
SET,LoadDebug true
// first, load all scripts in patch 'scripts' with extension .def LOG *** DefScript StartUp [${@version_short}]...
// first, load all scripts in path 'scripts' with extension .def
SET,fcount ?{LGETFILES,scriptlist,def scripts} SET,fcount ?{LGETFILES,scriptlist,def scripts}
LSORT scriptlist LSORT scriptlist
LOGDETAIL * Loading ${fcount} scripts. LOG *** Loading ${fcount} script files.
// iterate over all files and load them; if counter i is equal to the amount of files we are done. // iterate over all files and load them; if counter i is equal to the amount of files we are done.
SET,i 0 SET,i 0
SET,errors 0
LOOP LOOP
IF ?{EQUAL,${i} ${fcount}} IF ?{EQUAL,${i} ${fcount}}
EXITLOOP EXITLOOP
ENDIF ENDIF
SET,fn ./scripts/?{LINDEX,scriptlist ${i}} SET,fn ./scripts/?{LINDEX,scriptlist ${i}}
LOG *** Loading script file [${fn}] IF ?{AND,?{IsSet LoadDebug} ${LoadDebug}}
IF ?{NOT ?{LOADDEF ${fn}}} LOG * Loading script file [${fn}]
LOGERROR Can't load script [${fn}] ENDIF
ENDIF IF ?{NOT ?{LOADDEF ${fn}}}
ADD,i 1 LOGERROR * Error loading [${fn}]
ADD,errors 1
ENDIF
ADD,i 1
ENDLOOP ENDLOOP
UNSET tmp UNSET tmp
@ -28,13 +34,17 @@ UNSET i
UNSET fn UNSET fn
LDELETE scriptlist LDELETE scriptlist
IF ?{NOT ${errors}}
LOG *** All files loaded without errors.
ELSE
LOG *** All files loaded, ${errors} errors.
ENDIF
UNSET errors
// loads & applies the configuration // loads & applies the configuration
CONFIG CONFIG
// set permissions for internal functions // Load some SCP files
INTERNAL_PERM
// Load some SCP files
LOADALLSCP LOADALLSCP
// do more stuff here in future... // do more stuff here in future...

View File

@ -51,13 +51,13 @@ UNSET msg
//----------------------------------------------------------- //-----------------------------------------------------------
// is the char equal to the char we use for commands? does the player have a permission lvl below 255? // is the char equal to the char we use for commands? does the player have a permission lvl below 255?
IF ?{AND,?{string_is_command ${@def}} ?{SMALLER,?{GETPLAYERPERM ${@thiscmd_name}} 255}} IF ?{AND,?{string_is_command ${@def}} ?{SMALLER,?{GETPLAYERPERM ${@thiscmd_name}} 255}}
// yes: say a warning and the command the player wanted to use // yes: say a warning and the command the player wanted to use
SAY ${@thiscmd_name}: no permission to use commands [${@def}] SAY ${@thiscmd_name}: no permission to use commands [${@def}]
RETURN false RETURN false
ELSE ELSE
// no: say the text as usual. // no: say the text as usual.
SAY,{${@0}} ${@def} SAY,{${@0}} ${@def}
RETURN true RETURN true
ENDIF ENDIF
@ -140,10 +140,10 @@ SET,vl ${@0}
DEFAULT,vl 0 DEFAULT,vl 0
IF ?{NOT ?{ISSET ${vn}}} IF ?{NOT ?{ISSET ${vn}}}
SAY,{${vl}} * Var '${@def}' not defined. SAY,{${vl}} * Var '${@def}' not defined.
ELSE ELSE
SET,vv ${${vn}} SET,vv ${${vn}}
SAY,{${vl}} * Var '${@def}' = '${vv}' SAY,{${vl}} * Var '${@def}' = '${vv}'
ENDIF ENDIF
UNSET vv UNSET vv
@ -200,11 +200,30 @@ UNSET msg
//----------------------------------------------------------- //-----------------------------------------------------------
// is the char equal to the char we use for commands? does the player have a permission lvl below 255? // is the char equal to the char we use for commands? does the player have a permission lvl below 255?
IF ?{AND,?{string_is_command ${@def}} ?{SMALLER,?{GETPLAYERPERM ${@thiscmd_name}} 255}} IF ?{AND,?{string_is_command ${@def}} ?{SMALLER,?{GETPLAYERPERM ${@thiscmd_name}} 255}}
// yes: say a warning and the command the player wanted to use // yes: say a warning and the command the player wanted to use
YELL ${@thiscmd_name}: no permission to use commands [${@def}] YELL ${@thiscmd_name}: no permission to use commands [${@def}]
RETURN false RETURN false
ELSE ELSE
// no: say the text as usual. // no: say the text as usual.
YELL,{${@0}} ${@def} YELL,{${@0}} ${@def}
RETURN true RETURN true
ENDIF ENDIF
//----------------------------------------------------------
#script=me
#permission=0
//----------------------------------------------------------
// Send text emote. example: "me feels lolo" will result in "Pseuwow feels lolo" at other clients
SET,lang ${@0}
SET,msg ${@def}
DEFAULT,#DEFAULTLANG ?{GETSCPVALUE,race,{${@myrace}} faction}
DEFAULT,lang ${#DEFAULTLANG}
LOGDEBUG * Me ${msg} (in lang ${lang})
SENDCHATMESSAGE,8,${lang},{${msg}}
UNSET lang
UNSET msg

View File

@ -1,12 +1,11 @@
// core functions. required by other scripts to run! // core functions. required by other scripts to run!
#onload #onload
log * Loading core scripts... log * Loading core scripts...
#/onload #/onload
//-------------------------------------------------------- //--------------------------------------------------------
#script=append #script=append
#permission=255
//-------------------------------------------------------- //--------------------------------------------------------
// usage: append text to a string. // usage: append text to a string.
// args: // args:
@ -28,9 +27,9 @@ UNSET v
#permission=255 #permission=255
//-------------------------------------------------------- //--------------------------------------------------------
if ?{fileexists ${@def}} if ?{fileexists ${@def}}
loadscp,{${@0}} ${@def} loadscp,{${@0}} ${@def}
else else
logdebug skipped loading of non-existent file '${@def}' logdebug skipped loading of non-existent file '${@def}'
endif endif
@ -53,13 +52,13 @@ LOADSCP,race data/scp/race.scp
// load extended databases if present. // load extended databases if present.
EXLOADSCP,sound data/scp/sound.scp EXLOADSCP,sound data/scp/sound.scp
EXLOADSCP,emote data/scp/emote.scp EXLOADSCP,emote data/scp/emote.scp
EXLOADSCP,area data/scp/area.scp
LOG * SCP loaded. LOG * SCP loaded.
//------------------------------------------------- //-------------------------------------------------
#script=string_is_command #script=string_is_command
#permission=255
//------------------------------------------------- //-------------------------------------------------
// purpose: detect if @def might be a server command. // purpose: detect if @def might be a server command.
@ -71,8 +70,8 @@ SET,c ?{SUBSTR,1 ${@def}}
// does the char list contain our first char? if yes it can trigger a server command. // does the char list contain our first char? if yes it can trigger a server command.
if ?{lcontains,#CMDCHARLIST ${c}} if ?{lcontains,#CMDCHARLIST ${c}}
unset c unset c
return true return true
endif endif
unset c unset c
return false return false
@ -80,7 +79,6 @@ return false
//-------------------------------------------------------- //--------------------------------------------------------
#script=normalize_name #script=normalize_name
#permission=255
//-------------------------------------------------------- //--------------------------------------------------------
// uppercases first char, lowercases rest // uppercases first char, lowercases rest
set,name ?{uppercase ?{substr,1 ${@def}}} set,name ?{uppercase ?{substr,1 ${@def}}}
@ -91,14 +89,13 @@ return ${name}
//--------------------------------------------------------- //---------------------------------------------------------
#script=globname #script=globname
#permission=255
//--------------------------------------------------------- //---------------------------------------------------------
// purpose: returns the global name of a variable // purpose: returns the global name of a variable
// args: @def: var name, @0 (optional): name of the intended parent func // args: @def: var name, @0 (optional): name of the intended parent func
set,c ?{substr,1 ${@def}} set,c ?{substr,1 ${@def}}
// it is a global var if the varname starts with # or there is no caller script // it is a global var if the varname starts with # or there is no caller script
if ?{or,?{equal,# ${c}} ?{not ${@caller}}} if ?{or,?{equal,# ${c}} ?{not ${@caller}}}
return ${@def} return ${@def}
endif endif
set,top ${@0} set,top ${@0}
default,top ${@caller} default,top ${@caller}
@ -107,7 +104,6 @@ return #${top}::${@def}
//--------------------------------------------------------- //---------------------------------------------------------
#script=getvar #script=getvar
#permission=255
//--------------------------------------------------------- //---------------------------------------------------------
// purpose: returns the value of a variable. if the variable hasnt been set return empty string. // purpose: returns the value of a variable. if the variable hasnt been set return empty string.
set,top ${@caller} set,top ${@caller}
@ -116,8 +112,30 @@ set,v ?{globname,${top} ${@def}}
unset top unset top
out getvar: v=${v} -> ${${v}} out getvar: v=${v} -> ${${v}}
if ?{isset ${v}} if ?{isset ${v}}
return ${${v}} return ${${v}}
endif endif
return return
//---------------------------------------------------------
#script=reverse
//---------------------------------------------------------
// purpose: reverse a srtring
// args: @def: string to reverse
// returns: reversed string
set,outstr
set,elems ?{lsplit,mylist ${@def}}
set,i ${elems}
loop
sub,i 1
if ?{equal,${i} -1}
exitloop
endif
append,outstr ?{lindex,mylist ${i}}
endloop
ldelete mylist
return ${outstr}

View File

@ -10,21 +10,21 @@
// we can use this script only if we are in the world // we can use this script only if we are in the world
if ?{not ${@inworld}} if ?{not ${@inworld}}
logerror Can't slap anything if i am not in the world! logerror Can't slap anything if i am not in the world!
return return
endif endif
// normalize player name. first char uppercased, rest lowercased. // normalize player name. first char uppercased, rest lowercased.
set,name ?{normalize_name ${@def}} set,name ?{normalize_name ${@def}}
// target the player. if targeting was successful, cast spell "Knockback 500". // target the player. if targeting was successful, cast spell "Knockback 500".
set,t ?{target ${name}} set,t ?{target ${name}}
if ${t} if ${t}
logdebug slapping player '${name}' logdebug slapping player '${name}'
castspell 11027 castspell 11027
target target
else else
logerror Can't target player '${name}' logerror Can't target player '${name}'
endif endif
unset name unset name
@ -35,15 +35,14 @@ return ${t}
//------------------------------------------------ //------------------------------------------------
#script=toleet #script=toleet
#permission=255
//------------------------------------------------ //------------------------------------------------
// purpose: convert any text into leetspeak [1337sp34k] // purpose: convert any text into leetspeak [1337sp34k]
// args: @def: the text to convert // args: @def: the text to convert
// returns: leetspeak^^ // returns: leetspeak^^
#onload #onload
// this can be used by other scripts to check if we have loaded this script // this can be used by other scripts to check if we have loaded this script
set,#HAVE_LEET true set,#HAVE_LEET true
#endonload #endonload
// empty the string where the leet will be stored // empty the string where the leet will be stored
@ -55,65 +54,65 @@ set,x 0
loop loop
// check if we have reached the end of the string // check if we have reached the end of the string
if ?{bigger,${x} ${l}} if ?{bigger,${x} ${l}}
exitloop exitloop
endif endif
// c stores current char (@def at position x); c2 is the same char but always lowercased // c stores current char (@def at position x); c2 is the same char but always lowercased
set,c ?{substr,1,${x} ${@def}} set,c ?{substr,1,${x} ${@def}}
set,c2 ?{lowercase ${c}} set,c2 ?{lowercase ${c}}
// conversion functions: // conversion functions:
// note that "+" is a variable name here! // note that "+" is a variable name here!
// it will store the "new" char if c/c2 could be converted // it will store the "new" char if c/c2 could be converted
if ?{equal,${c2} a} if ?{equal,${c2} a}
set,+ 4 set,+ 4
endif endif
if ?{equal,${c2} e} if ?{equal,${c2} e}
set,+ 3 set,+ 3
endif endif
if ?{equal,${c2} i} if ?{equal,${c2} i}
set,+ ! set,+ !
endif endif
if ?{equal,${c2} l} if ?{equal,${c2} l}
set,+ 1 set,+ 1
endif endif
if ?{equal,${c2} t} if ?{equal,${c2} t}
set,+ 7 set,+ 7
endif endif
if ?{equal,${c2} s} if ?{equal,${c2} s}
set,+ 5 set,+ 5
endif endif
if ?{equal,${c2} o} if ?{equal,${c2} o}
set,+ 0 set,+ 0
endif endif
if ?{equal,${c2} f} if ?{equal,${c2} f}
set,+ ph set,+ ph
endif endif
if ?{equal,${c2} h} if ?{equal,${c2} h}
set,+ # set,+ #
endif endif
if ?{equal,${c} Z} if ?{equal,${c} Z}
set,+ 7 set,+ 7
endif endif
if ?{equal,${c} R} if ?{equal,${c} R}
set,+ 2 set,+ 2
endif endif
if ?{equal,${c} B} if ?{equal,${c} B}
set,+ <3 set,+ <3
endif endif
// if var "+" is still empty, default it to our current char // if var "+" is still empty, default it to our current char
default,+ ${c} default,+ ${c}
// and append it to the final output // and append it to the final output
append,str ${+} append,str ${+}
// finally delete it again // finally delete it again
unset + unset +
// and increase the counter by 1 // and increase the counter by 1
add,x 1 add,x 1
endloop endloop
unset l unset l

View File

@ -39,6 +39,7 @@ LOGDETAIL * Dangerous variables removed.
//----------------------------------------------- //-----------------------------------------------
// Load all conf files from directory /conf/ // Load all conf files from directory /conf/
// get all *.conf file names from /conf/ directory, store the names in list 'fl' and the amount in 'fcount' // get all *.conf file names from /conf/ directory, store the names in list 'fl' and the amount in 'fcount'
LOG ** Configuring PseuWoW...
SET,fcount ?{LGETFILES,fl,conf conf} SET,fcount ?{LGETFILES,fl,conf conf}
// sort the list, load conf files alphabetically. // sort the list, load conf files alphabetically.
LSORT fl LSORT fl
@ -76,9 +77,14 @@ APPLYPERMISSIONS
// remove dangerous variables // remove dangerous variables
CLEANUPVARS CLEANUPVARS
// set permissions for internal functions
INTERNAL_PERM
// if its not set in the conf file, default it to "." (WoWEmu & MaNGOS style) // if its not set in the conf file, default it to "." (WoWEmu & MaNGOS style)
DEFAULT,#CMDCHAR . DEFAULT,#CMDCHAR .
LOG ** All Config done.
//-------------------------------------------------- //--------------------------------------------------
#script=internal_perm #script=internal_perm

View File

@ -2,7 +2,6 @@
//-------------------------------------------- //--------------------------------------------
#script=lcontains #script=lcontains
#permission=255
//-------------------------------------------- //--------------------------------------------
// return true if any list element matches @def, else return false. // return true if any list element matches @def, else return false.
// @0: list name, @def: search string // @0: list name, @def: search string
@ -11,23 +10,22 @@ set,i 0
set,l ?{globname ${@0}} set,l ?{globname ${@0}}
out list: ${l} - len: ?{llen ${l}} out list: ${l} - len: ?{llen ${l}}
if ?{not ?{llen ${l}}} if ?{not ?{llen ${l}}}
return return
endif endif
set,result false set,result false
loop loop
out eq:?{equal,${i} ?{llen ${l}}} i:${i} len:?{llen ${l}} if ?{equal,${i} ?{llen ${l}}}
if ?{equal,${i} ?{llen ${l}}} exitloop
exitloop endif
endif set,elem ?{lindex,{${l}} ${i}}
set,elem ?{lindex,{${l}} ${i}} if ?{equal,{${elem}} ${@def}}
if ?{equal,{${elem}} ${@def}} set,result true
set,result true exitloop
exitloop endif
endif add,i 1
add,i 1
endloop endloop
unset i unset i
unset l unset l

View File

@ -2,6 +2,7 @@
//------------------------------------------------ //------------------------------------------------
#script=gc #script=gc
#permission=0
//------------------------------------------------ //------------------------------------------------
// example script to write into channel "generalchat" // example script to write into channel "generalchat"
// usage: "gc bla bla..." // usage: "gc bla bla..."

View File

@ -1,6 +1,4 @@
#permission=255 // this script gets executed if a player tries to give pseuwow a command but is not allowed to
// GETS EXECUTED IF A PLAYER TRIES TO GIVE PSEUWOW A COMMAND AND IS NOT ALLOWED TO
// Arguments: // Arguments:
// ========== // ==========

View File

@ -1,5 +1,3 @@
#permission=255
// EXECUTED EVERYTIME A WHISPER IS BEEING RECIEVED // EXECUTED EVERYTIME A WHISPER IS BEEING RECIEVED
// comment out the following line if you dont need it // comment out the following line if you dont need it

View File

@ -22,26 +22,21 @@ void CliRunnable::run(void)
if (in == NULL) if (in == NULL)
return; return;
for(int i=0;in[i];i++) for(int i=0;in[i];i++)
if(in[i]=='\r'||in[i]=='\n') if(in[i]=='\r'||in[i]=='\n')
{ {
in[i]=0; in[i]=0;
break; break;
} }
if(in[0]==0) if(in[0]==0)
continue; continue;
if(in[0]=='!') if(in[0]=='!')
cur = &in[1]; cur = &in[1];
else else
{ {
try out = cur.empty() ? in : (cur+" "+in);
{ _instance->AddCliCommand(out);
out = cur.empty() ? in : (cur+" "+in); // add delay just if necessary
_instance->GetScripts()->RunSingleLine(out); //ZThread::Thread::sleep(50);
}
catch (...)
{
printf("Exception while executing CLI command!\n");
}
} }
} }
} }

View File

@ -146,7 +146,7 @@ bool VarSet::ReadVarsFromFile(std::string fn)
unsigned int pos=line.find("="); unsigned int pos=line.find("=");
if(pos!=std::string::npos) if(pos!=std::string::npos)
{ {
std::string v=line.substr(0,pos);; std::string v=line.substr(0,pos);
if(upper) if(upper)
v=toUpper(v); v=toUpper(v);

View File

@ -94,7 +94,7 @@ DefReturnResult DefScriptPackage::SCsavecache(CmdSet& Set){
str << ((PseuInstance*)parentMethod)->GetWSession()->objmgr.GetItemProtoCount(); str << ((PseuInstance*)parentMethod)->GetWSession()->objmgr.GetItemProtoCount();
str << " Item Prototypes"; str << " Item Prototypes";
str << " ]"; str << " ]";
((PseuInstance*)parentMethod)->GetWSession()->SendChatMessage(CHAT_MSG_SAY,0,str.str(),""); ((PseuInstance*)parentMethod)->GetWSession()->SendChatMessage(CHAT_MSG_SAY,0,str.str(),"");
} }
return true; return true;
@ -135,7 +135,7 @@ DefReturnResult DefScriptPackage::SCemote(CmdSet& Set){
DefReturnResult DefScriptPackage::SCfollow(CmdSet& Set) DefReturnResult DefScriptPackage::SCfollow(CmdSet& Set)
{ {
DEF_RETURN_ERROR; // prevent execution for now DEF_RETURN_ERROR; // prevent execution for now
/* /*
WorldSession *ws=((PseuInstance*)parentMethod)->GetWSession(); WorldSession *ws=((PseuInstance*)parentMethod)->GetWSession();
if(Set.defaultarg.empty()){ if(Set.defaultarg.empty()){
ws->SendChatMessage(CHAT_MSG_SAY,0,"Stopping! (Please give me a Playername to follow!)",""); ws->SendChatMessage(CHAT_MSG_SAY,0,"Stopping! (Please give me a Playername to follow!)","");
@ -149,7 +149,7 @@ DefReturnResult DefScriptPackage::SCfollow(CmdSet& Set)
else else
ss << "Can't follow player '"<<Set.defaultarg<<"' (not known)"; ss << "Can't follow player '"<<Set.defaultarg<<"' (not known)";
ws->SendChatMessage(CHAT_MSG_SAY,0,ss.str(),""); ws->SendChatMessage(CHAT_MSG_SAY,0,ss.str(),"");
*/ */
return true; return true;
} }
@ -228,23 +228,23 @@ DefReturnResult DefScriptPackage::SClogerror(CmdSet& Set){
DefReturnResult DefScriptPackage::SCcastspell(CmdSet& Set) DefReturnResult DefScriptPackage::SCcastspell(CmdSet& Set)
{ {
if(Set.defaultarg.empty()) if(Set.defaultarg.empty())
return false; return false;
if(!(((PseuInstance*)parentMethod)->GetWSession())) if(!(((PseuInstance*)parentMethod)->GetWSession()))
{ {
logerror("Invalid Script call: SCcastspell: WorldSession not valid"); logerror("Invalid Script call: SCcastspell: WorldSession not valid");
DEF_RETURN_ERROR; DEF_RETURN_ERROR;
} }
uint32 spellId = atoi(Set.defaultarg.c_str()); uint32 spellId = atoi(Set.defaultarg.c_str());
if (spellId <= 0) if (spellId <= 0)
{ {
return false; return false;
} }
((PseuInstance*)parentMethod)->GetWSession()->SendCastSpell(spellId); ((PseuInstance*)parentMethod)->GetWSession()->SendCastSpell(spellId);
return true; return true;
} }
DefReturnResult DefScriptPackage::SCqueryitem(CmdSet& Set){ DefReturnResult DefScriptPackage::SCqueryitem(CmdSet& Set){
@ -297,22 +297,32 @@ DefReturnResult DefScriptPackage::SCtarget(CmdSet& Set)
DefReturnResult DefScriptPackage::SCloadscp(CmdSet& Set) DefReturnResult DefScriptPackage::SCloadscp(CmdSet& Set)
{ {
DefReturnResult r; SCPDatabaseMgr& dbmgr = ((PseuInstance*)parentMethod)->dbmgr;
if(Set.arg[0].empty() || Set.defaultarg.empty()) if(Set.defaultarg.empty()) // exit if no filename was given
return false; return false;
std::string dbname = stringToLower(Set.arg[0]); std::string dbname = stringToLower(Set.arg[0]);
// TODO: remove db if loading was not successful uint32 sections = 0;
uint32 sections=((PseuInstance*)parentMethod)->dbmgr.GetDB(dbname).LoadFromFile((char*)Set.defaultarg.c_str()); if(dbname.empty()) // if no db name was supplied, try to find it automatically in the file ("#dbname=...")
if(sections)
{ {
logdetail("Loaded SCP: \"%s\" [%s] (%u sections)",dbname.c_str(),Set.defaultarg.c_str(),sections); sections = dbmgr.AutoLoadFile((char*)Set.defaultarg.c_str());
if(!sections)
{
logerror("Tried to auto-load SCP file: \"%s\", but no name tag found. skipped.");
}
} }
else else
{ {
logerror("Failed to load SCP: \"%s\" [%s]",dbname.c_str(),Set.defaultarg.c_str()); sections = dbmgr.GetDB(dbname).LoadFromFile((char*)Set.defaultarg.c_str());
if(sections)
{
logdetail("Loaded SCP: \"%s\" [%s] (%u sections)",dbname.c_str(),Set.defaultarg.c_str(),sections);
}
else
{
logerror("Failed to load SCP: \"%s\" [%s]",dbname.c_str(),Set.defaultarg.c_str());
}
} }
r.ret=toString((uint64)sections); return toString((uint64)sections);;
return r;
} }
DefReturnResult DefScriptPackage::SCScpExists(CmdSet& Set) DefReturnResult DefScriptPackage::SCScpExists(CmdSet& Set)
@ -519,10 +529,10 @@ DefReturnResult DefScriptPackage::SCGetItemProtoValue(CmdSet& Set)
uint32 tmp=0; uint32 tmp=0;
if(t=="class") r.ret=toString(proto->Class); if(t=="class") r.ret=toString(proto->Class);
else if(t=="subclass") r.ret=toString(proto->SubClass); else if(t=="subclass") r.ret=toString(proto->SubClass);
else if(t=="name1" || t=="name") proto->Name[0]; else if(t=="name1" || t=="name") r.ret=proto->Name[0];
else if(t=="name2") proto->Name[1]; else if(t=="name2") r.ret=proto->Name[1];
else if(t=="name3") proto->Name[2]; else if(t=="name3") r.ret=proto->Name[2];
else if(t=="name4") proto->Name[3]; else if(t=="name4") r.ret=proto->Name[3];
else if(t=="model" || t=="displayid") r.ret=toString(proto->DisplayInfoID); else if(t=="model" || t=="displayid") r.ret=toString(proto->DisplayInfoID);
else if(t=="quality") r.ret=toString(proto->Quality); else if(t=="quality") r.ret=toString(proto->Quality);
else if(t=="flags") r.ret=toString(proto->Flags); else if(t=="flags") r.ret=toString(proto->Flags);
@ -756,7 +766,7 @@ void DefScriptPackage::My_LoadUserPermissions(VarSet &vs)
{ {
sub = variables[i].name.substr(0,strlen(prefix)); sub = variables[i].name.substr(0,strlen(prefix));
if(sub == prefix) if(sub == prefix)
{ {
usr = variables[i].name.substr(strlen(prefix), variables[i].name.length() - strlen(prefix)); usr = variables[i].name.substr(strlen(prefix), variables[i].name.length() - strlen(prefix));
my_usrPermissionMap[usr] = atoi(variables[i].value.c_str()); my_usrPermissionMap[usr] = atoi(variables[i].value.c_str());
DEBUG( logdebug("Player '%s' permission = %u",usr.c_str(),atoi(variables[i].value.c_str())); ) DEBUG( logdebug("Player '%s' permission = %u",usr.c_str(),atoi(variables[i].value.c_str())); )
@ -766,7 +776,7 @@ void DefScriptPackage::My_LoadUserPermissions(VarSet &vs)
void DefScriptPackage::My_Run(std::string line, std::string username) void DefScriptPackage::My_Run(std::string line, std::string username)
{ {
uint8 scperm=255; // builtin functions that have no explicit req. permission level assigned should be secure from beeing called int16 scperm = -1; // builtin functions that have no explicit req. permission level assigned should be secure from beeing called from ingame
uint8 usrperm=0; // users/players that have no explicit permission assigned should have minimal permission uint8 usrperm=0; // users/players that have no explicit permission assigned should have minimal permission
for (std::map<std::string,unsigned char>::iterator i = my_usrPermissionMap.begin(); i != my_usrPermissionMap.end(); i++) for (std::map<std::string,unsigned char>::iterator i = my_usrPermissionMap.begin(); i != my_usrPermissionMap.end(); i++)
@ -778,16 +788,15 @@ void DefScriptPackage::My_Run(std::string line, std::string username)
} }
DefXChgResult final; DefXChgResult final;
if(usrperm < 255) if(usrperm < 255 && line.find("?{")!=std::string::npos)
{ {
if(line.find("?{")!=std::string::npos) logerror("WARNING: %s wanted to exec \"%s\"",username.c_str(),line.c_str());
logerror("WARNING: %s wanted to exec \"%s\"",username.c_str(),line.c_str());
final=ReplaceVars(line,NULL,0,false); // prevent execution of embedded scripts (= using return values) that could trigger dangerous stuff. final=ReplaceVars(line,NULL,0,false); // prevent execution of embedded scripts (= using return values) that could trigger dangerous stuff.
} }
else else
final=ReplaceVars(line,NULL,0,true); // exec as usual final=ReplaceVars(line,NULL,0,true); // exec as usual
CmdSet curSet; CmdSet curSet;
SplitLine(curSet,final.str); SplitLine(curSet,final.str);
@ -799,17 +808,22 @@ void DefScriptPackage::My_Run(std::string line, std::string username)
} }
} }
if(usrperm < scperm)
if(scperm > 0) // skip "invisible" scripts (without any permission set) completely.
{ {
CmdSet Set; if(usrperm < scperm)
Set.arg[0] = username; {
Set.arg[1] = toString(usrperm); CmdSet Set;
Set.arg[2] = toString(scperm); Set.arg[0] = username;
Set.arg[3] = curSet.cmd; Set.arg[1] = toString(usrperm);
RunScript("_nopermission",&Set); Set.arg[2] = toString(scperm);
return; Set.arg[3] = curSet.cmd;
RunScript("_nopermission",&Set);
return;
}
} }
Interpret(curSet); Interpret(curSet);
} }

View File

@ -0,0 +1,67 @@
#include "common.h"
#include "log.h"
#include "DrawObject.h"
#include "DrawObjMgr.h"
DrawObjMgr::DrawObjMgr()
{
DEBUG( logdebug("DrawObjMgr created") );
}
DrawObjMgr::~DrawObjMgr()
{
DEBUG( logdebug("~DrawObjMgr(), deleting %u DrawObjects...", _storage.size() ) );
for(DrawObjStorage::iterator i = _storage.begin(); i != _storage.end(); i++)
{
DEBUG( logdebug("del for guid "I64FMT, i->first) );
delete i->second; // this can be done safely, since the object ptrs are not accessed
}
}
void DrawObjMgr::Add(uint64 objguid, DrawObject *o)
{
_add.add(std::pair<uint64,DrawObject*>(objguid,o));
}
void DrawObjMgr::Delete(uint64 guid)
{
_del.add(guid);
}
void DrawObjMgr::Update(void)
{
ZThread::FastMutex mut;
// now for the threadsafe part: lock every thread except this one
// to prevent obj ptr corruption caused by other running threads
// TODO: lock only main thread (that should be the only one to delete objects anyway!)
mut.acquire();
// add objects waiting on the add queue to the real storage
while(_add.size())
{
std::pair<uint64,DrawObject*> p = _add.next();
_storage[p.first] = p.second;
}
// same for objects that should be deleted
while(_del.size())
{
uint64 guid = _del.next();
if(_storage.find(guid) != _storage.end())
{
DrawObject *o = _storage[guid];
_storage.erase(guid);
delete o;
}
}
// now draw everything
for(DrawObjStorage::iterator i = _storage.begin(); i != _storage.end(); i++)
{
i->second->Draw();
}
mut.release();
}

View File

@ -0,0 +1,27 @@
#ifndef DRAWOBJMGR_H
#define DRAWOBJMGR_H
#include <utility>
class DrawObject;
typedef std::map<uint64,DrawObject*> DrawObjStorage;
class DrawObjMgr
{
public:
DrawObjMgr();
~DrawObjMgr();
void Add(uint64,DrawObject*);
void Delete(uint64);
void Update(void); // Threadsafe! delete code must be called from here!
uint32 StorageSize(void) { return _storage.size(); }
private:
DrawObjStorage _storage;
ZThread::LockedQueue<uint64,ZThread::FastMutex> _del;
ZThread::LockedQueue<std::pair<uint64,DrawObject*>,ZThread::FastMutex > _add;
};
#endif

View File

@ -0,0 +1,21 @@
#include "common.h"
#include "PseuGui.h"
#include "DrawObject.h"
#include "PseuWoW.h"
DrawObject::DrawObject(irr::scene::ISceneManager *smgr, Object *obj)
{
_smgr = smgr;
_obj = obj;
DEBUG( logdebug("create DrawObject() this=%X obj=%X smgr=%X",this,_obj,_smgr) );
}
DrawObject::~DrawObject()
{
DEBUG( logdebug("~DrawObject() this=%X obj=%X smgr=%X",this,_obj,_smgr) );
}
void DrawObject::Draw(void)
{
}

View File

@ -0,0 +1,23 @@
#ifndef DRAWOBJECT_H
#define DRAWOBJECT_H
#include "common.h"
#include "irrlicht/irrlicht.h"
class Object;
class DrawObject
{
public:
DrawObject(irr::scene::ISceneManager*, Object*);
~DrawObject();
void Draw(void); // call only in threadsafe environment!! (ensure the obj ptr is still valid!)
// additionally, we dont use a GetObject() func - that would fuck things up if the object was already deleted.
private:
Object *_obj;
irr::scene::ISceneManager *_smgr;
};
#endif

View File

@ -1,5 +1,7 @@
#include "common.h" #include "common.h"
#include "irrlicht/irrlicht.h" #include "irrlicht/irrlicht.h"
#include "Object.h"
#include "DrawObject.h"
#include "PseuWoW.h" #include "PseuWoW.h"
#include "PseuGUI.h" #include "PseuGUI.h"
@ -55,115 +57,145 @@ PseuGUI::PseuGUI()
PseuGUI::~PseuGUI() PseuGUI::~PseuGUI()
{ {
this->Shutdown(); this->Cancel();
} _instance->DeleteGUI(); // this makes the instance set its gui ptr to NULL
void PseuGUI::SetInstance(PseuInstance *i)
{
_instance = i;
} }
void PseuGUI::SetDriver(uint8 driverId) void PseuGUI::SetDriver(uint8 driverId)
{ {
switch(driverId) switch(driverId)
{ {
case DIRECTX9: _driverType = video::EDT_DIRECT3D9;break; case DIRECTX9: _driverType = video::EDT_DIRECT3D9;break;
case DIRECTX8: _driverType = video::EDT_DIRECT3D8;break; case DIRECTX8: _driverType = video::EDT_DIRECT3D8;break;
case OPENGL: _driverType = video::EDT_OPENGL; break; case OPENGL: _driverType = video::EDT_OPENGL; break;
case SOFTWARE: _driverType = video::EDT_SOFTWARE; break; case SOFTWARE: _driverType = video::EDT_SOFTWARE; break;
case BURNINGSVIDEO: _driverType = video::EDT_BURNINGSVIDEO;break; case BURNINGSVIDEO: _driverType = video::EDT_BURNINGSVIDEO;break;
case NULLDEVICE: _driverType = video::EDT_NULL; break; case NULLDEVICE: _driverType = video::EDT_NULL; break;
default: _driverType = video::EDT_BURNINGSVIDEO; // if no valid driver detected, use software default: _driverType = video::EDT_BURNINGSVIDEO; // if no valid driver detected, use software
} }
// TODO: add support for changing driver during runtime? // TODO: add support for changing driver during runtime?
} }
void PseuGUI::SetResolution(uint16 x, uint16 y, uint16 depth) void PseuGUI::SetResolution(uint16 x, uint16 y, uint16 depth)
{ {
_xres = x; _xres = x;
_yres = y; _yres = y;
_colordepth = depth; _colordepth = depth;
} }
void PseuGUI::SetWindowed(bool b) void PseuGUI::SetWindowed(bool b)
{ {
_windowed = b; _windowed = b;
// see PseuGUI::Init(): !_windowed == fullscreen // see PseuGUI::Init(): !_windowed == fullscreen
} }
void PseuGUI::SetVSync(bool b) void PseuGUI::SetVSync(bool b)
{ {
_vsync = b; _vsync = b;
} }
void PseuGUI::UseShadows(bool b) void PseuGUI::UseShadows(bool b)
{ {
_shadows = b; _shadows = b;
} }
// if this fuction is called from another thread the device will not work correctly. o_O // if this fuction is called from another thread the device will not work correctly. o_O
void PseuGUI::_Init(void) void PseuGUI::_Init(void)
{ {
_device = createDevice(_driverType,dimension2d<s32>(_xres,_yres),_colordepth,!_windowed,_shadows,_vsync); _device = createDevice(_driverType,dimension2d<s32>(_xres,_yres),_colordepth,!_windowed,_shadows,_vsync);
DEBUG(logdebug("PseuGUI::Init() _device=%X",_device)); DEBUG(logdebug("PseuGUI::Init() _device=%X",_device));
_device->setWindowCaption(L"PseuWoW - Initializing"); _device->setWindowCaption(L"PseuWoW - Initializing");
_driver = _device->getVideoDriver(); _driver = _device->getVideoDriver();
_smgr = _device->getSceneManager(); _smgr = _device->getSceneManager();
//... //...
_initialized = true; _initialized = true;
} }
void PseuGUI::Shutdown(void) void PseuGUI::Cancel(void)
{ {
DEBUG(logdebug("PseuGUI::Shutdown()")); DEBUG(logdebug("PseuGUI::Cancel()"));
_mustdie = true; _mustdie = true;
if(_device) if(_device)
{ {
_device->drop(); _device->drop();
_device = NULL; _device = NULL;
} }
} }
void PseuGUI::Run(void) void PseuGUI::Shutdown(void)
{ {
if(!_initialized) DEBUG(logdebug("PseuGUI::Shutdown()"));
this->_Init(); _mustdie = true;
}
DEBUG(logdebug("PseuGUI::Run() _device=%X",_device));
void PseuGUI::Run(void)
int lastFPS = -1, fps = -1; {
if(!_initialized)
while(_device && _device->run() && !_mustdie) this->_Init();
{
if (!_device->isWindowActive()) DEBUG(logdebug("PseuGUI::Run() _device=%X",_device));
{
_device->sleep(10); // save cpu & gpu power if not focused int lastFPS = -1, fps = -1;
}
_driver->beginScene(true, true, 0); while(_device && _device->run() && !_mustdie)
{
_smgr->drawAll(); if (!_device->isWindowActive())
{
_driver->endScene(); _device->sleep(10); // save cpu & gpu power if not focused
}
fps = _driver->getFPS();
try
if (lastFPS != fps) {
{ _driver->beginScene(true, true, 0);
core::stringw str = L"PseuWoW [";
str += _driver->getName(); domgr.Update(); // iterate over DrawObjects, draw them and clean up
str += "] FPS:";
str += fps; _smgr->drawAll();
_device->setWindowCaption(str.c_str()); _driver->endScene();
}
lastFPS = fps; catch(...)
DEBUG(logdebug("PseuGUI: Current FPS: %u",fps)); {
} logerror("Unhandled exception in PseuGUI::Run() device=%X smgr=%X objects:%u", _device, _smgr, domgr.StorageSize());
}
}
DEBUG(logdebug("PseuGUI::Run() finished")); fps = _driver->getFPS();
Shutdown();
} if (lastFPS != fps)
{
core::stringw str = L"PseuWoW [";
str += _driver->getName();
str += "] FPS:";
str += fps;
_device->setWindowCaption(str.c_str());
lastFPS = fps;
DEBUG(logdebug("PseuGUI: Current FPS: %u",fps));
}
}
DEBUG(logdebug("PseuGUI::Run() finished"));
Cancel(); // already got shut down somehow, we can now safely cancel and drop the device
}
// called from ObjMgr::Remove(guid)
void PseuGUI::NotifyObjectDeletion(uint64 guid)
{
domgr.Delete(guid);
}
// called from ObjMgr::Add(Object*)
void PseuGUI::NotifyObjectCreation(Object *o)
{
DrawObject *d = new DrawObject(_smgr,o);
domgr.Add(o->GetGUID(),d);
}
void PseuGUI::SetInstance(PseuInstance* in)
{
_instance = in;
}

View File

@ -2,11 +2,12 @@
#define PSEUGUI_H #define PSEUGUI_H
#include "irrlicht/irrlicht.h" #include "irrlicht/irrlicht.h"
#include "DrawObjMgr.h"
class PseuGUI; class PseuGUI;
class Object;
class PseuInstance; class PseuInstance;
class PseuGUIRunnable : public ZThread::Runnable class PseuGUIRunnable : public ZThread::Runnable
{ {
public: public:
@ -25,26 +26,33 @@ public:
PseuGUI(); PseuGUI();
~PseuGUI(); ~PseuGUI();
void Run(void);
void SetInstance(PseuInstance*); void SetInstance(PseuInstance*);
void Run(void);
void SetDriver(uint8); void SetDriver(uint8);
void SetResolution(uint16 x, uint16 y, uint16 depth=32); void SetResolution(uint16 x, uint16 y, uint16 depth=32);
void SetWindowed(bool); void SetWindowed(bool);
void SetVSync(bool); void SetVSync(bool);
void UseShadows(bool); void UseShadows(bool);
void Cancel(void);
void Shutdown(void); void Shutdown(void);
inline bool MustDie(void) { return _mustdie; }
// interfaces to tell the gui what to draw
void NotifyObjectDeletion(uint64 guid);
void NotifyObjectCreation(Object *o);
private: private:
void _Init(void); void _Init(void);
uint16 _xres,_yres,_colordepth; uint16 _xres,_yres,_colordepth;
bool _windowed,_vsync,_shadows; bool _windowed,_vsync,_shadows;
bool _initialized,_mustdie; bool _initialized,_mustdie;
PseuInstance *_instance;
irr::IrrlichtDevice *_device; irr::IrrlichtDevice *_device;
irr::video::IVideoDriver* _driver; irr::video::IVideoDriver* _driver;
irr::scene::ISceneManager* _smgr; irr::scene::ISceneManager* _smgr;
irr::gui::IGUIEnvironment* _guienv; irr::gui::IGUIEnvironment* _guienv;
irr::video::E_DRIVER_TYPE _driverType; irr::video::E_DRIVER_TYPE _driverType;
DrawObjMgr domgr;
PseuInstance *_instance;
}; };

View File

@ -25,15 +25,15 @@ PseuInstanceRunnable::PseuInstanceRunnable()
void PseuInstanceRunnable::run(void) void PseuInstanceRunnable::run(void)
{ {
_i = new PseuInstance(this); _i = new PseuInstance(this);
_i->SetConfDir("./conf/"); _i->SetConfDir("./conf/");
_i->SetScpDir("./scripts/"); _i->SetScpDir("./scripts/");
if(_i->Init()) if(_i->Init())
{ {
_i->Run(); _i->Run();
} }
else else
{ {
getchar(); getchar(); // if init failed, wait for keypress before exit
} }
delete _i; delete _i;
} }
@ -54,6 +54,8 @@ PseuInstance::PseuInstance(PseuInstanceRunnable *run)
_conf=NULL; _conf=NULL;
_cli=NULL; _cli=NULL;
_rmcontrol=NULL; _rmcontrol=NULL;
_gui=NULL;
_guithread=NULL;
_stop=false; _stop=false;
_fastquit=false; _fastquit=false;
_startrealm=true; _startrealm=true;
@ -61,7 +63,6 @@ PseuInstance::PseuInstance(PseuInstanceRunnable *run)
_error=false; _error=false;
_initialized=false; _initialized=false;
} }
PseuInstance::~PseuInstance() PseuInstance::~PseuInstance()
@ -72,6 +73,11 @@ PseuInstance::~PseuInstance()
// delete _cli; // ok this is a little mem leak... can be fixed sometime in future // delete _cli; // ok this is a little mem leak... can be fixed sometime in future
} }
if(_gui)
_gui->Shutdown();
if(_guithread)
_guithread->wait();
if(_rmcontrol) if(_rmcontrol)
delete _rmcontrol; delete _rmcontrol;
if(_rsession) if(_rsession)
@ -94,14 +100,14 @@ bool PseuInstance::Init(void) {
if(_confdir.empty()) if(_confdir.empty())
_confdir="./conf/"; _confdir="./conf/";
if(_scpdir.empty()) if(_scpdir.empty())
_scpdir="./scp/"; _scpdir="./scripts/";
srand((unsigned)time(NULL)); srand((unsigned)time(NULL));
RAND_set_rand_method(RAND_SSLeay()); // init openssl randomizer RAND_set_rand_method(RAND_SSLeay()); // init openssl randomizer
_scp=new DefScriptPackage(); _scp=new DefScriptPackage();
_scp->SetParentMethod((void*)this); _scp->SetParentMethod((void*)this);
_conf=new PseuInstanceConf(); _conf=new PseuInstanceConf();
_scp->SetPath(_scpdir); _scp->SetPath(_scpdir);
@ -138,13 +144,13 @@ bool PseuInstance::Init(void) {
if(x>0 && y>0 && (depth==16 || depth==32) && driver>0 && driver<=5) if(x>0 && y>0 && (depth==16 || depth==32) && driver>0 && driver<=5)
{ {
PseuGUIRunnable *rgui = new PseuGUIRunnable(); PseuGUIRunnable *rgui = new PseuGUIRunnable();
PseuGUI *gui = rgui->GetGUI(); _gui = rgui->GetGUI();
gui->SetInstance(this); _gui->SetInstance(this);
gui->SetDriver(driver); _gui->SetDriver(driver);
gui->SetResolution(x,y,depth); _gui->SetResolution(x,y,depth);
gui->SetVSync(vsync); _gui->SetVSync(vsync);
gui->UseShadows(shadows); _gui->UseShadows(shadows);
ZThread::Thread *t = new ZThread::Thread(rgui); _guithread = new ZThread::Thread(rgui);
} }
else else
logerror("GUI: incorrect settings!"); logerror("GUI: incorrect settings!");
@ -164,13 +170,13 @@ bool PseuInstance::Init(void) {
if(_error) if(_error)
{ {
logcritical("Errors while initializing!"); logcritical("Errors while initializing!");
return false; return false;
} }
log("Init complete.\n"); log("Init complete.\n");
_initialized=true; _initialized=true;
return true; return true;
} }
void PseuInstance::Run(void) void PseuInstance::Run(void)
@ -232,6 +238,10 @@ void PseuInstance::Run(void)
void PseuInstance::Update() void PseuInstance::Update()
{ {
// if the user typed anything into the console, process it before anything else
if(_cli) // need to to process only if cli exists
ProcessCliQueue();
// delete sessions if they are no longer needed // delete sessions if they are no longer needed
if(_rsession && _rsession->MustDie()) if(_rsession && _rsession->MustDie())
{ {
@ -264,7 +274,7 @@ void PseuInstance::Update()
_rsession->Connect(); _rsession->Connect();
_rsession->SendLogonChallenge(); // and login again _rsession->SendLogonChallenge(); // and login again
} }
// update currently existing/active sessions // update currently existing/active sessions
if(_rsession) if(_rsession)
_rsession->Update(); _rsession->Update();
@ -274,7 +284,7 @@ void PseuInstance::Update()
logerror("Unhandled exception in WorldSession::Update()"); logerror("Unhandled exception in WorldSession::Update()");
} }
if(_rmcontrol) if(_rmcontrol)
{ {
_rmcontrol->Update(); _rmcontrol->Update();
@ -290,6 +300,28 @@ void PseuInstance::Update()
this->Sleep(GetConf()->networksleeptime); this->Sleep(GetConf()->networksleeptime);
} }
void PseuInstance::ProcessCliQueue(void)
{
std::string cmd;
while(_cliQueue.size())
{
cmd = _cliQueue.next();
try
{
GetScripts()->RunSingleLine(cmd);
}
catch(...)
{
logerror("Exception while executing CLI command: \"%s\"",cmd.c_str());
}
}
}
void PseuInstance::AddCliCommand(std::string cmd)
{
_cliQueue.add(cmd);
}
void PseuInstance::SaveAllCache(void) void PseuInstance::SaveAllCache(void)
{ {
//... //...
@ -306,6 +338,12 @@ void PseuInstance::Sleep(uint32 msecs)
GetRunnable()->sleep(msecs); GetRunnable()->sleep(msecs);
} }
void PseuInstance::DeleteGUI(void)
{
_gui = NULL;
_guithread = NULL;
}
PseuInstanceConf::PseuInstanceConf() PseuInstanceConf::PseuInstanceConf()
{ {
enablecli=false; enablecli=false;
@ -317,22 +355,22 @@ void PseuInstanceConf::ApplyFromVarSet(VarSet &v)
{ {
debug=atoi(v.Get("DEBUG").c_str()); debug=atoi(v.Get("DEBUG").c_str());
realmlist=v.Get("REALMLIST"); realmlist=v.Get("REALMLIST");
accname=v.Get("ACCNAME"); accname=v.Get("ACCNAME");
accpass=v.Get("ACCPASS"); accpass=v.Get("ACCPASS");
exitonerror=(bool)atoi(v.Get("EXITONERROR").c_str()); exitonerror=(bool)atoi(v.Get("EXITONERROR").c_str());
reconnect=atoi(v.Get("RECONNECT").c_str()); reconnect=atoi(v.Get("RECONNECT").c_str());
realmport=atoi(v.Get("REALMPORT").c_str()); realmport=atoi(v.Get("REALMPORT").c_str());
clientversion_string=v.Get("CLIENTVERSION"); clientversion_string=v.Get("CLIENTVERSION");
clientbuild=atoi(v.Get("CLIENTBUILD").c_str()); clientbuild=atoi(v.Get("CLIENTBUILD").c_str());
clientlang=v.Get("CLIENTLANGUAGE"); clientlang=v.Get("CLIENTLANGUAGE");
realmname=v.Get("REALMNAME"); realmname=v.Get("REALMNAME");
charname=v.Get("CHARNAME"); charname=v.Get("CHARNAME");
networksleeptime=atoi(v.Get("NETWORKSLEEPTIME").c_str()); networksleeptime=atoi(v.Get("NETWORKSLEEPTIME").c_str());
showopcodes=atoi(v.Get("SHOWOPCODES").c_str()); showopcodes=atoi(v.Get("SHOWOPCODES").c_str());
hidefreqopcodes=(bool)atoi(v.Get("HIDEFREQOPCODES").c_str()); hidefreqopcodes=(bool)atoi(v.Get("HIDEFREQOPCODES").c_str());
enablecli=(bool)atoi(v.Get("ENABLECLI").c_str()); enablecli=(bool)atoi(v.Get("ENABLECLI").c_str());
allowgamecmd=(bool)atoi(v.Get("ALLOWGAMECMD").c_str()); allowgamecmd=(bool)atoi(v.Get("ALLOWGAMECMD").c_str());
enablechatai=(bool)atoi(v.Get("ENABLECHATAI").c_str()); enablechatai=(bool)atoi(v.Get("ENABLECHATAI").c_str());
notifyping=(bool)atoi(v.Get("NOTIFYPING").c_str()); notifyping=(bool)atoi(v.Get("NOTIFYPING").c_str());
showmyopcodes=(bool)atoi(v.Get("SHOWMYOPCODES").c_str()); showmyopcodes=(bool)atoi(v.Get("SHOWMYOPCODES").c_str());
disablespellcheck=(bool)atoi(v.Get("DISABLESPELLCHECK").c_str()); disablespellcheck=(bool)atoi(v.Get("DISABLESPELLCHECK").c_str());
@ -367,9 +405,9 @@ void PseuInstanceConf::ApplyFromVarSet(VarSet &v)
PseuInstanceConf::~PseuInstanceConf() PseuInstanceConf::~PseuInstanceConf()
{ {
//... //...
} }

View File

@ -9,6 +9,7 @@
#include "DefScript/DefScript.h" #include "DefScript/DefScript.h"
#include "Network/SocketHandler.h" #include "Network/SocketHandler.h"
#include "SCPDatabase.h" #include "SCPDatabase.h"
#include "GUI/PseuGUI.h"
class RealmSession; class RealmSession;
class WorldSession; class WorldSession;
@ -19,34 +20,34 @@ class RemoteController;
class PseuInstanceConf class PseuInstanceConf
{ {
public: public:
PseuInstanceConf(); PseuInstanceConf();
~PseuInstanceConf(); ~PseuInstanceConf();
void ApplyFromVarSet(VarSet &v); void ApplyFromVarSet(VarSet &v);
uint8 debug; uint8 debug;
std::string realmlist; std::string realmlist;
std::string accname; std::string accname;
std::string accpass; std::string accpass;
bool exitonerror; bool exitonerror;
uint32 reconnect; uint32 reconnect;
uint16 realmport; uint16 realmport;
uint16 worldport; uint16 worldport;
uint8 clientversion[3]; uint8 clientversion[3];
std::string clientversion_string; std::string clientversion_string;
uint16 clientbuild; uint16 clientbuild;
std::string clientlang; std::string clientlang;
std::string realmname; std::string realmname;
std::string charname; std::string charname;
std::string worldhost; std::string worldhost;
uint16 networksleeptime; uint16 networksleeptime;
uint8 showopcodes; uint8 showopcodes;
bool hidefreqopcodes; bool hidefreqopcodes;
bool allowgamecmd; bool allowgamecmd;
bool enablecli; bool enablecli;
bool enablechatai; bool enablechatai;
bool notifyping; bool notifyping;
bool showmyopcodes; bool showmyopcodes;
bool disablespellcheck; bool disablespellcheck;
@ -57,63 +58,72 @@ class PseuInstanceConf
// gui related // gui related
bool enablegui; bool enablegui;
// need more here // need more here
}; };
class PseuInstance class PseuInstance
{ {
public: public:
PseuInstance(PseuInstanceRunnable *run); PseuInstance(PseuInstanceRunnable *run);
~PseuInstance(); ~PseuInstance();
WorldSession *GetWSession(void) { return _wsession; }
RealmSession *GetRSession(void) { return _rsession; } inline WorldSession *GetWSession(void) { return _wsession; }
PseuInstanceConf *GetConf(void) { return _conf; } inline RealmSession *GetRSession(void) { return _rsession; }
DefScriptPackage *GetScripts(void) { return _scp; } inline PseuInstanceConf *GetConf(void) { return _conf; }
PseuInstanceRunnable *GetRunnable(void) { return _runnable; } inline DefScriptPackage *GetScripts(void) { return _scp; }
void SetConfDir(std::string dir) { _confdir = dir; } inline PseuInstanceRunnable *GetRunnable(void) { return _runnable; }
std::string GetConfDir(void) { return _confdir; } inline PseuGUI *GetGUI(void) { return _gui; }
void SetScpDir(std::string dir) { _scpdir = dir; } void DeleteGUI(void);
void SetSessionKey(BigNumber key) { _sessionkey = key; }
BigNumber GetSessionKey(void) { return _sessionkey; } inline void SetConfDir(std::string dir) { _confdir = dir; }
void SetError(void) { _error = true; } inline std::string GetConfDir(void) { return _confdir; }
inline void SetScpDir(std::string dir) { _scpdir = dir; }
inline void SetSessionKey(BigNumber key) { _sessionkey = key; }
inline BigNumber GetSessionKey(void) { return _sessionkey; }
inline void SetError(void) { _error = true; }
SCPDatabaseMgr dbmgr; SCPDatabaseMgr dbmgr;
bool Init();
void SaveAllCache(void);
void Stop(void) { _stop = true; }
bool Stopped(void) { return _stop; }
void SetFastQuit(bool q=true) { _fastquit=true; }
void Quit(void);
void Run(void);
void Update(void);
void Sleep(uint32 msecs);
void CreateWorldSession(void) { _createws = true; }
private: bool Init();
void SaveAllCache(void);
inline void Stop(void) { _stop = true; }
inline bool Stopped(void) { return _stop; }
inline void SetFastQuit(bool q=true) { _fastquit=true; }
void Quit(void);
void Run(void);
void Update(void);
void Sleep(uint32 msecs);
inline void CreateWorldSession(void) { _createws = true; }
void ProcessCliQueue(void);
void AddCliCommand(std::string);
private:
PseuInstanceRunnable *_runnable; PseuInstanceRunnable *_runnable;
RealmSession *_rsession; RealmSession *_rsession;
WorldSession *_wsession; WorldSession *_wsession;
PseuInstanceConf *_conf; PseuInstanceConf *_conf;
DefScriptPackage *_scp; DefScriptPackage *_scp;
std::string _confdir,_scpdir; std::string _confdir,_scpdir; // _scpdir is the scipts dir, and NOT where SCP files are stored!!
bool _initialized; bool _initialized;
bool _stop,_fastquit; bool _stop,_fastquit;
bool _startrealm; bool _startrealm;
bool _error; bool _error;
bool _createws; bool _createws;
BigNumber _sessionkey; BigNumber _sessionkey;
char *_ver,*_ver_short; char *_ver,*_ver_short;
SocketHandler _sh; SocketHandler _sh;
CliRunnable *_cli; CliRunnable *_cli;
ZThread::Thread _clithread; ZThread::Thread _clithread;
RemoteController *_rmcontrol; RemoteController *_rmcontrol;
ZThread::LockedQueue<std::string,ZThread::FastMutex> _cliQueue;
PseuGUI *_gui;
ZThread::Thread *_guithread;
}; };
@ -123,11 +133,11 @@ public:
PseuInstanceRunnable(); PseuInstanceRunnable();
void run(void); void run(void);
void sleep(uint32); void sleep(uint32);
PseuInstance *GetInstance(void) { return _i; } inline PseuInstance *GetInstance(void) { return _i; }
private: private:
PseuInstance *_i; PseuInstance *_i;
}; };
#endif #endif

View File

@ -2,30 +2,48 @@
#include "common.h" #include "common.h"
#include "SCPDatabase.h" #include "SCPDatabase.h"
uint32 SCPDatabase::LoadFromFile(char *fn) uint32 SCPDatabase::LoadFromFile(char *fn)
{ {
std::fstream fh; std::fstream fh;
std::string line,value,entry,storage; uint32 size = GetFileSize(fn);
uint32 id=0,sections=0; if(!size)
char c; return 0;
fh.open(fn,std::ios_base::in); fh.open(fn,std::ios_base::in | std::ios_base::binary);
if( !fh.is_open() ) if( !fh.is_open() )
return 0; return 0;
while(!fh.eof())
char *buf = new char[size];
fh.read(buf,size);
fh.close();
uint32 sections = LoadFromMem(buf,size);
delete [] buf;
return sections;
}
uint32 SCPDatabase::LoadFromMem(char *buf, uint32 size)
{
std::string line,value,entry,storage;
uint32 id=0,sections=0;
for(uint32 pos = 0; pos < size; pos++)
{ {
c=fh.get(); if(buf[pos] == '\n')
if(c=='\n' || fh.eof())
{ {
if(line.empty()) if(line.empty())
continue; continue;
while(line[0]==' ' || line[0]=='\t') while(line[0]==' ' || line[0]=='\t')
line.erase(0,1); line.erase(0,1);
if(line.empty() || (line.length() > 1 && (line[0]=='/' && line[1]=='/')) ) if(line.empty() || (line.length() > 1 && (line[0]=='#' || (line[0]=='/' && line[1]=='/'))) )
{ {
line.clear(); line.clear();
continue; continue;
} }
if(line[line.size()-1] == 13) // this fixes the annoying newline problems on windows + binary mode
line[line.size()-1] = 0;
if(line[0]=='[') if(line[0]=='[')
{ {
id=(uint32)toInt(line.c_str()+1); // start reading after '[' id=(uint32)toInt(line.c_str()+1); // start reading after '['
@ -45,9 +63,8 @@ uint32 SCPDatabase::LoadFromFile(char *fn)
line.clear(); line.clear();
} }
else else
line+=c; // fill up line until a newline is reached (see above) line += buf[pos]; // fill up line until a newline is reached (see above)
} }
fh.close();
return sections; return sections;
} }
@ -73,10 +90,7 @@ bool SCPField::HasEntry(std::string e)
std::string SCPField::GetString(std::string entry) std::string SCPField::GetString(std::string entry)
{ {
//return HasEntry(entry) ? _map[entry] : ""; //return HasEntry(entry) ? _map[entry] : "";
if(HasEntry(entry)) return _map[entry];
return _map[entry];
else
return "";
} }
// note that this can take a while depending on the size of the database! // note that this can take a while depending on the size of the database!
@ -101,11 +115,64 @@ SCPDatabase& SCPDatabaseMgr::GetDB(std::string n)
return _map[n]; return _map[n];
} }
uint32 SCPDatabaseMgr::AutoLoadFile(char *fn)
{
std::fstream fh;
uint32 size = GetFileSize(fn);
if(!size)
return 0;
fh.open(fn,std::ios_base::in | std::ios_base::binary);
if( !fh.is_open() )
return 0;
char *buf = new char[size];
fh.read(buf,size);
fh.close();
std::string line,dbname;
for(uint32 pos = 0; pos < size; pos++)
{
if(buf[pos] == '\n')
{
if(line.empty())
continue;
while(line[0]==' ' || line[0]=='\t')
line.erase(0,1);
if(line[0] == '#')
{
uint32 eq = line.find("=");
if(eq != std::string::npos)
{
std::string info = stringToLower(line.substr(0,pos));
std::string value = stringToLower(line.substr(pos+1,line.length()-1));
if(info == "#dbname")
{
dbname = value;
break;
}
}
}
}
else
line += buf[pos];
}
delete [] buf;
if(dbname.empty())
return 0;
uint32 sections = GetDB(dbname).LoadFromMem(buf,size);
return sections;
}
// -- helper functions -- // // -- helper functions -- //
std::string SCPDatabaseMgr::GetZoneName(uint32 id) std::string SCPDatabaseMgr::GetAreaName(uint32 id)
{ {
return GetDB("zone").GetField(id).GetString("name"); return GetDB("area").GetField(id).GetString("name");
} }
std::string SCPDatabaseMgr::GetRaceName(uint32 id) std::string SCPDatabaseMgr::GetRaceName(uint32 id)
@ -140,4 +207,4 @@ std::string SCPDatabaseMgr::GetLangName(uint32 id)
//if(r.empty()) //if(r.empty())
// r = LookupName(id,langNames); // r = LookupName(id,langNames);
return r; return r;
} }

View File

@ -3,36 +3,82 @@
#include <map> #include <map>
struct SCPEntry /*
* Some preparations for compiled databases. i will continue this later. [FG]
enum SCPTypes
{ {
std::string entry; SCP_TYPE_STRING = 0,
std::string value; SCP_TYPE_INT,
SCP_TYPE_UINT,
SCP_TYPE_FLOAT
}; };
class SCPEntry
{
private:
char *str;
public:
SCPEntry() { str = NULL; }
~SCPEntry() { if(str) delete [] str; }
union
{
int32 intvalue
uint32 uintvalue;
float floatvalue;
};
inline char *GetString(uint8 type)
{
if(str)
return str;
else
{
char buf[25];
char *fmt;
switch (type)
{
case SCP_TYPE_INT: sprintf(buf,"%d",intvalue); break;
case SCP_TYPE_UINT: sprintf(buf,"%u",uintvalue); break;
case SCP_TYPE_FLOAT: sprintf(buf,"%f",floatvalue); break;
}
str = new char[strlen(buf) + 1];
memcpy(str,buf,strlen(buf) + 1);
return str;
}
}
};
*/
typedef std::map<std::string,std::string> SCPEntryMap; typedef std::map<std::string,std::string> SCPEntryMap;
class SCPField class SCPField
{ {
public: public:
std::string GetString(std::string); std::string GetString(std::string);
uint64 GetInteger(std::string entry) { return toInt(GetString(entry)); } inline uint64 GetInteger(std::string entry) { return toInt(GetString(entry)); }
double GetDouble(std::string entry) { return strtod(GetString(entry).c_str(),NULL); } inline double GetDouble(std::string entry) { return strtod(GetString(entry).c_str(),NULL); }
void Set(std::string entry,std::string value) { _map[entry]=value; } inline void Set(std::string entry,std::string value) { _map[entry]=value; }
bool HasEntry(std::string); bool HasEntry(std::string);
private: private:
SCPEntryMap _map; SCPEntryMap _map;
}; };
typedef std::map<uint32,SCPField> SCPFieldMap; typedef std::map<uint32,SCPField> SCPFieldMap;
class SCPDatabase class SCPDatabase
{ {
public: public:
SCPField& GetField(uint32 id) { return _map[id]; } inline SCPField& GetField(uint32 id) { return _map[id]; }
bool HasField(uint32 id); bool HasField(uint32 id);
uint32 LoadFromFile(char*); uint32 LoadFromFile(char*);
uint32 LoadFromMem(char*,uint32);
uint32 GetFieldByValue(std::string entry, std::string value); uint32 GetFieldByValue(std::string entry, std::string value);
private: private:
@ -47,11 +93,13 @@ class SCPDatabaseMgr
public: public:
bool HasDB(std::string); bool HasDB(std::string);
SCPDatabase& GetDB(std::string); SCPDatabase& GetDB(std::string);
uint32 AutoLoadFile(char *fn);
inline void DropDB(std::string s) { _map.erase(stringToLower(s)); }
////////////////////// //////////////////////
// helper functions // // helper functions //
////////////////////// //////////////////////
std::string GetZoneName(uint32 id); std::string GetAreaName(uint32 id);
std::string GetRaceName(uint32 id); std::string GetRaceName(uint32 id);
std::string GetClassName_(uint32 id); std::string GetClassName_(uint32 id);
std::string GetGenderName(uint32 id); std::string GetGenderName(uint32 id);

View File

@ -1,46 +1,66 @@
#include "common.h"
#include "log.h"
#include "PseuWoW.h"
#include "ObjMgr.h" #include "ObjMgr.h"
#include "GUI/PseuGUI.h"
ObjMgr::ObjMgr()
{
DEBUG(logdebug("DEBUG: ObjMgr created"));
}
ObjMgr::~ObjMgr() ObjMgr::~ObjMgr()
{ {
RemoveAll(); RemoveAll();
} }
void ObjMgr::SetInstance(PseuInstance *i)
{
_instance = i;
DEBUG(logdebug("DEBUG: ObjMgr instance set to 0x%X",i));
}
void ObjMgr::RemoveAll(void) void ObjMgr::RemoveAll(void)
{ {
for(ItemProtoList::iterator i = _iproto.begin(); i!=_iproto.end(); i++) for(ItemProtoList::iterator i = _iproto.begin(); i!=_iproto.end(); i++)
{ {
delete *i; delete *i;
} }
for(ObjectList::iterator i = _obj.begin(); i!=_obj.end(); i++) while(_obj.size())
{ {
delete *i; Remove(_obj.begin()->first);
} }
} }
void ObjMgr::Remove(uint64 guid) void ObjMgr::Remove(uint64 guid)
{ {
for(ObjectList::iterator i = _obj.begin(); i!=_obj.end(); i++) Object *o = GetObj(guid);
if((*i)->GetGUID() == guid) if(o)
{ {
delete *i; PseuGUI *gui = _instance->GetGUI();
_obj.erase(i); if(gui)
return; gui->NotifyObjectDeletion(guid); // we have a gui, which must delete linked DrawObject
} _obj.erase(guid); // now delete the obj from the mgr
delete o; // and delete the obj itself
}
} }
void ObjMgr::Add(Object *o) void ObjMgr::Add(Object *o)
{ {
_obj.push_back(o); _obj[o->GetGUID()] = o;
PseuGUI *gui = _instance->GetGUI();
if(gui)
gui->NotifyObjectCreation(o);
} }
Object *ObjMgr::GetObj(uint64 guid) Object *ObjMgr::GetObj(uint64 guid)
{ {
if(!guid) if(!guid)
return NULL; return NULL;
for(ObjectList::iterator i = _obj.begin(); i!=_obj.end(); i++) for(ObjectMap::iterator i = _obj.begin(); i!=_obj.end(); i++)
if((*i)->GetGUID() == guid) if(i->second->GetGUID() == guid)
return (*i); return i->second;
return NULL; return NULL;
} }

View File

@ -7,12 +7,16 @@
#include "Item.h" #include "Item.h"
typedef std::vector<ItemProto*> ItemProtoList; typedef std::vector<ItemProto*> ItemProtoList;
typedef std::list<Object*> ObjectList; typedef std::map<uint64,Object*> ObjectMap;
class PseuInstance;
class ObjMgr class ObjMgr
{ {
public: public:
ObjMgr();
~ObjMgr(); ~ObjMgr();
void SetInstance(PseuInstance*);
void RemoveAll(void); // TODO: this needs to be called on SMSG_LOGOUT_COMPLETE once implemented. void RemoveAll(void); // TODO: this needs to be called on SMSG_LOGOUT_COMPLETE once implemented.
// Item Prototype functions // Item Prototype functions
@ -29,11 +33,13 @@ public:
void Add(Object*); void Add(Object*);
void Remove(uint64); // remove all objects with that guid (should be only 1 object in total anyway) void Remove(uint64); // remove all objects with that guid (should be only 1 object in total anyway)
Object *GetObj(uint64 guid); Object *GetObj(uint64 guid);
inline uint32 GetObjectCount(void) { return _obj.size(); }
private: private:
ItemProtoList _iproto; ItemProtoList _iproto;
ObjectList _obj; ObjectMap _obj;
std::vector<uint32> _noitem; std::vector<uint32> _noitem;
PseuInstance *_instance;
}; };

View File

@ -23,9 +23,15 @@ void Player::Create(uint64 guid)
MyCharacter::MyCharacter() : Player() MyCharacter::MyCharacter() : Player()
{ {
DEBUG(logdebug("MyCharacter() constructor, this=0x%x",this));
SetTarget(0); SetTarget(0);
} }
MyCharacter::~MyCharacter()
{
DEBUG(logdebug("~MyCharacter() destructor, this=0x%X guid="I64FMT,this,GetGUID())); // this _could_ crash if Player::Create(guid) wasnt called before!
}
void MyCharacter::SetActionButtons(WorldPacket &data) void MyCharacter::SetActionButtons(WorldPacket &data)
{ {

View File

@ -200,6 +200,7 @@ class MyCharacter : public Player
{ {
public: public:
MyCharacter(); MyCharacter();
~MyCharacter();
void SetActionButtons(WorldPacket &data); void SetActionButtons(WorldPacket &data);
void AddSpell(uint32 spellid, uint16 spellslot); void AddSpell(uint32 spellid, uint16 spellslot);

View File

@ -30,134 +30,159 @@ void WorldSession::_HandleCompressedUpdateObjectOpcode(WorldPacket& recvPacket)
WorldPacket wp; WorldPacket wp;
wp.SetOpcode(recvPacket.GetOpcode()); wp.SetOpcode(recvPacket.GetOpcode());
wp.append(z.contents(),z.size()); wp.append(z.contents(),z.size());
_HandleUpdateObjectOpcode(wp); _HandleUpdateObjectOpcode(wp);
} }
void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket) void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket)
{ {
uint8 utype; uint8 utype;
uint8 unk8; uint8 unk8;
uint32 usize, ublocks; uint32 usize, ublocks;
uint64 uguid; uint64 uguid;
recvPacket >> ublocks >> unk8; recvPacket >> ublocks >> unk8;
while(recvPacket.rpos() < recvPacket.size()) while(recvPacket.rpos() < recvPacket.size())
{ {
recvPacket >> utype; recvPacket >> utype;
switch(utype) switch(utype)
{ {
case UPDATETYPE_VALUES: case UPDATETYPE_VALUES:
{ {
uguid = recvPacket.GetPackedGuid(); uguid = recvPacket.GetPackedGuid();
_ValuesUpdate(uguid,recvPacket); _ValuesUpdate(uguid,recvPacket);
} }
break; break;
case UPDATETYPE_MOVEMENT: case UPDATETYPE_MOVEMENT:
{ {
recvPacket >> uguid; // the guid is NOT packed here! recvPacket >> uguid; // the guid is NOT packed here!
Object *obj = objmgr.GetObj(uguid); Object *obj = objmgr.GetObj(uguid);
if(obj) if(obj)
this->_MovementUpdate(obj->GetTypeId(),uguid,recvPacket); this->_MovementUpdate(obj->GetTypeId(),uguid,recvPacket);
else else
logcustom(2,RED,"Got UpdateObject_Movement for unknown object "I64FMT,uguid); logcustom(2,RED,"Got UpdateObject_Movement for unknown object "I64FMT,uguid);
} }
break; break;
case UPDATETYPE_CREATE_OBJECT: case UPDATETYPE_CREATE_OBJECT2: // will be sent when our very own character is created
case UPDATETYPE_CREATE_OBJECT2: case UPDATETYPE_CREATE_OBJECT: // will be sent on any other object creation
{ {
uguid = recvPacket.GetPackedGuid(); uguid = recvPacket.GetPackedGuid();
uint8 objtypeid; uint8 objtypeid;
recvPacket >> objtypeid; recvPacket >> objtypeid;
logdebug("Create Object type %u with guid "I64FMT,objtypeid,uguid); logdebug("Create Object type %u with guid "I64FMT,objtypeid,uguid);
// dont create objects if already present in memory. // dont create objects if already present in memory.
// recreate every object except ourself! // recreate every object except ourself!
if( uguid != GetGuid() && objmgr.GetObj(uguid)) if(objmgr.GetObj(uguid))
{ {
logdev("- already exists, deleting old , creating new object"); if(uguid != GetGuid())
objmgr.Remove(uguid);
}
switch(objtypeid)
{
case TYPEID_OBJECT: // no data to read
{
logerror("Recieved wrong UPDATETYPE_CREATE_OBJECT to create Object base type!");
}
case TYPEID_ITEM:
{
Item *item = new Item();
item->Create(uguid);
objmgr.Add(item);
break;
}
case TYPEID_CONTAINER:
{
Bag *bag = new Bag();
bag->Create(uguid);
objmgr.Add(bag);
break;
}
case TYPEID_UNIT:
{
Unit *unit = new Unit();
unit->Create(uguid);
objmgr.Add(unit);
break;
}
case TYPEID_PLAYER:
{ {
Player *player = new Player(); logdev("- already exists, deleting old , creating new object");
player->Create(uguid); objmgr.Remove(uguid);
objmgr.Add(player);
break;
} }
case TYPEID_GAMEOBJECT: else
{ {
GameObject *go = new GameObject(); logdev("- already exists, but not deleted (has our current GUID)");
go->Create(uguid);
objmgr.Add(go);
break;
}
case TYPEID_CORPSE:
{
Corpse *corpse = new Corpse();
corpse->Create(uguid);
objmgr.Add(corpse);
break;
}
case TYPEID_DYNAMICOBJECT:
{
DynamicObject *dobj = new DynamicObject();
dobj->Create(uguid);
objmgr.Add(dobj);
break;
} }
} }
// only if the obj didnt exist or was just deleted above, create it....
if(!objmgr.GetObj(uguid))
{
switch(objtypeid)
{
case TYPEID_OBJECT: // no data to read
{
logerror("Recieved wrong UPDATETYPE_CREATE_OBJECT to create Object base type!");
}
case TYPEID_ITEM:
{
Item *item = new Item();
item->Create(uguid);
objmgr.Add(item);
break;
}
case TYPEID_CONTAINER:
{
Bag *bag = new Bag();
bag->Create(uguid);
objmgr.Add(bag);
break;
}
case TYPEID_UNIT:
{
Unit *unit = new Unit();
unit->Create(uguid);
objmgr.Add(unit);
break;
}
case TYPEID_PLAYER:
{
Player *player = new Player();
player->Create(uguid);
objmgr.Add(player);
break;
}
case TYPEID_GAMEOBJECT:
{
GameObject *go = new GameObject();
go->Create(uguid);
objmgr.Add(go);
break;
}
case TYPEID_CORPSE:
{
Corpse *corpse = new Corpse();
corpse->Create(uguid);
objmgr.Add(corpse);
break;
}
case TYPEID_DYNAMICOBJECT:
{
DynamicObject *dobj = new DynamicObject();
dobj->Create(uguid);
objmgr.Add(dobj);
break;
}
}
}
else
{
logdebug("Obj "I64FMT" not created, already exists",uguid);
}
// ...regardless if it was freshly created or already present, update its values and stuff now...
this->_MovementUpdate(objtypeid, uguid, recvPacket); this->_MovementUpdate(objtypeid, uguid, recvPacket);
this->_ValuesUpdate(uguid, recvPacket); this->_ValuesUpdate(uguid, recvPacket);
// ...and ask the server for eventually missing data.
_QueryObjectInfo(uguid); _QueryObjectInfo(uguid);
}
break;
// if our own character got finally created, we have successfully entered the world,
// and should have gotten all info about our char already.
// TODO: make called script function like "_enterworld"
//if(uguid==GetGuid())
// _OnCharCreate();
}
break;
case UPDATETYPE_OUT_OF_RANGE_OBJECTS: case UPDATETYPE_OUT_OF_RANGE_OBJECTS:
recvPacket >> usize; {
for(uint16 i=0;i<usize;i++) recvPacket >> usize;
{ for(uint16 i=0;i<usize;i++)
uguid = recvPacket.GetPackedGuid(); // not 100% sure if this is correct {
logdebug("GUID "I64FMT" out of range",uguid); uguid = recvPacket.GetPackedGuid(); // not 100% sure if this is correct
objmgr.Remove(uguid); logdebug("GUID "I64FMT" out of range",uguid);
} objmgr.Remove(uguid);
break; }
}
break;
default: default:
logerror("UPDATE_OBJECT: Got unk updatetype 0x%X",utype); {
logerror("UPDATE_OBJECT: Read %u / %u bytes, skipped rest",recvPacket.rpos(),recvPacket.size()); logerror("UPDATE_OBJECT: Got unk updatetype 0x%X",utype);
return; logerror("UPDATE_OBJECT: Read %u / %u bytes, skipped rest",recvPacket.rpos(),recvPacket.size());
return;
}
} // switch } // switch
} // while } // while
@ -169,97 +194,97 @@ void WorldSession::_MovementUpdate(uint8 objtypeid, uint64 uguid, WorldPacket& r
uint32 unk32,flags2,time,transtime,higuid; uint32 unk32,flags2,time,transtime,higuid;
float unkfx,unkfy,unkfz,x,y,z,o,tx,ty,tz,to; float unkfx,unkfy,unkfz,x,y,z,o,tx,ty,tz,to;
uint64 transguid; uint64 transguid;
// uint64 fullguid; // see below // uint64 fullguid; // see below
float speedWalk, speedRun, speedSwimBack, speedSwim, speedWalkBack, speedTurn, speedFly, speedFlyBack; float speedWalk, speedRun, speedSwimBack, speedSwim, speedWalkBack, speedTurn, speedFly, speedFlyBack;
Object *obj = (Object*)objmgr.GetObj(uguid); Object *obj = (Object*)objmgr.GetObj(uguid);
Unit *u = (Unit*)obj; // only use for Unit:: functions!! Unit *u = (Unit*)obj; // only use for Unit:: functions!!
recvPacket >> flags; recvPacket >> flags;
flags2 = 0; // not sure if its correct to set it to 0 (needs some starting flag?) flags2 = 0; // not sure if its correct to set it to 0 (needs some starting flag?)
if(flags & UPDATEFLAG_LIVING) if(flags & UPDATEFLAG_LIVING)
{ {
recvPacket >> flags2 >> time; recvPacket >> flags2 >> time;
} }
logdev("MovementUpdate TypeID=%u GUID="I64FMT" pObj=%X flags=%u flags2=%u",objtypeid,uguid,obj,flags,flags2); logdev("MovementUpdate TypeID=%u GUID="I64FMT" pObj=%X flags=%u flags2=%u",objtypeid,uguid,obj,flags,flags2);
if(flags & UPDATEFLAG_HASPOSITION) if(flags & UPDATEFLAG_HASPOSITION)
{ {
if(flags & UPDATEFLAG_TRANSPORT) if(flags & UPDATEFLAG_TRANSPORT)
{ {
recvPacket >> unkfx >> unkfy >> unkfz >> o; // 3x (float)0 followed by orientation recvPacket >> unkfx >> unkfy >> unkfz >> o; // 3x (float)0 followed by orientation
logdev("TRANSPORT_FLOATS @ flags: x=%f y=%f z=%f o=%f",unkfx,unkfy,unkfz,o); logdev("TRANSPORT_FLOATS @ flags: x=%f y=%f z=%f o=%f",unkfx,unkfy,unkfz,o);
} }
else else
{ {
recvPacket >> x >> y >> z >> o; recvPacket >> x >> y >> z >> o;
logdev("FLOATS: x=%f y=%f z=%f o=%f",x,y,z,o); logdev("FLOATS: x=%f y=%f z=%f o=%f",x,y,z,o);
} }
} }
if(flags & UPDATEFLAG_LIVING) if(flags & UPDATEFLAG_LIVING)
{ {
if(flags2 & FLAGS2_TRANSPORT) if(flags2 & FLAGS2_TRANSPORT)
{ {
recvPacket >> transguid >> tx >> ty >> tz >> to; recvPacket >> transguid >> tx >> ty >> tz >> to;
recvPacket >> unk32; // added in 2.0.3 recvPacket >> unk32; // added in 2.0.3
logdev("TRANSPORT_FLOATS @ flags2: x=%f y=%f z=%f o=%f",tx,ty,tz,to); logdev("TRANSPORT_FLOATS @ flags2: x=%f y=%f z=%f o=%f",tx,ty,tz,to);
} }
recvPacket >> unk32; recvPacket >> unk32;
/* /*
// not sure if this is/was correct, MaNGOS doesnt use it anymore // not sure if this is/was correct, MaNGOS doesnt use it anymore
if(flags2 & 0x2000) // 0x2000 = ?? if(flags2 & 0x2000) // 0x2000 = ??
{ {
recvPacket >> unkf >> unkf >> unkf >> unkf; recvPacket >> unkf >> unkf >> unkf >> unkf;
} }
*/ */
recvPacket >> speedWalk >> speedRun >> speedSwimBack >> speedSwim; recvPacket >> speedWalk >> speedRun >> speedSwimBack >> speedSwim;
recvPacket >> speedWalkBack >> speedFly >> speedFlyBack >> speedTurn; // fly added in 2.0.x recvPacket >> speedWalkBack >> speedFly >> speedFlyBack >> speedTurn; // fly added in 2.0.x
if(u) if(u)
{ {
u->SetPosition(x,y,z,o); u->SetPosition(x,y,z,o);
u->SetSpeed(MOVE_WALK,speedWalk); u->SetSpeed(MOVE_WALK,speedWalk);
u->SetSpeed(MOVE_RUN,speedRun); u->SetSpeed(MOVE_RUN,speedRun);
u->SetSpeed(MOVE_SWIMBACK,speedSwimBack); u->SetSpeed(MOVE_SWIMBACK,speedSwimBack);
u->SetSpeed(MOVE_SWIM,speedSwim); u->SetSpeed(MOVE_SWIM,speedSwim);
u->SetSpeed(MOVE_WALKBACK,speedWalkBack); u->SetSpeed(MOVE_WALKBACK,speedWalkBack);
u->SetSpeed(MOVE_TURN,speedTurn); u->SetSpeed(MOVE_TURN,speedTurn);
u->SetSpeed(MOVE_FLY,speedFly); u->SetSpeed(MOVE_FLY,speedFly);
u->SetSpeed(MOVE_FLYBACK,speedFlyBack); u->SetSpeed(MOVE_FLYBACK,speedFlyBack);
} }
else else
{ {
logcustom(2,RED,"WorldSession::_MovementUpdate for unknown guid "I64FMT" typeid=%u",uguid,objtypeid); logcustom(2,RED,"WorldSession::_MovementUpdate for unknown guid "I64FMT" typeid=%u",uguid,objtypeid);
} }
} }
if(flags & UPDATEFLAG_ALL) if(flags & UPDATEFLAG_ALL)
{ {
recvPacket >> unk32; recvPacket >> unk32;
} }
if(flags & UPDATEFLAG_HIGHGUID) if(flags & UPDATEFLAG_HIGHGUID)
{ {
recvPacket >> higuid; // 2.0.6 - high guid was there, unk for 2.0.12 recvPacket >> higuid; // 2.0.6 - high guid was there, unk for 2.0.12
// not sure if this is correct, MaNGOS sends 0 always. // not sure if this is correct, MaNGOS sends 0 always.
//obj->SetUInt32Value(OBJECT_FIELD_GUID+1,higuid); // note that this sets only the high part of the guid //obj->SetUInt32Value(OBJECT_FIELD_GUID+1,higuid); // note that this sets only the high part of the guid
} }
if(flags & UPDATEFLAG_FULLGUID) if(flags & UPDATEFLAG_FULLGUID)
{ {
// unused in mangos? but what if its needed? // unused in mangos? but what if its needed?
// recvPacket >> fullguid; // recvPacket >> fullguid;
} }
if(flags & UPDATEFLAG_TRANSPORT) if(flags & UPDATEFLAG_TRANSPORT)
{ {
recvPacket >> transtime; // whats this used for? recvPacket >> transtime; // whats this used for?
} }
} }
@ -280,7 +305,7 @@ void WorldSession::_ValuesUpdate(uint64 uguid, WorldPacket& recvPacket)
recvPacket.read((uint8*)updateMask, masksize); recvPacket.read((uint8*)updateMask, masksize);
umask.SetMask(updateMask); umask.SetMask(updateMask);
//delete [] updateMask; // will be deleted at ~UpdateMask() !!!! //delete [] updateMask; // will be deleted at ~UpdateMask() !!!!
logdev("ValuesUpdate TypeId=%u GUID="I64FMT" pObj=%X Blocks=%u Masksize=%u",obj->GetTypeId(),uguid,obj,blockcount,masksize); logdev("ValuesUpdate TypeId=%u GUID="I64FMT" pObj=%X Blocks=%u Masksize=%u",obj->GetTypeId(),uguid,obj,blockcount,masksize);
for (uint32 i = 0; i < valuesCount; i++) for (uint32 i = 0; i < valuesCount; i++)
{ {
@ -288,13 +313,13 @@ void WorldSession::_ValuesUpdate(uint64 uguid, WorldPacket& recvPacket)
{ {
recvPacket >> value; recvPacket >> value;
// TODO: what to do here?! // TODO: what to do here?!
/*if( obj->isType(TYPE_UNIT) && ( /*if( obj->isType(TYPE_UNIT) && (
i >= UNIT_FIELD_POWER1 && i <= UNIT_FIELD_MAXPOWER5 || i >= UNIT_FIELD_POWER1 && i <= UNIT_FIELD_MAXPOWER5 ||
i >= UNIT_FIELD_BASEATTACKTIME && i <= UNIT_FIELD_RANGEDATTACKTIME || i >= UNIT_FIELD_BASEATTACKTIME && i <= UNIT_FIELD_RANGEDATTACKTIME ||
i >= UNIT_FIELD_STR && i <= UNIT_FIELD_RESISTANCES + 6 ) i >= UNIT_FIELD_STR && i <= UNIT_FIELD_RESISTANCES + 6 )
|| obj->isType(TYPE_PLAYER) && || obj->isType(TYPE_PLAYER) &&
i >= PLAYER_FIELD_POSSTAT0 && i <= PLAYER_FIELD_RESISTANCEBUFFMODSNEGATIVE + 6 ) i >= PLAYER_FIELD_POSSTAT0 && i <= PLAYER_FIELD_RESISTANCEBUFFMODSNEGATIVE + 6 )
{ {
obj->SetFloatValue(i, (float)value); obj->SetFloatValue(i, (float)value);
} }
@ -303,8 +328,8 @@ void WorldSession::_ValuesUpdate(uint64 uguid, WorldPacket& recvPacket)
obj->SetUInt32Value(i, value); obj->SetUInt32Value(i, value);
//} //}
// still nee to find out which values to interpret as floats // still need to find out which values to interpret as floats
logdev("-> Field[%u] = %u",i,value); logdev("-> Field[%u] = %u",i,value);
} }
} }
} }
@ -349,4 +374,4 @@ void WorldSession::_QueryObjectInfo(uint64 guid)
//case... //case...
} }
} }
} }

View File

@ -13,16 +13,16 @@
#include "RealmSession.h" #include "RealmSession.h"
#include "WorldSession.h" #include "WorldSession.h"
struct OpcodeHandler struct OpcodeHandler
{ {
uint16 opcode; uint16 opcode;
void (WorldSession::*handler)(WorldPacket& recvPacket); void (WorldSession::*handler)(WorldPacket& recvPacket);
}; };
WorldSession::WorldSession(PseuInstance *in) WorldSession::WorldSession(PseuInstance *in)
{ {
logdebug("-> Starting WorldSession from instance 0x%X",in); // should never output a null ptr logdebug("-> Starting WorldSession 0x%X from instance 0x%X",this,in); // should never output a null ptr
_instance = in; _instance = in;
_mustdie=false; _mustdie=false;
_logged=false; _logged=false;
@ -31,7 +31,10 @@ WorldSession::WorldSession(PseuInstance *in)
_channels = new Channel(this); _channels = new Channel(this);
_world = NULL; _world = NULL;
_sh.SetAutoCloseSockets(false); _sh.SetAutoCloseSockets(false);
objmgr.SetInstance(in);
//... //...
DEBUG(logdebug("WorldSession 0x%X constructor finished",this));
} }
WorldSession::~WorldSession() WorldSession::~WorldSession()
@ -50,6 +53,7 @@ WorldSession::~WorldSession()
delete _socket; delete _socket;
if(_world) if(_world)
delete _world; delete _world;
DEBUG(logdebug("~WorldSession() this=0x%X _instance=0x%X",this,_instance));
} }
void WorldSession::Start(void) void WorldSession::Start(void)
@ -114,34 +118,34 @@ void WorldSession::Update(void)
uint16 hpos; uint16 hpos;
bool known=false; bool known=false;
while(pktQueue.size()) while(pktQueue.size())
{ {
WorldPacket *packet = pktQueue.next(); WorldPacket *packet = pktQueue.next();
for (hpos = 0; table[hpos].handler != NULL; hpos++) for (hpos = 0; table[hpos].handler != NULL; hpos++)
{ {
if (table[hpos].opcode == packet->GetOpcode()) if (table[hpos].opcode == packet->GetOpcode())
{ {
known=true; known=true;
break; break;
} }
} }
bool hideOpcode = false; bool hideOpcode = false;
// TODO: Maybe make table or something with all the frequently opcodes // TODO: Maybe make table or something with all the frequently opcodes
if (packet->GetOpcode() == SMSG_MONSTER_MOVE) if (packet->GetOpcode() == SMSG_MONSTER_MOVE)
{ {
hideOpcode = true; hideOpcode = true;
} }
if( (known && GetInstance()->GetConf()->showopcodes==1) if( (known && GetInstance()->GetConf()->showopcodes==1)
|| ((!known) && GetInstance()->GetConf()->showopcodes==2) || ((!known) && GetInstance()->GetConf()->showopcodes==2)
|| (GetInstance()->GetConf()->showopcodes==3) ) || (GetInstance()->GetConf()->showopcodes==3) )
{ {
if(!(GetInstance()->GetConf()->hidefreqopcodes && hideOpcode)) if(!(GetInstance()->GetConf()->hidefreqopcodes && hideOpcode))
logcustom(1,YELLOW,">> Opcode %u [%s] (%s, %u bytes)", packet->GetOpcode(), GetOpcodeName(packet->GetOpcode()), known ? "Known" : "UNKNOWN", packet->size()); logcustom(1,YELLOW,">> Opcode %u [%s] (%s, %u bytes)", packet->GetOpcode(), GetOpcodeName(packet->GetOpcode()), known ? "Known" : "UNKNOWN", packet->size());
} }
if(known) if(known)
{ {
@ -156,14 +160,14 @@ void WorldSession::Update(void)
} }
} }
delete packet; delete packet;
known=false; known=false;
} }
_DoTimedActions(); _DoTimedActions();
if(_world) if(_world)
_world->Update(); _world->Update();
} }
@ -200,16 +204,16 @@ OpcodeHandler *WorldSession::_GetOpcodeHandlerTable() const
{MSG_MOVE_HEARTBEAT, &WorldSession::_HandleMovementOpcode}, {MSG_MOVE_HEARTBEAT, &WorldSession::_HandleMovementOpcode},
{MSG_MOVE_FALL_LAND, &WorldSession::_HandleMovementOpcode}, {MSG_MOVE_FALL_LAND, &WorldSession::_HandleMovementOpcode},
{MSG_MOVE_TELEPORT_ACK, &WorldSession::_HandleTelePortAckOpcode}, {MSG_MOVE_TELEPORT_ACK, &WorldSession::_HandleTelePortAckOpcode},
{SMSG_COMPRESSED_UPDATE_OBJECT, &WorldSession::_HandleCompressedUpdateObjectOpcode}, {SMSG_COMPRESSED_UPDATE_OBJECT, &WorldSession::_HandleCompressedUpdateObjectOpcode},
{SMSG_UPDATE_OBJECT, &WorldSession::_HandleUpdateObjectOpcode}, {SMSG_UPDATE_OBJECT, &WorldSession::_HandleUpdateObjectOpcode},
{SMSG_CAST_RESULT, &WorldSession::_HandleCastResultOpcode}, {SMSG_CAST_RESULT, &WorldSession::_HandleCastResultOpcode},
{SMSG_ITEM_QUERY_SINGLE_RESPONSE, &WorldSession::_HandleItemQuerySingleResponseOpcode}, {SMSG_ITEM_QUERY_SINGLE_RESPONSE, &WorldSession::_HandleItemQuerySingleResponseOpcode},
{SMSG_DESTROY_OBJECT, &WorldSession::_HandleDestroyObjectOpcode}, {SMSG_DESTROY_OBJECT, &WorldSession::_HandleDestroyObjectOpcode},
{SMSG_INITIAL_SPELLS, &WorldSession::_HandleInitialSpellsOpcode}, {SMSG_INITIAL_SPELLS, &WorldSession::_HandleInitialSpellsOpcode},
{SMSG_LEARNED_SPELL, &WorldSession::_HandleLearnedSpellOpcode}, {SMSG_LEARNED_SPELL, &WorldSession::_HandleLearnedSpellOpcode},
{SMSG_REMOVED_SPELL, &WorldSession::_HandleLearnedSpellOpcode}, {SMSG_REMOVED_SPELL, &WorldSession::_HandleLearnedSpellOpcode},
{SMSG_CHANNEL_LIST, &WorldSession::_HandleChannelListOpcode}, {SMSG_CHANNEL_LIST, &WorldSession::_HandleChannelListOpcode},
{SMSG_EMOTE, &WorldSession::_HandleEmoteOpcode}, {SMSG_EMOTE, &WorldSession::_HandleEmoteOpcode},
{SMSG_TEXT_EMOTE, &WorldSession::_HandleTextEmoteOpcode}, {SMSG_TEXT_EMOTE, &WorldSession::_HandleTextEmoteOpcode},
{SMSG_NEW_WORLD, &WorldSession::_HandleNewWorldOpcode}, {SMSG_NEW_WORLD, &WorldSession::_HandleNewWorldOpcode},
@ -233,7 +237,7 @@ void WorldSession::_OnEnterWorld(void)
_logged=true; _logged=true;
GetInstance()->GetScripts()->variables.Set("@inworld","true"); GetInstance()->GetScripts()->variables.Set("@inworld","true");
GetInstance()->GetScripts()->RunScript("_enterworld",NULL); GetInstance()->GetScripts()->RunScript("_enterworld",NULL);
} }
} }
@ -270,34 +274,34 @@ void WorldSession::_DoTimedActions(void)
void WorldSession::_HandleAuthChallengeOpcode(WorldPacket& recvPacket) void WorldSession::_HandleAuthChallengeOpcode(WorldPacket& recvPacket)
{ {
std::string acc = stringToUpper(GetInstance()->GetConf()->accname); std::string acc = stringToUpper(GetInstance()->GetConf()->accname);
uint32 serverseed; uint32 serverseed;
recvPacket >> serverseed; recvPacket >> serverseed;
logdebug("Auth: serverseed=0x%X",serverseed); logdebug("Auth: serverseed=0x%X",serverseed);
Sha1Hash digest; Sha1Hash digest;
digest.UpdateData(acc); digest.UpdateData(acc);
uint32 unk=0; uint32 unk=0;
digest.UpdateData((uint8*)&unk,sizeof(uint32)); digest.UpdateData((uint8*)&unk,sizeof(uint32));
BigNumber clientseed; BigNumber clientseed;
clientseed.SetRand(8*4); clientseed.SetRand(8*4);
uint32 clientseed_uint32=clientseed.AsDword(); uint32 clientseed_uint32=clientseed.AsDword();
digest.UpdateData((uint8*)&clientseed_uint32,sizeof(uint32)); digest.UpdateData((uint8*)&clientseed_uint32,sizeof(uint32));
digest.UpdateData((uint8*)&serverseed,sizeof(uint32)); digest.UpdateData((uint8*)&serverseed,sizeof(uint32));
digest.UpdateBigNumbers(&(GetInstance()->GetSessionKey()),NULL); digest.UpdateBigNumbers(&(GetInstance()->GetSessionKey()),NULL);
digest.Finalize(); digest.Finalize();
WorldPacket auth; WorldPacket auth;
auth<<(uint32)(GetInstance()->GetConf()->clientbuild)<<unk<<acc<<clientseed_uint32; auth<<(uint32)(GetInstance()->GetConf()->clientbuild)<<unk<<acc<<clientseed_uint32;
auth.append(digest.GetDigest(),20); auth.append(digest.GetDigest(),20);
// recvPacket << real_size // recvPacket << real_size
// recvPacket << ziped_UI_Plugins_Info // recvPacket << ziped_UI_Plugins_Info
// TODO: add addon data, simulate no addons. // TODO: add addon data, simulate no addons.
auth<<(uint32)0; // no addons? no idea, but seems to work. MaNGOS doesnt accept without this. auth<<(uint32)0; // no addons? no idea, but seems to work. MaNGOS doesnt accept without this.
auth.SetOpcode(CMSG_AUTH_SESSION); auth.SetOpcode(CMSG_AUTH_SESSION);
SendWorldPacket(auth); SendWorldPacket(auth);
// note that if the sessionkey/auth is wrong or failed, the server sends the following packet UNENCRYPTED! // note that if the sessionkey/auth is wrong or failed, the server sends the following packet UNENCRYPTED!
// so its not 100% correct to init the crypt here, but it should do the job if authing was correct // so its not 100% correct to init the crypt here, but it should do the job if authing was correct
_socket->InitCrypt(GetInstance()->GetSessionKey().AsByteArray(), 40); _socket->InitCrypt(GetInstance()->GetSessionKey().AsByteArray(), 40);
} }
@ -306,12 +310,12 @@ void WorldSession::_HandleAuthResponseOpcode(WorldPacket& recvPacket)
uint8 errcode; uint8 errcode;
recvPacket >> errcode; recvPacket >> errcode;
if(errcode==0xC){ if(errcode==0xC){
logdetail("World Authentication successful, preparing for char list request..."); logdetail("World Authentication successful, preparing for char list request...");
WorldPacket pkt; WorldPacket pkt;
pkt.SetOpcode(CMSG_CHAR_ENUM); pkt.SetOpcode(CMSG_CHAR_ENUM);
SendWorldPacket(pkt); SendWorldPacket(pkt);
} else { } else {
logcritical("World Authentication failed, errcode=0x%X",(unsigned char)errcode); logcritical("World Authentication failed, errcode=0x%X",(unsigned char)errcode);
GetInstance()->SetError(); GetInstance()->SetError();
} }
} }
@ -319,59 +323,60 @@ void WorldSession::_HandleAuthResponseOpcode(WorldPacket& recvPacket)
void WorldSession::_HandleCharEnumOpcode(WorldPacket& recvPacket) void WorldSession::_HandleCharEnumOpcode(WorldPacket& recvPacket)
{ {
uint8 num; uint8 num;
PlayerEnum plr[10]; // max characters per realm is 10 PlayerEnum plr[10]; // max characters per realm is 10
uint8 dummy8; uint8 dummy8;
recvPacket >> num; recvPacket >> num;
if(num==0){ if(num==0){
logerror("No chars found!"); logerror("No chars found!");
GetInstance()->SetError(); GetInstance()->SetError();
return; return;
} }
_LoadCache(); // we are about to login, so we need cache data
logdetail("W: Chars in list: %u\n",num); logdetail("Chars in list: %u\n",num);
for(unsigned int i=0;i<num;i++){ _LoadCache(); // we are about to login, so we need cache data
recvPacket >> plr[i]._guid; for(unsigned int i=0;i<num;i++){
recvPacket >> plr[i]._name; recvPacket >> plr[i]._guid;
recvPacket >> plr[i]._race; recvPacket >> plr[i]._name;
recvPacket >> plr[i]._class; recvPacket >> plr[i]._race;
recvPacket >> plr[i]._gender; recvPacket >> plr[i]._class;
recvPacket >> plr[i]._bytes1; recvPacket >> plr[i]._gender;
recvPacket >> plr[i]._bytes2; recvPacket >> plr[i]._bytes1;
recvPacket >> plr[i]._bytes3; recvPacket >> plr[i]._bytes2;
recvPacket >> plr[i]._bytes4; recvPacket >> plr[i]._bytes3;
recvPacket >> plr[i]._bytesx; recvPacket >> plr[i]._bytes4;
recvPacket >> plr[i]._level; recvPacket >> plr[i]._bytesx;
recvPacket >> plr[i]._zoneId; recvPacket >> plr[i]._level;
recvPacket >> plr[i]._mapId; recvPacket >> plr[i]._zoneId;
recvPacket >> plr[i]._x; recvPacket >> plr[i]._mapId;
recvPacket >> plr[i]._y; recvPacket >> plr[i]._x;
recvPacket >> plr[i]._z; recvPacket >> plr[i]._y;
recvPacket >> plr[i]._guildId; recvPacket >> plr[i]._z;
recvPacket >> dummy8; recvPacket >> plr[i]._guildId;
recvPacket >> plr[i]._flags; recvPacket >> dummy8;
recvPacket >> dummy8 >> dummy8 >> dummy8; recvPacket >> plr[i]._flags;
recvPacket >> plr[i]._petInfoId; recvPacket >> dummy8 >> dummy8 >> dummy8;
recvPacket >> plr[i]._petLevel; recvPacket >> plr[i]._petInfoId;
recvPacket >> plr[i]._petFamilyId; recvPacket >> plr[i]._petLevel;
for(unsigned int inv=0;inv<20;inv++) recvPacket >> plr[i]._petFamilyId;
for(unsigned int inv=0;inv<20;inv++)
{ {
recvPacket >> plr[i]._items[inv].displayId >> plr[i]._items[inv].inventorytype; recvPacket >> plr[i]._items[inv].displayId >> plr[i]._items[inv].inventorytype;
} }
plrNameCache.AddInfo(plr[i]._guid, plr[i]._name); plrNameCache.AddInfo(plr[i]._guid, plr[i]._name);
} }
bool char_found=false; bool char_found=false;
for(unsigned int i=0;i<num;i++){ for(unsigned int i=0;i<num;i++){
logcustom(0,LGREEN,"## %s (%u) [%s/%s] Map: %s; Zone: %s", logcustom(0,LGREEN,"## %s (%u) [%s/%s] Map: %s; Area: %s",
plr[i]._name.c_str(), plr[i]._name.c_str(),
plr[i]._level, plr[i]._level,
GetDBMgr().GetRaceName(plr[i]._race).c_str(), GetDBMgr().GetRaceName(plr[i]._race).c_str(),
GetDBMgr().GetClassName_(plr[i]._class).c_str(), GetDBMgr().GetClassName_(plr[i]._class).c_str(),
GetDBMgr().GetMapName(plr[i]._mapId).c_str(), GetDBMgr().GetMapName(plr[i]._mapId).c_str(),
GetDBMgr().GetZoneName(plr[i]._zoneId).c_str()); GetDBMgr().GetAreaName(plr[i]._zoneId).c_str());
logdetail("-> coords: map=%u zone=%u x=%f y=%f z=%f", logdetail("-> coords: map=%u zone=%u x=%f y=%f z=%f",
plr[i]._mapId,plr[i]._zoneId,plr[i]._x,plr[i]._y,plr[i]._z); plr[i]._mapId,plr[i]._zoneId,plr[i]._x,plr[i]._y,plr[i]._z);
for(unsigned int inv=0;inv<20;inv++) for(unsigned int inv=0;inv<20;inv++)
{ {
if(plr[i]._items[inv].displayId) if(plr[i]._items[inv].displayId)
@ -379,66 +384,76 @@ void WorldSession::_HandleCharEnumOpcode(WorldPacket& recvPacket)
} }
if(plr[i]._name==GetInstance()->GetConf()->charname) if(plr[i]._name==GetInstance()->GetConf()->charname)
{ {
char_found=true; char_found=true;
_myGUID=plr[i]._guid; _myGUID=plr[i]._guid;
GetInstance()->GetScripts()->variables.Set("@myrace",toString(plr[i]._race)); GetInstance()->GetScripts()->variables.Set("@myrace",toString(plr[i]._race));
} }
} }
if(!char_found){ if(!char_found){
logerror("Character \"%s\" was not found on char list!",GetInstance()->GetConf()->charname.c_str()); logerror("Character \"%s\" was not found on char list!",GetInstance()->GetConf()->charname.c_str());
GetInstance()->SetError(); GetInstance()->SetError();
return; return;
} else { } else {
log("Entering World with Character \"%s\"...",GetInstance()->GetConf()->charname.c_str()); log("Entering World with Character \"%s\"...",GetInstance()->GetConf()->charname.c_str());
// create the character and add it to the objmgr.
MyCharacter *my = new MyCharacter(); // create the character and add it to the objmgr.
my->Create(_myGUID); // note: this is the only object that has to stay in memory unless its explicitly deleted by the server!
objmgr.Add(my); // that means even if the server sends create object with that guid, do NOT recreate it!!
MyCharacter *my = new MyCharacter();
my->Create(_myGUID);
objmgr.Add(my);
// TODO: initialize the world here, and load required maps. // TODO: initialize the world here, and load required maps.
// must remove appropriate code from _HandleLoginVerifyWorldOpcode() then!! // must remove appropriate code from _HandleLoginVerifyWorldOpcode() then!!
WorldPacket pkt(CMSG_PLAYER_LOGIN,8); WorldPacket pkt(CMSG_PLAYER_LOGIN,8);
pkt << _myGUID; pkt << _myGUID;
SendWorldPacket(pkt); SendWorldPacket(pkt);
} }
} }
void WorldSession::_HandleSetProficiencyOpcode(WorldPacket& recvPacket) void WorldSession::_HandleSetProficiencyOpcode(WorldPacket& recvPacket)
{ {
_OnEnterWorld(); if(recvPacket.size())
{
DEBUG(
logdebug("SetProficiency: Hexdump:");
logdebug(toHexDump((uint8*)recvPacket.contents(),recvPacket.size(),true).c_str());
);
}
} }
void WorldSession::_HandleAccountDataMD5Opcode(WorldPacket& recvPacket) void WorldSession::_HandleAccountDataMD5Opcode(WorldPacket& recvPacket)
{ {
_OnEnterWorld(); // packet structure not yet known
} }
void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket) void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket)
{ {
uint8 type=0; uint8 type=0;
uint32 lang=0; uint32 lang=0;
uint64 target_guid=0; uint64 target_guid=0;
uint32 msglen=0; uint32 msglen=0;
std::string msg,channel=""; std::string msg,channel="";
bool isCmd=false; bool isCmd=false;
recvPacket >> type >> lang; recvPacket >> type >> lang;
std::string langname = GetDBMgr().GetLangName(lang); std::string langname = GetDBMgr().GetLangName(lang);
const char* ln = langname.c_str(); const char* ln = langname.c_str();
if (type == CHAT_MSG_CHANNEL) if (type == CHAT_MSG_CHANNEL)
{ {
recvPacket >> channel; // extract channel name recvPacket >> channel; // extract channel name
} }
recvPacket >> target_guid; recvPacket >> target_guid;
std::string plrname; std::string plrname;
if(target_guid){ if(target_guid)
{
plrname=plrNameCache.GetName(target_guid); plrname=plrNameCache.GetName(target_guid);
if(plrname.empty()) if(plrname.empty())
{ {
@ -446,54 +461,54 @@ void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket)
plrname="Unknown Entity"; plrname="Unknown Entity";
} }
} }
GetInstance()->GetScripts()->variables.Set("@thismsg_name",plrname); GetInstance()->GetScripts()->variables.Set("@thismsg_name",plrname);
GetInstance()->GetScripts()->variables.Set("@thismsg",toString(target_guid)); GetInstance()->GetScripts()->variables.Set("@thismsg",toString(target_guid));
if(type == CHAT_MSG_SAY || type == CHAT_MSG_YELL || type == CHAT_MSG_PARTY) if(type == CHAT_MSG_SAY || type == CHAT_MSG_YELL || type == CHAT_MSG_PARTY)
recvPacket >> target_guid; recvPacket >> target_guid;
recvPacket >> msglen >> msg; recvPacket >> msglen >> msg;
if (type == CHAT_MSG_SYSTEM) if (type == CHAT_MSG_SYSTEM)
{ {
logcustom(0,WHITE,"SYSMSG: \"%s\"",msg.c_str()); logcustom(0,WHITE,"SYSMSG: \"%s\"",msg.c_str());
} }
else if (type==CHAT_MSG_WHISPER ) 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",plrname.c_str(),ln,msg.c_str());
} }
else if (type==CHAT_MSG_CHANNEL ) 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(),plrname.c_str(),ln,msg.c_str());
} }
else if (type==CHAT_MSG_SAY ) 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",plrname.c_str(),ln,msg.c_str());
} }
else if (type==CHAT_MSG_YELL ) 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 ",plrname.c_str(),ln,msg.c_str());
} }
else if (type==CHAT_MSG_WHISPER_INFORM ) 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",plrname.c_str(),ln,msg.c_str());
} }
else if (type==CHAT_MSG_GUILD ) 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",plrname.c_str(),ln,msg.c_str());
} }
else if (type==CHAT_MSG_PARTY ) 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",plrname.c_str(),ln,msg.c_str());
} }
else if (type==CHAT_MSG_EMOTE ) else if (type==CHAT_MSG_EMOTE )
{ {
logcustom(0,WHITE,"EMOTE: %s [%s]: %s",plrname.c_str(),ln,msg.c_str()); logcustom(0,WHITE,"EMOTE [%s]: %s %s",ln,plrname.c_str(),msg.c_str());
} }
else 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,plrname.c_str(),ln,msg.c_str());
} }
if(target_guid!=GetGuid() && msg.length()>1 && msg.at(0)=='-' && GetInstance()->GetConf()->allowgamecmd) if(target_guid!=GetGuid() && msg.length()>1 && msg.at(0)=='-' && GetInstance()->GetConf()->allowgamecmd)
isCmd=true; isCmd=true;
@ -502,14 +517,14 @@ void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket)
if(type==CHAT_MSG_SAY && target_guid!=_myGUID && !isCmd) if(type==CHAT_MSG_SAY && target_guid!=_myGUID && !isCmd)
{ {
// TODO: insert a good ChatAI here. // TODO: insert a good ChatAI here.
if (GetInstance()->GetConf()->enablechatai) if (GetInstance()->GetConf()->enablechatai)
{ {
if(msg=="lol") if(msg=="lol")
SendChatMessage(CHAT_MSG_SAY,lang,"say \"lol\" if you have nothing else to say... lol xD",""); SendChatMessage(CHAT_MSG_SAY,lang,"say \"lol\" if you have nothing else to say... lol xD","");
else if(msg.length()>4 && msg.find("you?")!=std::string::npos) else if(msg.length()>4 && msg.find("you?")!=std::string::npos)
SendChatMessage(CHAT_MSG_SAY,lang,GetInstance()->GetScripts()->variables.Get("@version").append(" -- i am a bot, made by False.Genesis, my master."),""); SendChatMessage(CHAT_MSG_SAY,lang,GetInstance()->GetScripts()->variables.Get("@version").append(" -- i am a bot, made by False.Genesis, my master."),"");
else if(msg=="hi") else if(msg=="hi")
SendChatMessage(CHAT_MSG_SAY,lang,"Hi, wadup?",""); SendChatMessage(CHAT_MSG_SAY,lang,"Hi, wadup?","");
else if(msg.length()<12 && msg.find("wtf")!=std::string::npos) else if(msg.length()<12 && msg.find("wtf")!=std::string::npos)
SendChatMessage(CHAT_MSG_SAY,lang,"Yeah, WTF is a good way to say you dont understand anything... :P",""); SendChatMessage(CHAT_MSG_SAY,lang,"Yeah, WTF is a good way to say you dont understand anything... :P","");
else if(msg.length()<15 && (msg.find("omg")!=std::string::npos || msg.find("omfg")!=std::string::npos) ) else if(msg.length()<15 && (msg.find("omg")!=std::string::npos || msg.find("omfg")!=std::string::npos) )
@ -523,8 +538,8 @@ void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket)
if(isCmd) if(isCmd)
{ {
GetInstance()->GetScripts()->variables.Set("@thiscmd_name",plrname); GetInstance()->GetScripts()->variables.Set("@thiscmd_name",plrname);
GetInstance()->GetScripts()->variables.Set("@thiscmd",toString(target_guid)); GetInstance()->GetScripts()->variables.Set("@thiscmd",toString(target_guid));
std::string lin=msg.substr(1,msg.length()-1); std::string lin=msg.substr(1,msg.length()-1);
try try
{ {
@ -534,12 +549,12 @@ void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket)
{ {
SendChatMessage(CHAT_MSG_SAY,0,"Exception while trying to execute: [ "+lin+" ]",""); SendChatMessage(CHAT_MSG_SAY,0,"Exception while trying to execute: [ "+lin+" ]","");
} }
} }
if(type==CHAT_MSG_WHISPER && (!isCmd) && target_guid!=GetGuid()) if(type==CHAT_MSG_WHISPER && (!isCmd) && target_guid!=GetGuid())
{ {
GetInstance()->GetScripts()->variables.Set("@thiswhisper_name",plrname); GetInstance()->GetScripts()->variables.Set("@thiswhisper_name",plrname);
GetInstance()->GetScripts()->variables.Set("@thiswhisper",toString(target_guid)); GetInstance()->GetScripts()->variables.Set("@thiswhisper",toString(target_guid));
GetInstance()->GetScripts()->variables.Set("@thiswhisper_lang",toString((uint64)lang)); GetInstance()->GetScripts()->variables.Set("@thiswhisper_lang",toString((uint64)lang));
GetInstance()->GetScripts()->RunScript("_onwhisper",NULL); GetInstance()->GetScripts()->RunScript("_onwhisper",NULL);
} }
@ -560,9 +575,12 @@ void WorldSession::_HandleMessageChatOpcode(WorldPacket& recvPacket)
pos++; pos++;
} }
id = atoi(itemid.c_str()); id = atoi(itemid.c_str());
logdebug("Found Item in chat message: %u",id); if(id)
if(objmgr.GetItemProto(id)==NULL) {
SendQueryItem(id,0); logdebug("Found Item in chat message: %u",id);
if(objmgr.GetItemProto(id)==NULL)
SendQueryItem(id,0);
}
} }
} }
} }
@ -636,35 +654,37 @@ void WorldSession::_HandleMovementOpcode(WorldPacket& recvPacket)
void WorldSession::_HandleTelePortAckOpcode(WorldPacket& recvPacket) void WorldSession::_HandleTelePortAckOpcode(WorldPacket& recvPacket)
{ {
uint32 unk32,time; uint32 unk32,time;
uint64 guid; uint64 guid;
float x, y, z, o; float x, y, z, o;
guid = recvPacket.GetPackedGuid(); guid = recvPacket.GetPackedGuid();
recvPacket >> unk32 >> unk32 >> time >> x >> y >> z >> o >> unk32; recvPacket >> unk32 >> unk32 >> time >> x >> y >> z >> o >> unk32;
logdetail("Got teleported, data: x: %f, y: %f, z: %f, o: %f, guid: "I64FMT, x, y, z, o, guid); logdetail("Got teleported, data: x: %f, y: %f, z: %f, o: %f, guid: "I64FMT, x, y, z, o, guid);
// TODO: put this into a capsule class later, that autodetects movement flags etc. // TODO: put this into a capsule class later, that autodetects movement flags etc.
WorldPacket response; WorldPacket response;
response.SetOpcode(MSG_MOVE_FALL_LAND); response.SetOpcode(MSG_MOVE_FALL_LAND);
response << uint32(0) << (uint32)getMSTime(); // no flags; time correct? response << uint32(0) << (uint32)getMSTime(); // no flags; time correct?
response << x << y << z << o << uint32(0); response << x << y << z << o << uint32(0);
SendWorldPacket(response); SendWorldPacket(response);
if(_world) if(_world)
_world->UpdatePos(x,y); _world->UpdatePos(x,y);
} }
void WorldSession::_HandleNewWorldOpcode(WorldPacket& recvPacket) void WorldSession::_HandleNewWorldOpcode(WorldPacket& recvPacket)
{ {
DEBUG(logdebug("DEBUG: _HandleNewWorldOpcode() objs:%u mychar: ptr=0x%X, guid="I64FMT,objmgr.GetObjectCount(),GetMyChar(),GetMyChar()->GetGUID()));
uint32 mapid; uint32 mapid;
float x,y,z,o; float x,y,z,o;
// we assume we are NOT on a transport! // we assume we are NOT on a transport!
// else we had to do the following before: // else we had to do the following before:
// recvPacket >> tmapid >> tx >> ty >> tz >> to; // recvPacket >> tmapid >> tx >> ty >> tz >> to;
recvPacket >> mapid >> x >> y >> z >> o; recvPacket >> mapid >> x >> y >> z >> o;
GetMyChar()->ClearSpells(); // will be resent by server if(GetMyChar())
GetMyChar()->ClearSpells(); // will be resent by server
// TODO: clear action buttons // TODO: clear action buttons
if(_world) if(_world)
delete _world; delete _world;
@ -674,7 +694,7 @@ void WorldSession::_HandleNewWorldOpcode(WorldPacket& recvPacket)
void WorldSession::_HandleChannelNotifyOpcode(WorldPacket& recvPacket) void WorldSession::_HandleChannelNotifyOpcode(WorldPacket& recvPacket)
{ {
_channels->HandleNotifyOpcode(recvPacket); _channels->HandleNotifyOpcode(recvPacket);
} }
void WorldSession::_HandleCastResultOpcode(WorldPacket& recvPacket) void WorldSession::_HandleCastResultOpcode(WorldPacket& recvPacket)
@ -695,26 +715,26 @@ void WorldSession::_HandleCastResultOpcode(WorldPacket& recvPacket)
void WorldSession::_HandleInitialSpellsOpcode(WorldPacket& recvPacket) void WorldSession::_HandleInitialSpellsOpcode(WorldPacket& recvPacket)
{ {
uint8 unk; uint8 unk;
uint16 spellid,spellslot,count; uint16 spellid,spellslot,count;
recvPacket >> unk >> count; recvPacket >> unk >> count;
logdebug("Got initial spells list, %u spells.",count); logdebug("Got initial spells list, %u spells.",count);
for(uint16 i = 0; i < count; i++) for(uint16 i = 0; i < count; i++)
{ {
recvPacket >> spellid >> spellslot; recvPacket >> spellid >> spellslot;
logdebug("Initial Spell: id=%u slot=%u",spellid,spellslot); logdebug("Initial Spell: id=%u slot=%u",spellid,spellslot);
GetMyChar()->AddSpell(spellid, spellslot); GetMyChar()->AddSpell(spellid, spellslot);
} }
} }
void WorldSession::_HandleLearnedSpellOpcode(WorldPacket& recvPacket) void WorldSession::_HandleLearnedSpellOpcode(WorldPacket& recvPacket)
{ {
uint32 spellid; uint32 spellid;
recvPacket >> spellid; recvPacket >> spellid;
GetMyChar()->AddSpell(spellid, 0); // other spells must be moved by +1 in slot? GetMyChar()->AddSpell(spellid, 0); // other spells must be moved by +1 in slot?
logdebug("Learned spell: id=%u",spellid); logdebug("Learned spell: id=%u",spellid);
} }
void WorldSession::_HandleRemovedSpellOpcode(WorldPacket& recvPacket) void WorldSession::_HandleRemovedSpellOpcode(WorldPacket& recvPacket)
@ -727,7 +747,7 @@ void WorldSession::_HandleRemovedSpellOpcode(WorldPacket& recvPacket)
void WorldSession::_HandleChannelListOpcode(WorldPacket& recvPacket) void WorldSession::_HandleChannelListOpcode(WorldPacket& recvPacket)
{ {
_channels->HandleListRequest(recvPacket); _channels->HandleListRequest(recvPacket);
} }
void WorldSession::_HandleEmoteOpcode(WorldPacket& recvPacket) void WorldSession::_HandleEmoteOpcode(WorldPacket& recvPacket)
@ -812,7 +832,7 @@ void WorldSession::_HandleTextEmoteOpcode(WorldPacket& recvPacket)
target += "me"; target += "me";
else else
target += "one"; target += "one";
if(targeted) if(targeted)
{ {
target += "to"; target += "to";
@ -857,6 +877,7 @@ void WorldSession::_HandleLoginVerifyWorldOpcode(WorldPacket& recvPacket)
recvPacket >> m >> x >> y >> z >> o; recvPacket >> m >> x >> y >> z >> o;
// for now, init the world as soon as the server confirmed that we are where we are. // for now, init the world as soon as the server confirmed that we are where we are.
logdebug("LoginVerifyWorld: map=%u x=%f y=%f z=%f o=%f",m,x,y,z,o); logdebug("LoginVerifyWorld: map=%u x=%f y=%f z=%f o=%f",m,x,y,z,o);
_OnEnterWorld();
if(_world) if(_world)
delete _world; delete _world;
_world = new World(this); _world = new World(this);

View File

@ -408,6 +408,18 @@
<Filter <Filter
Name="GUI" Name="GUI"
Filter=""> Filter="">
<File
RelativePath=".\Client\Gui\DrawObject.cpp">
</File>
<File
RelativePath=".\Client\Gui\DrawObject.h">
</File>
<File
RelativePath=".\Client\Gui\DrawObjMgr.cpp">
</File>
<File
RelativePath=".\Client\Gui\DrawObjMgr.h">
</File>
<File <File
RelativePath=".\Client\Gui\PseuGUI.cpp"> RelativePath=".\Client\Gui\PseuGUI.cpp">
</File> </File>

View File

@ -74,12 +74,13 @@ public:
inline void SetTile(MapTile* tile, uint32 x, uint32 y) { SetTile(tile, y*64 + x); } inline void SetTile(MapTile* tile, uint32 x, uint32 y) { SetTile(tile, y*64 + x); }
inline void SetTile(MapTile* tile, uint32 pos) inline void SetTile(MapTile* tile, uint32 pos)
{ {
_tiles[pos] = tile; if(pos < 4096)
_tiles[pos] = tile;
} }
inline void UnloadMapTile(uint32 x, uint32 y) { UnloadMapTile(y*64 + x); } inline void UnloadMapTile(uint32 x, uint32 y) { UnloadMapTile(y*64 + x); }
inline void UnloadMapTile(uint32 pos) inline void UnloadMapTile(uint32 pos)
{ {
if(_tiles[pos]) if(pos < 4096 && _tiles[pos])
{ {
delete _tiles[pos]; delete _tiles[pos];
_tiles[pos] = NULL; _tiles[pos] = NULL;
@ -88,12 +89,12 @@ public:
inline bool TileExists(uint32 x, uint32 y) { return TileExists(y*64 + x); } inline bool TileExists(uint32 x, uint32 y) { return TileExists(y*64 + x); }
inline bool TileExists(uint32 pos) inline bool TileExists(uint32 pos)
{ {
return _hasTile[pos]; return pos < 4096 ? _hasTile[pos] : false;
} }
inline MapTile *GetTile(uint32 x, uint32 y) { return GetTile(y*64 + x); } inline MapTile *GetTile(uint32 x, uint32 y) { return GetTile(y*64 + x); }
inline MapTile *GetTile(uint32 pos) inline MapTile *GetTile(uint32 pos)
{ {
return _tiles[pos]; return pos < 4096 ? _tiles[pos] : NULL;
} }
void _DebugDump(void); void _DebugDump(void);

View File

@ -105,7 +105,7 @@ std::deque<std::string> GetFileList(std::string path)
std::deque<std::string> files; std::deque<std::string> files;
# ifndef _WIN32 // TODO: fix this function for linux if needed # ifndef _WIN32 // TODO: fix this function for linux if needed
const char *p = path.c_str(); const char *p = path.c_str();
DIR * dirp; DIR * dirp;
struct dirent * dp; struct dirent * dp;
dirp = opendir(p); dirp = opendir(p);
@ -130,15 +130,17 @@ std::deque<std::string> GetFileList(std::string path)
HANDLE hFil=FindFirstFile(p,&fil); HANDLE hFil=FindFirstFile(p,&fil);
if(hFil!=INVALID_HANDLE_VALUE) if(hFil!=INVALID_HANDLE_VALUE)
{ {
files.push_back(std::string(fil.cFileName)); if( !(fil.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
while(FindNextFile(hFil,&fil))
files.push_back(std::string(fil.cFileName)); files.push_back(std::string(fil.cFileName));
while(FindNextFile(hFil,&fil))
{
if( !(fil.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
files.push_back(std::string(fil.cFileName));
}
} }
# endif # endif
while(files.size() && (files.front()=="." || files.front()==".."))
files.pop_front();
return files; return files;
} }