GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/eathena/guildrecv.cpp Lines: 1 374 0.3 %
Date: 2017-11-29 Branches: 0 320 0.0 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2009-2010  The Mana Developers
4
 *  Copyright (C) 2011-2017  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()), ChatMsgType::BY_SERVER);
131
        if (!master.empty())
132
        {
133
            // TRANSLATORS: guild info message
134
            guildTab->chatLog(strprintf(_("Guild master: %s"),
135
                master.c_str()), ChatMsgType::BY_SERVER);
136
        }
137
        // TRANSLATORS: guild info message
138
        guildTab->chatLog(strprintf(_("Guild level: %d"), level),
139
            ChatMsgType::BY_SERVER);
140
        // TRANSLATORS: guild info message
141
        guildTab->chatLog(strprintf(_("Online members: %d"),
142
            members), ChatMsgType::BY_SERVER);
143
        // TRANSLATORS: guild info message
144
        guildTab->chatLog(strprintf(_("Max members: %d"),
145
            maxMembers), ChatMsgType::BY_SERVER);
146
        // TRANSLATORS: guild info message
147
        guildTab->chatLog(strprintf(_("Average level: %d"),
148
            avgLevel), ChatMsgType::BY_SERVER);
149
        // TRANSLATORS: guild info message
150
        guildTab->chatLog(strprintf(_("Guild exp: %d"), exp),
151
            ChatMsgType::BY_SERVER);
152
        // TRANSLATORS: guild info message
153
        guildTab->chatLog(strprintf(_("Guild next exp: %d"),
154
            nextExp), ChatMsgType::BY_SERVER);
155
        // TRANSLATORS: guild info message
156
        guildTab->chatLog(strprintf(_("Guild castle: %s"),
157
            castle.c_str()), ChatMsgType::BY_SERVER);
158
    }
159
160
    Guild *const g = Guild::getGuild(CAST_S16(guildId));
161
    if (g == nullptr)
162
        return;
163
    g->setName(name);
164
    g->setEmblemId(emblem);
