[8768] Rewrite code for prepare and send mails.

* Move send functions to new MailDraft class from WorldSession
* Simplify use different args combinations used in SendMailTo
  by groupping its by functionality in Helper classes. This also will prevent wrong way use args combinations.
This commit is contained in:
VladimirMangos 2009-11-03 17:29:35 +03:00
parent 50e80d67f9
commit d009994f59
12 changed files with 381 additions and 317 deletions

View file

@ -1706,16 +1706,6 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
{
Item* item = reward->itemId ? Item::CreateItem(reward->itemId,1,GetPlayer ()) : NULL;
MailItemsInfo mi;
if(item)
{
// save new item before send
item->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted
// item
mi.AddItem(item);
}
int loc_idx = GetPlayer()->GetSession()->GetSessionDbLocaleIndex();
// subject and text
@ -1734,7 +1724,18 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
uint32 itemTextId = objmgr.CreateItemText( text );
WorldSession::SendMailTo(GetPlayer(), MAIL_CREATURE, MAIL_STATIONERY_NORMAL, reward->sender, GetPlayer()->GetGUIDLow(), subject, itemTextId , &mi, 0, 0, MAIL_CHECK_MASK_NONE);
MailDraft draft(subject, itemTextId);
if(item)
{
// save new item before send
item->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted
// item
draft.AddItem(item);
}
draft.SendMailTo(GetPlayer(), MailSender(MAIL_CREATURE, reward->sender));
}
}

View file

@ -122,7 +122,9 @@ void WorldSession::SendAuctionOutbiddedMail(AuctionEntry *auction, uint32 newPri
if (oldBidder)
oldBidder->GetSession()->SendAuctionBidderNotification( auction->GetHouseId(), auction->Id, _player->GetGUID(), newPrice, auction->GetAuctionOutBid(), auction->item_template);
WorldSession::SendMailTo(oldBidder, MAIL_AUCTION, MAIL_STATIONERY_AUCTION, auction->GetHouseId(), auction->bidder, msgAuctionOutbiddedSubject.str(), 0, NULL, auction->bid, 0, MAIL_CHECK_MASK_NONE);
MailDraft(msgAuctionOutbiddedSubject.str())
.AddMoney(auction->bid)
.SendMailTo(MailReceiver(oldBidder, auction->bidder), auction);
}
}
@ -142,7 +144,9 @@ void WorldSession::SendAuctionCancelledToBidderMail( AuctionEntry* auction )
std::ostringstream msgAuctionCancelledSubject;
msgAuctionCancelledSubject << auction->item_template << ":0:" << AUCTION_CANCELLED_TO_BIDDER;
WorldSession::SendMailTo(bidder, MAIL_AUCTION, MAIL_STATIONERY_AUCTION, auction->GetHouseId(), auction->bidder, msgAuctionCancelledSubject.str(), 0, NULL, auction->bid, 0, MAIL_CHECK_MASK_NONE);
MailDraft(msgAuctionCancelledSubject.str())
.AddMoney(auction->bid)
.SendMailTo(MailReceiver(bidder, auction->bidder), auction);
}
}
@ -443,11 +447,10 @@ void WorldSession::HandleAuctionRemoveItem( WorldPacket & recv_data )
std::ostringstream msgAuctionCanceledOwner;
msgAuctionCanceledOwner << auction->item_template << ":0:" << AUCTION_CANCELED;
MailItemsInfo mi;
mi.AddItem(pItem);
// item will deleted or added to received mail list
WorldSession::SendMailTo(pl, MAIL_AUCTION, MAIL_STATIONERY_AUCTION, auction->GetHouseId(), pl->GetGUIDLow(), msgAuctionCanceledOwner.str(), 0, &mi, 0, 0, MAIL_CHECK_MASK_NONE);
MailDraft(msgAuctionCanceledOwner.str())
.AddItem(pItem)
.SendMailTo(pl, auction);
}
else
{

View file

@ -141,16 +141,15 @@ void AuctionHouseMgr::SendAuctionWonMail( AuctionEntry *auction )
CharacterDatabase.PExecute("UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'",auction->bidder,pItem->GetGUIDLow());
CharacterDatabase.CommitTransaction();
MailItemsInfo mi;
mi.AddItem(pItem);
if (bidder)
bidder->GetSession()->SendAuctionBidderNotification( auction->GetHouseId(), auction->Id, bidder_guid, 0, 0, auction->item_template);
else
RemoveAItem(pItem->GetGUIDLow()); // we have to remove the item, before we delete it !!
// will delete item or place to receiver mail list
WorldSession::SendMailTo(bidder, MAIL_AUCTION, MAIL_STATIONERY_AUCTION, auction->GetHouseId(), auction->bidder, msgAuctionWonSubject.str(), itemTextId, &mi, 0, 0, MAIL_CHECK_MASK_AUCTION);
MailDraft(msgAuctionWonSubject.str(), itemTextId)
.AddItem(pItem)
.SendMailTo(MailReceiver(bidder,auction->bidder), auction, MAIL_CHECK_MASK_AUCTION);
}
// receiver not exist
else
@ -187,7 +186,8 @@ void AuctionHouseMgr::SendAuctionSalePendingMail( AuctionEntry * auction )
uint32 itemTextId = objmgr.CreateItemText( msgAuctionSalePendingBody.str() );
WorldSession::SendMailTo(owner, MAIL_AUCTION, MAIL_STATIONERY_AUCTION, auction->GetHouseId(), auction->owner, msgAuctionSalePendingSubject.str(), itemTextId, NULL, 0, 0, MAIL_CHECK_MASK_AUCTION);
MailDraft(msgAuctionSalePendingSubject.str(), itemTextId)
.SendMailTo(MailReceiver(owner,auction->owner), auction, MAIL_CHECK_MASK_AUCTION);
}
}
@ -229,7 +229,9 @@ void AuctionHouseMgr::SendAuctionSuccessfulMail( AuctionEntry * auction )
owner->GetSession()->SendAuctionOwnerNotification( auction );
}
WorldSession::SendMailTo(owner, MAIL_AUCTION, MAIL_STATIONERY_AUCTION, auction->GetHouseId(), auction->owner, msgAuctionSuccessfulSubject.str(), itemTextId, NULL, profit, 0, MAIL_CHECK_MASK_AUCTION, HOUR);
MailDraft(msgAuctionSuccessfulSubject.str(), itemTextId)
.AddMoney(profit)
.SendMailTo(MailReceiver(owner,auction->owner), auction, MAIL_CHECK_MASK_AUCTION, HOUR);
}
}
@ -261,11 +263,10 @@ void AuctionHouseMgr::SendAuctionExpiredMail( AuctionEntry * auction )
else
RemoveAItem(pItem->GetGUIDLow()); // we have to remove the item, before we delete it !!
MailItemsInfo mi;
mi.AddItem(pItem);
// will delete item or place to receiver mail list
WorldSession::SendMailTo(owner, MAIL_AUCTION, MAIL_STATIONERY_AUCTION, auction->GetHouseId(), GUID_LOPART(owner_guid), subject.str(), 0, &mi, 0, 0, MAIL_CHECK_MASK_NONE);
MailDraft(subject.str())
.AddItem(pItem)
.SendMailTo(MailReceiver(owner,auction->owner), auction);
}
// owner not found
else

