GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/eathena/chatrecv.cpp Lines: 2 394 0.5 %
Date: 2017-11-29 Branches: 2 339 0.6 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2004-2009  The Mana World Development Team
4
 *  Copyright (C) 2009-2010  The Mana Developers
5
 *  Copyright (C) 2011-2017  The ManaPlus Developers
6
 *
7
 *  This file is part of The ManaPlus Client.
8
 *
9
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 2 of the License, or
12
 *  any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
#include "net/eathena/chatrecv.h"
24
25
#include "actormanager.h"
26
#include "notifymanager.h"
27
28
#include "being/localplayer.h"
29
#include "being/playerinfo.h"
30
#include "being/playerrelation.h"
31
#include "being/playerrelations.h"
32
33
#include "const/gui/chat.h"
34
35
#include "enums/resources/notifytypes.h"
36
37
#include "gui/windows/chatwindow.h"
38
39
#include "gui/widgets/tabs/chat/chattab.h"
40
41
#include "net/messagein.h"
42
43
#include "net/ea/chatrecv.h"
44
45
#include "net/eathena/mercenaryrecv.h"
46
47
#include "resources/chatobject.h"
48
#include "utils/gettext.h"
49
#include "utils/stringutils.h"
50
51
#include "debug.h"
52
53
namespace EAthena
54
{
55
56
namespace ChatRecv
57
{
58
2
    std::string mChatRoom;
59
}  // namespace ChatRecv
60
61
void ChatRecv::processIgnoreNickAck(Net::MessageIn &msg)
62
{
63
    const int type = msg.readUInt8("type");
64
    const int flag = msg.readUInt8("flag");
65
    switch (type)
66
    {
67
        case 0:
68
            switch (flag)
69
            {
70
                case 0:
71
                    NotifyManager::notify(NotifyTypes::IGNORE_PLAYER_SUCCESS);
72
                    break;
73
                case 1:
74
                    NotifyManager::notify(NotifyTypes::IGNORE_PLAYER_FAILURE);
75
                    break;
76
                case 2:
77
                    NotifyManager::notify(NotifyTypes::IGNORE_PLAYER_TOO_MANY);
78
                    break;
79
                default:
80
                    NotifyManager::notify(NotifyTypes::IGNORE_PLAYER_UNKNOWN);
81
                    break;
82
            }
83
            break;
84
        case 1:
85
            switch (flag)
86
            {
87
                case 0:
88
                    NotifyManager::notify(
89
                        NotifyTypes::UNIGNORE_PLAYER_SUCCESS);
90
                    break;
91
                case 1:
92
                    NotifyManager::notify(
93
                        NotifyTypes::UNIGNORE_PLAYER_FAILURE);
94
                    break;
95
                default:
96
                    NotifyManager::notify(
97
                        NotifyTypes::UNIGNORE_PLAYER_UNKNOWN);
98
                    break;
99
            }
100
            break;
101
102
        default:
103
            NotifyManager::notify(NotifyTypes::IGNORE_PLAYER_TYPE_UNKNOWN);
104
            break;
105
    }
106
}
107
108
void ChatRecv::processChat(Net::MessageIn &msg)
109
{
110
    BLOCK_START("ChatRecv::processChat")
111
    const int chatMsgLength = msg.readInt16("len") - 4;
112
    if (chatMsgLength <= 0)
113
    {
114
        BLOCK_END("ChatRecv::processChat")
115
        return;
116
    }
117
118
    processChatContinue(msg.readRawString(chatMsgLength, "message"),
119
        ChatMsgType::BY_PLAYER);
120
}
121
122
void ChatRecv::processFormatMessage(Net::MessageIn &msg)
123
{
124
    const int msgId = msg.readInt16("msg id");
125
    // +++ here need load message from configuration file
126
    std::string chatMsg;
127
    if (msgId >= 1266 && msgId <= 1269)
128
    {
129
        MercenaryRecv::handleMercenaryMessage(msgId - 1266);
130
        return;
131
    }
132
    switch (msgId)
133
    {
134
        case 1334:
135
            // TRANSLATORS: error message
136
            chatMsg = _("Can't cast skill in this area.");
137
            break;
138
        case 1335:
139
            // TRANSLATORS: error message
140
            chatMsg = _("Can't use item in this area.");
141
            break;
142
        case 1773:
143
            // TRANSLATORS: error message
144
            chatMsg = _("Can't equip. Wrong level.");
145
            break;
146
        case 1774:
147
            // TRANSLATORS: error message
148
            chatMsg = _("Can't use. Wrong level.");
149
            break;
150
        case 1923:
151
            // TRANSLATORS: error message
152
            chatMsg = _("Work in progress.");  // busy with npc
153
            break;
154
        default:
155
            chatMsg = strprintf("Message #%d", msgId);
156
            break;
157
    }
158
    processChatContinue(chatMsg, ChatMsgType::BY_SERVER);
159
}
160
161
void ChatRecv::processFormatMessageNumber(Net::MessageIn &msg)
162
{
163
    const int msgId = msg.readInt16("msg id");
164
    const int value = msg.readInt32("value");
165
    if (msgId == 1862)
166
    {
167
        NotifyManager::notify(NotifyTypes::USE_ITEM_WAIT, value);
168
        return;
169
    }
170
    // +++ here need load message from configuration file
171
    const std::string chatMsg = strprintf(
172
        "Message #%d, value: %d", msgId, value);
173
    processChatContinue(chatMsg, ChatMsgType::BY_SERVER);
174
}
175
176
void ChatRecv::processFormatMessageSkill(Net::MessageIn &msg)
177
{
178
    const int skillId = msg.readInt16("skill id");
179
    const int msgId = msg.readInt32("msg id");
180
    // +++ here need load message from configuration file
181
    const std::string chatMsg = strprintf(
182
        "Message #%d, skill: %d", msgId, skillId);
183
    processChatContinue(chatMsg, ChatMsgType::BY_SERVER);
184
}
185
186
void ChatRecv::processColorChat(Net::MessageIn &msg)
187
{
188
    BLOCK_START("ChatRecv::processChat")
189
    int chatMsgLength = msg.readInt16("len") - 4;
190
    msg.readInt32("unused");
191
    msg.readInt32("chat color");
192
    chatMsgLength -= 8;
193
    if (chatMsgLength <= 0)
194
    {
195
        BLOCK_END("ChatRecv::processChat")
196
        return;
197
    }
198
199
    std::string message = msg.readRawString(chatMsgLength, "message");
200
    std::string msg2 = message;
201
    if (findCutFirst(msg2, "You're now in the '#") && findCutLast(msg2, "'"))
202
    {
203
        const size_t idx = msg2.find("' channel for '");
204
        if (idx != std::string::npos && (chatWindow != nullptr))
205
        {
206
            chatWindow->addChannelTab(std::string("#").append(
207
                msg2.substr(0, idx)), false);
208
            return;
209
        }
210
    }
211
    else
212
    {
213
        const std::string nick = Ea::ChatRecv::getLastWhisperNick();
214
        if (nick.size() > 1 && nick[0] == '#')
215
        {
216
            if (message == strprintf("[ %s ] %s : \302\202\302",
217
                nick.c_str(), localPlayer->getName().c_str()))
218
            {
219
                Ea::ChatRecv::mSentWhispers.pop();
220
            }
221
        }
222
    }
223
    processChatContinue(message, ChatMsgType::BY_UNKNOWN);
224
}
225
226
std::string ChatRecv::extractChannelFromMessage(std::string &chatMsg)
227
{
228
    std::string msg = chatMsg;
229
    std::string channel(GENERAL_CHANNEL);
230
    if (findCutFirst(msg, "[ #"))
231
    {   // found channel message
232
        const size_t idx = msg.find(" ] ");
233
        if (idx != std::string::npos)
234
        {
235
            channel = std::string("#").append(msg.substr(0, idx));
236
            chatMsg = msg.substr(idx + 3);
237
        }
238
    }
239
    return channel;
240
}
241
242
void ChatRecv::processChatContinue(std::string chatMsg,
243
                                   const ChatMsgTypeT own)
244
{
245
    const std::string channel = extractChannelFromMessage(chatMsg);
246
    bool allow(true);
247
    if (chatWindow != nullptr)
248
    {
249
        allow = chatWindow->resortChatLog(chatMsg,
250
            own,
251
            channel,
252
            IgnoreRecord_false,
253
            TryRemoveColors_true);
254
    }
255
256
    const size_t pos = chatMsg.find(" : ", 0);
257
    if (pos != std::string::npos)
258
        chatMsg.erase(0, pos + 3);
259
260
    trim(chatMsg);
261
262
    if (localPlayer != nullptr)
263
    {
264
        if (((chatWindow != nullptr) || Ea::ChatRecv::mShowMotd) && allow)
265
            localPlayer->setSpeech(chatMsg, GENERAL_CHANNEL);
266
    }
267
    BLOCK_END("ChatRecv::processChat")
268
}
269
270
void ChatRecv::processGmChat(Net::MessageIn &msg)
271
{
272
    BLOCK_START("ChatRecv::processChat")
273
    const int chatMsgLength = msg.readInt16("len") - 4;
274
    if (chatMsgLength <= 0)
275
    {
276
        BLOCK_END("ChatRecv::processChat")
277
        return;
278
    }
279
280
    std::string chatMsg = msg.readRawString(chatMsgLength, "message");
281
    // remove non persistend "colors" from server.
282
    if (!findCutFirst(chatMsg, "ssss"))
283
        findCutFirst(chatMsg, "eulb");
284
285
    if (chatWindow != nullptr)
286
        chatWindow->addGlobalMessage(chatMsg);
287
    BLOCK_END("ChatRecv::processChat")
288
}
289
290
void ChatRecv::processGmChat2(Net::MessageIn &msg)
291
{
292
    const int chatMsgLength = msg.readInt16("len") - 16;
293
    msg.readInt32("font color");
294
    msg.readInt16("font type");
295
    msg.readInt16("font size");
296
    msg.readInt16("font align");
297
    msg.readInt16("font y");
298
    if (chatWindow != nullptr)
299
    {
300
        const std::string chatMsg = msg.readRawString(chatMsgLength,
301
            "message");
302
        chatWindow->addGlobalMessage(chatMsg);
303
    }
304
    else
305
    {
306
        msg.readRawString(chatMsgLength, "message");
307
    }
308
}
309
310
void ChatRecv::processWhisper(Net::MessageIn &msg)
311
{
312
    BLOCK_START("ChatRecv::processWhisper")
313
    int packetLen = 28;
314
    if (msg.getVersion() >= 20091104)
315
        packetLen += 4;
316
    const int chatMsgLength = msg.readInt16("len") - packetLen;
317
    std::string nick = msg.readString(24, "nick");
318
    if (msg.getVersion() >= 20091104)
319
        msg.readInt32("admin flag");
320
321
    if (chatMsgLength <= 0)
322
    {
323
        BLOCK_END("ChatRecv::processWhisper")
324
        return;
325
    }
326
327
    processWhisperContinue(nick, msg.readString(chatMsgLength, "message"));
328
}
329
330
void ChatRecv::processWhisperResponse(Net::MessageIn &msg)
331
{
332
    BLOCK_START("ChatRecv::processWhisperResponse")
333
334
    const uint8_t type = msg.readUInt8("response");
335
    if (msg.getVersion() >= 20131223)
336
        msg.readInt32("unknown");
337
    if (type == 1 && (chatWindow != nullptr))
338
    {
339
        const std::string nick = Ea::ChatRecv::getLastWhisperNick();
340
        if (nick.size() > 1 && nick[0] == '#')
341
        {
342
            chatWindow->channelChatLog(nick,
343
                // TRANSLATORS: chat message
344
                strprintf(_("Message could not be sent, channel "
345
                "%s is not exists."), nick.c_str()),
346
                ChatMsgType::BY_SERVER,
347
                IgnoreRecord_false,
348
                TryRemoveColors_false);
349
            if (!Ea::ChatRecv::mSentWhispers.empty())
350
                Ea::ChatRecv::mSentWhispers.pop();
351
            return;
352
        }
353
    }
354
    Ea::ChatRecv::processWhisperResponseContinue(msg, type);
355
}
356
357
void ChatRecv::processChatIgnoreList(Net::MessageIn &msg)
358
{
359
    UNIMPLEMENTEDPACKET;
360
    // +++ need put it in some object or window
361
    const int count = (msg.readInt16("len") - 4) / 24;
362
    for (int f = 0; f < count; f ++)
363
        msg.readString(24, "nick");
364
}
365
366
void ChatRecv::processChatDisplay(Net::MessageIn &msg)
367
{
368
    const int len = msg.readInt16("len") - 17;
369
    ChatObject *const obj = new ChatObject;
370
    obj->ownerId = msg.readBeingId("owner account id");
371
    obj->chatId = msg.readInt32("chat id");
372
    obj->maxUsers = msg.readInt16("max users");
373
    obj->currentUsers = msg.readInt16("current users");
374
    obj->type = msg.readUInt8("type");
375
    obj->title = msg.readString(len, "title");
376
    obj->update();
377
378
    Being *const dstBeing = actorManager->findBeing(obj->ownerId);
379
    if (dstBeing != nullptr)
380
        dstBeing->setChat(obj);
381
}
382
383
void ChatRecv::processChatRoomJoinAck(Net::MessageIn &msg)
384
{
385
    const int count = (msg.readInt16("len") - 8) / 28;
386
    const int id = msg.readInt32("chat id");
387
388
    // +++ ignore chat members for now
389
    for (int f = 0; f < count; f ++)
390
    {
391
        msg.readInt32("role");
392
        msg.readString(24, "name");
393
    }
394
395
    const ChatObject *const oldChat = ChatObject::findById(id);
396
397
    if (oldChat != nullptr)
398
        PlayerInfo::setRoomName(oldChat->title);
399
    else
400
        PlayerInfo::setRoomName(std::string());
401
    chatWindow->joinRoom(true);
402
    ChatObject *const obj = new ChatObject;
403
    if (oldChat != nullptr)
404
    {
405
        obj->ownerId = oldChat->ownerId;
406
        obj->chatId = oldChat->chatId;
407
        obj->maxUsers = oldChat->maxUsers;
408
        obj->currentUsers = oldChat->currentUsers;
409
        obj->type = oldChat->type;
410
        obj->title = oldChat->title;
411
//        obj->update();
412
    }
413
    localPlayer->setChat(obj);
414
}
415
416
void ChatRecv::processChatRoomLeave(Net::MessageIn &msg)
417
{
418
    msg.readInt16("users");
419
    const std::string name = msg.readString(24, "name");
420
    const int status = msg.readUInt8("flag");  // 0 - left, 1 - kicked
421
    switch (status)
422
    {
423
        case 0:
424
            NotifyManager::notify(NotifyTypes::ROOM_LEAVE, name);
425
            break;
426
        case 1:
427
            NotifyManager::notify(NotifyTypes::ROOM_KICKED, name);
428
            break;
429
        default:
430
            UNIMPLEMENTEDPACKETFIELD(status);
431
            break;
432
    }
433
    if ((localPlayer != nullptr) && name == localPlayer->getName())
434
    {
435
        if (chatWindow != nullptr)
436
            chatWindow->joinRoom(false);
437
        PlayerInfo::setRoomName(std::string());
438
        if (localPlayer != nullptr)
439
            localPlayer->setChat(nullptr);
440
    }
441
    else
442
    {
443
        Being *const being = actorManager->findBeingByName(
444
            name, ActorType::Player);
445
        if (being != nullptr)
446
            being->setChat(nullptr);
447
    }
448
}
449
450
void ChatRecv::processJoinChannel(Net::MessageIn &msg)
451
{
452
    if (chatWindow == nullptr)
453
        return;
454
455
    const std::string channel = msg.readString(24, "channel name");
456
    const int flag = msg.readUInt8("flag");
457
458
    if (channel.size() < 2)
459
        return;
460
    switch (flag)
461
    {
462
        case 0:
463
        default:
464
            chatWindow->channelChatLog(channel,
465
                // TRANSLATORS: chat message
466
                strprintf(_("Can't open channel. Channel "
467
                "%s is not exists."), channel.c_str()),
468
                ChatMsgType::BY_SERVER,
469
                IgnoreRecord_false,
470
                TryRemoveColors_false);
471
            break;
472
473
        case 1:
474
        case 2:
475
            chatWindow->addChannelTab(std::string("#").append(
476
                channel.substr(1)), false);
477
            break;
478
    }
479
}
480
481
void ChatRecv::processWhisperContinue(const std::string &nick,
482
                                      std::string chatMsg)
483
{
484
    // ignoring future whisper messages
485
    if (chatMsg.find("\302\202G") == 0 || chatMsg.find("\302\202A") == 0)
486
    {
487
        BLOCK_END("ChatRecv::processWhisper")
488
        return;
489
    }
490
    // remove first unicode space if this is may be whisper command.
491
    if (chatMsg.find("\302\202!") == 0)
492
        chatMsg = chatMsg.substr(2);
493
494
    if (nick != "Server")
495
    {
496
        if (playerRelations.hasPermission(nick, PlayerRelation::WHISPER))
497
            chatWindow->addWhisper(nick, chatMsg);
498
    }
499
    else if (localChatTab != nullptr)
500
    {
501
        localChatTab->chatLog(chatMsg, ChatMsgType::BY_SERVER);
502
    }
503
    BLOCK_END("ChatRecv::processWhisper")
504
}
505
506
void ChatRecv::processBeingChat(Net::MessageIn &msg)
507
{
508
    if (actorManager == nullptr)
509
        return;
510
511
    BLOCK_START("ChatRecv::processBeingChat")
512
    const int chatMsgLength = msg.readInt16("len") - 8;
513
    Being *const being = actorManager->findBeing(msg.readBeingId("being id"));
514
515
    if (chatMsgLength <= 0)
516
    {
517
        BLOCK_END("ChatRecv::processBeingChat")
518
        return;
519
    }
520
521
    std::string chatMsg = msg.readRawString(chatMsgLength, "message");
522
523
    if ((being != nullptr) && being->getType() == ActorType::Player)
524
        being->setTalkTime();
525
526
    const size_t pos = chatMsg.find(" : ", 0);
527
    std::string sender_name = ((pos == std::string::npos)
528
        ? "" : chatMsg.substr(0, pos));
529
530
    if ((being != nullptr) && sender_name != being->getName()
531
        && being->getType() == ActorType::Player)
532
    {
533
        if (!being->getName().empty())
534
            sender_name = being->getName();
535
    }
536
    else
537
    {
538
        chatMsg.erase(0, pos + 3);
539
    }
540
541
    trim(chatMsg);
542
543
    bool allow(true);
544
    // We use getIgnorePlayer instead of ignoringPlayer here
545
    // because ignorePlayer' side effects are triggered
546
    // right below for Being::IGNORE_SPEECH_FLOAT.
547
    if ((playerRelations.checkPermissionSilently(sender_name,
548
        PlayerRelation::SPEECH_LOG) != 0u) && (chatWindow != nullptr))
549
    {
550
        allow = chatWindow->resortChatLog(
551
            removeColors(sender_name).append(" : ").append(chatMsg),
552
            ChatMsgType::BY_OTHER,
553
            GENERAL_CHANNEL,
554
            IgnoreRecord_false,
555
            TryRemoveColors_true);
556
    }
557
558
    if (allow &&
559
        being != nullptr &&
560
        playerRelations.hasPermission(sender_name,
561
        PlayerRelation::SPEECH_FLOAT))
562
    {
563
        being->setSpeech(chatMsg, GENERAL_CHANNEL);
564
    }
565
    BLOCK_END("ChatRecv::processBeingChat")
566
}
567
568
void ChatRecv::processChatRoomCreateAck(Net::MessageIn &msg)
569
{
570
    const int result = msg.readUInt8("flag");
571
    switch (result)
572
    {
573
        case 0:
574
        {
575
            PlayerInfo::setRoomName(mChatRoom);
576
            chatWindow->joinRoom(true);
577
            ChatObject *const obj = new ChatObject;
578
            obj->ownerId = localPlayer->getId();
579
            obj->chatId = 0;
580
            obj->maxUsers = 1000;
581
            obj->currentUsers = 1;
582
            obj->type = 1;
583
            obj->title = mChatRoom;
584
            obj->update();
585
            localPlayer->setChat(obj);
586
            break;
587
        }
588
        case 1:
589
            NotifyManager::notify(NotifyTypes::ROOM_LIMIT_EXCEEDED);
590
            break;
591
        case 2:
592
            NotifyManager::notify(NotifyTypes::ROOM_ALREADY_EXISTS);
593
            break;
594
        default:
595
            UNIMPLEMENTEDPACKETFIELD(result);
596
            break;
597
    }
598
    mChatRoom.clear();
599
}
600
601
void ChatRecv::processChatRoomDestroy(Net::MessageIn &msg)
602
{
603
    const int chatId = msg.readInt32("chat id");
604
    actorManager->removeRoom(chatId);
605
}
606
607
void ChatRecv::processChatRoomJoinFailed(Net::MessageIn &msg)
608
{
609
    const int result = msg.readUInt8("flag");
610
    switch (result)
611
    {
612
        case 0:
613
            NotifyManager::notify(NotifyTypes::ROOM_ERROR_FULL);
614
            break;
615
        case 1:
616
            NotifyManager::notify(NotifyTypes::ROOM_ERROR_WRONG_PASSWORD);
617
            break;
618
        case 2:
619
            NotifyManager::notify(NotifyTypes::ROOM_ERROR_KICKED);
620
            break;
621
        case 3:
622
            break;
623
        case 4:
624
            NotifyManager::notify(NotifyTypes::ROOM_ERROR_ZENY);
625
            break;
626
        case 5:
627
            NotifyManager::notify(NotifyTypes::ROOM_ERROR_LOW_LEVEL);
628
            break;
629
        case 6:
630
            NotifyManager::notify(NotifyTypes::ROOM_ERROR_HIGH_LEVEL);
631
            break;
632
        case 7:
633
            NotifyManager::notify(NotifyTypes::ROOM_ERROR_RACE);
634
            break;
635
        default:
636
            UNIMPLEMENTEDPACKETFIELD(result);
637
            break;
638
    }
639
}
640
641
void ChatRecv::processChatRoomAddMember(Net::MessageIn &msg)
642
{
643
    msg.readInt16("users");
644
    const std::string name = msg.readString(24, "name");
645
    if (localChatTab == nullptr)
646
        return;
647
    NotifyManager::notify(NotifyTypes::ROOM_JOINED, name);
648
}
649
650
void ChatRecv::processChatRoomSettings(Net::MessageIn &msg)
651
{
652
    const int sz = msg.readInt16("len") - 17;
653
    const BeingId ownerId = msg.readBeingId("owner id");
654
    const int chatId = msg.readInt32("chat id");
655
    const uint16_t limit = msg.readInt16("limit");
656
    msg.readInt16("users");
657
    const uint8_t type = msg.readUInt8("type");
658
    const std::string &title = msg.readString(sz, "title");
659
    ChatObject *const chat = localPlayer->getChat();
660
    if ((chat != nullptr) && chat->chatId == chatId)
661
    {
662
        chat->ownerId = ownerId;
663
        chat->maxUsers = limit;
664
        chat->type = type;
665
        if (chat->title != title)
666
        {
667
            chat->title = title;
668
            actorManager->updateRoom(chat);
669
            chatWindow->joinRoom(true);
670
        }
671
    }
672
}
673
674
void ChatRecv::processChatRoomRoleChange(Net::MessageIn &msg)
675
{
676
    const int role = msg.readInt32("role");
677
    const std::string name = msg.readString(24, "name");
678
    switch (role)
679
    {
680
        case 0:
681
            NotifyManager::notify(NotifyTypes::ROOM_ROLE_OWNER, name);
682
            break;
683
        case 1:
684
            // dont show normal role
685
            break;
686
        default:
687
            UNIMPLEMENTEDPACKETFIELD(role);
688
            break;
689
    }
690
}
691
692
void ChatRecv::processMVPItem(Net::MessageIn &msg)
693
{
694
    UNIMPLEMENTEDPACKET;
695
    msg.readInt16("item id");
696
}
697
698
void ChatRecv::processMVPExp(Net::MessageIn &msg)
699
{
700
    UNIMPLEMENTEDPACKET;
701
    msg.readInt32("exo");
702
}
703
704
void ChatRecv::processMVPNoItem(Net::MessageIn &msg)
705
{
706
    UNIMPLEMENTEDPACKET;
707
}
708
709
void ChatRecv::processMannerMessage(Net::MessageIn &msg)
710
{
711
    const int result = msg.readInt32("type");
712
    switch (result)
713
    {
714
        case 0:
715
            NotifyManager::notify(NotifyTypes::MANNER_CHANGED);
716
            break;
717
        case 5:
718
            break;
719
        default:
720
            UNIMPLEMENTEDPACKETFIELD(result);
721
            break;
722
    }
723
}
724
725
void ChatRecv::processChatSilence(Net::MessageIn &msg)
726
{
727
    const int result = msg.readUInt8("type");
728
    const std::string name = msg.readString(24, "gm name");
729
730
    switch (result)
731
    {
732
        case 0:
733
            NotifyManager::notify(NotifyTypes::MANNER_POSITIVE_POINTS, name);
734
            break;
735
        case 1:
736
            NotifyManager::notify(NotifyTypes::MANNER_NEGATIVE_POINTS, name);
737
            break;
738
        default:
739
            UNIMPLEMENTEDPACKETFIELD(result);
740
            break;
741
    }
742
}
743
744
void ChatRecv::processChatTalkieBox(Net::MessageIn &msg)
745
{
746
    msg.readBeingId("being id");
747
    const std::string message = msg.readString(80, "message");
748
    localChatTab->chatLog(message, ChatMsgType::BY_SERVER);
749
}
750
751
void ChatRecv::processBattleChatMessage(Net::MessageIn &msg)
752
{
753
    UNIMPLEMENTEDPACKET;
754
    const int sz = msg.readInt16("len") - 24 - 8;
755
    msg.readBeingId("account id");
756
    msg.readString(24, "nick");
757
    msg.readString(sz, "message");
758
}
759
760
void ChatRecv::processScriptMessage(Net::MessageIn &msg)
761
{
762
    const int sz = msg.readInt16("len") - 8;
763
    msg.readBeingId("being id");
764
    const std::string message = msg.readString(sz, "message");
765
    localChatTab->chatLog(message, ChatMsgType::BY_SERVER);
766
}
767
768

6
}  // namespace EAthena