From 712b197ea0fb305905b4762422fdae1c49008710 Mon Sep 17 00:00:00 2001 From: David Athay Date: Fri, 19 Sep 2008 14:39:49 +0000 Subject: Added post communication between chat and game servers. --- src/account-server/main-account.cpp | 7 +++ src/account-server/serverhandler.cpp | 92 +++++++++++++++++++++++++++++++++++ src/chat-server/post.cpp | 69 ++++++++++++++++++++++++++ src/chat-server/post.hpp | 63 ++++++++++++++++++++++-- src/defines.h | 43 ++++++++++------ src/game-server/accountconnection.cpp | 74 ++++++++++++++++++++++++++++ src/game-server/accountconnection.hpp | 10 ++++ src/game-server/gamehandler.cpp | 25 ++++++++++ src/game-server/gamehandler.hpp | 10 ++++ src/game-server/main-game.cpp | 6 +++ src/game-server/postman.hpp | 60 +++++++++++++++++++++++ 11 files changed, 440 insertions(+), 19 deletions(-) create mode 100644 src/game-server/postman.hpp (limited to 'src') diff --git a/src/account-server/main-account.cpp b/src/account-server/main-account.cpp index c4c451ee..f203f363 100644 --- a/src/account-server/main-account.cpp +++ b/src/account-server/main-account.cpp @@ -38,6 +38,7 @@ #include "chat-server/chatchannelmanager.hpp" #include "chat-server/chathandler.hpp" #include "chat-server/guildmanager.hpp" +#include "chat-server/post.hpp" #include "common/configuration.hpp" #include "net/connectionhandler.hpp" #include "net/messageout.hpp" @@ -67,6 +68,9 @@ ChatChannelManager *chatChannelManager; /** Guild Manager */ GuildManager *guildManager; +/** Post Manager */ +PostManager *postalManager; + /** Callback used when SIGQUIT signal is received. */ static void closeGracefully(int) { @@ -151,6 +155,8 @@ static void initialize() chatChannelManager = new ChatChannelManager; // Initialise the Guild manager guildManager = new GuildManager; + // Initialise the post manager + postalManager = new PostManager; // --- Initialize the global handlers // FIXME: Make the global handlers global vars or part of a bigger @@ -192,6 +198,7 @@ static void deinitialize() delete stringFilter; delete chatChannelManager; delete guildManager; + delete postalManager; // Get rid of persistent data storage delete storage; diff --git a/src/account-server/serverhandler.cpp b/src/account-server/serverhandler.cpp index 7fc81100..db8d2640 100644 --- a/src/account-server/serverhandler.cpp +++ b/src/account-server/serverhandler.cpp @@ -31,6 +31,7 @@ #include "account-server/accounthandler.hpp" #include "account-server/character.hpp" #include "account-server/dalstorage.hpp" +#include "chat-server/post.hpp" #include "net/connectionhandler.hpp" #include "net/messagein.hpp" #include "net/messageout.hpp" @@ -324,6 +325,97 @@ void ServerHandler::processMessage(NetComputer *comp, MessageIn &msg) } } break; + case GCMSG_REQUEST_POST: + { + // Retrieve the post for user + LOG_DEBUG("GCMSG_REQUEST_POST"); + result.writeShort(CGMSG_POST_RESPONSE); + + // get the character + int characterId = msg.readLong(); + Character *ptr = storage->getCharacter(characterId, NULL); + if (!ptr) + { + // Invalid character + LOG_ERROR("Error finding character id for post"); + break; + } + + // get the post for that character + Post *post = postalManager->getPost(ptr); + + // send the character id of receiver + result.writeLong(characterId); + + // send the post if valid + if (post) + { + for (unsigned int i = 0; i < post->getNumberOfLetters(); ++i) + { + // get each letter, send the sender's id, + // the contents and any attachments + Letter *letter = post->getLetter(i); + result.writeLong(letter->getSender()->getDatabaseID()); + result.writeString(letter->getContents()); + std::vector items = letter->getAttachments(); + for (unsigned int j = 0; j < items.size(); ++j) + { + result.writeShort(items[j].itemId); + result.writeShort(items[j].amount); + } + } + + // clean up + postalManager->clearPost(ptr); + } + + } break; + + case GCMSG_STORE_POST: + { + // Store the letter for the user + LOG_DEBUG("GCMSG_STORE_POST"); + result.writeShort(CGMSG_STORE_POST_RESPONSE); + + // get the sender and receiver + int senderId = msg.readLong(); + std::string receiverName = msg.readString(); + + // get their characters + Character *sender = storage->getCharacter(senderId, NULL); + Character *receiver = storage->getCharacter(receiverName); + if (!sender || !receiver) + { + // Invalid character + LOG_ERROR("Error finding character id for post"); + result.writeByte(ERRMSG_INVALID_ARGUMENT); + break; + } + + // get the letter contents + std::string contents = msg.readString(); + + std::vector< std::pair > items; + while (msg.getUnreadLength()) + { + items.push_back(std::pair(msg.readShort(), msg.readShort())); + } + + // save the letter + Letter *letter = new Letter(0, sender, receiver); + letter->addText(contents); + for (unsigned int i = 0; i < items.size(); ++i) + { + InventoryItem item; + item.itemId = items[i].first; + item.amount = items[i].second; + letter->addAttachment(item); + } + postalManager->addLetter(letter); + + result.writeByte(ERRMSG_OK); + } break; + default: LOG_WARN("ServerHandler::processMessage, Invalid message type: " << msg.getId()); diff --git a/src/chat-server/post.cpp b/src/chat-server/post.cpp index ca5af04a..6fc06e2a 100644 --- a/src/chat-server/post.cpp +++ b/src/chat-server/post.cpp @@ -23,6 +23,7 @@ #include "post.hpp" +#include "../account-server/character.hpp" #include "../defines.h" Letter::Letter(int type, Character *sender, Character *receiver) @@ -31,6 +32,16 @@ Letter::Letter(int type, Character *sender, Character *receiver) } +Letter::~Letter() +{ + if (mSender) + delete mSender; + + if (mReceiver) + delete mReceiver; + +} + void Letter::setExpiry(unsigned long expiry) { mExpiry = expiry; @@ -41,6 +52,16 @@ unsigned long Letter::getExpiry() const return mExpiry; } +void Letter::addText(const std::string &text) +{ + mContents = text; +} + +std::string Letter::getContents() +{ + return mContents; +} + bool Letter::addAttachment(InventoryItem item) { if (mAttachments.size() > MAX_ATTACHMENTS) @@ -58,6 +79,29 @@ Character* Letter::getReceiver() return mReceiver; } +Character* Letter::getSender() +{ + return mSender; +} + +std::vector Letter::getAttachments() +{ + return mAttachments; +} + +Post::~Post() +{ + std::vector::iterator itr_end = mLetters.end(); + for (std::vector::iterator itr = mLetters.begin(); + itr != itr_end; + ++itr) + { + delete (*itr); + } + + mLetters.clear(); +} + bool Post::addLetter(Letter *letter) { if (mLetters.size() > MAX_LETTERS) @@ -70,6 +114,20 @@ bool Post::addLetter(Letter *letter) return true; } +Letter* Post::getLetter(int letter) const +{ + if (letter < 0 || letter > mLetters.size()) + { + return NULL; + } + return mLetters[letter]; +} + +unsigned int Post::getNumberOfLetters() const +{ + return mLetters.size(); +} + void PostManager::addLetter(Letter *letter) { std::map::iterator itr = @@ -99,3 +157,14 @@ Post* PostManager::getPost(Character *player) return itr->second; } + +void PostManager::clearPost(Character *player) +{ + std::map::iterator itr = + mPostBox.find(player); + if (itr != mPostBox.end()) + { + delete itr->second; + mPostBox.erase(itr); + } +} diff --git a/src/chat-server/post.hpp b/src/chat-server/post.hpp index f1102b7d..25aefb50 100644 --- a/src/chat-server/post.hpp +++ b/src/chat-server/post.hpp @@ -24,8 +24,8 @@ #ifndef _TMWSERV_POST_H_ #define _TMWSERV_POST_H_ -#include #include +#include #include #include "../common/inventorydata.hpp" @@ -38,10 +38,17 @@ class Letter public: /** * Constructor - * @param type Type of Letter + * @param type Type of Letter - unused + * @param sender Pointer to character that sent the letter + * @param receiver Pointer to character that will receive the letter */ Letter(int type, Character *sender, Character *receiver); + /** + * Destructor + */ + ~Letter(); + /** * Set the expiry */ @@ -52,9 +59,22 @@ public: */ unsigned long getExpiry() const; + /** + * Add text contents of letter + * This overwrites whatever was there previously + * @param text The content of the letter to add + */ + void addText(const std::string &text); + + /** + * Get the text contents of letter + * @return String containing the text + */ + std::string getContents(); + /** * Add an attachment - * @param aitem The attachment to add to the letter + * @param item The attachment to add to the letter * @return Returns true if the letter doesnt have too many attachments */ bool addAttachment(InventoryItem item); @@ -65,9 +85,21 @@ public: */ Character* getReceiver(); + /** + * Get the character who sent the letter + * @return Returns the Character who sent the letter + */ + Character* getSender(); + + /** + * Get the attachments + */ + std::vector getAttachments(); + private: unsigned int mType; unsigned long mExpiry; + std::string mContents; std::vector mAttachments; Character *mSender; Character *mReceiver; @@ -76,12 +108,28 @@ private: class Post { public: + /** + * Destructor + */ + ~Post(); + /** * Add letter to post * @param letter Letter to add * @return Returns true if post isnt full */ - bool addLetter(Letter *letter); + bool addLetter(Letter *letter); + + /** + * Return next letter + */ + Letter* getLetter(int letter) const; + + /** + * Return number of letters in post + * @return Returns the size of mLetters + */ + unsigned int getNumberOfLetters() const; private: std::vector mLetters; @@ -103,8 +151,15 @@ public: */ Post* getPost(Character *player); + /** + * Remove the post for character + */ + void clearPost(Character *player); + private: std::map mPostBox; }; +extern PostManager *postalManager; + #endif diff --git a/src/defines.h b/src/defines.h index 4538945f..0e7574a9 100644 --- a/src/defines.h +++ b/src/defines.h @@ -91,7 +91,7 @@ enum * - CPMSG_*: from chat server to client * - PGMSG_*: from client to game server * - GPMSG_*: from game server to client - * Components: B byte, W word, D double word, S variable-size string + * Components: B byte, W word, L long, S variable-size string * C tile-based coordinates (B*3) */ enum { @@ -239,20 +239,32 @@ enum { PCMSG_USER_MODE = 0x0465, // W channel id, S name, B mode PCMSG_KICK_USER = 0x0466, // W channel id, S name + // Post + PGMSG_SEND_POST = 0x04A0, // S player, S letter, { W attachment id } + GPMSG_SEND_POST_RESPONSE = 0x04A1, // B error + PGMSG_GET_POST = 0x04A2, // + GPMSG_GET_POST_RESPONSE = 0x04A3, // { L sender id, S letter, { W attachment id } } + // Inter-server - GAMSG_REGISTER = 0x0500, // S address, W port, { W map id }* - AGMSG_ACTIVE_MAP = 0x0501, // W map id - AGMSG_PLAYER_ENTER = 0x0510, // B*32 token, L id, S name, serialised character data - GAMSG_PLAYER_DATA = 0x0520, // L id, serialised character data - GAMSG_REDIRECT = 0x0530, // L id - AGMSG_REDIRECT_RESPONSE = 0x0531, // L id, B*32 token, S game address, W game port - GAMSG_PLAYER_RECONNECT = 0x0532, // L id, B*32 token - GAMSG_SET_QUEST = 0x0540, // L id, S name, S value - GAMSG_GET_QUEST = 0x0541, // L id, S name - AGMSG_GET_QUEST_RESPONSE = 0x0542, // L id, S name, S value - GAMSG_BAN_PLAYER = 0x550, // L id, W duration - GAMSG_STATISTICS = 0x560, // { W map id, W thing nb, W monster nb, W player nb, { L character id }* }* - CGMSG_CHANGED_PARTY = 0x0590, // L character id, L party id + GAMSG_REGISTER = 0x0500, // S address, W port, { W map id }* + AGMSG_ACTIVE_MAP = 0x0501, // W map id + AGMSG_PLAYER_ENTER = 0x0510, // B*32 token, L id, S name, serialised character data + GAMSG_PLAYER_DATA = 0x0520, // L id, serialised character data + GAMSG_REDIRECT = 0x0530, // L id + AGMSG_REDIRECT_RESPONSE = 0x0531, // L id, B*32 token, S game address, W game port + GAMSG_PLAYER_RECONNECT = 0x0532, // L id, B*32 token + GAMSG_SET_QUEST = 0x0540, // L id, S name, S value + GAMSG_GET_QUEST = 0x0541, // L id, S name + AGMSG_GET_QUEST_RESPONSE = 0x0542, // L id, S name, S value + GAMSG_BAN_PLAYER = 0x0550, // L id, W duration + GAMSG_STATISTICS = 0x0560, // { W map id, W thing nb, W monster nb, W player nb, { L character id }* }* + CGMSG_CHANGED_PARTY = 0x0590, // L character id, L party id + GCMSG_REQUEST_POST = 0x05A0, // L character id + CGMSG_POST_RESPONSE = 0x05A1, // L receiver id, { L sender id, S letter, W num attachments { W attachment item id, W quantity } } + GCMSG_STORE_POST = 0x05A5, // L sender id, L receiver id, S letter, { W attachment item id, W quantity } + CGMSG_STORE_POST_RESPONSE = 0x05A6, // L id, B error + + XXMSG_INVALID = 0x7FFF }; @@ -269,7 +281,8 @@ enum { ERRMSG_EMAIL_ALREADY_EXISTS, // The Email Address already exists ERRMSG_ALREADY_TAKEN, // name used was already taken ERRMSG_SERVER_FULL, // the server is overloaded - ERRMSG_TIME_OUT // data failed to arrive in due time + ERRMSG_TIME_OUT, // data failed to arrive in due time + ERRMSG_TOO_MANY_ATTACHMENTS, // too many attachments in letter }; // Login specific return values diff --git a/src/game-server/accountconnection.cpp b/src/game-server/accountconnection.cpp index 67ea9571..80e65730 100644 --- a/src/game-server/accountconnection.cpp +++ b/src/game-server/accountconnection.cpp @@ -30,6 +30,7 @@ #include "game-server/map.hpp" #include "game-server/mapcomposite.hpp" #include "game-server/mapmanager.hpp" +#include "game-server/postman.hpp" #include "game-server/quest.hpp" #include "game-server/state.hpp" #include "net/messagein.hpp" @@ -112,6 +113,56 @@ void AccountConnection::processMessage(MessageIn &msg) gameHandler->updateCharacter(charid, partyid); } break; + case CGMSG_POST_RESPONSE: + { + // get the character + Character *character = postMan->getCharacter(msg.readLong()); + + // check character is still valid + if (!character) + { + break; + } + + // create the message + MessageOut out(GPMSG_GET_POST_RESPONSE); + + // get all the post for a character + while (msg.getUnreadLength()) + { + // write the sender + out.writeLong(msg.readLong()); + + // write the contents + out.writeString(msg.readString()); + + // read the number of attachments then + // write the attachments + for (int i = 0; i < msg.readShort(); ++i) + { + // write the id and amount + out.writeShort(msg.readShort()); + out.writeShort(msg.readShort()); + } + } + + // send post to character + gameHandler->sendTo(character, out); + } break; + + case CGMSG_STORE_POST_RESPONSE: + { + // get character + Character *character = postMan->getCharacter(msg.readLong()); + + // create message and put error inside + MessageOut out(GPMSG_SEND_POST_RESPONSE); + out.writeByte(msg.readByte()); + + // send message to character + gameHandler->sendTo(character, out); + } break; + default: LOG_WARN("Invalid message type"); break; @@ -196,3 +247,26 @@ void AccountConnection::sendStatistics() send(msg); } +void AccountConnection::sendPost(Character *c, MessageIn &msg) +{ + // send message to account server with id of sending player, + // the id of receiving player, the letter contents, and attachments + MessageOut out(GCMSG_STORE_POST); + out.writeLong(c->getDatabaseID()); + out.writeString(msg.readString()); + out.writeString(msg.readString()); + while (msg.getUnreadLength()) + { + // write the item id and amount for each attachment + out.writeLong(msg.readShort()); + out.writeLong(msg.readShort()); + } +} + +void AccountConnection::getPost(Character *c) +{ + // send message to account server with id of retrieving player + MessageOut out(GCMSG_REQUEST_POST); + out.writeLong(c->getDatabaseID()); + send(out); +} diff --git a/src/game-server/accountconnection.hpp b/src/game-server/accountconnection.hpp index 6bad4651..2aa981ea 100644 --- a/src/game-server/accountconnection.hpp +++ b/src/game-server/accountconnection.hpp @@ -71,6 +71,16 @@ class AccountConnection : public Connection */ void sendStatistics(); + /** + * Send letter + */ + void sendPost(Character *, MessageIn &); + + /** + * Get post + */ + void getPost(Character *); + protected: /** * Processes server messages. diff --git a/src/game-server/gamehandler.cpp b/src/game-server/gamehandler.cpp index bd5248bd..3540ac51 100644 --- a/src/game-server/gamehandler.cpp +++ b/src/game-server/gamehandler.cpp @@ -34,6 +34,7 @@ #include "game-server/map.hpp" #include "game-server/mapcomposite.hpp" #include "game-server/npc.hpp" +#include "game-server/postman.hpp" #include "game-server/state.hpp" #include "game-server/trade.hpp" #include "net/messagein.hpp" @@ -449,6 +450,16 @@ void GameHandler::processMessage(NetComputer *comp, MessageIn &message) computer.character->respawn(); // plausibility check is done by character class } break; + case PGMSG_SEND_POST: + { + handleSendPost(&computer, message); + } break; + + case PGMSG_GET_POST: + { + handleGetPost(&computer, message); + } break; + default: LOG_WARN("Invalid message type"); result.writeShort(XXMSG_INVALID); @@ -585,3 +596,17 @@ void GameHandler::handleWalk(GameClient *client, MessageIn &message) client->character->setDestination(dst); } + +void GameHandler::handleSendPost(GameClient *client, MessageIn &message) +{ + // add the character so that the post man knows them + postMan->addCharacter(client->character); + accountHandler->sendPost(client->character, message); +} + +void GameHandler::handleGetPost(GameClient *client, MessageIn &message) +{ + // add the character so that the post man knows them + postMan->addCharacter(client->character); + accountHandler->getPost(client->character); +} diff --git a/src/game-server/gamehandler.hpp b/src/game-server/gamehandler.hpp index 77ba8a29..c41cdfd0 100644 --- a/src/game-server/gamehandler.hpp +++ b/src/game-server/gamehandler.hpp @@ -139,6 +139,16 @@ class GameHandler: public ConnectionHandler */ void handleWalk(GameClient *client, MessageIn &message); + /** + * Send a letter + */ + void handleSendPost(GameClient *client, MessageIn &message); + + /** + * Retrieve a letter + */ + void handleGetPost(GameClient *client, MessageIn &message); + private: /** diff --git a/src/game-server/main-game.cpp b/src/game-server/main-game.cpp index 2cf025e7..b1c454e4 100644 --- a/src/game-server/main-game.cpp +++ b/src/game-server/main-game.cpp @@ -37,6 +37,7 @@ #include "game-server/itemmanager.hpp" #include "game-server/mapmanager.hpp" #include "game-server/monstermanager.hpp" +#include "game-server/postman.hpp" #include "game-server/resourcemanager.hpp" #include "game-server/state.hpp" #include "net/connectionhandler.hpp" @@ -66,6 +67,9 @@ GameHandler *gameHandler; /** Account server message handler */ AccountConnection *accountHandler; +/** Post Man **/ +PostMan *postMan; + /** Callback used when SIGQUIT signal is received. */ void closeGracefully(int) { @@ -148,6 +152,7 @@ void initialize() // singleton or a local variable in the event-loop gameHandler = new GameHandler; accountHandler = new AccountConnection; + postMan = new PostMan; // --- Initialize enet. if (enet_initialize() != 0) { @@ -183,6 +188,7 @@ void deinitialize() // Destroy message handlers delete gameHandler; delete accountHandler; + delete postMan; // Destroy Managers delete stringFilter; diff --git a/src/game-server/postman.hpp b/src/game-server/postman.hpp new file mode 100644 index 00000000..45963cf9 --- /dev/null +++ b/src/game-server/postman.hpp @@ -0,0 +1,60 @@ +/* + * The Mana World + * Copyright 2008 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#ifndef _TMW_POSTMAN_H_ +#define _TMW_POSTMAN_H_ + +#include + +class Character; + +class PostMan +{ +public: + Character* getCharacter(int id) + { + std::map::iterator itr = mCharacters.find(id); + if (itr != mCharacters.end()) + { + return itr->second; + } + + return NULL; + } + + void addCharacter(Character *player) + { + std::map::iterator itr = mCharacters.find(player->getDatabaseID()); + if (itr == mCharacters.end()) + { + mCharacters.insert(std::pair(player->getDatabaseID(), player)); + } + } + +private: + std::map mCharacters; +}; + +extern PostMan *postMan; + +#endif -- cgit v1.2.3-60-g2f50