View file

@ -933,10 +933,6 @@ void BattleGround::SendRewardMarkByMail(Player *plr,uint32 mark, uint32 count)
// save new item before send
markItem->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted
// item
MailItemsInfo mi;
mi.AddItem(markItem);
// subject: item name
std::string subject = markProto->Name1;
int loc_idx = plr->GetSession()->GetSessionDbLocaleIndex();
@ -951,7 +947,9 @@ void BattleGround::SendRewardMarkByMail(Player *plr,uint32 mark, uint32 count)
snprintf(textBuf,300,textFormat.c_str(),GetName(),GetName());
uint32 itemTextId = objmgr.CreateItemText( textBuf );
WorldSession::SendMailTo(plr, MAIL_CREATURE, MAIL_STATIONERY_NORMAL, bmEntry, plr->GetGUIDLow(), subject, itemTextId , &mi, 0, 0, MAIL_CHECK_MASK_NONE);
MailDraft(subject, itemTextId)
.AddItem(markItem)
.SendMailTo(plr, MailSender(MAIL_CREATURE, bmEntry));
}
}

View file

@ -2003,13 +2003,12 @@ bool ChatHandler::HandleSendMailCommand(const char* args)
std::string text = msgText;
// from console show not existed sender
uint32 sender_guidlo = m_session ? m_session->GetPlayer()->GetGUIDLow() : 0;
MailSender sender(MAIL_NORMAL,m_session ? m_session->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM);
uint32 messagetype = MAIL_NORMAL;
uint32 stationery = MAIL_STATIONERY_GM;
uint32 itemTextId = !text.empty() ? objmgr.CreateItemText( text ) : 0;
WorldSession::SendMailTo(target,messagetype, stationery, sender_guidlo, GUID_LOPART(target_guid), subject, itemTextId, NULL, 0, 0, MAIL_CHECK_MASK_NONE);
MailDraft(subject, itemTextId)
.SendMailTo(MailReceiver(target,GUID_LOPART(target_guid)),sender);
std::string nameLink = playerLink(target_name);
PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str());

View file

@ -6216,25 +6216,23 @@ bool ChatHandler::HandleSendItemsCommand(const char* args)
}
// from console show not existed sender
uint32 sender_guidlo = m_session ? m_session->GetPlayer()->GetGUIDLow() : 0;
MailSender sender(MAIL_NORMAL,m_session ? m_session->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM);
uint32 messagetype = MAIL_NORMAL;
uint32 stationery = MAIL_STATIONERY_GM;
uint32 itemTextId = !text.empty() ? objmgr.CreateItemText( text ) : 0;
// fill mail
MailItemsInfo mi; // item list preparing
MailDraft draft(subject, itemTextId);
for(ItemPairs::const_iterator itr = items.begin(); itr != items.end(); ++itr)
{
if(Item* item = Item::CreateItem(itr->first,itr->second,m_session ? m_session->GetPlayer() : 0))
{
item->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted
mi.AddItem(item);
draft.AddItem(item);
}
}
WorldSession::SendMailTo(receiver,messagetype, stationery, sender_guidlo, GUID_LOPART(receiver_guid), subject, itemTextId, &mi, 0, 0, MAIL_CHECK_MASK_NONE);
draft.SendMailTo(MailReceiver(receiver,GUID_LOPART(receiver_guid)), sender);
std::string nameLink = playerLink(receiver_name);
PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str());
@ -6278,13 +6276,13 @@ bool ChatHandler::HandleSendMoneyCommand(const char* args)
std::string text = msgText;
// from console show not existed sender
uint32 sender_guidlo = m_session ? m_session->GetPlayer()->GetGUIDLow() : 0;
MailSender sender(MAIL_NORMAL,m_session ? m_session->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM);
uint32 messagetype = MAIL_NORMAL;
uint32 stationery = MAIL_STATIONERY_GM;
uint32 itemTextId = !text.empty() ? objmgr.CreateItemText( text ) : 0;
WorldSession::SendMailTo(receiver,messagetype, stationery, sender_guidlo, GUID_LOPART(receiver_guid), subject, itemTextId, NULL, money, 0, MAIL_CHECK_MASK_NONE);
MailDraft(subject, itemTextId)
.AddMoney(money)
.SendMailTo(MailReceiver(receiver,GUID_LOPART(receiver_guid)),sender);
std::string nameLink = playerLink(receiver_name);
PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str());

