* added possibility to disable handling of incoming opcodes by the core (they will still be handled if a script is assigned!)

* script command: switchopcodehandler,<opcode> true(on)/false(off)
* added script events _onworldsessioncreate/delete
* added new conf option: HideDisabledOpcodes=1/0
* added possibility to spoof worldpackets
This commit is contained in:
false_genesis 2008-02-19 20:01:50 +00:00
parent c87f175ad6
commit d295e30b3f
9 changed files with 183 additions and 28 deletions

View File

@ -35,6 +35,10 @@ showopcodes=3
// 0 - No // 0 - No
hidefreqopcodes=1 hidefreqopcodes=1
// Hide disabled (= unhandled, but known) opcodes?
// 1 - Yes
// 0 - No
HideDisabledOpcodes=0
// the IP or hostname the realm server is running on // the IP or hostname the realm server is running on
realmlist=localhost realmlist=localhost

View File

@ -94,3 +94,20 @@ SAY Forget it, ${@0}, you have only permission ${@1} but need ${@2} to run the s
LOG Player '${@0}' (p:${@1}) wanted to execute '${@3}' (p:${@2}) LOG Player '${@0}' (p:${@1}) wanted to execute '${@3}' (p:${@2})
EMOTE 66 // say NO! EMOTE 66 // say NO!
// ----==== INTERNAL/MISC ====----
#script=_onworldsessioncreate
// no args. called when an instance of the WorldSession class is created
//- script content here
#script=_onworldsessiondelete
// no args. called when an instance of the WorldSession class is deleted
//- script content here

View File

