From 0d100ca5fc6854de9906d9e972ef26be6bbed802 Mon Sep 17 00:00:00 2001 From: blue112 Date: Tue, 21 Apr 2009 15:36:50 +0200 Subject: Trade System Patch (server side) Server side modification for making the three steps trade working. For tmwserv Some trade related protocol modification too. --- src/defines.h | 15 +++--- src/game-server/character.cpp | 2 +- src/game-server/gamehandler.cpp | 12 +++-- src/game-server/trade.cpp | 101 +++++++++++++++++++++++++++++++--------- src/game-server/trade.hpp | 22 ++++++--- 5 files changed, 113 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/defines.h b/src/defines.h index e4421e0c..a6655447 100644 --- a/src/defines.h +++ b/src/defines.h @@ -172,12 +172,15 @@ enum { GPMSG_TRADE_COMPLETE = 0x02C3, // - PGMSG_TRADE_CANCEL = 0x02C4, // - GPMSG_TRADE_CANCEL = 0x02C5, // - - PGMSG_TRADE_ACCEPT = 0x02C6, // - - GPMSG_TRADE_ACCEPT = 0x02C7, // - - PGMSG_TRADE_ADD_ITEM = 0x02C8, // B slot, B amount - GPMSG_TRADE_ADD_ITEM = 0x02C9, // W item id, B amount - PGMSG_TRADE_SET_MONEY = 0x02CA, // L amount - GPMSG_TRADE_SET_MONEY = 0x02CB, // L amount + PGMSG_TRADE_AGREED = 0x02C6, // - + GPMSG_TRADE_AGREED = 0x02C7, // - + PGMSG_TRADE_CONFIRM = 0x02C8, // - + GPMSG_TRADE_CONFIRM = 0x02C9, // - + PGMSG_TRADE_ADD_ITEM = 0x02CA, // B slot, B amount + GPMSG_TRADE_ADD_ITEM = 0x02CB, // W item id, B amount + PGMSG_TRADE_SET_MONEY = 0x02CC, // L amount + GPMSG_TRADE_SET_MONEY = 0x02CD, // L amount + GPMSG_TRADE_BOTH_CONFIRM = 0x02CE, // - PGMSG_USE_ITEM = 0x0300, // B slot GPMSG_USE_RESPONSE = 0x0301, // B error GPMSG_BEINGS_DAMAGE = 0x0310, // { W being id, W amount }* diff --git a/src/game-server/character.cpp b/src/game-server/character.cpp index d35124e5..b60cf4e1 100644 --- a/src/game-server/character.cpp +++ b/src/game-server/character.cpp @@ -221,7 +221,7 @@ void Character::cancelTransaction() switch (t) { case TRANS_TRADE: - static_cast< Trade * >(mTransactionHandler)->cancel(this); + static_cast< Trade * >(mTransactionHandler)->cancel(); break; case TRANS_BUYSELL: static_cast< BuySell * >(mTransactionHandler)->cancel(); diff --git a/src/game-server/gamehandler.cpp b/src/game-server/gamehandler.cpp index 7caa7191..e1301712 100644 --- a/src/game-server/gamehandler.cpp +++ b/src/game-server/gamehandler.cpp @@ -443,7 +443,8 @@ void GameHandler::processMessage(NetComputer *comp, MessageIn &message) } break; case PGMSG_TRADE_CANCEL: - case PGMSG_TRADE_ACCEPT: + case PGMSG_TRADE_AGREED: + case PGMSG_TRADE_CONFIRM: case PGMSG_TRADE_ADD_ITEM: case PGMSG_TRADE_SET_MONEY: { @@ -454,10 +455,13 @@ void GameHandler::processMessage(NetComputer *comp, MessageIn &message) switch (message.getId()) { case PGMSG_TRADE_CANCEL: - t->cancel(computer.character); + t->cancel(); break; - case PGMSG_TRADE_ACCEPT : - t->accept(computer.character); + case PGMSG_TRADE_CONFIRM: + t->confirm(computer.character); + break; + case PGMSG_TRADE_AGREED: + t->agree(computer.character); // log transaction accountHandler->sendTransaction(computer.character->getDatabaseID(), TRANS_TRADE_END, "User finished trading"); diff --git a/src/game-server/trade.cpp b/src/game-server/trade.cpp index e5ceea3d..92c31a82 100644 --- a/src/game-server/trade.cpp +++ b/src/game-server/trade.cpp @@ -30,6 +30,15 @@ #include "game-server/inventory.hpp" #include "net/messageout.hpp" +/* + * States : + * TRADE_INIT : A player has ask to make a trade, waiting for accept + * TRADE_RUN : Both player are now trading and can add objects and GP (1) + * TRADE_CONFIRM_WAIT : One player has confirm, waiting for the other one + * TRADE_CONFIRMED : Both player has confirmed and agree button is unlock (2) + * TRADE_AGREE_WAIT : One player has agreed, waiting for the other one + */ + Trade::Trade(Character *c1, Character *c2): mChar1(c1), mChar2(c2), mMoney1(0), mMoney2(0), mState(TRADE_INIT) { @@ -46,26 +55,31 @@ Trade::~Trade() mChar2->setTrading(NULL); } -void Trade::cancel(Character *c) +void Trade::cancel() { MessageOut msg(GPMSG_TRADE_CANCEL); - if (c != mChar1) mChar1->getClient()->send(msg); - if (c != mChar2) mChar2->getClient()->send(msg); + mChar1->getClient()->send(msg); + mChar2->getClient()->send(msg); delete this; } bool Trade::request(Character *c, int id) { + //The trade isn't confirmed, the player which is request is the same. if (mState != TRADE_INIT || c != mChar2 || mChar1->getPublicID() != id) { /* This is not an ack for the current transaction. So assume a new one is about to start and cancel the current one. */ - cancel(c); + cancel(); return false; } - - // Starts trading. + + //Second player confirmed. + + //Starts trading. mState = TRADE_RUN; + + //Telling both player that the trade has started MessageOut msg(GPMSG_TRADE_START); mChar1->getClient()->send(msg); mChar2->getClient()->send(msg); @@ -87,30 +101,37 @@ bool Trade::perform(TradedItems items, Inventory &inv1, Inventory &inv2) return true; } -void Trade::accept(Character *c) +void Trade::agree(Character *c) { - if (mState == TRADE_RUN) + //No player agreed + if(mState == TRADE_CONFIRMED) { + //One player agreed, if it's the player 2, make it player 1 if (c == mChar2) { std::swap(mChar1, mChar2); std::swap(mItems1, mItems2); std::swap(mMoney1, mMoney2); } - assert(c == mChar1); // First player agrees. - mState = TRADE_EXIT; - MessageOut msg(GPMSG_TRADE_ACCEPT); + mState = TRADE_CONFIRM_WAIT; + + //Send the other player that the first player has confirmed + MessageOut msg(GPMSG_TRADE_AGREED); mChar2->getClient()->send(msg); return; } - - if (mState != TRADE_EXIT || c != mChar2) + + if(mState == TRADE_AGREE_WAIT && c == mChar1) { - // First player has already agreed. We only care about the second one. + //We don't care about the first player, he already agreed return; } - + + //The second player has agreed + + //Check if both player has the objects in their inventories + // and enouth money, then swap them. Inventory v1(mChar1, true), v2(mChar2, true); if (!perform(mItems1, v1, v2) || !perform(mItems2, v2, v1) || @@ -119,19 +140,56 @@ void Trade::accept(Character *c) { v1.cancel(); v2.cancel(); - cancel(NULL); + cancel(); return; } - + MessageOut msg(GPMSG_TRADE_COMPLETE); mChar1->getClient()->send(msg); mChar2->getClient()->send(msg); delete this; } +void Trade::confirm(Character *c) +{ + if(mState == TRADE_CONFIRMED || mState == TRADE_AGREE_WAIT) return; + + if (mState == TRADE_RUN) //No player has confirmed + { + //One player confirms, if it's the player 2, make it player 1 + if (c == mChar2) + { + std::swap(mChar1, mChar2); + std::swap(mItems1, mItems2); + std::swap(mMoney1, mMoney2); + } + assert(c == mChar1); + // First player agrees. + mState = TRADE_CONFIRM_WAIT; + + //Send the other player that the first player has confirmed + MessageOut msg(GPMSG_TRADE_CONFIRM); + mChar2->getClient()->send(msg); + return; + } + + if (mState != TRADE_CONFIRM_WAIT || c != mChar2) + { + // First player has already agreed. We only care about the second one. + return; + } + + mState = TRADE_CONFIRMED; + MessageOut msg(GPMSG_TRADE_BOTH_CONFIRM); + mChar1->getClient()->send(msg); + mChar2->getClient()->send(msg); +} + void Trade::setMoney(Character *c, int amount) { - if (mState == TRADE_INIT || amount < 0) return; + //If the player has already confirmed, exit. + if ((mState != TRADE_RUN && (mState != TRADE_CONFIRM_WAIT || c != mChar1)) + || amount < 0) return; /* Checking now if there is enough money is useless as it can change later on. At worst, the transaction will be canceled at the end if @@ -158,7 +216,9 @@ void Trade::setMoney(Character *c, int amount) void Trade::addItem(Character *c, int slot, int amount) { - if (mState == TRADE_INIT) return; + //If the player has already confirmed, exit. + if ((mState != TRADE_RUN && (mState != TRADE_CONFIRM_WAIT || c != mChar1)) + || amount < 0) return; Character *other; TradedItems *items; @@ -192,7 +252,4 @@ void Trade::addItem(Character *c, int slot, int amount) msg.writeShort(id); msg.writeByte(amount); other->getClient()->send(msg); - - // Go back to normal run. - mState = TRADE_RUN; } diff --git a/src/game-server/trade.hpp b/src/game-server/trade.hpp index 14e99e82..f1a9613a 100644 --- a/src/game-server/trade.hpp +++ b/src/game-server/trade.hpp @@ -42,7 +42,7 @@ class Trade * Warns the other character the trade is cancelled. * Takes care of cleaning afterwards. */ - void cancel(Character *); + void cancel(void); /** * Requests a trade to start with given public ID. @@ -53,10 +53,15 @@ class Trade bool request(Character *, int); /** - * Agrees to complete the trade. + * Confirm the trade. */ - void accept(Character *); + void confirm(Character *); + /* + * Agree to complete the trade + */ + void agree(Character *c); + /** * Adds some items to the trade. */ @@ -79,11 +84,16 @@ class Trade typedef std::vector< TradedItem > TradedItems; + /* + * See trade.cpp for doc on TradeStates + */ enum TradeState { - TRADE_INIT = 0, /**< Waiting for an ack from player 2. */ - TRADE_RUN, /**< Currently trading. */ - TRADE_EXIT /**< Waiting for an ack from player 2. */ + TRADE_INIT = 0, + TRADE_RUN, + TRADE_CONFIRM_WAIT, + TRADE_CONFIRMED, + TRADE_AGREE_WAIT }; static bool perform(TradedItems items, Inventory &inv1, Inventory &inv2); -- cgit v1.2.3-60-g2f50