Mana
Loading...
Searching...
No Matches
tradehandler.cpp
Go to the documentation of this file.
1/*
2 * The Mana Client
3 * Copyright (C) 2004-2009 The Mana World Development Team
4 * Copyright (C) 2009-2012 The Mana Developers
5 *
6 * This file is part of The Mana 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
23
24#include "event.h"
25#include "inventory.h"
26#include "item.h"
27#include "localplayer.h"
28#include "playerinfo.h"
29#include "playerrelations.h"
30
31#include "gui/confirmdialog.h"
32#include "gui/tradewindow.h"
33
35
36#include "net/tmwa/messagein.h"
37#include "net/tmwa/messageout.h"
38#include "net/tmwa/protocol.h"
39
40#include "resources/iteminfo.h"
41
42#include "utils/gettext.h"
43#include "utils/stringutils.h"
44
45extern std::string tradePartnerName;
47
51namespace {
52 struct RequestTradeListener : public gcn::ActionListener
53 {
54 void action(const gcn::ActionEvent &event) override
55 {
56 confirmDlg = nullptr;
57 Net::getTradeHandler()->respond(event.getId() == "yes");
58 }
59 } listener;
60}
61
63
64namespace TmwAthena {
65
67{
68 static const Uint16 _messages[] = {
76 0
77 };
78 handledMessages = _messages;
79 tradeHandler = this;
80 confirmDlg = nullptr;
81}
82
83
85{
86 switch (msg.getId())
87 {
89 {
90 // If a trade window or request window is already open, send a
91 // trade cancel to any other trade request.
92 //
93 // Note that it would be nice if the server would prevent this
94 // situation, and that the requesting player would get a
95 // special message about the player being occupied.
96 std::string tradePartnerNameTemp = msg.readString(24);
97
100 {
101 if (mTrading || confirmDlg)
102 {
104 break;
105 }
106
107 tradePartnerName = tradePartnerNameTemp;
108 mTrading = true;
109 confirmDlg = new ConfirmDialog(_("Request for Trade"),
110 strprintf(_("%s wants to trade with you, do you "
111 "accept?"), tradePartnerName.c_str()));
112 confirmDlg->addActionListener(&listener);
113 }
114 else
115 {
117 break;
118 }
119 }
120 break;
121
123 switch (msg.readInt8())
124 {
125 case 0: // Too far away
126 serverNotice(_("Trading isn't possible. Trade "
127 "partner is too far away."));
128 break;
129 case 1: // Character doesn't exist
130 serverNotice(_("Trading isn't possible. Character "
131 "doesn't exist."));
132 break;
133 case 2: // Invite request check failed...
134 serverNotice(_("Trade canceled due to an unknown "
135 "reason."));
136 break;
137 case 3: // Trade accepted
139 tradeWindow->setCaption(strprintf(_("Trade: You and %s"),
140 tradePartnerName.c_str()));
141 tradeWindow->setVisible(true);
142 break;
143 case 4: // Trade canceled
146 {
147 serverNotice(strprintf(_("Trade with %s canceled."),
148 tradePartnerName.c_str()));
149 }
150 // otherwise ignore silently
151
152 tradeWindow->setVisible(false);
153 mTrading = false;
154 break;
155 default: // Shouldn't happen as well, but to be sure
156 serverNotice(_("Unhandled trade cancel packet."));
157 break;
158 }
159 break;
160
162 {
163 int amount = msg.readInt32();
164 int type = msg.readInt16();
165 msg.readInt8(); // identified flag
166 msg.readInt8(); // attribute
167 msg.readInt8(); // refine
168 msg.skip(8); // card (4 shorts)
169
170 // TODO: handle also identified, etc
171 if (type == 0)
172 tradeWindow->setMoney(amount);
173 else
174 tradeWindow->addItem(type, false, amount);
175 }
176 break;
177
179 // Trade: New Item add response (was 0x00ea, now 01b1)
180 {
181 const int index = msg.readInt16() - INVENTORY_OFFSET;
182 Item *item = PlayerInfo::getInventory()->getItem(index);
183 if (!item)
184 {
185 tradeWindow->receivedOk(true);
186 return;
187 }
188 int quantity = msg.readInt16();
189
190 switch (msg.readInt8())
191 {
192 case 0:
193 // Successfully added item
194 if (item->isEquippable() && item->isEquipped())
195 {
197 }
198 tradeWindow->addItem(item->getId(), true, quantity);
199
200 item->increaseQuantity(-quantity);
201 break;
202 case 1:
203 // Add item failed - player overweighted
204 serverNotice(_("Failed adding item. "
205 "Trade partner is over weighted."));
206 break;
207 case 2:
208 // Add item failed - player has no free slot
209 serverNotice(_("Failed adding item. "
210 "Trade partner has no free slot."));
211 break;
212 case 3:
213 // Add item failed - non tradable item
214 serverNotice(_("Failed adding item. "
215 "You can't trade this item."));
216 break;
217 default:
218 serverNotice(_("Failed adding item for unknown "
219 "reason."));
220 break;
221 }
222 }
223 break;
224
225 case SMSG_TRADE_OK:
226 // 0 means ok from myself, 1 means ok from other;
227 tradeWindow->receivedOk(msg.readInt8() == 0);
228 break;
229
231 serverNotice(_("Trade canceled."));
232 tradeWindow->setVisible(false);
234 mTrading = false;
235 break;
236
238 serverNotice(_("Trade completed."));
239 tradeWindow->setVisible(false);
241 mTrading = false;
242 break;
243 }
244}
245
247{
249 outMsg.writeInt32(being->getId());
250}
251
252void TradeHandler::respond(bool accept)
253{
254 if (!accept)
255 mTrading = false;
256
258 outMsg.writeInt8(accept ? 3 : 4);
259}
260
261void TradeHandler::addItem(Item *item, int amount)
262{
264 outMsg.writeInt16(item->getInvIndex() + INVENTORY_OFFSET);
265 outMsg.writeInt32(amount);
266}
267
268void TradeHandler::removeItem(int slotNum, int amount)
269{
270 // TODO
271}
272
274{
276 outMsg.writeInt16(0);
277 outMsg.writeInt32(amount);
278}
279
284
286{
288}
289
294
295} // namespace TmwAthena
int getId() const
Definition actorsprite.h:63
Definition being.h:65
An option dialog.
@ DoUnequip
Definition event.h:78
Item * getItem(int index) const
Returns the item at the specified index.
Definition inventory.cpp:44
Represents one or more instances of a certain item type.
Definition item.h:35
void doEvent(Event::Type eventType)
Definition item.cpp:54
bool isEquipped() const
Returns whether this item is equipped.
Definition item.h:79
int getInvIndex() const
Returns the inventory index of this item.
Definition item.h:94
void increaseQuantity(int amount)
Increases the number of items by the given amount.
Definition item.h:64
int getId() const
Returns the item id.
Definition item.h:49
bool isEquippable() const
Returns whether this item is equippable.
Definition item.cpp:69
const uint16_t * handledMessages
virtual void respond(bool accept)
bool hasPermission(Being *being, unsigned int flags)
Tests whether the player in question is being ignored for any of the actions in the specified flags.
Used for parsing an incoming message from eAthena.
Definition messagein.h:35
std::string readString(int length=-1)
Reads a string.
void skip(unsigned int length)
Skips a given number of bytes.
uint16_t readInt16()
Reads an unsigned 16-bit integer from the message.
Definition messagein.cpp:57
uint8_t readInt8()
Reads an unsigned 8-bit integer from the message.
Definition messagein.cpp:46
uint16_t getId() const
Returns the message ID.
Definition messagein.h:42
uint32_t readInt32()
Reads an unsigned 32-bit integer from the message.
Definition messagein.cpp:69
Used for building an outgoing message to eAthena.
Definition messageout.h:35
void writeInt32(uint32_t value)
Writes an unsigned 32-bit integer to the message.
void writeInt8(uint8_t value)
Writes an unsigned 8-bit integer to the message.
void writeInt16(uint16_t value)
Writes an unsigned 16-bit integer to the message.
void handleMessage(MessageIn &msg) override
void respond(bool accept) override
void setMoney(int amount) override
void addItem(Item *item, int amount) override
void removeItem(int slotNum, int amount) override
void request(Being *being) override
void addItem(int id, bool own, int quantity)
Add an item to the trade window.
void reset()
Reset both item containers.
void receivedOk(bool own)
Player received ok message from server.
void setMoney(int quantity)
Displays expected money in the trade window.
virtual void setVisible(bool visible)
Overloads window setVisible by Guichan to allow sticky window handling.
Definition window.cpp:282
void serverNotice(const std::string &message)
Definition event.h:319
TradeWindow * tradeWindow
Definition game.cpp:101
#define _(s)
Definition gettext.h:38
std::string tradePartnerName
Definition popupmenu.cpp:55
Net::TradeHandler * tradeHandler
Definition net.cpp:58
TradeHandler * getTradeHandler()
Definition net.cpp:120
Inventory * getInventory()
Returns the player's inventory.
Warning: buffers and other variables are shared, so there can be only one connection active at a time...
@ CMSG_TRADE_RESPONSE
Definition protocol.h:229
@ CMSG_TRADE_ADD_COMPLETE
Definition protocol.h:233
@ SMSG_TRADE_COMPLETE
Definition protocol.h:238
@ SMSG_TRADE_ITEM_ADD
Definition protocol.h:232
@ CMSG_TRADE_ITEM_ADD_REQUEST
Definition protocol.h:231
@ SMSG_TRADE_OK
Definition protocol.h:234
@ SMSG_TRADE_RESPONSE
Definition protocol.h:230
@ CMSG_TRADE_OK
Definition protocol.h:237
@ SMSG_TRADE_REQUEST
Definition protocol.h:228
@ SMSG_TRADE_ITEM_ADD_RESPONSE
Definition protocol.h:284
@ SMSG_TRADE_CANCEL
Definition protocol.h:236
@ CMSG_TRADE_CANCEL_REQUEST
Definition protocol.h:235
@ CMSG_TRADE_REQUEST
Definition protocol.h:227
PlayerRelationsManager player_relations
std::string tradePartnerName
Definition popupmenu.cpp:55
std::string strprintf(char const *format,...)
A safe version of sprintf that returns a std::string of the result.
ConfirmDialog * confirmDlg