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