2 * Copyright (C) 2005,2006 MaNGOS <http://www.mangosproject.org/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "WorldPacket.h"
20 #include "WorldSession.h"
25 #include "ObjectMgr.h"
27 #include "UpdateMask.h"
30 void WorldSession::HandleSendMail(WorldPacket
& recv_data
)
32 time_t base
= time(NULL
);
35 std::string receiver
,subject
,body
;
36 uint32 unk1
,unk2
,money
,COD
,mID
;
38 recv_data
>> receiver
>> subject
>> body
;
39 recv_data
>> unk1
>> unk2
;
41 recv_data
>> money
>> COD
;
43 sLog
.outDetail("Player %u is sending mail to %s with subject %s and body %s includes item %u and %u copper and %u COD copper",GUID_LOPART(sender
),receiver
.c_str(),subject
.c_str(),body
.c_str(),GUID_LOPART(item
),money
,COD
);
44 mID
= objmgr
.GenerateMailID();
50 uint64 rc
= objmgr
.GetPlayerGUIDByName(receiver
.c_str());
51 if(pl
->GetGUID() == rc
)
53 tmpData
.Initialize(SMSG_SEND_MAIL_RESULT
);
56 tmpData
<< uint32(MAIL_ERR_CANNOT_SEND_TO_SELF
);
61 if (pl
->GetMoney() < money
+ 30)
63 tmpData
.Initialize(SMSG_SEND_MAIL_RESULT
);
66 tmpData
<< uint32(MAIL_ERR_NOT_ENOUGH_MONEY
);
73 data
.Initialize(SMSG_SEND_MAIL_RESULT
);
76 data
<< uint32(MAIL_ERR_RECIPIENT_NOT_FOUND
);
81 Player
*receive
= objmgr
.GetPlayer(rc
);
86 rc_team
= receive
->GetTeam();
88 rc_team
= objmgr
.GetPlayerTeamByGUID(rc
);
90 // test the receiver's Faction...
91 if (pl
->GetTeam() != rc_team
)
93 data
.Initialize(SMSG_SEND_MAIL_RESULT
);
96 data
<< uint32(MAIL_ERR_NOT_YOUR_TEAM
);
106 item_pos
= pl
->GetPosByGuid(item
);
107 it
= pl
->GetItemByPos( item_pos
);
109 // prevent sending bag with items (cheat: can be placed in bag after adding equiped empty bag to mail)
110 if(it
->IsBag() && !((Bag
*)it
)->IsEmpty())
112 data
.Initialize(SMSG_SEND_MAIL_RESULT
);
115 data
<< uint32(MAIL_ERR_INTERNAL_ERROR
);
121 data
.Initialize(SMSG_SEND_MAIL_RESULT
);
124 data
<< uint32(MAIL_OK
);
129 //item reminds in item_instance table already, used it in mail now
130 pl
->RemoveItem( (item_pos
>> 8), (item_pos
& 255), true );
132 pl
->ModifyMoney( -30 - money
);
134 time_t etime
= base
+ 3600 * ((COD
> 0)? 3 : 30); //time if COD 3 days, if no COD 30 days
139 m
->sender
= pl
->GetGUIDLow();
140 m
->receiver
= GUID_LOPART(rc
);
141 m
->subject
= subject
;
143 m
->item
= GUID_LOPART(item
);
151 receive
->AddMItem(it
);
154 sDatabase
.PExecute("DELETE FROM `mail` WHERE `id` = '%u'",mID
);
155 // there was (long)etime ;-) COD added
156 sDatabase
.PExecute("INSERT INTO `mail` (`id`,`sender`,`receiver`,`subject`,`body`,`item`,`time`,`money`,`cod`,`checked`) VALUES ('%u', '%u', '%u', '%s', '%s', '%u', '" I64FMTD
"', '%u', '%u', '%u')", mID
, pl
->GetGUIDLow(), GUID_LOPART(rc
), subject
.c_str(), body
.c_str(), GUID_LOPART(item
), (uint64
)etime
, money
, COD
, 0);
159 void WorldSession::HandleMarkAsRead(WorldPacket
& recv_data
)
163 recv_data
>> mailbox
;
164 recv_data
>> message
;
165 Player
*pl
= _player
;
166 Mail
*m
= pl
->GetMail(message
);
172 m
->time
= time(NULL
) + (3 * 3600);
173 pl
->m_mailsUpdated
= true;
178 void WorldSession::HandleMailDelete(WorldPacket
& recv_data
)
183 recv_data
>> mailbox
;
184 recv_data
>> message
;
185 Player
*pl
= _player
;
186 // pl->m_mailsUpdated = true; there 's no need to change it .. because query deletes mail from DB...
187 Mail
*m
= pl
->GetMail(message
);
191 sDatabase
.PExecute("DELETE FROM `mail` WHERE `id` = '%u'", m
->messageID
);
192 /*if (m->item) //player cannot delete mail, when it has money , or item, that mail can be returned
193 sDatabase.PExecute("DELETE FROM `item_instance` WHERE `guid` = '%u'", m->item);*/
196 pl
->RemoveMail(message
);
198 data
.Initialize(SMSG_SEND_MAIL_RESULT
);
199 data
<< uint32(message
);
200 data
<< uint32(MAIL_DELETED
);
205 void WorldSession::HandleReturnToSender(WorldPacket
& recv_data
)
210 recv_data
>> mailbox
;
211 recv_data
>> message
;
212 Player
*pl
= _player
;
213 Mail
*m
= pl
->GetMail(message
);
218 m
->receiver
= m
->sender
;
219 m
->sender
= pl
->GetGUIDLow();
220 m
->time
= time(NULL
) + (30 * 3600);
223 uint64 rc
= m
->receiver
;
224 Player
*receive
= objmgr
.GetPlayer(rc
);
229 Item
*pItem
= pl
->GetMItem(m
->item
);
230 receive
->AddMItem(pItem
);
231 pl
->RemoveMItem(m
->item
);
235 //pl->m_mailsUpdated = true; - not needed, query does all we need
237 data
.Initialize(SMSG_SEND_MAIL_RESULT
);
238 data
<< uint32(message
);
239 data
<< uint32(MAIL_RETURNED_TO_SENDER
);
243 sDatabase
.PExecute("DELETE FROM `mail` WHERE `id` = '%u'", message
);
244 sDatabase
.PExecute("INSERT INTO `mail` (`id`,`sender`,`receiver`,`subject`,`body`,`item`,`time`,`money`,`cod`,`checked`) VALUES ('%u', '%u','%u', '%s', '%s', '%u','" I64FMTD
"','%u','%u','%u')", m
->messageID
, pl
->GetGUIDLow(), m
->receiver
, m
->subject
.c_str(), m
->body
.c_str(), m
->item
, (uint64
)m
->time
, m
->money
, 0, 0);
246 pl
->RemoveMail(message
);
249 void WorldSession::HandleTakeItem(WorldPacket
& recv_data
)
255 recv_data
>> mailbox
;
256 recv_data
>> message
;
257 Player
* pl
= _player
;
259 Mail
* m
= pl
->GetMail(message
);
263 Item
*it
= pl
->GetMItem(m
->item
);
265 uint8 msg
= _player
->CanStoreItem( 0, NULL_SLOT
, dest
, it
, false );
266 if( msg
== EQUIP_ERR_OK
)
273 mn
->messageID
= objmgr
.GenerateMailID();
274 mn
->sender
= m
->receiver
;
275 mn
->receiver
= m
->sender
;
276 mn
->subject
= m
->subject
;
277 mn
->body
= "Your item sold, player paid a COD";
279 mn
->time
= time(NULL
) + (30 * 3600);
284 Player
*receive
= objmgr
.GetPlayer((uint64
)m
->sender
);
287 receive
->AddMail(mn
);
289 sDatabase
.PExecute("DELETE FROM `mail` WHERE `id` = '%u'",mn
->messageID
);
291 sDatabase
.PExecute("INSERT INTO `mail` (`id`,`sender`,`receiver`,`subject`,`body`,`item`,`time`,`money`,`cod`,`checked`) VALUES ('%u', '%u', '%u', '%s', '%s', '%u', '" I64FMTD
"', '%u', '%u', '%u')", mn
->messageID
, mn
->sender
, mn
->receiver
, mn
->subject
.c_str(), mn
->body
.c_str(), 0, (uint64
)mn
->time
, mn
->money
, 0, 0);
292 // client tests, if player has enought money !!!
293 pl
->ModifyMoney( -int32(m
->COD
) );
298 uint32 it_guidlow
= it
->GetGUIDLow();
299 _player
->StoreItem( dest
, it
, true); // item can be remove at adding to existed item stack
300 pl
->RemoveMItem(it_guidlow
);
302 data
.Initialize(SMSG_SEND_MAIL_RESULT
);
303 data
<< uint32(message
);
304 data
<< uint32(MAIL_ITEM_TAKEN
);
310 data
.Initialize(SMSG_SEND_MAIL_RESULT
);
311 data
<< uint32(message
);
313 data
<< uint32(MAIL_ERR_BAG_FULL
);
318 void WorldSession::HandleTakeMoney(WorldPacket
& recv_data
)
323 recv_data
>> mailbox
;
325 Player
*pl
= _player
;
327 Mail
* m
= pl
->GetMail(id
);
331 data
.Initialize(SMSG_SEND_MAIL_RESULT
);
333 data
<< uint32(MAIL_MONEY_TAKEN
);
337 pl
->ModifyMoney(m
->money
);
340 pl
->m_mailsUpdated
= true;
344 void WorldSession::HandleGetMail(WorldPacket
& recv_data
)
347 recv_data
>> mailbox
; // from mailbox in Storm near bank it was 0x000068A2 (dec 26786) and 0xF0004000 (dec 4026548224)
350 Player
* pl
= _player
;
352 //load players mails, and mailed items
353 if(!pl
->m_mailsLoaded
)
356 data
.Initialize(SMSG_MAIL_LIST_RESULT
);
357 data
<< uint8(pl
->GetMailSize());
358 std::list
<Mail
*>::iterator itr
;
359 for (itr
= pl
->GetmailBegin(); itr
!= pl
->GetmailEnd();itr
++)
361 data
<< uint32((*itr
)->messageID
); // Correct..., also message id , if you change it, server crashes
362 data
<< uint8(0); // Message Type 0 = Default, maybe there will be also Reply
363 data
<< uint32((*itr
)->sender
); // SenderID
364 data
<< uint32(0); // Constant
366 data
<< (*itr
)->subject
.c_str(); // Subject string
367 if((*itr
)->body
.c_str()!=NULL
)
368 data
<< uint32((*itr
)->messageID
); // MessageID!!
370 data
<< uint32(0); // No messageID
371 data
<< uint32(0); // Unknown - 0x00000029
372 data
<< uint32(0); // Unknown
373 if ((*itr
)->item
!= 0)
375 if(Item
* i
= pl
->GetMItem((*itr
)->item
))
376 data
<< uint32(i
->GetUInt32Value(OBJECT_FIELD_ENTRY
));
379 sLog
.outError("Mail to %s marked as having item (mail item idx: %u), but item not found.",pl
->GetName(),(*itr
)->item
);
386 data
<< uint32(0); // Unknown
387 data
<< uint32(0); // Unknown
388 data
<< uint32(0); // Unknown
389 data
<< uint8(1); // Unknown - Count
390 data
<< uint32(0xFFFFFFFF); // Unknown - Charges
391 data
<< uint32(0); // Unknown - MaxDurability
392 data
<< uint32(0); // Unknown - Durability
393 data
<< uint32((*itr
)->money
); // Gold
394 data
<< uint32((*itr
)->COD
); // COD
395 data
<< uint32((*itr
)->checked
); // flags 0: not checked 1: checked 8: COD Payment: "Subject"
396 data
<< float(((*itr
)->time
- time(NULL
)) / 3600); // Time
397 data
<< uint32(0); // Unknown
403 extern char *fmtstring( char *format
, ... );
405 uint32
GetItemGuidFromDisplayID ( uint32 displayID
, Player
* pl
)
411 for (i
= EQUIPMENT_SLOT_START
; i
< BANK_SLOT_BAG_END
; i
++)
413 srcitem
= pl
->GetItemByPos( INVENTORY_SLOT_BAG_0
, i
);
417 if (srcitem
->GetProto()->DisplayInfoID
== displayID
)
424 if( i
>= BANK_SLOT_BAG_END
)
426 QueryResult
*result
= sDatabase
.PQuery( "SELECT `entry` FROM `item_template` WHERE `displayid`='%u'", displayID
);
433 uint32 id
= (*result
)[0].GetUInt32();
438 return srcitem
->GetProto()->ItemId
;
441 bool WorldSession::SendItemInfo( uint32 itemid
, WorldPacket data
)
444 uint32 realID
= GetItemGuidFromDisplayID(itemid
, _player
);
445 char const *itemInfo
;
449 sLog
.outError( "WORLD: Unknown item id 0x%.8X", realID
);
453 ItemPrototype
const *itemProto
= objmgr
.GetItemPrototype(realID
);
457 sLog
.outError( "WORLD: Unknown item id 0x%.8X", realID
);
461 sLog
.outDebug( "WORLD: Real item id is %u. Name %s.", realID
, itemProto
->Name1
);
463 data
.Initialize(SMSG_ITEM_TEXT_QUERY_RESPONSE
);
466 itemInfo
= fmtstring("<HTML>\n<BODY>\n");
468 itemInfo
= fmtstring("%s</P></BODY>\n</HTML>\n", itemInfo
);
477 void WorldSession::HandleItemTextQuery(WorldPacket
& recv_data
)
483 recv_data
>> mailguid
>> unk1
;
485 Player
* pl
= _player
;
489 itr
= pl
->GetMail(mailguid
);
492 sLog
.outDebug("We got mailguid: %u with unk: %u", mailguid
, unk1
);
494 data
.Initialize(SMSG_ITEM_TEXT_QUERY_RESPONSE
);
496 data
<< itr
->body
.c_str();
503 QueryResult
*result
= sDatabase
.PQuery( "SELECT `text`,`next_page` FROM `item_page` WHERE `id` = '%u'", mailguid
);
507 data
.Initialize(SMSG_ITEM_TEXT_QUERY_RESPONSE
);
510 uint32 nextpage
= mailguid
;
514 data
<< (*result
)[0].GetString();
515 nextpage
= (*result
)[1].GetUInt32();
525 if (!SendItemInfo( mailguid
, data
))
527 data
.Initialize(SMSG_ITEM_TEXT_QUERY_RESPONSE
);
530 data
<< "There is no info for this item.";
538 void WorldSession::HandleMailCreateTextItem(WorldPacket
& recv_data
)
540 uint32 unk1
,unk2
,mailid
;
542 recv_data
>> unk1
>> unk2
>> mailid
;
544 sLog
.outDetail("HandleMailCreateTextItem unk1=%u,unk2=%u,mailid=%u",unk1
,unk2
,mailid
);
546 Item
*item
= new Item();
548 if(!item
->Create(objmgr
.GenerateLowGuid(HIGHGUID_ITEM
), 889, _player
))
553 item
->SetUInt32Value( ITEM_FIELD_ITEM_TEXT_ID
, mailid
);
556 data
.Initialize(SMSG_SEND_MAIL_RESULT
);
559 uint8 msg
= _player
->CanStoreItem( 0, NULL_SLOT
, dest
, item
, false );
560 if( msg
== EQUIP_ERR_OK
)
562 _player
->StoreItem(dest
, item
, true);
563 data
<< uint32(mailid
);
564 data
<< uint32(MAIL_MADE_PERMANENT
);
570 _player
->SendEquipError( msg
, item
, NULL
);
571 data
<< uint32(mailid
);
573 data
<< uint32(MAIL_ERR_INTERNAL_ERROR
);
579 void WorldSession::HandleMsgQueryNextMailtime(WorldPacket
& recv_data
)
584 if( _player
->unReadMails
> 0 )
586 Data
.Initialize(MSG_QUERY_NEXT_MAIL_TIME
);
592 Data
.Initialize(MSG_QUERY_NEXT_MAIL_TIME
);