rendered paste bodyIndex: src/shared/Database/Database.h
===================================================================
--- src/shared/Database/Database.h (révision 5105)
+++ src/shared/Database/Database.h (copie de travail)
@@ -59,10 +59,14 @@
bool AsyncQuery(Class *object, void (Class::*method)(QueryResult*), const char *sql);
template<class Class, typename ParamType1>
bool AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql);
+ template<class Class, typename ParamType1, typename ParamType2, typename ParamType3>
+ bool AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql);
template<class Class>
bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult*), const char *format,...) ATTR_PRINTF(4,5);
template<class Class, typename ParamType1>
bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...) ATTR_PRINTF(5,6);
+ template<class Class, typename ParamType1, typename ParamType2, typename ParamType3>
+ bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...) ATTR_PRINTF(5,6);
template<class Class>
bool DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*), SqlQueryHolder *holder);
template<class Class, typename ParamType1>
Index: src/shared/Database/DatabaseImpl.h
===================================================================
--- src/shared/Database/DatabaseImpl.h (révision 5105)
+++ src/shared/Database/DatabaseImpl.h (copie de travail)
@@ -45,6 +45,18 @@
return true;
}
+template<class Class, typename ParamType1, typename ParamType2, typename ParamType3>
+bool
+Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql)
+{
+ if (!sql) return false;
+ ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current();
+ QueryQueues::iterator itr = m_queryQueues.find(queryThread);
+ if (itr == m_queryQueues.end()) return false;
+ m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback<Class, ParamType1, ParamType2, ParamType3>(object, method, (QueryResult*)NULL, param1, param2, param3), itr->second));
+ return true;
+}
+
template<class Class>
bool
Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult*), const char *format,...)
@@ -87,6 +99,28 @@
return AsyncQuery(object, method, param1, szQuery);
}
+
+template<class Class, typename ParamType1, typename ParamType2, typename ParamType3>
+bool
+Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...)
+{
+ if(!format) return false;
+
+ va_list ap;
+ char szQuery [MAX_QUERY_LEN];
+ va_start(ap, format);
+ int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap );
+ va_end(ap);
+
+ if(res==-1)
+ {
+ sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
+ return false;
+ }
+
+ return AsyncQuery(object, method, param1, param2, param3, szQuery);
+}
+
template<class Class>
bool
Database::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*), SqlQueryHolder *holder)
Index: src/game/Player.cpp
===================================================================
--- src/game/Player.cpp (révision 5105)
+++ src/game/Player.cpp (copie de travail)
@@ -14077,27 +14065,43 @@
tokens[index] = buf;
}
-void Player::SetUInt32ValueInDB(uint16 index, uint32 value, uint64 guid)
+class PlayerCallback
{
- Tokens tokens;
- if(!LoadValuesArrayFromDB(tokens,guid))
- return;
+ public:
+ void CallbackSetUInt32ValueInDB(QueryResult* result, uint16 index, uint32 value, uint64 guid)
+ {
+ if(!result)
+ return;
+
+ Tokens tokens;
+
+ Field *fields = result->Fetch();
- if(index >= tokens.size())
- return;
+ tokens = StrSplit(fields[0].GetCppString(), " ");
- char buf[11];
- snprintf(buf,11,"%u",value);
- tokens[index] = buf;
+ delete result;
- SaveValuesArrayInDB(tokens,guid);
+ if(index >= tokens.size())
+ return;
+
+ char buf[11];
+ snprintf(buf,11,"%u",value);
+ tokens[index] = buf;
+
+ Player::SaveValuesArrayInDB(tokens,guid);
+ }
+} pCallback;
+
+void Player::SetUInt32ValueInDB(uint16 index, uint32 value, uint64 guid)
+{
+ CharacterDatabase.AsyncPQuery(&pCallback, &PlayerCallback::CallbackSetUInt32ValueInDB, index, value, guid, "SELECT `data` FROM `character` WHERE `guid`='%u'", GUID_LOPART(guid));
}
void Player::SetFloatValueInDB(uint16 index, float value, uint64 guid)
{
uint32 temp;
memcpy(&temp, &value, sizeof(value));
Player::SetUInt32ValueInDB(index, temp, guid);
}
void Player::SendAttackSwingNotStanding()
Index: src/game/ObjectMgr.h
===================================================================
--- src/game/ObjectMgr.h (révision 5105)
+++ src/game/ObjectMgr.h (copie de travail)
@@ -277,6 +277,7 @@
//auction messages
void SendAuctionWonMail( AuctionEntry * auction );
+ void CallbackSendAuctionWonMail(QueryResult *result, AuctionEntry *auction );
void SendAuctionSuccessfulMail( AuctionEntry * auction );
void SendAuctionExpiredMail( AuctionEntry * auction );
uint32 GetAuctionCut( uint32 location, uint32 highBid );
Index: src/game/ObjectMgr.cpp
===================================================================
--- src/game/ObjectMgr.cpp (révision 5105)
+++ src/game/ObjectMgr.cpp (copie de travail)
@@ -37,6 +37,7 @@
#include "GameEvent.h"
#include "Spell.h"
#include "Chat.h"
+#include "Database/DatabaseImpl.h"
INSTANTIATE_SINGLETON_1(ObjectMgr);
@@ -242,49 +243,17 @@
uint64 bidder_guid = MAKE_GUID(auction->bidder,HIGHGUID_PLAYER);
Player *bidder = objmgr.GetPlayer(bidder_guid);
- uint32 bidder_accId = 0;
-
- // data for gm.log
- if( sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
+ // prevent DB access for online player
+ if(bidder)
{
- uint32 bidder_security = 0;
- std::string bidder_name;
- if (bidder)
- {
- bidder_accId = bidder->GetSession()->GetAccountId();
- bidder_security = bidder->GetSession()->GetSecurity();
- bidder_name = bidder->GetName();
- }
- else
- {
- bidder_accId = GetPlayerAccountIdByGUID(bidder_guid);
- bidder_security = GetSecurityByAccount(bidder_accId);
-
- if(bidder_security > SEC_PLAYER ) // not do redundant DB requests
- {
- if(!GetPlayerNameByGUID(bidder_guid,bidder_name))
- bidder_name = LANG_UNKNOWN;
- }
- }
-
- if( bidder_security > SEC_PLAYER )
- {
- std::string owner_name;
- if(!GetPlayerNameByGUID(auction->owner,owner_name))
- owner_name = LANG_UNKNOWN;
-
- uint32 owner_accid = GetPlayerAccountIdByGUID(auction->owner);
-
- sLog.outCommand("GM %s (Account: %u) won item in auction: %s (Entry: %u Count: %u) and pay money: %u. Original owner %s (Account: %u)",
- bidder_name.c_str(),bidder_accId,pItem->GetProto()->Name1,pItem->GetEntry(),pItem->GetCount(),auction->bid,owner_name.c_str(),owner_accid);
- }
+ std::string bidder_name = bidder->GetName();
}
- else if(!bidder)
- bidder_accId = GetPlayerAccountIdByGUID(bidder_guid);
+ else
+ {
+ CharacterDatabase.AsyncPQuery(this, &ObjectMgr::CallbackSendAuctionWonMail, auction, "SELECT `name` FROM `character` WHERE `guid` = '%u'", GUID_LOPART(bidder_guid));
+ return;
+ }
- // receiver exist
- if(bidder || bidder_accId)
- {
std::ostringstream msgAuctionWonSubject;
msgAuctionWonSubject << auction->item_template << ":0:" << AUCTION_WON;
@@ -305,32 +274,74 @@
CharacterDatabase.PExecute("UPDATE `item_instance` SET `owner_guid` = '%u' WHERE `guid`='%u'",auction->bidder,pItem->GetGUIDLow());
CharacterDatabase.CommitTransaction();
- if (bidder)
- {
- bidder->GetSession()->SendAuctionBidderNotification( auction->location, auction->Id, bidder_guid, 0, 0, auction->item_template);
+ bidder->GetSession()->SendAuctionBidderNotification( auction->location, auction->Id, bidder_guid, 0, 0, auction->item_template);
- MailItemsInfo mi;
- mi.AddItem(auction->item_guidlow, auction->item_template, pItem);
- bidder->CreateMail(mailId, MAIL_AUCTION, auction->location, msgAuctionWonSubject.str(), itemTextId, &mi, etime, dtime, 0, 0, AUCTION_CHECKED);
- }
- else
- {
- objmgr.RemoveAItem(pItem->GetGUIDLow()); // we have to remove the item, before we delete it !!
- delete pItem;
- }
+ MailItemsInfo mi;
+ mi.AddItem(auction->item_guidlow, auction->item_template, pItem);
+ bidder->CreateMail(mailId, MAIL_AUCTION, auction->location, msgAuctionWonSubject.str(), itemTextId, &mi, etime, dtime, 0, 0, AUCTION_CHECKED);
+
CharacterDatabase.PExecute("INSERT INTO `mail` (`id`,`messageType`,`sender`,`receiver`,`subject`,`itemTextId`,`has_items`,`expire_time`,`deliver_time`,`money`,`cod`,`checked`) "
"VALUES ('%u', '%d', '%u', '%u', '%s', '%u', '1', '" I64FMTD "','" I64FMTD "', '0', '0', '%d')",
mailId, MAIL_AUCTION, auction->location, auction->bidder, msgAuctionWonSubject.str().c_str(), itemTextId, (uint64)etime, (uint64)dtime, AUCTION_CHECKED);
CharacterDatabase.PExecute("INSERT INTO `mail_items` (`mail_id`,`item_guid`,`item_template`) VALUES ('%u', '%u', '%u')", mailId, auction->item_guidlow, auction->item_template);
- }
- // receiver not exist
- else
+
+}
+
+//does not clear ram
+void ObjectMgr::CallbackSendAuctionWonMail(QueryResult *result, AuctionEntry* auction)
+{
+ if(!result)
+ return;
+
+ if(!auction)
+ return;
+
+ Item *pItem = objmgr.GetAItem(auction->item_guidlow);
+
+ if(!pItem)
+ return;
+
+ uint64 bidder_guid = MAKE_GUID(auction->bidder,HIGHGUID_PLAYER);
+
+ std::string bidder_name = (*result)[0].GetCppString();
+
+ delete result;
+
+ uint32 bidder_accId = GetPlayerAccountIdByGUID(bidder_guid);
+
+ if(bidder_accId)
{
+ std::ostringstream msgAuctionWonSubject;
+ msgAuctionWonSubject << auction->item_template << ":0:" << AUCTION_WON;
+
+ std::ostringstream msgAuctionWonBody;
+ msgAuctionWonBody.width(16);
+ msgAuctionWonBody << std::right << std::hex << auction->owner;
+ msgAuctionWonBody << std::dec << ":" << auction->bid << ":" << auction->buyout;
+ sLog.outDebug( "AuctionWon body string : %s", msgAuctionWonBody.str().c_str() );
+
+ //prepare mail data... :
+ uint32 mailId = this->GenerateMailID();
+ uint32 itemTextId = this->CreateItemText( msgAuctionWonBody.str() );
+ time_t dtime = time(NULL); //Will always be instant when from Auction House.
+ time_t etime = dtime + (30 * DAY);
+
+ // set owner to bidder (to prevent delete item with sender char deleting)
+ // owner in `data` will set at mail receive and item extracting
+ CharacterDatabase.PExecute("UPDATE `item_instance` SET `owner_guid` = '%u' WHERE `guid`='%u'",auction->bidder,pItem->GetGUIDLow());
+ CharacterDatabase.CommitTransaction();
+
+ objmgr.RemoveAItem(pItem->GetGUIDLow()); // we have to remove the item, before we delete it !!
+ delete pItem;
+ }
+ // receiver not exist
+ else
+ {
CharacterDatabase.PExecute("DELETE FROM `item_instance` WHERE `guid`='%u'", pItem->GetGUIDLow());
objmgr.RemoveAItem(pItem->GetGUIDLow()); // we have to remove the item, before we delete it !!
delete pItem;
- }
+ }
}
//call this method to send mail to auction owner, when auction is successful, it does not clear ram
Index: src/framework/Utilities/Callback.h
===================================================================
--- src/framework/Utilities/Callback.h (révision 5105)
+++ src/framework/Utilities/Callback.h (copie de travail)
@@ -23,10 +23,31 @@
namespace MaNGOS
{
- template < class Class, typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void, typename ParamType4 = void >
+
+ template < class Class, typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void, typename ParamType4 = void, typename ParamType5 = void >
class _Callback
{
protected:
+ typedef void (Class::*Method)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5);
+ Class *m_object;
+ Method m_method;
+ ParamType1 m_param1;
+ ParamType2 m_param2;
+ ParamType3 m_param3;
+ ParamType4 m_param4;
+ ParamType5 m_param5;
+ void _Execute() { (m_object->*m_method)(m_param1, m_param2, m_param3, m_param4, m_param5); }
+ public:
+ _Callback(Class *object, Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3, ParamType4 param4, ParamType5 param5)
+ : m_object(object), m_method(method), m_param1(param1), m_param2(param2), m_param3(param3), m_param4(param4), m_param5(param5) {}
+ _Callback(_Callback < Class, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5> const& cb)
+ : m_object(cb.object), m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3), m_param4(cb.m_param4), m_param5(cb.m_param5) {}
+ };
+
+ template < class Class, typename ParamType1, typename ParamType2, typename ParamType3, typename ParamType4 >
+ class _Callback < Class, ParamType1, ParamType2, ParamType3, ParamType4 >
+ {
+ protected:
typedef void (Class::*Method)(ParamType1, ParamType2, ParamType3, ParamType4);
Class *m_object;
Method m_method;
@@ -38,10 +59,11 @@
public:
_Callback(Class *object, Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3, ParamType4 param4)
: m_object(object), m_method(method), m_param1(param1), m_param2(param2), m_param3(param3), m_param4(param4) {}
- _Callback(_Callback < Class, ParamType1, ParamType2, ParamType3, ParamType4> const& cb)
- : m_object(cb.object), m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3), m_param4(cb.m_param4) {}
+ _Callback(_Callback < Class, ParamType1, ParamType2, ParamType3, ParamType4 > const& cb)
+ : m_object(cb.m_object), m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3), m_param4(cb.m_param4) {}
};
+
template < class Class, typename ParamType1, typename ParamType2, typename ParamType3 >
class _Callback < Class, ParamType1, ParamType2, ParamType3 >
{
@@ -55,9 +77,9 @@
void _Execute() { (m_object->*m_method)(m_param1, m_param2, m_param3); }
public:
_Callback(Class *object, Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3)
- : m_object(object), m_method(method), m_param1(param1), m_param2(param2) {}
+ : m_object(object), m_method(method), m_param1(param1), m_param2(param2), m_param3(param3) {}
_Callback(_Callback < Class, ParamType1, ParamType2, ParamType3 > const& cb)
- : m_object(cb.object), m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3) {}
+ : m_object(cb.m_object), m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3) {}
};
template < class Class, typename ParamType1, typename ParamType2 >
@@ -208,12 +230,26 @@
QueryResult* GetResult() { return CB::m_param1; }
};
- template < class Class, typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void >
+
+ template < class Class, typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void, typename ParamType4 = void >
class QueryCallback :
+ public _IQueryCallback< _Callback < Class, QueryResult*, ParamType1, ParamType2, ParamType3, ParamType4 > >
+ {
+ private:
+ typedef _Callback < Class, QueryResult*, ParamType1, ParamType2, ParamType3, ParamType4 > QC4;
+ public:
+ QueryCallback(Class *object, typename QC4::Method method, QueryResult* result, ParamType1 param1, ParamType2 param2, ParamType3 param3, ParamType4 param4)
+ : _IQueryCallback< QC4 >(QC4(object, method, result, param1, param2, param3, param4)) {}
+ };
+
+
+
+ template < class Class, typename ParamType1, typename ParamType2, typename ParamType3 >
+ class QueryCallback < Class, ParamType1, ParamType2, ParamType3 > :
public _IQueryCallback< _Callback < Class, QueryResult*, ParamType1, ParamType2, ParamType3 > >
{
private:
- typedef _Callback < Class, QueryResult*, ParamType1, ParamType2, ParamType3 > QC3;
+ typedef _Callback < Class, QueryResult*, ParamType1, ParamType2, ParamType3> QC3;
public:
QueryCallback(Class *object, typename QC3::Method method, QueryResult* result, ParamType1 param1, ParamType2 param2, ParamType3 param3)
: _IQueryCallback< QC3 >(QC3(object, method, result, param1, param2, param3)) {}