GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/eathena/chatrecv.cpp Lines: 2 394 0.5 %
Date: 2019-10-15 Branches: 2 381 0.5 %

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

3
}  // namespace EAthena