View file

@ -30,6 +30,7 @@
#include "DBCStores.h"
#include "BattleGroundMgr.h"
#include "Item.h"
#include "AuctionHouseMgr.h"
enum MailShowFlags
{
@ -40,36 +41,6 @@ enum MailShowFlags
MAIL_SHOW_RETURN = 0x0010,
};
void MailItemsInfo::deleteIncludedItems( bool inDB /*= false*/ )
{
for(MailItemMap::iterator mailItemIter = begin(); mailItemIter != end(); ++mailItemIter)
{
Item* item = mailItemIter->second;
if(inDB)
CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid='%u'", item->GetGUIDLow());
delete item;
}
i_MailItemMap.clear();
}
void MailItemsInfo::AddItem( Item *item )
{
i_MailItemMap[item->GetGUIDLow()] = item;
}
void Mail::AddAllItems( MailItemsInfo& pMailItemsInfo )
{
for(MailItemMap::iterator mailItemIter = pMailItemsInfo.begin(); mailItemIter != pMailItemsInfo.end(); ++mailItemIter)
{
Item* item = mailItemIter->second;
AddItem(item->GetGUIDLow(), item->GetEntry());
}
}
void WorldSession::HandleSendMail(WorldPacket & recv_data )
{
uint64 mailbox, unk3;
@ -79,9 +50,6 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data )
recv_data >> mailbox;
recv_data >> receiver;
if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX))
return;
recv_data >> subject;
recv_data >> body;
@ -111,6 +79,11 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data )
recv_data >> unk3; // const 0
recv_data >> unk4; // const 0
// packet read complete, now do check
if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX))
return;
if (receiver.empty())
return;
@ -196,6 +169,7 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data )
}
Item* item = pl->GetItemByGuid(itemGUIDs[i]);
// prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to mail)
if(!item)
{
@ -239,7 +213,7 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data )
bool needItemDelay = false;
MailItemsInfo mi;
MailDraft draft(subject, itemTextId);
if (items_count > 0 || money > 0)
{
@ -262,7 +236,7 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data )
CharacterDatabase.PExecute("UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'", GUID_LOPART(rc), item->GetGUIDLow());
CharacterDatabase.CommitTransaction();
mi.AddItem(item);
draft.AddItem(item);
}
// if item send to character at another account, then apply item delivery delay
@ -280,7 +254,10 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data )
uint32 deliver_delay = needItemDelay ? sWorld.getConfig(CONFIG_MAIL_DELIVERY_DELAY) : 0;
// will delete item or place to receiver mail list
WorldSession::SendMailTo(receive, MAIL_NORMAL, MAIL_STATIONERY_NORMAL, pl->GetGUIDLow(), GUID_LOPART(rc), subject, itemTextId, &mi, money, COD, MAIL_CHECK_MASK_NONE, deliver_delay);
draft
.AddMoney(money)
.AddCOD(COD)
.SendMailTo(MailReceiver(receive, GUID_LOPART(rc)), pl, MAIL_CHECK_MASK_NONE, deliver_delay);
CharacterDatabase.BeginTransaction();
pl->SaveInventoryAndGoldToDB();
@ -345,11 +322,12 @@ void WorldSession::HandleMailReturnToSender(WorldPacket & recv_data )
uint64 mailbox;
uint32 mailId;
recv_data >> mailbox;
recv_data >> mailId;
recv_data.read_skip<uint64>(); // original sender GUID for return to, not used
if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX))
return;
recv_data >> mailId;
Player *pl = _player;
Mail *m = pl->GetMail(mailId);
if(!m || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL))
@ -366,7 +344,12 @@ void WorldSession::HandleMailReturnToSender(WorldPacket & recv_data )
CharacterDatabase.CommitTransaction();
pl->RemoveMail(mailId);
MailItemsInfo mi;
// send back only to players and simple drop for other cases
if (m->messageType == MAIL_NORMAL)
{
MailDraft draft(m->subject, m->itemTextId);
if (m->mailTemplateId)
draft = MailDraft(m->mailTemplateId,false); // items already included
if(m->HasItems())
{
@ -374,7 +357,7 @@ void WorldSession::HandleMailReturnToSender(WorldPacket & recv_data )
{
Item *item = pl->GetMItem(itr2->item_guid);
if(item)
mi.AddItem(item);
draft.AddItem(item);
else
{
//WTF?
@ -384,59 +367,13 @@ void WorldSession::HandleMailReturnToSender(WorldPacket & recv_data )
}
}
SendReturnToSender(MAIL_NORMAL, GetAccountId(), m->receiver, m->sender, m->subject, m->itemTextId, &mi, m->money, m->mailTemplateId);
draft.AddMoney(m->money).SendReturnToSender(GetAccountId(), m->receiver, m->sender);
}
delete m; // we can deallocate old mail
pl->SendMailResult(mailId, MAIL_RETURNED_TO_SENDER, MAIL_OK);
}
void WorldSession::SendReturnToSender(uint8 messageType, uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid, const std::string& subject, uint32 itemTextId, MailItemsInfo *mi, uint32 money, uint16 mailTemplateId )
{
if(messageType != MAIL_NORMAL) // return only to players
{
mi->deleteIncludedItems(true);
return;
}
Player *receiver = objmgr.GetPlayer(MAKE_NEW_GUID(receiver_guid, 0, HIGHGUID_PLAYER));
uint32 rc_account = 0;
if(!receiver)
rc_account = objmgr.GetPlayerAccountIdByGUID(MAKE_NEW_GUID(receiver_guid, 0, HIGHGUID_PLAYER));
if(!receiver && !rc_account) // sender not exist
{
mi->deleteIncludedItems(true);
return;
}
// prepare mail and send in other case
bool needItemDelay = false;
if(mi && !mi->empty())
{
// 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(MailItemMap::iterator mailItemIter = mi->begin(); mailItemIter != mi->end(); ++mailItemIter)
{
Item* item = mailItemIter->second;
item->SaveToDB(); // item not in inventory and can be save standalone
// 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, item->GetGUIDLow());
}
CharacterDatabase.CommitTransaction();
}
// If theres is an item, there is a one hour delivery delay.
uint32 deliver_delay = needItemDelay ? sWorld.getConfig(CONFIG_MAIL_DELIVERY_DELAY) : 0;
// will delete item or place to receiver mail list
WorldSession::SendMailTo(receiver, MAIL_NORMAL, MAIL_STATIONERY_NORMAL, sender_guid, receiver_guid, subject, itemTextId, mi, money, 0, MAIL_CHECK_MASK_RETURNED, deliver_delay, mailTemplateId);
}
//called when player takes item attached in mail
void WorldSession::HandleMailTakeItem(WorldPacket & recv_data )
{
@ -507,7 +444,9 @@ void WorldSession::HandleMailTakeItem(WorldPacket & recv_data )
// check player existence
if(receive || sender_accId)
{
WorldSession::SendMailTo(receive, MAIL_NORMAL, MAIL_STATIONERY_NORMAL, m->receiver, m->sender, m->subject, 0, NULL, m->COD, 0, MAIL_CHECK_MASK_COD_PAYMENT);
MailDraft(m->subject)
.AddMoney(m->COD)
.SendMailTo(MailReceiver(receive,m->sender),MailSender(MAIL_NORMAL,m->receiver), MAIL_CHECK_MASK_COD_PAYMENT);
}
pl->ModifyMoney( -int32(m->COD) );
@ -612,7 +551,7 @@ void WorldSession::HandleGetMailList(WorldPacket & recv_data )
if ((*itr)->HasItems() && (*itr)->messageType == MAIL_NORMAL)
show_flags |= MAIL_SHOW_RETURN;
data << uint16(0x0040); // unknown 2.3.0, different values
data << uint16(next_mail_size); // Message size
data << uint32((*itr)->messageID); // Message ID
data << uint8((*itr)->messageType); // Message Type
@ -834,145 +773,217 @@ void WorldSession::HandleQueryNextMailTime(WorldPacket & /*recv_data*/ )
SendPacket(&data);
}
void WorldSession::SendMailTo(Player* receiver, uint8 messageType, uint8 stationery, uint32 sender_guidlow_or_entry, uint32 receiver_guidlow, std::string subject, uint32 itemTextId, MailItemsInfo* mi, uint32 money, uint32 COD, uint32 checked, uint32 deliver_delay, uint16 mailTemplateId)
MailSender::MailSender( Object* sender, MailStationery stationery ) : m_stationery(stationery)
{
uint32 mailId = objmgr.GenerateMailID();
time_t deliver_time = time(NULL) + deliver_delay;
uint32 expire_delay;
// auction mail without any items and money (auction sale note) pending 1 hour
if (messageType == MAIL_AUCTION && !mi && !money)
expire_delay = HOUR;
// mail from battlemaster (rewardmarks) should last only one day
else if (messageType == MAIL_CREATURE && sBattleGroundMgr.GetBattleMasterBG(sender_guidlow_or_entry) != BATTLEGROUND_TYPE_NONE)
expire_delay = DAY;
// default case: expire time if COD 3 days, if no COD 30 days
else
expire_delay = (COD > 0) ? 3 * DAY : 30 * DAY;
time_t expire_time = deliver_time + expire_delay;
if (mailTemplateId && !sMailTemplateStore.LookupEntry(mailTemplateId))
{
sLog.outError( "WorldSession::SendMailTo - Mail have not existed MailTemplateId (%u), remove at send", mailTemplateId);
mailTemplateId = 0;
}
// Add to DB
CharacterDatabase.BeginTransaction();
CharacterDatabase.escape_string(subject);
CharacterDatabase.PExecute("INSERT INTO mail (id,messageType,stationery,mailTemplateId,sender,receiver,subject,itemTextId,has_items,expire_time,deliver_time,money,cod,checked) "
"VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '%s', '%u', '%u', '" UI64FMTD "','" UI64FMTD "', '%u', '%u', '%d')",
mailId, messageType, stationery, mailTemplateId, sender_guidlow_or_entry, receiver_guidlow, subject.c_str(), itemTextId, (mi && !mi->empty() ? 1 : 0), (uint64)expire_time, (uint64)deliver_time, money, COD, checked);
if (mi)
{
for(MailItemMap::const_iterator mailItemIter = mi->begin(); mailItemIter != mi->end(); ++mailItemIter)
{
Item* item = mailItemIter->second;
CharacterDatabase.PExecute("INSERT INTO mail_items (mail_id,item_guid,item_template,receiver) VALUES ('%u', '%u', '%u','%u')", mailId, item->GetGUIDLow(), item->GetEntry(), receiver_guidlow);
}
}
CharacterDatabase.CommitTransaction();
// For online receiver update in game mail status and data
if (receiver)
{
receiver->AddNewMailDeliverTime(deliver_time);
if (receiver->IsMailsLoaded())
{
Mail *m = new Mail;
m->messageID = mailId;
m->messageType = messageType;
m->stationery = stationery;
m->mailTemplateId = mailTemplateId;
m->sender = sender_guidlow_or_entry;
m->receiver = receiver->GetGUIDLow();
m->subject = subject;
m->itemTextId = itemTextId;
if (mi)
m->AddAllItems(*mi);
m->expire_time = expire_time;
m->deliver_time = deliver_time;
m->money = money;
m->COD = COD;
m->checked = checked;
m->state = MAIL_STATE_UNCHANGED;
receiver->AddMail(m); // to insert new mail to beginning of maillist
if (mi)
{
for(MailItemMap::iterator mailItemIter = mi->begin(); mailItemIter != mi->end(); ++mailItemIter)
receiver->AddMItem(mailItemIter->second);
}
}
else if (mi)
mi->deleteIncludedItems();
}
else if (mi)
mi->deleteIncludedItems();
}
void WorldSession::SendMailTo(Player* receiver, Object* sender, uint8 stationery, uint32 receiver_guidlow, std::string subject, uint32 itemTextId, MailItemsInfo* mi, uint32 money, uint32 COD, uint32 checked, uint32 deliver_delay, uint16 mailTemplateId)
{
MailMessageType mailType;
uint32 senderGuidOrEntry;
switch(sender->GetTypeId())
{
case TYPEID_UNIT:
mailType = MAIL_CREATURE;
senderGuidOrEntry = sender->GetEntry();
m_messageType = MAIL_CREATURE;
m_senderId = sender->GetEntry();
break;
case TYPEID_GAMEOBJECT:
mailType = MAIL_GAMEOBJECT;
senderGuidOrEntry = sender->GetEntry();
m_messageType = MAIL_GAMEOBJECT;
m_senderId = sender->GetEntry();
break;
case TYPEID_ITEM:
mailType = MAIL_ITEM;
senderGuidOrEntry = sender->GetEntry();
m_messageType = MAIL_ITEM;
m_senderId = sender->GetEntry();
break;
case TYPEID_PLAYER:
mailType = MAIL_NORMAL;
senderGuidOrEntry = sender->GetGUIDLow();
m_messageType = MAIL_NORMAL;
m_senderId = sender->GetGUIDLow();
break;
default:
mailType = MAIL_NORMAL;
senderGuidOrEntry = receiver_guidlow;
sLog.outError( "WorldSession::SendMailTo - Mail have unexpected sender typeid (%u), sent from receiver to self", sender->GetTypeId());
m_messageType = MAIL_NORMAL;
m_senderId = 0; // will show mail from not existed player
sLog.outError( "MailSender::MailSender - Mail have unexpected sender typeid (%u)", sender->GetTypeId());
break;
}
SendMailTo(receiver, mailType, stationery, senderGuidOrEntry, receiver_guidlow, subject, itemTextId, mi, money, COD, checked,deliver_delay,mailTemplateId);
}
void WorldSession::SendMailTemplateTo(Player* receiver, Object* sender, uint8 stationery, uint16 mailTemplateId, uint32 money, uint32 COD, uint32 checked, uint32 deliver_delay)
MailSender::MailSender( AuctionEntry* sender )
: m_messageType(MAIL_AUCTION), m_senderId(sender->GetHouseId()), m_stationery(MAIL_STATIONERY_AUCTION)
{
}
MailReceiver::MailReceiver( Player* receiver ) : m_receiver(receiver), m_receiver_lowguid(receiver->GetGUIDLow())
{
}
MailReceiver::MailReceiver( Player* receiver,uint32 receiver_lowguid ) : m_receiver(receiver), m_receiver_lowguid(receiver_lowguid)
{
ASSERT(!receiver || receiver->GetGUIDLow() == receiver_lowguid);
}
MailDraft& MailDraft::AddItem( Item* item )
{
m_items[item->GetGUIDLow()] = item; return *this;
}
void MailDraft::prepareItems(Player* receiver)
{
if (!m_mailTemplateId || !m_mailTemplateItemsNeed)
return;
m_mailTemplateItemsNeed = false;
Loot mailLoot;
mailLoot.FillLoot(mailTemplateId, LootTemplates_Mail, receiver,true);
// fill mail
MailItemsInfo mi; // item list preparing
mailLoot.FillLoot(m_mailTemplateId, LootTemplates_Mail, receiver,true);
uint32 max_slot = mailLoot.GetMaxSlotInLootFor(receiver);
for(uint32 i = 0; mi.size() < MAX_MAIL_ITEMS && i < max_slot; ++i)
for(uint32 i = 0; m_items.size() < MAX_MAIL_ITEMS && i < max_slot; ++i)
{
if (LootItem* lootitem = mailLoot.LootItemInSlot(i,receiver))
{
if (Item* item = Item::CreateItem(lootitem->itemid,lootitem->count,receiver))
{
item->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted
mi.AddItem(item);
AddItem(item);
}
}
}
}
WorldSession::SendMailTo(receiver, sender, stationery, receiver->GetGUIDLow(), "", 0, &mi, money, COD, checked,deliver_delay,mailTemplateId);
void MailDraft::deleteIncludedItems( bool inDB /*= false*/ )
{
for(MailItemMap::iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter)
{
Item* item = mailItemIter->second;
if(inDB)
CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid='%u'", item->GetGUIDLow());
delete item;
}
m_items.clear();
}
void MailDraft::SendReturnToSender(uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid )
{
Player *receiver = objmgr.GetPlayer(MAKE_NEW_GUID(receiver_guid, 0, HIGHGUID_PLAYER));
uint32 rc_account = 0;
if(!receiver)
rc_account = objmgr.GetPlayerAccountIdByGUID(MAKE_NEW_GUID(receiver_guid, 0, HIGHGUID_PLAYER));
if(!receiver && !rc_account) // sender not exist
{
deleteIncludedItems(true);
return;
}
// prepare mail and send in other case
bool needItemDelay = false;
if(!m_items.empty())
{
// 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(MailItemMap::iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter)
{
Item* item = mailItemIter->second;
item->SaveToDB(); // item not in inventory and can be save standalone
// 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, item->GetGUIDLow());
}
CharacterDatabase.CommitTransaction();
}
// If theres is an item, there is a one hour delivery delay.
uint32 deliver_delay = needItemDelay ? sWorld.getConfig(CONFIG_MAIL_DELIVERY_DELAY) : 0;
// will delete item or place to receiver mail list
SendMailTo(MailReceiver(receiver,receiver_guid), MailSender(MAIL_NORMAL, sender_guid), MAIL_CHECK_MASK_RETURNED, deliver_delay);
}
void MailDraft::SendMailTo(MailReceiver const& receiver, MailSender const& sender, MailCheckMask checked, uint32 deliver_delay)
{
Player* pReceiver = receiver.GetPlayer(); // can be NULL
if (pReceiver)
prepareItems(pReceiver); // generate mail template items
uint32 mailId = objmgr.GenerateMailID();
time_t deliver_time = time(NULL) + deliver_delay;
uint32 expire_delay;
// auction mail without any items and money (auction sale note) pending 1 hour
if (sender.GetMailMessageType() == MAIL_AUCTION && m_items.empty() && !m_money)
expire_delay = HOUR;
// mail from battlemaster (rewardmarks) should last only one day
else if (sender.GetMailMessageType() == MAIL_CREATURE && sBattleGroundMgr.GetBattleMasterBG(sender.GetSenderId()) != BATTLEGROUND_TYPE_NONE)
expire_delay = DAY;
// default case: expire time if COD 3 days, if no COD 30 days
else
expire_delay = (m_COD > 0) ? 3 * DAY : 30 * DAY;
time_t expire_time = deliver_time + expire_delay;
// Add to DB
std::string safe_subject = GetSubject();
CharacterDatabase.BeginTransaction();
CharacterDatabase.escape_string(safe_subject);
CharacterDatabase.PExecute("INSERT INTO mail (id,messageType,stationery,mailTemplateId,sender,receiver,subject,itemTextId,has_items,expire_time,deliver_time,money,cod,checked) "
"VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '%s', '%u', '%u', '" UI64FMTD "','" UI64FMTD "', '%u', '%u', '%d')",
mailId, sender.GetMailMessageType(), sender.GetStationery(), GetMailTemplateId(), sender.GetSenderId(), receiver.GetPlayerGUIDLow(), safe_subject.c_str(), GetBodyId(), (m_items.empty() ? 0 : 1), (uint64)expire_time, (uint64)deliver_time, m_money, m_COD, checked);
for(MailItemMap::const_iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter)
{
Item* item = mailItemIter->second;
CharacterDatabase.PExecute("INSERT INTO mail_items (mail_id,item_guid,item_template,receiver) VALUES ('%u', '%u', '%u','%u')", mailId, item->GetGUIDLow(), item->GetEntry(), receiver.GetPlayerGUIDLow());
}
CharacterDatabase.CommitTransaction();
// For online receiver update in game mail status and data
if (pReceiver)
{
pReceiver->AddNewMailDeliverTime(deliver_time);
if (pReceiver->IsMailsLoaded())
{
Mail *m = new Mail;
m->messageID = mailId;
m->mailTemplateId = GetMailTemplateId();
m->subject = GetSubject();
m->itemTextId = GetBodyId();
m->money = GetMoney();
m->COD = GetCOD();
for(MailItemMap::const_iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter)
{
Item* item = mailItemIter->second;
m->AddItem(item->GetGUIDLow(), item->GetEntry());
}
m->messageType = sender.GetMailMessageType();
m->stationery = sender.GetStationery();
m->sender = sender.GetSenderId();
m->receiver = receiver.GetPlayerGUIDLow();
m->expire_time = expire_time;
m->deliver_time = deliver_time;
m->checked = checked;
m->state = MAIL_STATE_UNCHANGED;
pReceiver->AddMail(m); // to insert new mail to beginning of maillist
if (!m_items.empty())
{
for(MailItemMap::iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter)
pReceiver->AddMItem(mailItemIter->second);
}
}
else if (!m_items.empty())
deleteIncludedItems();
}
else if (!m_items.empty())
deleteIncludedItems();
}

