From 203774b4e7d1c5c0a74cb6f9e3e104fb2f5a2c81 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Sun, 31 Jul 2011 17:43:25 +0300 Subject: Extract shared logic from tradehandler netcode to ea namespace. --- src/net/ea/tradehandler.cpp | 284 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 src/net/ea/tradehandler.cpp (limited to 'src/net/ea/tradehandler.cpp') diff --git a/src/net/ea/tradehandler.cpp b/src/net/ea/tradehandler.cpp new file mode 100644 index 000000000..36a5f8811 --- /dev/null +++ b/src/net/ea/tradehandler.cpp @@ -0,0 +1,284 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011 The ManaPlus Developers + * + * This file is part of The ManaPlus 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/ea/tradehandler.h" + +#include "event.h" +#include "inventory.h" +#include "item.h" +#include "log.h" +#include "playerinfo.h" +#include "playerrelations.h" + +#include "gui/confirmdialog.h" +#include "gui/tradewindow.h" + +#include "net/inventoryhandler.h" +#include "net/messagein.h" + +#include "net/ea/eaprotocol.h" + +#include "utils/gettext.h" + +#include "debug.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; + if (event.getId() == "ignore") + player_relations.ignoreTrade(tradePartnerName); + Net::getTradeHandler()->respond(event.getId() == "yes"); + } + } listener; +} + +namespace Ea +{ + +TradeHandler::TradeHandler() +{ + confirmDlg = 0; +} + +void TradeHandler::removeItem(int slotNum A_UNUSED, int amount A_UNUSED) +{ + // TODO +} + +void TradeHandler::processTradeRequest(Net::MessageIn &msg) +{ + // 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 (PlayerInfo::isTrading() || confirmDlg) + { + Net::getTradeHandler()->respond(false); + return; + } + + tradePartnerName = tradePartnerNameTemp; + PlayerInfo::setTrading(true); + if (tradeWindow) + { + if (tradePartnerName.empty() + || tradeWindow->getAutoTradeNick() + != tradePartnerName) + { + tradeWindow->clear(); + confirmDlg = new ConfirmDialog( + _("Request for Trade"), + strprintf(_("%s wants to trade with you, do" + " you accept?"), tradePartnerName.c_str()), + true); + confirmDlg->addActionListener(&listener); + } + else + { + Net::getTradeHandler()->respond(true); + } + } + } + else + { + Net::getTradeHandler()->respond(false); + return; + } +} + +void TradeHandler::processTradeResponse(Net::MessageIn &msg) +{ + switch (msg.readInt8()) + { + case 0: // Too far away + SERVER_NOTICE(_("Trading isn't possible. Trade " + "partner is too far away.")) + break; + case 1: // Character doesn't exist + SERVER_NOTICE(_("Trading isn't possible. Character " + "doesn't exist.")) + break; + case 2: // Invite request check failed... + SERVER_NOTICE(_("Trade cancelled due to an unknown " + "reason.")) + break; + case 3: // Trade accepted + if (tradeWindow) + { + tradeWindow->reset(); + tradeWindow->setCaption(strprintf( + _("Trade: You and %s"), + tradePartnerName.c_str())); + tradeWindow->initTrade(tradePartnerName); + tradeWindow->setVisible(true); + } + break; + case 4: // Trade cancelled + if (player_relations.hasPermission(tradePartnerName, + PlayerRelation::SPEECH_LOG)) + { + SERVER_NOTICE(strprintf(_("Trade with %s cancelled."), + tradePartnerName.c_str())) + } + // otherwise ignore silently + + if (tradeWindow) + { + tradeWindow->setVisible(false); +// tradeWindow->clear(); + } + PlayerInfo::setTrading(false); + break; + default: // Shouldn't happen as well, but to be sure + SERVER_NOTICE(_("Unhandled trade cancel packet.")) + if (tradeWindow) + tradeWindow->clear(); + break; + } +} + +void TradeHandler::processTradeItemAdd(Net::MessageIn &msg) +{ + int amount = msg.readInt32(); + int type = msg.readInt16(); + int identify = msg.readInt8(); // identified flag + msg.readInt8(); // attribute + int refine = msg.readInt8(); // refine + msg.skip(8); // card (4 shorts) + + // TODO: handle also identified, etc + if (tradeWindow) + { + if (type == 0) + { + tradeWindow->setMoney(amount); + } + else + { + tradeWindow->addItem2(type, false, amount, refine, + static_cast(identify), false); + } + } +} + +void TradeHandler::processTradeItemAddResponse(Net::MessageIn &msg) +{ + // Trade: New Item add response (was 0x00ea, now 01b1) + const int index = msg.readInt16() - INVENTORY_OFFSET; + Item *item = PlayerInfo::getInventory()->getItem(index); + if (!item) + { + if (tradeWindow) + tradeWindow->receivedOk(true); + return; + } + int quantity = msg.readInt16(); + + int res = msg.readInt8(); + switch (res) + { + case 0: + // Successfully added item + if (item->isEquipment() && item->isEquipped()) + Net::getInventoryHandler()->unequipItem(item); + + if (tradeWindow) + { + tradeWindow->addItem2(item->getId(), true, + quantity, item->getRefine(), item->getColor(), + item->isEquipment()); + } + item->increaseQuantity(-quantity); + break; + case 1: + // Add item failed - player overweighted + SERVER_NOTICE(_("Failed adding item. Trade " + "partner is over weighted.")) + break; + case 2: + // Add item failed - player has no free slot + SERVER_NOTICE(_("Failed adding item. Trade " + "partner has no free slot.")) + break; + case 3: + // Add item failed - non tradable item + SERVER_NOTICE(_("Failed adding item. You " + "can't trade this item.")) + break; + default: + SERVER_NOTICE(_("Failed adding item for " + "unknown reason.")) + logger->log("QQQ SMSG_TRADE_ITEM_ADD_RESPONSE: " + + toString(res)); + break; + } +} + +void TradeHandler::processTradeOk(Net::MessageIn &msg) +{ + // 0 means ok from myself, 1 means ok from other; + if (tradeWindow) + tradeWindow->receivedOk(msg.readInt8() == 0); + else + msg.readInt8(); +} + +void TradeHandler::processTradeCancel(Net::MessageIn &msg A_UNUSED) +{ + SERVER_NOTICE(_("Trade canceled.")) + if (tradeWindow) + { + tradeWindow->setVisible(false); + tradeWindow->reset(); + } + PlayerInfo::setTrading(false); +} + +void TradeHandler::processTradeComplete(Net::MessageIn &msg A_UNUSED) +{ + SERVER_NOTICE(_("Trade completed.")) + if (tradeWindow) + { + tradeWindow->setVisible(false); + tradeWindow->reset(); + } + PlayerInfo::setTrading(false); +} + +} // namespace Ea -- cgit v1.2.3-60-g2f50