GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/eathena/vendingrecv.cpp Lines: 1 137 0.7 %
Date: 2017-11-29 Branches: 2 79 2.5 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2011-2017  The ManaPlus Developers
4
 *
5
 *  This file is part of The ManaPlus Client.
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; either version 2 of the License, or
10
 *  any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU General Public License
18
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
 */
20
21
#include "net/eathena/vendingrecv.h"
22
23
#include "actormanager.h"
24
#include "itemcolormanager.h"
25
#include "notifymanager.h"
26
27
#include "const/resources/currency.h"
28
29
#include "being/localplayer.h"
30
#include "being/playerinfo.h"
31
32
#include "const/net/inventory.h"
33
34
#include "enums/resources/notifytypes.h"
35
36
#include "gui/windows/buydialog.h"
37
38
#include "gui/widgets/createwidget.h"
39
40
#include "listeners/vendingmodelistener.h"
41
#include "listeners/vendingslotslistener.h"
42
43
#include "net/messagein.h"
44
45
#include "resources/iteminfo.h"
46
47
#include "resources/db/unitsdb.h"
48
49
#include "resources/inventory/inventory.h"
50
51
#include "resources/item/itemoptionslist.h"
52
#include "resources/item/shopitem.h"
53
54
#include "utils/gettext.h"
55
#include "utils/stringutils.h"
56
57
#include "debug.h"
58
59
extern int packetVersion;
60
extern int serverVersion;
61
62
namespace EAthena
63
{
64
65
namespace VendingRecv
66
{
67
    BuyDialog *mBuyDialog = nullptr;
68
}  // namespace VendingRecv
69
70
void VendingRecv::processOpenReq(Net::MessageIn &msg)
71
{
72
    VendingSlotsListener::distributeEvent(msg.readInt16("slots allowed"));
73
}
74
75
void VendingRecv::processShowBoard(Net::MessageIn &msg)
76
{
77
    const BeingId id = msg.readBeingId("owner id");
78
    Being *const dstBeing = actorManager->findBeing(id);
79
    if (dstBeing != nullptr)
80
    {
81
        dstBeing->setSellBoard(msg.readString(80, "shop name"));
82
    }
83
    else
84
    {
85
        msg.readString(80, "shop name");
86
    }
87
}
88
89
void VendingRecv::processHideBoard(Net::MessageIn &msg)
90
{
91
    const BeingId id = msg.readBeingId("owner id");
92
    Being *const dstBeing = actorManager->findBeing(id);
93
    if (dstBeing != nullptr)
94
        dstBeing->setSellBoard(std::string());
95
    if (dstBeing == localPlayer)
96
    {
97
        PlayerInfo::enableVending(false);
98
        VendingModeListener::distributeEvent(false);
99
    }
100
}
101
102
void VendingRecv::processItemsList(Net::MessageIn &msg)
103
{
104
    int packetLen = 22;
105
    if (msg.getVersion() >= 20160921)
106
        packetLen = 53;
107
    else if (msg.getVersion() >= 20150226)
108
        packetLen = 47;
109
    int offset = 8;
110
    if (msg.getVersion() >= 20100105)
111
        offset += 4;
112
113
    const int count = (msg.readInt16("len") - offset) / packetLen;
114
    const BeingId id = msg.readBeingId("id");
115
    const Being *const being = actorManager->findBeing(id);
116
    if (being == nullptr)
117
        return;
118
    int cards[maxCards];
119
    CREATEWIDGETV(mBuyDialog, BuyDialog, being, DEFAULT_CURRENCY);
120
    mBuyDialog->setMoney(PlayerInfo::getAttribute(Attributes::MONEY));
121
    if (msg.getVersion() >= 20100105)
122
        msg.readInt32("vender id");
123
    for (int f = 0; f < count; f ++)
124
    {
125
        const int value = msg.readInt32("price");
126
        const int amount = msg.readInt16("amount");
127
        const int index = msg.readInt16("inv index");
128
        const ItemTypeT type = static_cast<ItemTypeT>(
129
            msg.readUInt8("item type"));
130
        const int itemId = msg.readInt16("item id");
131
        msg.readUInt8("identify");
132
        msg.readUInt8("attribute");
133
        msg.readUInt8("refine");
134
        for (int d = 0; d < maxCards; d ++)
135
            cards[d] = msg.readUInt16("card");
136
        ItemOptionsList *options = nullptr;
137
        if (msg.getVersion() >= 20150226)
138
        {
139
            options = new ItemOptionsList;
140
            for (int d = 0; d < 5; d ++)
141
            {
142
                const uint16_t idx = msg.readInt16("option index");
143
                const uint16_t val = msg.readInt16("option value");
144
                msg.readUInt8("option param");
145
                options->add(idx, val);
146
            }
147
        }
148
        if (msg.getVersion() >= 20160921)
149
        {
150
            msg.readInt32("equip type?");
151
            msg.readInt16("look");
152
        }
153
154
        const ItemColor color = ItemColorManager::getColorFromCards(&cards[0]);
155
        ShopItem *const item = mBuyDialog->addItem(itemId, type,
156
            color, amount, value);
157
        if (item != nullptr)
158
        {
159
            item->setInvIndex(index);
160
            item->setOptions(options);
161
        }
162
        delete options;
163
    }
164
    mBuyDialog->sort();
165
}
166
167
void VendingRecv::processBuyAck(Net::MessageIn &msg)
168
{
169
    msg.readInt16("inv index");
170
    msg.readInt16("amount");
171
    const int flag = msg.readUInt8("flag");
172
    switch (flag)
173
    {
174
        case 0:
175
            break;
176
        case 1:
177
            NotifyManager::notify(NotifyTypes::BUY_FAILED_NO_MONEY);
178
            break;
179
        case 2:
180
            NotifyManager::notify(NotifyTypes::BUY_FAILED_OVERWEIGHT);
181
            break;
182
        case 4:
183
            NotifyManager::notify(NotifyTypes::BUY_FAILED_TOO_MANY_ITEMS);
184
            break;
185
        case 5:
186
            NotifyManager::notify(NotifyTypes::BUY_TRADE_FAILED);
187
            break;
188
        case 6:  // +++ probably need show exact error messages?
189
        case 7:
190
            NotifyManager::notify(NotifyTypes::BUY_FAILED);
191
            break;
192
        default:
193
            NotifyManager::notify(NotifyTypes::BUY_FAILED);
194
            UNIMPLEMENTEDPACKETFIELD(flag);
195
            break;
196
    }
197
}
198
199
void VendingRecv::processOpen(Net::MessageIn &msg)
200
{
201
    int packetLen = 22;
202
    if (msg.getVersion() >= 20150226)
203
        packetLen += 25;
204
205
    const int count = (msg.readInt16("len") - 8) / packetLen;
206
    msg.readInt32("id");
207
    for (int f = 0; f < count; f ++)
208
    {
209
        msg.readInt32("price");
210
        msg.readInt16("inv index");
211
        msg.readInt16("amount");
212
        msg.readUInt8("item type");
213
        msg.readInt16("item id");
214
        msg.readUInt8("identify");
215
        msg.readUInt8("attribute");
216
        msg.readUInt8("refine");
217
        for (int d = 0; d < maxCards; d ++)
218
            msg.readUInt16("card");
219
        if (msg.getVersion() >= 20150226)
220
        {
221
            for (int d = 0; d < 5; d ++)
222
            {
223
                msg.readInt16("option index");
224
                msg.readInt16("option value");
225
                msg.readUInt8("option param");
226
            }
227
        }
228
    }
229
    PlayerInfo::enableVending(true);
230
    VendingModeListener::distributeEvent(true);
231
}
232
233
void VendingRecv::processReport(Net::MessageIn &msg)
234
{
235
    const int index = msg.readInt16("inv index") - INVENTORY_OFFSET;
236
    const int amount = msg.readInt16("amount");
237
    int money = 0;
238
    if (msg.getVersion() >= 20141016)
239
    {
240
        msg.readInt32("char id");
241
        msg.readInt32("time");
242
        money = msg.readInt32("zeny");
243
    }
244
    const Inventory *const inventory = PlayerInfo::getCartInventory();
245
    if (inventory == nullptr)
246
        return;
247
    const Item *const item = inventory->getItem(index);
248
    if (item == nullptr)
249
        return;
250
251
    const ItemInfo &info = item->getInfo();
252
    std::string str;
253
    if (money != 0)
254
    {
255
        // TRANSLATORS: vending sold item message
256
        str = strprintf(_("Sold item %s amount %d. You got: %s"),
257
            info.getLink().c_str(),
258
            amount,
259
            UnitsDb::formatCurrency(money).c_str());
260
    }
261
    else
262
    {
263
        // TRANSLATORS: vending sold item message
264
        str = strprintf(_("Sold item %s amount %d"),
265
            info.getLink().c_str(),
266
            amount);
267
    }
268
    NotifyManager::notify(NotifyTypes::VENDING_SOLD_ITEM, str);
269
}
270
271
void VendingRecv::processOpenStatus(Net::MessageIn &msg)
272
{
273
    UNIMPLEMENTEDPACKET;
274
    msg.readUInt8("result");
275
}
276
277

6
}  // namespace EAthena