@ -58,6 +58,9 @@ void DefScriptPackage::_InitDefScriptInterface(void)
AddFunc("gui",&DefScriptPackage::SCGui); AddFunc("gui",&DefScriptPackage::SCGui);
AddFunc("sendwho",&DefScriptPackage::SCSendWho); AddFunc("sendwho",&DefScriptPackage::SCSendWho);
AddFunc("getobjectdist",&DefScriptPackage::SCGetObjectDistance); AddFunc("getobjectdist",&DefScriptPackage::SCGetObjectDistance);
AddFunc("switchopcodehandler",&DefScriptPackage::SCSwitchOpcodeHandler);
AddFunc("opcodedisabled",&DefScriptPackage::SCOpcodeDisabled);
AddFunc("spoofworldpacket",&DefScriptPackage::SCSpoofWorldPacket);
} }
DefReturnResult DefScriptPackage::SCshdn(CmdSet& Set) DefReturnResult DefScriptPackage::SCshdn(CmdSet& Set)
@ -278,16 +281,18 @@ DefReturnResult DefScriptPackage::SCcastspell(CmdSet& Set)
return true; return true;
} }
DefReturnResult DefScriptPackage::SCqueryitem(CmdSet& Set){ DefReturnResult DefScriptPackage::SCqueryitem(CmdSet& Set)
uint32 id = atoi(Set.defaultarg.c_str()); {
if(!id)
return false;
if(!(((PseuInstance*)parentMethod)->GetWSession())) if(!(((PseuInstance*)parentMethod)->GetWSession()))
{ {
logerror("Invalid Script call: SCqueryitem: WorldSession not valid"); logerror("Invalid Script call: SCqueryitem: WorldSession not valid");
DEF_RETURN_ERROR; DEF_RETURN_ERROR;
} }
uint32 id = atoi(Set.defaultarg.c_str());
if(!id)
return false;
((PseuInstance*)parentMethod)->GetWSession()->SendQueryItem(id,0); ((PseuInstance*)parentMethod)->GetWSession()->SendQueryItem(id,0);
return true; return true;
} }
@ -295,9 +300,8 @@ DefReturnResult DefScriptPackage::SCqueryitem(CmdSet& Set){
DefReturnResult DefScriptPackage::SCtarget(CmdSet& Set) DefReturnResult DefScriptPackage::SCtarget(CmdSet& Set)
{ {
// TODO: special targets: _self _pet _nearest ... // TODO: special targets: _self _pet _nearest ...
DefReturnResult r; WorldSession *ws = ((PseuInstance*)parentMethod)->GetWSession();
if(!ws)
if(!(((PseuInstance*)parentMethod)->GetWSession()))
{ {
logerror("Invalid Script call: SCtarget: WorldSession not valid"); logerror("Invalid Script call: SCtarget: WorldSession not valid");
DEF_RETURN_ERROR; DEF_RETURN_ERROR;
@ -309,21 +313,30 @@ DefReturnResult DefScriptPackage::SCtarget(CmdSet& Set)
return true; return true;
} }
// TODO: search through all objects. for now only allow to target player std::string what = stringToLower(Set.arg[0]);
uint64 guid = (((PseuInstance*)parentMethod)->GetWSession()->plrNameCache.GetGuid(Set.defaultarg)); uint64 guid = 0;
if(what == "guid")
if( guid && ((PseuInstance*)parentMethod)->GetWSession()->objmgr.GetObj(guid) ) // object must be near
{ {
((PseuInstance*)parentMethod)->GetWSession()->SendSetSelection(guid); // will also set the target for myCharacter guid = DefScriptTools::toUint64(Set.defaultarg);
r.ret=toString(guid); }
else if(what.empty() || what == "player")
{
// TODO: search through all objects. for now only allow to target player
guid = ws->plrNameCache.GetGuid(Set.defaultarg);
}
Object *obj = ws->objmgr.GetObj(guid);
if(obj && obj->IsUnit() || obj->IsCorpse()) // only units and corpses are targetable
{
ws->SendSetSelection(guid); // will also set the target for myCharacter
return toString(guid);
} }
else else
{ {
logdetail("Target '%s' not found!",Set.defaultarg.c_str()); logdetail("Target '%s' not found!",Set.defaultarg.c_str());
return false; return false;
} }
return "";
return r;
} }
DefReturnResult DefScriptPackage::SCloadscp(CmdSet& Set) DefReturnResult DefScriptPackage::SCloadscp(CmdSet& Set)
@ -899,10 +912,16 @@ DefReturnResult DefScriptPackage::SCSendWorldPacket(CmdSet &Set)
ByteBuffer *bb = bytebuffers.GetNoCreate(_NormalizeVarName(Set.defaultarg,Set.myname)); ByteBuffer *bb = bytebuffers.GetNoCreate(_NormalizeVarName(Set.defaultarg,Set.myname));
if(bb) if(bb)
{ {
uint32 opcode = (uint32)DefScriptTools::toNumber(Set.arg[0]); uint16 opc = (uint16)DefScriptTools::toUint64(Set.arg[0]);
if(opcode) // prevent sending CMSG_NULL_ACTION if(!opc)
{ {
WorldPacket wp(opcode, bb->size()); opc = (uint16)GetOpcodeID(Set.arg[0].c_str());
if(opc == uint16(-1))
return false;
}
if(opc) // prevent sending CMSG_NULL_ACTION
{
WorldPacket wp(opc, bb->size());
if(bb->size()) if(bb->size())
wp.append(bb->contents(), bb->size()); wp.append(bb->contents(), bb->size());
ws->SendWorldPacket(wp); ws->SendWorldPacket(wp);
@ -1064,6 +1083,84 @@ DefReturnResult DefScriptPackage::SCGetObjectDistance(CmdSet &Set)
return ""; return "";
} }
DefReturnResult DefScriptPackage::SCSwitchOpcodeHandler(CmdSet &Set)
{
WorldSession *ws = ((PseuInstance*)parentMethod)->GetWSession();
if(!ws)
{
logerror("Invalid Script call: SCRemoveOpcodeHandler: WorldSession not valid");
DEF_RETURN_ERROR;
}
uint16 opc = (uint16)DefScriptTools::toUint64(Set.arg[0]);
bool switchon = DefScriptTools::isTrue(Set.defaultarg);
if(!opc) // ok we cant turn off MSG_NULL_ACTION with this, but who needs it anyway...
{
opc = (uint16)GetOpcodeID(Set.arg[0].c_str());
if(opc == uint16(-1))
return false;
}
else if(opc >= MAX_OPCODE_ID)
{
logerror("Can't enable/disable opcode handling of %u", opc);
return false;
}
if(switchon)
ws->EnableOpcode(opc);
else
ws->DisableOpcode(opc);
logdebug("Opcode handler for %s (%u) %s",GetOpcodeName(opc), opc, switchon ? "enabled" : "disabled");
return true;
}
DefReturnResult DefScriptPackage::SCOpcodeDisabled(CmdSet &Set)
{
WorldSession *ws = ((PseuInstance*)parentMethod)->GetWSession();
if(!ws)
{
logerror("Invalid Script call: SCOpcodeDisabled: WorldSession not valid");
DEF_RETURN_ERROR;
}
uint16 opc = (uint16)DefScriptTools::toUint64(Set.defaultarg);
if(!opc)
{
opc = (uint16)GetOpcodeID(Set.arg[0].c_str());
if(opc == uint16(-1))
return false;
}
else if(opc >= MAX_OPCODE_ID)
{
logerror("SCOpcodeDisabled: Opcode %u out of range", opc);
return false; // we can NEVER handle out of range opcode, but since its not disabled, return false
}
return ws->IsOpcodeDisabled(opc);
}
DefReturnResult DefScriptPackage::SCSpoofWorldPacket(CmdSet &Set)
{
WorldSession *ws = ((PseuInstance*)parentMethod)->GetWSession();
if(!ws)
{
logerror("Invalid Script call: SCSpoofWorldPacket: WorldSession not valid");
DEF_RETURN_ERROR;
}
ByteBuffer *bb = bytebuffers.GetNoCreate(_NormalizeVarName(Set.defaultarg,Set.myname));
if(bb)
{
uint32 opcode = (uint32)DefScriptTools::toNumber(Set.arg[0]);
if(opcode) // ok, here again CMSG_NULL_ACTION doesnt work, but who cares
{
WorldPacket *wp = new WorldPacket(opcode, bb->size()); // will be deleted by the opcode handler later
if(bb->size())
wp->append(bb->contents(), bb->size());
logdebug("Spoofing WorldPacket with opcode %s (%u), size %u",GetOpcodeName(opcode),opcode,wp->size());
ws->AddToPktQueue(wp); // handle this packet as if it was sent by the server
return true;
}
}
return false;
}
void DefScriptPackage::My_LoadUserPermissions(VarSet &vs) void DefScriptPackage::My_LoadUserPermissions(VarSet &vs)
{ {
static char *prefix = "USERS::"; static char *prefix = "USERS::";

View File

@ -49,5 +49,8 @@ DefReturnResult SCBBPutPackedGuid(CmdSet&);
DefReturnResult SCGui(CmdSet&); DefReturnResult SCGui(CmdSet&);
DefReturnResult SCSendWho(CmdSet&); DefReturnResult SCSendWho(CmdSet&);
DefReturnResult SCGetObjectDistance(CmdSet&); DefReturnResult SCGetObjectDistance(CmdSet&);
DefReturnResult SCSwitchOpcodeHandler(CmdSet&);
DefReturnResult SCOpcodeDisabled(CmdSet&);
DefReturnResult SCSpoofWorldPacket(CmdSet&);
#endif #endif

View File

@ -404,6 +404,7 @@ void PseuInstanceConf::ApplyFromVarSet(VarSet &v)
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());
hideDisabledOpcodes=(bool)atoi(v.Get("HIDEDISABLEDOPCODES").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());

View File

@ -45,6 +45,7 @@ class PseuInstanceConf
uint16 networksleeptime; uint16 networksleeptime;
uint8 showopcodes; uint8 showopcodes;
bool hidefreqopcodes; bool hidefreqopcodes;
bool hideDisabledOpcodes;
bool allowgamecmd; bool allowgamecmd;
bool enablecli; bool enablecli;
bool enablechatai; bool enablechatai;

View File

@ -140,6 +140,7 @@ bool PlayerNameCache::ReadFromFile(void)
} }
printf("\n"); printf("\n");
delete nameptr; delete nameptr;
fh.flush();
fh.close(); fh.close();
if(success) if(success)
log("PlayerNameCache successfully loaded."); log("PlayerNameCache successfully loaded.");
@ -409,6 +410,7 @@ void ItemProtoCache_WriteDataToCache(WorldSession *session)
fh.write((char*)buf.contents(),buf.size()); fh.write((char*)buf.contents(),buf.size());
counter++; counter++;
} }
fh.flush();
fh.close(); fh.close();
log("ItemProtoCache: Saved %u Item Prototypes",counter); log("ItemProtoCache: Saved %u Item Prototypes",counter);
} }
@ -523,6 +525,7 @@ void CreatureTemplateCache_WriteDataToCache(WorldSession *session)
fh.write((char*)buf.contents(),buf.size()); fh.write((char*)buf.contents(),buf.size());
counter++; counter++;
} }
fh.flush();
fh.close(); fh.close();
log("CreatureTemplateCache: Saved %u Creature Templates",counter); log("CreatureTemplateCache: Saved %u Creature Templates",counter);
} }