View file

@ -21,20 +21,12 @@
#include "Common.h"
#include <map>
struct AuctionEntry;
class Item;
#define MAIL_BODY_ITEM_TEMPLATE 8383 // - plain letter, A Dusty Unsent Letter: 889
#define MAX_MAIL_ITEMS 12
enum MailCheckMask
{
MAIL_CHECK_MASK_NONE = 0,
MAIL_CHECK_MASK_READ = 1,
MAIL_CHECK_MASK_AUCTION = 4,
MAIL_CHECK_MASK_COD_PAYMENT = 8,
MAIL_CHECK_MASK_RETURNED = 16
};
enum MailMessageType
{
MAIL_NORMAL = 0,
@ -62,16 +54,75 @@ enum MailAuctionAnswers
AUCTION_SALE_PENDING = 6
};
// gathered from Stationery.dbc
enum MailStationery
class MailSender
{
MAIL_STATIONERY_UNKNOWN = 1,
MAIL_STATIONERY_NORMAL = 41,
MAIL_STATIONERY_GM = 61,
MAIL_STATIONERY_AUCTION = 62,
MAIL_STATIONERY_VAL = 64,
MAIL_STATIONERY_CHR = 65,
MAIL_STATIONERY_ORP = 67, // new in 3.2.2
public: // Constructors
MailSender(MailMessageType messageType, uint32 sender_guidlow_or_entry, MailStationery stationery = MAIL_STATIONERY_NORMAL)
: m_messageType(messageType), m_senderId(sender_guidlow_or_entry), m_stationery(stationery)
{
}
MailSender(Object* sender, MailStationery stationery = MAIL_STATIONERY_NORMAL);
MailSender(AuctionEntry* sender);
public: // Accessors
MailMessageType GetMailMessageType() const { return m_messageType; }
uint32 GetSenderId() const { return m_senderId; }
MailStationery GetStationery() const { return m_stationery; }
private:
MailMessageType m_messageType;
uint32 m_senderId; // player low guid or other object entry
MailStationery m_stationery;
};
class MailReceiver
{
public: // Constructors
explicit MailReceiver(uint32 receiver_lowguid) : m_receiver(NULL), m_receiver_lowguid(receiver_lowguid) {}
MailReceiver(Player* receiver);
MailReceiver(Player* receiver,uint32 receiver_lowguid);
public: // Accessors
Player* GetPlayer() const { return m_receiver; }
uint32 GetPlayerGUIDLow() const { return m_receiver_lowguid; }
private:
Player* m_receiver;
uint32 m_receiver_lowguid;
};
class MailDraft
{
typedef std::map<uint32, Item*> MailItemMap;
public: // Constructors
explicit MailDraft(uint16 mailTemplateId, bool need_items = true)
: m_mailTemplateId(mailTemplateId), m_mailTemplateItemsNeed(need_items), m_bodyId(0), m_money(0), m_COD(0)
{}
MailDraft(std::string subject, uint32 itemTextId = 0)
: m_mailTemplateId(0), m_mailTemplateItemsNeed(false), m_subject(subject), m_bodyId(itemTextId), m_money(0), m_COD(0) {}
public: // Accessors
uint16 GetMailTemplateId() const { return m_mailTemplateId; }
std::string const& GetSubject() const { return m_subject; }
uint32 GetBodyId() const { return m_bodyId; }
uint32 GetMoney() const { return m_money; }
uint32 GetCOD() const { return m_COD; }
public: // modifiers
MailDraft& AddItem(Item* item);
MailDraft& AddMoney(uint32 money) { m_money = money; return *this; }
MailDraft& AddCOD(uint32 COD) { m_COD = COD; return *this; }
public: // finishers
void SendReturnToSender(uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid);
void SendMailTo(MailReceiver const& receiver, MailSender const& sender, MailCheckMask checked = MAIL_CHECK_MASK_NONE, uint32 deliver_delay = 0);
private:
void deleteIncludedItems(bool inDB = false);
void prepareItems(Player* receiver); // called from SendMailTo for generate mailTemplateBase items
uint16 m_mailTemplateId;
bool m_mailTemplateItemsNeed;
std::string m_subject;
uint32 m_bodyId;
MailItemMap m_items; // Keep the items in a map to avoid duplicate guids (which can happen), store only low part of guid
uint32 m_money;
uint32 m_COD;
};
struct MailItemInfo
@ -80,26 +131,6 @@ struct MailItemInfo
uint32 item_template;
};
typedef std::map<uint32, Item*> MailItemMap;
class MailItemsInfo
{
public:
MailItemMap::const_iterator begin() const { return i_MailItemMap.begin(); }
MailItemMap::const_iterator end() const { return i_MailItemMap.end(); }
MailItemMap::iterator begin() { return i_MailItemMap.begin(); }
MailItemMap::iterator end() { return i_MailItemMap.end(); }
void AddItem(Item *item);
uint8 size() const { return i_MailItemMap.size(); }
bool empty() const { return i_MailItemMap.empty(); }
void deleteIncludedItems(bool inDB = false);
private:
MailItemMap i_MailItemMap; // Keep the items in a map to avoid duplicate guids (which can happen), store only low part of guid
};
struct Mail
{
uint32 messageID;
@ -127,8 +158,6 @@ struct Mail
items.push_back(mii);
}
void AddAllItems(MailItemsInfo& pMailItemsInfo);
bool RemoveItem(uint32 item_guid)
{
for(std::vector<MailItemInfo>::iterator itr = items.begin(); itr != items.end(); ++itr)
@ -144,4 +173,5 @@ struct Mail
bool HasItems() const { return !items.empty(); }
};
#endif

