diff --git a/sql/mangos.sql b/sql/mangos.sql index 6a603bc4e..dddc5c54f 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -22,7 +22,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, - `required_2008_11_14_01_mangos_scripts` bit(1) default NULL + `required_2008_11_16_01_mangos_command` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -408,15 +408,19 @@ INSERT INTO `command` VALUES ('sendmoney','3','Syntax: .sendmoney #playername "#subject" "#text" #money\r\n\r\nSend mail with money to a player. Subject and mail text must be in "".'), ('sendmessage',3,'Syntax: .sendmessage $playername $message\r\n\r\nSend screen message to player from ADMINISTRATOR.'), ('server corpses',2,'Syntax: .server corpses\r\n\r\nTriggering corpses expire check in world.'), -('server exit',4,'Syntax: .server exit\r\n\r\nTerminate mangosd NOW.'), +('server exit',4,'Syntax: .server exit\r\n\r\nTerminate mangosd NOW. Exit code 0.'), ('server info',0,'Syntax: .server info\r\n\r\nDisplay server version and the number of connected players.'), -('server idleshutdown',3,'Syntax: .server idleshutdown #delay|cancel\r\n\r\nShut the server down after #delay seconds if no active connections are present (no players) or cancel the restart/shutdown if cancel value is used.'), -('server idlerestart',3,'Syntax: .server idlerestart #delay|cancel\r\n\r\nRestart the server after #delay seconds if no active connections are present (no players) or cancel the restart/shutdown if cancel value is used.'), +('server idleshutdown',3,'Syntax: .server idleshutdown #delay [#exist_code]\r\n\r\nShut the server down after #delay seconds if no active connections are present (no players). Use #exist_code or 0 as program exist code.'), +('server idleshutdown cancel',3,'Syntax: .server idleshutdown cancel\r\n\r\nCancel the restart/shutdown timer if any.'), +('server idlerestart',3,'Syntax: .server idlerestart #delay\r\n\r\nRestart the server after #delay seconds if no active connections are present (no players). Use #exist_code or 2 as program exist code.'), +('server idlerestart cancel',3,'Syntax: .server idlerestart cancel\r\n\r\nCancel the restart/shutdown timer if any.'), ('server motd',0,'Syntax: .server motd\r\n\r\nShow server Message of the day.'), -('server restart',3,'Syntax: .server restart seconds\r\n\r\nRestart the server after given seconds and show "Restart server in X" or cancel the restart/shutdown if cancel value is used.'), +('server restart',3,'Syntax: .server restart #delay\r\n\r\nRestart the server after #delay seconds. Use #exist_code or 2 as program exist code.'), +('server restart cancel',3,'Syntax: .server restart cancel\r\n\r\nCancel the restart/shutdown timer if any.'), ('server set loglevel',4,'Syntax: .server set loglevel #level\r\n\r\nSet server log level (0 - errors only, 1 - basic, 2 - detail, 3 - debug).'), ('server set motd',3,'Syntax: .server set motd $MOTD\r\n\r\nSet server Message of the day.'), -('server shutdown',3,'Syntax: .server shutdown seconds\r\n\r\nShut the server down after given seconds and show "Off server in X" or cancel the restart/shutdown if cancel value is used.'), +('server shutdown',3,'Syntax: .server shutdown #delay [#exist_code]\r\n\r\nShut the server down after #delay seconds. Use #exist_code or 0 as program exist code.'), +('server shutdown cancel',3,'Syntax: .server shutdown cancel\r\n\r\nCancel the restart/shutdown timer if any.'), ('setskill',3,'Syntax: .setskill #skill #level [#max]\r\n\r\nSet a skill of id #skill with a current skill value of #level and a maximum value of #max (or equal current maximum if not provide) for the selected character. If no character is selected, you learn the skill.'), ('showarea',3,'Syntax: .showarea #areaid\r\n\r\nReveal the area of #areaid to the selected character. If no character is selected, reveal this area to you.'), ('start',0,'Syntax: .start\r\n\r\nTeleport you to the starting area of your character.'), diff --git a/sql/updates/2008_11_16_01_mangos_command.sql b/sql/updates/2008_11_16_01_mangos_command.sql new file mode 100644 index 000000000..bc8f75b65 --- /dev/null +++ b/sql/updates/2008_11_16_01_mangos_command.sql @@ -0,0 +1,24 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_11_14_01_mangos_scripts required_2008_11_16_01_mangos_command bit; + +DELETE FROM `command` WHERE `name` IN ( + 'server exit', + 'server idleshutdown', + 'server idleshutdown cancel', + 'server idlerestart', + 'server idlerestart cancel', + 'server restart', + 'server restart cancel', + 'server shutdown', + 'server shutdown cancel' +); + +INSERT INTO `command` (`name`, `security`, `help`) VALUES +('server exit',4,'Syntax: .server exit\r\n\r\nTerminate mangosd NOW. Exit code 0.'), +('server idleshutdown',3,'Syntax: .server idleshutdown #delay [#exist_code]\r\n\r\nShut the server down after #delay seconds if no active connections are present (no players). Use #exist_code or 0 as program exist code.'), +('server idleshutdown cancel',3,'Syntax: .server idleshutdown cancel\r\n\r\nCancel the restart/shutdown timer if any.'), +('server idlerestart',3,'Syntax: .server idlerestart #delay\r\n\r\nRestart the server after #delay seconds if no active connections are present (no players). Use #exist_code or 2 as program exist code.'), +('server idlerestart cancel',3,'Syntax: .server idlerestart cancel\r\n\r\nCancel the restart/shutdown timer if any.'), +('server restart',3,'Syntax: .server restart #delay\r\n\r\nRestart the server after #delay seconds. Use #exist_code or 2 as program exist code.'), +('server restart cancel',3,'Syntax: .server restart cancel\r\n\r\nCancel the restart/shutdown timer if any.'), +('server shutdown',3,'Syntax: .server shutdown #delay [#exist_code]\r\n\r\nShut the server down after #delay seconds. Use #exist_code or 0 as program exist code.'), +('server shutdown cancel',3,'Syntax: .server shutdown cancel\r\n\r\nCancel the restart/shutdown timer if any.'); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index b743c6d15..a919714a8 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -132,7 +132,9 @@ pkgdata_DATA = \ 2008_11_09_03_mangos_mangos_string.sql \ 2008_11_11_01_mangos_db_script_string.sql \ 2008_11_11_02_mangos_scripts.sql \ + 2008_11_12_01_character_character_aura.sql \ 2008_11_14_01_mangos_scripts.sql \ + 2008_11_16_01_mangos_command.sql README ## Additional files to include when running 'make dist' @@ -248,4 +250,5 @@ EXTRA_DIST = \ 2008_11_11_02_mangos_scripts.sql \ 2008_11_12_01_character_character_aura.sql \ 2008_11_14_01_mangos_scripts.sql \ + 2008_11_16_01_mangos_command.sql README 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/Chat.cpp b/src/game/Chat.cpp index ab51c3987..10baaeae3 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -61,16 +61,44 @@ ChatCommand * ChatHandler::getCommandTable() { NULL, 0, false, NULL, "", NULL } }; + static ChatCommand serverIdleRestartCommandTable[] = + { + { "cancel", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerShutDownCancelCommand,"", NULL }, + { "" , SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerIdleRestartCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand serverIdleShutdownCommandTable[] = + { + { "cancel", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerShutDownCancelCommand,"", NULL }, + { "" , SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerIdleShutDownCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand serverRestartCommandTable[] = + { + { "cancel", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerShutDownCancelCommand,"", NULL }, + { "" , SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerRestartCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand serverShutdownCommandTable[] = + { + { "cancel", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerShutDownCancelCommand,"", NULL }, + { "" , SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerShutDownCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + static ChatCommand serverCommandTable[] = { { "corpses", SEC_GAMEMASTER, true, &ChatHandler::HandleServerCorpsesCommand, "", NULL }, { "exit", SEC_CONSOLE, true, &ChatHandler::HandleServerExitCommand, "", NULL }, - { "idlerestart", SEC_ADMINISTRATOR, true, &ChatHandler::HandleIdleRestartCommand, "", NULL }, - { "idleshutdown", SEC_ADMINISTRATOR, true, &ChatHandler::HandleIdleShutDownCommand, "", NULL }, + { "idlerestart", SEC_ADMINISTRATOR, true, NULL, "", serverIdleRestartCommandTable }, + { "idleshutdown", SEC_ADMINISTRATOR, true, NULL, "", serverShutdownCommandTable }, { "info", SEC_PLAYER, true, &ChatHandler::HandleServerInfoCommand, "", NULL }, { "motd", SEC_PLAYER, true, &ChatHandler::HandleServerMotdCommand, "", NULL }, - { "restart", SEC_ADMINISTRATOR, true, &ChatHandler::HandleRestartCommand, "", NULL }, - { "shutdown", SEC_ADMINISTRATOR, true, &ChatHandler::HandleShutDownCommand, "", NULL }, + { "restart", SEC_ADMINISTRATOR, true, NULL, "", serverRestartCommandTable }, + { "shutdown", SEC_ADMINISTRATOR, true, NULL, "", serverShutdownCommandTable }, { "set", SEC_ADMINISTRATOR, true, NULL, "", serverSetCommandTable }, { NULL, 0, false, NULL, "", NULL } }; diff --git a/src/game/Chat.h b/src/game/Chat.h index dd0dbe956..3d4f174f4 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -269,10 +269,15 @@ class ChatHandler bool HandleServerCorpsesCommand(const char* args); bool HandleServerExitCommand(const char* args); + bool HandleServerIdleRestartCommand(const char* args); + bool HandleServerIdleShutDownCommand(const char* args); bool HandleServerInfoCommand(const char* args); bool HandleServerMotdCommand(const char* args); + bool HandleServerRestartCommand(const char* args); bool HandleServerSetMotdCommand(const char* args); bool HandleServerSetLogLevelCommand(const char* args); + bool HandleServerShutDownCommand(const char* args); + bool HandleServerShutDownCancelCommand(const char* args); bool HandleAddHonorCommand(const char* args); bool HandleHonorAddKillCommand(const char* args); @@ -322,10 +327,6 @@ class ChatHandler bool HandleBanListAccountCommand(const char* args); bool HandleBanListCharacterCommand(const char* args); bool HandleBanListIPCommand(const char* args); - bool HandleIdleRestartCommand(const char* args); - bool HandleIdleShutDownCommand(const char* args); - bool HandleShutDownCommand(const char* args); - bool HandleRestartCommand(const char* args); bool HandleGoXYCommand(const char* args); bool HandleGoXYZCommand(const char* args); bool HandleGoZoneXYCommand(const char* args); diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index d03b1d416..9a3f9bed0 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -1937,9 +1937,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 a95a3998b..dbe3e9248 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 @@ -489,7 +489,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 7296b44d3..3865a23c8 100644 --- a/src/game/GameObject.h +++ b/src/game/GameObject.h @@ -362,7 +362,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 1994e64c7..5328308b4 100644 --- a/src/game/ItemPrototype.h +++ b/src/game/ItemPrototype.h @@ -553,7 +553,7 @@ struct ItemPrototype float ArmorDamageModifier; int32 Duration; // negative = realtime, positive = ingame time uint32 ItemLimitCategory; // id from ItemLimitCategory.dbc - char* ScriptName; + uint32 ScriptId; uint32 DisenchantID; uint32 FoodType; uint32 MinMoneyLoot; diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 23023b2cb..bf9cbbc9d 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -4574,91 +4574,149 @@ bool ChatHandler::HandleResetAllCommand(const char * args) return true; } -bool ChatHandler::HandleShutDownCommand(const char* args) +bool ChatHandler::HandleServerShutDownCancelCommand(const char* args) { - if(!*args) - return false; - - if(std::string(args)=="cancel") - { - sWorld.ShutdownCancel(); - } - else - { - int32 time = atoi(args); - - ///- Prevent interpret wrong arg value as 0 secs shutdown time - if(time == 0 && (args[0]!='0' || args[1]!='\0') || time < 0) - return false; - - sWorld.ShutdownServ(time); - } + sWorld.ShutdownCancel(); return true; } -bool ChatHandler::HandleRestartCommand(const char* args) +bool ChatHandler::HandleServerShutDownCommand(const char* args) { if(!*args) return false; - if(std::string(args)=="cancel") - { - sWorld.ShutdownCancel(); - } - else - { - int32 time = atoi(args); + char* time_str = strtok ((char*) args, " "); + char* exitcode_str = strtok (NULL, ""); - ///- Prevent interpret wrong arg value as 0 secs shutdown time - if(time == 0 && (args[0]!='0' || args[1]!='\0') || time < 0) + int32 time = atoi (time_str); + + ///- Prevent interpret wrong arg value as 0 secs shutdown time + if(time == 0 && (time_str[0]!='0' || time_str[1]!='\0') || time < 0) + return false; + + if (exitcode_str) + { + int32 exitcode = atoi (exitcode_str); + + // Handle atoi() errors + if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0')) return false; - sWorld.ShutdownServ(time, SHUTDOWN_MASK_RESTART); + // Exit code should be in range of 0-125, 126-255 is used + // in many shells for their own return codes and code > 255 + // is not supported in many others + if (exitcode < 0 || exitcode > 125) + return false; + + sWorld.ShutdownServ (time, 0, exitcode); } + else + sWorld.ShutdownServ(time,0,SHUTDOWN_EXIT_CODE); return true; } -bool ChatHandler::HandleIdleRestartCommand(const char* args) +bool ChatHandler::HandleServerRestartCommand(const char* args) { if(!*args) return false; - if(std::string(args)=="cancel") - { - sWorld.ShutdownCancel(); - } - else - { - int32 time = atoi(args); + char* time_str = strtok ((char*) args, " "); + char* exitcode_str = strtok (NULL, ""); - ///- Prevent interpret wrong arg value as 0 secs shutdown time - if(time == 0 && (args[0]!='0' || args[1]!='\0') || time < 0) + int32 time = atoi (time_str); + + ///- Prevent interpret wrong arg value as 0 secs shutdown time + if(time == 0 && (time_str[0]!='0' || time_str[1]!='\0') || time < 0) + return false; + + if (exitcode_str) + { + int32 exitcode = atoi (exitcode_str); + + // Handle atoi() errors + if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0')) return false; - sWorld.ShutdownServ(time,SHUTDOWN_MASK_RESTART+SHUTDOWN_MASK_IDLE); + // Exit code should be in range of 0-125, 126-255 is used + // in many shells for their own return codes and code > 255 + // is not supported in many others + if (exitcode < 0 || exitcode > 125) + return false; + + sWorld.ShutdownServ (time, SHUTDOWN_MASK_RESTART, exitcode); } + else + sWorld.ShutdownServ(time, SHUTDOWN_MASK_RESTART, RESTART_EXIT_CODE); return true; } -bool ChatHandler::HandleIdleShutDownCommand(const char* args) +bool ChatHandler::HandleServerIdleRestartCommand(const char* args) { if(!*args) return false; - if(std::string(args)=="cancel") - { - sWorld.ShutdownCancel(); - } - else - { - int32 time = atoi(args); + char* time_str = strtok ((char*) args, " "); + char* exitcode_str = strtok (NULL, ""); - ///- Prevent interpret wrong arg value as 0 secs shutdown time - if(time == 0 && (args[0]!='0' || args[1]!='\0') || time < 0) + int32 time = atoi (time_str); + + ///- Prevent interpret wrong arg value as 0 secs shutdown time + if(time == 0 && (time_str[0]!='0' || time_str[1]!='\0') || time < 0) + return false; + + if (exitcode_str) + { + int32 exitcode = atoi (exitcode_str); + + // Handle atoi() errors + if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0')) return false; - sWorld.ShutdownServ(time,SHUTDOWN_MASK_IDLE); + // Exit code should be in range of 0-125, 126-255 is used + // in many shells for their own return codes and code > 255 + // is not supported in many others + if (exitcode < 0 || exitcode > 125) + return false; + + sWorld.ShutdownServ (time, SHUTDOWN_MASK_RESTART|SHUTDOWN_MASK_IDLE, exitcode); } + else + sWorld.ShutdownServ(time,SHUTDOWN_MASK_RESTART|SHUTDOWN_MASK_IDLE,RESTART_EXIT_CODE); + return true; +} + +bool ChatHandler::HandleServerIdleShutDownCommand(const char* args) +{ + if(!*args) + return false; + + char* time_str = strtok ((char*) args, " "); + char* exitcode_str = strtok (NULL, ""); + + int32 time = atoi (time_str); + + ///- Prevent interpret wrong arg value as 0 secs shutdown time + if(time == 0 && (time_str[0]!='0' || time_str[1]!='\0') || time < 0) + return false; + + if (exitcode_str) + { + int32 exitcode = atoi (exitcode_str); + + // Handle atoi() errors + if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0')) + return false; + + // Exit code should be in range of 0-125, 126-255 is used + // in many shells for their own return codes and code > 255 + // is not supported in many others + if (exitcode < 0 || exitcode > 125) + return false; + + sWorld.ShutdownServ (time, SHUTDOWN_MASK_IDLE, exitcode); + } + else + sWorld.ShutdownServ(time,SHUTDOWN_MASK_IDLE,SHUTDOWN_EXIT_CODE); return true; } diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 2e6c60244..585ffa93d 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 333e2e182..f287cf719 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 @@ -340,7 +340,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;} @@ -356,7 +356,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 eef12f485..011d61eee 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" @@ -563,7 +564,7 @@ void ObjectMgr::LoadCreatureLocales() sLog.outString(); sLog.outString( ">> Loaded %u creature locale strings", mCreatureLocaleMap.size() ); } - + void ObjectMgr::LoadCompletedAchievements() { QueryResult *result = CharacterDatabase.Query("SELECT achievement FROM character_achievement GROUP BY achievement"); @@ -648,9 +649,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(); @@ -1553,9 +1564,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(); @@ -4173,9 +4194,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++) { @@ -4589,7 +4620,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) @@ -4597,7 +4628,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; @@ -5203,7 +5234,7 @@ uint32 ObjectMgr::GenerateArenaTeamId() if(m_arenaTeamId>=0xFFFFFFFF) { sLog.outError("Arena team ids overflow!! Can't continue, shutting down server. "); - sWorld.m_stopEvent = true; + World::StopNow(ERROR_EXIT_CODE); } return m_arenaTeamId; } @@ -5214,7 +5245,7 @@ uint32 ObjectMgr::GenerateGuildId() if(m_guildId>=0xFFFFFFFF) { sLog.outError("Guild ids overflow!! Can't continue, shutting down server. "); - sWorld.m_stopEvent = true; + World::StopNow(ERROR_EXIT_CODE); } return m_guildId; } @@ -5225,7 +5256,7 @@ uint32 ObjectMgr::GenerateAuctionID() if(m_auctionid>=0xFFFFFFFF) { sLog.outError("Auctions ids overflow!! Can't continue, shutting down server. "); - sWorld.m_stopEvent = true; + World::StopNow(ERROR_EXIT_CODE); } return m_auctionid; } @@ -5236,7 +5267,7 @@ uint32 ObjectMgr::GenerateMailID() if(m_mailid>=0xFFFFFFFF) { sLog.outError("Mail ids overflow!! Can't continue, shutting down server. "); - sWorld.m_stopEvent = true; + World::StopNow(ERROR_EXIT_CODE); } return m_mailid; } @@ -5247,7 +5278,7 @@ uint32 ObjectMgr::GenerateItemTextID() if(m_ItemTextId>=0xFFFFFFFF) { sLog.outError("Item text ids overflow!! Can't continue, shutting down server. "); - sWorld.m_stopEvent = true; + World::StopNow(ERROR_EXIT_CODE); } return m_ItemTextId; } @@ -5275,7 +5306,7 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh) if(m_hiItemGuid>=0xFFFFFFFF) { sLog.outError("Item guid overflow!! Can't continue, shutting down server. "); - sWorld.m_stopEvent = true; + World::StopNow(ERROR_EXIT_CODE); } return m_hiItemGuid; case HIGHGUID_UNIT: @@ -5283,7 +5314,7 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh) if(m_hiCreatureGuid>=0x00FFFFFF) { sLog.outError("Creature guid overflow!! Can't continue, shutting down server. "); - sWorld.m_stopEvent = true; + World::StopNow(ERROR_EXIT_CODE); } return m_hiCreatureGuid; case HIGHGUID_PET: @@ -5291,7 +5322,7 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh) if(m_hiPetGuid>=0x00FFFFFF) { sLog.outError("Pet guid overflow!! Can't continue, shutting down server. "); - sWorld.m_stopEvent = true; + World::StopNow(ERROR_EXIT_CODE); } return m_hiPetGuid; case HIGHGUID_VEHICLE: @@ -5307,7 +5338,7 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh) if(m_hiCharGuid>=0xFFFFFFFF) { sLog.outError("Players guid overflow!! Can't continue, shutting down server. "); - sWorld.m_stopEvent = true; + World::StopNow(ERROR_EXIT_CODE); } return m_hiCharGuid; case HIGHGUID_GAMEOBJECT: @@ -5315,7 +5346,7 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh) if(m_hiGoGuid>=0x00FFFFFF) { sLog.outError("Gameobject guid overflow!! Can't continue, shutting down server. "); - sWorld.m_stopEvent = true; + World::StopNow(ERROR_EXIT_CODE); } return m_hiGoGuid; case HIGHGUID_CORPSE: @@ -5323,7 +5354,7 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh) if(m_hiCorpseGuid>=0xFFFFFFFF) { sLog.outError("Corpse guid overflow!! Can't continue, shutting down server. "); - sWorld.m_stopEvent = true; + World::StopNow(ERROR_EXIT_CODE); } return m_hiCorpseGuid; case HIGHGUID_DYNAMICOBJECT: @@ -5331,7 +5362,7 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh) if(m_hiDoGuid>=0xFFFFFFFF) { sLog.outError("DynamicObject guid overflow!! Can't continue, shutting down server. "); - sWorld.m_stopEvent = true; + World::StopNow(ERROR_EXIT_CODE); } return m_hiDoGuid; default: @@ -5413,9 +5444,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++) @@ -6560,12 +6601,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 @@ -7276,6 +7317,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) @@ -7314,11 +7391,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) @@ -7333,3 +7409,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 789048435..968181759 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -288,9 +288,10 @@ class ObjectMgr typedef UNORDERED_MAP QuestMap; + typedef UNORDERED_MAP AreaTriggerMap; - typedef UNORDERED_MAP AreaTriggerScriptMap; + typedef UNORDERED_MAP AreaTriggerScriptMap; typedef UNORDERED_MAP RepOnKillMap; @@ -298,6 +299,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); } @@ -462,7 +465,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 { @@ -770,6 +773,10 @@ class ObjectMgr AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type); std::set allCompletedAchievements; + 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; @@ -788,7 +795,7 @@ class ObjectMgr uint32 m_hiPetNumber; - QuestMap mQuestTemplates; + QuestMap mQuestTemplates; typedef UNORDERED_MAP GossipTextMap; typedef UNORDERED_MAP QuestAreaTriggerMap; @@ -832,6 +839,8 @@ class ObjectMgr GameTeleMap m_GameTeleMap; + ScriptNameMap m_scriptNames; + typedef std::vector LocalForIndex; LocalForIndex m_LocalForIndex; int GetOrNewIndexForLocale(LocaleConstant loc); @@ -896,7 +905,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/Pet.h b/src/game/Pet.h index 4a0ff2d04..f43a1e305 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -214,6 +214,9 @@ class Pet : public Creature void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); } void ResetAuraUpdateMask() { m_auraUpdateMask = 0; } + // overwrite Creature function for name localization back to WorldObject version without localization + const char* GetNameForLocaleIdx(int32 locale_idx) const { return WorldObject::GetNameForLocaleIdx(locale_idx); } + DeclinedName const* GetDeclinedNames() const { return m_declinedname; } bool m_removed; // prevent overwrite pet state in DB at next Pet::Update if pet already removed(saved) 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 e61193068..f54541931 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -62,6 +62,7 @@ INSTANTIATE_SINGLETON_1( World ); volatile bool World::m_stopEvent = false; +uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE; volatile uint32 World::m_worldLoopCounter = 0; float World::m_MaxVisibleDistanceForCreature = DEFAULT_VISIBILITY_DISTANCE; @@ -927,6 +928,9 @@ void World::SetInitialWorldSettings() LoadDBCStores(m_dataPath); DetectDBCLang(); + sLog.outString( "Loading Script Names..."); + objmgr.LoadScriptNames(); + sLog.outString( "Loading InstanceTemplate" ); objmgr.LoadInstanceTemplate(); @@ -1534,6 +1538,8 @@ void World::ScriptsProcess() } } + if(source && !source->IsInWorld()) source = NULL; + Object* target = NULL; if(step.targetGUID) @@ -1564,6 +1570,8 @@ void World::ScriptsProcess() } } + if(target && !target->IsInWorld()) target = NULL; + switch (step.script->command) { case SCRIPT_COMMAND_TALK: @@ -2323,13 +2331,13 @@ void World::_UpdateGameTime() m_gameTime = thisTime; ///- if there is a shutdown timer - if(m_ShutdownTimer > 0 && elapsed > 0) + if(!m_stopEvent && m_ShutdownTimer > 0 && elapsed > 0) { ///- ... and it is overdue, stop the world (set m_stopEvent) if( m_ShutdownTimer <= elapsed ) { if(!(m_ShutdownMask & SHUTDOWN_MASK_IDLE) || GetActiveAndQueuedSessionCount()==0) - m_stopEvent = true; + m_stopEvent = true; // exist code already set else m_ShutdownTimer = 1; // minimum timer value to wait idle state } @@ -2344,15 +2352,20 @@ void World::_UpdateGameTime() } /// Shutdown the server -void World::ShutdownServ(uint32 time, uint32 options) +void World::ShutdownServ(uint32 time, uint32 options, uint8 exitcode) { + // ignore if server shutdown at next tick + if(m_stopEvent) + return; + m_ShutdownMask = options; + m_ExitCode = exitcode; ///- If the shutdown time is 0, set m_stopEvent (except if shutdown is 'idle' with remaining sessions) if(time==0) { if(!(options & SHUTDOWN_MASK_IDLE) || GetActiveAndQueuedSessionCount()==0) - m_stopEvent = true; + m_stopEvent = true; // exist code already set else m_ShutdownTimer = 1; //So that the session count is re-evaluated at next world tick } @@ -2397,13 +2410,15 @@ void World::ShutdownMsg(bool show, Player* player) /// Cancel a planned server shutdown void World::ShutdownCancel() { - if(!m_ShutdownTimer) + // nothing cancel or too later + if(!m_ShutdownTimer || m_stopEvent) return; uint32 msgid = (m_ShutdownMask & SHUTDOWN_MASK_RESTART) ? SERVER_MSG_RESTART_CANCELLED : SERVER_MSG_SHUTDOWN_CANCELLED; m_ShutdownMask = 0; m_ShutdownTimer = 0; + m_ExitCode = SHUTDOWN_EXIT_CODE; // to default value SendServerMessage(msgid); DEBUG_LOG("Server %s cancelled.",(m_ShutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shuttingdown")); diff --git a/src/game/World.h b/src/game/World.h index baa36fdb5..b5a66e7d6 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -49,6 +49,13 @@ enum ShutdownMask SHUTDOWN_MASK_IDLE = 2, }; +enum ShutdownExitCode +{ + SHUTDOWN_EXIT_CODE = 0, + ERROR_EXIT_CODE = 1, + RESTART_EXIT_CODE = 2, +}; + /// Timers for different object refresh rates enum WorldTimers { @@ -310,7 +317,6 @@ struct CliCommandHolder class World { public: - static volatile bool m_stopEvent; static volatile uint32 m_worldLoopCounter; World(); @@ -387,11 +393,13 @@ class World void SendServerMessage(uint32 type, const char *text = "", Player* player = NULL); /// Are we in the middle of a shutdown? - uint32 GetShutdownMask() const { return m_ShutdownMask; } bool IsShutdowning() const { return m_ShutdownTimer > 0; } - void ShutdownServ(uint32 time, uint32 options = 0); + void ShutdownServ(uint32 time, uint32 options, uint8 exitcode); void ShutdownCancel(); void ShutdownMsg(bool show = false, Player* player = NULL); + static uint8 GetExitCode() { return m_ExitCode; } + static void StopNow(uint8 exitcode) { m_stopEvent = true; m_ExitCode = exitcode; } + static bool IsStopped() { return m_stopEvent; } void Update(time_t diff); @@ -467,6 +475,11 @@ class World void InitDailyQuestResetTime(); void ResetDailyQuests(); private: + static volatile bool m_stopEvent; + static uint8 m_ExitCode; + uint32 m_ShutdownTimer; + uint32 m_ShutdownMask; + time_t m_startTime; time_t m_gameTime; IntervalTimer m_timers[WUPDATE_COUNT]; @@ -493,9 +506,6 @@ class World std::string m_motd; std::string m_dataPath; - uint32 m_ShutdownTimer; - uint32 m_ShutdownMask; - // for max speed access static float m_MaxVisibleDistanceForCreature; static float m_MaxVisibleDistanceForPlayer; diff --git a/src/mangosd/CliRunnable.cpp b/src/mangosd/CliRunnable.cpp index 77d87fcda..d4c635660 100644 --- a/src/mangosd/CliRunnable.cpp +++ b/src/mangosd/CliRunnable.cpp @@ -165,7 +165,7 @@ bool ChatHandler::HandleCharacterDeleteCommand(const char* args) bool ChatHandler::HandleServerExitCommand(const char* args) { SendSysMessage(LANG_COMMAND_EXIT); - World::m_stopEvent = true; + World::StopNow(SHUTDOWN_EXIT_CODE); return true; } @@ -306,14 +306,14 @@ void CliRunnable::run() printf("mangos>"); ///- As long as the World is running (no World::m_stopEvent), get the command line and handle it - while (!World::m_stopEvent) + while (!World::IsStopped()) { fflush(stdout); #ifdef linux - while (!kb_hit_return() && !World::m_stopEvent) + while (!kb_hit_return() && !World::IsStopped()) // With this, we limit CLI to 10commands/second usleep(100); - if (World::m_stopEvent) + if (World::IsStopped()) break; #endif char *command_str = fgets(commandbuf,sizeof(commandbuf),stdin); @@ -344,7 +344,7 @@ void CliRunnable::run() } else if (feof(stdin)) { - World::m_stopEvent = true; + World::StopNow(SHUTDOWN_EXIT_CODE); } } diff --git a/src/mangosd/Master.cpp b/src/mangosd/Master.cpp index 4a01c10ab..1b6929267 100644 --- a/src/mangosd/Master.cpp +++ b/src/mangosd/Master.cpp @@ -75,7 +75,7 @@ public: w_loops = 0; m_lastchange = 0; w_lastchange = 0; - while(!World::m_stopEvent) + while(!World::IsStopped()) { ZThread::Thread::sleep(1000); uint32 curtime = getMSTime(); @@ -170,13 +170,13 @@ public: // if use ra spend time waiting for io, if not use ra ,just sleep if (usera) - while (!World::m_stopEvent) + while (!World::IsStopped()) { h.Select (0, socketSelecttime); checkping (); } else - while (!World::m_stopEvent) + while (!World::IsStopped()) { ZThread::Thread::sleep (static_cast (socketSelecttime / 1000)); checkping (); @@ -308,7 +308,7 @@ int Master::Run() if (sWorldSocketMgr->StartNetwork (wsport, bind_ip.c_str ()) == -1) { sLog.outError ("Failed to start network"); - World::m_stopEvent = true; + World::StopNow(ERROR_EXIT_CODE); // go down and shutdown the server } @@ -379,7 +379,8 @@ int Master::Run() // fixes a memory leak related to detaching threads from the module UnloadScriptingModule(); - return sWorld.GetShutdownMask() & SHUTDOWN_MASK_RESTART ? 2 : 0; + // Exit the process with specified return value + return World::GetExitCode(); } /// Initialize connection to the databases @@ -462,17 +463,18 @@ void Master::clearOnlineAccounts() } /// Handle termination signals -/** Put the World::m_stopEvent to 'true' if a termination signal is caught **/ void Master::_OnSignal(int s) { switch (s) { case SIGINT: + World::StopNow(RESTART_EXIT_CODE); + break; case SIGTERM: #ifdef _WIN32 case SIGBREAK: #endif - World::m_stopEvent = true; + World::StopNow(SHUTDOWN_EXIT_CODE); break; } diff --git a/src/mangosd/WorldRunnable.cpp b/src/mangosd/WorldRunnable.cpp index e812e23ec..7ebe95fc7 100644 --- a/src/mangosd/WorldRunnable.cpp +++ b/src/mangosd/WorldRunnable.cpp @@ -49,7 +49,7 @@ void WorldRunnable::run() uint32 prevSleepTime = 0; // used for balanced full tick time length near WORLD_SLEEP_CONST ///- While we have not World::m_stopEvent, update the world - while (!World::m_stopEvent) + while (!World::IsStopped()) { ++World::m_worldLoopCounter; realCurrTime = getMSTime(); 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 6d15d083a..74248b31c 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; @@ -27,165 +25,57 @@ 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[]="iiii"; -const char GameObjectInfofmt[]="iiissiifiiiiiiiiiiiiiiiiiiiiiiiis"; -const char ItemPrototypefmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiffiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiisiiii"; +const char GameObjectInfosrcfmt[]="iiissiifiiiiiiiiiiiiiiiiiiiiiiiis"; +const char GameObjectInfodstfmt[]="iiissiifiiiiiiiiiiiiiiiiiiiiiiiii"; +const char ItemPrototypesrcfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiffiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifsiiiiii"; +const char ItemPrototypedstfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiffiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiiiiiii"; 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 () { 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); } 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..d2d1ba018 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 "6832" #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" > + +