All pastes #832136 Raw Edit

Untitled

public cpp v1 · immutable
#832136 ·published 2007-12-25 20:57 UTC
rendered paste body
Index: configure.ac===================================================================--- configure.ac	(revision 4909)+++ configure.ac	(working copy)@@ -228,7 +228,9 @@    src/mangosd/Makefile    src/mangosd/mangosd.conf    src/bindings/Makefile-   src/bindings/universal/Makefile+   src/bindings/ScriptDev2/Makefile+   src/bindings/ScriptDev2/sql/Makefile+   src/bindings/ScriptDev2/sql/Updates/Makefile ])  ## Disabled Makefiles, until they are ready for a successful make andIndex: src/bindings/Makefile.am===================================================================--- src/bindings/Makefile.am	(revision 4909)+++ src/bindings/Makefile.am	(working copy)@@ -14,4 +14,4 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA -SUBDIRS = universal+SUBDIRS = ScriptDev2Index: src/game/BattleGroundMgr.cpp===================================================================--- src/game/BattleGroundMgr.cpp	(revision 4909)+++ src/game/BattleGroundMgr.cpp	(working copy)@@ -79,10 +79,34 @@     else         m_QueuedPlayers[queue_id].Horde++; -    /* temporary BG queue status message -    std::ostringstream str;-    str << "Battleground queue invited status: horde: " << m_QueuedPlayers[queue_id].Horde << ", aliance: " << m_QueuedPlayers[queue_id].Alliance;-    plr->Say(str.str(), LANG_UNIVERSAL);*/+    /* temporary BG queue status message */+	//#TODO: add proper check for the number of players in queue+	if ( m_QueuedPlayers[queue_id].Alliance == 5 || m_QueuedPlayers[queue_id].Alliance == 7 || m_QueuedPlayers[queue_id].Alliance == 10 ||+		m_QueuedPlayers[queue_id].Horde == 5 || m_QueuedPlayers[queue_id].Horde == 7 || m_QueuedPlayers[queue_id].Horde == 10 )+	{+	    std::ostringstream str;+		str << "Battleground queue invited status for ";+		switch (bgTypeId)+		{+		case 1:+			str << "Alterac Valley"; break;+		case 2:+			str << "Warsong Gulch"; break;+		case 3:+			str << "Arathi Basin"; break;+	//#TODO: add other cases+		default:+			str << "other bg / arena"; break;+		}+		str << ", for level ";+		if(plr->getLevel()!=sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))+		    str << (int)(plr->getLevel()/10)*10 << " - " << (int)(plr->getLevel()/10)*10+9;+		else+		    str << plr->getLevel(); +		str << ":\n Horde: " << m_QueuedPlayers[queue_id].Horde << ", Alliance: " << m_QueuedPlayers[queue_id].Alliance;+		sWorld.SendWorldText(str.str().c_str(), NULL);+	}+    /* plr->Say(str.str(), LANG_UNIVERSAL);*/      this->Update(bgTypeId, queue_id); }Index: src/game/Chat.cpp===================================================================--- src/game/Chat.cpp	(revision 4909)+++ src/game/Chat.cpp	(working copy)@@ -262,6 +262,9 @@         { "help",        SEC_PLAYER,        &ChatHandler::HandleHelpCommand,             "",   NULL },         { "info",        SEC_PLAYER,        &ChatHandler::HandleInfoCommand,             "",   NULL },         { "npcinfo",     SEC_ADMINISTRATOR, &ChatHandler::HandleNpcInfoCommand,          "",   NULL },+        { "creatureinfo", SEC_PLAYER,       &ChatHandler::HandleCreatureInfoCommand,     "",   NULL },+        { "bug",         SEC_PLAYER,        &ChatHandler::HandleBugCommand,              "",   NULL },+        { "dlb",         SEC_ADMINISTRATOR, &ChatHandler::HandleDelBugCommand,           "",   NULL },         { "npcinfoset",  SEC_ADMINISTRATOR, &ChatHandler::HandleNpcInfoSetCommand,       "",   NULL },         { "addvendoritem",SEC_GAMEMASTER,   &ChatHandler::HandleAddVendorItemCommand,    "",   NULL },         { "delvendoritem",SEC_GAMEMASTER,   &ChatHandler::HandleDelVendorItemCommand,    "",   NULL },Index: src/game/Chat.h===================================================================--- src/game/Chat.h	(revision 4909)+++ src/game/Chat.h	(working copy)@@ -257,6 +257,9 @@         bool HandleExploreCheatCommand(const char* args);         bool HandleTextEmoteCommand(const char* args);         bool HandleNpcInfoCommand(const char* args);+        bool HandleCreatureInfoCommand(const char* args);+        bool HandleBugCommand(const char* args);+        bool HandleDelBugCommand(const char* args);         bool HandleNpcInfoSetCommand(const char* args);         bool HandleHoverCommand(const char* args);         bool HandleLevelUpCommand(const char* args);Index: src/game/Group.cpp===================================================================--- src/game/Group.cpp	(revision 4909)+++ src/game/Group.cpp	(working copy)@@ -51,6 +51,14 @@         else if(m_bgGroup->GetBgRaid(HORDE) == this) m_bgGroup->SetBgRaid(HORDE, NULL);         else sLog.outError("Group::~Group: battleground group is not linked to the correct battleground.");     }+    Rolls::iterator itr;+    while(!RollId.empty())+    {+        itr = RollId.begin();+        Roll *r = *itr;+        RollId.erase(itr);+        delete(r);+    } }  bool Group::Create(const uint64 &guid, const char * name)@@ -392,12 +400,12 @@         //roll for over-threshold item if it's one-player loot         if (item->Quality >= uint32(m_lootThreshold) && !i->freeforall)         {-            Roll r;+            Roll* r=new Roll();             uint32 newitemGUID = objmgr.GenerateLowGuid(HIGHGUID_ITEM);-            r.itemGUID = newitemGUID;-            r.itemid = i->itemid;-            r.itemRandomPropId = i->randomPropertyId;-            r.itemRandomSuffix = i->randomSuffix;+            r->itemGUID = newitemGUID;+            r->itemid = i->itemid;+            r->itemRandomPropId = i->randomPropertyId;+            r->itemRandomSuffix = i->randomSuffix;              //a vector is filled with only near party members             for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())@@ -409,16 +417,16 @@                 {                     if (member->GetDistance2dSq(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE))                     {-                        r.playerVote[member->GetGUID()] = NOT_EMITED_YET;-                        r.totalPlayersRolling++;+                        r->playerVote[member->GetGUID()] = NOT_EMITED_YET;+                        r->totalPlayersRolling++;                     }                 }             } -            r.loot = loot;-            r.itemSlot = itemSlot;+            r->setLoot(loot);+            r->itemSlot = itemSlot; -            group->SendLootStartRoll(newitemGUID, 60000, r);+            group->SendLootStartRoll(newitemGUID, 60000, *r);              loot->items[itemSlot].is_blocked = true;             creature->m_groupLootTimer = 60000;@@ -447,12 +455,12 @@         //only roll for one-player items, not for ones everyone can get         if (item->Quality >= uint32(m_lootThreshold) && !i->freeforall)         {-            Roll r;+            Roll* r=new Roll();             uint32 newitemGUID = objmgr.GenerateLowGuid(HIGHGUID_ITEM);-            r.itemGUID = newitemGUID;-            r.itemid = i->itemid;-            r.itemRandomPropId = i->randomPropertyId;-            r.itemRandomSuffix = i->randomSuffix;+            r->itemGUID = newitemGUID;+            r->itemid = i->itemid;+            r->itemRandomPropId = i->randomPropertyId;+            r->itemRandomSuffix = i->randomSuffix;              for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())             {@@ -464,23 +472,27 @@                 {                     if (playerToRoll->GetDistance2dSq(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE))                     {-                        r.playerVote[playerToRoll->GetGUID()] = NOT_EMITED_YET;-                        r.totalPlayersRolling++;+                        r->playerVote[playerToRoll->GetGUID()] = NOT_EMITED_YET;+                        r->totalPlayersRolling++;                     }                 }             } -            if (r.totalPlayersRolling > 0)+            if (r->totalPlayersRolling > 0)             {-                r.loot = loot;-                r.itemSlot = itemSlot;+                r->setLoot(loot);+                r->itemSlot = itemSlot; -                group->SendLootStartRoll(newitemGUID, 60000, r);+                group->SendLootStartRoll(newitemGUID, 60000, *r);                  loot->items[itemSlot].is_blocked = true;                  RollId.push_back(r);             }+            else+            {+                delete r;+            }         }         else             i->is_underthreshold=1;@@ -489,8 +501,9 @@  void Group::CountRollVote(uint64 playerGUID, uint64 Guid, uint32 NumberOfPlayers, uint8 Choise) {-    Rolls::iterator roll = GetRoll(Guid);-    if (roll == RollId.end())+    Rolls::iterator rollI = GetRoll(Guid);+    Roll* roll = *rollI;+    if (rollI == RollId.end())         return;      Roll::PlayerVote::iterator itr = roll->playerVote.find(playerGUID);@@ -498,8 +511,8 @@     if (itr == roll->playerVote.end())         return; -    if (roll->loot)-        if (roll->loot->items.empty())+    if (roll->getLoot())+        if (roll->getLoot()->items.empty())             return;      switch (Choise)@@ -528,7 +541,7 @@     }     if (roll->totalPass + roll->totalGreed + roll->totalNeed >= roll->totalPlayersRolling)     {-        CountTheRoll(roll, NumberOfPlayers);+        CountTheRoll(rollI, NumberOfPlayers);     } } @@ -544,8 +557,15 @@     } } -void Group::CountTheRoll(Rolls::iterator roll, uint32 NumberOfPlayers)+void Group::CountTheRoll(Rolls::iterator rollI, uint32 NumberOfPlayers) {+    Roll* roll = *rollI;+    if(!roll->isValid()) // is loot already deleted ?+    {+        RollId.erase(rollI);+        delete roll;+        return;+    }     //end of the roll     if (roll->totalNeed > 0)     {@@ -574,13 +594,13 @@             if(player && player->GetSession())             {                 uint16 dest;-                LootItem *item = &(roll->loot->items[roll->itemSlot]);+                LootItem *item = &(roll->getLoot()->items[roll->itemSlot]);                 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, roll->itemid, item->count, false );                 if ( msg == EQUIP_ERR_OK )                 {                     item->is_looted = true;-                    roll->loot->NotifyItemRemoved(roll->itemSlot);-                    roll->loot->unlootedCount--;+                    roll->getLoot()->NotifyItemRemoved(roll->itemSlot);+                    roll->getLoot()->unlootedCount--;                     player->StoreNewItem( dest, roll->itemid, item->count, true, item->randomPropertyId);                 }                 else@@ -619,13 +639,13 @@             if(player && player->GetSession())             {                 uint16 dest;-                LootItem *item = &(roll->loot->items[roll->itemSlot]);+                LootItem *item = &(roll->getLoot()->items[roll->itemSlot]);                 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, roll->itemid, item->count, false );                 if ( msg == EQUIP_ERR_OK )                 {                     item->is_looted = true;-                    roll->loot->NotifyItemRemoved(roll->itemSlot);-                    roll->loot->unlootedCount--;+                    roll->getLoot()->NotifyItemRemoved(roll->itemSlot);+                    roll->getLoot()->unlootedCount--;                     player->StoreNewItem( dest, roll->itemid, item->count, true, item->randomPropertyId);                 }                 else@@ -639,10 +659,11 @@     else     {         SendLootAllPassed(roll->itemGUID, NumberOfPlayers, *roll);-        LootItem *item = &(roll->loot->items[roll->itemSlot]);+        LootItem *item = &(roll->getLoot()->items[roll->itemSlot]);         if(item) item->is_blocked = false;     }-    RollId.erase(roll);+    RollId.erase(rollI);+    delete roll; }  void Group::SetTargetIcon(uint8 id, uint64 guid)@@ -995,18 +1016,19 @@ {     for (Rolls::iterator it = RollId.begin(); it < RollId.end(); it++)     {-        Roll::PlayerVote::iterator itr2 = it->playerVote.find(guid);-        if(itr2 == it->playerVote.end())+        Roll* roll = *it;+        Roll::PlayerVote::iterator itr2 = roll->playerVote.find(guid);+        if(itr2 == roll->playerVote.end())             continue; -        if (itr2->second == GREED) it->totalGreed--;-        if (itr2->second == NEED) it->totalNeed--;-        if (itr2->second == PASS) it->totalPass--;-        if (itr2->second != NOT_VALID) it->totalPlayersRolling--;+        if (itr2->second == GREED) roll->totalGreed--;+        if (itr2->second == NEED) roll->totalNeed--;+        if (itr2->second == PASS) roll->totalPass--;+        if (itr2->second != NOT_VALID) roll->totalPlayersRolling--; -        it->playerVote.erase(itr2);+        roll->playerVote.erase(itr2); -        CountRollVote(guid, it->itemGUID, GetMembersCount()-1, 3);+        CountRollVote(guid, roll->itemGUID, GetMembersCount()-1, 3);     } } @@ -1095,3 +1117,13 @@         SendUpdate();     } }++//===================================================+//============== Roll ===============================+//===================================================++void Roll::targetObjectBuildLink()+{+    // called from link()+    this->getTarget()->addLootInvalidListener(this);+}Index: src/game/Group.h===================================================================--- src/game/Group.h	(revision 4909)+++ src/game/Group.h	(working copy)@@ -21,6 +21,7 @@  #include "GroupReference.h" #include "GroupRefManager.h"+#include "LootMgr.h"  #include <map> #include <vector>@@ -100,6 +101,28 @@                                                             //0, 1, 2, 3, 4, 5, 6, 7, 8, 9 static const uint8 GroupUpdateLength[GROUP_UPDATE_FLAGS_COUNT] = { 0, 1, 2, 2, 1, 2, 2, 2, 2, 4}; +class Roll : public LootInvalidListener+{+public:+    Roll(): itemGUID(0), itemid(0), itemRandomPropId(0), totalPlayersRolling(0), totalNeed(0), totalGreed(0), totalPass(0), itemSlot(0) {}+    ~Roll() { }+    void setLoot(Loot *pLoot) { link(pLoot, this); }+    Loot *getLoot() { return getTarget(); }+    void targetObjectBuildLink();++    uint64 itemGUID;+    uint32 itemid;+    uint32 itemRandomSuffix;+    int32  itemRandomPropId;+    typedef std::map<uint64, RollVote> PlayerVote;+    PlayerVote playerVote;                          //vote position correspond with player position (in group)+    uint8 totalPlayersRolling;+    uint8 totalNeed;+    uint8 totalGreed;+    uint8 totalPass;+    uint8 itemSlot;+};+ /** request member stats checken **/ /** todo: uninvite people that not accepted invite **/ class MANGOS_DLL_SPEC Group@@ -118,26 +141,8 @@         typedef MemberSlotList::iterator member_witerator;         typedef std::set<uint64> InvitesList; -        struct Roll-        {-            Roll(): itemGUID(0), itemid(0), itemRandomPropId(0), totalPlayersRolling(0), totalNeed(0), totalGreed(0), totalPass(0), loot(NULL), itemSlot(0) {}+        typedef std::vector<Roll*> Rolls; -            uint64 itemGUID;-            uint32 itemid;-            uint32 itemRandomSuffix;-            int32  itemRandomPropId;-            typedef std::map<uint64, RollVote> PlayerVote;-            PlayerVote playerVote;                          //vote position correspond with player position (in group)-            uint8 totalPlayersRolling;-            uint8 totalNeed;-            uint8 totalGreed;-            uint8 totalPass;-            Loot *loot;-            uint8 itemSlot;-        };--        typedef std::vector<Roll> Rolls;-     public:         Group();         ~Group();@@ -271,7 +276,7 @@             Rolls::iterator iter;             for (iter=RollId.begin(); iter != RollId.end(); ++iter)             {-                if (iter->itemGUID == Guid)+                if ((*iter)->itemGUID == Guid)                 {                     return iter;                 }Index: src/game/Language.h===================================================================--- src/game/Language.h	(revision 4909)+++ src/game/Language.h	(working copy)@@ -483,6 +483,7 @@ #define LANG_MOVEGENS_UNKNOWN            "Unknown movement generator (%u)"  #define LANG_NPCINFO_CHAR                "Player selected NPC\nGUID: %u.\nFaction: %u.\nnpcFlags: %u.\nEntry: %u.\nDisplayID: %u (Native: %u)."+#define LANG_CREATUREINFO_CHAR           "Player selected Creature\nGUID: %u.\nEntry: %u." #define LANG_NPCINFO_LEVEL               "Level: %u." #define LANG_NPCINFO_HEALTH              "Health (base): %u. (max): %u. (current): %u." #define LANG_NPCINFO_FLAGS               "Field Flags: %u.\nDynamic Flags: %u.\nFaction Template: %u."Index: src/game/Level0.cpp===================================================================--- src/game/Level0.cpp	(revision 4909)+++ src/game/Level0.cpp	(working copy)@@ -297,3 +297,33 @@         SendSysMessage(LANG_BAD_VALUE);     return true; }++bool ChatHandler::HandleCreatureInfoCommand(const char* args)+{+    Creature* target = getSelectedCreature();++    if(!target)+    {+        SendSysMessage(LANG_SELECT_CREATURE);+        return true;+    }++    uint32 Entry = target->GetUInt32Value(OBJECT_FIELD_ENTRY);+    CreatureInfo const* cInfo = target->GetCreatureInfo();++    PSendSysMessage(LANG_CREATUREINFO_CHAR,  target->GetDBTableGUIDLow(), Entry);++    return true;+}++bool ChatHandler::HandleBugCommand(const char* args)+{+    if (!*args)+        return false;++       std::string bug=args;+       WorldDatabase.escape_string(bug);+    WorldDatabase.PExecute("INSERT INTO `bugs` (`name`, `bug`) VALUES ('%s', '%s')", m_session->GetPlayerName(), bug.c_str());+       PSendSysMessage("Thank you %s, Remember that bad reports leads you to punishment", m_session->GetPlayerName());+    return true;+}Index: src/game/Level3.cpp===================================================================--- src/game/Level3.cpp	(revision 4909)+++ src/game/Level3.cpp	(working copy)@@ -4418,3 +4418,15 @@     return true; } +bool ChatHandler::HandleDelBugCommand(const char* args)+{+         if (!*args)+               return false;++       std::string bug=args;+       WorldDatabase.escape_string(bug);+       PSendSysMessage("Bugs you have listed(%s) was deleted.", bug.c_str());+       WorldDatabase.PExecute("DELETE FROM `bugs` WHERE `entry` in (%s)", bug.c_str());+       return true;+}+Index: src/game/LootMgr.cpp===================================================================--- src/game/LootMgr.cpp	(revision 4909)+++ src/game/LootMgr.cpp	(working copy)@@ -556,6 +556,8 @@     return ql; } +//===================================================+ void Loot::NotifyItemRemoved(uint8 lootIndex) {     // notify all players that are looting this that the item was removedIndex: src/game/LootMgr.h===================================================================--- src/game/LootMgr.h	(revision 4909)+++ src/game/LootMgr.h	(working copy)@@ -25,6 +25,7 @@ #include "ItemEnchantmentMgr.h" #include "ByteBuffer.h" #include "Util.h"+#include "Utilities/LinkedReference/RefManager.h"  #include <map> #include <vector>@@ -141,11 +142,41 @@         : index(_index), is_looted(_islooted) {} }; + typedef std::vector<QuestItem> QuestItemList; typedef std::map<uint32, QuestItemList *> QuestItemMap; typedef std::vector<LootStoreItem> LootStoreItemList; typedef HM_NAMESPACE::hash_map<uint32, LootStoreItemList > LootStore; +//=====================================================++struct Loot;+class LootInvalidListener :  public Reference<Loot, LootInvalidListener>+{+public:+    LootInvalidListener() {}+    void targetObjectDestroyLink() {}+    void sourceObjectDestroyLink() {}+};++//=====================================================++class LootInvalidRefManager : public RefManager<Loot, LootInvalidListener>+{+    public:+        typedef LinkedListHead::Iterator< LootInvalidListener > iterator;++        LootInvalidListener* getFirst() { return (LootInvalidListener*)RefManager<Loot, LootInvalidListener>::getFirst(); }+        LootInvalidListener* getLast() { return (LootInvalidListener*)RefManager<Loot, LootInvalidListener>::getLast(); }++        iterator begin() { return iterator(getFirst()); }+        iterator end() { return iterator(NULL); }+        iterator rbegin() { return iterator(getLast()); }+        iterator rend() { return iterator(NULL); }+};++//=====================================================+ struct Loot {     std::set<uint64> PlayersLooting;@@ -154,6 +185,8 @@     QuestItemMap PlayerNonQuestNonFFAConditionalItems;     std::vector<LootItem> items;     std::vector<LootItem> quest_items;+    // All rolls are registered here. They need to know, when the loot is not valid anymore+    LootInvalidRefManager i_LootInvalidRefManager;     uint32 gold;     uint8 unlootedCount;     bool released;@@ -161,6 +194,13 @@     Loot(uint32 _gold = 0) : gold(_gold), unlootedCount(0), released(false) {}     ~Loot() { clear(); } +    // if loot becomes invalid this reference is used to inform the listener+    void addLootInvalidListener(LootInvalidListener* pLootInvalidListener)+    { +        i_LootInvalidRefManager.insertFirst(pLootInvalidListener);+    }++   // void clear();     void clear()     {         items.clear(); gold = 0; PlayersLooting.clear();@@ -179,6 +219,7 @@         quest_items.clear();         gold = 0;         unlootedCount = 0;+        i_LootInvalidRefManager.clearReferences();     }      bool empty() const { return items.empty() && gold == 0; }Index: src/game/Mail.cpp===================================================================--- src/game/Mail.cpp	(revision 4909)+++ src/game/Mail.cpp	(working copy)@@ -56,23 +56,29 @@      MailItemsInfo mi; -    recv_data >> mi.items_count;                            // attached items count+    uint8 items_count;+    recv_data >> items_count;                               // attached items count -    if(mi.items_count > 12)                                 // client limit+    if(items_count > 12)                                 // client limit         return; -    if(mi.items_count)+    if(items_count)     {-        for(uint8 i = 0; i < mi.items_count; ++i)+        for(uint8 i = 0; i < items_count; ++i)         {-            recv_data >> mi.item_slot[i];-            recv_data >> mi.item_guid[i];+            uint8  item_slot;+            uint64 item_guid;+            recv_data >> item_slot;+            recv_data >> item_guid;+            mi.AddItem(item_guid, item_slot);         }     }      recv_data >> money >> COD;                              // then there are two (uint32) 0;     recv_data >> unk3 >> unk4 >> unk5;                      // unknown 2.3.0 (zero's) +    items_count = mi.size(); // this is the real size after the duplicates have been removed+     if (receiver.empty())         return; @@ -81,7 +87,7 @@      Player* pl = _player; -    sLog.outDetail("Player %u is sending mail to %s with subject %s and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u", pl->GetGUIDLow(), receiver.c_str(), subject.c_str(), body.c_str(), mi.items_count, money, COD, unk1, unk2);+    sLog.outDetail("Player %u is sending mail to %s with subject %s and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u", pl->GetGUIDLow(), receiver.c_str(), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2);      uint64 rc = objmgr.GetPlayerGUIDByName(receiver);     if (!rc)@@ -97,8 +103,8 @@     }      uint32 reqmoney = money + 30;-    if (mi.items_count)-        reqmoney = money + (30 * mi.items_count);+    if (items_count)+        reqmoney = money + (30 * items_count);      if (pl->GetMoney() < reqmoney)     {@@ -140,19 +146,21 @@         return;     } -    if (mi.items_count)+    if (items_count)     {-        for(uint8 i = 0; i < mi.items_count; ++i)+        for(MailItemMap::iterator mailItemIter = mi.begin(); mailItemIter != mi.end(); ++mailItemIter)         {-            mi.item_pos[i] = pl->GetPosByGuid(mi.item_guid[i]);-            mi.items[i] = pl->GetItemByPos(mi.item_pos[i]);+            MailItem& mailItem = mailItemIter->second;++            mailItem.item_pos = pl->GetPosByGuid(mailItem.item_guid);+            mailItem.item = pl->GetItemByPos(mailItem.item_pos);             // prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to mail)-            if(!mi.items[i] || !mi.items[i]->CanBeTraded())+            if(!mailItem.item || !mailItem.item->CanBeTraded())             {                 pl->SendMailResult(0, 0, MAIL_ERR_INTERNAL_ERROR);                 return;             }-            if (mi.items[i]->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_CONJURED))+            if (mailItem.item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_CONJURED))             {                 pl->SendMailResult(0, 0, MAIL_ERR_INTERNAL_ERROR);                 return;@@ -171,7 +179,7 @@      bool needItemDelay = false; -    if (mi.items_count)+    if (items_count)     {         uint32 rc_account = 0;         if(receive)@@ -179,33 +187,34 @@         else             rc_account = objmgr.GetPlayerAccountIdByGUID(rc); -        for(uint8 i = 0; i < mi.items_count; ++i)+        for(MailItemMap::iterator mailItemIter = mi.begin(); mailItemIter != mi.end(); ++mailItemIter)         {-            if(!mi.items[i])+            MailItem& mailItem = mailItemIter->second;+            if(!mailItem.item)                 continue; -            mi.item_template[i] = mi.items[i] ? mi.items[i]->GetEntry() : 0;+            mailItem.item_template = mailItem.item ? mailItem.item->GetEntry() : 0;              if( GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )             {                 sLog.outCommand("GM %s (Account: %u) mail item: %s (Entry: %u Count: %u) and money: %u to player: %s (Account: %u)",-                    GetPlayerName(), GetAccountId(), mi.items[i]->GetProto()->Name1, mi.items[i]->GetEntry(), mi.items[i]->GetCount(), money, receiver.c_str(), rc_account);+                    GetPlayerName(), GetAccountId(), mailItem.item->GetProto()->Name1, mailItem.item->GetEntry(), mailItem.item->GetCount(), money, receiver.c_str(), rc_account);             } -            pl->RemoveItem( (mi.item_pos[i] >> 8), (mi.item_pos[i] & 255), true );-            mi.items[i]->RemoveFromUpdateQueueOf( pl );+            pl->RemoveItem( (mailItem.item_pos >> 8), (mailItem.item_pos & 255), true );+            mailItem.item->RemoveFromUpdateQueueOf( pl );             //item reminds in item_instance table already, used it in mail now-            if(mi.items[i]->IsInWorld())+            if(mailItem.item->IsInWorld())             {-                mi.items[i]->RemoveFromWorld();-                mi.items[i]->DestroyForPlayer( pl );+                mailItem.item->RemoveFromWorld();+                mailItem.item->DestroyForPlayer( pl );             }              CharacterDatabase.BeginTransaction();-            mi.items[i]->DeleteFromInventoryDB();           //deletes item from character's inventory-            mi.items[i]->SaveToDB();                        // recursive and not have transaction guard into self+            mailItem.item->DeleteFromInventoryDB();           //deletes item from character's inventory+            mailItem.item->SaveToDB();                        // recursive and not have transaction guard into self             // owner in `data` will set at mail receive and item extracting-            CharacterDatabase.PExecute("UPDATE `item_instance` SET `owner_guid` = '%u' WHERE `guid`='%u'", GUID_LOPART(rc), mi.items[i]->GetGUIDLow());+            CharacterDatabase.PExecute("UPDATE `item_instance` SET `owner_guid` = '%u' WHERE `guid`='%u'", GUID_LOPART(rc), mailItem.item->GetGUIDLow());             CharacterDatabase.CommitTransaction();         } @@ -225,20 +234,20 @@     if (receive)         receive->CreateMail(mailId, messagetype, pl->GetGUIDLow(), subject, itemTextId, &mi, etime, dtime, money, COD, NOT_READ);     else-        for(uint8 i = 0; i < mi.items_count; ++i)-            if (mi.items[i])-                delete mi.items[i];                         //item is sent, but receiver isn't online .. so remove it from RAM+        mi.deleteIncludedItems();      // backslash all '     CharacterDatabase.escape_string(subject);     //not needed : CharacterDatabase.PExecute("DELETE FROM `mail` WHERE `id` = '%u'",mID);     CharacterDatabase.PExecute("INSERT INTO `mail` (`id`,`messageType`,`sender`,`receiver`,`subject`,`itemTextId`,`has_items`,`expire_time`,`deliver_time`,`money`,`cod`,`checked`) "         "VALUES ('%u', '%u', '%u', '%u', '%s', '%u', '%u', '" I64FMTD "','" I64FMTD "', '%u', '%u', '%d')",-        mailId, messagetype, pl->GetGUIDLow(), GUID_LOPART(rc), subject.c_str(), itemTextId, mi.items_count ? 1 : 0, (uint64)etime, (uint64)dtime, money, COD, NOT_READ);+        mailId, messagetype, pl->GetGUIDLow(), GUID_LOPART(rc), subject.c_str(), itemTextId, items_count ? 1 : 0, (uint64)etime, (uint64)dtime, money, COD, NOT_READ); -    for(uint8 i = 0; i < mi.items_count; ++i)-        CharacterDatabase.PExecute("INSERT INTO `mail_items` (`mail_id`,`item_guid`,`item_template`) VALUES ('%u', '%u', '%u')", mailId, GUID_LOPART(mi.item_guid[i]), mi.item_template[i]);-+    for(MailItemMap::iterator mailItemIter = mi.begin(); mailItemIter != mi.end(); ++mailItemIter)+    {+        MailItem& mailItem = mailItemIter->second;+        CharacterDatabase.PExecute("INSERT INTO `mail_items` (`mail_id`,`item_guid`,`item_template`) VALUES ('%u', '%u', '%u')", mailId, GUID_LOPART(mailItem.item_guid), mailItem.item_template);+    }     CharacterDatabase.BeginTransaction();     pl->SaveInventoryAndGoldToDB();     CharacterDatabase.CommitTransaction();@@ -345,18 +354,19 @@     {         bool needItemDelay = false; -        if(mi->items_count)+        if(mi->size())         {             // if item send to character at another account, then apply item delivery delay             needItemDelay = sender_acc != rc_account;              // set owner to new receiver (to prevent delete item with sender char deleting)             CharacterDatabase.BeginTransaction();-            for(uint8 i = 0; i < mi->items_count; ++i)+            for(MailItemMap::iterator mailItemIter = mi->begin(); mailItemIter != mi->end(); ++mailItemIter)             {-                mi->items[i]->SaveToDB();                   // recursive and not have transaction guard into self+                MailItem& mailItem = mailItemIter->second;+                mailItem.item->SaveToDB();                 // owner in `data` will set at mail receive and item extracting-                CharacterDatabase.PExecute("UPDATE `item_instance` SET `owner_guid` = '%u' WHERE `guid`='%u'", receiver_guid, mi->items[i]->GetGUIDLow());+                CharacterDatabase.PExecute("UPDATE `item_instance` SET `owner_guid` = '%u' WHERE `guid`='%u'", receiver_guid, mailItem.item->GetGUIDLow());             }             CharacterDatabase.CommitTransaction();         }@@ -372,28 +382,27 @@         }         else         {-            if (mi->items_count)-                for(uint8 i = 0; i < mi->items_count; ++i)-                    delete mi->items[i];+            mi->deleteIncludedItems();         }          CharacterDatabase.escape_string(subject);           //we cannot forget to delete COD, if returning mail with COD         CharacterDatabase.PExecute("INSERT INTO `mail` (`id`,`messageType`,`sender`,`receiver`,`subject`,`itemTextId`,`has_items`,`expire_time`,`deliver_time`,`money`,`cod`,`checked`) "             "VALUES ('%u', '0', '%u', '%u', '%s', '%u', '%u', '" I64FMTD "', '" I64FMTD "', '%u', '0', '%d')",-            mailId, sender_guid, receiver_guid, subject.c_str(), itemTextId, mi->items_count ? 1 : 0, (uint64)expire_time, (uint64)deliver_time, money,RETURNED_CHECKED);+            mailId, sender_guid, receiver_guid, subject.c_str(), itemTextId, mi->size() ? 1 : 0, (uint64)expire_time, (uint64)deliver_time, money,RETURNED_CHECKED); -        for(uint8 i = 0; i < mi->items_count; ++i)-            CharacterDatabase.PExecute("INSERT INTO `mail_items` (`mail_id`,`item_guid`,`item_template`) VALUES ('%u', '%u', '%u')", mailId, GUID_LOPART(mi->item_guid[i]), mi->item_template[i]);+            for(MailItemMap::iterator mailItemIter = mi->begin(); mailItemIter != mi->end(); ++mailItemIter)+            {+                MailItem& mailItem = mailItemIter->second;+                CharacterDatabase.PExecute("INSERT INTO `mail_items` (`mail_id`,`item_guid`,`item_template`) VALUES ('%u', '%u', '%u')", mailId, GUID_LOPART(mailItem.item_guid), mailItem.item_template);+            }     }     else     {-        if(mi->items_count)+        for(MailItemMap::iterator mailItemIter = mi->begin(); mailItemIter != mi->end(); ++mailItemIter)         {-            for(uint8 i = 0; i < mi->items_count; ++i)-            {-                CharacterDatabase.PExecute("DELETE FROM `item_instance` WHERE `guid`='%u'", mi->items[i]->GetGUIDLow());-                delete mi->items[i];-            }+            MailItem& mailItem = mailItemIter->second;+            CharacterDatabase.PExecute("DELETE FROM `item_instance` WHERE `guid`='%u'", mailItem.item->GetGUIDLow());+            mailItem.deleteItem();         }     } }Index: src/game/Mail.h===================================================================--- src/game/Mail.h	(revision 4909)+++ src/game/Mail.h	(working copy)@@ -18,6 +18,8 @@ #ifndef MANGOS_MAIL_H #define MANGOS_MAIL_H +#include <map>+ #define MAIL_BODY_ITEM_TEMPLATE 8383                        // - plain letter, A Dusty Unsent Letter: 889  enum MAIL_RESPONSE@@ -96,6 +98,79 @@     uint32 item_template; }; +struct MailItem+{+    MailItem() : item(NULL) {}+    uint8 item_slot;                                    // slot in mail+    uint16 item_pos;                                    // inventory pos+    uint64 item_guid;                                   // item guid+    uint32 item_template;                               // item entry+    Item *item;                                         // item pointer+    +    void deleteItem()+    {+        if(item)+        {+            delete item;+            item=NULL;+        }+    }+};++typedef std::map<uint64, MailItem> MailItemMap;+++struct MailItemsInfo+{+    MailItemMap i_MailItemMap;                            // Keep the items in a map to avoid duplicate guids (which can happen)++    MailItemMap::iterator begin() { return i_MailItemMap.begin(); }+    MailItemMap::iterator end() { return i_MailItemMap.end(); }++    void AddItem(uint32 guid, uint32 _template, Item *item, uint8 slot = 0, uint16 pos = 0)+    {+        MailItem mailItem;+        mailItem.item_slot = slot;+        mailItem.item_pos = pos;+        mailItem.item_guid = guid;+        mailItem.item_template = _template;+        mailItem.item = item;+        i_MailItemMap[guid] = mailItem;+    }++    void AddItem(uint64 guid, uint8 slot = 0)+    {+        MailItem mailItem;+        mailItem.item_guid = guid;+        mailItem.item_slot = slot;+        i_MailItemMap[guid] = mailItem;+    }+    +    bool hasGuid(uint64 pGuid)+    {+        return(i_MailItemMap.find(pGuid) != i_MailItemMap.end());+    }++    MailItem& getMailItemInfo(uint64 pGuid)+    {+        return i_MailItemMap.find(pGuid)->second;+    }++    uint8 size()+    {+        return i_MailItemMap.size();+    }++    void deleteIncludedItems()+    {+        for(MailItemMap::iterator mailItemIter = begin(); mailItemIter != end(); ++mailItemIter)+        {+            MailItem& mailItem = mailItemIter->second;+            mailItem.deleteItem();+        }+    }+};+ struct Mail {     uint32 messageID;@@ -122,6 +197,15 @@         items.push_back(mii);     } +    void AddAllItems(MailItemsInfo& pMailItemsInfo)+    {+        for(MailItemMap::iterator mailItemIter = pMailItemsInfo.begin(); mailItemIter != pMailItemsInfo.end(); ++mailItemIter)+        {+            MailItem& mailItem = mailItemIter->second;+            AddItem(GUID_LOPART(mailItem.item_guid), mailItem.item_template);+        }+    }+     bool RemoveItem(uint32 itemId)     {         for(std::vector<MailItemInfo>::iterator itr = items.begin(); itr != items.end(); ++itr)@@ -138,28 +222,4 @@     bool HasItems() { return items.empty() ? false : true; } }; -struct MailItemsInfo-{-    uint8 items_count;                                      // item's count-    uint8 item_slot[12];                                    // slot in mail-    uint16 item_pos[12];                                    // inventory pos-    uint64 item_guid[12];                                   // item guid-    uint32 item_template[12];                               // item entry-    Item *items[12];                                        // item pointer--    MailItemsInfo()-    {-        items_count = 0;-    }--    void AddItem(uint32 guid, uint32 _template, Item *item, uint8 slot = 0, uint16 pos = 0)-    {-        item_slot[items_count] = slot;-        item_pos[items_count] = pos;-        item_guid[items_count] = guid;-        item_template[items_count] = _template;-        items[items_count] = item;-        items_count++;-    }-}; #endifIndex: src/game/Player.cpp===================================================================--- src/game/Player.cpp	(revision 4909)+++ src/game/Player.cpp	(working copy)@@ -2344,9 +2344,7 @@      if ( !m_mailsLoaded )     {-        for(uint8 i = 0; i < mi->items_count; ++i)-            if ( mi->items[i] )-                delete mi->items[i];+        mi->deleteIncludedItems();         return;     }     Mail * m = new Mail;@@ -2357,8 +2355,7 @@     m->subject = subject;     m->itemTextId = itemTextId; -    for(uint8 i = 0; i < mi->items_count; ++i)-        m->AddItem(GUID_LOPART(mi->item_guid[i]), mi->item_template[i]);+    m->AddAllItems(*mi);      m->expire_time = expire_time;     m->deliver_time = deliver_time;@@ -2369,9 +2366,12 @@      m_mail.push_front(m);                                   //to insert new mail to beginning of maillist     if(m->HasItems())-        for(uint8 i = 0; i < m->items.size(); ++i)-            if(mi->items[i])-                AddMItem(mi->items[i]);+        for(MailItemMap::iterator mailItemIter = mi->begin(); mailItemIter != mi->end(); ++mailItemIter)+        {+            MailItem& mailItem = mailItemIter->second;+            if(mailItem.item)+                AddMItem(mailItem.item);+        } }  void Player::SendMailResult(uint32 mailId, uint32 mailAction, uint32 mailError, uint32 equipError, uint32 item_guid, uint32 item_count)Index: src/mangosd/Makefile.am===================================================================--- src/mangosd/Makefile.am	(revision 4909)+++ src/mangosd/Makefile.am	(working copy)@@ -33,8 +33,8 @@ 	WorldRunnable.h  ## Link world daemon against the shared library-mangos_worldd_LDADD = ../bindings/universal/libmangosscript.la ../game/libmangosgame.a ../shared/Database/libmangosdatabase.a ../shared/Config/libmangosconfig.a ../shared/Auth/libmangosauth.a ../shared/libmangosshared.a ../shared/vmap/libmangosvmaps.a ../shared/Network/libmangosnetwork.a ../framework/libmangosframework.a ../../dep/src/zthread/libZThread.la ../../dep/src/g3dlite/libg3dlite.a-mangos_worldd_LDFLAGS = -L../../dep/src/zthread  -L../../dep/src/g3dlite -L../bindings/universal/ $(MYSQL_LIBS) $(POSTGRE_LIBS) -L$(libdir) $(ZLIB) $(COMPATLIB) $(SSLLIB) -export-dynamic+mangos_worldd_LDADD = ../bindings/ScriptDev2/libmangosscript.la ../game/libmangosgame.a ../shared/Database/libmangosdatabase.a ../shared/Config/libmangosconfig.a ../shared/Auth/libmangosauth.a ../shared/libmangosshared.a ../shared/vmap/libmangosvmaps.a ../shared/Network/libmangosnetwork.a ../framework/libmangosframework.a ../../dep/src/zthread/libZThread.la ../../dep/src/g3dlite/libg3dlite.a+mangos_worldd_LDFLAGS = -L../../dep/src/zthread  -L../../dep/src/g3dlite -L../bindings/ScriptDev2/ $(MYSQL_LIBS) $(POSTGRE_LIBS) -L$(libdir) $(ZLIB) $(COMPATLIB) $(SSLLIB) -export-dynamic  ## Additional files to include when running 'make dist' #  Include world daemon configurationIndex: src/shared/Network/Socket.cpp===================================================================--- src/shared/Network/Socket.cpp	(revision 4909)+++ src/shared/Network/Socket.cpp	(working copy)@@ -345,6 +345,15 @@ 			SetCloseAndDelete(); 			return INVALID_SOCKET; 		}++        optval = 1;+        if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *)&optval, sizeof(optval)) == -1)+        {+            Handler().LogError(this, "setsockopt(IPPROTO_TCP, TCP_NODELAY)", Errno, StrError(Errno), LOG_LEVEL_FATAL);+            closesocket(s);+            SetCloseAndDelete();+            return INVALID_SOCKET;+        } 	} 	return s; }@@ -1254,3 +1263,5 @@   ++