diff options
author | Guillaume Melquiond <guillaume.melquiond@gmail.com> | 2006-05-23 05:35:13 +0000 |
---|---|---|
committer | Guillaume Melquiond <guillaume.melquiond@gmail.com> | 2006-05-23 05:35:13 +0000 |
commit | 351f050dd77c7dfae7ab901b9dab08336e59b4fc (patch) | |
tree | 709142480b61e116eca5ac17685e29b6fe658e5a /src | |
parent | 71ef3ccdc4d628e93d445251121f36a35c6f6a4e (diff) | |
download | manaserv-351f050dd77c7dfae7ab901b9dab08336e59b4fc.tar.gz manaserv-351f050dd77c7dfae7ab901b9dab08336e59b4fc.tar.bz2 manaserv-351f050dd77c7dfae7ab901b9dab08336e59b4fc.tar.xz manaserv-351f050dd77c7dfae7ab901b9dab08336e59b4fc.zip |
Split server into three logical servers: an account server, a chat
server, and a game server.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/accounthandler.cpp | 215 | ||||
-rw-r--r-- | src/accounthandler.h | 31 | ||||
-rw-r--r-- | src/chatchannel.cpp | 34 | ||||
-rw-r--r-- | src/chatchannel.h | 10 | ||||
-rw-r--r-- | src/chatchannelmanager.cpp | 157 | ||||
-rw-r--r-- | src/chatchannelmanager.h | 29 | ||||
-rw-r--r-- | src/chathandler.cpp | 304 | ||||
-rw-r--r-- | src/chathandler.h | 104 | ||||
-rw-r--r-- | src/client.cpp | 96 | ||||
-rw-r--r-- | src/connectionhandler.cpp | 153 | ||||
-rw-r--r-- | src/connectionhandler.h | 69 | ||||
-rw-r--r-- | src/defines.h | 46 | ||||
-rw-r--r-- | src/gamehandler.cpp | 202 | ||||
-rw-r--r-- | src/gamehandler.h | 51 | ||||
-rw-r--r-- | src/main.cpp | 54 | ||||
-rw-r--r-- | src/messagehandler.cpp | 30 | ||||
-rw-r--r-- | src/messagehandler.h | 53 | ||||
-rw-r--r-- | src/netcomputer.cpp | 44 | ||||
-rw-r--r-- | src/netcomputer.h | 61 | ||||
-rw-r--r-- | src/state.cpp | 4 |
21 files changed, 902 insertions, 847 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 8d745a77..6fff83eb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -39,8 +39,6 @@ tmwserv_SOURCES = main.cpp \ mapmanager.cpp \ mapreader.cpp \ mapreader.h \ - messagehandler.h \ - messagehandler.cpp \ messagein.h \ messagein.cpp \ messageout.h \ diff --git a/src/accounthandler.cpp b/src/accounthandler.cpp index d1f9263a..d778c86c 100644 --- a/src/accounthandler.cpp +++ b/src/accounthandler.cpp @@ -24,29 +24,130 @@ #include "accounthandler.h" #include "account.h" +#include "chathandler.h" #include "configuration.h" #include "connectionhandler.h" #include "debug.h" -#include "storage.h" +#include "gamehandler.h" #include "messagein.h" #include "messageout.h" #include "netcomputer.h" +#include "storage.h" #include "utils/logger.h" #include "utils/stringfilter.h" using tmwserv::Account; using tmwserv::AccountPtr; +using tmwserv::BeingPtr; using tmwserv::Storage; +class AccountClient: public NetComputer +{ + public: + /** + * Constructor. + */ + AccountClient(AccountHandler *, ENetPeer *); + + /** + * Destructor. + */ + ~AccountClient(); + + /** + * Set the account associated with the connection + */ + void setAccount(AccountPtr acc); + + /** + * Unset the account associated with the connection + */ + void unsetAccount(); + + /** + * Get account associated with the connection. + */ + AccountPtr getAccount() { return mAccountPtr; } + + /** + * Set the selected character associated with connection. + */ + void setCharacter(BeingPtr ch); + + /** + * Deselect the character associated with connection. + */ + void unsetCharacter(); + + /** + * Get character associated with the connection + */ + BeingPtr getCharacter() { return mCharacterPtr; } + + private: + /** Account associated with connection */ + AccountPtr mAccountPtr; + + /** Selected character */ + BeingPtr mCharacterPtr; +}; + +AccountClient::AccountClient(AccountHandler *handler, ENetPeer *peer): + NetComputer(handler, peer), + mAccountPtr(NULL), + mCharacterPtr(NULL) +{ +} + +AccountClient::~AccountClient() +{ + unsetAccount(); +} + + +void AccountClient::setAccount(AccountPtr acc) +{ + unsetAccount(); + mAccountPtr = acc; +} + +void AccountClient::setCharacter(BeingPtr ch) +{ + unsetCharacter(); + mCharacterPtr = ch; +} + +void AccountClient::unsetAccount() +{ + unsetCharacter(); + mAccountPtr = AccountPtr(NULL); +} + +void AccountClient::unsetCharacter() +{ + if (mCharacterPtr.get() == NULL) return; + mCharacterPtr = BeingPtr(NULL); +} + +NetComputer *AccountHandler::computerConnected(ENetPeer *peer) +{ + return new AccountClient(this, peer); +} + +void AccountHandler::computerDisconnected(NetComputer *comp) +{ + delete comp; +} + /** * Generic interface convention for getting a message and sending it to the * correct subroutines. Account handler takes care of determining the * current step in the account process, be it creation, setup, or login. */ -void AccountHandler::receiveMessage(NetComputer &comp, MessageIn &message) +void AccountHandler::processMessage(NetComputer *comp, MessageIn &message) { - ClientComputer &computer = static_cast< ClientComputer & >(comp); + AccountClient &computer = *static_cast< AccountClient * >(comp); Storage &store = Storage::instance("tmw"); @@ -91,7 +192,7 @@ void AccountHandler::receiveMessage(NetComputer &comp, MessageIn &message) result.writeByte(LOGIN_ALREADY_LOGGED); break; } - if (connectionHandler->getClientNumber() >= MAX_CLIENTS ) + if (getClientNumber() >= MAX_CLIENTS ) { // Too much clients logged in. LOG_INFO("Client couldn't login. Already has " << MAX_CLIENTS @@ -704,6 +805,59 @@ void AccountHandler::receiveMessage(NetComputer &comp, MessageIn &message) } break; + case CMSG_ENTER_WORLD: + { + result.writeShort(SMSG_ENTER_WORLD_RESPONSE); + + if (computer.getAccount().get() == NULL) + { + result.writeByte(ENTER_WORLD_NOLOGIN); + LOG_INFO("Not logged in. Can't enter the world.", 1); + break; // not logged in + } + if (computer.getCharacter().get() == NULL) + { + result.writeByte(ENTER_WORLD_NO_CHARACTER_SELECTED); + LOG_INFO("No character selected. Can't enter the world.", 2); + break; // no character selected + } + std::string magic_token(32, ' '); + for(int i = 0; i < 32; ++i) magic_token[i] = 1 + (int) (127 * (rand() / (RAND_MAX + 1.0))); + result.writeByte(ENTER_WORLD_OK); + result.writeString("localhost"); + result.writeShort(9603); + result.writeString(magic_token, 32); + registerGameClient(magic_token, computer.getCharacter()); + } + break; + + case CMSG_ENTER_CHAT: + { + result.writeShort(SMSG_ENTER_CHAT_RESPONSE); + + if (computer.getAccount().get() == NULL) + { + result.writeByte(ENTER_CHAT_NOLOGIN); + LOG_INFO("Not logged in. Can't enter the chat.", 1); + break; // not logged in + } + if (computer.getCharacter().get() == NULL) + { + result.writeByte(ENTER_CHAT_NO_CHARACTER_SELECTED); + LOG_INFO("No character selected. Can't enter the chat.", 2); + break; // no character selected + } + std::string magic_token(32, ' '); + for(int i = 0; i < 32; ++i) magic_token[i] = 1 + (int) (127 * (rand() / (RAND_MAX + 1.0))); + result.writeByte(ENTER_CHAT_OK); + result.writeString("localhost"); + result.writeShort(9603); + result.writeString(magic_token, 32); + registerChatClient(magic_token, computer.getCharacter()->getName(), + computer.getAccount()->getLevel()); + } + break; + default: LOG_WARN("Invalid message type", 0); result.writeShort(SMSG_LOGIN_RESPONSE); @@ -714,56 +868,3 @@ void AccountHandler::receiveMessage(NetComputer &comp, MessageIn &message) // return result computer.send(result.getPacket()); } - -/* ----Login Message---- - * Accepts a login message and interprets it, assigning the proper - * login - * Preconditions: The requested handle is not logged in already. - * The requested handle exists. - * The requested handle is not banned or restricted. - * The character profile is valid - * Postconditions: The player recieves access through a character in - * the world. - * Return Value: SUCCESS if the player was successfully assigned the - * requested char, ERROR on early termination of the - * routine. - */ -int AccountHandler::loginMessage(ClientComputer &computer, MessageIn &message) -{ - // Get the handle (account) the player is requesting - // RETURN TMW_ACCOUNTERROR_NOEXIST if: requested does not handle exist - // RETURN TMW_ACCOUNTERROR_BANNED if: the handle status is - // HANDLE_STATUS_BANNED - // RETURN TMW_ACCOUNTERROR_ALREADYASSIGNED if: the handle is already - // assigned - - // Get the character within that handle that the player is requesting - // RETURN TMW_ACCOUNTERROR_CHARNOTFOUND if: character not found - - // Assign the player to that character - // RETURN TMW_ACCOUNTERROR_ASSIGNFAILED if: assignment not successful - - // return TMW_SUCCESS -- successful exit - return TMW_SUCCESS; -} - -/* ----Account Assignment---- - * Assigns the computer to this account, and allows it to make account - * changes using this structure. - * Preconditions: This structure already contains a valid accountHandle - * Postconditions: The player is connected to the account through this handle - * Return Value: SUCCESS if the player was successfully assigned the - * requested handle, ERROR on early termination of the - * routine. - */ -int -AccountHandler::assignAccount(ClientComputer &computer, tmwserv::Account *account) -{ - // RETURN TMW_ACCOUNTERROR_ASSIGNFAILED if: the account was accessed before - // being initalized. - - // Assign the handle - - - return TMW_SUCCESS; -} diff --git a/src/accounthandler.h b/src/accounthandler.h index 7c8f8b96..8b6bb8d2 100644 --- a/src/accounthandler.h +++ b/src/accounthandler.h @@ -24,15 +24,7 @@ #ifndef _TMWSERV_ACCOUNTHANDLER_H_ #define _TMWSERV_ACCOUNTHANDLER_H_ -#include "messagehandler.h" - -class MessageIn; -class NetComputer; -class ClientComputer; - -namespace tmwserv { - class Account; -} +#include "connectionhandler.h" /** * Manages the data stored in user accounts and provides a reliable interface @@ -42,24 +34,15 @@ namespace tmwserv { * be traced to this account through the NetComputer structure, then processed * here with the persistent stored data). */ -class AccountHandler : public MessageHandler +class AccountHandler : public ConnectionHandler { - public: - /** - * Receives account related messages. - */ - void receiveMessage(NetComputer &computer, MessageIn &message); - - private: - /** - * Handles the login message. - */ - int loginMessage(ClientComputer &computer, MessageIn &message); - + protected: /** - * Account assignment. + * Process account related messages. */ - int assignAccount(ClientComputer &computer, tmwserv::Account *account); + void processMessage(NetComputer *computer, MessageIn &message); + NetComputer *computerConnected(ENetPeer *); + void computerDisconnected(NetComputer *); }; #endif diff --git a/src/chatchannel.cpp b/src/chatchannel.cpp index ce1f6967..49301474 100644 --- a/src/chatchannel.cpp +++ b/src/chatchannel.cpp @@ -85,40 +85,30 @@ ChatChannel::setPassword(const std::string &channelPassword) mChannelPassword = channelPassword; } -std::vector<tmwserv::BeingPtr> -ChatChannel::getUserList() const +ChatChannel::ChannelUsers const &ChatChannel::getUserList() const { return mRegisteredUsers; } -bool -ChatChannel::addUserInChannel(tmwserv::BeingPtr beingPtr) +bool ChatChannel::addUserInChannel(std::string const &user) { // Check if the user already exists in the channel - for (std::vector<tmwserv::BeingPtr>::iterator i = mRegisteredUsers.begin(); i != mRegisteredUsers.end();) - { - if ( i->get() == beingPtr.get() ) return false; - ++i; - } - mRegisteredUsers.push_back(beingPtr); + ChannelUsers::const_iterator i = mRegisteredUsers.begin(), + i_end = mRegisteredUsers.end(); + if (std::find(i, i_end, user) == i_end) return false; + mRegisteredUsers.push_back(user); return true; } -bool -ChatChannel::removeUserFromChannel(tmwserv::BeingPtr beingPtr) +bool ChatChannel::removeUserFromChannel(std::string const &user) { - for (std::vector<tmwserv::BeingPtr>::iterator i = mRegisteredUsers.begin(); i != mRegisteredUsers.end();) - { - if ( i->get() == beingPtr.get() ) - { - mRegisteredUsers.erase(i); - return true; - } - ++i; - } - return false; + ChannelUsers::iterator i_end = mRegisteredUsers.end(), + i = std::find(mRegisteredUsers.begin(), i_end, user); + if (i == i_end) return false; + mRegisteredUsers.erase(i); + return true; } void ChatChannel::removeEveryUsersFromChannel() diff --git a/src/chatchannel.h b/src/chatchannel.h index 997519a8..f46b1dae 100644 --- a/src/chatchannel.h +++ b/src/chatchannel.h @@ -30,8 +30,8 @@ #include "being.h" class ChatChannel { - public: + typedef std::vector< std::string > ChannelUsers; /** * Constructors @@ -78,17 +78,17 @@ class ChatChannel { /** * Get the list of the users registered in the channel */ - std::vector<tmwserv::BeingPtr> getUserList() const; + ChannelUsers const &getUserList() const; /** * Add a user in the channel */ - bool addUserInChannel(tmwserv::BeingPtr beingPtr); + bool addUserInChannel(std::string const &); /** * Remove a user from the channel. */ - bool removeUserFromChannel(tmwserv::BeingPtr beingPtr); + bool removeUserFromChannel(std::string const &); /** * Empties a channel from its users (admin included). @@ -114,7 +114,7 @@ class ChatChannel { /** * The registered user list */ - std::vector<tmwserv::BeingPtr> mRegisteredUsers; + ChannelUsers mRegisteredUsers; }; diff --git a/src/chatchannelmanager.cpp b/src/chatchannelmanager.cpp index 05c9ea25..9a2af3b9 100644 --- a/src/chatchannelmanager.cpp +++ b/src/chatchannelmanager.cpp @@ -87,8 +87,7 @@ ChatChannelManager::registerPrivateChannel(const std::string& channelName, return channelId; } -bool -ChatChannelManager::removeChannel(const short channelId) +bool ChatChannelManager::removeChannel(short channelId) { for (std::map<short, ChatChannel>::iterator i = mChatChannels.begin(); i != mChatChannels.end();) { @@ -107,154 +106,92 @@ ChatChannelManager::removeChannel(const short channelId) } -short -ChatChannelManager::getChannelId(const std::string& channelName) +short ChatChannelManager::getChannelId(std::string const &channelName) { - for (std::map<short, ChatChannel>::iterator i = mChatChannels.begin(); i != mChatChannels.end();) - { - if ( i->second.getName() == channelName ) return i->first; - ++i; + for (std::map<short, ChatChannel>::const_iterator i = mChatChannels.begin(), i_end = mChatChannels.end(); + i != i_end; ++i) { + if (i->second.getName() == channelName) return i->first; } return 0; } -const std::string -ChatChannelManager::getChannelName(const short channelId) +std::string ChatChannelManager::getChannelName(short channelId) { - for (std::map<short, ChatChannel>::iterator i = mChatChannels.begin(); i != mChatChannels.end();) - { - if ( i->first == channelId ) return i->second.getName(); - ++i; - } - return ""; + std::map<short, ChatChannel>::iterator i = mChatChannels.find(channelId); + return (i != mChatChannels.end()) ? i->second.getName() : std::string(); } -const std::string -ChatChannelManager::getChannelAnnouncement(const short channelId) +std::string ChatChannelManager::getChannelAnnouncement(short channelId) { - for (std::map<short, ChatChannel>::iterator i = mChatChannels.begin(); i != mChatChannels.end();) - { - if ( i->first == channelId ) return i->second.getAnnouncement(); - ++i; - } - return "None"; + std::map<short, ChatChannel>::iterator i = mChatChannels.find(channelId); + return (i != mChatChannels.end()) ? i->second.getAnnouncement() : std::string(); } -const std::string -ChatChannelManager::getChannelPassword(const short channelId) +std::string ChatChannelManager::getChannelPassword(short channelId) { - for (std::map<short, ChatChannel>::iterator i = mChatChannels.begin(); i != mChatChannels.end();) - { - if ( i->first == channelId ) return i->second.getPassword(); - ++i; - } - return "None"; + std::map<short, ChatChannel>::iterator i = mChatChannels.find(channelId); + return (i != mChatChannels.end()) ? i->second.getPassword() : std::string(); } -bool -ChatChannelManager::setChannelAnnouncement(const short channelId, const std::string& channelAnnouncement) +bool ChatChannelManager::setChannelAnnouncement(short channelId, std::string const &channelAnnouncement) { - for (std::map<short, ChatChannel>::iterator i = mChatChannels.begin(); i != mChatChannels.end();) - { - if ( i->first == channelId ) - { - i->second.setAnnouncement(channelAnnouncement); - return true; - } - ++i; - } - return false; + std::map<short, ChatChannel>::iterator i = mChatChannels.find(channelId); + if (i == mChatChannels.end()) return false; + i->second.setAnnouncement(channelAnnouncement); + return true; } -bool -ChatChannelManager::setChannelPassword(const short channelId, const std::string& channelPassword) +bool ChatChannelManager::setChannelPassword(short channelId, std::string const &channelPassword) { - for (std::map<short, ChatChannel>::iterator i = mChatChannels.begin(); i != mChatChannels.end();) - { - if ( i->first == channelId ) - { - i->second.setPassword(channelPassword); - return true; - } - ++i; - } - return false; + std::map<short, ChatChannel>::iterator i = mChatChannels.find(channelId); + if (i == mChatChannels.end()) return false; + i->second.setPassword(channelPassword); + return true; } -const ChatChannel -ChatChannelManager::_getChannel(const short channelId) +ChatChannel ChatChannelManager::_getChannel(short channelId) { - for (std::map<short, ChatChannel>::iterator i = mChatChannels.begin(); i != mChatChannels.end();) - { - if ( i->first == channelId ) return i->second; - ++i; - } + std::map<short, ChatChannel>::iterator i = mChatChannels.find(channelId); + if (i != mChatChannels.end()) return i->second; return ChatChannel("", "", ""); } -bool -ChatChannelManager::addUserInChannel(tmwserv::BeingPtr beingPtr, const short channelId) +bool ChatChannelManager::addUserInChannel(std::string const &user, short channelId) { - for (std::map<short, ChatChannel>::iterator i = mChatChannels.begin(); i != mChatChannels.end();) - { - if ( i->first == channelId ) - { - return i->second.addUserInChannel(beingPtr); - } - ++i; - } - return false; + std::map<short, ChatChannel>::iterator i = mChatChannels.find(channelId); + if (i == mChatChannels.end()) return false; + return i->second.addUserInChannel(user); } -bool -ChatChannelManager::removeUserFromChannel(tmwserv::BeingPtr beingPtr, const short channelId) +bool ChatChannelManager::removeUserFromChannel(std::string const &user, short channelId) { - for (std::map<short, ChatChannel>::iterator i = mChatChannels.begin(); i != mChatChannels.end();) - { - if ( i->first == channelId ) - { - return i->second.removeUserFromChannel(beingPtr); - } - ++i; - } - return false; + std::map<short, ChatChannel>::iterator i = mChatChannels.find(channelId); + if (i == mChatChannels.end()) return false; + return i->second.removeUserFromChannel(user); } -void -ChatChannelManager::removeUserFromEveryChannels(tmwserv::BeingPtr beingPtr) +void ChatChannelManager::removeUserFromEveryChannels(std::string const &user) { - for (std::map<short, ChatChannel>::iterator i = mChatChannels.begin(); i != mChatChannels.end();) - { - i->second.removeUserFromChannel(beingPtr); - ++i; + for (std::map<short, ChatChannel>::iterator i = mChatChannels.begin(), i_end = mChatChannels.end(); + i != i_end; ++i) { + i->second.removeUserFromChannel(user); } } -std::vector<tmwserv::BeingPtr> -ChatChannelManager::getUserListInChannel(const short channelId) +std::vector< std::string > const & +ChatChannelManager::getUserListInChannel(short channelId) { - for (std::map<short, ChatChannel>::iterator i = mChatChannels.begin(); i != mChatChannels.end();) - { - if ( i->first == channelId ) - { - return i->second.getUserList(); - } - ++i; - } - std::vector<tmwserv::BeingPtr> emptyList; + std::map<short, ChatChannel>::iterator i = mChatChannels.find(channelId); + if (i != mChatChannels.end()) return i->second.getUserList(); + static std::vector< std::string > emptyList; return emptyList; } -bool -ChatChannelManager::isChannelRegistered(const short channelId) +bool ChatChannelManager::isChannelRegistered(short channelId) { - for (std::map<short, ChatChannel>::iterator i = mChatChannels.begin(); i != mChatChannels.end();) - { - if ( i->first == channelId ) return true; - ++i; - } - return false; + std::map<short, ChatChannel>::iterator i = mChatChannels.find(channelId); + return i != mChatChannels.end(); } diff --git a/src/chatchannelmanager.h b/src/chatchannelmanager.h index 3a2597f4..c1e50299 100644 --- a/src/chatchannelmanager.h +++ b/src/chatchannelmanager.h @@ -65,7 +65,7 @@ public: /** * Remove a channel. */ - bool removeChannel(const short channelId); + bool removeChannel(short channelId); /** * Get the id of a channel from its name. @@ -80,73 +80,68 @@ public: * * @return the name of the channel */ - const std::string getChannelName(const short channelId); + std::string getChannelName(short channelId); /** * Get the announcement string of a channel from its id. * * @return the announcement string of the channel */ - const std::string - getChannelAnnouncement(const short channelId); + std::string getChannelAnnouncement(short channelId); /** * Set the announcement string of a channel from its id. * * @return the announcement string of the channel */ - bool - setChannelAnnouncement(const short channelId, const std::string& channelAnnouncement); + bool setChannelAnnouncement(short channelId, std::string const &channelAnnouncement); /** * Set the announcement string of a channel from its id. * * @return the announcement string of the channel */ - bool - setChannelPassword(const short channelId, const std::string& channelPassword); + bool setChannelPassword(short channelId, const std::string& channelPassword); /** * Get the password of a channel from its id. * * @return the password of the channel */ - const std::string - getChannelPassword(const short channelId); + std::string getChannelPassword(short channelId); /** * get the ChatChannel object from its id. * * @return the ChatChannel object */ - const ChatChannel - _getChannel(const short channelId); + ChatChannel _getChannel(short channelId); /** * Add a user in a channel */ - bool addUserInChannel(tmwserv::BeingPtr beingPtr, const short channelId); + bool addUserInChannel(std::string const &, short channelId); /** * Remove a user from a channel. */ - bool removeUserFromChannel(tmwserv::BeingPtr beingPtr, const short channelId); + bool removeUserFromChannel(std::string const &, short channelId); /** * Remove a user from every channels. * Used at logout. */ - void removeUserFromEveryChannels(tmwserv::BeingPtr beingPtr); + void removeUserFromEveryChannels(std::string const &); /** * Get the list of the users registered in a channel */ - std::vector<tmwserv::BeingPtr> getUserListInChannel(const short channelId); + std::vector< std::string > const &getUserListInChannel(short channelId); /** * tells if a channel exists */ - bool isChannelRegistered(const short channelId); + bool isChannelRegistered(short channelId); private: diff --git a/src/chathandler.cpp b/src/chathandler.cpp index a9ad9f91..b1bf23b2 100644 --- a/src/chathandler.cpp +++ b/src/chathandler.cpp @@ -32,37 +32,128 @@ #include "utils/logger.h" #include "utils/stringfilter.h" -void ChatHandler::receiveMessage(NetComputer &comp, MessageIn &message) + +class ChatClient: public NetComputer +{ + public: + /** + * Constructor. + */ + ChatClient(ChatHandler *, ENetPeer *); + + std::string characterName; + AccountLevels accountLevel; +}; + +ChatClient::ChatClient(ChatHandler *handler, ENetPeer *peer): + NetComputer(handler, peer), + accountLevel(AL_NORMAL) +{ +} + +struct ChatPendingLogin { - ClientComputer &computer = static_cast< ClientComputer & >(comp); + std::string character; + AccountLevels level; + int timeout; +}; + +typedef std::map< std::string, ChatPendingLogin > ChatPendingLogins; +static ChatPendingLogins pendingLogins; - // If not logged in... - if (computer.getAccount().get() == NULL) +typedef std::map< std::string, ChatClient * > ChatPendingClients; +static ChatPendingClients pendingClients; + +void registerChatClient(std::string const &token, std::string const &name, int level) +{ + ChatPendingClients::iterator i = pendingClients.find(token); + if (i != pendingClients.end()) { - LOG_INFO("Not logged in, can't chat...", 2); + ChatClient *computer = i->second; + computer->characterName = name; + computer->accountLevel = (AccountLevels)level; + pendingClients.erase(i); MessageOut result; - result.writeShort(SMSG_CHAT); - result.writeByte(CHAT_NOLOGIN); - computer.send(result.getPacket()); - return; + result.writeShort(SMSG_CHATSRV_CONNECT_RESPONSE); + result.writeByte(CSRV_CONNECT_OK); + computer->send(result.getPacket()); } else { - // If no character selected yet... - if (computer.getCharacter().get() == NULL) + ChatPendingLogin p; + p.character = name; + p.level = (AccountLevels)level; + p.timeout = 300; // world ticks + pendingLogins.insert(std::make_pair(token, p)); + } +} + +void ChatHandler::removeOutdatedPending() +{ + ChatPendingLogins::iterator i = pendingLogins.begin(), next; + while (i != pendingLogins.end()) + { + next = i; ++next; + if (--i->second.timeout <= 0) pendingLogins.erase(i); + i = next; + } +} + +NetComputer *ChatHandler::computerConnected(ENetPeer *peer) +{ + return new ChatClient(this, peer); +} + +void ChatHandler::computerDisconnected(NetComputer *computer) +{ + for (ChatPendingClients::iterator i = pendingClients.begin(), i_end = pendingClients.end(); + i != i_end; ++i) + { + if (i->second == computer) { - MessageOut result; - result.writeShort(SMSG_CHAT); - result.writeByte(CHAT_NO_CHARACTER_SELECTED); - computer.send(result.getPacket()); - LOG_INFO("No character selected. Can't chat...", 2); - return; // character not selected + pendingClients.erase(i); + break; } } + delete computer; +} + +void ChatHandler::process() +{ + ConnectionHandler::process(); + removeOutdatedPending(); +} + +void ChatHandler::processMessage(NetComputer *comp, MessageIn &message) +{ + ChatClient &computer = *static_cast< ChatClient * >(comp); + + if (computer.characterName.empty()) { + if (message.getId() != CMSG_CHATSRV_CONNECT) return; + std::string magic_token = message.readString(32); + ChatPendingLogins::iterator i = pendingLogins.find(magic_token); + if (i == pendingLogins.end()) + { + for (ChatPendingClients::iterator i = pendingClients.begin(), i_end = pendingClients.end(); + i != i_end; ++i) { + if (i->second == &computer) return; + } + pendingClients.insert(std::make_pair(magic_token, &computer)); + return; + } + computer.characterName = i->second.character; + computer.accountLevel = i->second.level; + pendingLogins.erase(i); + MessageOut result; + result.writeShort(SMSG_CHATSRV_CONNECT_RESPONSE); + result.writeByte(CSRV_CONNECT_OK); + computer.send(result.getPacket()); + return; + } switch (message.getId()) { - case CMSG_SAY: + case CMSG_CHAT: { // chat to people around area std::string text = message.readString(); @@ -78,15 +169,6 @@ void ChatHandler::receiveMessage(NetComputer &comp, MessageIn &message) // The message is a command. Deal with it. handleCommand(computer, text); } - else - { - // The default channel (0) is when the character speaks - // to the characters around him in the map. - // We, then, look for every characters around him and - // send the message to them. - // By 'around', let's say AROUND_AREA_IN_TILES tiles square wide. - sayAround(computer, text); - } } else { @@ -144,8 +226,8 @@ void ChatHandler::receiveMessage(NetComputer &comp, MessageIn &message) char channelType = message.readByte(); if (!channelType) { - if (computer.getAccount()->getLevel() != (AccountLevels)AL_ADMIN && - computer.getAccount()->getLevel() != (AccountLevels)AL_GM) + if (computer.accountLevel != AL_ADMIN && + computer.accountLevel != AL_GM) { result.writeByte(CHATCNL_CREATE_UNSUFFICIENT_RIGHTS); computer.send(result.getPacket()); @@ -157,7 +239,7 @@ void ChatHandler::receiveMessage(NetComputer &comp, MessageIn &message) std::string channelPassword = message.readString(); // Checking datas // Seeking double-quotes in strings - if (channelName == "" || channelName.length() > MAX_CHANNEL_NAME || + if (channelName.empty() || channelName.length() > MAX_CHANNEL_NAME || stringFilter->findDoubleQuotes(channelName)) { result.writeByte(CHATCNL_CREATE_INVALID_NAME); @@ -198,7 +280,7 @@ void ChatHandler::receiveMessage(NetComputer &comp, MessageIn &message) // We add the player as admin of this channel as he created it. // The user registering a private channel is the only one to be able // to update the password and the announcement in it and also to remove it. - chatChannelManager->addUserInChannel(computer.getCharacter(), channelId); + chatChannelManager->addUserInChannel(computer.characterName, channelId); result.writeByte(CHATCNL_CREATE_OK); result.writeShort(channelId); @@ -230,8 +312,8 @@ void ChatHandler::receiveMessage(NetComputer &comp, MessageIn &message) // Public channels if (channelId < (signed)MAX_PUBLIC_CHANNELS_RANGE) { - if (computer.getAccount()->getLevel() != (AccountLevels)AL_ADMIN && - computer.getAccount()->getLevel() != (AccountLevels)AL_GM) + if (computer.accountLevel != AL_ADMIN && + computer.accountLevel != AL_GM) { result.writeByte(CHATCNL_DEL_UNSUFFICIENT_RIGHTS); } @@ -240,7 +322,7 @@ void ChatHandler::receiveMessage(NetComputer &comp, MessageIn &message) if (chatChannelManager->isChannelRegistered(channelId)) { // Make every user quit the channel - connectionHandler->makeUsersLeaveChannel(channelId); + makeUsersLeaveChannel(channelId); if (chatChannelManager->removeChannel(channelId)) result.writeByte(CHATCNL_DEL_OK); else @@ -257,14 +339,14 @@ void ChatHandler::receiveMessage(NetComputer &comp, MessageIn &message) if (chatChannelManager->isChannelRegistered(channelId)) { // We first see if the user is the admin (first user) of the channel - std::vector<tmwserv::BeingPtr> userList = + std::vector< std::string > const &userList = chatChannelManager->getUserListInChannel(channelId); - std::vector<tmwserv::BeingPtr>::const_iterator i = userList.begin(); + std::vector< std::string >::const_iterator i = userList.begin(); // if it's actually the private channel's admin - if ( (*i).get() == computer.getCharacter().get() ) + if (*i == computer.characterName) { // Make every user quit the channel - connectionHandler->makeUsersLeaveChannel(channelId); + makeUsersLeaveChannel(channelId); if (chatChannelManager->removeChannel(channelId)) result.writeByte(CHATCNL_DEL_OK); else @@ -301,7 +383,7 @@ void ChatHandler::receiveMessage(NetComputer &comp, MessageIn &message) if (channelId != 0 && chatChannelManager->isChannelRegistered(channelId)) { std::string channelPassword = chatChannelManager->getChannelPassword(channelId); - if (channelPassword != "None") + if (!channelPassword.empty()) { if (channelPassword != givenPassword) { @@ -310,25 +392,23 @@ void ChatHandler::receiveMessage(NetComputer &comp, MessageIn &message) break; } } - if (chatChannelManager->addUserInChannel(computer.getCharacter(), channelId)) + if (chatChannelManager->addUserInChannel(computer.characterName, channelId)) { result.writeByte(CHATCNL_IN_OK); // The user entered the channel, now give him the announcement string // and the user list. result.writeString(chatChannelManager->getChannelAnnouncement(channelId)); - std::vector<tmwserv::BeingPtr> userList = + std::vector< std::string > const &userList = chatChannelManager->getUserListInChannel(channelId); result.writeShort(userList.size()); - for (std::vector<tmwserv::BeingPtr>::iterator i = userList.begin(); i != userList.end(); - ++i) - { - result.writeString(i->get()->getName()); + for (std::vector< std::string >::const_iterator i = userList.begin(), i_end = userList.end(); + i != i_end; ++i) { + result.writeString(*i); } // Send an SMSG_UPDATE_CHANNEL_RESPONSE to warn other clients a user went // in the channel. - connectionHandler->warnUsersAboutPlayerEventInChat(channelId, - computer.getCharacter()->getName(), - CHATCNL_UPD_NEW_PLAYER); + warnUsersAboutPlayerEventInChat(channelId, computer.characterName, + CHATCNL_UPD_NEW_PLAYER); } else { @@ -350,14 +430,13 @@ void ChatHandler::receiveMessage(NetComputer &comp, MessageIn &message) short channelId = message.readShort(); if (channelId != 0 && chatChannelManager->isChannelRegistered(channelId)) { - if (chatChannelManager->removeUserFromChannel(computer.getCharacter(), channelId)) + if (chatChannelManager->removeUserFromChannel(computer.characterName, channelId)) { result.writeByte(CHATCNL_OUT_OK); // Send an SMSG_UPDATE_CHANNEL_RESPONSE to warn other clients a user left // the channel. - connectionHandler->warnUsersAboutPlayerEventInChat(channelId, - computer.getCharacter()->getName(), - CHATCNL_UPD_LEAVING_PLAYER); + warnUsersAboutPlayerEventInChat(channelId, computer.characterName, + CHATCNL_UPD_LEAVING_PLAYER); } else { @@ -378,7 +457,7 @@ void ChatHandler::receiveMessage(NetComputer &comp, MessageIn &message) } } -void ChatHandler::handleCommand(ClientComputer &computer, const std::string& command) +void ChatHandler::handleCommand(ChatClient &computer, std::string const &command) { LOG_INFO("Chat: Received unhandled command: " << command, 2); MessageOut result; @@ -387,7 +466,7 @@ void ChatHandler::handleCommand(ClientComputer &computer, const std::string& com computer.send(result.getPacket()); } -void ChatHandler::warnPlayerAboutBadWords(ClientComputer &computer) +void ChatHandler::warnPlayerAboutBadWords(ChatClient &computer) { // We could later count if the player is really often unpolite. MessageOut result; @@ -395,71 +474,116 @@ void ChatHandler::warnPlayerAboutBadWords(ClientComputer &computer) result.writeByte(CHAT_USING_BAD_WORDS); // The Channel computer.send(result.getPacket()); - LOG_INFO(computer.getCharacter()->getName() << " says bad words.", 2); + LOG_INFO(computer.characterName << " says bad words.", 2); } -void ChatHandler::announce(ClientComputer &computer, const std::string& text) +void ChatHandler::announce(ChatClient &computer, std::string const &text) { MessageOut result; - if ( computer.getAccount()->getLevel() == (AccountLevels)AL_ADMIN || - computer.getAccount()->getLevel() == (AccountLevels)AL_GM ) + if (computer.accountLevel == AL_ADMIN || + computer.accountLevel == AL_GM ) { LOG_INFO("ANNOUNCE: " << text, 0); // Send it to every beings. result.writeShort(SMSG_ANNOUNCEMENT); result.writeString(text); - connectionHandler->sendToEveryone(result); + sendToEveryone(result); } else { result.writeShort(SMSG_CHAT); result.writeByte(CHATCMD_UNSUFFICIENT_RIGHTS); computer.send(result.getPacket()); - LOG_INFO(computer.getCharacter()->getName() << + LOG_INFO(computer.characterName << " couldn't make an announcement due to insufficient rights.", 2); } } -void ChatHandler::sayAround(ClientComputer &computer, const std::string& text) +void ChatHandler::sayToPlayer(ChatClient &computer, std::string const &playerName, std::string const &text) { MessageOut result; - LOG_INFO( computer.getCharacter()->getName() << " says: " << text, 2); - // Send it to every beings around - result.writeShort(SMSG_CHAT); - result.writeShort(0); // The default channel - std::string say = computer.getCharacter()->getName(); - say += ": "; - say += text; - result.writeString(say); - connectionHandler->sendAround(computer.getCharacter(), result); -} - -void ChatHandler::sayToPlayer(ClientComputer &computer, const std::string& playerName, const std::string& text) -{ - MessageOut result; - LOG_INFO( computer.getCharacter()->getName() << " says to " << playerName - << ": " << text, 2); + LOG_INFO(computer.characterName << " says to " << playerName << ": " << text, 2); // Send it to the being if the being exists result.writeShort(SMSG_PRIVMSG); - std::string say = computer.getCharacter()->getName(); - say += ": "; - say += text; - result.writeString(say); - connectionHandler->sendTo(playerName, result); + result.writeString(computer.characterName); + result.writeString(text); + for (NetComputers::iterator i = clients.begin(), i_end = clients.end(); + i != i_end; ++i) { + if (static_cast< ChatClient * >(*i)->characterName == playerName) + { + (*i)->send(result.getPacket()); + break; + } + } } -void ChatHandler::sayInChannel(ClientComputer &computer, short channel, const std::string& text) +void ChatHandler::sayInChannel(ChatClient &computer, short channel, std::string const &text) { MessageOut result; - LOG_INFO( computer.getCharacter()->getName() << " says in channel " << channel - << ": " << text, 2); + LOG_INFO(computer.characterName << " says in channel " << channel << ": " << text, 2); // Send it to every beings in channel result.writeShort(SMSG_CHAT_CNL); result.writeShort(channel); - std::string say = computer.getCharacter()->getName(); - say += ": "; - say += text; - result.writeString(say); - connectionHandler->sendInChannel(channel, result); + result.writeString(computer.characterName); + result.writeString(text); + sendInChannel(channel, result); +} + +void ChatHandler::makeUsersLeaveChannel(short channelId) +{ + MessageOut result; + result.writeShort(SMSG_QUIT_CHANNEL_RESPONSE); + result.writeByte(CHATCNL_OUT_OK); + + std::vector< std::string > const &users = + chatChannelManager->getUserListInChannel(channelId); + for (NetComputers::iterator i = clients.begin(), i_end = clients.end(); + i != i_end; ++i) { + // If the client is in the channel, send it the 'leave now' packet + std::vector< std::string >::const_iterator j_end = users.end(), + j = std::find(users.begin(), j_end, static_cast< ChatClient * >(*i)->characterName); + if (j != j_end) + { + (*i)->send(result.getPacket()); + } + } +} + +void ChatHandler::warnUsersAboutPlayerEventInChat(short channelId, + std::string const &userName, + char eventId) +{ + MessageOut result; + result.writeShort(SMSG_UPDATE_CHANNEL_RESPONSE); + result.writeByte(eventId); + result.writeString(userName); + std::vector< std::string > const &users = + chatChannelManager->getUserListInChannel(channelId); + for (NetComputers::iterator i = clients.begin(), i_end = clients.end(); + i != i_end; ++i) { + // If the client is in the channel, send it the 'eventId' packet + std::vector< std::string >::const_iterator j_end = users.end(), + j = std::find(users.begin(), j_end, static_cast< ChatClient * >(*i)->characterName); + if (j != j_end) + { + (*i)->send(result.getPacket()); + } + } +} + +void ChatHandler::sendInChannel(short channelId, MessageOut &msg) +{ + std::vector< std::string > const &users = + chatChannelManager->getUserListInChannel(channelId); + for (NetComputers::iterator i = clients.begin(), i_end = clients.end(); + i != i_end; ++i) { + // If the being is in the channel, send it + std::vector< std::string >::const_iterator j_end = users.end(), + j = std::find(users.begin(), j_end, static_cast< ChatClient * >(*i)->characterName); + if (j != j_end) + { + (*i)->send(msg.getPacket()); + } + } } diff --git a/src/chathandler.h b/src/chathandler.h index d7273528..b5a81375 100644 --- a/src/chathandler.h +++ b/src/chathandler.h @@ -26,55 +26,73 @@ #include <iosfwd> -#include "messagehandler.h" +#include "connectionhandler.h" -class MessageIn; -class NetComputer; -class ClientComputer; +class ChatClient; /** * Manages all chat related */ -class ChatHandler : public MessageHandler +class ChatHandler : public ConnectionHandler { - public: - /** - * Receives chat related messages. - */ - void receiveMessage(NetComputer &computer, MessageIn &message); - - private: - /** - * Deals with command messages - */ - void handleCommand(ClientComputer &computer, const std::string& command); - - /** - * Tells the player to be more polite. - */ - void warnPlayerAboutBadWords(ClientComputer &computer); - - /** - * Announce a message to every being in the default channel. - */ - void announce(ClientComputer &computer, const std::string& text); - - /** - * Display a message to every player around one's player - * in the default channel. - * The tile area has been set to 10 for now. - */ - void sayAround(ClientComputer &computer, const std::string& text); - - /** - * Say something private to a player. - */ - void sayToPlayer(ClientComputer &computer, const std::string& playerName, const std::string& text); - - /** - * Say something in a specific channel. - */ - void sayInChannel(ClientComputer &computer, short channel, const std::string& text); + public: + void process(); + + protected: + /** + * Process chat related messages. + */ + void processMessage(NetComputer *computer, MessageIn &message); + NetComputer *computerConnected(ENetPeer *); + void computerDisconnected(NetComputer *); + + private: + /** + * Deal with command messages. + */ + void handleCommand(ChatClient &computer, std::string const &command); + + /** + * Tell the player to be more polite. + */ + void warnPlayerAboutBadWords(ChatClient &computer); + + /** + * Announce a message to every being in the default channel. + */ + void announce(ChatClient &computer, std::string const &text); + + /** + * Say something private to a player. + */ + void sayToPlayer(ChatClient &computer, std::string const &playerName, std::string const &text); + + /** + * Say something in a specific channel. + */ + void sayInChannel(ChatClient &computer, short channel, std::string const &); + + /** + * Send packet to every client in a registered channel. + */ + void sendInChannel(short channelId, MessageOut &); + + /** + * Tell a list of user they are leaving a channel. + */ + void makeUsersLeaveChannel(short channelId); + + /** + * Tell a list of user about an event in a chatchannel about a player. + */ + void warnUsersAboutPlayerEventInChat(short channelId, std::string const &userName, char eventId); + + void removeOutdatedPending(); }; +/** + * Register future client attempt. Temporary until physical server split. + */ +void registerChatClient(std::string const &, std::string const &, int); + #endif diff --git a/src/client.cpp b/src/client.cpp index b9c9ea71..925f36a2 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -35,6 +35,12 @@ void parsePacket(char *data, int recvLength); +ENetHost *client; +ENetAddress addressAccount, addressGame; +ENetPeer *peerAccount, *peerGame; +std::string token; +bool connected = false; + int main(int argc, char *argv[]) { @@ -51,10 +57,8 @@ int main(int argc, char *argv[]) atexit(enet_deinitialize); - ENetHost *client; - client = enet_host_create(NULL /* create a client host */, - 1 /* only allow 1 outgoing connection */, + 3 /* allows 3 outgoing connection */, 57600 / 8 /* 56K modem with 56 Kbps downstream bandwidth */, 14400 / 8 /* 56K modem with 14 Kbps upstream bandwidth */); @@ -64,49 +68,45 @@ int main(int argc, char *argv[]) exit (EXIT_FAILURE); } - ENetAddress address; - ENetPeer *peer; - /* Connect to localhost:9601. */ - enet_address_set_host(&address, "localhost"); - address.port = 9601; + enet_address_set_host(&addressAccount, "localhost"); + addressAccount.port = 9601; /* Initiate the connection, allocating one channel. */ - peer = enet_host_connect(client, &address, 1); + peerAccount = enet_host_connect(client, &addressAccount, 1); - if (peer == NULL) + if (peerAccount == NULL) { printf("No available peers for initiating an ENet connection.\n"); exit (EXIT_FAILURE); } ENetEvent event; - bool exit = false; - bool connected = false; - int answer = 0; + bool exit = true; char line[256] = ""; - bool responseRequired = false; printf("Starting client...\n"); /* Wait up to 1000 milliseconds for an event. */ - while (!exit) { + do { if (connected) { + int answer = -1; std::cout << std::endl; std::cout << "0) Quit 9) Character selection" << std::endl; std::cout << "1) Register 10) Delete Character" << std::endl; std::cout << "2) Unregister 11) List Characters" << std::endl; std::cout << "3) Login 12) Move Character" << std::endl; - std::cout << "4) Logout 13) Chat" << std::endl; + std::cout << "4) Logout 13) Say around" << std::endl; std::cout << "5) Change Password 14) Equip Item" << std::endl; std::cout << "6) Change Email 15) Ruby Expression" << std::endl; - std::cout << "7) Get Email" << std::endl; - std::cout << "8) Create character" << std::endl; + std::cout << "7) Get Email 16) Enter world" << std::endl; + std::cout << "8) Create character 17) Enter world (GS)" << std::endl; std::cout << "Choose your option: "; std::cin >> answer; std::cin.getline(line, 256); // skip the remaining of the line MessageOut msg; + int msgDestination = 0; // account server switch (answer) { case 0: @@ -272,19 +272,19 @@ int main(int argc, char *argv[]) msg.writeLong(x); msg.writeLong(y); - responseRequired = false; + msgDestination = 1; } break; case 13: { // Chat msg.writeShort(CMSG_SAY); - std::cout << "Chat: "; + std::cout << "Say: "; std::cin.getline(line, 256); line[255] = '\0'; msg.writeString(line); - msg.writeShort(0); - responseRequired = false; + + msgDestination = 1; } break; case 14: @@ -299,6 +299,8 @@ int main(int argc, char *argv[]) msg.writeShort(CMSG_EQUIP); msg.writeLong(itemId); msg.writeByte(slot); + + msgDestination = 1; } break; case 15: @@ -307,13 +309,22 @@ int main(int argc, char *argv[]) std::cin >> line; msg.writeShort(0x800); msg.writeString(line); + } break; - responseRequired = false; + case 16: + { + msg.writeShort(CMSG_ENTER_WORLD); + } break; + + case 17: + { + msg.writeShort(CMSG_GAMESRV_CONNECT); + msg.writeString(token, 32); + msgDestination = 1; } break; default: - continue; - break; + goto process_enet; } // end switch // Send prepared message @@ -323,15 +334,17 @@ int main(int argc, char *argv[]) msg.getDataSize() + 1, ENET_PACKET_FLAG_RELIABLE); // Send the packet to the peer over channel id 0. - enet_peer_send(peer, 0, packet); + enet_peer_send(msgDestination == 0 ? peerAccount : peerGame, 0, packet); } // end if } // end if + process_enet: while (enet_host_service(client, &event, 1000)) { switch (event.type) { case ENET_EVENT_TYPE_CONNECT: printf("Connected to server\n"); connected = true; + exit = false; break; case ENET_EVENT_TYPE_RECEIVE: @@ -351,6 +364,7 @@ int main(int argc, char *argv[]) case ENET_EVENT_TYPE_DISCONNECT: printf("Disconnected.\n"); connected = false; + exit = true; break; default: @@ -358,11 +372,7 @@ int main(int argc, char *argv[]) break; } // end switch } // end while - - if (!connected) { - exit = true; - } - } // end while + } while (!exit); if (connected) { // The disconnection attempt didn't succeed yet. Force disconnection. @@ -697,13 +707,31 @@ void parsePacket(char *data, int recvLength) { } } break; - case SMSG_CHAT: + case SMSG_SAY: { - short channel = msg.readShort(); - std::cout << "Chat on channel " << channel << ':' << std::endl + std::string who = msg.readString(); + std::cout << who << " says around:" << std::endl << msg.readString() << std::endl; } break; + case SMSG_ENTER_WORLD_RESPONSE: + { + switch (msg.readByte()) { + case ENTER_WORLD_OK: + { + std::string server = msg.readString(); + enet_address_set_host(&addressGame, server.c_str()); + addressGame.port = msg.readShort(); + peerGame = enet_host_connect(client, &addressGame, 1); + token = msg.readString(32); + connected = false; + std::cout << "Connecting to " << server << ':' << addressGame.port << std::endl; + } break; + default: + std::cout << "Enter world failed." << std::endl; + } + } break; + default: break; } // end switch MessageId diff --git a/src/connectionhandler.cpp b/src/connectionhandler.cpp index bbb3e9d4..bf2e942b 100644 --- a/src/connectionhandler.cpp +++ b/src/connectionhandler.cpp @@ -23,7 +23,6 @@ #include "connectionhandler.h" #include "chatchannelmanager.h" -#include "messagehandler.h" #include "messagein.h" #include "messageout.h" #include "netcomputer.h" @@ -56,8 +55,7 @@ ClientData::ClientData(): { } -bool -ConnectionHandler::startListen(enet_uint16 port) +bool ConnectionHandler::startListen(enet_uint16 port) { // Bind the server to the default localhost. address.host = ENET_HOST_ANY; @@ -72,8 +70,7 @@ ConnectionHandler::startListen(enet_uint16 port) return host; } -void -ConnectionHandler::stopListen() +void ConnectionHandler::stopListen() { // - Disconnect all clients (close sockets) @@ -92,10 +89,20 @@ ConnectionHandler::stopListen() } } enet_host_destroy(host); + // FIXME: memory leak on NetComputers } -void -ConnectionHandler::process() +void ConnectionHandler::forceDisconnect(NetComputer *comp) +{ + enet_peer_disconnect(comp->getPeer(), 0); // ENet should generate a disconnect event +} + +void ConnectionHandler::flush() +{ + enet_host_flush(host); +} + +void ConnectionHandler::process() { ENetEvent event; // Process Enet events and do not block. @@ -143,18 +150,7 @@ ConnectionHandler::process() Packet *packet = new Packet((char *)event.packet->data, event.packet->dataLength); MessageIn msg(packet); // (MessageIn frees packet) - - short messageId = msg.getId(); - - HandlerMap::iterator it = handlers.find(messageId); - if (it != handlers.end()) { - // send message to appropriate handler - it->second->receiveMessage(*comp, msg); - } else { - // bad message (no registered handler) - LOG_ERROR("Unhandled message (" << messageId - << ") received from " << ipaddr, 0); - } + processMessage(comp, msg); } else { LOG_ERROR("Message too short from " << ipaddr, 0); } @@ -166,8 +162,7 @@ ConnectionHandler::process() case ENET_EVENT_TYPE_DISCONNECT: { NetComputer *comp = (NetComputer *)event.peer->data; - /*LOG_INFO(event.peer->address.host - << " disconected.", 0);*/ + LOG_INFO(ip4ToString(event.peer->address.host) << " disconnected.", 0); // Reset the peer's client information. computerDisconnected(comp); clients.erase(std::find(clients.begin(), clients.end(), comp)); @@ -179,34 +174,6 @@ ConnectionHandler::process() } } -void ConnectionHandler::registerHandler( - unsigned int msgId, MessageHandler *handler) -{ - handlers[msgId] = handler; -} - -void ClientConnectionHandler::sendTo(tmwserv::BeingPtr beingPtr, MessageOut &msg) -{ - for (NetComputers::iterator i = clients.begin(), i_end = clients.end(); - i != i_end; ++i) { - if (static_cast< ClientComputer * >(*i)->getCharacter().get() == beingPtr.get()) { - (*i)->send(msg.getPacket()); - break; - } - } -} - -void ClientConnectionHandler::sendTo(std::string name, MessageOut &msg) -{ - for (NetComputers::iterator i = clients.begin(), i_end = clients.end(); - i != i_end; ++i) { - if (static_cast< ClientComputer * >(*i)->getCharacter()->getName() == name) { - (*i)->send(msg.getPacket()); - break; - } - } -} - void ConnectionHandler::sendToEveryone(MessageOut &msg) { for (NetComputers::iterator i = clients.begin(), i_end = clients.end(); @@ -215,95 +182,7 @@ void ConnectionHandler::sendToEveryone(MessageOut &msg) } } -void ClientConnectionHandler::sendAround(tmwserv::BeingPtr beingPtr, MessageOut &msg) -{ - unsigned speakerMapId = beingPtr->getMapId(); - std::pair<unsigned, unsigned> speakerXY = beingPtr->getXY(); - for (NetComputers::iterator i = clients.begin(), i_end = clients.end(); - i != i_end; ++i) { - // See if the other being is near enough, then send the message - tmwserv::Being const *listener = static_cast< ClientComputer * >(*i)->getCharacter().get(); - if (listener->getMapId() != speakerMapId) continue; - std::pair<unsigned, unsigned> listenerXY = listener->getXY(); - if (abs(listenerXY.first - speakerXY.first ) > (int)AROUND_AREA_IN_TILES) continue; - if (abs(listenerXY.second - speakerXY.second) > (int)AROUND_AREA_IN_TILES) continue; - (*i)->send(msg.getPacket()); - } -} - -void ClientConnectionHandler::sendInChannel(short channelId, MessageOut &msg) -{ - for (NetComputers::iterator i = clients.begin(), i_end = clients.end(); - i != i_end; ++i) { - const std::vector<tmwserv::BeingPtr> beingList = - chatChannelManager->getUserListInChannel(channelId); - // If the being is in the channel, send it - for (std::vector<tmwserv::BeingPtr>::const_iterator j = beingList.begin(), j_end = beingList.end(); - j != j_end; ++j) { - if (static_cast< ClientComputer * >(*i)->getCharacter().get() == j->get()) - { - (*i)->send(msg.getPacket()); - } - } - } -} - unsigned int ConnectionHandler::getClientNumber() { return clients.size(); } - -void ClientConnectionHandler::makeUsersLeaveChannel(const short channelId) -{ - MessageOut result; - result.writeShort(SMSG_QUIT_CHANNEL_RESPONSE); - result.writeByte(CHATCNL_OUT_OK); - - const std::vector<tmwserv::BeingPtr> beingList = - chatChannelManager->getUserListInChannel(channelId); - for (NetComputers::iterator i = clients.begin(), i_end = clients.end(); - i != i_end; ++i) { - // If the being is in the channel, send it the 'leave now' packet - for (std::vector<tmwserv::BeingPtr>::const_iterator j = beingList.begin(), j_end = beingList.end(); - j != j_end; ++j) { - if (static_cast< ClientComputer * >(*i)->getCharacter().get() == j->get()) - { - (*i)->send(result.getPacket()); - } - } - } -} - -void ClientConnectionHandler::warnUsersAboutPlayerEventInChat(const short channelId, - const std::string& userName, - const char eventId) -{ - MessageOut result; - result.writeShort(SMSG_UPDATE_CHANNEL_RESPONSE); - result.writeByte(eventId); - result.writeString(userName); - - const std::vector<tmwserv::BeingPtr> beingList = - chatChannelManager->getUserListInChannel(channelId); - for (NetComputers::iterator i = clients.begin(), i_end = clients.end(); - i != i_end; ++i) { - // If the being is in the channel, send it the 'eventId' packet - for (std::vector<tmwserv::BeingPtr>::const_iterator j = beingList.begin(), j_end = beingList.end(); - j != j_end; ++j) { - if (static_cast< ClientComputer * >(*i)->getCharacter().get() == j->get() ) - { - (*i)->send(result.getPacket()); - } - } - } -} - -NetComputer *ClientConnectionHandler::computerConnected(ENetPeer *peer) { - LOG_INFO("A client connected!", 0); - return new ClientComputer(this, peer); -} - -void ClientConnectionHandler::computerDisconnected(NetComputer *comp) { - delete comp; - LOG_INFO("A client disconnected!", 0); -} diff --git a/src/connectionhandler.h b/src/connectionhandler.h index 1b4e8036..3ce8bdbe 100644 --- a/src/connectionhandler.h +++ b/src/connectionhandler.h @@ -25,14 +25,11 @@ #define _TMWSERV_CONNECTIONHANDLER_H_ #include <list> -#include <map> #include <enet/enet.h> -#include "being.h" - #define IN_BUFFER_SIZE 8192 -class MessageHandler; +class MessageIn; class MessageOut; class NetComputer; @@ -75,7 +72,12 @@ class ConnectionHandler * Process outgoing messages and listen to the server socket for * incoming messages and new connections. */ - void process(); + virtual void process(); + + /** + * Process outgoing messages. + */ + void flush(); /** * Called when a computer sends a packet to the network session. @@ -83,9 +85,9 @@ class ConnectionHandler //void receivePacket(NetComputer *computer, Packet *packet); /** - * Registers a message handler to handle a certain message type. + * Force disconnection of target computer. */ - void registerHandler(unsigned int msgId, MessageHandler *handler); + void forceDisconnect(NetComputer *); /** * Send packet to every client, used for announcements. @@ -101,9 +103,6 @@ class ConnectionHandler ENetAddress address; /**< Includes the port to listen to. */ ENetHost *host; /**< The host that listen for connections. */ - typedef std::map< unsigned int, MessageHandler * > HandlerMap; - HandlerMap handlers; - protected: /** * Called when a computer connects to the server. Initialize @@ -124,6 +123,11 @@ class ConnectionHandler */ virtual void computerDisconnected(NetComputer *) = 0; + /** + * Called when a message is received. + */ + virtual void processMessage(NetComputer *, MessageIn &) = 0; + typedef std::list<NetComputer*> NetComputers; /** * A list of pointers to the client structures created by @@ -132,49 +136,4 @@ class ConnectionHandler NetComputers clients; }; -/** - * Temporary placeholder until the connection handlers have been split. - */ -class ClientConnectionHandler: public ConnectionHandler -{ - public: - /** - * Send packet to client with matching BeingPtr - */ - void sendTo(tmwserv::BeingPtr, MessageOut &); - - /** - * Send packet to client with matching Being name - */ - void sendTo(std::string name, MessageOut &); - - /** - * Send packet to every client around the client on screen. - */ - void sendAround(tmwserv::BeingPtr, MessageOut &); - - /** - * Send packet to every client in a registered channel. - */ - void sendInChannel(short channelId, MessageOut &); - - /** - * tells a list of user they're leaving a channel. - */ - void makeUsersLeaveChannel(const short channelId); - - /** - * tells a list of user about an event in a chatchannel about a player. - */ - void warnUsersAboutPlayerEventInChat(const short channelId, - const std::string& userName, - const char eventId); - - protected: - virtual NetComputer *computerConnected(ENetPeer *); - virtual void computerDisconnected(NetComputer *); -}; - -extern ClientConnectionHandler *connectionHandler; - #endif diff --git a/src/defines.h b/src/defines.h index faab7073..a37c7e74 100644 --- a/src/defines.h +++ b/src/defines.h @@ -116,6 +116,8 @@ enum { SMSG_LOGIN_RESPONSE = 0x0012, CMSG_LOGOUT = 0x0013, SMSG_LOGOUT_RESPONSE = 0x0014, + CMSG_FORGOT_PASSWORD = 0x0015, + SMSG_FORGOT_PASSWORD_RESPONSE = 0x0016, CMSG_CHAR_CREATE = 0x0020, SMSG_CHAR_CREATE_RESPONSE = 0x0021, CMSG_CHAR_DELETE = 0x0022, @@ -128,10 +130,18 @@ enum { SMSG_EMAIL_CHANGE_RESPONSE = 0x0031, CMSG_EMAIL_GET = 0x0032, SMSG_EMAIL_GET_RESPONSE = 0x0033, - CMSG_FORGOT_PASSWORD = 0x0040, - SMSG_FORGOT_PASSWORD_RESPONSE = 0x0041, - CMSG_PASSWORD_CHANGE = 0x0050, - SMSG_PASSWORD_CHANGE_RESPONSE = 0x0051, + CMSG_PASSWORD_CHANGE = 0x0034, + SMSG_PASSWORD_CHANGE_RESPONSE = 0x0035, + CMSG_ENTER_WORLD = 0x0040, + SMSG_ENTER_WORLD_RESPONSE = 0x0041, + CMSG_ENTER_CHAT = 0x0042, + SMSG_ENTER_CHAT_RESPONSE = 0x0043, + CMSG_GAMESRV_CONNECT = 0x0050, + SMSG_GAMESRV_CONNECT_RESPONSE = 0x0051, + SMSG_GAMESRV_DISCONNECT = 0x0052, + CMSG_CHATSRV_CONNECT = 0x0053, + SMSG_CHATSRV_CONNECT_RESPONSE = 0x0054, + SMSG_CHATSRV_DISCONNECT = 0x0055, // Objects SMSG_NEW_OBJECT = 0x0100, @@ -166,9 +176,11 @@ enum { SMSG_ANNOUNCEMENT = 0x0402, SMSG_PRIVMSG = 0x0403, SMSG_CHAT_CNL = 0x0404, - CMSG_SAY = 0x0410, + SMSG_SAY = 0x0405, + CMSG_CHAT = 0x0410, CMSG_ANNOUNCE = 0x0411, CMSG_PRIVMSG = 0x0412, + CMSG_SAY = 0x0413, // -- Channeling CMSG_REGISTER_CHANNEL = 0x0413, SMSG_REGISTER_CHANNEL_RESPONSE = 0x0414, @@ -296,6 +308,30 @@ enum { PASSCHG_UNKNOWN }; +// Enter world return values +enum { + ENTER_WORLD_OK = 0, + ENTER_WORLD_NOLOGIN, + ENTER_WORLD_NO_CHARACTER_SELECTED +}; + +// Enter chat return values +enum { + ENTER_CHAT_OK = 0, + ENTER_CHAT_NOLOGIN, + ENTER_CHAT_NO_CHARACTER_SELECTED +}; + +// Game server connect values +enum { + GSRV_CONNECT_OK = 0 +}; + +// Chat server connect values +enum { + CSRV_CONNECT_OK = 0 +}; + // Chat errors return values enum { // CHAT_AROUND = 0, diff --git a/src/gamehandler.cpp b/src/gamehandler.cpp index ff4a0dde..dc14fd2a 100644 --- a/src/gamehandler.cpp +++ b/src/gamehandler.cpp @@ -23,23 +23,184 @@ #include "gamehandler.h" +#include <cassert> #include <iostream> +#include <map> #include "messagein.h" #include "messageout.h" #include "netcomputer.h" #include "packet.h" +#include "state.h" -void GameHandler::receiveMessage(NetComputer &comp, MessageIn &message) +using tmwserv::BeingPtr; + +class GameClient: public NetComputer { - ClientComputer &computer = static_cast< ClientComputer & >(comp); - if (computer.getCharacter().get() == NULL) - return; + public: + /** + * Constructor. + */ + GameClient(GameHandler *, ENetPeer *); + + /** + * Destructor. + */ + ~GameClient(); + + /** + * Set the selected character associated with connection. + */ + void setCharacter(BeingPtr ch); + + /** + * Deselect the character associated with connection. + */ + void unsetCharacter(); + + /** + * Get character associated with the connection. + */ + BeingPtr getCharacter() { return mCharacterPtr; } + + private: + /** Character associated with the conneciton. */ + BeingPtr mCharacterPtr; +}; + +GameClient::GameClient(GameHandler *handler, ENetPeer *peer): + NetComputer(handler, peer), + mCharacterPtr(NULL) +{ +} + +GameClient::~GameClient() +{ + unsetCharacter(); +} + + +void GameClient::setCharacter(tmwserv::BeingPtr ch) +{ + assert(mCharacterPtr.get() == NULL); + tmwserv::State &state = tmwserv::State::instance(); + mCharacterPtr = ch; + state.addBeing(mCharacterPtr, mCharacterPtr->getMapId()); +} + +void GameClient::unsetCharacter() +{ + if (mCharacterPtr.get() == NULL) return; + // remove being from world + tmwserv::State &state = tmwserv::State::instance(); + state.removeBeing(mCharacterPtr); + mCharacterPtr = tmwserv::BeingPtr(NULL); +} + +struct GamePendingLogin +{ + tmwserv::BeingPtr character; + int timeout; +}; + +typedef std::map< std::string, GamePendingLogin > GamePendingLogins; +static GamePendingLogins pendingLogins; + +typedef std::map< std::string, GameClient * > GamePendingClients; +static GamePendingClients pendingClients; + +void registerGameClient(std::string const &token, tmwserv::BeingPtr ch) +{ + GamePendingClients::iterator i = pendingClients.find(token); + if (i != pendingClients.end()) + { + GameClient *computer = i->second; + computer->setCharacter(ch); + pendingClients.erase(i); + MessageOut result; + result.writeShort(SMSG_GAMESRV_CONNECT_RESPONSE); + result.writeByte(GSRV_CONNECT_OK); + computer->send(result.getPacket()); + } + else + { + GamePendingLogin p; + p.character = ch; + p.timeout = 300; // world ticks + pendingLogins.insert(std::make_pair(token, p)); + } +} + +void GameHandler::removeOutdatedPending() +{ + GamePendingLogins::iterator i = pendingLogins.begin(), next; + while (i != pendingLogins.end()) + { + next = i; ++next; + if (--i->second.timeout <= 0) pendingLogins.erase(i); + i = next; + } +} +NetComputer *GameHandler::computerConnected(ENetPeer *peer) +{ + return new GameClient(this, peer); +} + +void GameHandler::computerDisconnected(NetComputer *computer) +{ + for (GamePendingClients::iterator i = pendingClients.begin(), i_end = pendingClients.end(); + i != i_end; ++i) + { + if (i->second == computer) + { + pendingClients.erase(i); + break; + } + } + delete computer; +} + +void GameHandler::process() +{ + ConnectionHandler::process(); + removeOutdatedPending(); +} + +void GameHandler::processMessage(NetComputer *comp, MessageIn &message) +{ + GameClient &computer = *static_cast< GameClient * >(comp); MessageOut result; + if (computer.getCharacter().get() == NULL) { + if (message.getId() != CMSG_GAMESRV_CONNECT) return; + std::string magic_token = message.readString(32); + GamePendingLogins::iterator i = pendingLogins.find(magic_token); + if (i == pendingLogins.end()) + { + for (GamePendingClients::iterator i = pendingClients.begin(), i_end = pendingClients.end(); + i != i_end; ++i) { + if (i->second == &computer) return; + } + pendingClients.insert(std::make_pair(magic_token, &computer)); + return; + } + computer.setCharacter(i->second.character); + pendingLogins.erase(i); + result.writeShort(SMSG_GAMESRV_CONNECT_RESPONSE); + result.writeByte(GSRV_CONNECT_OK); + computer.send(result.getPacket()); + return; + } + switch (message.getId()) { + case CMSG_SAY: + { + std::string say = message.readString(); + sayAround(computer, say); + } break; + case CMSG_PICKUP: { // add item to inventory (this is too simplistic atm) @@ -121,3 +282,36 @@ void GameHandler::receiveMessage(NetComputer &comp, MessageIn &message) if (result.getPacket()->length > 0) computer.send(result.getPacket()); } + +void GameHandler::sayAround(GameClient &computer, std::string const &text) +{ + BeingPtr beingPtr = computer.getCharacter(); + MessageOut msg; + msg.writeShort(SMSG_SAY); + msg.writeString(beingPtr->getName()); + msg.writeString(text); + unsigned speakerMapId = beingPtr->getMapId(); + std::pair<unsigned, unsigned> speakerXY = beingPtr->getXY(); + for (NetComputers::iterator i = clients.begin(), i_end = clients.end(); + i != i_end; ++i) + { + // See if the other being is near enough, then send the message + tmwserv::Being const *listener = static_cast< GameClient * >(*i)->getCharacter().get(); + if (!listener || listener->getMapId() != speakerMapId) continue; + std::pair<unsigned, unsigned> listenerXY = listener->getXY(); + if (abs(listenerXY.first - speakerXY.first ) > (int)AROUND_AREA_IN_TILES) continue; + if (abs(listenerXY.second - speakerXY.second) > (int)AROUND_AREA_IN_TILES) continue; + (*i)->send(msg.getPacket()); + } +} + +void GameHandler::sendTo(BeingPtr beingPtr, MessageOut &msg) +{ + for (NetComputers::iterator i = clients.begin(), i_end = clients.end(); + i != i_end; ++i) { + if (static_cast< GameClient * >(*i)->getCharacter().get() == beingPtr.get()) { + (*i)->send(msg.getPacket()); + break; + } + } +} diff --git a/src/gamehandler.h b/src/gamehandler.h index 4a017705..6a2da6e9 100644 --- a/src/gamehandler.h +++ b/src/gamehandler.h @@ -24,21 +24,50 @@ #ifndef _TMW_SERVER_GAMEHANDLER_ #define _TMW_SERVER_GAMEHANDLER_ -#include "messagehandler.h" +#include "account.h" +#include "being.h" +#include "connectionhandler.h" -class MessageIn; -class NetComputer; +class GameClient; -/** - * Manage main game events & server processing. +/* + * Manage connections to game server. */ -class GameHandler : public MessageHandler +class GameHandler: public ConnectionHandler { - public: - /** - * Recieve messages related to core game events - */ - void receiveMessage(NetComputer &computer, MessageIn &message); + public: + void process(); + + /** + * Send message to the given being. + */ + void sendTo(tmwserv::BeingPtr beingPtr, MessageOut &msg); + + protected: + NetComputer *computerConnected(ENetPeer *); + void computerDisconnected(NetComputer *); + + /** + * Process messages related to core game events. + */ + void processMessage(NetComputer *computer, MessageIn &message); + + private: + /** + * Display a message to every player around one's player + * in the default channel. + * The tile area has been set to 10 for now. + */ + void sayAround(GameClient &computer, std::string const &text); + + void removeOutdatedPending(); }; +/** + * Register future client attempt. Temporary until physical server split. + */ +void registerGameClient(std::string const &, tmwserv::BeingPtr); + +extern GameHandler *gameHandler; + #endif diff --git a/src/main.cpp b/src/main.cpp index 98eb2989..1b609f89 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -99,9 +99,6 @@ ChatChannelManager *chatChannelManager; /** Core game message handler */ GameHandler *gameHandler; -/** Primary connection handler */ -ClientConnectionHandler *connectionHandler; - /** * Initializes the server. */ @@ -164,7 +161,6 @@ void initialize() chatHandler = new ChatHandler(); accountHandler = new AccountHandler(); gameHandler = new GameHandler(); - connectionHandler = new ClientConnectionHandler(); // Reset to default segmentation fault handling for debugging purposes signal(SIGSEGV, SIG_DFL); @@ -242,7 +238,6 @@ void deinitialize() delete accountHandler; delete chatHandler; delete gameHandler; - delete connectionHandler; delete chatChannelManager; @@ -327,37 +322,9 @@ int main(int argc, char *argv[]) // General Initialization initialize(); - // Note: This is just an idea, we could also pass the connection handler - // to the constructor of the account handler, upon which it would register - // itself for the messages it handles. - - // Register message handlers - connectionHandler->registerHandler(CMSG_LOGIN, accountHandler); - connectionHandler->registerHandler(CMSG_LOGOUT, accountHandler); - connectionHandler->registerHandler(CMSG_REGISTER, accountHandler); - connectionHandler->registerHandler(CMSG_UNREGISTER, accountHandler); - connectionHandler->registerHandler(CMSG_CHAR_CREATE, accountHandler); - connectionHandler->registerHandler(CMSG_CHAR_SELECT, accountHandler); - connectionHandler->registerHandler(CMSG_CHAR_DELETE, accountHandler); - connectionHandler->registerHandler(CMSG_CHAR_LIST, accountHandler); - connectionHandler->registerHandler(CMSG_EMAIL_GET, accountHandler); - connectionHandler->registerHandler(CMSG_PASSWORD_CHANGE, accountHandler); - connectionHandler->registerHandler(CMSG_EMAIL_CHANGE, accountHandler); - - connectionHandler->registerHandler(CMSG_SAY, chatHandler); - connectionHandler->registerHandler(CMSG_ANNOUNCE, chatHandler); - - connectionHandler->registerHandler(CMSG_PICKUP, gameHandler); - connectionHandler->registerHandler(CMSG_USE_OBJECT, gameHandler); - connectionHandler->registerHandler(CMSG_USE_ITEM, gameHandler); // NOTE: this is probably redundant (CMSG_USE_OBJECT) - connectionHandler->registerHandler(CMSG_TARGET, gameHandler); - connectionHandler->registerHandler(CMSG_WALK, gameHandler); - connectionHandler->registerHandler(CMSG_START_TRADE, gameHandler); - connectionHandler->registerHandler(CMSG_START_TALK, gameHandler); - connectionHandler->registerHandler(CMSG_REQ_TRADE, gameHandler); - connectionHandler->registerHandler(CMSG_EQUIP, gameHandler); - - if (!connectionHandler->startListen(int(config.getValue("ListenOnPort", DEFAULT_SERVER_PORT)))) { + if (!accountHandler->startListen(int(config.getValue("ListenOnPort", DEFAULT_SERVER_PORT))) || + !chatHandler->startListen(int(config.getValue("ListenOnPort", DEFAULT_SERVER_PORT)) + 1) || + !gameHandler->startListen(int(config.getValue("ListenOnPort", DEFAULT_SERVER_PORT)) + 2)) { LOG_ERROR("Unable to create an ENet server host.", 0); return 3; } @@ -393,16 +360,21 @@ int main(int argc, char *argv[]) LOG_INFO("World time: " << worldTime, 0); } - // - Handle all messages that are in the message queue - // - Update all active objects/beings - connectionHandler->process(); + // Handle all messages that are in the message queues + accountHandler->process(); + chatHandler->process(); + gameHandler->process(); + // Update all active objects/beings state.update(); - connectionHandler->process(); + // Send potentially urgent outgoing messages + gameHandler->flush(); } worldTimer.sleep(); } LOG_INFO("Received: Quit signal, closing down...", 0); - connectionHandler->stopListen(); + gameHandler->stopListen(); + chatHandler->stopListen(); + accountHandler->stopListen(); deinitialize(); } diff --git a/src/messagehandler.cpp b/src/messagehandler.cpp deleted file mode 100644 index 104ef2db..00000000 --- a/src/messagehandler.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * The Mana World Server - * Copyright 2004 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$ - */ - -#include "messagehandler.h" - -#include "utils/logger.h" - -void MessageHandler::receiveMessage(NetComputer &computer, MessageIn &message) { - LOG_WARN("MessageHandler class created without receiveMessage override", 0); -} diff --git a/src/messagehandler.h b/src/messagehandler.h deleted file mode 100644 index 022b6c5d..00000000 --- a/src/messagehandler.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * The Mana World Server - * Copyright 2004 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 _TMWSERV_MESSAGEHANDLER_H_ -#define _TMWSERV_MESSAGEHANDLER_H_ - -class MessageIn; -class NetComputer; - -/** - * This class represents the message handler interface. This interface is - * implemented by classes that mean to handle a certain subset of the incoming - * messages, after instanciation they will have to register at a connection - * handler before they will receive messages. - */ -class MessageHandler -{ - public: - /** - * Destructor. - */ - virtual ~MessageHandler() {}; - - /** - * Called when a message is received with a message ID that corresponds - * to an ID this message handler registered to handle. - */ - virtual void - receiveMessage(NetComputer &computer, MessageIn &message); //= 0; no pure virtual - -}; - -#endif diff --git a/src/netcomputer.cpp b/src/netcomputer.cpp index 7a06ba34..2a8ecc22 100644 --- a/src/netcomputer.cpp +++ b/src/netcomputer.cpp @@ -50,47 +50,3 @@ void NetComputer::send(const Packet *p) // Send the packet to the peer over channel id 0. enet_peer_send(peer, 0, packet); } - -void ClientComputer::setAccount(tmwserv::AccountPtr acc) -{ - mAccountPtr = acc; -} - -void ClientComputer::setCharacter(tmwserv::BeingPtr ch) -{ - tmwserv::State &state = tmwserv::State::instance(); - if (mCharacterPtr.get() != NULL) - { - // Remove being from the world. - unsetCharacter(); - } - mCharacterPtr = ch; - state.addBeing(mCharacterPtr, mCharacterPtr->getMapId()); -} - -void ClientComputer::unsetAccount() -{ - unsetCharacter(); - mAccountPtr = tmwserv::AccountPtr(NULL); -} - -void ClientComputer::unsetCharacter() -{ - // remove being from world - tmwserv::State &state = tmwserv::State::instance(); - state.removeBeing(mCharacterPtr); - chatChannelManager->removeUserFromEveryChannels(mCharacterPtr); - mCharacterPtr = tmwserv::BeingPtr(NULL); -} - -ClientComputer::ClientComputer(ClientConnectionHandler *handler, ENetPeer *peer): - NetComputer(handler, peer), - mAccountPtr(NULL), - mCharacterPtr(NULL) -{ -} - -ClientComputer::~ClientComputer() -{ - unsetAccount(); -} diff --git a/src/netcomputer.h b/src/netcomputer.h index 7aaa78ea..6f68ef2c 100644 --- a/src/netcomputer.h +++ b/src/netcomputer.h @@ -89,65 +89,4 @@ class NetComputer ENetPeer *peer; /**< Client peer */ }; -/** - * Temporary placeholder until the connection handlers have been split. - */ -class ClientComputer: public NetComputer -{ - public: - /** - * Constructor - */ - ClientComputer(ClientConnectionHandler *handler, ENetPeer *peer); - - /** - * Destructor - */ - ~ClientComputer(); - - /** - * Set the account associated with the connection - */ - void - setAccount(tmwserv::AccountPtr acc); - - /** - * Unset the account associated with the connection - */ - void - unsetAccount(); - - /** - * Get account associated with the connection - */ - tmwserv::AccountPtr - getAccount() { return mAccountPtr; } - - /** - * Set the selected character associated with connection - */ - void - setCharacter(tmwserv::BeingPtr ch); - - /** - * Deselect the character associated with connection - * and remove it from the world - */ - void - unsetCharacter(); - - /** - * Get character associated with the connection - */ - tmwserv::BeingPtr - getCharacter() { return mCharacterPtr; } - - private: - /** Account associated with connection */ - tmwserv::AccountPtr mAccountPtr; - - /** Selected character */ - tmwserv::BeingPtr mCharacterPtr; -}; - #endif diff --git a/src/state.cpp b/src/state.cpp index 8f8c3692..e6c2089e 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -23,7 +23,7 @@ #include "state.h" -#include "connectionhandler.h" +#include "gamehandler.h" #include "map.h" #include "mapmanager.h" #include "messageout.h" @@ -78,7 +78,7 @@ void State::update() msg.writeLong(b2->get()->getX());// x msg.writeLong(b2->get()->getY());// y - connectionHandler->sendTo(*b, msg); + gameHandler->sendTo(*b, msg); } } } |