View file

@ -3914,8 +3914,8 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
// remove signs from petitions (also remove petitions if owner);
RemovePetitionsAndSigns(playerguid, 10);
// return back all mails with COD and Item 0 1 2 3 4 5 6
QueryResult *resultMail = CharacterDatabase.PQuery("SELECT id,mailTemplateId,sender,subject,itemTextId,money,has_items FROM mail WHERE receiver='%u' AND has_items<>0 AND cod<>0", guid);
// return back all mails with COD and Item 0 1 2 3 4 5 6 7
QueryResult *resultMail = CharacterDatabase.PQuery("SELECT id,messageType,mailTemplateId,sender,subject,itemTextId,money,has_items FROM mail WHERE receiver='%u' AND has_items<>0 AND cod<>0", guid);
if(resultMail)
{
do
@ -3923,18 +3923,30 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
Field *fields = resultMail->Fetch();
uint32 mail_id = fields[0].GetUInt32();
uint16 mailTemplateId= fields[1].GetUInt16();
uint32 sender = fields[2].GetUInt32();
std::string subject = fields[3].GetCppString();
uint32 itemTextId = fields[4].GetUInt32();
uint32 money = fields[5].GetUInt32();
bool has_items = fields[6].GetBool();
uint16 mailType = fields[1].GetUInt16();
uint16 mailTemplateId= fields[2].GetUInt16();
uint32 sender = fields[3].GetUInt32();
std::string subject = fields[4].GetCppString();
uint32 itemTextId = fields[5].GetUInt32();
uint32 money = fields[6].GetUInt32();
bool has_items = fields[7].GetBool();
//we can return mail now
//so firstly delete the old one
CharacterDatabase.PExecute("DELETE FROM mail WHERE id = '%u'", mail_id);
MailItemsInfo mi;
// mail not from player
if (mailType != MAIL_NORMAL)
{
if(has_items)
CharacterDatabase.PExecute("DELETE FROM mail_items WHERE mail_id = '%u'", mail_id);
continue;
}
MailDraft draft(subject, itemTextId);
if (mailTemplateId)
draft = MailDraft(mailTemplateId,false); // itesm already included
if(has_items)
{
// data needs to be at first place for Item::LoadFromDB
@ -3963,7 +3975,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
continue;
}
mi.AddItem(pItem);
draft.AddItem(pItem);
}
while (resultItems->NextRow());
@ -3975,7 +3987,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
uint32 pl_account = objmgr.GetPlayerAccountIdByGUID(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER));
WorldSession::SendReturnToSender(MAIL_NORMAL, pl_account, guid, sender, subject, itemTextId, &mi, money, mailTemplateId);
draft.AddMoney(money).SendReturnToSender(pl_account, guid, sender);
}
while (resultMail->NextRow());
@ -12715,7 +12727,7 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
// Send reward mail
if (uint32 mail_template_id = pQuest->GetRewMailTemplateId())
WorldSession::SendMailTemplateTo(this, questGiver, MAIL_STATIONERY_NORMAL, mail_template_id, 0, 0, MAIL_CHECK_MASK_NONE, pQuest->GetRewMailDelaySecs());
MailDraft(mail_template_id).SendMailTo(this, questGiver, MAIL_CHECK_MASK_NONE, pQuest->GetRewMailDelaySecs());
if (pQuest->IsDaily())
{
@ -14941,20 +14953,20 @@ void Player::_LoadInventory(QueryResult *result, uint32 timediff)
// send by mail problematic items
while(!problematicItems.empty())
{
std::string subject = GetSession()->GetMangosString(LANG_NOT_EQUIPPED_ITEM);
// fill mail
MailItemsInfo mi; // item list preparing
MailDraft draft(subject);
for(int i = 0; !problematicItems.empty() && i < MAX_MAIL_ITEMS; ++i)
{
Item* item = problematicItems.front();
problematicItems.pop_front();
mi.AddItem(item);
draft.AddItem(item);
}
std::string subject = GetSession()->GetMangosString(LANG_NOT_EQUIPPED_ITEM);
WorldSession::SendMailTo(this, MAIL_NORMAL, MAIL_STATIONERY_GM, GetGUIDLow(), GetGUIDLow(), subject, 0, &mi, 0, 0, MAIL_CHECK_MASK_NONE);
draft.SendMailTo(this, MailSender(this, MAIL_STATIONERY_GM));
}
}
//if(isAlive())
@ -18822,8 +18834,6 @@ void Player::AutoUnequipOffhandIfNeed()
}
else
{
MailItemsInfo mi;
mi.AddItem(offItem);
MoveItemFromInventory(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND, true);
CharacterDatabase.BeginTransaction();
offItem->DeleteFromInventoryDB(); // deletes item from character's inventory
@ -18831,7 +18841,7 @@ void Player::AutoUnequipOffhandIfNeed()
CharacterDatabase.CommitTransaction();
std::string subject = GetSession()->GetMangosString(LANG_NOT_EQUIPPED_ITEM);
WorldSession::SendMailTo(this, MAIL_NORMAL, MAIL_STATIONERY_GM, GetGUIDLow(), GetGUIDLow(), subject, 0, &mi, 0, 0, MAIL_CHECK_MASK_NONE);
MailDraft(subject).AddItem(offItem).SendMailTo(this, MailSender(this, MAIL_STATIONERY_GM));
}
}

