GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/eathena/guildrecv.cpp Lines: 1 377 0.3 %
Date: 2018-07-14 Branches: 0 322 0.0 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2009-2010  The Mana Developers
4
 *  Copyright (C) 2011-2018  The ManaPlus Developers
5
 *
6
 *  This file is part of The ManaPlus Client.
7
 *
8
 *  This program is free software; you can redistribute it and/or modify
9
 *  it under the terms of the GNU General Public License as published by
10
 *  the Free Software Foundation; either version 2 of the License, or
11
 *  any later version.
12
 *
13
 *  This program is distributed in the hope that it will be useful,
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 *  GNU General Public License for more details.
17
 *
18
 *  You should have received a copy of the GNU General Public License
19
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 */
21
22
#include "net/eathena/guildrecv.h"
23
24
#include "actormanager.h"
25
#include "configuration.h"
26
#include "notifymanager.h"
27
28
#include "being/localplayer.h"
29
#include "being/playerinfo.h"
30
31
#include "enums/resources/notifytypes.h"
32
33
#include "gui/windows/chatwindow.h"
34
#include "gui/windows/skilldialog.h"
35
#include "gui/windows/socialwindow.h"
36
37
#include "gui/widgets/tabs/chat/guildtab.h"
38
39
#include "net/messagein.h"
40
41
#include "net/eathena/guildhandler.h"
42
43
#include "utils/delete2.h"
44
#include "utils/checkutils.h"
45
#include "utils/gettext.h"
46
47
#include "debug.h"
48
49
namespace EAthena
50
{
51
52
Guild *taGuild = nullptr;
53
54
namespace GuildRecv
55
{
56
    bool showBasicInfo = false;
57
}  // namespace GuildRecv
58
59
void GuildRecv::processGuildCreateResponse(Net::MessageIn &msg)
60
{
61
    const uint8_t flag = msg.readUInt8("flag");
62
63
    switch (flag)
64
    {
65
        case 0:
66
            // Success
67
            NotifyManager::notify(NotifyTypes::GUILD_CREATED);
68
            break;
69
70
        case 1:
71
            // Already in a guild
72
            NotifyManager::notify(NotifyTypes::GUILD_ALREADY);
73
            break;
74
75
        case 2:
76
            // Unable to make (likely name already in use)
77
            NotifyManager::notify(NotifyTypes::GUILD_ALREADY);
78
            break;
79
80
        case 3:
81
            // Emperium check failed
82
            NotifyManager::notify(NotifyTypes::GUILD_EMPERIUM_CHECK_FAILED);
83
            break;
84
85
        default:
86
            // Unknown response
87
            NotifyManager::notify(NotifyTypes::GUILD_ERROR);
88
            break;
89
    }
90
}
91
92
void GuildRecv::processGuildMasterOrMember(Net::MessageIn &msg)
93
{
94
    msg.readInt32("type");  // Type (0x57 for member, 0xd7 for master)
95
}
96
97
void GuildRecv::processGuildBasicInfo(Net::MessageIn &msg)
98
{
99
    const int guildId = msg.readInt32("guild id");
100
    const int level = msg.readInt32("guild level");
101
    const int members = msg.readInt32("connect member");
102
    const int maxMembers = msg.readInt32("max member");
103
    const int avgLevel = msg.readInt32("average level");
104
    const int exp = msg.readInt32("exp");
105
    const int nextExp = msg.readInt32("next exp");
106
    msg.skip(12, "unused");
107
    const int emblem = msg.readInt32("emblem id");
108
    std::string name = msg.readString(24, "guild name");
109
    std::string castle;
110
    std::string master;
111
    if (msg.getVersion() >= 20160622)
112
    {
113
        castle = msg.readString(16, "castles");
114
        msg.readInt32("money, unused");
115
        msg.readBeingId("leader char id");
116
    }
117
    else
118
    {
119
        master = msg.readString(24, "master name");
120
        castle = msg.readString(16, "castles");
121
        msg.readInt32("money, unused");
122
    }
123
124
    if (guildTab != nullptr &&
125
        showBasicInfo)
126
    {
127
        showBasicInfo = false;
128
        // TRANSLATORS: guild info message
129
        guildTab->chatLog(strprintf(_("Guild name: %s"),
130
            name.c_str()),
131
            ChatMsgType::BY_SERVER,
132
            IgnoreRecord_false,
133
            TryRemoveColors_true);
134
        if (!master.empty())
135
        {
136
            // TRANSLATORS: guild info message
137
            guildTab->chatLog(strprintf(_("Guild master: %s"),
138
                master.c_str()),
139
                ChatMsgType::BY_SERVER,
140
                IgnoreRecord_false,
141
                TryRemoveColors_true);
142
        }
143
        // TRANSLATORS: guild info message
144
        guildTab->chatLog(strprintf(_("Guild level: %d"), level),
145
            ChatMsgType::BY_SERVER,
146
            IgnoreRecord_false,
147
            TryRemoveColors_true);
148
        // TRANSLATORS: guild info message
149
        guildTab->chatLog(strprintf(_("Online members: %d"), members),
150
            ChatMsgType::BY_SERVER,
151
            IgnoreRecord_false,
152
            TryRemoveColors_true);
153
        // TRANSLATORS: guild info message
154
        guildTab->chatLog(strprintf(_("Max members: %d"), maxMembers),
155
            ChatMsgType::BY_SERVER,
156
            IgnoreRecord_false,
157
            TryRemoveColors_true);
158
        // TRANSLATORS: guild info message
159
        guildTab->chatLog(strprintf(_("Average level: %d"), avgLevel),
160
            ChatMsgType::BY_SERVER,
161
            IgnoreRecord_false,
162
            TryRemoveColors_true);
163
        // TRANSLATORS: guild info message
164
        guildTab->chatLog(strprintf(_("Guild exp: %d"), exp),
165
            ChatMsgType::BY_SERVER,
166
            IgnoreRecord_false,
167
            TryRemoveColors_true);
168
        // TRANSLATORS: guild info message
169
        guildTab->chatLog(strprintf(_("Guild next exp: %d"), nextExp),
170
            ChatMsgType::BY_SERVER,
171
            IgnoreRecord_false,
172
            TryRemoveColors_true);
173
        // TRANSLATORS: guild info message
174
        guildTab->chatLog(strprintf(_("Guild castle: %s"), castle.c_str()),
175
            ChatMsgType::BY_SERVER,
176
            IgnoreRecord_false,
177
            TryRemoveColors_true);
178
    }
179
180
    Guild *const g = Guild::getGuild(CAST_S16(guildId));
181
    if (g == nullptr)
182
        return;
183
    g->setName(name);
184
    g->setEmblemId(emblem);
185
}
186
187
void GuildRecv::processGuildAlianceInfo(Net::MessageIn &msg)
188
{
189
    const int length = msg.readInt16("len");
190
    if (length < 4)
191
        return;
192
    const int count = (length - 4) / 32;
193
194
    for (int i = 0; i < count; i++)
195
    {
196
        msg.readInt32("opposition");
197
        msg.readInt32("guild id");
198
        msg.readString(24, "guild name");
199
    }
200
}
201
202
void GuildRecv::processGuildMemberList(Net::MessageIn &msg)
203
{
204
    const int length = msg.readInt16("len");
205
    if (length < 4)
206
        return;
207
    int guildSize = 0;
208
    if (msg.getVersion() >= 20161026)
209
    {
210
        guildSize = 34;
211
        reportAlways("missing guild member names");
212
    }
213
    else
214
    {
215
        guildSize = 104;
216
    }
217
218
    const int count = (length - 4) / guildSize;
219
    if (taGuild == nullptr)
220
    {
221
        logger->log1("!taGuild");
222
        return;
223
    }
224
225
    taGuild->clearMembers();
226
227
    int onlineNum = 0;
228
    int totalNum = 0;
229
    for (int i = 0; i < count; i++)
230
    {
231
        const BeingId id = msg.readBeingId("account id");
232
        const int charId = msg.readInt32("char id");
233
        msg.readInt16("hair");
234
        msg.readInt16("hair color");
235
        const int gender = msg.readInt16("gender");
236
        const int race = msg.readInt16("class");
237
        const int level = msg.readInt16("level");
238
        const int exp = msg.readInt32("exp");
239
        const int online = msg.readInt32("online");
240
        const int pos = msg.readInt32("position");
241
        std::string name;
242
        if (msg.getVersion() < 20161026)
243
        {
244
            msg.skip(50, "unused");
245
            name = msg.readString(24, "name");
246
        }
247
        else
248
        {
249
            msg.readInt32("last login");  // for now unused
250
            continue;
251
        }
252
253
        GuildMember *const m = taGuild->addMember(id, charId, name);
254
        if (m != nullptr)
255
        {
256
            m->setOnline(online != 0);
257
            m->setID(id);
258
            m->setCharId(charId);
259
            m->setGender(Being::intToGender(CAST_U8(gender)));
260
            m->setLevel(level);
261
            m->setExp(exp);
262
            m->setPos(pos);
263
            m->setRace(race);
264
            if (actorManager != nullptr)
265
            {
266
                Being *const being = actorManager->findBeingByName(
267
                    name, ActorType::Player);
268
                if (being != nullptr)
269
                {
270
                    being->setGuildName(taGuild->getName());
271
                    if (being->getLevel() != level)
272
                    {
273
                        being->setLevel(level);
274
                        being->updateName();
275
                    }
276
                }
277
            }
278
            if (online != 0)
279
                onlineNum ++;
280
            totalNum ++;
281
        }
282
    }
283
    taGuild->sort();
284
    if (actorManager != nullptr)
285
    {
286
        actorManager->updatePlayerGuild();
287
        actorManager->updatePlayerColors();
288
    }
289
    if (socialWindow != nullptr)
290
        socialWindow->updateGuildCounter(onlineNum, totalNum);
291
}
292
293
void GuildRecv::processGuildPosNameList(Net::MessageIn &msg)
294
{
295
    if (taGuild == nullptr)
296
    {
297
        logger->log1("!taGuild");
298
        return;
299
    }
300
301
    const int length = msg.readInt16("len");
302
    if (length < 4)
303
        return;
304
    const int count = (length - 4) / 28;
305
306
    for (int i = 0; i < count; i++)
307
    {
308
        const int id = msg.readInt32("position id");
309
        const std::string name = msg.readString(24, "position name");
310
        taGuild->addPos(id, name);
311
    }
312
}
313
314
void GuildRecv::processGuildPosInfoList(Net::MessageIn &msg)
315
{
316
    const int length = msg.readInt16("len");
317
    if (length < 4)
318
        return;
319
    const int count = (length - 4) / 16;
320
321
    for (int i = 0; i < count; i++)
322
    {
323
        msg.readInt32("id");
324
        msg.readInt32("mode");
325
        msg.readInt32("same id");
326
        msg.readInt32("exp mode");
327
    }
328
}
329
330
void GuildRecv::processGuildPositionChanged(Net::MessageIn &msg)
331
{
332
    UNIMPLEMENTEDPACKET;
333
    msg.readInt16("len");
334
    msg.readInt32("id");
335
    msg.readInt32("mode");
336
    msg.readInt32("same ip");
337
    msg.readInt32("exp mode");
338
    msg.readString(24, "name");
339
}
340
341
void GuildRecv::processGuildMemberPosChange(Net::MessageIn &msg)
342
{
343
    msg.readInt16("len");
344
    const BeingId accountId = msg.readBeingId("account id");
345
    const int charId = msg.readInt32("char id");
346
    const int pos = msg.readInt32("position");
347
    if (taGuild != nullptr)
348
    {
349
        GuildMember *const m = taGuild->getMember(accountId, charId);
350
        if (m != nullptr)
351
            m->setPos(pos);
352
    }
353
}
354
355
void GuildRecv::processGuildEmblemData(Net::MessageIn &msg)
356
{
357
    UNIMPLEMENTEDPACKET;
358
    const int length = msg.readInt16("len");
359
360
    msg.readInt32("guild id");
361
    msg.readInt32("emblem id");
362
    if (length < 12)
363
        return;
364
    msg.skip(length - 12, "emblem data");
365
}
366
367
void GuildRecv::processGuildSkillInfo(Net::MessageIn &msg)
368
{
369
    const int count = (msg.readInt16("len") - 6) / 37;
370
    msg.readInt16("skill points");
371
372
    if (skillDialog != nullptr)
373
        skillDialog->hideSkills(SkillOwner::Guild);
374
    for (int i = 0; i < count; i++)
375
    {
376
        const int skillId = msg.readInt16("skill id");
377
        const SkillType::SkillType inf = static_cast<SkillType::SkillType>(
378
            msg.readInt32("inf"));
379
        const int level = msg.readInt16("skill level");
380
        const int sp = msg.readInt16("sp");
381
        const int range = msg.readInt16("range");
382
        const std::string name = msg.readString(24, "skill name");
383
        const Modifiable up = fromBool(msg.readUInt8("up flag"), Modifiable);
384
        PlayerInfo::setSkillLevel(skillId, level);
385
        if (skillDialog != nullptr)
386
        {
387
            if (!skillDialog->updateSkill(skillId, range, up, inf, sp))
388
            {
389
                skillDialog->addSkill(SkillOwner::Guild,
390
                    skillId, name, level, range, up, inf, sp);
391
            }
392
        }
393
    }
394
    if (skillDialog != nullptr)
395
        skillDialog->updateModels();
396
}
397
398
void GuildRecv::processGuildNotice(Net::MessageIn &msg)
399
{
400
    if (guildTab != nullptr)
401
    {
402
        const std::string msg1 = msg.readString(60, "msg1");
403
        const std::string msg2 = msg.readString(120, "msg2");
404
        guildTab->chatLog(msg1,
405
            ChatMsgType::BY_SERVER,
406
            IgnoreRecord_false,
407
            TryRemoveColors_true);
408
        guildTab->chatLog(msg2,
409
            ChatMsgType::BY_SERVER,
410
            IgnoreRecord_false,
411
            TryRemoveColors_true);
412
    }
413
    else
414
    {
415
        msg.readString(60, "msg1");
416
        msg.readString(120, "msg2");
417
    }
418
}
419
420
void GuildRecv::processGuildInvite(Net::MessageIn &msg)
421
{
422
    const int guildId = msg.readInt32("guild id");
423
424
    if (socialWindow != nullptr)
425
    {
426
        const std::string guildName = msg.readString(24, "guild name");
427
        socialWindow->showGuildInvite(guildName, guildId, "");
428
    }
429
    else
430
    {
431
        msg.readString(24, "guild name");
432
    }
433
}
434
435
void GuildRecv::processGuildInviteAck(Net::MessageIn &msg)
436
{
437
    const uint8_t flag = msg.readUInt8("flag");
438
    if (guildTab == nullptr)
439
        return;
440
441
    switch (flag)
442
    {
443
        case 0:
444
            NotifyManager::notify(NotifyTypes::GUILD_INVITE_FAILED);
445
            break;
446
447
        case 1:
448
            NotifyManager::notify(NotifyTypes::GUILD_INVITE_REJECTED);
449
            break;
450
451
        case 2:
452
            NotifyManager::notify(NotifyTypes::GUILD_INVITE_JOINED);
453
            break;
454
455
        case 3:
456
            NotifyManager::notify(NotifyTypes::GUILD_INVITE_FULL);
457
            break;
458
459
        default:
460
            NotifyManager::notify(NotifyTypes::GUILD_INVITE_ERROR);
461
            break;
462
    }
463
}
464
465
void GuildRecv::processGuildLeave(Net::MessageIn &msg)
466
{
467
    const std::string nick = msg.readString(24, "nick");
468
    msg.readString(40, "message");
469
470
    if (taGuild != nullptr)
471
        taGuild->removeMember(nick);
472
473
    if (localPlayer == nullptr)
474
        return;
475
476
    if (nick == localPlayer->getName())
477
    {
478
        if (taGuild != nullptr)
479
        {
480
            taGuild->removeFromMembers();
481
            taGuild->clearMembers();
482
            localPlayer->removeGuild(taGuild->getId());
483
        }
484
        NotifyManager::notify(NotifyTypes::GUILD_LEFT);
485
        delete2(guildTab)
486
487
        if ((socialWindow != nullptr) && (taGuild != nullptr))
488
            socialWindow->removeTab(taGuild);
489
        if (actorManager != nullptr)
490
            actorManager->updatePlayerColors();
491
    }
492
    else
493
    {
494
        NotifyManager::notify(NotifyTypes::GUILD_USER_LEFT, nick);
495
        if (actorManager != nullptr)
496
        {
497
            Being *const b = actorManager->findBeingByName(
498
                nick, ActorType::Player);
499
500
            if (b != nullptr)
501
                b->clearGuilds();
502
            if (taGuild != nullptr)
503
                taGuild->removeMember(nick);
504
        }
505
    }
506
}
507
508
void GuildRecv::processGuildMessage(Net::MessageIn &msg)
509
{
510
    const int msgLength = msg.readInt16("len") - 4;
511
512
    if (msgLength <= 0)
513
        return;
514
    if (guildTab != nullptr)
515
    {
516
        std::string chatMsg = msg.readString(msgLength, "message");
517
        const size_t pos = chatMsg.find(" : ", 0);
518
        if (pos != std::string::npos)
519
        {
520
            const std::string sender_name = chatMsg.substr(0, pos);
521
            chatMsg.erase(0, pos + 3);
522
            trim(chatMsg);
523
            guildTab->chatLog(sender_name, chatMsg);
524
        }
525
        else
526
        {
527
            guildTab->chatLog(chatMsg,
528
                ChatMsgType::BY_SERVER,
529
                IgnoreRecord_false,
530
                TryRemoveColors_true);
531
        }
532
    }
533
    else
534
    {
535
        DEBUGLOGSTR("invisible guild?");
536
        msg.readString(msgLength, "message");
537
    }
538
}
539
540
void GuildRecv::processGuildReqAlliance(Net::MessageIn &msg)
541
{
542
    UNIMPLEMENTEDPACKET;
543
    msg.readInt32("id");
544
    msg.readString(24, "name");
545
}
546
547
void GuildRecv::processGuildReqAllianceAck(Net::MessageIn &msg)
548
{
549
    UNIMPLEMENTEDPACKET;
550
    msg.readInt32("flag");
551
}
552
553
void GuildRecv::processGuildDelAlliance(Net::MessageIn &msg)
554
{
555
    UNIMPLEMENTEDPACKET;
556
    msg.readInt32("guild id");
557
    msg.readInt32("flag");
558
}
559
560
void GuildRecv::processGuildOppositionAck(Net::MessageIn &msg)
561
{
562
    UNIMPLEMENTEDPACKET;
563
    msg.readUInt8("flag");
564
}
565
566
void GuildRecv::processGuildBroken(Net::MessageIn &msg)
567
{
568
    UNIMPLEMENTEDPACKET;
569
    msg.readInt32("flag");
570
}
571
572
void GuildRecv::processGuildExpulsionContinue(const std::string &nick)
573
{
574
    if (taGuild != nullptr)
575
        taGuild->removeMember(nick);
576
577
    if (localPlayer == nullptr)
578
        return;
579
580
    if (nick == localPlayer->getName())
581
    {
582
        if (taGuild != nullptr)
583
        {
584
            taGuild->removeFromMembers();
585
            taGuild->clearMembers();
586
        }
587
        NotifyManager::notify(NotifyTypes::GUILD_KICKED);
588
        delete2(guildTab)
589
590
        if ((socialWindow != nullptr) && (taGuild != nullptr))
591
            socialWindow->removeTab(taGuild);
592
        if (actorManager != nullptr)
593
            actorManager->updatePlayerColors();
594
    }
595
    else
596
    {
597
        NotifyManager::notify(NotifyTypes::GUILD_USER_KICKED, nick);
598
        if (actorManager != nullptr)
599
        {
600
            Being *const b = actorManager->findBeingByName(
601
                nick, ActorType::Player);
602
603
            if (b != nullptr)
604
                b->clearGuilds();
605
            if (taGuild != nullptr)
606
                taGuild->removeMember(nick);
607
        }
608
    }
609
}
610
611
void GuildRecv::processGuildUpdateCoords(Net::MessageIn &msg)
612
{
613
    const BeingId id = msg.readBeingId("account id");
614
    const int x = msg.readInt16("x");
615
    const int y = msg.readInt16("y");
616
    if (taGuild != nullptr)
617
    {
618
        GuildMember *const m = taGuild->getMember(id);
619
        if (m != nullptr)
620
        {
621
            m->setX(x);
622
            m->setY(y);
623
        }
624
    }
625
}
626
627
void GuildRecv::processGuildPositionInfo(Net::MessageIn &msg)
628
{
629
    const int guildId =  msg.readInt32("guild id");
630
    const int emblem =  msg.readInt32("elblem id");
631
    PlayerInfo::setGuildPositionFlags(
632
        static_cast<GuildPositionFlags::Type>(msg.readInt32("mode")));
633
    msg.readUInt8("guild master");
634
    msg.readInt32("unused");
635
    std::string guildName = msg.readString(24, "guild name");
636
637
    Guild *const g = Guild::getGuild(CAST_S16(guildId));
638
    if (g == nullptr)
639
        return;
640
641
    g->setName(guildName);
642
    g->setEmblemId(emblem);
643
    if (taGuild == nullptr)
644
        taGuild = g;
645
    if ((guildTab == nullptr) && (chatWindow != nullptr))
646
    {
647
        guildTab = new GuildTab(chatWindow);
648
        if (config.getBoolValue("showChatHistory"))
649
            guildTab->loadFromLogFile("#Guild");
650
        if (localPlayer != nullptr)
651
            localPlayer->addGuild(taGuild);
652
        guildHandler->memberList();
653
    }
654
655
    if (localPlayer != nullptr)
656
    {
657
        localPlayer->setGuild(g);
658
        localPlayer->setGuildName(g->getName());
659
    }
660
}
661
662
void GuildRecv::processGuildMemberLogin(Net::MessageIn &msg)
663
{
664
    const BeingId accountId = msg.readBeingId("account id");
665
    const int charId = msg.readInt32("char id");
666
    const int online = msg.readInt32("flag");
667
    const GenderT gender = Being::intToGender(CAST_U8(
668
        msg.readInt16("sex")));
669
    msg.readInt16("hair");
670
    msg.readInt16("hair color");
671
    if (taGuild != nullptr)
672
    {
673
        GuildMember *const m = taGuild->getMember(accountId, charId);
674
        if (m != nullptr)
675
        {
676
            m->setOnline(online != 0);
677
            if (online != 0)
678
                m->setGender(gender);
679
            if (guildTab != nullptr)
680
                guildTab->showOnline(m->getName(), fromBool(online, Online));
681
            if (socialWindow != nullptr)
682
                socialWindow->updateGuildCounter(0, 0);
683
        }
684
    }
685
}
686
687
void GuildRecv::processGuildExpulsion(Net::MessageIn &msg)
688
{
689
    const std::string nick = msg.readString(24, "name");
690
    msg.readString(40, "message");
691
692
    GuildRecv::processGuildExpulsionContinue(nick);
693
}
694
695
void GuildRecv::processGuildExpulsionList(Net::MessageIn &msg)
696
{
697
    const int length = msg.readInt16("len");
698
    if (length < 4)
699
        return;
700
701
    int count;
702
    if (msg.getVersion() < 20100803)
703
    {
704
        count = (length - 4) / 64;
705
        for (int i = 0; i < count; i++)
706
        {
707
            msg.readString(24, "name");
708
            msg.readString(40, "message");
709
        }
710
    }
711
    else
712
    {
713
        count = (length - 4) / 40;
714
        for (int i = 0; i < count; i++)
715
            msg.readString(40, "message");
716
    }
717
}
718
719
void GuildRecv::processGuildEmblem(Net::MessageIn &msg)
720
{
721
    UNIMPLEMENTEDPACKET;
722
    msg.readBeingId("being id");
723
    msg.readInt32("guild id");
724
    msg.readInt16("emblem id");
725
}
726
727
void GuildRecv::processOnlineInfo(Net::MessageIn &msg)
728
{
729
    // look like unused packet
730
    UNIMPLEMENTEDPACKET;
731
    msg.readBeingId("being id");
732
    msg.readInt32("char id");
733
    msg.readInt32("online");
734
}
735
736
2
}  // namespace EAthena