diff options
-rw-r--r-- | sql/base/characters_database.sql | 11 | ||||
-rw-r--r-- | sql/updates/9090_item_instance.sql | 87 | ||||
-rw-r--r-- | src/server/game/AuctionHouse/AuctionHouseMgr.cpp | 9 | ||||
-rw-r--r-- | src/server/game/Entities/Item/Container/Bag.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Entities/Item/Container/Bag.h | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Item/Item.cpp | 143 | ||||
-rw-r--r-- | src/server/game/Entities/Item/Item.h | 4 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 18 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Object.h | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 44 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 1 | ||||
-rw-r--r-- | src/server/game/Guilds/Guild.cpp | 14 | ||||
-rw-r--r-- | src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp | 2 |
13 files changed, 236 insertions, 104 deletions
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql index 7bd03bffb07..07ae8a0359a 100644 --- a/sql/base/characters_database.sql +++ b/sql/base/characters_database.sql @@ -1711,7 +1711,16 @@ DROP TABLE IF EXISTS `item_instance`; CREATE TABLE `item_instance` ( `guid` int(11) unsigned NOT NULL default '0', `owner_guid` int(11) unsigned NOT NULL default '0', - `data` longtext, + `creatorGuid` int(10) unsigned NOT NULL default '0', + `giftCreatorGuid` int(10) unsigned NOT NULL default '0', + `count` int(10) unsigned NOT NULL default '1', + `duration` int(10) unsigned NOT NULL default '0', + `charges` text NOT NULL, + `flags` int(10) unsigned NOT NULL default '0', + `enchantments` text NOT NULL, + `randomPropertyId` int(11) NOT NULL default '0', + `durability` int(10) unsigned NOT NULL default '0', + `playedTime` int(10) unsigned NOT NULL default '0'; `text` longtext, PRIMARY KEY (`guid`), KEY `idx_owner_guid` (`owner_guid`) diff --git a/sql/updates/9090_item_instance.sql b/sql/updates/9090_item_instance.sql new file mode 100644 index 00000000000..89301903d2d --- /dev/null +++ b/sql/updates/9090_item_instance.sql @@ -0,0 +1,87 @@ +-- Add new fields +ALTER TABLE `item_instance` + ADD `creatorGuid` int(10) unsigned NOT NULL default '0' AFTER `owner_guid`, + ADD `giftCreatorGuid` int(10) unsigned NOT NULL default '0' AFTER `creatorGuid`, + ADD `count` int(10) unsigned NOT NULL default '1' AFTER `giftCreatorGuid`, + ADD `duration` int(10) unsigned NOT NULL AFTER `count`, + ADD `charges` text NOT NULL AFTER `duration`, + ADD `flags` int(10) unsigned NOT NULL default '0' AFTER `charges`, + ADD `enchantments` text NOT NULL AFTER `flags`, + ADD `randomPropertyId` int(11) NOT NULL default '0' AFTER `enchantments`, + ADD `durability` int(10) unsigned NOT NULL default '0' AFTER `randomPropertyId`, + ADD `playedTime` int(10) unsigned NOT NULL default '0' AFTER `durability`; + +-- Function to convert ints from unsigned to signed +DROP FUNCTION IF EXISTS `uint32toint32`; +CREATE FUNCTION `uint32toint32`(input INT(10) UNSIGNED) RETURNS INT(11) SIGNED DETERMINISTIC +BEGIN + RETURN input; +END; + +-- Move data to new fields +UPDATE `item_instance` SET +`creatorGuid` = SUBSTRING(`data`, +length(SUBSTRING_INDEX(`data`,' ',10))+2, +length(SUBSTRING_INDEX(`data`,' ',10+1))-length(SUBSTRING_INDEX(data,' ',10))-1), + +`giftCreatorGuid` = SUBSTRING(`data`, +length(SUBSTRING_INDEX(`data`,' ',12))+2, +length(SUBSTRING_INDEX(`data`,' ',12+1))-length(SUBSTRING_INDEX(data,' ',12))-1), + +`count` = SUBSTRING(`data`, +length(SUBSTRING_INDEX(`data`,' ',14))+2, +length(SUBSTRING_INDEX(`data`,' ',14+1))-length(SUBSTRING_INDEX(data,' ',14))-1), + +`duration` = SUBSTRING(`data`, +length(SUBSTRING_INDEX(`data`,' ',15))+2, +length(SUBSTRING_INDEX(`data`,' ',15+1))-length(SUBSTRING_INDEX(data,' ',15))-1), + +`charges` = CONCAT_WS(' ', +uint32toint32(SUBSTRING(`data`, +length(SUBSTRING_INDEX(`data`,' ',16))+2, +length(SUBSTRING_INDEX(`data`,' ',16+1))-length(SUBSTRING_INDEX(data,' ',16))-1)), +uint32toint32(SUBSTRING(`data`, +length(SUBSTRING_INDEX(`data`,' ',17))+2, +length(SUBSTRING_INDEX(`data`,' ',17+1))-length(SUBSTRING_INDEX(data,' ',17))-1)), +uint32toint32(SUBSTRING(`data`, +length(SUBSTRING_INDEX(`data`,' ',18))+2, +length(SUBSTRING_INDEX(`data`,' ',18+1))-length(SUBSTRING_INDEX(data,' ',18))-1)), +uint32toint32(SUBSTRING(`data`, +length(SUBSTRING_INDEX(`data`,' ',19))+2, +length(SUBSTRING_INDEX(`data`,' ',19+1))-length(SUBSTRING_INDEX(data,' ',19))-1)), +uint32toint32(SUBSTRING(`data`, +length(SUBSTRING_INDEX(`data`,' ',20))+2, +length(SUBSTRING_INDEX(`data`,' ',20+1))-length(SUBSTRING_INDEX(data,' ',20))-1))), + +`flags` = SUBSTRING(`data`, +length(SUBSTRING_INDEX(`data`,' ',21))+2, +length(SUBSTRING_INDEX(`data`,' ',21+1))-length(SUBSTRING_INDEX(data,' ',21))-1), + +`enchantments` = SUBSTRING(`data`, +length(SUBSTRING_INDEX(`data`,' ',22))+2, +length(SUBSTRING_INDEX(`data`,' ',57+1))-length(SUBSTRING_INDEX(data,' ',22))-1), + +`randomPropertyId` = uint32toint32(SUBSTRING(`data`, +length(SUBSTRING_INDEX(`data`,' ',58))+2, +length(SUBSTRING_INDEX(`data`,' ',58+1))-length(SUBSTRING_INDEX(data,' ',58))-1)), + +`durability` = SUBSTRING(`data`, +length(SUBSTRING_INDEX(`data`,' ',60))+2, +length(SUBSTRING_INDEX(`data`,' ',60+1))-length(SUBSTRING_INDEX(data,' ',60))-1), + +`playedTime` = SUBSTRING(`data`, +length(SUBSTRING_INDEX(`data`,' ',62))+2, +length(SUBSTRING_INDEX(`data`,' ',62+1))-length(SUBSTRING_INDEX(data,' ',62))-1); + +-- Drop function +DROP FUNCTION IF EXISTS `uint32toint32`; + +-- Fix heroic item flag +UPDATE `item_instance` SET `flags`=`flags`&~0x8 WHERE +SUBSTRING(`data`, +length(SUBSTRING_INDEX(`data`,' ',3))+2, +length(SUBSTRING_INDEX(`data`,' ',3+1))-length(SUBSTRING_INDEX(data,' ',3))-1) +NOT IN (5043,5044,17302,17305,17308,21831); + +-- Drop old field +ALTER TABLE `item_instance` DROP `data`; diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp index 95e1fb5e931..544626c1f79 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp @@ -257,7 +257,8 @@ void AuctionHouseMgr::SendAuctionExpiredMail(AuctionEntry * auction) void AuctionHouseMgr::LoadAuctionItems() { // data needs to be at first place for Item::LoadFromDB - QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT data, text, itemguid, item_template FROM auctionhouse JOIN item_instance ON itemguid = guid"); + // 0 1 2 3 4 5 6 7 8 9 10 11 12 + QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, itemguid, item_template FROM auctionhouse JOIN item_instance ON itemguid = guid"); if (!result) { @@ -278,8 +279,8 @@ void AuctionHouseMgr::LoadAuctionItems() bar.step(); fields = result->Fetch(); - uint32 item_guid = fields[2].GetUInt32(); - uint32 item_template = fields[3].GetUInt32(); + uint32 item_guid = fields[11].GetUInt32(); + uint32 item_template = fields[12].GetUInt32(); ItemPrototype const *proto = objmgr.GetItemPrototype(item_template); @@ -291,7 +292,7 @@ void AuctionHouseMgr::LoadAuctionItems() Item *item = NewItemOrBag(proto); - if (!item->LoadFromDB(item_guid,0, result)) + if (!item->LoadFromDB(item_guid, 0, result, item_template)) { delete item; continue; diff --git a/src/server/game/Entities/Item/Container/Bag.cpp b/src/server/game/Entities/Item/Container/Bag.cpp index 12fd9efee28..9774c46c011 100644 --- a/src/server/game/Entities/Item/Container/Bag.cpp +++ b/src/server/game/Entities/Item/Container/Bag.cpp @@ -108,9 +108,9 @@ void Bag::SaveToDB() Item::SaveToDB(); } -bool Bag::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult_AutoPtr result) +bool Bag::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult_AutoPtr result, uint32 entry) { - if (!Item::LoadFromDB(guid, owner_guid, result)) + if (!Item::LoadFromDB(guid, owner_guid, result, entry)) return false; // cleanup bag content related item value fields (its will be filled correctly from `character_inventory`) diff --git a/src/server/game/Entities/Item/Container/Bag.h b/src/server/game/Entities/Item/Container/Bag.h index 5bc2480fc47..4937b307547 100644 --- a/src/server/game/Entities/Item/Container/Bag.h +++ b/src/server/game/Entities/Item/Container/Bag.h @@ -55,7 +55,7 @@ class Bag : public Item // overwrite virtual Item::SaveToDB void SaveToDB(); // overwrite virtual Item::LoadFromDB - bool LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult_AutoPtr result); + bool LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult_AutoPtr result, uint32 entry); // overwrite virtual Item::DeleteFromDB void DeleteFromDB(); diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp index 52d9daeb4c8..0c2c460cc73 100644 --- a/src/server/game/Entities/Item/Item.cpp +++ b/src/server/game/Entities/Item/Item.cpp @@ -314,10 +314,29 @@ void Item::SaveToDB() std::string text = m_text; CharacterDatabase.escape_string(text); std::ostringstream ss; - ss << "REPLACE INTO item_instance (guid, owner_guid, data, text) VALUES (" << guid << "," << GUID_LOPART(GetOwnerGUID()) << ",'"; - for (uint16 i = 0; i < m_valuesCount; ++i) - ss << GetUInt32Value(i) << " "; - ss << "', '" << text << "')"; + ss << "REPLACE INTO item_instance (guid,owner_guid,creatorGuid,giftCreatorGuid,count,duration,charges,flags,enchantments,randomPropertyId,durability,playedTime,text) VALUES ("; + ss << guid << ","; + ss << GUID_LOPART(GetOwnerGUID()) << ","; + ss << GUID_LOPART(GetUInt64Value(ITEM_FIELD_CREATOR)) << ","; + ss << GUID_LOPART(GetUInt64Value(ITEM_FIELD_GIFTCREATOR)) << ","; + ss << GetCount() << ","; + ss << GetUInt32Value(ITEM_FIELD_DURATION) << ",'"; + for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + ss << GetSpellCharges(i) << " "; + + ss << "'," << GetUInt32Value(ITEM_FIELD_FLAGS) << ",'"; + for (uint8 i = 0; i < MAX_ENCHANTMENT_SLOT; ++i) + { + ss << GetEnchantmentId(EnchantmentSlot(i)) << " "; + ss << GetEnchantmentDuration(EnchantmentSlot(i)) << " "; + ss << GetEnchantmentCharges(EnchantmentSlot(i)) << " "; + } + + ss << "'," << GetItemRandomPropertyId() << ","; + ss << GetUInt32Value(ITEM_FIELD_DURABILITY) << ","; + ss << GetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME) << ","; + ss << ",'" << text << "')"; + CharacterDatabase.Execute(ss.str().c_str()); }break; case ITEM_CHANGED: @@ -325,11 +344,28 @@ void Item::SaveToDB() std::string text = m_text; CharacterDatabase.escape_string(text); std::ostringstream ss; - ss << "UPDATE item_instance SET data = '"; - for (uint16 i = 0; i < m_valuesCount; ++i) - ss << GetUInt32Value(i) << " "; - ss << "', owner_guid = '" << GUID_LOPART(GetOwnerGUID()); - ss << "', text = '" << text << "' WHERE guid = '" << guid << "'"; + ss << "UPDATE item_instance SET owner_guid = " << GUID_LOPART(GetOwnerGUID()); + ss << ", creatorGuid = " << GUID_LOPART(GetUInt64Value(ITEM_FIELD_CREATOR)); + ss << ", giftCreatorGuid = " << GUID_LOPART(GetUInt64Value(ITEM_FIELD_GIFTCREATOR)); + ss << ", count = " << GetCount(); + ss << ", duration = " << GetUInt32Value(ITEM_FIELD_DURATION); + ss << ", charges = '"; + for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + ss << GetSpellCharges(i) << " "; + + ss << "', flags = " << GetUInt32Value(ITEM_FIELD_FLAGS); + ss << ", enchantments = '"; + for (uint8 i = 0; i < MAX_ENCHANTMENT_SLOT; ++i) + { + ss << GetEnchantmentId(EnchantmentSlot(i)) << " "; + ss << GetEnchantmentDuration(EnchantmentSlot(i)) << " "; + ss << GetEnchantmentCharges(EnchantmentSlot(i)) << " "; + } + + ss << "', randomPropertyId = " << GetItemRandomPropertyId(); + ss << ", durability = " << GetUInt32Value(ITEM_FIELD_DURABILITY); + ss << ", playedTime = " << GetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME); + ss << ", text = '" << text << "' WHERE guid = " << guid; CharacterDatabase.Execute(ss.str().c_str()); @@ -350,73 +386,72 @@ void Item::SaveToDB() SetState(ITEM_UNCHANGED); } -bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult_AutoPtr result) +bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult_AutoPtr result, uint32 entry) { // create item before any checks for store correct guid // and allow use "FSetState(ITEM_REMOVED); SaveToDB();" for deleting item from DB Object::_Create(guid, 0, HIGHGUID_ITEM); - if (!result) - result = CharacterDatabase.PQuery("SELECT data FROM item_instance WHERE guid = '%u'", guid); - - if (!result) - { - sLog.outError("Item (GUID: %u owner: %u) not found in table `item_instance`, can't load. ",guid,GUID_LOPART(owner_guid)); + SetEntry(entry); + ItemPrototype const* proto = GetProto(); + if (!proto) return false; - } - Field *fields = result->Fetch(); + //if (!result) // 0 1 2 3 4 5 6 7 8 9 10 + // result = CharacterDatabase.PQuery("SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text FROM item_instance WHERE guid = '%u'", guid); - if (!LoadValues(fields[0].GetString())) + if (!result) { - sLog.outError("Item #%d have broken data in `data` field. Can't be loaded.",guid); + sLog.outError("Item (GUID: %u owner: %u) not found in table `item_instance`, can't load. ", guid, GUID_LOPART(owner_guid)); return false; } + Field *fields = result->Fetch(); bool need_save = false; // need explicit save data at load fixes + SetUInt64Value(ITEM_FIELD_CREATOR, MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER)); + SetUInt64Value(ITEM_FIELD_GIFTCREATOR, MAKE_NEW_GUID(fields[1].GetUInt32(), 0, HIGHGUID_PLAYER)); + SetCount(fields[2].GetUInt32()); - // overwrite possible wrong/corrupted guid - uint64 new_item_guid = MAKE_NEW_GUID(guid,0, HIGHGUID_ITEM); - if (GetUInt64Value(OBJECT_FIELD_GUID) != new_item_guid) + uint32 duration = fields[3].GetUInt32(); + SetUInt32Value(ITEM_FIELD_DURATION, duration); + // update duration if need, and remove if not need + if ((proto->Duration == 0) != (duration == 0)) { - SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid,0, HIGHGUID_ITEM)); + SetUInt32Value(ITEM_FIELD_DURATION, abs(proto->Duration)); need_save = true; } - ItemPrototype const* proto = GetProto(); - if (!proto) - return false; + Tokens tokens = StrSplit(fields[4].GetCppString(), " "); + if (tokens.size() == MAX_ITEM_PROTO_SPELLS) + for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + SetSpellCharges(i, atoi(tokens[i].c_str())); - // update max durability (and durability) if need - if (proto->MaxDurability!= GetUInt32Value(ITEM_FIELD_MAXDURABILITY)) + SetUInt32Value(ITEM_FIELD_FLAGS, fields[5].GetUInt32()); + // Remove bind flag for items vs NO_BIND set + if (IsSoulBound() && proto->Bonding == NO_BIND) { - SetUInt32Value(ITEM_FIELD_MAXDURABILITY,proto->MaxDurability); - if (GetUInt32Value(ITEM_FIELD_DURABILITY) > proto->MaxDurability) - SetUInt32Value(ITEM_FIELD_DURABILITY,proto->MaxDurability); - + ApplyModFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_BINDED, false); need_save = true; } + _LoadIntoDataField(fields[6].GetString(), ITEM_FIELD_ENCHANTMENT_1_1, MAX_ENCHANTMENT_SLOT * MAX_ENCHANTMENT_OFFSET); + SetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID, fields[7].GetInt32()); // recalculate suffix factor if (GetItemRandomPropertyId() < 0) - { - if (UpdateItemSuffixFactor()) - need_save = true; - } + UpdateItemSuffixFactor(); - // Remove bind flag for items vs NO_BIND set - if (IsSoulBound() && proto->Bonding == NO_BIND) + uint32 durability = fields[8].GetUInt32(); + SetUInt32Value(ITEM_FIELD_DURABILITY, durability); + // update max durability (and durability) if need + SetUInt32Value(ITEM_FIELD_MAXDURABILITY, proto->MaxDurability); + if (durability > proto->MaxDurability) { - ApplyModFlag(ITEM_FIELD_FLAGS,ITEM_FLAGS_BINDED, false); + SetUInt32Value(ITEM_FIELD_DURABILITY, proto->MaxDurability); need_save = true; } - // update duration if need, and remove if not need - if ((proto->Duration == 0) != (GetUInt32Value(ITEM_FIELD_DURATION) == 0)) - { - SetUInt32Value(ITEM_FIELD_DURATION,abs(proto->Duration)); - need_save = true; - } + SetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME, fields[9].GetUInt32()); + SetText(fields[10].GetCppString()); // set correct owner if (owner_guid != 0 && GetOwnerGUID() != owner_guid) @@ -428,10 +463,11 @@ bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult_AutoPtr result if (need_save) // normal item changed state set not work at loading { std::ostringstream ss; - ss << "UPDATE item_instance SET data = '"; - for (uint16 i = 0; i < m_valuesCount; ++i) - ss << GetUInt32Value(i) << " "; - ss << "', owner_guid = '" << GUID_LOPART(GetOwnerGUID()) << "' WHERE guid = '" << guid << "'"; + ss << "UPDATE item_instance SET duration = " << GetUInt32Value(ITEM_FIELD_DURABILITY) + << ", flags = " << GetUInt32Value(ITEM_FIELD_FLAGS) + << ", durability = " << GetUInt32Value(ITEM_FIELD_DURABILITY) + << ", owner_guid = " << GUID_LOPART(GetOwnerGUID()) + << " WHERE guid = " << guid; CharacterDatabase.Execute(ss.str().c_str()); } @@ -620,13 +656,12 @@ void Item::SetItemRandomProperties(int32 randomPropId) } } -bool Item::UpdateItemSuffixFactor() +void Item::UpdateItemSuffixFactor() { uint32 suffixFactor = GenerateEnchSuffixFactor(GetEntry()); if (GetItemSuffixFactor() == suffixFactor) - return false; - SetUInt32Value(ITEM_FIELD_PROPERTY_SEED,suffixFactor); - return true; + return; + SetUInt32Value(ITEM_FIELD_PROPERTY_SEED, suffixFactor); } void Item::SetState(ItemUpdateState state, Player *forplayer) diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h index ffdbfb07201..400ce86ef68 100644 --- a/src/server/game/Entities/Item/Item.h +++ b/src/server/game/Entities/Item/Item.h @@ -240,7 +240,7 @@ class Item : public Object bool IsBindedNotWith(Player const* player) const; bool IsBoundByEnchant() const; virtual void SaveToDB(); - virtual bool LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult_AutoPtr result); + virtual bool LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult_AutoPtr result, uint32 entry); virtual void DeleteFromDB(); void DeleteFromInventoryDB(); void SaveRefundDataToDB(); @@ -284,7 +284,7 @@ class Item : public Object int32 GetItemRandomPropertyId() const { return GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID); } uint32 GetItemSuffixFactor() const { return GetUInt32Value(ITEM_FIELD_PROPERTY_SEED); } void SetItemRandomProperties(int32 randomPropId); - bool UpdateItemSuffixFactor(); + void UpdateItemSuffixFactor(); static int32 GenerateItemRandomPropertyId(uint32 item_id); void SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges); void SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration, Player* owner); diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 88396fda4c9..f173e48a254 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -769,6 +769,24 @@ bool Object::LoadValues(const char* data) return true; } +void Object::_LoadIntoDataField(const char* data, uint32 startOffset, uint32 count) +{ + if (!data) + return; + + Tokens tokens = StrSplit(data, " "); + + if (tokens.size() != count) + return; + + Tokens::iterator iter; + uint32 index; + for (iter = tokens.begin(), index = 0; index < count; ++iter, ++index) + { + m_uint32Values[startOffset + index] = atol((*iter).c_str()); + } +} + void Object::_SetUpdateBits(UpdateMask *updateMask, Player* /*target*/) const { uint32 *value = m_uint32Values; diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 0129e30b952..1d900a0bbc7 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -329,6 +329,7 @@ class Object void _InitValues(); void _Create (uint32 guidlow, uint32 entry, HighGuid guidhigh); + void _LoadIntoDataField(const char* data, uint32 startOffset, uint32 count); virtual void _SetUpdateBits(UpdateMask *updateMask, Player *target) const; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 4cee9f5b5fa..25c4bebe2ce 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -4434,15 +4434,15 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC if (has_items) { // Data needs to be at first place for Item::LoadFromDB - QueryResult_AutoPtr resultItems = CharacterDatabase.PQuery("SELECT data,text,item_guid,item_template FROM mail_items JOIN item_instance ON item_guid = guid WHERE mail_id='%u'", mail_id); + QueryResult_AutoPtr resultItems = CharacterDatabase.PQuery("SELECT creatorGuid,giftCreatorGuid,count,duration,charges,flags,enchantments,randomPropertyId,durability,playedTime,text,item_guid,item_template FROM mail_items JOIN item_instance ON item_guid = guid WHERE mail_id='%u'", mail_id); if (resultItems) { do { Field *fields2 = resultItems->Fetch(); - uint32 item_guidlow = fields2[2].GetUInt32(); - uint32 item_template = fields2[3].GetUInt32(); + uint32 item_guidlow = fields2[11].GetUInt32(); + uint32 item_template = fields2[12].GetUInt32(); ItemPrototype const* itemProto = objmgr.GetItemPrototype(item_template); if (!itemProto) @@ -4452,7 +4452,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC } Item *pItem = NewItemOrBag(itemProto); - if (!pItem->LoadFromDB(item_guidlow, MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER),resultItems)) + if (!pItem->LoadFromDB(item_guidlow, MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER), resultItems, item_template)) { pItem->FSetState(ITEM_REMOVED); pItem->SaveToDB(); // it also deletes item object! @@ -15864,24 +15864,6 @@ float Player::GetFloatValueFromArray(Tokens const& data, uint16 index) return result; } -void Player::_LoadIntoDataField(const char* data, uint32 startOffset, uint32 count) -{ - if (!data) - return; - - Tokens tokens = StrSplit(data, " "); - - if (tokens.size() != count) - return; - - Tokens::iterator iter; - uint32 index; - for (iter = tokens.begin(), index = 0; index < count; ++iter, ++index) - { - m_uint32Values[startOffset + index] = atol((*iter).c_str()); - } -} - bool Player::LoadFromDB(uint32 guid, SqlQueryHolder *holder) { //// 0 1 2 3 4 5 6 7 8 9 10 11 @@ -16733,10 +16715,10 @@ void Player::_LoadInventory(QueryResult_AutoPtr result, uint32 timediff) do { Field *fields = result->Fetch(); - uint32 bag_guid = fields[2].GetUInt32(); - uint8 slot = fields[3].GetUInt8(); - uint32 item_guid = fields[4].GetUInt32(); - uint32 item_id = fields[5].GetUInt32(); + uint32 bag_guid = fields[11].GetUInt32(); + uint8 slot = fields[12].GetUInt8(); + uint32 item_guid = fields[13].GetUInt32(); + uint32 item_id = fields[14].GetUInt32(); ItemPrototype const * proto = objmgr.GetItemPrototype(item_id); @@ -16750,7 +16732,7 @@ void Player::_LoadInventory(QueryResult_AutoPtr result, uint32 timediff) Item *item = NewItemOrBag(proto); - if (!item->LoadFromDB(item_guid, GetGUID(), result)) + if (!item->LoadFromDB(item_guid, GetGUID(), result, item_id)) { sLog.outError("Player::_LoadInventory: Player %s has broken item (id: #%u) in inventory, deleted.", GetName(),item_id); CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item = '%u'", item_guid); @@ -16909,15 +16891,15 @@ void Player::_LoadInventory(QueryResult_AutoPtr result, uint32 timediff) void Player::_LoadMailedItems(Mail *mail) { // data needs to be at first place for Item::LoadFromDB - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT data, text, item_guid, item_template FROM mail_items JOIN item_instance ON item_guid = guid WHERE mail_id='%u'", mail->messageID); + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, item_guid, item_template FROM mail_items JOIN item_instance ON item_guid = guid WHERE mail_id='%u'", mail->messageID); if (!result) return; do { Field *fields = result->Fetch(); - uint32 item_guid_low = fields[2].GetUInt32(); - uint32 item_template = fields[3].GetUInt32(); + uint32 item_guid_low = fields[11].GetUInt32(); + uint32 item_template = fields[12].GetUInt32(); mail->AddItem(item_guid_low, item_template); @@ -16933,7 +16915,7 @@ void Player::_LoadMailedItems(Mail *mail) Item *item = NewItemOrBag(proto); - if (!item->LoadFromDB(item_guid_low, 0, result)) + if (!item->LoadFromDB(item_guid_low, 0, result, item_template)) { sLog.outError("Player::_LoadMailedItems - Item in mail (%u) doesn't exist !!!! - item guid: %u, deleted from mail", mail->messageID, item_guid_low); CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid = '%u'", item_guid_low); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 82efe19e3c7..cdcd20910ea 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2410,7 +2410,6 @@ class Player : public Unit, public GridObject<Player> void _LoadBGData(QueryResult_AutoPtr result); void _LoadGlyphs(QueryResult_AutoPtr result); void _LoadTalents(QueryResult_AutoPtr result); - void _LoadIntoDataField(const char* data, uint32 startOffset, uint32 count); /*********************************************************/ /*** SAVE SYSTEM ***/ diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index 514398dc62f..03eec31535e 100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -1140,18 +1140,18 @@ void Guild::LoadGuildBankFromDB() } while (result->NextRow()); // data needs to be at first place for Item::LoadFromDB - // 0 1 2 3 4 - result = CharacterDatabase.PQuery("SELECT data, text, TabId, SlotId, item_guid, item_entry FROM guild_bank_item JOIN item_instance ON item_guid = guid WHERE guildid='%u' ORDER BY TabId", m_Id); + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + result = CharacterDatabase.PQuery("SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, TabId, SlotId, item_guid, item_entry FROM guild_bank_item JOIN item_instance ON item_guid = guid WHERE guildid='%u' ORDER BY TabId", m_Id); if (!result) return; do { Field *fields = result->Fetch(); - uint8 TabId = fields[2].GetUInt8(); - uint8 SlotId = fields[3].GetUInt8(); - uint32 ItemGuid = fields[4].GetUInt32(); - uint32 ItemEntry = fields[5].GetUInt32(); + uint8 TabId = fields[11].GetUInt8(); + uint8 SlotId = fields[12].GetUInt8(); + uint32 ItemGuid = fields[13].GetUInt32(); + uint32 ItemEntry = fields[14].GetUInt32(); if (TabId >= m_PurchasedTabs || TabId >= GUILD_BANK_MAX_TABS) { @@ -1174,7 +1174,7 @@ void Guild::LoadGuildBankFromDB() } Item *pItem = NewItemOrBag(proto); - if (!pItem->LoadFromDB(ItemGuid, 0, result)) + if (!pItem->LoadFromDB(ItemGuid, 0, result, ItemEntry)) { CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE guildid='%u' AND TabId='%u' AND SlotId='%u'", m_Id, uint32(TabId), uint32(SlotId)); sLog.outError("Item GUID %u not found in item_instance, deleting from Guild Bank!", ItemGuid); diff --git a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp index 9d9132ae3c3..66dc2ddb3f6 100644 --- a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp @@ -78,7 +78,7 @@ bool LoginQueryHolder::Initialize() res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS,"SELECT quest,time FROM character_queststatus_daily WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADWEKLYQUESTSTATUS,"SELECT quest FROM character_queststatus_weekly WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADREPUTATION, "SELECT faction,standing,flags FROM character_reputation WHERE guid = '%u'", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADINVENTORY, "SELECT data,text,bag,slot,item,item_template FROM character_inventory JOIN item_instance ON character_inventory.item = item_instance.guid WHERE character_inventory.guid = '%u' ORDER BY bag,slot", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADINVENTORY, "SELECT creatorGuid,giftCreatorGuid,count,duration,charges,flags,enchantments,randomPropertyId,durability,playedTime,text,bag,slot,item,item_template FROM character_inventory JOIN item_instance ON character_inventory.item = item_instance.guid WHERE character_inventory.guid = '%u' ORDER BY bag,slot", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADACTIONS, "SELECT a.button,a.action,a.type FROM character_action as a, characters as c WHERE a.guid = c.guid AND a.spec = c.activespec AND a.guid = '%u' ORDER BY button", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADMAILCOUNT, "SELECT COUNT(id) FROM mail WHERE receiver = '%u' AND (checked & 1)=0 AND deliver_time <= '" UI64FMTD "'", GUID_LOPART(m_guid),(uint64)time(NULL)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADMAILDATE, "SELECT MIN(deliver_time) FROM mail WHERE receiver = '%u' AND (checked & 1)=0", GUID_LOPART(m_guid)); |