summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog17
-rw-r--r--src/Makefile.am2
-rw-r--r--src/accounthandler.cpp215
-rw-r--r--src/accounthandler.h31
-rw-r--r--src/chatchannel.cpp34
-rw-r--r--src/chatchannel.h10
-rw-r--r--src/chatchannelmanager.cpp157
-rw-r--r--src/chatchannelmanager.h29
-rw-r--r--src/chathandler.cpp304
-rw-r--r--src/chathandler.h104
-rw-r--r--src/client.cpp96
-rw-r--r--src/connectionhandler.cpp153
-rw-r--r--src/connectionhandler.h69
-rw-r--r--src/defines.h46
-rw-r--r--src/gamehandler.cpp202
-rw-r--r--src/gamehandler.h51
-rw-r--r--src/main.cpp54
-rw-r--r--src/messagehandler.cpp30
-rw-r--r--src/messagehandler.h53
-rw-r--r--src/netcomputer.cpp44
-rw-r--r--src/netcomputer.h61
-rw-r--r--src/state.cpp4
22 files changed, 919 insertions, 847 deletions
diff --git a/ChangeLog b/ChangeLog
index f55b8373..79f07fde 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2006-05-20 Guillaume Melquiond <guillaume.melquiond@gmail.com>
+
+ * src/chatchannelmanager.cpp, src/chatchannelmanager.h: Removed
+ unwarranted constness. Used binary searches instead of loops.
+ * src/chatchannel.cpp, src/chatchannel.h: Replaced usage of whole Being
+ by character name.
+ * src/client.cpp: Implemented client-side server split.
+ * src/messagehandler.cpp, src/messagehandler.h, src/Makefile.am:
+ Removed unused MessageHandler class.
+ * src/accounthandler.cpp, src/accounthandler.h, src/chathandler.cpp,
+ src/chathandler.h, src/gamehandler.cpp, src/gamehandler.h: Respectively
+ changed into an account server, a chat server, and a game server.
+ * src/main.cpp, src/state.cpp, src/state.h, src/defines.h: Small fixes
+ to cope with server split.
+ * src/connectionhandler.cpp, src/connectionhandler.h,
+ src/netcomputer.cpp, src/netcomputer.h: Removed temporary classes.
+
2006-05-22 Eugenio Favalli <elvenprogrammer@gmail.com>
* tmwserv.dev: Updated Dev-C++ project file.
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);
}
}
}