View file

@ -2620,6 +2620,27 @@ enum BattleGroundTypeId
};
#define MAX_BATTLEGROUND_TYPE_ID 33
enum MailCheckMask
{
MAIL_CHECK_MASK_NONE = 0x00,
MAIL_CHECK_MASK_READ = 0x01,
MAIL_CHECK_MASK_AUCTION = 0x04,
MAIL_CHECK_MASK_COD_PAYMENT = 0x08,
MAIL_CHECK_MASK_RETURNED = 0x10
};
// gathered from Stationery.dbc
enum MailStationery
{
MAIL_STATIONERY_UNKNOWN = 1,
MAIL_STATIONERY_NORMAL = 41,
MAIL_STATIONERY_GM = 61,
MAIL_STATIONERY_AUCTION = 62,
MAIL_STATIONERY_VAL = 64,
MAIL_STATIONERY_CHR = 65,
MAIL_STATIONERY_ORP = 67, // new in 3.2.2
};
enum MailResponseType
{
MAIL_SEND = 0,

View file

@ -26,7 +26,6 @@
#include "Common.h"
#include "SharedDefines.h"
class MailItemsInfo;
struct ItemPrototype;
struct AuctionEntry;
struct DeclinedName;
@ -39,7 +38,6 @@ class Player;
class Unit;
class WorldPacket;
class WorldSocket;
class WorldSession;
class QueryResult;
class LoginQueryHolder;
class CharacterHandler;
@ -220,14 +218,8 @@ class MANGOS_DLL_SPEC WorldSession
m_TutorialsChanged = true;
}
}
//mail
//used with item_page table
bool SendItemInfo( uint32 itemid, WorldPacket data );
static void SendReturnToSender(uint8 messageType, uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid, const std::string& subject, uint32 itemTextId, MailItemsInfo *mi, uint32 money, uint16 mailTemplateId = 0);
static void SendMailTo(Player* receiver, uint8 messageType, uint8 stationery, uint32 sender_guidlow_or_entry, uint32 received_guidlow, std::string subject, uint32 itemTextId, MailItemsInfo* mi, uint32 money, uint32 COD, uint32 checked, uint32 deliver_delay = 0, uint16 mailTemplateId = 0);
static void SendMailTo(Player* receiver, Object* sender, uint8 stationery, uint32 received_guidlow, std::string subject, uint32 itemTextId, MailItemsInfo* mi, uint32 money, uint32 COD, uint32 checked, uint32 deliver_delay = 0, uint16 mailTemplateId = 0);
static void SendMailTemplateTo(Player* receiver, Object* sender, uint8 stationery, uint16 mailTemplateId, uint32 money, uint32 COD, uint32 checked, uint32 deliver_delay = 0);
//auction
void SendAuctionHello( uint64 guid, Creature * unit );

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "8767"
#define REVISION_NR "8768"
#endif // __REVISION_NR_H__