root/trunk/src/arcemu-world/MailSystem.cpp @ 3153

Revision 3153, 22.6 kB (checked in by Hoffa, 7 months ago)

Applied 3.3.2 misc fixes by Terrorblade -> http://arcemu.org/forums/index.php?showtopic=20707

  • Property svn:eol-style set to native
  • Property ff set to
    *.cpp = svn:eol-style=native
    Makefile = svn:eol-style=native
    README = svn:eol-style=native
    CHANGELOG = svn:eol-style=native
    LICENSE = svn:eol-style=native
  • Property svn:keywords set to Date Author Rev
Line 
1/*
2 * ArcEmu MMORPG Server
3 * Copyright (C) 2005-2007 Ascent Team <http://www.ascentemu.com/>
4 * Copyright (C) 2008-2010 <http://www.ArcEmu.org/>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#include "StdAfx.h"
22initialiseSingleton(MailSystem);
23
24void MailSystem::StartMailSystem()
25{
26
27}
28
29MailError MailSystem::DeliverMessage(uint64 recipent, MailMessage* message)
30{
31        // assign a new id
32        message->message_id = Generate_Message_Id();
33
34        Player * plr = objmgr.GetPlayer((uint32)recipent);
35        if(plr != NULL)
36        {
37                plr->m_mailBox.AddMessage(message);
38                if((uint32)UNIXTIME >= message->delivery_time)
39                {
40                        uint32 v = 0;
41                        plr->GetSession()->OutPacket(SMSG_RECEIVED_MAIL, 4, &v);
42                }
43        }
44
45        SaveMessageToSQL(message);
46        return MAIL_OK;
47}
48
49void Mailbox::AddMessage(MailMessage* Message)
50{
51        Messages[Message->message_id] = *Message;
52}
53
54void Mailbox::DeleteMessage(uint32 MessageId, bool sql)
55{
56        Messages.erase(MessageId);
57        if(sql)
58                CharacterDatabase.WaitExecute("DELETE FROM mailbox WHERE message_id = %u", MessageId);
59}
60
61WorldPacket * Mailbox::BuildMailboxListingPacket()
62{
63        WorldPacket * data = new WorldPacket(SMSG_MAIL_LIST_RESULT, 500);
64        MessageMap::iterator itr;
65        uint32 realcount = 0;
66        uint32 count = 0;
67        uint32 t = (uint32)UNIXTIME;
68        *data << uint32(0);      // realcount - this can be used to tell the client we have more mail than that fits into this packet
69        *data << uint8(0);       // size placeholder
70
71        for(itr = Messages.begin(); itr != Messages.end(); ++itr)
72        {
73                if(itr->second.expire_time && t > itr->second.expire_time)
74                        continue;          // expired mail -> skip it
75
76                if((uint32)UNIXTIME < itr->second.delivery_time)
77                        continue;               // undelivered
78
79                if(count >= 50) //VLack: We could calculate message sizes instead of this, but the original code did a break at 50, so I won't fix this up if no one felt the need to do so before ;-)
80                {
81                        ++realcount;
82                        continue;
83                }
84
85                if(itr->second.AddMessageDataToPacket(*data))
86                {
87                        ++count;
88                        ++realcount;
89                }
90        }
91
92        data->put<uint32>(0, realcount); 
93        data->put<uint8>(4, static_cast< uint8 >( count )); 
94
95        // do cleanup on request mail
96        CleanupExpiredMessages();
97        return data;
98}
99
100void Mailbox::CleanupExpiredMessages()
101{
102        MessageMap::iterator itr, it2;
103        uint32 curtime = (uint32)UNIXTIME;
104
105        for(itr = Messages.begin(); itr != Messages.end();)
106        {
107                it2 = itr++;
108                if(it2->second.expire_time && it2->second.expire_time < curtime)
109                {
110                        Messages.erase(it2);
111                }
112        }
113}
114
115bool MailMessage::AddMessageDataToPacket(WorldPacket& data)
116{
117        uint8 i = 0;
118        uint32 j;
119        size_t pos;
120        vector<uint64>::iterator itr;
121        Item * pItem;
122
123        // add stuff
124        if(deleted_flag)
125                return false;
126
127        data << uint16(0x0032);
128        data << message_id;
129        data << uint8(message_type);
130        if(message_type)
131                data << uint32(sender_guid);
132        else
133                data << sender_guid;
134
135        data << cod;                    // cod
136        data << message_id;             // itempageid
137        data << uint32(0);
138        data << stationery;
139        data << money;          // money
140        data << uint32(0x10);
141        data << float(float(expire_time - (uint32)UNIXTIME) / 86400.0f);
142        data << uint32(0);      // mail template
143        data << subject;
144        pos = data.wpos();
145        data << uint8(items.size());            // item count
146
147        if( !items.empty( ) )
148        {
149                for( itr = items.begin( ); itr != items.end( ); ++itr )
150                {
151                        pItem = objmgr.LoadItem( *itr );
152                        if( pItem == NULL )
153                                continue;
154
155                        data << uint8(i++);
156            data << pItem->GetLowGUID();
157                        data << pItem->GetEntry();
158
159                        for( j = 0; j < 6; ++j )
160                        {
161                /* Don't remove this please - dfighter
162                                data << pItem->GetUInt32Value( ITEM_FIELD_ENCHANTMENT_1_1 + ( j * 3 ) );
163                                data << pItem->GetUInt32Value( ITEM_FIELD_ENCHANTMENT_2_1 + ( j * 3 ) );
164                                data << pItem->GetUInt32Value( ITEM_FIELD_ENCHANTMENT_3_1 + ( j * 3 ) );
165                */
166
167                data << uint32( pItem->GetEnchantmentId( j ) );
168                data << uint32( pItem->GetEnchantmentId( j + 1 * 3 ) );
169                data << uint32( pItem->GetEnchantmentId( j + 2 * 3 ) );
170                        }
171
172            data << uint32( pItem->GetItemRandomPropertyId() );
173            if( ( (int32)pItem->GetItemRandomPropertyId() ) < 0 )
174                data << uint32( pItem->GetItemRandomSuffixFactor() );
175                        else
176                                data << uint32( 0 );
177
178                        data << uint8( pItem->GetStackCount() );
179                        data << uint32( pItem->GetChargesLeft() );
180            data << uint32( pItem->GetDurabilityMax() );
181            data << uint32( pItem->GetDurability() );
182                        data << uint32( 0 );
183                        data << uint32( 0 );
184                        data << uint32( 0 );
185                        data << uint32( 0 );
186                }
187
188                data.put< uint8 >( pos, i );
189        }
190
191        return true;
192
193}
194
195void MailSystem::SaveMessageToSQL(MailMessage * message)
196{
197        stringstream ss;
198
199
200    ss << "DELETE FROM mailbox WHERE message_id = ";
201    ss << message->message_id;
202    ss << ";";
203
204    CharacterDatabase.ExecuteNA( ss.str().c_str() );
205
206    ss.rdbuf()->str("");
207
208        vector< uint64 >::iterator itr;
209        ss << "INSERT INTO mailbox VALUES("
210                << message->message_id << ","
211                << message->message_type << ","
212                << message->player_guid << ","
213                << message->sender_guid << ",\'"
214                << CharacterDatabase.EscapeString(message->subject) << "\',\'"
215                << CharacterDatabase.EscapeString(message->body) << "\',"
216                << message->money << ",'";
217
218        for( itr = message->items.begin( ); itr != message->items.end( ); ++itr )
219                ss << (*itr) << ",";
220
221        ss << "'," 
222                << message->cod << ","
223                << message->stationery << ","
224                << message->expire_time << ","
225                << message->delivery_time << ","
226                << message->copy_made << ","
227                << message->read_flag << ","
228                << message->deleted_flag << ");";
229       
230    CharacterDatabase.Execute(ss.str().c_str());
231}
232
233void WorldSession::HandleSendMail(WorldPacket & recv_data )
234{
235        MailMessage msg;
236        uint64 gameobject;
237        uint32 unk2;
238        uint8 itemcount;
239        uint8 itemslot;
240        uint8 i;
241        uint64 itemguid;
242        vector< Item* > items;
243        vector< Item* >::iterator itr;
244        string recepient;
245        Item * pItem;
246        //uint32 err = MAIL_OK;
247
248        recv_data >> gameobject >> recepient;
249        recv_data >> msg.subject >> msg.body >> msg.stationery;
250        recv_data >> unk2 >> itemcount;
251
252        if( itemcount > 12 || msg.body.find("%") != string::npos || msg.subject.find("%") != string::npos)
253        {
254                //SystemMessage("Sorry, Ascent does not support sending multiple items at this time. (don't want to lose your item do you) Remove some items, and try again.");
255                SendMailError(MAIL_ERR_INTERNAL_ERROR);
256                return;
257        }
258
259        // Search for the recipient
260        PlayerInfo* player = ObjectMgr::getSingleton().GetPlayerInfoByName(recepient.c_str());
261        if( player == NULL )
262        {
263                SendMailError( MAIL_ERR_RECIPIENT_NOT_FOUND );
264                return;
265        }
266
267        for( i = 0; i < itemcount; ++i )
268        {
269                recv_data >> itemslot;
270                recv_data >> itemguid;
271
272                pItem = _player->GetItemInterface()->GetItemByGUID( itemguid );
273        if( pItem == NULL || pItem->IsSoulbound() || pItem->IsConjured() )
274                {
275                        SendMailError( MAIL_ERR_INTERNAL_ERROR );
276                        return;
277                }
278                if(pItem->IsAccountbound() && GetAccountId() !=  player->acct) // don't mail account-bound items to another account
279                {
280                        SendMailError( MAIL_ERR_INTERNAL_ERROR );
281                        return;
282                }
283
284                items.push_back( pItem );
285        }
286       
287        recv_data >> msg.money;
288        recv_data >> msg.cod;
289        // left over: (TODO- FIX ME BURLEX!)
290        // uint32
291        // uint32
292        // uint8
293       
294        bool interfaction = false;
295        if( sMailSystem.MailOption( MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION ) || (HasGMPermissions() && sMailSystem.MailOption( MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION_GM ) ) )
296        {
297                interfaction = true;
298        }
299
300        // Check we're sending to the same faction (disable this for testing)
301        if( player->team != _player->GetTeam() && !interfaction )
302        {
303                SendMailError( MAIL_ERR_NOT_YOUR_ALLIANCE );
304                return;
305        }
306
307        // Check if we're sending mail to ourselves
308        if( strcmp(player->name, _player->GetName()) == 0 && !GetPermissionCount())
309        {
310                SendMailError(MAIL_ERR_CANNOT_SEND_TO_SELF);
311                return;
312        }
313
314        if( msg.stationery == MAIL_STATIONERY_GM && !HasGMPermissions())
315        {
316                SendMailError(MAIL_ERR_INTERNAL_ERROR);
317                return;
318        }
319
320        // Instant delivery time by default.
321        msg.delivery_time = (uint32)UNIXTIME;
322
323        // Set up the cost
324        int32 cost = 0;
325
326        // Check for attached money
327        if( msg.money > 0 )
328                cost += msg.money;
329
330        if( cost < 0 )
331        {
332                SendMailError(MAIL_ERR_INTERNAL_ERROR);
333                return;
334        }
335
336        if( !sMailSystem.MailOption( MAIL_FLAG_DISABLE_POSTAGE_COSTS ) && !( GetPermissionCount() && sMailSystem.MailOption( MAIL_FLAG_NO_COST_FOR_GM ) ) )
337        {
338                cost += 30;
339                if( cost < 30 )//Overflow prevention for those silly WPE hoez.
340                {
341                        SendMailError(MAIL_ERR_INTERNAL_ERROR);
342                        return;
343                }                       
344        }       
345       
346        // check that we have enough in our backpack
347        if( !_player->HasGold(cost) )
348        {
349                SendMailError( MAIL_ERR_NOT_ENOUGH_MONEY );
350                return;
351        }
352
353        // Check for the item, and required item.
354        if( !items.empty( ) )
355        {
356                for( itr = items.begin(); itr != items.end(); ++itr )
357                {
358                        pItem = *itr;
359                        if( _player->GetItemInterface()->SafeRemoveAndRetreiveItemByGuid(pItem->GetGUID(), false) != pItem )
360                                continue;               // should never be hit.
361
362                        pItem->RemoveFromWorld();
363                        pItem->SetOwner( NULL );
364                        pItem->SaveToDB( INVENTORY_SLOT_NOT_SET, 0, true, NULL );
365            msg.items.push_back( pItem->GetLowGUID() );
366
367                        if( GetPermissionCount() > 0 )
368                        {
369                                /* log the message */
370                                sGMLog.writefromsession(this, "sent mail with item entry %u to %s, with gold %u.", pItem->GetEntry(), player->name, msg.money);
371                        }
372
373                        pItem->DeleteMe();
374                }
375        }
376
377        if(msg.money != 0 || msg.cod != 0 || ( !msg.items.size() && player->acct != _player->GetSession()->GetAccountId()) )
378        {
379                if(!sMailSystem.MailOption(MAIL_FLAG_DISABLE_HOUR_DELAY_FOR_ITEMS))
380                        msg.delivery_time += 3600;  // 1hr
381        }
382
383        // take the money
384        _player->ModGold( -cost );
385
386        // Fill in the rest of the info
387        msg.player_guid = player->guid;
388        msg.sender_guid = _player->GetGUID();
389       
390        // 30 day expiry time for unread mail
391        if(!sMailSystem.MailOption(MAIL_FLAG_NO_EXPIRY))
392                msg.expire_time = (uint32)UNIXTIME + (TIME_DAY * MAIL_DEFAULT_EXPIRATION_TIME);
393        else
394                msg.expire_time = 0;
395
396        msg.copy_made = false;
397        msg.read_flag = false;
398        msg.deleted_flag = false;
399        msg.message_type = 0;
400
401        // Great, all our info is filled in. Now we can add it to the other players mailbox.
402        sMailSystem.DeliverMessage(player->guid, &msg);
403        // Save/Update character's gold if they've received gold that is. This prevents a rollback.
404        CharacterDatabase.Execute("UPDATE characters SET gold = %u WHERE guid = %u", _player->GetGold(), _player->m_playerInfo->guid);
405        // Success packet :)
406        SendMailError(MAIL_OK);
407}
408
409void WorldSession::HandleMarkAsRead(WorldPacket & recv_data )
410{
411        uint64 mailbox;
412        uint32 message_id;
413        recv_data >> mailbox >> message_id;
414
415        MailMessage * message = _player->m_mailBox.GetMessage(message_id);
416        if(message == 0) return;
417
418        // mark the message as read
419        message->read_flag = 1;
420
421        // mail now has a 30 day expiry time
422        if(!sMailSystem.MailOption(MAIL_FLAG_NO_EXPIRY))
423                message->expire_time = (uint32)UNIXTIME + (TIME_DAY * 30);
424
425        // update it in sql
426        CharacterDatabase.WaitExecute("UPDATE mailbox SET read_flag = 1, expiry_time = %u WHERE message_id = %u", message->message_id, message->expire_time);
427}
428
429void WorldSession::HandleMailDelete(WorldPacket & recv_data )
430{
431        uint64 mailbox;
432        uint32 message_id;
433        recv_data >> mailbox >> message_id;
434
435        WorldPacket data(SMSG_SEND_MAIL_RESULT, 12);
436        data << message_id << uint32(MAIL_RES_DELETED);
437
438        MailMessage * message = _player->m_mailBox.GetMessage(message_id);
439        if(message == 0)
440        {
441                data << uint32(MAIL_ERR_INTERNAL_ERROR);
442                SendPacket(&data);
443
444                return;
445        }
446
447        if(message->copy_made)
448        {
449                // we have the message as a copy on the item. we can't delete it or this item
450                // will no longer function.
451
452                // deleted_flag prevents it from being shown in the mail list.
453                message->deleted_flag = 1;
454
455                // update in sql
456                CharacterDatabase.WaitExecute("UPDATE mailbox SET deleted_flag = 1 WHERE message_id = %u", message_id);
457        }
458        else
459        {
460                // delete the message, there are no other references to it.
461                _player->m_mailBox.DeleteMessage(message_id, true);
462        }
463
464        data << uint32(MAIL_OK);
465        SendPacket(&data);
466}
467
468void WorldSession::HandleTakeItem(WorldPacket & recv_data )
469{
470        uint64 mailbox;
471        uint32 message_id;
472        uint32 lowguid;
473        vector< uint64 >::iterator itr;
474
475        recv_data >> mailbox >> message_id >> lowguid;
476
477        WorldPacket data(SMSG_SEND_MAIL_RESULT, 12);
478        data << message_id << uint32(MAIL_RES_ITEM_TAKEN);
479       
480        MailMessage * message = _player->m_mailBox.GetMessage(message_id);
481        if(message == 0 || message->items.empty())
482        {
483                data << uint32(MAIL_ERR_INTERNAL_ERROR);
484                SendPacket(&data);
485
486                return;
487        }
488
489        for( itr = message->items.begin( ); itr != message->items.end( ); ++itr )
490        {
491                if ( (*itr) == lowguid )
492                        break;
493        }
494
495        if( itr == message->items.end( ) )
496        {
497                data << uint32(MAIL_ERR_INTERNAL_ERROR);
498                SendPacket(&data);
499
500                return;
501        }
502
503        // check for cod credit
504        if(message->cod > 0)
505        {
506                if( !_player->HasGold(message->cod) )
507                {
508                        data << uint32(MAIL_ERR_NOT_ENOUGH_MONEY);
509                        SendPacket(&data);
510                        return;
511                }
512        }
513
514        // grab the item
515        Item * item = objmgr.LoadItem( *itr );
516        if(item == 0)
517        {
518                // doesn't exist
519                data << uint32(MAIL_ERR_INTERNAL_ERROR);
520                SendPacket(&data);
521               
522                return;
523        }
524
525        //Find free slot
526        SlotResult result = _player->GetItemInterface()->FindFreeInventorySlot(item->GetProto());
527        if(result.Result == 0)
528        {
529                //End of slots
530                data << uint32(MAIL_ERR_BAG_FULL);
531                SendPacket(&data);
532
533                item->DeleteMe();
534                return;
535        }
536        item->m_isDirty = true;
537       
538        if( !_player->GetItemInterface()->SafeAddItem(item, result.ContainerSlot, result.Slot) )
539        {
540                if( !_player->GetItemInterface()->AddItemToFreeSlot(item) )
541                {
542                        //End of slots
543                        data << uint32(MAIL_ERR_BAG_FULL);
544                        SendPacket(&data);
545                        item->DeleteMe();
546                        return;
547                }
548        }
549        else
550        item->SaveToDB(result.ContainerSlot, result.Slot, true, NULL);
551
552        // send complete packet
553        data << uint32(MAIL_OK);
554    data << item->GetLowGUID();
555        data << item->GetStackCount();
556
557        message->items.erase( itr );
558
559        // re-save (update the items field)
560        sMailSystem.SaveMessageToSQL( message);
561        SendPacket(&data);
562       
563        if( message->cod > 0 )
564        {
565                _player->ModGold( -(int32)message->cod );
566                string subject = "COD Payment: ";
567                subject += message->subject;
568                sMailSystem.SendAutomatedMessage(NORMAL, message->player_guid, message->sender_guid, subject, "", message->cod, 0, 0, MAIL_STATIONERY_TEST1 );
569
570                message->cod = 0;
571                CharacterDatabase.Execute("UPDATE mailbox SET cod = 0 WHERE message_id = %u", message->message_id);
572        }
573
574        // probably need to send an item push here
575}
576
577void WorldSession::HandleTakeMoney(WorldPacket & recv_data )
578{
579        uint64 mailbox;
580        uint32 message_id;
581        recv_data >> mailbox >> message_id;
582
583        WorldPacket data(SMSG_SEND_MAIL_RESULT, 12);
584        data << message_id << uint32(MAIL_RES_MONEY_TAKEN);
585
586        MailMessage * message = _player->m_mailBox.GetMessage(message_id);
587        if(message == 0 || !message->money)
588        {
589                data << uint32(MAIL_ERR_INTERNAL_ERROR);
590                SendPacket(&data);
591
592                return;
593        }
594
595        // Check they don't have more than the max gold
596        if(sWorld.GoldCapEnabled)
597        {
598                if( (_player->GetGold() + message->money) > sWorld.GoldLimit )
599                {
600                        _player->GetItemInterface()->BuildInventoryChangeError(NULL, NULL, INV_ERR_TOO_MUCH_GOLD);
601                        return;
602                }
603        }
604
605        // add the money to the player
606        _player->ModGold( message->money );
607
608        // message no longer has any money
609        message->money = 0;
610
611        // update in sql!
612        CharacterDatabase.WaitExecute("UPDATE mailbox SET money = 0 WHERE message_id = %u", message->message_id);
613
614        // send result
615        data << uint32(MAIL_OK);
616        SendPacket(&data);
617}
618
619void WorldSession::HandleReturnToSender(WorldPacket & recv_data )
620{
621        uint64 mailbox;
622        uint32 message_id;
623        recv_data >> mailbox >> message_id;
624
625        WorldPacket data(SMSG_SEND_MAIL_RESULT, 12);
626        data << message_id << uint32(MAIL_RES_RETURNED_TO_SENDER);
627
628        MailMessage * msg = _player->m_mailBox.GetMessage(message_id);
629        if(msg == 0)
630        {
631                data << uint32(MAIL_ERR_INTERNAL_ERROR);
632                SendPacket(&data);
633
634                return;
635        }
636       
637        // copy into a new struct
638        MailMessage message = *msg;
639
640        // remove the old message
641        _player->m_mailBox.DeleteMessage(message_id, true);
642
643        // re-assign the owner/sender
644        message.player_guid = message.sender_guid;
645        message.sender_guid = _player->GetGUID();
646
647        // turn off the read flag
648        message.read_flag = false;
649        message.deleted_flag = false;
650        message.copy_made = false;
651
652        // null out the cod charges. (the sender doesn't want to have to pay for his own item
653        // that he got nothing for.. :p)
654        message.cod = 0;
655
656        // assign new delivery time
657        message.delivery_time = message.items.empty() ? (uint32)UNIXTIME : (uint32)UNIXTIME + 3600;
658
659        // add to the senders mailbox
660        sMailSystem.DeliverMessage(message.player_guid, &message);
661
662        // finish the packet
663        data << uint32(MAIL_OK);
664        SendPacket(&data);
665}
666
667void WorldSession::HandleMailCreateTextItem(WorldPacket & recv_data )
668{
669        uint64 mailbox;
670        uint32 message_id;
671        recv_data >> mailbox >> message_id;
672
673        WorldPacket data(SMSG_SEND_MAIL_RESULT, 12);
674        data << message_id << uint32(MAIL_RES_MADE_PERMANENT);
675       
676
677        ItemPrototype * proto = ItemPrototypeStorage.LookupEntry(8383);
678        MailMessage * message = _player->m_mailBox.GetMessage(message_id);
679        if(message == 0 || !proto)
680        {
681                data << uint32(MAIL_ERR_INTERNAL_ERROR);
682                SendPacket(&data);
683
684                return;
685        }
686
687        SlotResult result = _player->GetItemInterface()->FindFreeInventorySlot(proto);
688        if(result.Result == 0)
689        {
690                data << uint32(MAIL_ERR_INTERNAL_ERROR);
691                SendPacket(&data);
692
693                return;
694        }
695
696        Item * pItem = objmgr.CreateItem(8383, _player);
697        if (pItem== NULL)
698                return;
699
700        pItem->SetTextId(message_id);
701        if( _player->GetItemInterface()->AddItemToFreeSlot(pItem) )
702        {
703                // mail now has an item after it
704                message->copy_made = true;
705
706                // update in sql
707                CharacterDatabase.WaitExecute("UPDATE mailbox SET copy_made = 1 WHERE message_id = %u", message_id);
708
709                data << uint32(MAIL_OK);
710                SendPacket(&data);
711        }
712        else
713        {
714                pItem->DeleteMe();
715        }
716}
717
718void WorldSession::HandleItemTextQuery(WorldPacket & recv_data)
719{
720        uint32 message_id;
721        recv_data >> message_id;
722
723        string body = "Internal Error";
724
725        MailMessage * msg = _player->m_mailBox.GetMessage(message_id);
726        if(msg)
727                body = msg->body;
728
729        WorldPacket data(SMSG_ITEM_TEXT_QUERY_RESPONSE, body.length() + 5);
730        data << message_id << body;
731        SendPacket(&data);
732}
733
734void Mailbox::FillTimePacket(WorldPacket& data)
735{
736        uint32 c = 0;
737        MessageMap::iterator iter = Messages.begin();
738        data << uint32(0) << uint32(0);
739
740        for(; iter != Messages.end(); ++iter)
741        {
742                if(iter->second.deleted_flag == 0 && iter->second.read_flag == 0 && (uint32)UNIXTIME >= iter->second.delivery_time)
743                {
744                        // unread message, w00t.
745                        ++c;
746                        data << uint64(iter->second.sender_guid);
747                        data << uint32(0);
748                        data << uint32(0);// money or something?
749                        data << uint32(iter->second.stationery);
750                        //data << float(UNIXTIME-iter->second.delivery_time);
751                        data << float(-9.0f);   // maybe the above?
752                }
753        }
754
755        if(c== 0)
756        {
757
758                *(uint32*)(&data.contents()[0])= 0xc7a8c000;
759        }
760        else
761        {
762
763                *(uint32*)(&data.contents()[4])=c;
764        }
765}
766
767void WorldSession::HandleMailTime(WorldPacket & recv_data)
768{
769        WorldPacket data(MSG_QUERY_NEXT_MAIL_TIME, 100);
770        _player->m_mailBox.FillTimePacket(data);
771        SendPacket(&data);
772}
773
774void WorldSession::SendMailError(uint32 error)
775{
776        WorldPacket data(SMSG_SEND_MAIL_RESULT, 12);
777        data << uint32(0);
778        data << uint32(MAIL_RES_MAIL_SENT);
779        data << error;
780        SendPacket(&data);
781}
782
783void WorldSession::HandleGetMail(WorldPacket & recv_data )
784{
785        WorldPacket * data = _player->m_mailBox.BuildMailboxListingPacket();
786        SendPacket(data);
787        delete data;
788}
789
790void MailSystem::RemoveMessageIfDeleted(uint32 message_id, Player * plr)
791{
792        MailMessage * msg = plr->m_mailBox.GetMessage(message_id);
793        if(msg == 0) return;
794
795        if(msg->deleted_flag)   // we've deleted from inbox
796                plr->m_mailBox.DeleteMessage(message_id, true);   // wipe the message
797}
798
799void MailSystem::SendAutomatedMessage(uint32 type, uint64 sender, uint64 receiver, string subject, string body,
800                                                                          uint32 money, uint32 cod, uint64 item_guid, uint32 stationery)
801{
802        // This is for sending automated messages, for example from an auction house.
803        MailMessage msg;
804        msg.message_type = type;
805        msg.sender_guid = sender;
806        msg.player_guid = receiver;
807        msg.subject = subject;
808        msg.body = body;
809        msg.money = money;
810        msg.cod = cod;
811        if( Arcemu::Util::GUID_LOPART(item_guid) != 0 )
812                msg.items.push_back( Arcemu::Util::GUID_LOPART(item_guid) );
813
814        msg.stationery = stationery;
815        msg.delivery_time = (uint32)UNIXTIME;
816        msg.expire_time = 0;
817        msg.read_flag = false;
818        msg.copy_made = false;
819        msg.deleted_flag = false;
820
821        // Send the message.
822        DeliverMessage(receiver, &msg);
823}
824
825uint32 MailSystem::Generate_Message_Id()
826{
827        /** I know this is horrible. But when you have external mail sources unfortunately this is the only way to do this.
828         * - Burlex
829         */
830
831        uint32 id = 1;
832        QueryResult * result = CharacterDatabase.Query("SELECT MAX(message_id) FROM mailbox");
833        if(result)
834        {
835                id = result->Fetch()[0].GetUInt32()+1;
836                delete result;
837        }
838
839        return id;
840}
841
842void Mailbox::Load(QueryResult * result)
843{
844        if(!result)
845                return;
846
847        Field * fields;
848        MailMessage msg;
849        uint32 i;
850        char * str;
851        char * p;
852        uint64 itemguid;
853
854        do 
855        {
856                fields = result->Fetch();
857
858                // Create message struct
859                i = 0;
860                msg.items.clear();
861                msg.message_id = fields[i++].GetUInt32();
862                msg.message_type = fields[i++].GetUInt32();
863                msg.player_guid = fields[i++].GetUInt32();
864                msg.sender_guid = fields[i++].GetUInt32();
865                msg.subject = fields[i++].GetString();
866                msg.body = fields[i++].GetString();
867                msg.money = fields[i++].GetUInt32();
868                str = (char*)fields[i++].GetString();
869                p = strchr(str, ',');
870                if( p == NULL )
871                {
872                        itemguid = atoi(str);
873                        if( itemguid != 0 )
874                                msg.items.push_back( itemguid );
875                }
876                else
877                {
878                        while( p )
879                        {
880                                *p = 0;
881                                p++;
882
883                                itemguid = atoi( str );
884                                if( itemguid != 0 )
885                                        msg.items.push_back( itemguid );
886
887                str = p;
888                                p = strchr( str, ',' );
889                        }
890                }
891
892                msg.cod = fields[i++].GetUInt32();
893                msg.stationery = fields[i++].GetUInt32();
894                msg.expire_time = fields[i++].GetUInt32();
895                msg.delivery_time = fields[i++].GetUInt32();
896                msg.copy_made = fields[i++].GetBool();
897                msg.read_flag = fields[i++].GetBool();
898                msg.deleted_flag = fields[i++].GetBool();
899
900                /*if( msg.copy_made )
901                {
902                        QueryResult * result = CharacterDatabase.Query( "SELECT * FROM playeritems WHERE itemtext = %u", msg.message_id );
903                        if( result == NULL )
904                        {
905                                if( msg.deleted_flag )
906                                        CharacterDatabase.WaitExecute( "DELETE FROM mailbox WHERE message_id = %u", msg.message_id );
907                                else
908                                {
909                                        msg.copy_made = false;
910                                        CharacterDatabase.WaitExecute( "UPDATE mailbox SET copy_made = 0 WHERE message_id = %u", msg.message_id );
911                                }
912                        }
913                        else
914                                delete result;
915                }*/
916
917                // Add to the mailbox
918                AddMessage(&msg);
919
920        } while(result->NextRow());
921}
Note: See TracBrowser for help on using the browser.