View File

@ -3,7 +3,6 @@
#include "Auth/Sha1.h" #include "Auth/Sha1.h"
#include "Auth/BigNumber.h" #include "Auth/BigNumber.h"
#include "Auth/AuthCrypt.h" #include "Auth/AuthCrypt.h"
#include "Opcodes.h"
#include "WorldPacket.h" #include "WorldPacket.h"
#include "WorldSocket.h" #include "WorldSocket.h"
#include "RealmSocket.h" #include "RealmSocket.h"
@ -34,11 +33,16 @@ WorldSession::WorldSession(PseuInstance *in)
_lag_ms = 0; _lag_ms = 0;
//... //...
in->GetScripts()->RunScriptIfExists("_onworldsessioncreate");
DEBUG(logdebug("WorldSession 0x%X constructor finished",this)); DEBUG(logdebug("WorldSession 0x%X constructor finished",this));
} }
WorldSession::~WorldSession() WorldSession::~WorldSession()
{ {
_instance->GetScripts()->RunScriptIfExists("_onworldsessiondelete");
logdebug("~WorldSession(): %u packets left unhandled, and %u delayed. deleting.",pktQueue.size(),delayedPktQueue.size());
WorldPacket *packet; WorldPacket *packet;
// clear the queue // clear the queue
while(pktQueue.size()) while(pktQueue.size())
@ -46,6 +50,13 @@ WorldSession::~WorldSession()
packet = pktQueue.next(); packet = pktQueue.next();
delete packet; delete packet;
} }
// clear the delayed queue
while(delayedPktQueue.size())
{
packet = delayedPktQueue.back().pkt;
delayedPktQueue.c.pop_back();
delete packet;
}
if(_channels) if(_channels)
delete _channels; delete _channels;
@ -156,27 +167,30 @@ void WorldSession::HandleWorldPacket(WorldPacket *packet)
} }
bool hideOpcode = false; bool hideOpcode = false;
bool disabledOpcode = IsOpcodeDisabled(packet->GetOpcode());
if(disabledOpcode && GetInstance()->GetConf()->hideDisabledOpcodes)
hideOpcode = true;
// 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 (GetInstance()->GetConf()->hidefreqopcodes)
{ {
hideOpcode = true; switch(packet->GetOpcode())
{
case SMSG_MONSTER_MOVE:
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(!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 ? (disabledOpcode ? "Disabled" : "Known") : "UNKNOWN"), packet->size());
} }
try try
{ {
// call the opcode handler
if(known)
(this->*table[hpos].handler)(*packet);
// if there is a script attached to that opcode, call it now. // if there is a script attached to that opcode, call it now.
// note: the pkt rpos needs to be reset by the scripts! // note: the pkt rpos needs to be reset by the scripts!
std::string scname = "opcode::"; std::string scname = "opcode::";
@ -190,6 +204,12 @@ void WorldSession::HandleWorldPacket(WorldPacket *packet)
GetInstance()->GetScripts()->bytebuffers.Unlink(pktname); GetInstance()->GetScripts()->bytebuffers.Unlink(pktname);
} }
// call the opcode handler
if(known && !disabledOpcode)
{
packet->rpos(0);
(this->*table[hpos].handler)(*packet);
}
} }
catch (ByteBufferException bbe) catch (ByteBufferException bbe)
{ {

View File

@ -2,6 +2,7 @@
#define _WORLDSESSION_H #define _WORLDSESSION_H
#include <queue> #include <queue>
#include <bitset>
#include "common.h" #include "common.h"
#include "PseuWoW.h" #include "PseuWoW.h"
@ -11,6 +12,7 @@
#include "SharedDefines.h" #include "SharedDefines.h"
#include "ObjMgr.h" #include "ObjMgr.h"
#include "CacheHandler.h" #include "CacheHandler.h"
#include "Opcodes.h"
class WorldSocket; class WorldSocket;
class WorldPacket; class WorldPacket;
@ -84,10 +86,16 @@ public:
void HandleWorldPacket(WorldPacket*); void HandleWorldPacket(WorldPacket*);
inline void DisableOpcode(uint16 opcode) { _disabledOpcodes[opcode] = true; }
inline void EnableOpcode(uint16 opcode) { _disabledOpcodes[opcode] = false; }
inline bool IsOpcodeDisabled(uint16 opcode) { return _disabledOpcodes[opcode]; }
PlayerNameCache plrNameCache; PlayerNameCache plrNameCache;
ObjMgr objmgr; ObjMgr objmgr;
private: private:
OpcodeHandler *_GetOpcodeHandlerTable(void) const; OpcodeHandler *_GetOpcodeHandlerTable(void) const;
// Helpers // Helpers
@ -148,6 +156,7 @@ private:
World *_world; World *_world;
WhoList _whoList; WhoList _whoList;
uint32 _lag_ms; uint32 _lag_ms;
std::bitset<MAX_OPCODE_ID> _disabledOpcodes;
}; };
#endif #endif