GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/eathena/vendingrecv.cpp Lines: 1 140 0.7 %
Date: 2018-06-18 21:15:20 Branches: 2 85 2.4 %

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

6
}  // namespace EAthena