GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/eathena/partyrecv.cpp Lines: 1 213 0.5 %
Date: 2021-03-17 Branches: 0 262 0.0 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2008  Lloyd Bryant <[email protected]>
4
 *  Copyright (C) 2011-2019  The ManaPlus Developers
5
 *  Copyright (C) 2019-2021  Andrei Karas
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/partyrecv.h"
24
25
#include "notifymanager.h"
26
#include "party.h"
27
28
#include "being/localplayer.h"
29
30
#include "enums/resources/notifytypes.h"
31
32
#include "gui/windows/chatwindow.h"
33
#include "gui/windows/socialwindow.h"
34
35
#include "gui/widgets/tabs/chat/partytab.h"
36
37
#include "net/messagein.h"
38
39
#include "net/ea/partyrecv.h"
40
41
#include "utils/checkutils.h"
42
#include "utils/foreach.h"
43
44
#include "debug.h"
45
46
extern bool packets_zero;
47
48
namespace EAthena
49
{
50
51
namespace PartyRecv
52
{
53
    PartyShareT mShareAutoItems = PartyShare::UNKNOWN;
54
}  // namespace PartyRecv
55
56
void PartyRecv::processPartyInvitationStats(Net::MessageIn &msg)
57
{
58
    // +++ for now server allow only switch this option but not using it.
59
    msg.readUInt8("allow party");
60
}
61
62
void PartyRecv::processPartyMemberInfo(Net::MessageIn &msg)
63
{
64
    const BeingId id = msg.readBeingId("account id");
65
    if (msg.getVersion() >= 20171207)
66
        msg.readBeingId("char id");
67
    const bool leader = msg.readInt32("leader") == 0U;
68
    int level = 0;
69
    if (msg.getVersionMain() >= 20170524 ||
70
        msg.getVersionRe() >= 20170502 ||
71
        packets_zero == true)
72
    {
73
        msg.readInt16("class");
74
        level = msg.readInt16("level");
75
    }
76
    const int x = msg.readInt16("x");
77
    const int y = msg.readInt16("y");
78
    const bool online = msg.readInt8("online") == 0U;
79
    msg.readString(24, "party name");
80
    const std::string nick = msg.readString(24, "player name");
81
    const std::string map = msg.readString(16, "map name");
82
    msg.readInt8("pickup item share (&1)");
83
    msg.readInt8("get item share (&2)");
84
85
    if (Ea::taParty == nullptr)
86
        return;
87
88
    PartyMember *const member = Ea::taParty->addMember(id, nick);
89
    if (member != nullptr)
90
    {
91
        if ((partyTab != nullptr) && member->getOnline() != online)
92
            partyTab->showOnline(nick, fromBool(online, Online));
93
        member->setLeader(leader);
94
        member->setOnline(online);
95
        member->setMap(map);
96
        member->setX(x);
97
        member->setY(y);
98
        if (level != 0)
99
            member->setLevel(level);
100
    }
101
}
102
103
void PartyRecv::processPartyMemberJobLevel(Net::MessageIn &msg)
104
{
105
    const BeingId id = msg.readBeingId("account id");
106
    msg.readInt16("class");
107
    const int level = msg.readInt16("level");
108
109
    if (Ea::taParty == nullptr)
110
        return;
111
112
    PartyMember *const member = Ea::taParty->getMember(id);
113
    if (member != nullptr)
114
    {
115
        member->setOnline(true);
116
        if (level != 0)
117
            member->setLevel(level);
118
    }
119
    else
120
    {
121
        reportAlways("processPartyMemberJobLevel: party member not exists.")
122
    }
123
}
124
125
void PartyRecv::processPartySettings(Net::MessageIn &msg)
126
{
127
    if (partyTab == nullptr)
128
    {
129
        if (chatWindow == nullptr)
130
            return;
131
132
        Ea::PartyRecv::createTab();
133
    }
134
135
    const PartyShareT exp = static_cast<PartyShareT>(
136
        msg.readInt32("party exp"));
137
    Ea::PartyRecv::processPartyExpSettingsContinue(msg, exp);
138
    if (msg.getVersion() >= 20090603)
139
    {
140
        const PartyShareT item = static_cast<PartyShareT>(
141
            msg.readInt8("pickup item share (&1)"));
142
        Ea::PartyRecv::processPartyItemSettingsContinue(msg, item);
143
        const PartyShareT autoItem = static_cast<PartyShareT>(
144
            msg.readInt8("get auto item share (&2)"));
145
        processPartyAutoItemSettingsContinue(msg, autoItem);
146
    }
147
}
148
149
void PartyRecv::processPartyInfo(Net::MessageIn &msg)
150
{
151
    bool isOldParty = false;
152
    std::set<std::string> names;
153
    std::set<std::string> onlineNames;
154
    if (Ea::taParty == nullptr)
155
    {
156
        logger->log1("error: party empty in SMSG_PARTY_INFO");
157
        Ea::taParty = Party::getParty(1);
158
    }
159
    if (partyTab == nullptr)
160
        Ea::PartyRecv::createTab();
161
162
    if (Ea::taParty != nullptr)
163
    {
164
        if (Ea::taParty->getNumberOfElements() > 1)
165
        {
166
            isOldParty = true;
167
            Ea::taParty->getNamesSet(names);
168
            const Party::MemberList *const members = Ea::taParty->getMembers();
169
            FOR_EACHP (Party::MemberList::const_iterator, it, members)
170
            {
171
                if ((*it)->getOnline())
172
                    onlineNames.insert((*it)->getName());
173
            }
174
            if (localPlayer != nullptr)
175
                onlineNames.insert(localPlayer->getName());
176
        }
177
    }
178
179
    if (localPlayer == nullptr)
180
        logger->log1("error: localPlayer==0 in SMSG_PARTY_INFO");
181
182
    if (Ea::taParty != nullptr)
183
        Ea::taParty->clearMembers();
184
185
    const int length = msg.readInt16("len");
186
    if (Ea::taParty != nullptr)
187
    {
188
        const std::string name = msg.readString(24, "party name");
189
        Ea::taParty->setName(name);
190
    }
191
    else
192
    {
193
        msg.readString(24, "party name");
194
    }
195
196
    int partySize = 0;
197
    const int offset = 28;
198
    if (msg.getVersion() >= 20171207)
199
    {
200
        partySize = 4 + 4 + 24 + 16 + 1 + 1 + 2 + 2;
201
    }
202
    else if (msg.getVersionMain() >= 20170524 ||
203
             msg.getVersionRe() >= 20170502 ||
204
             packets_zero == true)
205
    {
206
        partySize = 4 + 24 + 16 + 1 + 1 + 2 + 2;
207
    }
208
    else
209
    {
210
        partySize = 4 + 24 + 16 + 1 + 1;
211
    }
212
213
    const int count = (length - offset) / partySize;
214
    if (localPlayer != nullptr &&
215
        Ea::taParty != nullptr)
216
    {
217
        localPlayer->setParty(Ea::taParty);
218
        localPlayer->setPartyName(Ea::taParty->getName());
219
    }
220
221
    for (int i = 0; i < count; i++)
222
    {
223
        const BeingId id = msg.readBeingId("account id");
224
        if (msg.getVersion() >= 20171207)
225
            msg.readBeingId("char id");
226
        std::string nick = msg.readString(24, "nick");
227
        std::string map = msg.readString(16, "map name");
228
        const bool leader = msg.readUInt8("leader") == 0U;
229
        const bool online = msg.readUInt8("online") == 0U;
230
        int level = 0;
231
        if (msg.getVersionMain() >= 20170524 ||
232
            msg.getVersionRe() >= 20170502 ||
233
            packets_zero == true)
234
        {
235
            msg.readInt16("class");
236
            level = msg.readInt16("level");
237
        }
238
239
        if (Ea::taParty != nullptr)
240
        {
241
            bool joined(false);
242
243
            if (isOldParty)
244
            {
245
                if (names.find(nick) == names.end())
246
                {
247
                    NotifyManager::notify(NotifyTypes::PARTY_USER_JOINED,
248
                        nick);
249
                    joined = true;
250
                }
251
            }
252
            PartyMember *const member = Ea::taParty->addMember(id, nick);
253
            if (member != nullptr)
254
            {
255
                if (!joined && (partyTab != nullptr))
256
                {
257
                    if (!names.empty() && ((onlineNames.find(nick)
258
                        == onlineNames.end() && online)
259
                        || (onlineNames.find(nick) != onlineNames.end()
260
                        && !online)))
261
                    {
262
                        partyTab->showOnline(nick, fromBool(online, Online));
263
                    }
264
                }
265
                member->setLeader(leader);
266
                member->setOnline(online);
267
                member->setMap(map);
268
                if (level != 0)
269
                    member->setLevel(level);
270
            }
271
        }
272
    }
273
274
    // fix for wrong data sent by old hercules. in future need delete it
275
    if (msg.getVersion() >= 20170502 && msg.getUnreadLength() >= 6)
276
    {
277
        msg.readInt8("pickup item share (&1)");
278
        msg.readInt8("get item share (&2)");
279
        msg.readInt32("unknown");
280
    }
281
282
    if (Ea::taParty != nullptr)
283
        Ea::taParty->sort();
284
285
    if ((localPlayer != nullptr) && (Ea::taParty != nullptr))
286
    {
287
        localPlayer->setParty(Ea::taParty);
288
        localPlayer->setPartyName(Ea::taParty->getName());
289
        if (socialWindow != nullptr)
290
            socialWindow->updateParty();
291
    }
292
}
293
294
void PartyRecv::processPartyMessage(Net::MessageIn &msg)
295
{
296
    const int msgLength = msg.readInt16("len") - 8;
297
    if (msgLength <= 0)
298
        return;
299
300
    const BeingId id = msg.readBeingId("id");
301
    std::string chatMsg = msg.readString(msgLength, "message");
302
303
    const size_t pos = chatMsg.find(" : ", 0);
304
    if (pos != std::string::npos)
305
        chatMsg.erase(0, pos + 3);
306
307
    if ((Ea::taParty != nullptr) && (partyTab != nullptr))
308
    {
309
        const PartyMember *const member = Ea::taParty->getMember(id);
310
        if (member != nullptr)
311
        {
312
            partyTab->chatLog(member->getName(), chatMsg);
313
        }
314
        else
315
        {
316
            NotifyManager::notify(NotifyTypes::PARTY_UNKNOWN_USER_MSG,
317
                chatMsg);
318
        }
319
    }
320
}
321
322
void PartyRecv::processPartyInviteResponse(Net::MessageIn &msg)
323
{
324
    if (partyTab == nullptr)
325
        return;
326
327
    const std::string nick = msg.readString(24, "nick");
328
329
    switch (msg.readInt32("result"))
330
    {
331
        case 0:
332
            NotifyManager::notify(NotifyTypes::PARTY_INVITE_ALREADY_MEMBER,
333
                nick);
334
            break;
335
        case 1:
336
            NotifyManager::notify(NotifyTypes::PARTY_INVITE_REFUSED, nick);
337
            break;
338
        case 2:
339
            NotifyManager::notify(NotifyTypes::PARTY_INVITE_DONE, nick);
340
            break;
341
        case 3:
342
            NotifyManager::notify(NotifyTypes::PARTY_INVITE_PARTY_FULL,
343
                nick);
344
            break;
345
        case 4:
346
            NotifyManager::notify(NotifyTypes::PARTY_INVITE_PARTY_SAME_ACCOUNT,
347
                nick);
348
            break;
349
        case 5:
350
            NotifyManager::notify(
351
                NotifyTypes::PARTY_INVITE_PARTY_BLOCKED_INVITE,
352
                nick);
353
            break;
354
        case 7:
355
            NotifyManager::notify(NotifyTypes::PARTY_INVITE_PARTY_NOT_ONLINE,
356
                nick);
357
            break;
358
        default:
359
            NotifyManager::notify(NotifyTypes::PARTY_INVITE_ERROR, nick);
360
            break;
361
    }
362
}
363
364
void PartyRecv::processPartyItemPickup(Net::MessageIn &msg)
365
{
366
    UNIMPLEMENTEDPACKET;
367
    // +++ probably need add option to show pickup notifications
368
    // in party tab
369
    msg.readBeingId("account id");
370
    msg.readItemId("item id");
371
    msg.readUInt8("identify");
372
    msg.readUInt8("attribute");
373
    msg.readUInt8("refine");
374
    for (int f = 0; f < maxCards; f++)
375
        msg.readItemId("card");
376
    msg.readInt16("equip location");
377
    msg.readUInt8("item type");
378
    // for color can be used ItemColorManager
379
}
380
381
void PartyRecv::processPartyLeader(Net::MessageIn &msg)
382
{
383
    PartyMember *const oldMember = Ea::taParty->getMember(
384
        msg.readBeingId("old leder id"));
385
    PartyMember *const newMember = Ea::taParty->getMember(
386
        msg.readBeingId("new leder id"));
387
    if (oldMember != nullptr)
388
        oldMember->setLeader(false);
389
    if (newMember != nullptr)
390
        newMember->setLeader(true);
391
}
392
393
void PartyRecv::processPartyInvited(Net::MessageIn &msg)
394
{
395
    if (socialWindow == nullptr)
396
    {
397
        msg.readInt32("party id");
398
        msg.readString(24, "party name");
399
        return;
400
    }
401
    const int id = msg.readInt32("party id");
402
    const std::string partyName = msg.readString(24, "party name");
403
404
    if (socialWindow != nullptr)
405
        socialWindow->showPartyInvite(partyName, std::string(), id);
406
}
407
408
void PartyRecv::processPartyAutoItemSettingsContinue(Net::MessageIn &msg,
409
                                                     const PartyShareT item)
410
{
411
    switch (item)
412
    {
413
        case PartyShare::YES:
414
            if (mShareAutoItems == PartyShare::YES)
415
                break;
416
            mShareAutoItems = PartyShare::YES;
417
            NotifyManager::notify(NotifyTypes::PARTY_ITEM_SHARE_ON);
418
            break;
419
        case PartyShare::NO:
420
            if (mShareAutoItems == PartyShare::NO)
421
                break;
422
            mShareAutoItems = PartyShare::NO;
423
            NotifyManager::notify(NotifyTypes::PARTY_ITEM_SHARE_OFF);
424
            break;
425
        case PartyShare::NOT_POSSIBLE:
426
            if (mShareAutoItems == PartyShare::NOT_POSSIBLE)
427
                break;
428
            mShareAutoItems = PartyShare::NOT_POSSIBLE;
429
            NotifyManager::notify(NotifyTypes::PARTY_ITEM_SHARE_ERROR);
430
            break;
431
        default:
432
        case PartyShare::UNKNOWN:
433
            UNIMPLEMENTEDPACKETFIELD(CAST_S32(item));
434
            break;
435
    }
436
}
437
438
void PartyRecv::processPartyMemberDead(Net::MessageIn &msg)
439
{
440
    const BeingId id = msg.readBeingId("account id");
441
    const int isDead = msg.readUInt8("is dead");
442
    PartyMember *const member = Ea::taParty->getMember(id);
443
    if (member != nullptr && isDead != 0)
444
    {
445
        member->setHp(0);
446
    }
447
}
448
449
2
}  // namespace EAthena