From 074bd3a08fbb4422251913b013219c681316f5d8 Mon Sep 17 00:00:00 2001 From: Wyk3d Date: Sat, 15 Nov 2008 20:30:06 +0200 Subject: [PATCH 1/6] [6827] Added an interface for defining custom SQLStorage loaders. --- src/shared/Database/Makefile.am | 1 + src/shared/Database/SQLStorage.cpp | 138 ++--------------- src/shared/Database/SQLStorage.h | 64 ++++++-- src/shared/Database/SQLStorageImpl.h | 214 +++++++++++++++++++++++++++ src/shared/revision_nr.h | 2 +- win/VC71/shared.vcproj | 3 + win/VC80/shared.vcproj | 4 + win/VC90/shared.vcproj | 4 + 8 files changed, 294 insertions(+), 136 deletions(-) create mode 100644 src/shared/Database/SQLStorageImpl.h diff --git a/src/shared/Database/Makefile.am b/src/shared/Database/Makefile.am index d967e1ea0..d28f9b960 100644 --- a/src/shared/Database/Makefile.am +++ b/src/shared/Database/Makefile.am @@ -55,6 +55,7 @@ libmangosdatabase_a_SOURCES = \ QueryResultSqlite.h \ SQLStorage.cpp \ SQLStorage.h \ + SQLStorageImpl.h \ SqlDelayThread.cpp \ SqlDelayThread.h \ SqlOperations.cpp \ diff --git a/src/shared/Database/SQLStorage.cpp b/src/shared/Database/SQLStorage.cpp index 9c980dcb8..b504a178d 100644 --- a/src/shared/Database/SQLStorage.cpp +++ b/src/shared/Database/SQLStorage.cpp @@ -17,9 +17,7 @@ */ #include "SQLStorage.h" -#include "ProgressBar.h" -#include "Log.h" -#include "dbcfile.h" +#include "SQLStorageImpl.h" #ifdef DO_POSTGRESQL extern DatabasePostgre WorldDatabase; @@ -53,139 +51,27 @@ void SQLStorage::Free () { uint32 offset=0; for(uint32 x=0;xFetch(); - RecordCount=fields[0].GetUInt32(); - delete result; - } - else - RecordCount = 0; - - result = WorldDatabase.PQuery("SELECT * FROM %s",table); - - if(!result) - { - sLog.outError("%s table is empty!\n",table); - RecordCount = 0; - return; - } - - uint32 recordsize=0; - uint32 offset=0; - - if(iNumFields!=result->GetFieldCount()) - { - RecordCount = 0; - sLog.outError("Error in %s table, probably sql file format was updated (there should be %d fields in sql).\n",table,iNumFields); - delete result; - exit(1); // Stop server at loading broken or non-compatible table. - } - - //get struct size - uint32 sc=0; - uint32 bo=0; - uint32 bb=0; - for(uint32 x=0;xFetch(); - bar.step(); - char *p=(char*)&_data[recordsize*count]; - newIndex[fields[0].GetUInt32()]=p; - - offset=0; - for(uint32 x=0;x0); - offset+=sizeof(bool); - break; - case FT_BYTE: - *((char*)(&p[offset]))=(fields[x].GetUInt8()); - offset+=sizeof(char); - break; - case FT_INT: - *((uint32*)(&p[offset]))=fields[x].GetUInt32(); - offset+=sizeof(uint32); - break; - case FT_FLOAT: - *((float*)(&p[offset]))=fields[x].GetFloat(); - offset+=sizeof(float); - break; - case FT_STRING: - char const* tmp = fields[x].GetString(); - char* st; - if(!tmp) - { - st=new char[1]; - *st=0; - } - else - { - uint32 l=strlen(tmp)+1; - st=new char[l]; - memcpy(st,tmp,l); - } - *((char**)(&p[offset]))=st; - offset+=sizeof(char*); - break; - } - ++count; - }while( result->NextRow() ); - - delete result; - - pIndex =newIndex; - MaxEntry=maxi; - data=_data; -} + SQLStorageLoader loader; + loader.Load(*this); +} \ No newline at end of file diff --git a/src/shared/Database/SQLStorage.h b/src/shared/Database/SQLStorage.h index 6a06eb01a..69275c155 100644 --- a/src/shared/Database/SQLStorage.h +++ b/src/shared/Database/SQLStorage.h @@ -24,18 +24,26 @@ class SQLStorage { + template + friend struct SQLStorageLoaderBase; + public: - SQLStorage(const char*fmt,const char * _entry_field,const char * sqlname) + SQLStorage(const char* fmt, const char * _entry_field, const char * sqlname) { - format=fmt; - entry_field = _entry_field; - table=sqlname; - data=NULL; - pIndex=NULL; - iNumFields =strlen(fmt); - MaxEntry = 0; + src_format = fmt; + dst_format = fmt; + init(_entry_field, sqlname); } + + SQLStorage(const char* src_fmt, const char* dst_fmt, const char * _entry_field, const char * sqlname) + { + src_format = src_fmt; + dst_format = dst_fmt; + init(_entry_field, sqlname); + } + + ~SQLStorage() { Free(); @@ -54,15 +62,53 @@ class SQLStorage uint32 RecordCount; uint32 MaxEntry; uint32 iNumFields; + void Load(); void Free(); + private: + void init(const char * _entry_field, const char * sqlname) + { + entry_field = _entry_field; + table=sqlname; + data=NULL; + pIndex=NULL; + iNumFields = strlen(src_format); + MaxEntry = 0; + } + char** pIndex; char *data; - const char *format; + const char *src_format; + const char *dst_format; const char *table; const char *entry_field; //bool HasString; }; + +template +struct SQLStorageLoaderBase +{ + public: + void Load(SQLStorage &storage); + + template + void convert(uint32 field_pos, S src, D &dst); + template + void convert_to_str(uint32 field_pos, S src, char * & dst); + template + void convert_from_str(uint32 field_pos, char * src, D& dst); + void convert_str_to_str(uint32 field_pos, char *src, char *&dst); + + private: + template + void storeValue(V value, SQLStorage &store, char *p, int x, uint32 &offset); + void storeValue(char * value, SQLStorage &store, char *p, int x, uint32 &offset); +}; + +struct SQLStorageLoader : public SQLStorageLoaderBase +{ +}; + #endif diff --git a/src/shared/Database/SQLStorageImpl.h b/src/shared/Database/SQLStorageImpl.h new file mode 100644 index 000000000..4f10c6eee --- /dev/null +++ b/src/shared/Database/SQLStorageImpl.h @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ProgressBar.h" +#include "Log.h" +#include "dbcfile.h" + +template +template +void SQLStorageLoaderBase::convert(uint32 field_pos, S src, D &dst) +{ + dst = D(src); +} + +template +void SQLStorageLoaderBase::convert_str_to_str(uint32 field_pos, char *src, char *&dst) +{ + if(!src) + { + dst = new char[1]; + *dst = 0; + } + else + { + uint32 l = strlen(src) + 1; + dst = new char[l]; + memcpy(dst, src, l); + } +} + +template +template +void SQLStorageLoaderBase::convert_to_str(uint32 field_pos, S src, char * & dst) +{ + dst = new char[1]; + *dst = 0; +} + +template +template +void SQLStorageLoaderBase::convert_from_str(uint32 field_pos, char * src, D& dst) +{ + dst = 0; +} + +template +template +void SQLStorageLoaderBase::storeValue(V value, SQLStorage &store, char *p, int x, uint32 &offset) +{ + T * subclass = (static_cast(this)); + switch(store.dst_format[x]) + { + case FT_LOGIC: + subclass->convert(x, value, *((bool*)(&p[offset])) ); + offset+=sizeof(bool); + break; + case FT_BYTE: + subclass->convert(x, value, *((char*)(&p[offset])) ); + offset+=sizeof(char); + break; + case FT_INT: + subclass->convert(x, value, *((uint32*)(&p[offset])) ); + offset+=sizeof(uint32); + break; + case FT_FLOAT: + subclass->convert(x, value, *((float*)(&p[offset])) ); + offset+=sizeof(float); + break; + case FT_STRING: + subclass->convert_to_str(x, value, *((char**)(&p[offset])) ); + offset+=sizeof(char*); + break; + } +} + +template +void SQLStorageLoaderBase::storeValue(char * value, SQLStorage &store, char *p, int x, uint32 &offset) +{ + T * subclass = (static_cast(this)); + switch(store.dst_format[x]) + { + case FT_LOGIC: + subclass->convert_from_str(x, value, *((bool*)(&p[offset])) ); + offset+=sizeof(bool); + break; + case FT_BYTE: + subclass->convert_from_str(x, value, *((char*)(&p[offset])) ); + offset+=sizeof(char); + break; + case FT_INT: + subclass->convert_from_str(x, value, *((uint32*)(&p[offset])) ); + offset+=sizeof(uint32); + break; + case FT_FLOAT: + subclass->convert_from_str(x, value, *((float*)(&p[offset])) ); + offset+=sizeof(float); + break; + case FT_STRING: + subclass->convert_str_to_str(x, value, *((char**)(&p[offset])) ); + offset+=sizeof(char*); + break; + } +} + +template +void SQLStorageLoaderBase::Load(SQLStorage &store) +{ + uint32 maxi; + Field *fields; + QueryResult *result = WorldDatabase.PQuery("SELECT MAX(%s) FROM %s", store.entry_field, store.table); + if(!result) + { + sLog.outError("Error loading %s table (not exist?)\n", store.table); + exit(1); // Stop server at loading non exited table or not accessable table + } + + maxi = (*result)[0].GetUInt32()+1; + delete result; + + result = WorldDatabase.PQuery("SELECT COUNT(*) FROM %s", store.table); + if(result) + { + fields = result->Fetch(); + store.RecordCount = fields[0].GetUInt32(); + delete result; + } + else + store.RecordCount = 0; + + result = WorldDatabase.PQuery("SELECT * FROM %s", store.table); + + if(!result) + { + sLog.outError("%s table is empty!\n", store.table); + store.RecordCount = 0; + return; + } + + uint32 recordsize = 0; + uint32 offset = 0; + + if(store.iNumFields != result->GetFieldCount()) + { + store.RecordCount = 0; + sLog.outError("Error in %s table, probably sql file format was updated (there should be %d fields in sql).\n", store.table, store.iNumFields); + delete result; + exit(1); // Stop server at loading broken or non-compatible table. + } + + //get struct size + uint32 sc=0; + uint32 bo=0; + uint32 bb=0; + for(uint32 x=0; x< store.iNumFields; x++) + if(store.dst_format[x]==FT_STRING) + ++sc; + else if (store.dst_format[x]==FT_LOGIC) + ++bo; + else if (store.dst_format[x]==FT_BYTE) + ++bb; + recordsize=(store.iNumFields-sc-bo-bb)*4+sc*sizeof(char*)+bo*sizeof(bool)+bb*sizeof(char); + + char** newIndex=new char*[maxi]; + memset(newIndex,0,maxi*sizeof(char*)); + + char * _data= new char[store.RecordCount *recordsize]; + uint32 count=0; + barGoLink bar( store.RecordCount ); + do + { + fields = result->Fetch(); + bar.step(); + char *p=(char*)&_data[recordsize*count]; + newIndex[fields[0].GetUInt32()]=p; + + offset=0; + for(uint32 x = 0; x < store.iNumFields; x++) + switch(store.src_format[x]) + { + case FT_LOGIC: + storeValue((bool)(fields[x].GetUInt32() > 0), store, p, x, offset); break; + case FT_BYTE: + storeValue((char)fields[x].GetUInt8(), store, p, x, offset); break; + case FT_INT: + storeValue((uint32)fields[x].GetUInt32(), store, p, x, offset); break; + case FT_FLOAT: + storeValue((float)fields[x].GetFloat(), store, p, x, offset); break; + case FT_STRING: + storeValue((char*)fields[x].GetString(), store, p, x, offset); break; + } + ++count; + }while( result->NextRow() ); + + delete result; + + store.pIndex = newIndex; + store.MaxEntry = maxi; + store.data = _data; +} diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 6c2212faa..b7d979b8c 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6826" + #define REVISION_NR "6827" #endif // __REVISION_NR_H__ diff --git a/win/VC71/shared.vcproj b/win/VC71/shared.vcproj index 5321788cb..deefd9881 100644 --- a/win/VC71/shared.vcproj +++ b/win/VC71/shared.vcproj @@ -192,6 +192,9 @@ + + + + diff --git a/win/VC90/shared.vcproj b/win/VC90/shared.vcproj index f6ad561c0..3254e559c 100644 --- a/win/VC90/shared.vcproj +++ b/win/VC90/shared.vcproj @@ -436,6 +436,10 @@ RelativePath="..\..\src\shared\Database\SQLStorage.h" > + + From 766654c85d9415ccff3338fe9c00aff854d2dc23 Mon Sep 17 00:00:00 2001 From: Wyk3d Date: Sun, 16 Nov 2008 03:18:26 +0200 Subject: [PATCH 2/6] [6828] Added script name indexing for creature, gameobject, item, areatrigger and instance scripts. * loaded all distinct script names into one vector at server startup * added custom loaders to convert the script names to indices * converted all the script lookup functions to use the index instead of the name --- src/bindings/universal/ScriptMgr.cpp | 68 ++++------- src/bindings/universal/ScriptMgr.h | 18 +-- src/bindings/universal/Scripts/sc_default.cpp | 2 +- src/game/Creature.cpp | 9 +- src/game/Creature.h | 6 +- src/game/GameObject.h | 2 +- src/game/ItemPrototype.h | 2 +- src/game/Map.cpp | 6 +- src/game/Map.h | 6 +- src/game/ObjectMgr.cpp | 114 +++++++++++++++--- src/game/ObjectMgr.h | 21 +++- src/game/ScriptCalls.cpp | 2 +- src/game/ScriptCalls.h | 2 +- src/game/World.cpp | 3 + src/shared/Database/SQLStorage.cpp | 22 ++-- src/shared/revision_nr.h | 2 +- 16 files changed, 184 insertions(+), 101 deletions(-) diff --git a/src/bindings/universal/ScriptMgr.cpp b/src/bindings/universal/ScriptMgr.cpp index 3e2a557db..e2e7349cb 100644 --- a/src/bindings/universal/ScriptMgr.cpp +++ b/src/bindings/universal/ScriptMgr.cpp @@ -27,8 +27,6 @@ //uint8 loglevel = 0; int nrscripts; Script *m_scripts[MAX_SCRIPTS]; -InstanceDataScript* m_instance_scripts[MAX_INSTANCE_SCRIPTS]; -int num_inst_scripts; // -- Scripts to be added -- extern void AddSC_default(); @@ -40,22 +38,16 @@ void ScriptsFree() for(int i=0;iName == Name ) - return m_scripts[i]; - } - return NULL; + int id = GetScriptId(Name.c_str()); + if(id != 0) m_scripts[id] = this; } MANGOS_DLL_EXPORT bool GossipHello ( Player * player, Creature *_Creature ) { - Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + Script *tmpscript = m_scripts[_Creature->GetScriptId()]; if(!tmpscript || !tmpscript->pGossipHello) return false; player->PlayerTalkClass->ClearMenus(); @@ -97,7 +83,7 @@ bool GossipSelect( Player *player, Creature *_Creature,uint32 sender, uint32 act { debug_log("DEBUG: Gossip selection, sender: %d, action: %d",sender, action); - Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + Script *tmpscript = m_scripts[_Creature->GetScriptId()]; if(!tmpscript || !tmpscript->pGossipSelect) return false; player->PlayerTalkClass->ClearMenus(); @@ -109,7 +95,7 @@ bool GossipSelectWithCode( Player *player, Creature *_Creature, uint32 sender, u { debug_log("DEBUG: Gossip selection, sender: %d, action: %d",sender, action); - Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + Script *tmpscript = m_scripts[_Creature->GetScriptId()]; if(!tmpscript || !tmpscript->pGossipSelectWithCode) return false; player->PlayerTalkClass->ClearMenus(); @@ -119,7 +105,7 @@ bool GossipSelectWithCode( Player *player, Creature *_Creature, uint32 sender, u MANGOS_DLL_EXPORT bool QuestAccept( Player *player, Creature *_Creature, Quest *_Quest ) { - Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + Script *tmpscript = m_scripts[_Creature->GetScriptId()]; if(!tmpscript || !tmpscript->pQuestAccept) return false; player->PlayerTalkClass->ClearMenus(); @@ -129,7 +115,7 @@ bool QuestAccept( Player *player, Creature *_Creature, Quest *_Quest ) MANGOS_DLL_EXPORT bool QuestSelect( Player *player, Creature *_Creature, Quest *_Quest ) { - Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + Script *tmpscript = m_scripts[_Creature->GetScriptId()]; if(!tmpscript || !tmpscript->pQuestSelect) return false; player->PlayerTalkClass->ClearMenus(); @@ -139,7 +125,7 @@ bool QuestSelect( Player *player, Creature *_Creature, Quest *_Quest ) MANGOS_DLL_EXPORT bool QuestComplete( Player *player, Creature *_Creature, Quest *_Quest ) { - Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + Script *tmpscript = m_scripts[_Creature->GetScriptId()]; if(!tmpscript || !tmpscript->pQuestComplete) return false; player->PlayerTalkClass->ClearMenus(); @@ -149,7 +135,7 @@ bool QuestComplete( Player *player, Creature *_Creature, Quest *_Quest ) MANGOS_DLL_EXPORT bool ChooseReward( Player *player, Creature *_Creature, Quest *_Quest, uint32 opt ) { - Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + Script *tmpscript = m_scripts[_Creature->GetScriptId()]; if(!tmpscript || !tmpscript->pChooseReward) return false; player->PlayerTalkClass->ClearMenus(); @@ -159,7 +145,7 @@ bool ChooseReward( Player *player, Creature *_Creature, Quest *_Quest, uint32 op MANGOS_DLL_EXPORT uint32 NPCDialogStatus( Player *player, Creature *_Creature ) { - Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + Script *tmpscript = m_scripts[_Creature->GetScriptId()]; if(!tmpscript || !tmpscript->pNPCDialogStatus) return 100; player->PlayerTalkClass->ClearMenus(); @@ -171,7 +157,7 @@ uint32 GODialogStatus( Player *player, GameObject *_GO ) { Script *tmpscript = NULL; - tmpscript = GetScriptByName(_GO->GetGOInfo()->ScriptName); + tmpscript = m_scripts[_GO->GetGOInfo()->ScriptId]; if(!tmpscript || !tmpscript->pGODialogStatus) return 100; player->PlayerTalkClass->ClearMenus(); @@ -183,7 +169,7 @@ bool ItemHello( Player *player, Item *_Item, Quest *_Quest ) { Script *tmpscript = NULL; - tmpscript = GetScriptByName(_Item->GetProto()->ScriptName); + tmpscript = m_scripts[_Item->GetProto()->ScriptId]; if(!tmpscript || !tmpscript->pItemHello) return false; player->PlayerTalkClass->ClearMenus(); @@ -195,7 +181,7 @@ bool ItemQuestAccept( Player *player, Item *_Item, Quest *_Quest ) { Script *tmpscript = NULL; - tmpscript = GetScriptByName(_Item->GetProto()->ScriptName); + tmpscript = m_scripts[_Item->GetProto()->ScriptId]; if(!tmpscript || !tmpscript->pItemQuestAccept) return false; player->PlayerTalkClass->ClearMenus(); @@ -207,7 +193,7 @@ bool GOHello( Player *player, GameObject *_GO ) { Script *tmpscript = NULL; - tmpscript = GetScriptByName(_GO->GetGOInfo()->ScriptName); + tmpscript = m_scripts[_GO->GetGOInfo()->ScriptId]; if(!tmpscript || !tmpscript->pGOHello) return false; player->PlayerTalkClass->ClearMenus(); @@ -219,7 +205,7 @@ bool GOQuestAccept( Player *player, GameObject *_GO, Quest *_Quest ) { Script *tmpscript = NULL; - tmpscript = GetScriptByName(_GO->GetGOInfo()->ScriptName); + tmpscript = m_scripts[_GO->GetGOInfo()->ScriptId]; if(!tmpscript || !tmpscript->pGOQuestAccept) return false; player->PlayerTalkClass->ClearMenus(); @@ -231,7 +217,7 @@ bool GOChooseReward( Player *player, GameObject *_GO, Quest *_Quest, uint32 opt { Script *tmpscript = NULL; - tmpscript = GetScriptByName(_GO->GetGOInfo()->ScriptName); + tmpscript = m_scripts[_GO->GetGOInfo()->ScriptId]; if(!tmpscript || !tmpscript->pGOChooseReward) return false; player->PlayerTalkClass->ClearMenus(); @@ -243,7 +229,7 @@ bool AreaTrigger ( Player *player, AreaTriggerEntry* atEntry ) { Script *tmpscript = NULL; - tmpscript = GetScriptByName(GetAreaTriggerScriptNameById(atEntry->id)); + tmpscript = m_scripts[GetAreaTriggerScriptId(atEntry->id)]; if(!tmpscript || !tmpscript->pAreaTrigger) return false; return tmpscript->pAreaTrigger(player, atEntry); @@ -252,7 +238,7 @@ bool AreaTrigger ( Player *player, AreaTriggerEntry* atEntry ) MANGOS_DLL_EXPORT bool ReceiveEmote ( Player *player, Creature *_Creature, uint32 emote ) { - Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + Script *tmpscript = m_scripts[_Creature->GetScriptId()]; if(!tmpscript || !tmpscript->pReceiveEmote) return false; return tmpscript->pReceiveEmote(player,_Creature, emote); @@ -263,7 +249,7 @@ bool ItemUse( Player *player, Item* _Item, SpellCastTargets const& targets) { Script *tmpscript = NULL; - tmpscript = GetScriptByName(_Item->GetProto()->ScriptName); + tmpscript = m_scripts[_Item->GetProto()->ScriptId]; if(!tmpscript || !tmpscript->pItemUse) return false; return tmpscript->pItemUse(player,_Item,targets); @@ -272,7 +258,7 @@ bool ItemUse( Player *player, Item* _Item, SpellCastTargets const& targets) MANGOS_DLL_EXPORT CreatureAI* GetAI(Creature *_Creature ) { - Script *tmpscript = GetScriptByName(_Creature->GetScriptName()); + Script *tmpscript = m_scripts[_Creature->GetScriptId()]; if(!tmpscript || !tmpscript->GetAI) return NULL; return tmpscript->GetAI(_Creature); @@ -282,12 +268,10 @@ MANGOS_DLL_EXPORT InstanceData* CreateInstanceData(Map *map) { if(!map->IsDungeon()) return NULL; - std::string name = ((InstanceMap*)map)->GetScript(); - if(!name.empty()) - for(int i=0;iname == name) - return m_instance_scripts[i]->GetInstanceData(map); - return NULL; + Script *tmpscript = m_scripts[((InstanceMap*)map)->GetScriptId()]; + if(!tmpscript || !tmpscript->GetInstanceData) return NULL; + + return tmpscript->GetInstanceData(map); } void ScriptedAI::UpdateAI(const uint32) diff --git a/src/bindings/universal/ScriptMgr.h b/src/bindings/universal/ScriptMgr.h index f374f1db9..0b4605b5e 100644 --- a/src/bindings/universal/ScriptMgr.h +++ b/src/bindings/universal/ScriptMgr.h @@ -66,24 +66,12 @@ struct Script bool (*pItemUse )(Player *player, Item* _Item, SpellCastTargets const& targets); CreatureAI* (*GetAI)(Creature *_Creature); + InstanceData* (*GetInstanceData)(Map*); // ----------------------------------------- - + + void registerSelf(); }; -class InstanceDataScript -{ - public: - InstanceDataScript() : GetInstanceData(NULL) {}; - - std::string name; - InstanceData* (*GetInstanceData)(Map *_Map); -}; - -extern int nrscripts; -extern Script *m_scripts[MAX_SCRIPTS]; -extern InstanceDataScript *m_instance_scripts[MAX_INSTANCE_SCRIPTS]; -extern int num_inst_scripts; - #define VISIBLE_RANGE (50.0f) struct MANGOS_DLL_DECL ScriptedAI : public CreatureAI diff --git a/src/bindings/universal/Scripts/sc_default.cpp b/src/bindings/universal/Scripts/sc_default.cpp index c84eb2463..d4a98feaa 100644 --- a/src/bindings/universal/Scripts/sc_default.cpp +++ b/src/bindings/universal/Scripts/sc_default.cpp @@ -115,5 +115,5 @@ void AddSC_default() newscript->pGOQuestAccept = &GOQuestAccept_default; newscript->pGOChooseReward = &GOChooseReward_default; - m_scripts[nrscripts++] = newscript; + newscript->registerSelf(); } diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index db576c362..256f7bb1d 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -1942,9 +1942,14 @@ uint32 Creature::getLevelForTarget( Unit const* target ) const return level; } -char const* Creature::GetScriptName() const +std::string Creature::GetScriptName() { - return ObjectMgr::GetCreatureTemplate(GetEntry())->ScriptName; + return objmgr.GetScriptName(GetScriptId()); +} + +uint32 Creature::GetScriptId() +{ + return ObjectMgr::GetCreatureTemplate(GetEntry())->ScriptID; } VendorItemData const* Creature::GetVendorItems() const diff --git a/src/game/Creature.h b/src/game/Creature.h index 941f4cf3d..997faf652 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -201,7 +201,7 @@ struct CreatureInfo uint32 equipmentId; uint32 MechanicImmuneMask; uint32 flags_extra; - char const* ScriptName; + uint32 ScriptID; // helpers SkillType GetRequiredLootSkill() const @@ -490,7 +490,9 @@ class MANGOS_DLL_SPEC Creature : public Unit CreatureInfo const *GetCreatureInfo() const { return m_creatureInfo; } CreatureDataAddon const* GetCreatureAddon() const; - char const* GetScriptName() const; + + std::string GetScriptName(); + uint32 GetScriptId(); void prepareGossipMenu( Player *pPlayer, uint32 gossipid = 0 ); void sendPreparedGossip( Player* player ); diff --git a/src/game/GameObject.h b/src/game/GameObject.h index b029bf4ce..0961a9cfc 100644 --- a/src/game/GameObject.h +++ b/src/game/GameObject.h @@ -355,7 +355,7 @@ struct GameObjectInfo uint32 data[24]; } raw; }; - char *ScriptName; + uint32 ScriptId; }; struct GameObjectLocale diff --git a/src/game/ItemPrototype.h b/src/game/ItemPrototype.h index 6898281a5..ba6f50f48 100644 --- a/src/game/ItemPrototype.h +++ b/src/game/ItemPrototype.h @@ -538,7 +538,7 @@ struct ItemPrototype uint32 GemProperties; // id from GemProperties.dbc uint32 RequiredDisenchantSkill; float ArmorDamageModifier; - char* ScriptName; + uint32 ScriptId; uint32 DisenchantID; uint32 FoodType; uint32 MinMoneyLoot; diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 68a4ddf74..972a08916 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -1626,7 +1626,7 @@ void InstanceMap::CreateInstanceData(bool load) InstanceTemplate const* mInstance = objmgr.GetInstanceTemplate(GetId()); if (mInstance) { - i_script = mInstance->script; + i_script_id = mInstance->script_id; i_data = Script->CreateInstanceData(this); } @@ -1643,7 +1643,7 @@ void InstanceMap::CreateInstanceData(bool load) const char* data = fields[0].GetString(); if(data) { - sLog.outDebug("Loading instance data for `%s` with id %u", i_script.c_str(), i_InstanceId); + sLog.outDebug("Loading instance data for `%s` with id %u", objmgr.GetScriptName(i_script_id), i_InstanceId); i_data->Load(data); } delete result; @@ -1651,7 +1651,7 @@ void InstanceMap::CreateInstanceData(bool load) } else { - sLog.outDebug("New instance data, \"%s\" ,initialized!",i_script.c_str()); + sLog.outDebug("New instance data, \"%s\" ,initialized!", objmgr.GetScriptName(i_script_id)); i_data->Initialize(); } } diff --git a/src/game/Map.h b/src/game/Map.h index df4b8d004..cf67a566d 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -102,7 +102,7 @@ struct InstanceTemplate float startLocY; float startLocZ; float startLocO; - char const* script; + uint32 script_id; }; enum LevelRequirementVsMode @@ -329,7 +329,7 @@ class MANGOS_DLL_SPEC InstanceMap : public Map void Update(const uint32&); void CreateInstanceData(bool load); bool Reset(uint8 method); - std::string GetScript() { return i_script; } + uint32 GetScriptId() { return i_script_id; } InstanceData* GetInstanceData() { return i_data; } void PermBindAllPlayers(Player *player); PlayerList const& GetPlayers() const { return i_Players;} @@ -345,7 +345,7 @@ class MANGOS_DLL_SPEC InstanceMap : public Map bool m_resetAfterUnload; bool m_unloadWhenEmpty; InstanceData* i_data; - std::string i_script; + uint32 i_script_id; // only online players that are inside the instance currently // TODO ? - use the grid instead to access the players PlayerList i_Players; diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index f49f0a136..a2c865922 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -19,6 +19,7 @@ #include "Common.h" #include "Database/DatabaseEnv.h" #include "Database/SQLStorage.h" +#include "Database/SQLStorageImpl.h" #include "Log.h" #include "MapManager.h" @@ -562,7 +563,7 @@ void ObjectMgr::LoadCreatureLocales() sLog.outString(); sLog.outString( ">> Loaded %u creature locale strings", mCreatureLocaleMap.size() ); } - + void ObjectMgr::LoadNpcOptionLocales() { mNpcOptionLocaleMap.clear(); // need for reload case @@ -631,9 +632,19 @@ void ObjectMgr::LoadNpcOptionLocales() sLog.outString( ">> Loaded %u npc_option locale strings", mNpcOptionLocaleMap.size() ); } +struct SQLCreatureLoader : public SQLStorageLoaderBase +{ + template + void convert_from_str(uint32 field_pos, char *src, D &dst) + { + dst = D(objmgr.GetScriptId(src)); + } +}; + void ObjectMgr::LoadCreatureTemplates() { - sCreatureStorage.Load(); + SQLCreatureLoader loader; + loader.Load(sCreatureStorage); sLog.outString( ">> Loaded %u creature definitions", sCreatureStorage.RecordCount ); sLog.outString(); @@ -1500,9 +1511,19 @@ void ObjectMgr::LoadItemLocales() sLog.outString( ">> Loaded %u Item locale strings", mItemLocaleMap.size() ); } +struct SQLItemLoader : public SQLStorageLoaderBase +{ + template + void convert_from_str(uint32 field_pos, char *src, D &dst) + { + dst = D(objmgr.GetScriptId(src)); + } +}; + void ObjectMgr::LoadItemPrototypes() { - sItemStorage.Load (); + SQLItemLoader loader; + loader.Load(sItemStorage); sLog.outString( ">> Loaded %u item prototypes", sItemStorage.RecordCount ); sLog.outString(); @@ -4120,9 +4141,19 @@ void ObjectMgr::LoadPageTextLocales() sLog.outString( ">> Loaded %u PageText locale strings", mPageTextLocaleMap.size() ); } +struct SQLInstanceLoader : public SQLStorageLoaderBase +{ + template + void convert_from_str(uint32 field_pos, char *src, D &dst) + { + dst = D(objmgr.GetScriptId(src)); + } +}; + void ObjectMgr::LoadInstanceTemplate() { - sInstanceTemplate.Load(); + SQLInstanceLoader loader; + loader.Load(sInstanceTemplate); for(uint32 i = 0; i < sInstanceTemplate.MaxEntry; i++) { @@ -4536,7 +4567,7 @@ void ObjectMgr::LoadAreaTriggerScripts() Field *fields = result->Fetch(); uint32 Trigger_ID = fields[0].GetUInt32(); - std::string scriptName = fields[1].GetCppString(); + const char *scriptName = fields[1].GetString(); AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(Trigger_ID); if(!atEntry) @@ -4544,7 +4575,7 @@ void ObjectMgr::LoadAreaTriggerScripts() sLog.outErrorDb("Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`.",Trigger_ID); continue; } - mAreaTriggerScripts[Trigger_ID] = scriptName; + mAreaTriggerScripts[Trigger_ID] = GetScriptId(scriptName); } while( result->NextRow() ); delete result; @@ -5350,9 +5381,19 @@ void ObjectMgr::LoadGameObjectLocales() sLog.outString( ">> Loaded %u gameobject locale strings", mGameObjectLocaleMap.size() ); } +struct SQLGameObjectLoader : public SQLStorageLoaderBase +{ + template + void convert_from_str(uint32 field_pos, char *src, D &dst) + { + dst = D(objmgr.GetScriptId(src)); + } +}; + void ObjectMgr::LoadGameobjectInfo() { - sGOStorage.Load(); + SQLGameObjectLoader loader; + loader.Load(sGOStorage); // some checks for(uint32 id = 1; id < sGOStorage.MaxEntry; id++) @@ -6480,12 +6521,12 @@ bool ObjectMgr::CheckDeclinedNames( std::wstring mainpart, DeclinedName const& n return true; } -const char* ObjectMgr::GetAreaTriggerScriptName(uint32 id) +uint32 ObjectMgr::GetAreaTriggerScriptId(uint32 trigger_id) { - AreaTriggerScriptMap::const_iterator i = mAreaTriggerScripts.find(id); + AreaTriggerScriptMap::const_iterator i = mAreaTriggerScripts.find(trigger_id); if(i!= mAreaTriggerScripts.end()) - return i->second.c_str(); - return ""; + return i->second; + return 0; } // Checks if player meets the condition @@ -7196,6 +7237,42 @@ bool ObjectMgr::IsVendorItemValid( uint32 vendor_entry, uint32 item_id, uint32 m return true; } +void ObjectMgr::LoadScriptNames() +{ + m_scriptNames.push_back(""); + QueryResult *result = WorldDatabase.Query( + "SELECT DISTINCT(ScriptName) FROM creature_template WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM gameobject_template WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM item_template WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM areatrigger_scripts WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(script) FROM instance_template WHERE script <> ''"); + if(result) + { + do + { + m_scriptNames.push_back((*result)[0].GetString()); + } while (result->NextRow()); + delete result; + } + + std::sort(m_scriptNames.begin(), m_scriptNames.end()); +} + +uint32 ObjectMgr::GetScriptId(const char *name) +{ + // use binary search to find the script name in the sorted vector + // assume "" is the first element + if(!name) return 0; + ScriptNameMap::const_iterator itr = + std::lower_bound(m_scriptNames.begin(), m_scriptNames.end(), name); + if(itr == m_scriptNames.end()) return 0; + return itr - m_scriptNames.begin(); +} + void ObjectMgr::CheckScripts(ScriptMapMap const& scripts,std::set& ids) { for(ScriptMapMap::const_iterator itrMM = scripts.begin(); itrMM != scripts.end(); ++itrMM) @@ -7234,11 +7311,10 @@ void ObjectMgr::LoadDbScriptStrings() sLog.outErrorDb( "Table `db_script_string` has unused string id %u", *itr); } - // Functions for scripting access -const char* GetAreaTriggerScriptNameById(uint32 id) +uint32 GetAreaTriggerScriptId(uint32 trigger_id) { - return objmgr.GetAreaTriggerScriptName(id); + return objmgr.GetAreaTriggerScriptId(trigger_id); } bool LoadMangosStrings(DatabaseType& db, char const* table,int32 start_value, int32 end_value) @@ -7253,3 +7329,13 @@ bool LoadMangosStrings(DatabaseType& db, char const* table,int32 start_value, in // for scripting localized strings allowed use _only_ negative entries return objmgr.LoadMangosStrings(db,table,end_value,start_value); } + +uint32 MANGOS_DLL_SPEC GetScriptId(const char *name) +{ + return objmgr.GetScriptId(name); +} + +ObjectMgr::ScriptNameMap & GetScriptNames() +{ + return objmgr.GetScriptNames(); +} diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index 4c5a1c4bd..38cf68dc9 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -286,9 +286,10 @@ class ObjectMgr typedef UNORDERED_MAP QuestMap; + typedef UNORDERED_MAP AreaTriggerMap; - typedef UNORDERED_MAP AreaTriggerScriptMap; + typedef UNORDERED_MAP AreaTriggerScriptMap; typedef UNORDERED_MAP RepOnKillMap; @@ -296,6 +297,8 @@ class ObjectMgr typedef UNORDERED_MAP PetCreateSpellMap; + typedef std::vector ScriptNameMap; + Player* GetPlayer(const char* name) const { return ObjectAccessor::Instance().FindPlayerByName(name);} Player* GetPlayer(uint64 guid) const { return ObjectAccessor::FindPlayer(guid); } @@ -460,7 +463,7 @@ class ObjectMgr AreaTrigger const* GetGoBackTrigger(uint32 Map) const; - const char* GetAreaTriggerScriptName(uint32 id); + uint32 GetAreaTriggerScriptId(uint32 trigger_id); ReputationOnKillEntry const* GetReputationOnKilEntry(uint32 id) const { @@ -764,6 +767,10 @@ class ObjectMgr bool RemoveVendorItem(uint32 entry,uint32 item); bool IsVendorItemValid( uint32 vendor_entry, uint32 item, uint32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* pl = NULL, std::set* skip_vendors = NULL ) const; + void LoadScriptNames(); + ScriptNameMap &GetScriptNames() { return m_scriptNames; } + const char * GetScriptName(uint32 id) { return id < m_scriptNames.size() ? m_scriptNames[id].c_str() : ""; } + uint32 GetScriptId(const char *name); protected: uint32 m_auctionid; uint32 m_mailid; @@ -781,7 +788,7 @@ class ObjectMgr uint32 m_hiPetNumber; - QuestMap mQuestTemplates; + QuestMap mQuestTemplates; typedef UNORDERED_MAP GossipTextMap; typedef UNORDERED_MAP QuestAreaTriggerMap; @@ -825,6 +832,8 @@ class ObjectMgr GameTeleMap m_GameTeleMap; + ScriptNameMap m_scriptNames; + typedef std::vector LocalForIndex; LocalForIndex m_LocalForIndex; int GetOrNewIndexForLocale(LocaleConstant loc); @@ -885,7 +894,9 @@ class ObjectMgr #define objmgr MaNGOS::Singleton::Instance() // scripting access functions -bool MANGOS_DLL_SPEC LoadMangosStrings(DatabaseType& db, char const* table,int32 start_value = -1, int32 end_value = std::numeric_limits::min()); -MANGOS_DLL_SPEC const char* GetAreaTriggerScriptNameById(uint32 id); +MANGOS_DLL_SPEC bool LoadMangosStrings(DatabaseType& db, char const* table,int32 start_value = -1, int32 end_value = std::numeric_limits::min()); +MANGOS_DLL_SPEC uint32 GetAreaTriggerScriptId(uint32 trigger_id); +MANGOS_DLL_SPEC uint32 GetScriptId(const char *name); +MANGOS_DLL_SPEC ObjectMgr::ScriptNameMap& GetScriptNames(); #endif diff --git a/src/game/ScriptCalls.cpp b/src/game/ScriptCalls.cpp index 00435fa8f..d258ea199 100644 --- a/src/game/ScriptCalls.cpp +++ b/src/game/ScriptCalls.cpp @@ -91,7 +91,7 @@ bool LoadScriptingModule(char const* libName) UnloadScriptingModule(); Script=testScript; - Script->ScriptsInit(); + Script->ScriptsInit(objmgr.GetScriptNames()); sWorld.SetScriptsVersion(Script->ScriptsVersion()); diff --git a/src/game/ScriptCalls.h b/src/game/ScriptCalls.h index bab186187..d2aafd507 100644 --- a/src/game/ScriptCalls.h +++ b/src/game/ScriptCalls.h @@ -35,7 +35,7 @@ class InstanceData; bool LoadScriptingModule(char const* libName = ""); void UnloadScriptingModule(); -typedef void(MANGOS_IMPORT * scriptCallScriptsInit) (); +typedef void(MANGOS_IMPORT * scriptCallScriptsInit) (const ObjectMgr::ScriptNameMap &scriptNames); typedef void(MANGOS_IMPORT * scriptCallScriptsFree) (); typedef char const* (MANGOS_IMPORT * scriptCallScriptsVersion) (); diff --git a/src/game/World.cpp b/src/game/World.cpp index 182a2a6df..171e0d189 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -927,6 +927,9 @@ void World::SetInitialWorldSettings() LoadDBCStores(m_dataPath); DetectDBCLang(); + sLog.outString( "Loading Script Names..."); + objmgr.LoadScriptNames(); + sLog.outString( "Loading InstanceTemplate" ); objmgr.LoadInstanceTemplate(); diff --git a/src/shared/Database/SQLStorage.cpp b/src/shared/Database/SQLStorage.cpp index b504a178d..1a4a823e5 100644 --- a/src/shared/Database/SQLStorage.cpp +++ b/src/shared/Database/SQLStorage.cpp @@ -25,27 +25,31 @@ extern DatabasePostgre WorldDatabase; extern DatabaseMysql WorldDatabase; #endif -const char CreatureInfofmt[]="iiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiilliiis"; +const char CreatureInfosrcfmt[]="iiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiilliiis"; +const char CreatureInfodstfmt[]="iiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiilliiii"; const char CreatureDataAddonInfofmt[]="iiiiiiis"; const char CreatureModelfmt[]="iffbi"; const char CreatureInfoAddonInfofmt[]="iiiiiiis"; const char EquipmentInfofmt[]="iiiiiiiiii"; -const char GameObjectInfofmt[]="iiissiifiiiiiiiiiiiiiiiiiiiiiiiis"; -const char ItemPrototypefmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiffiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifsiiiii"; +const char GameObjectInfosrcfmt[]="iiissiifiiiiiiiiiiiiiiiiiiiiiiiis"; +const char GameObjectInfodstfmt[]="iiissiifiiiiiiiiiiiiiiiiiiiiiiiii"; +const char ItemPrototypesrcfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiffiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifsiiiii"; +const char ItemPrototypedstfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiffiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiiiiii"; const char PageTextfmt[]="isi"; const char SpellThreatfmt[]="ii"; -const char InstanceTemplatefmt[]="iiiiiiffffs"; +const char InstanceTemplatesrcfmt[]="iiiiiiffffs"; +const char InstanceTemplatedstfmt[]="iiiiiiffffi"; -SQLStorage sCreatureStorage(CreatureInfofmt,"entry","creature_template"); +SQLStorage sCreatureStorage(CreatureInfosrcfmt, CreatureInfodstfmt, "entry","creature_template"); SQLStorage sCreatureDataAddonStorage(CreatureDataAddonInfofmt,"guid","creature_addon"); SQLStorage sCreatureModelStorage(CreatureModelfmt,"modelid","creature_model_info"); SQLStorage sCreatureInfoAddonStorage(CreatureInfoAddonInfofmt,"entry","creature_template_addon"); SQLStorage sEquipmentStorage(EquipmentInfofmt,"entry","creature_equip_template"); -SQLStorage sGOStorage(GameObjectInfofmt,"entry","gameobject_template"); -SQLStorage sItemStorage(ItemPrototypefmt,"entry","item_template"); +SQLStorage sGOStorage(GameObjectInfosrcfmt, GameObjectInfodstfmt, "entry","gameobject_template"); +SQLStorage sItemStorage(ItemPrototypesrcfmt, ItemPrototypedstfmt, "entry","item_template"); SQLStorage sPageTextStore(PageTextfmt,"entry","page_text"); SQLStorage sSpellThreatStore(SpellThreatfmt,"entry","spell_threat"); -SQLStorage sInstanceTemplate(InstanceTemplatefmt,"map","instance_template"); +SQLStorage sInstanceTemplate(InstanceTemplatesrcfmt, InstanceTemplatedstfmt, "map","instance_template"); void SQLStorage::Free () { @@ -74,4 +78,4 @@ void SQLStorage::Load() { SQLStorageLoader loader; loader.Load(*this); -} \ No newline at end of file +} diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index b7d979b8c..f527cfb63 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6827" + #define REVISION_NR "6828" #endif // __REVISION_NR_H__ From 3d72b06fcd96d6ef5617fd553ad6a0c6d7048377 Mon Sep 17 00:00:00 2001 From: Wyk3d Date: Sun, 16 Nov 2008 03:27:09 +0200 Subject: [PATCH 3/6] [6829] Fixed a crash in ScriptsProcess when the source or target's map is looked up while it's not in world. --- src/game/World.cpp | 4 ++++ src/shared/revision_nr.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/game/World.cpp b/src/game/World.cpp index 171e0d189..92bc56548 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1525,6 +1525,8 @@ void World::ScriptsProcess() } } + if(source && !source->IsInWorld()) source = NULL; + Object* target = NULL; if(step.targetGUID) @@ -1552,6 +1554,8 @@ void World::ScriptsProcess() } } + if(target && !target->IsInWorld()) target = NULL; + switch (step.script->command) { case SCRIPT_COMMAND_TALK: diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index f527cfb63..cfcb1eea6 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6828" + #define REVISION_NR "6829" #endif // __REVISION_NR_H__ From 528a9d830a8cee7d1c3f27aff595f560059754ab Mon Sep 17 00:00:00 2001 From: freghar Date: Wed, 12 Nov 2008 21:09:56 +0100 Subject: [PATCH 4/6] [6830] Implement custom exit codes on server shutdown/restart Added the possibility to use custom process return values instead of hardcoded 0 (shutdown) or 2 (restart) to allow using them for various custom external features / better handling. This can be used through 4 commands in ".server" family: - shutdown - restart - idleshutdown - idlerestart Those have from now on 2 arguments, where the second (return value) is optional: .server