From 3ae525b05858af105cc7e3eb6ac7316fc2f5bbd5 Mon Sep 17 00:00:00 2001 From: Bertram Date: Fri, 16 Apr 2010 13:58:56 +0200 Subject: Changed eAthena protocol name to TmwAthena and changed the config files accordingly. This makes room for the actual eAthena protocol future inclusion. --- src/net/tmwa/tradehandler.cpp | 288 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 288 insertions(+) create mode 100644 src/net/tmwa/tradehandler.cpp (limited to 'src/net/tmwa/tradehandler.cpp') diff --git a/src/net/tmwa/tradehandler.cpp b/src/net/tmwa/tradehandler.cpp new file mode 100644 index 00000000..9089f8e6 --- /dev/null +++ b/src/net/tmwa/tradehandler.cpp @@ -0,0 +1,288 @@ +/* + * The Mana Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * + * This file is part of The Mana Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "net/tmwa/tradehandler.h" + +#include "inventory.h" +#include "item.h" +#include "localplayer.h" +#include "playerrelations.h" + +#include "gui/confirmdialog.h" +#include "gui/trade.h" + +#include "gui/widgets/chattab.h" + +#include "net/inventoryhandler.h" +#include "net/messagein.h" +#include "net/messageout.h" + +#include "net/tmwa/protocol.h" + +#include "utils/gettext.h" +#include "utils/stringutils.h" + +extern std::string tradePartnerName; +ConfirmDialog *confirmDlg; + +/** + * Listener for request trade dialogs + */ +namespace { + struct RequestTradeListener : public gcn::ActionListener + { + void action(const gcn::ActionEvent &event) + { + confirmDlg = 0; + Net::getTradeHandler()->respond(event.getId() == "yes"); + } + } listener; +} + +extern Net::TradeHandler *tradeHandler; + +namespace TmwAthena { + +TradeHandler::TradeHandler() +{ + static const Uint16 _messages[] = { + SMSG_TRADE_REQUEST, + SMSG_TRADE_RESPONSE, + SMSG_TRADE_ITEM_ADD, + SMSG_TRADE_ITEM_ADD_RESPONSE, + SMSG_TRADE_OK, + SMSG_TRADE_CANCEL, + SMSG_TRADE_COMPLETE, + 0 + }; + handledMessages = _messages; + tradeHandler = this; + confirmDlg = 0; +} + + +void TradeHandler::handleMessage(Net::MessageIn &msg) +{ + switch (msg.getId()) + { + case SMSG_TRADE_REQUEST: + { + // If a trade window or request window is already open, send a + // trade cancel to any other trade request. + // + // Note that it would be nice if the server would prevent this + // situation, and that the requesting player would get a + // special message about the player being occupied. + std::string tradePartnerNameTemp = msg.readString(24); + + if (player_relations.hasPermission(tradePartnerName, + PlayerRelation::TRADE)) + { + if (!player_node->tradeRequestOk() || confirmDlg) + { + Net::getTradeHandler()->respond(false); + break; + } + + tradePartnerName = tradePartnerNameTemp; + player_node->setTrading(true); + confirmDlg = new ConfirmDialog(_("Request for Trade"), + strprintf(_("%s wants to trade with you, do you " + "accept?"), tradePartnerName.c_str())); + confirmDlg->addActionListener(&listener); + } + else + { + Net::getTradeHandler()->respond(false); + break; + } + } + break; + + case SMSG_TRADE_RESPONSE: + switch (msg.readInt8()) + { + case 0: // Too far away + localChatTab->chatLog(_("Trading isn't possible. Trade " + "partner is too far away."), BY_SERVER); + break; + case 1: // Character doesn't exist + localChatTab->chatLog(_("Trading isn't possible. Character " + "doesn't exist."), BY_SERVER); + break; + case 2: // Invite request check failed... + localChatTab->chatLog(_("Trade cancelled due to an unknown " + "reason."), BY_SERVER); + break; + case 3: // Trade accepted + tradeWindow->reset(); + tradeWindow->setCaption(strprintf(_("Trade: You and %s"), + tradePartnerName.c_str())); + tradeWindow->setVisible(true); + break; + case 4: // Trade cancelled + if (player_relations.hasPermission(tradePartnerName, + PlayerRelation::SPEECH_LOG)) + localChatTab->chatLog(strprintf(_("Trade with %s " + "cancelled."), tradePartnerName.c_str()), + BY_SERVER); + // otherwise ignore silently + + tradeWindow->setVisible(false); + player_node->setTrading(false); + break; + default: // Shouldn't happen as well, but to be sure + localChatTab->chatLog(_("Unhandled trade cancel packet."), + BY_SERVER); + break; + } + break; + + case SMSG_TRADE_ITEM_ADD: + { + int amount = msg.readInt32(); + int type = msg.readInt16(); + msg.readInt8(); // identified flag + msg.readInt8(); // attribute + msg.readInt8(); // refine + msg.skip(8); // card (4 shorts) + + // TODO: handle also identified, etc + if (type == 0) + tradeWindow->setMoney(amount); + else + tradeWindow->addItem(type, false, amount, false); + } + break; + + case SMSG_TRADE_ITEM_ADD_RESPONSE: + // Trade: New Item add response (was 0x00ea, now 01b1) + { + const int index = msg.readInt16() - INVENTORY_OFFSET; + Item *item = player_node->getInventory()->getItem(index); + if (!item) + { + tradeWindow->receivedOk(true); + return; + } + int quantity = msg.readInt16(); + + switch (msg.readInt8()) + { + case 0: + // Successfully added item + if (item->isEquipment() && item->isEquipped()) + { + Net::getInventoryHandler()->unequipItem(item); + } + tradeWindow->addItem(item->getId(), true, quantity, + item->isEquipment()); + item->increaseQuantity(-quantity); + break; + case 1: + // Add item failed - player overweighted + localChatTab->chatLog(_("Failed adding item. Trade " + "partner is over weighted."), BY_SERVER); + break; + case 2: + // Add item failed - player has no free slot + localChatTab->chatLog(_("Failed adding item. Trade " + "partner has no free slot."), BY_SERVER); + break; + default: + localChatTab->chatLog(_("Failed adding item for " + "unknown reason."), BY_SERVER); + break; + } + } + break; + + case SMSG_TRADE_OK: + // 0 means ok from myself, 1 means ok from other; + tradeWindow->receivedOk(msg.readInt8() == 0); + break; + + case SMSG_TRADE_CANCEL: + localChatTab->chatLog(_("Trade canceled."), BY_SERVER); + tradeWindow->setVisible(false); + tradeWindow->reset(); + player_node->setTrading(false); + break; + + case SMSG_TRADE_COMPLETE: + localChatTab->chatLog(_("Trade completed."), BY_SERVER); + tradeWindow->setVisible(false); + tradeWindow->reset(); + player_node->setTrading(false); + break; + } +} + +void TradeHandler::request(Being *being) +{ + MessageOut outMsg(CMSG_TRADE_REQUEST); + outMsg.writeInt32(being->getId()); +} + +void TradeHandler::respond(bool accept) +{ + if (!accept) + player_node->setTrading(false); + + MessageOut outMsg(CMSG_TRADE_RESPONSE); + outMsg.writeInt8(accept ? 3 : 4); +} + +void TradeHandler::addItem(Item *item, int amount) +{ + MessageOut outMsg(CMSG_TRADE_ITEM_ADD_REQUEST); + outMsg.writeInt16(item->getInvIndex() + INVENTORY_OFFSET); + outMsg.writeInt32(amount); +} + +void TradeHandler::removeItem(int slotNum, int amount) +{ + // TODO +} + +void TradeHandler::setMoney(int amount) +{ + MessageOut outMsg(CMSG_TRADE_ITEM_ADD_REQUEST); + outMsg.writeInt16(0); + outMsg.writeInt32(amount); +} + +void TradeHandler::confirm() +{ + MessageOut outMsg(CMSG_TRADE_ADD_COMPLETE); +} + +void TradeHandler::finish() +{ + MessageOut outMsg(CMSG_TRADE_OK); +} + +void TradeHandler::cancel() +{ + MessageOut outMsg(CMSG_TRADE_CANCEL_REQUEST); +} + +} // namespace TmwAthena -- cgit v1.2.3-70-g09d2