GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/eathena/vendingrecv.cpp Lines: 1 139 0.7 %
Date: 2018-09-20 Branches: 2 89 2.2 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2011-2018  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
extern int itemIdLen;
62
63
namespace EAthena
64
{
65
66
namespace VendingRecv
67
{
68
    BuyDialog *mBuyDialog = nullptr;
69
}  // namespace VendingRecv
70
71
void VendingRecv::processOpenReq(Net::MessageIn &msg)
72
{
73
    VendingSlotsListener::distributeEvent(msg.readInt16("slots allowed"));
74
}
75
76
void VendingRecv::processShowBoard(Net::MessageIn &msg)
77
{
78
    if (actorManager == nullptr)
79
        return;
80
    const BeingId id = msg.readBeingId("owner id");
81
    Being *const dstBeing = actorManager->findBeing(id);
82
    if (dstBeing != nullptr)
83
    {
84
        dstBeing->setSellBoard(msg.readString(80, "shop name"));
85
    }
86
    else
87
    {
88
        msg.readString(80, "shop name");
89
    }
90
}
91
92
void VendingRecv::processHideBoard(Net::MessageIn &msg)
93
{
94
    if (actorManager == nullptr)
95
        return;
96
    const BeingId id = msg.readBeingId("owner id");
97
    Being *const dstBeing = actorManager->findBeing(id);
98
    if (dstBeing != nullptr)
99
        dstBeing->setSellBoard(std::string());
100
    if (dstBeing == localPlayer)
101
    {
102
        PlayerInfo::enableVending(false);
103
        VendingModeListener::distributeEvent(false);
104
    }
105
}
106
107
void VendingRecv::processItemsList(Net::MessageIn &msg)
108
{
109
    if (actorManager == nullptr)
110
        return;
111
    int packetLen = 22;
112
    if (msg.getVersion() >= 20160921)
113
        packetLen = 53;
114
    else if (msg.getVersion() >= 20150226)
115
        packetLen = 47;
116
    if (itemIdLen == 4)
117
        packetLen += 10;
118
    int offset = 8;
119
    if (msg.getVersion() >= 20100105)
120
        offset += 4;
121
122
    const int count = (msg.readInt16("len") - offset) / packetLen;
123
    const BeingId id = msg.readBeingId("id");
124
    const Being *const being = actorManager->findBeing(id);
125
    if (being == nullptr)
126
        return;
127
    int cards[maxCards];
128
    CREATEWIDGETV(mBuyDialog, BuyDialog, being, DEFAULT_CURRENCY);
129
    mBuyDialog->setMoney(PlayerInfo::getAttribute(Attributes::MONEY));
130
    if (msg.getVersion() >= 20100105)
131
        msg.readInt32("vender id");
132
    for (int f = 0; f < count; f ++)
133
    {
134
        const int value = msg.readInt32("price");
135
        const int amount = msg.readInt16("amount");
136
        const int index = msg.readInt16("inv index");
137
        const ItemTypeT type = static_cast<ItemTypeT>(
138
            msg.readUInt8("item type"));
139
        const int itemId = msg.readItemId("item id");
140
        msg.readUInt8("identify");
141
        msg.readUInt8("attribute");
142
        msg.readUInt8("refine");
143
        for (int d = 0; d < maxCards; d ++)
144
            cards[d] = msg.readItemId("card");
145
        ItemOptionsList *options = nullptr;
146
        if (msg.getVersion() >= 20150226)
147
        {
148
            options = new ItemOptionsList;
149
            for (int d = 0; d < 5; d ++)
150
            {
151
                const uint16_t idx = msg.readInt16("option index");
152
                const uint16_t val = msg.readInt16("option value");
153
                msg.readUInt8("option param");
154
                options->add(idx, val);
155
            }
156
        }
157
        if (msg.getVersion() >= 20160921)
158
        {
159
            msg.readInt32("equip type?");
160
            msg.readInt16("look");
161
        }
162
163
        const ItemColor color = ItemColorManager::getColorFromCards(&cards[0]);
164
        ShopItem *const item = mBuyDialog->addItem(itemId, type,
165
            color, amount, value);
166
        if (item != nullptr)
167
        {
168
            item->setInvIndex(index);
169
            item->setOptions(options);
170
        }
171
        delete options;
172
    }
173
    mBuyDialog->sort();
174
}
175
176
void VendingRecv::processBuyAck(Net::MessageIn &msg)
177
{
178
    msg.readInt16("inv index");
179
    msg.readInt16("amount");
180
    const int flag = msg.readUInt8("flag");
181
    switch (flag)
182
    {
183
        case 0:
184
            break;
185
        case 1:
186
            NotifyManager::notify(NotifyTypes::BUY_FAILED_NO_MONEY);
187
            break;
188
        case 2:
189
            NotifyManager::notify(NotifyTypes::BUY_FAILED_OVERWEIGHT);
190
            break;
191
        case 4:
192
            NotifyManager::notify(NotifyTypes::BUY_FAILED_TOO_MANY_ITEMS);
193
            break;
194
        case 5:
195
            NotifyManager::notify(NotifyTypes::BUY_TRADE_FAILED);
196
            break;
197
        case 6:  // +++ probably need show exact error messages?
198
        case 7:
199
            NotifyManager::notify(NotifyTypes::BUY_FAILED);
200
            break;
201
        default:
202
            NotifyManager::notify(NotifyTypes::BUY_FAILED);
203
            UNIMPLEMENTEDPACKETFIELD(flag);
204
            break;
205
    }
206
}
207
208
void VendingRecv::processOpen(Net::MessageIn &msg)
209
{
210
    int packetLen = 22;
211
    if (msg.getVersion() >= 20150226)
212
        packetLen += 25;
213
    if (itemIdLen == 4)
214
        packetLen += 10;
215
216
    const int count = (msg.readInt16("len") - 8) / packetLen;
217
    msg.readInt32("id");
218
    for (int f = 0; f < count; f ++)
219
    {
220
        msg.readInt32("price");
221
        msg.readInt16("inv index");
222
        msg.readInt16("amount");
223
        msg.readUInt8("item type");
224
        msg.readItemId("item id");
225
        msg.readUInt8("identify");
226
        msg.readUInt8("attribute");
227
        msg.readUInt8("refine");
228
        for (int d = 0; d < maxCards; d ++)
229
            msg.readItemId("card");
230
        if (msg.getVersion() >= 20150226)
231
        {
232
            for (int d = 0; d < 5; d ++)
233
            {
234
                msg.readInt16("option index");
235
                msg.readInt16("option value");
236
                msg.readUInt8("option param");
237
            }
238
        }
239
    }
240
    PlayerInfo::enableVending(true);
241
    VendingModeListener::distributeEvent(true);
242
}
243
244
void VendingRecv::processReport(Net::MessageIn &msg)
245
{
246
    const int index = msg.readInt16("inv index") - INVENTORY_OFFSET;
247
    const int amount = msg.readInt16("amount");
248
    int money = 0;
249
    if (msg.getVersion() >= 20141016)
250
    {
251
        msg.readInt32("char id");
252
        msg.readInt32("time");
253
        money = msg.readInt32("zeny");
254
    }
255
    const Inventory *const inventory = PlayerInfo::getCartInventory();
256
    if (inventory == nullptr)
257
        return;
258
    const Item *const item = inventory->getItem(index);
259
    if (item == nullptr)
260
        return;
261
262
    const ItemInfo &info = item->getInfo();
263
    std::string str;
264
    if (money != 0)
265
    {
266
        // TRANSLATORS: vending sold item message
267
        str = strprintf(_("Sold item %s amount %d. You got: %s"),
268
            info.getLink().c_str(),
269
            amount,
270
            UnitsDb::formatCurrency(money).c_str());
271
    }
272
    else
273
    {
274
        // TRANSLATORS: vending sold item message
275
        str = strprintf(_("Sold item %s amount %d"),
276
            info.getLink().c_str(),
277
            amount);
278
    }
279
    NotifyManager::notify(NotifyTypes::VENDING_SOLD_ITEM, str);
280
}
281
282
void VendingRecv::processOpenStatus(Net::MessageIn &msg)
283
{
284
    UNIMPLEMENTEDPACKET;
285
    msg.readUInt8("result");
286
}
287
288

3
}  // namespace EAthena