165
}
166
167
void GuildRecv::processGuildAlianceInfo(Net::MessageIn &msg)
168
{
169
    const int length = msg.readInt16("len");
170
    if (length < 4)
171
        return;
172
    const int count = (length - 4) / 32;
173
174
    for (int i = 0; i < count; i++)
175
    {
176
        msg.readInt32("opposition");
177
        msg.readInt32("guild id");
178
        msg.readString(24, "guild name");
179
    }
180
}
181
182
void GuildRecv::processGuildMemberList(Net::MessageIn &msg)
183
{
184
    const int length = msg.readInt16("len");
185
    if (length < 4)
186
        return;
187
    int guildSize = 0;
188
    if (msg.getVersion() >= 20161026)
189
    {
190
        guildSize = 34;
191
        reportAlways("missing guild member names");
192
    }
193
    else
194
    {
195
        guildSize = 104;
196
    }
197
198
    const int count = (length - 4) / guildSize;
199
    if (taGuild == nullptr)
200
    {
201
        logger->log1("!taGuild");
202
        return;
203
    }
204
205
    taGuild->clearMembers();
206
207
    int onlineNum = 0;
208
    int totalNum = 0;
209
    for (int i = 0; i < count; i++)
210
    {
211
        const BeingId id = msg.readBeingId("account id");
212
        const int charId = msg.readInt32("char id");
213
        msg.readInt16("hair");
214
        msg.readInt16("hair color");
215
        const int gender = msg.readInt16("gender");
216
        const int race = msg.readInt16("class");
217
        const int level = msg.readInt16("level");
218
        const int exp = msg.readInt32("exp");
219
        const int online = msg.readInt32("online");
220
        const int pos = msg.readInt32("position");
221
        std::string name;
222
        if (msg.getVersion() < 20161026)
223
        {
224
            msg.skip(50, "unused");
225
            name = msg.readString(24, "name");
226
        }
227
        else
228
        {
229
            msg.readInt32("last login");  // for now unused
230
            continue;
231
        }
232
233
        GuildMember *const m = taGuild->addMember(id, charId, name);
234
        if (m != nullptr)
235
        {
236
            m->setOnline(online != 0);
237
            m->setID(id);
238
            m->setCharId(charId);
239
            m->setGender(Being::intToGender(CAST_U8(gender)));
240
            m->setLevel(level);
241
            m->setExp(exp);
242
            m->setPos(pos);
243
            m->setRace(race);
244
            if (actorManager != nullptr)
245
            {
246
                Being *const being = actorManager->findBeingByName(
247
                    name, ActorType::Player);
248
                if (being != nullptr)
249
                {
250
                    being->setGuildName(taGuild->getName());
251
                    if (being->getLevel() != level)
252
                    {
253
                        being->setLevel(level);
254
                        being->updateName();
255
                    }
256
                }
257
            }
258
            if (online != 0)
259
                onlineNum ++;
260
            totalNum ++;
261
        }
262
    }
263
    taGuild->sort();
264
    if (actorManager != nullptr)
265
    {
266
        actorManager->updatePlayerGuild();
267
        actorManager->updatePlayerColors();
268
    }
269
    if (socialWindow != nullptr)
270
        socialWindow->updateGuildCounter(onlineNum, totalNum);
271
}
272
273
void GuildRecv::processGuildPosNameList(Net::MessageIn &msg)
274
{
275
    if (taGuild == nullptr)
276
    {
277
        logger->log1("!taGuild");
278
        return;
279
    }
280
281
    const int length = msg.readInt16("len");
282
    if (length < 4)
283
        return;
284
    const int count = (length - 4) / 28;
285
286
    for (int i = 0; i < count; i++)
287
    {
288
        const int id = msg.readInt32("position id");
289
        const std::string name = msg.readString(24, "position name");
290
        taGuild->addPos(id, name);
291
    }
292
}
293
294
void GuildRecv::processGuildPosInfoList(Net::MessageIn &msg)
295
{
296
    const int length = msg.readInt16("len");
297
    if (length < 4)
298
        return;
299
    const int count = (length - 4) / 16;
300
301
    for (int i = 0; i < count; i++)
302
    {
303
        msg.readInt32("id");
304
        msg.readInt32("mode");
305
        msg.readInt32("same id");
306
        msg.readInt32("exp mode");
307
    }
308
}
309
310
void GuildRecv::processGuildPositionChanged(Net::MessageIn &msg)
311
{
312
    UNIMPLEMENTEDPACKET;
313
    msg.readInt16("len");
314
    msg.readInt32("id");
315
    msg.readInt32("mode");
316
    msg.readInt32("same ip");
317
    msg.readInt32("exp mode");
318
    msg.readString(24, "name");
319
}
320
321
void GuildRecv::processGuildMemberPosChange(Net::MessageIn &msg)
322
{
323
    msg.readInt16("len");
324
    const BeingId accountId = msg.readBeingId("account id");
325
    const int charId = msg.readInt32("char id");
326
    const int pos = msg.readInt32("position");
327
    if (taGuild != nullptr)
328
    {
329
        GuildMember *const m = taGuild->getMember(accountId, charId);
330
        if (m != nullptr)
331
            m->setPos(pos);
332
    }
333
}
334
335
void GuildRecv::processGuildEmblemData(Net::MessageIn &msg)
336
{
337
    UNIMPLEMENTEDPACKET;
338
    const int length = msg.readInt16("len");
339
340
    msg.readInt32("guild id");
341
    msg.readInt32("emblem id");
342
    if (length < 12)
343
        return;
344
    msg.skip(length - 12, "emblem data");
345
}
346
347
void GuildRecv::processGuildSkillInfo(Net::MessageIn &msg)
348
{
349
    const int count = (msg.readInt16("len") - 6) / 37;
350
    msg.readInt16("skill points");
351
352
    if (skillDialog != nullptr)
353
        skillDialog->hideSkills(SkillOwner::Guild);
354
    for (int i = 0; i < count; i++)
355
    {
356
        const int skillId = msg.readInt16("skill id");
357
        const SkillType::SkillType inf = static_cast<SkillType::SkillType>(
358
            msg.readInt32("inf"));
359
        const int level = msg.readInt16("skill level");
360
        const int sp = msg.readInt16("sp");
361
        const int range = msg.readInt16("range");
362
        const std::string name = msg.readString(24, "skill name");
363
        const Modifiable up = fromBool(msg.readUInt8("up flag"), Modifiable);
364
        PlayerInfo::setSkillLevel(skillId, level);
365
        if (skillDialog != nullptr)
366
        {
367
            if (!skillDialog->updateSkill(skillId, range, up, inf, sp))
368
            {
369
                skillDialog->addSkill(SkillOwner::Guild,
370
                    skillId, name, level, range, up, inf, sp);
371
            }
372
        }
373
    }
374
    if (skillDialog != nullptr)
375
        skillDialog->updateModels();
376
}
377
378
void GuildRecv::processGuildNotice(Net::MessageIn &msg)
379
{
380
    if (guildTab != nullptr)
381
    {
382
        const std::string msg1 = msg.readString(60, "msg1");
383
        const std::string msg2 = msg.readString(120, "msg2");
384
        guildTab->chatLog(msg1, ChatMsgType::BY_SERVER);
385
        guildTab->chatLog(msg2, ChatMsgType::BY_SERVER);
386
    }
387
    else
388
    {
389
        msg.readString(60, "msg1");
390
        msg.readString(120, "msg2");
391
    }
392
}
393
394
void GuildRecv::processGuildInvite(Net::MessageIn &msg)
395
{
396
    const int guildId = msg.readInt32("guild id");
397
398
    if (socialWindow != nullptr)
399
    {
400
        const std::string guildName = msg.readString(24, "guild name");
401
        socialWindow->showGuildInvite(guildName, guildId, "");
402
    }
403
    else
404
    {
405
        msg.readString(24, "guild name");
406
    }
407
}
408
409
void GuildRecv::processGuildInviteAck(Net::MessageIn &msg)
410
{
411
    const uint8_t flag = msg.readUInt8("flag");
412
    if (guildTab == nullptr)
413
        return;
414
415
    switch (flag)
416
    {
417
        case 0:
418
            NotifyManager::notify(NotifyTypes::GUILD_INVITE_FAILED);
419
            break;
420
421
        case 1:
422
            NotifyManager::notify(NotifyTypes::GUILD_INVITE_REJECTED);
423
            break;
424
425
        case 2:
426
            NotifyManager::notify(NotifyTypes::GUILD_INVITE_JOINED);
427
            break;
428
429
        case 3:
430
            NotifyManager::notify(NotifyTypes::GUILD_INVITE_FULL);
431
            break;
432
433
        default:
434
            NotifyManager::notify(NotifyTypes::GUILD_INVITE_ERROR);
435
            break;
436
    }
437
}
438
439
void GuildRecv::processGuildLeave(Net::MessageIn &msg)
440
{
441
    const std::string nick = msg.readString(24, "nick");
442
    msg.readString(40, "message");
443
444
    if (taGuild != nullptr)
445
        taGuild->removeMember(nick);
446
447
    if (localPlayer == nullptr)
448
        return;
449
450
    if (nick == localPlayer->getName())
451
    {
452
        if (taGuild != nullptr)
453
        {
454
            taGuild->removeFromMembers();
455
            taGuild->clearMembers();
456
            localPlayer->removeGuild(taGuild->getId());
457
        }
458
        NotifyManager::notify(NotifyTypes::GUILD_LEFT);
459
        delete2(guildTab)
460
461
        if ((socialWindow != nullptr) && (taGuild != nullptr))
462
            socialWindow->removeTab(taGuild);
463
        if (actorManager != nullptr)
464
            actorManager->updatePlayerColors();
465
    }
466
    else
467
    {
468
        NotifyManager::notify(NotifyTypes::GUILD_USER_LEFT, nick);
469
        if (actorManager != nullptr)
470
        {
471
            Being *const b = actorManager->findBeingByName(
472
                nick, ActorType::Player);
473
474
            if (b != nullptr)
475
                b->clearGuilds();
476
            if (taGuild != nullptr)
477
                taGuild->removeMember(nick);
478
        }
479
    }
480
}
481
482
void GuildRecv::processGuildMessage(Net::MessageIn &msg)
483
{
484
    const int msgLength = msg.readInt16("len") - 4;
485
486
    if (msgLength <= 0)
487
        return;
488
    if (guildTab != nullptr)
489
    {
490
        std::string chatMsg = msg.readString(msgLength, "message");
491
        const size_t pos = chatMsg.find(" : ", 0);
492
        if (pos != std::string::npos)
493
        {
494
            const std::string sender_name = chatMsg.substr(0, pos);
495
            chatMsg.erase(0, pos + 3);
496
            trim(chatMsg);
497
            guildTab->chatLog(sender_name, chatMsg);
498
        }
499
        else
500
        {
501
            guildTab->chatLog(chatMsg, ChatMsgType::BY_SERVER);
502
        }
503
    }
504
    else
505
    {
506
        DEBUGLOGSTR("invisible guild?");
507
        msg.readString(msgLength, "message");
508
    }
509
}
510
511
void GuildRecv::processGuildReqAlliance(Net::MessageIn &msg)
512
{
513
    UNIMPLEMENTEDPACKET;
514
    msg.readInt32("id");
515
    msg.readString(24, "name");
516
}
517
518
void GuildRecv::processGuildReqAllianceAck(Net::MessageIn &msg)
519
{
520
    UNIMPLEMENTEDPACKET;
521
    msg.readInt32("flag");
522
}
523
524
void GuildRecv::processGuildDelAlliance(Net::MessageIn &msg)
525
{
526
    UNIMPLEMENTEDPACKET;
527
    msg.readInt32("guild id");
528
    msg.readInt32("flag");
529
}
530
531
void GuildRecv::processGuildOppositionAck(Net::MessageIn &msg)
532
{
533
    UNIMPLEMENTEDPACKET;
534
    msg.readUInt8("flag");
535
}
536
537
void GuildRecv::processGuildBroken(Net::MessageIn &msg)
538
{
539
    UNIMPLEMENTEDPACKET;
540
    msg.readInt32("flag");
541
}
542
543
void GuildRecv::processGuildExpulsionContinue(const std::string &nick)
544
{
545
    if (taGuild != nullptr)
546
        taGuild->removeMember(nick);
547
548
    if (localPlayer == nullptr)
549
        return;
550
551
    if (nick == localPlayer->getName())
552
    {
553
        if (taGuild != nullptr)
554
        {
555
            taGuild->removeFromMembers();
556
            taGuild->clearMembers();
557
        }
558
        NotifyManager::notify(NotifyTypes::GUILD_KICKED);
559
        delete2(guildTab)
560
561
        if ((socialWindow != nullptr) && (taGuild != nullptr))
562
            socialWindow->removeTab(taGuild);
563
        if (actorManager != nullptr)
564
            actorManager->updatePlayerColors();
565
    }
566
    else
567
    {
568
        NotifyManager::notify(NotifyTypes::GUILD_USER_KICKED, nick);
569
        if (actorManager != nullptr)
570
        {
571
            Being *const b = actorManager->findBeingByName(
572
                nick, ActorType::Player);
573
574
            if (b != nullptr)
575
                b->clearGuilds();
576
            if (taGuild != nullptr)
577
                taGuild->removeMember(nick);
578
        }
579
    }
580
}
581
582
void GuildRecv::processGuildUpdateCoords(Net::MessageIn &msg)
583
{
584
    const BeingId id = msg.readBeingId("account id");
585
    const int x = msg.readInt16("x");
586
    const int y = msg.readInt16("y");
587
    if (taGuild != nullptr)
588
    {
589
        GuildMember *const m = taGuild->getMember(id);
590
        if (m != nullptr)
591
        {
592
            m->setX(x);
593
            m->setY(y);
594
        }
595
    }
596
}
597
598
void GuildRecv::processGuildPositionInfo(Net::MessageIn &msg)
599
{
600
    const int guildId =  msg.readInt32("guild id");
601
    const int emblem =  msg.readInt32("elblem id");
602
    PlayerInfo::setGuildPositionFlags(
603
        static_cast<GuildPositionFlags::Type>(msg.readInt32("mode")));
604
    msg.readUInt8("guild master");
605
    msg.readInt32("unused");
606
    std::string guildName = msg.readString(24, "guild name");
607
608
    Guild *const g = Guild::getGuild(CAST_S16(guildId));
609
    if (g == nullptr)
610
        return;
611
612
    g->setName(guildName);
613
    g->setEmblemId(emblem);
614
    if (taGuild == nullptr)
615
        taGuild = g;
616
    if ((guildTab == nullptr) && (chatWindow != nullptr))
617
    {
618
        guildTab = new GuildTab(chatWindow);
619
        if (config.getBoolValue("showChatHistory"))
620
            guildTab->loadFromLogFile("#Guild");
621
        if (localPlayer != nullptr)
622
            localPlayer->addGuild(taGuild);
623
        guildHandler->memberList();
624
    }
625
626
    if (localPlayer != nullptr)
627
    {
628
        localPlayer->setGuild(g);
629
        localPlayer->setGuildName(g->getName());
630
    }
631
}
632
633
void GuildRecv::processGuildMemberLogin(Net::MessageIn &msg)
634
{
635
    const BeingId accountId = msg.readBeingId("account id");
636
    const int charId = msg.readInt32("char id");
637
    const int online = msg.readInt32("flag");
638
    const GenderT gender = Being::intToGender(CAST_U8(
639
        msg.readInt16("sex")));
640
    msg.readInt16("hair");
641
    msg.readInt16("hair color");
642
    if (taGuild != nullptr)
643
    {
644
        GuildMember *const m = taGuild->getMember(accountId, charId);
645
        if (m != nullptr)
646
        {
647
            m->setOnline(online != 0);
648
            if (online != 0)
649
                m->setGender(gender);
650
            if (guildTab != nullptr)
651
                guildTab->showOnline(m->getName(), fromBool(online, Online));
652
            if (socialWindow != nullptr)
653
                socialWindow->updateGuildCounter();
654
        }
655
    }
656
}
657
658
void GuildRecv::processGuildExpulsion(Net::MessageIn &msg)
659
{
660
    const std::string nick = msg.readString(24, "name");
661
    msg.readString(40, "message");
662
663
    GuildRecv::processGuildExpulsionContinue(nick);
664
}
665
666
void GuildRecv::processGuildExpulsionList(Net::MessageIn &msg)
667
{
668
    const int length = msg.readInt16("len");
669
    if (length < 4)
670
        return;
671
672
    int count;
673
    if (msg.getVersion() < 20100803)
674
    {
675
        count = (length - 4) / 64;
676
        for (int i = 0; i < count; i++)
677
        {
678
            msg.readString(24, "name");
679
            msg.readString(40, "message");
680
        }
681
    }
682
    else
683
    {
684
        count = (length - 4) / 40;
685
        for (int i = 0; i < count; i++)
686
            msg.readString(40, "message");
687
    }
688
}
689
690
void GuildRecv::processGuildEmblem(Net::MessageIn &msg)
691
{
692
    UNIMPLEMENTEDPACKET;
693
    msg.readBeingId("being id");
694
    msg.readInt32("guild id");
695
    msg.readInt16("emblem id");
696
}
697
698
void GuildRecv::processOnlineInfo(Net::MessageIn &msg)
699
{
700
    // look like unused packet
701
    UNIMPLEMENTEDPACKET;
702
    msg.readBeingId("being id");
703
    msg.readInt32("char id");
704
    msg.readInt32("online");
705
}
706
707
4
}  // namespace EAthena