diff options
author | Guillaume Melquiond <guillaume.melquiond@gmail.com> | 2006-12-29 13:43:24 +0000 |
---|---|---|
committer | Guillaume Melquiond <guillaume.melquiond@gmail.com> | 2006-12-29 13:43:24 +0000 |
commit | 291ad04d5b5c4ab08d85eadde116f968cd579b77 (patch) | |
tree | e4dced5715a5d9792cfdc0455a6b3ee6d3116079 /src | |
parent | 3d404e743105bb9168c89e3451cf35d7d59120b1 (diff) | |
download | manaserv-291ad04d5b5c4ab08d85eadde116f968cd579b77.tar.gz manaserv-291ad04d5b5c4ab08d85eadde116f968cd579b77.tar.bz2 manaserv-291ad04d5b5c4ab08d85eadde116f968cd579b77.tar.xz manaserv-291ad04d5b5c4ab08d85eadde116f968cd579b77.zip |
Physically split the server into one tmwserv-acount program (account +
chat + database) and multiple tmwserv-game programs (selected with
respect to the maps). Cleaned the repository by moving server-specific
source files into dedicated directories.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 261 | ||||
-rw-r--r-- | src/account-server/account.cpp (renamed from src/account.cpp) | 3 | ||||
-rw-r--r-- | src/account-server/account.hpp (renamed from src/account.h) | 0 | ||||
-rw-r--r-- | src/account-server/accountclient.cpp (renamed from src/accountclient.cpp) | 7 | ||||
-rw-r--r-- | src/account-server/accountclient.hpp (renamed from src/accountclient.h) | 6 | ||||
-rw-r--r-- | src/account-server/accounthandler.cpp (renamed from src/accounthandler.cpp) | 50 | ||||
-rw-r--r-- | src/account-server/accounthandler.hpp (renamed from src/accounthandler.h) | 2 | ||||
-rw-r--r-- | src/account-server/dalstorage.cpp (renamed from src/dalstorage.cpp) | 42 | ||||
-rw-r--r-- | src/account-server/dalstorage.hpp (renamed from src/dalstorage.h) | 9 | ||||
-rw-r--r-- | src/account-server/dalstoragesql.hpp (renamed from src/dalstoragesql.h) | 21 | ||||
-rw-r--r-- | src/account-server/main-account.cpp | 327 | ||||
-rw-r--r-- | src/account-server/serverhandler.cpp | 115 | ||||
-rw-r--r-- | src/account-server/serverhandler.hpp | 90 | ||||
-rw-r--r-- | src/account-server/storage.cpp (renamed from src/storage.cpp) | 5 | ||||
-rw-r--r-- | src/account-server/storage.hpp (renamed from src/storage.h) | 14 | ||||
-rw-r--r-- | src/being.cpp | 93 | ||||
-rw-r--r-- | src/being.h | 29 | ||||
-rw-r--r-- | src/chat-server/chatchannel.cpp (renamed from src/chatchannel.cpp) | 2 | ||||
-rw-r--r-- | src/chat-server/chatchannel.hpp (renamed from src/chatchannel.h) | 2 | ||||
-rw-r--r-- | src/chat-server/chatchannelmanager.cpp (renamed from src/chatchannelmanager.cpp) | 5 | ||||
-rw-r--r-- | src/chat-server/chatchannelmanager.hpp (renamed from src/chatchannelmanager.h) | 2 | ||||
-rw-r--r-- | src/chat-server/chathandler.cpp (renamed from src/chathandler.cpp) | 16 | ||||
-rw-r--r-- | src/chat-server/chathandler.hpp (renamed from src/chathandler.h) | 2 | ||||
-rw-r--r-- | src/client.cpp | 4 | ||||
-rw-r--r-- | src/configuration.h | 3 | ||||
-rw-r--r-- | src/controller.cpp | 42 | ||||
-rw-r--r-- | src/controller.h | 16 | ||||
-rw-r--r-- | src/defines.h | 9 | ||||
-rw-r--r-- | src/game-server/accountconnection.cpp | 85 | ||||
-rw-r--r-- | src/game-server/accountconnection.hpp | 50 | ||||
-rw-r--r-- | src/game-server/gameclient.cpp (renamed from src/gameclient.cpp) | 7 | ||||
-rw-r--r-- | src/game-server/gameclient.hpp (renamed from src/gameclient.h) | 5 | ||||
-rw-r--r-- | src/game-server/gamehandler.cpp (renamed from src/gamehandler.cpp) | 30 | ||||
-rw-r--r-- | src/game-server/gamehandler.hpp (renamed from src/gamehandler.h) | 8 | ||||
-rw-r--r-- | src/game-server/itemmanager.cpp | 155 | ||||
-rw-r--r-- | src/game-server/itemmanager.hpp (renamed from src/itemmanager.h) | 11 | ||||
-rw-r--r-- | src/game-server/main-game.cpp (renamed from src/main.cpp) | 95 | ||||
-rw-r--r-- | src/game-server/mapmanager.cpp | 112 | ||||
-rw-r--r-- | src/game-server/mapmanager.hpp (renamed from src/mapmanager.h) | 48 | ||||
-rw-r--r-- | src/game-server/state.cpp (renamed from src/state.cpp) | 44 | ||||
-rw-r--r-- | src/game-server/state.hpp (renamed from src/state.h) | 0 | ||||
-rw-r--r-- | src/inventory.cpp | 9 | ||||
-rw-r--r-- | src/inventory.h | 24 | ||||
-rw-r--r-- | src/item.cpp | 2 | ||||
-rw-r--r-- | src/item.h | 6 | ||||
-rw-r--r-- | src/itemhandler.cpp | 2 | ||||
-rw-r--r-- | src/itemhandler.h | 2 | ||||
-rw-r--r-- | src/itemmanager.cpp | 205 | ||||
-rw-r--r-- | src/mapcomposite.cpp | 2 | ||||
-rw-r--r-- | src/mapcomposite.h | 4 | ||||
-rw-r--r-- | src/mapmanager.cpp | 99 | ||||
-rw-r--r-- | src/net/connection.cpp | 110 | ||||
-rw-r--r-- | src/net/connection.hpp | 80 | ||||
-rw-r--r-- | src/net/connectionhandler.cpp (renamed from src/connectionhandler.cpp) | 24 | ||||
-rw-r--r-- | src/net/connectionhandler.hpp (renamed from src/connectionhandler.h) | 17 | ||||
-rw-r--r-- | src/net/messagein.cpp (renamed from src/messagein.cpp) | 5 | ||||
-rw-r--r-- | src/net/messagein.hpp (renamed from src/messagein.h) | 5 | ||||
-rw-r--r-- | src/net/messageout.cpp (renamed from src/messageout.cpp) | 9 | ||||
-rw-r--r-- | src/net/messageout.hpp (renamed from src/messageout.h) | 0 | ||||
-rw-r--r-- | src/net/netcomputer.cpp (renamed from src/netcomputer.cpp) | 7 | ||||
-rw-r--r-- | src/net/netcomputer.hpp (renamed from src/netcomputer.h) | 15 | ||||
-rw-r--r-- | src/object.cpp | 31 | ||||
-rw-r--r-- | src/object.h | 15 | ||||
-rw-r--r-- | src/player.cpp | 93 | ||||
-rw-r--r-- | src/player.h | 15 | ||||
-rw-r--r-- | src/utils/xml.cpp | 53 | ||||
-rw-r--r-- | src/utils/xml.hpp | 43 |
67 files changed, 1715 insertions, 989 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index fbd3bd8b..13eb6797 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,126 +2,183 @@ AUTOMAKE_OPTIONS = subdir-objects -bin_PROGRAMS = tmwclient tmwserv +bin_PROGRAMS = tmwclient tmwserv-account tmwserv-game -tmwclient_SOURCES = client.cpp \ - defines.h \ - messageout.h \ - messageout.cpp \ - messagein.h \ - messagein.cpp +tmwclient_SOURCES = \ + client.cpp \ + defines.h \ + net/messagein.hpp \ + net/messagein.cpp \ + net/messageout.hpp \ + net/messageout.cpp -tmwserv_SOURCES = main.cpp \ - being.h \ - being.cpp \ - account.h \ - account.cpp \ - accountclient.h \ - accountclient.cpp \ - accounthandler.h \ - accounthandler.cpp \ - chathandler.h \ - chathandler.cpp \ - chatchannel.h \ - chatchannel.cpp \ - chatchannelmanager.h \ - chatchannelmanager.cpp \ - configuration.h \ - configuration.cpp \ - connectionhandler.h \ - connectionhandler.cpp \ - controller.h \ - controller.cpp \ - debug.h \ - debug.cpp \ - defines.h \ - gameclient.h \ - gameclient.cpp \ - gamehandler.h \ - gamehandler.cpp \ - inventory.h \ - inventory.cpp \ - item.h \ - item.cpp \ - itemmanager.h \ - itemmanager.cpp \ - map.h \ - map.cpp \ - mapcomposite.h \ - mapcomposite.cpp \ - mapmanager.h \ - mapmanager.cpp \ - mapreader.cpp \ - mapreader.h \ - messagein.h \ - messagein.cpp \ - messageout.h \ - messageout.cpp \ - netcomputer.h \ - netcomputer.cpp \ - object.h \ - object.cpp \ - player.h \ - player.cpp \ - point.h \ - properties.h \ - resourcemanager.cpp \ - resourcemanager.h \ - skill.h \ - skill.cpp \ - state.h \ - state.cpp \ - storage.h \ - storage.cpp \ - dalstorage.h \ - dalstorage.cpp \ - dal/dalexcept.h \ - dal/dataprovider.h \ - dal/dataprovider.cpp \ - dal/dataproviderfactory.h \ - dal/dataproviderfactory.cpp \ - dal/recordset.h \ - dal/recordset.cpp \ - utils/base64.h \ - utils/base64.cpp \ - utils/countedptr.h \ - utils/functors.h \ - utils/singleton.h \ - utils/cipher.h \ - utils/cipher.cpp \ - utils/logger.h \ - utils/logger.cpp \ - utils/stringfilter.h \ - utils/stringfilter.cpp \ - utils/timer.h \ - utils/timer.cpp +tmwserv_account_SOURCES = \ + account-server/main-account.cpp \ + being.h \ + configuration.h \ + configuration.cpp \ + debug.h \ + debug.cpp \ + defines.h \ + inventory.h \ + item.h \ + object.h \ + player.h \ + player.cpp \ + point.h \ + properties.h \ + resourcemanager.h \ + resourcemanager.cpp \ + skill.h \ + skill.cpp \ + account-server/account.hpp \ + account-server/account.cpp \ + account-server/accountclient.hpp \ + account-server/accountclient.cpp \ + account-server/accounthandler.hpp \ + account-server/accounthandler.cpp \ + account-server/dalstorage.hpp \ + account-server/dalstorage.cpp \ + account-server/dalstoragesql.hpp \ + account-server/serverhandler.hpp \ + account-server/serverhandler.cpp \ + account-server/storage.hpp \ + account-server/storage.cpp \ + chat-server/chathandler.hpp \ + chat-server/chathandler.cpp \ + chat-server/chatchannel.hpp \ + chat-server/chatchannel.cpp \ + chat-server/chatchannelmanager.hpp \ + chat-server/chatchannelmanager.cpp \ + dal/dalexcept.h \ + dal/dataprovider.h \ + dal/dataprovider.cpp \ + dal/dataproviderfactory.h \ + dal/dataproviderfactory.cpp \ + dal/recordset.h \ + dal/recordset.cpp \ + net/connectionhandler.hpp \ + net/connectionhandler.cpp \ + net/messagein.hpp \ + net/messagein.cpp \ + net/messageout.hpp \ + net/messageout.cpp \ + net/netcomputer.hpp \ + net/netcomputer.cpp \ + utils/base64.h \ + utils/base64.cpp \ + utils/countedptr.h \ + utils/functors.h \ + utils/singleton.h \ + utils/cipher.h \ + utils/cipher.cpp \ + utils/logger.h \ + utils/logger.cpp \ + utils/stringfilter.h \ + utils/stringfilter.cpp \ + utils/timer.h \ + utils/timer.cpp + +tmwserv_game_SOURCES = \ + game-server/main-game.cpp \ + being.h \ + being.cpp \ + configuration.h \ + configuration.cpp \ + controller.h \ + controller.cpp \ + debug.h \ + debug.cpp \ + defines.h \ + inventory.h \ + inventory.cpp \ + item.h \ + item.cpp \ + map.h \ + map.cpp \ + mapcomposite.h \ + mapcomposite.cpp \ + mapreader.h \ + mapreader.cpp \ + object.h \ + object.cpp \ + player.h \ + player.cpp \ + point.h \ + properties.h \ + resourcemanager.h \ + resourcemanager.cpp \ + skill.h \ + skill.cpp \ + game-server/accountconnection.hpp \ + game-server/accountconnection.cpp \ + game-server/gameclient.hpp \ + game-server/gameclient.cpp \ + game-server/gamehandler.hpp \ + game-server/gamehandler.cpp \ + game-server/itemmanager.hpp \ + game-server/itemmanager.cpp \ + game-server/mapmanager.hpp \ + game-server/mapmanager.cpp \ + game-server/state.hpp \ + game-server/state.cpp \ + net/connection.hpp \ + net/connection.cpp \ + net/connectionhandler.hpp \ + net/connectionhandler.cpp \ + net/messagein.hpp \ + net/messagein.cpp \ + net/messageout.hpp \ + net/messageout.cpp \ + net/netcomputer.hpp \ + net/netcomputer.cpp \ + utils/base64.h \ + utils/base64.cpp \ + utils/countedptr.h \ + utils/functors.h \ + utils/singleton.h \ + utils/cipher.h \ + utils/cipher.cpp \ + utils/logger.h \ + utils/logger.cpp \ + utils/stringfilter.h \ + utils/stringfilter.cpp \ + utils/timer.h \ + utils/timer.cpp \ + utils/xml.h \ + utils/xml.cpp if BUILD_MYSQL -tmwserv_SOURCES += dal/mysqldataprovider.h \ - dal/mysqldataprovider.cpp +tmwserv_account_SOURCES += \ + dal/mysqldataprovider.h \ + dal/mysqldataprovider.cpp endif if BUILD_POSTGRESQL -tmwserv_SOURCES += dal/pqdataprovider.h \ - dal/pqdataprovider.cpp +tmwserv_account_SOURCES += \ + dal/pqdataprovider.h \ + dal/pqdataprovider.cpp endif if BUILD_SQLITE -tmwserv_SOURCES += dal/sqlitedataprovider.h \ - dal/sqlitedataprovider.cpp +tmwserv_account_SOURCES += \ + dal/sqlitedataprovider.h \ + dal/sqlitedataprovider.cpp endif if BUILD_SQUIRREL -tmwserv_SOURCES += script.h \ - script.cpp \ - script-squirrel.h \ - script-squirrel.cpp +tmwserv_game_SOURCES += \ + script.h \ + script.cpp \ + script-squirrel.h \ + script-squirrel.cpp endif if BUILD_RUBY -tmwserv_SOURCES += bindings_wrap.cpp bindings_wrap.cpp: bindings.i $(SWIG) $(SWIGFLAGS) -o bindings_wrap.cpp bindings.i +tmwserv_game_SOURCES += \ + bindings_wrap.cpp endif diff --git a/src/account.cpp b/src/account-server/account.cpp index 2caf1af5..c827a92d 100644 --- a/src/account.cpp +++ b/src/account-server/account.cpp @@ -22,8 +22,7 @@ #include <cassert> -#include "account.h" - +#include "account-server/account.hpp" #include "utils/functors.h" /** diff --git a/src/account.h b/src/account-server/account.hpp index e9d9e408..e9d9e408 100644 --- a/src/account.h +++ b/src/account-server/account.hpp diff --git a/src/accountclient.cpp b/src/account-server/accountclient.cpp index 5cdbba29..79d3cf0c 100644 --- a/src/accountclient.cpp +++ b/src/account-server/accountclient.cpp @@ -21,10 +21,9 @@ * $Id$ */ -#include "accountclient.h" - -#include "account.h" -#include "accounthandler.h" +#include "account-server/account.hpp" +#include "account-server/accountclient.hpp" +#include "account-server/accounthandler.hpp" AccountClient::AccountClient(ENetPeer *peer): NetComputer(peer), diff --git a/src/accountclient.h b/src/account-server/accountclient.hpp index c3ab8a44..8d42e0e4 100644 --- a/src/accountclient.h +++ b/src/account-server/accountclient.hpp @@ -24,11 +24,11 @@ #ifndef _TMWSERV_ACCOUNTCLIENT_H_ #define _TMWSERV_ACCOUNTCLIENT_H_ -#include "netcomputer.h" -#include "account.h" - #include <enet/enet.h> +#include "account-server/account.hpp" +#include "net/netcomputer.hpp" + class AccountHandler; /** diff --git a/src/accounthandler.cpp b/src/account-server/accounthandler.cpp index 2e2e4a29..72a23818 100644 --- a/src/accounthandler.cpp +++ b/src/account-server/accounthandler.cpp @@ -21,21 +21,19 @@ * $Id$ */ -#include "accounthandler.h" - -#include "account.h" -#include "accountclient.h" -#include "chathandler.h" #include "configuration.h" -#include "connectionhandler.h" #include "debug.h" -#include "gamehandler.h" -#include "messagein.h" -#include "messageout.h" -#include "netcomputer.h" #include "point.h" -#include "storage.h" - +#include "account-server/accounthandler.hpp" +#include "account-server/account.hpp" +#include "account-server/accountclient.hpp" +#include "account-server/serverhandler.hpp" +#include "account-server/storage.hpp" +#include "chat-server/chathandler.hpp" +#include "net/connectionhandler.hpp" +#include "net/messagein.hpp" +#include "net/messageout.hpp" +#include "net/netcomputer.hpp" #include "utils/logger.h" #include "utils/stringfilter.h" @@ -43,7 +41,7 @@ bool AccountHandler::startListen(enet_uint16 port) { LOG_INFO("Account handler started:", 0); - ConnectionHandler::startListen(port); + return ConnectionHandler::startListen(port); } NetComputer* @@ -178,7 +176,16 @@ AccountHandler::processMessage(NetComputer *comp, MessageIn &message) if (charNum >= chars.size()) { // invalid char selection result.writeByte(ERRMSG_INVALID_ARGUMENT); - LOG_INFO("Character Selection : Selection out of ID range.", 1); + LOG_INFO("Character Selection: Selection out of ID range.", 1); + break; + } + + std::string address; + short port; + if (!serverHandler->getGameServerFromMap(chars[charNum]->getMapId(), address, port)) + { + result.writeByte(ERRMSG_FAILURE); + LOG_ERROR("Character Selection: No game server for the map.", 0); break; } @@ -199,14 +206,13 @@ AccountHandler::processMessage(NetComputer *comp, MessageIn &message) 1 + (int) (127 * (rand() / (RAND_MAX + 1.0))); } result.writeString(magic_token, 32); - result.writeString(config.getValue("clientGameServerAddress", - "localhost")); - result.writeShort(9603); - result.writeString(config.getValue("clientChatServerAddress", - "localhost")); - result.writeShort(9602); - - registerGameClient(magic_token, selectedChar); + result.writeString(address); + result.writeShort(port); + // TODO: get correct address and port for the chat server + result.writeString(config.getValue("accountServerAddress", "localhost")); + result.writeShort(int(config.getValue("accountServerPort", DEFAULT_SERVER_PORT)) + 2); + + serverHandler->registerGameClient(magic_token, selectedChar); registerChatClient(magic_token, selectedChar->getName(), AL_NORMAL); } diff --git a/src/accounthandler.h b/src/account-server/accounthandler.hpp index 5a1a38db..2d75fbf5 100644 --- a/src/accounthandler.h +++ b/src/account-server/accounthandler.hpp @@ -24,7 +24,7 @@ #ifndef _TMWSERV_ACCOUNTHANDLER_H_ #define _TMWSERV_ACCOUNTHANDLER_H_ -#include "connectionhandler.h" +#include "net/connectionhandler.hpp" class AccountClient; diff --git a/src/dalstorage.cpp b/src/account-server/dalstorage.cpp index 44e702ef..95d6c019 100644 --- a/src/dalstorage.cpp +++ b/src/account-server/dalstorage.cpp @@ -22,15 +22,12 @@ #include <cassert> -#include "dalstorage.h" - #include "configuration.h" -#include "dalstoragesql.h" #include "point.h" - +#include "account-server/dalstorage.hpp" +#include "account-server/dalstoragesql.hpp" #include "dal/dalexcept.h" #include "dal/dataproviderfactory.h" - #include "utils/cipher.h" #include "utils/functors.h" #include "utils/logger.h" @@ -146,7 +143,6 @@ DALStorage::open(void) // a DbSqlQueryExecFailure assert on sqlite while registering. // Also, this would initialize connection to the database earlier in memory. - createTable(MAPS_TBL_NAME, SQL_MAPS_TABLE); createTable(ACCOUNTS_TBL_NAME, SQL_ACCOUNTS_TABLE); createTable(CHARACTERS_TBL_NAME, SQL_CHARACTERS_TABLE); createTable(ITEMS_TBL_NAME, SQL_ITEMS_TABLE); @@ -384,40 +380,6 @@ bool DALStorage::doesCharacterNameExist(const std::string& name) return true; } -/** - * Tells the map name from the map id - */ -const std::string -DALStorage::getMapNameFromId(const unsigned int mapId) -{ - std::string name = "None"; - - // If not opened already - open(); - - try { - std::stringstream sql; - sql << "select map from "; - sql << MAPS_TBL_NAME; - sql << " where id = "; - sql << mapId; - sql << ";"; - - const dal::RecordSet &mapInfo = mDb->execSql(sql.str()); - - // If the map return is empty then we have no choice but to return None. - if (!mapInfo.isEmpty()) { - name = mapInfo(0, 0); - } - } - catch (const dal::DbSqlQueryExecFailure& e) { - // TODO: throw an exception. - LOG_ERROR("SQL query failure: " << e.what(), 0); - } - - return name; -} - std::map<short, ChatChannel> DALStorage::getChannelList() { diff --git a/src/dalstorage.h b/src/account-server/dalstorage.hpp index b5e7c03b..22c6c6e8 100644 --- a/src/dalstorage.h +++ b/src/account-server/dalstorage.hpp @@ -24,8 +24,7 @@ #ifndef _TMWSERV_DALSTORAGE_H_ #define _TMWSERV_DALSTORAGE_H_ -#include "storage.h" - +#include "account-server/storage.hpp" #include "dal/dataprovider.h" /** @@ -110,12 +109,6 @@ class DALStorage: public Storage bool doesCharacterNameExist(std::string const &name); /** - * Tells the map name from the map id - */ - const std::string - getMapNameFromId(const unsigned int mapId); - - /** * Gives the list of opened public channels registered in database * @return a map of the public channels */ diff --git a/src/dalstoragesql.h b/src/account-server/dalstoragesql.hpp index 582b21fe..391b5572 100644 --- a/src/dalstoragesql.h +++ b/src/account-server/dalstoragesql.hpp @@ -64,27 +64,6 @@ namespace { /** - * TABLE: tmw_maps. - */ -const std::string MAPS_TBL_NAME("tmw_maps"); -const std::string SQL_MAPS_TABLE( - "CREATE TABLE tmw_maps (" -#if defined (MYSQL_SUPPORT) - "id TINYINT PRIMARY KEY AUTO_INCREMENT," - "map TEXT NOT NULL," - "INDEX (id)" -#elif defined (SQLITE_SUPPORT) - "id INTEGER PRIMARY KEY," - "map TEXT NOT NULL" -#elif defined (POSTGRESQL_SUPPORT) - "id SERIAL PRIMARY KEY," - "map TEXT NOT NULL" -#endif - ");" -); - - -/** * TABLE: tmw_accounts. * * Notes: diff --git a/src/account-server/main-account.cpp b/src/account-server/main-account.cpp new file mode 100644 index 00000000..f462ff08 --- /dev/null +++ b/src/account-server/main-account.cpp @@ -0,0 +1,327 @@ +/* + * 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 <cstdlib> +#include <getopt.h> +#include <signal.h> +#include <iostream> +#include <physfs.h> +#include <enet/enet.h> + +#if (defined __USE_UNIX98 || defined __FreeBSD__) +#include "../config.h" +#elif defined WIN32 +#include "../tmwserv_private.h" +#define PACKAGE_VERSION PRODUCT_VERSION +#endif + +#include "configuration.h" +#include "resourcemanager.h" +#include "skill.h" +#include "account-server/accounthandler.hpp" +#include "account-server/serverhandler.hpp" +#include "account-server/storage.hpp" +#include "chat-server/chatchannelmanager.hpp" +#include "chat-server/chathandler.hpp" +#include "net/connectionhandler.hpp" +#include "net/messageout.hpp" +#include "utils/logger.h" +#include "utils/stringfilter.h" +#include "utils/timer.h" + +// Default options that automake should be able to override. +#define DEFAULT_LOG_FILE "tmwserv.log" +#define DEFAULT_CONFIG_FILE "tmwserv.xml" +#define DEFAULT_ITEMSDB_FILE "items.xml" + +utils::Timer worldTimer(100, false); /**< Timer for world tics set to 100 ms */ +int worldTime = 0; /**< Current world time in 100ms ticks */ +bool running = true; /**< Determines if server keeps running */ + +Skill skillTree("base"); /**< Skill tree */ + +Configuration config; /**< XML config reader */ + +utils::StringFilter *stringFilter; /**< Slang's Filter */ + +/** Account message handler */ +AccountHandler *accountHandler; + +/** Communications (chat) message handler */ +ChatHandler *chatHandler; + +/** Server message handler */ +ServerHandler *serverHandler; + +/** Chat Channels Manager */ +ChatChannelManager *chatChannelManager; + +/** + * Initializes the server. + */ +void initialize() +{ + + // Reset to default segmentation fault handling for debugging purposes + signal(SIGSEGV, SIG_DFL); + + // Set enet to quit on exit. + atexit(enet_deinitialize); + + /* + * If the path values aren't defined, we set the default + * depending on the platform. + */ + // The config path +#if defined CONFIG_FILE + std::string configPath = CONFIG_FILE; +#else + +#if (defined __USE_UNIX98 || defined __FreeBSD__) + std::string configPath = getenv("HOME"); + configPath += "/."; + configPath += DEFAULT_CONFIG_FILE; +#else // Win32, ... + std::string configPath = DEFAULT_CONFIG_FILE; +#endif + +#endif // defined CONFIG_FILE + + // The log path +#if defined LOG_FILE + std::string logPath = LOG_FILE; +#else + +#if (defined __USE_UNIX98 || defined __FreeBSD__) + std::string logPath = getenv("HOME"); + logPath += "/."; + logPath += DEFAULT_LOG_FILE; +#else // Win32, ... + std::string logPath = DEFAULT_LOG_FILE; +#endif + +#endif // defined LOG_FILE + + // Initialize PhysicsFS + PHYSFS_init(""); + + // Initialize the logger. + using namespace utils; + Logger::instance().setLogFile(logPath); + + // write the messages to both the screen and the log file. + Logger::instance().setTeeMode(true); + + config.init(configPath); + LOG_INFO("Using Config File: " << configPath, 0); + LOG_INFO("Using Log File: " << logPath, 0); + + // --- Initialize the managers + // Initialize the slang's and double quotes filter. + stringFilter = new StringFilter(&config); + // Initialize the Chat channels manager + chatChannelManager = new ChatChannelManager(); + + // --- Initialize the global handlers + // FIXME: Make the global handlers global vars or part of a bigger + // singleton or a local variable in the event-loop + accountHandler = new AccountHandler(); + chatHandler = new ChatHandler(); + serverHandler = new ServerHandler(); + + // --- Initialize enet. + if (enet_initialize() != 0) { + LOG_FATAL("An error occurred while initializing ENet", 0); + exit(2); + } + + +#if defined (MYSQL_SUPPORT) + LOG_INFO("Using MySQL DB Backend.", 0); +#elif defined (POSTGRESQL_SUPPORT) + LOG_INFO("Using PostGreSQL DB Backend.", 0); +#elif defined (SQLITE_SUPPORT) + LOG_INFO("Using SQLite DB Backend.", 0); +#else + LOG_WARN("No Database Backend Support.", 0); +#endif + + // Initialize configuration defaults + config.setValue("dbuser", ""); + config.setValue("dbpass", ""); + config.setValue("dbhost", ""); +} + + +/** + * Deinitializes the server. + */ +void deinitialize() +{ + delete stringFilter; + // Write configuration file + config.write(); + + // Stop world timer + worldTimer.stop(); + + // Quit ENet + enet_deinitialize(); + + // Destroy message handlers + delete serverHandler; + delete chatHandler; + delete accountHandler; + + // Destroy Managers + delete chatChannelManager; + + // Get rid of persistent data storage + Storage::destroy(); + + PHYSFS_deinit(); +} + + +/** + * Show command line arguments + */ +void printHelp() +{ + std::cout << "tmwserv" << std::endl << std::endl + << "Options: " << std::endl + << " -h --help : Display this help" << std::endl + << " --verbosity <n> : Set the verbosity level" << std::endl + << " --port <n> : Set the default port to listen on" << std::endl; + exit(0); +} + +/** + * Parse the command line arguments + */ +void parseOptions(int argc, char *argv[]) +{ + const char *optstring = "h"; + + const struct option long_options[] = { + { "help", no_argument, 0, 'h' }, + { "verbosity", required_argument, 0, 'v' }, + { "port", required_argument, 0, 'p' }, + { 0 } + }; + + while (optind < argc) { + int result = getopt_long(argc, argv, optstring, long_options, NULL); + + if (result == -1) { + break; + } + + switch (result) { + default: // Unknown option + case 'h': + // Print help + printHelp(); + break; + case 'v': + // Set Verbosity to level + unsigned short verbosityLevel; + verbosityLevel = atoi(optarg); + utils::Logger::instance().setVerbosity(verbosityLevel); + LOG_INFO("Setting Log Verbosity Level to " << verbosityLevel, 0); + break; + case 'p': + // Change the port to listen on. + unsigned short portToListenOn; + portToListenOn = atoi(optarg); + config.setValue("ListenOnPort", portToListenOn); + LOG_INFO("Setting Default Port to " << portToListenOn, 0); + break; + } + } +} + + +/** + * Main function, initializes and runs server. + */ +int main(int argc, char *argv[]) +{ + int elapsedWorldTicks; + + LOG_INFO("The Mana World Server v" << PACKAGE_VERSION, 0); + + // Parse Command Line Options + parseOptions(argc, argv); + + // General Initialization + initialize(); + + int port = int(config.getValue("accountServerPort", DEFAULT_SERVER_PORT)); + if (!accountHandler->startListen(port) || + !serverHandler->startListen(port + 1) || + !chatHandler->startListen(port + 2)) { + LOG_ERROR("Unable to create an ENet server host.", 0); + return 3; + } + + // Create storage wrapper + Storage& store = Storage::instance("tmw"); + store.setUser(config.getValue("dbuser", "")); + store.setPassword(config.getValue("dbpass", "")); + store.close(); + store.open(); + + // Initialize world timer + worldTimer.start(); + + while (running) { + elapsedWorldTicks = worldTimer.poll(); + if (elapsedWorldTicks > 0) { + worldTime += elapsedWorldTicks; + + if (elapsedWorldTicks > 1) + { + LOG_WARN(elapsedWorldTicks -1 << " World Tick(s) skipped " + "because of insufficient time. please buy a faster " + "machine ;-)", 0); + }; + + // Print world time at 10 second intervals to show we're alive + if (worldTime % 100 == 0) { + LOG_INFO("World time: " << worldTime, 0); + } + + // Handle all messages that are in the message queues + accountHandler->process(); + chatHandler->process(); + serverHandler->process(); + } + worldTimer.sleep(); + } + + LOG_INFO("Received: Quit signal, closing down...", 0); + serverHandler->stopListen(); + chatHandler->stopListen(); + accountHandler->stopListen(); + deinitialize(); +} diff --git a/src/account-server/serverhandler.cpp b/src/account-server/serverhandler.cpp new file mode 100644 index 00000000..5300a066 --- /dev/null +++ b/src/account-server/serverhandler.cpp @@ -0,0 +1,115 @@ +/* + * 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 <cassert> +#include <sstream> + +#include "account-server/serverhandler.hpp" +#include "net/messagein.hpp" +#include "net/messageout.hpp" +#include "net/netcomputer.hpp" +#include "utils/logger.h" + +bool ServerHandler::startListen(enet_uint16 port) +{ + LOG_INFO("Server handler started:", 0); + return ConnectionHandler::startListen(port); +} + +NetComputer *ServerHandler::computerConnected(ENetPeer *peer) +{ + return new NetComputer(peer); +} + +void ServerHandler::computerDisconnected(NetComputer *comp) +{ + delete comp; +} + +bool ServerHandler::getGameServerFromMap(unsigned mapId, std::string &address, short &port) +{ + Servers::const_iterator i = servers.find(mapId); + if (i == servers.end()) return false; + address = i->second.address; + port = i->second.port; + return true; +} + +void ServerHandler::registerGameClient(std::string const &token, PlayerPtr ptr) +{ + unsigned mapId = ptr->getMapId(); + MessageOut msg(AGMSG_PLAYER_ENTER); + msg.writeLong(ptr->getDatabaseID()); + msg.writeString(ptr->getName()); + msg.writeByte(ptr->getGender()); + msg.writeByte(ptr->getHairStyle()); + msg.writeByte(ptr->getHairColor()); + msg.writeByte(ptr->getLevel()); + msg.writeShort(ptr->getMoney()); + for (int j = 0; j < NB_RSTAT; ++j) + msg.writeShort(ptr->getRawStat(j)); + Point pos = ptr->getPosition(); + msg.writeShort(pos.x); + msg.writeShort(pos.y); + msg.writeShort(mapId); + msg.writeString(token, 32); + Servers::const_iterator i = servers.find(mapId); + assert(i != servers.end()); + i->second.server->send(msg); +} + +void ServerHandler::processMessage(NetComputer *comp, MessageIn &msg) +{ + MessageOut result; + + switch (msg.getId()) + { + case GAMSG_REGISTER: + { + // TODO: check the credentials of the game server + std::string address = msg.readString(); + int port = msg.readShort(); + Server s = { address, port, comp }; + LOG_INFO("Game server " << address << ':' << port + << " wants to register " << (msg.getUnreadLength() / 2) + << " maps.", 0); + while (msg.getUnreadLength()) + { + unsigned id = msg.readShort(); + if (!servers.insert(std::make_pair(id, s)).second) + { + LOG_ERROR("Server Handler: map is already registered.", 0); + } + } + } break; + + default: + LOG_WARN("Invalid message type.", 0); + result.writeShort(XXMSG_INVALID); + break; + } + + // return result + if (result.getLength() > 0) + comp->send(result); +} diff --git a/src/account-server/serverhandler.hpp b/src/account-server/serverhandler.hpp new file mode 100644 index 00000000..797e0a48 --- /dev/null +++ b/src/account-server/serverhandler.hpp @@ -0,0 +1,90 @@ +/* + * The Mana World Server + * Copyright 2006 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_SERVERHANDLER_H_ +#define _TMWSERV_SERVERHANDLER_H_ + +#include <map> + +#include "player.h" +#include "net/connectionhandler.hpp" + +/** + * Manages communications with all the game servers. This class also keeps + * track of the maps each game server supports. + */ +class ServerHandler: public ConnectionHandler +{ + public: + /** + * Starts the handler on the given port. + */ + bool startListen(enet_uint16 port); + + /** + * Returns the information a client needs to connect to the game server + * corresponding to the given map ID. + */ + bool getGameServerFromMap(unsigned, std::string &address, short &port); + + /** + * Sends a magic token and player data to the relevant game server. + */ + void registerGameClient(std::string const &, PlayerPtr); + + protected: + /** + * Processes server messages. + */ + void processMessage(NetComputer *computer, MessageIn &message); + + /** + * Called when a game server connects. Initializes a simple NetComputer + * as these connections are stateless. + */ + NetComputer *computerConnected(ENetPeer *peer); + + /** + * Called when a game server disconnects. + */ + void computerDisconnected(NetComputer *comp); + + private: + struct Server + { + std::string address; + short port; + NetComputer *server; + }; + + typedef std::map< unsigned, Server > Servers; + + /** + * Maps map IDs to game server data. + */ + Servers servers; +}; + +extern ServerHandler *serverHandler; + +#endif diff --git a/src/storage.cpp b/src/account-server/storage.cpp index ed31bad4..a02ec010 100644 --- a/src/storage.cpp +++ b/src/account-server/storage.cpp @@ -20,9 +20,8 @@ * $Id$ */ -#include "storage.h" - -#include "dalstorage.h" +#include "account-server/dalstorage.hpp" +#include "account-server/storage.hpp" // initialize the static attributes. Storage* Storage::mInstance = 0; diff --git a/src/storage.h b/src/account-server/storage.hpp index c4486b5c..fec6dcf3 100644 --- a/src/storage.h +++ b/src/account-server/storage.hpp @@ -24,12 +24,11 @@ #ifndef _TMWSERV_STORAGE_H_ #define _TMWSERV_STORAGE_H_ - -#include <map> #include <list> +#include <map> -#include "account.h" -#include "chatchannel.h" +#include "account-server/account.hpp" +#include "chat-server/chatchannel.hpp" /** * Data type for the list of accounts. @@ -222,13 +221,6 @@ class Storage virtual bool doesCharacterNameExist(std::string const &name) = 0; /** - * Tells the map name from the map id - * @return the name of the map - */ - virtual const std::string - getMapNameFromId(const unsigned int mapId) = 0; - - /** * Gives the list of opened public channels registered in database * @return a map of the public channels */ diff --git a/src/being.cpp b/src/being.cpp index 1f57b0b2..6f8b7028 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -21,19 +21,9 @@ */ #include "being.h" - -#include "controller.h" - +#include "mapcomposite.h" #include "utils/logger.h" -void Being::update() -{ - if (mController) - mController->update();
-
- mHitsTaken.clear(); -}
-
void Being::damage(Damage damage)
{
int HPloss;
@@ -44,8 +34,79 @@ void Being::damage(Damage damage) mHitsTaken.push_back(HPloss);
LOG_DEBUG("Being " << getPublicID() << " got hit", 0);
}
-
-void Being::performAttack(MapComposite* map)
-{
- //Monster attack
-}
+ +void Being::performAttack(MapComposite* map) +{ + std::list<ObjectPtr> victimList; + std::list<Point> attackZone; + + Point attackPoint = getPosition(); + + unsigned char direction = getDirection(); + if (direction & UP) + { + attackPoint.y -= 32; + attackPoint.x -= 32; + attackZone.push_back(attackPoint); + attackPoint.x += 32; + attackZone.push_back(attackPoint); + attackPoint.x += 32; + attackZone.push_back(attackPoint); + } + else if (direction & RIGHT) + { + attackPoint.x += 32; + attackPoint.y -= 32; + attackZone.push_back(attackPoint); + attackPoint.y += 32; + attackZone.push_back(attackPoint); + attackPoint.y += 32; + attackZone.push_back(attackPoint); + } + else if (direction & DOWN) + { + attackPoint.y += 32; + attackPoint.x -= 32; + attackZone.push_back(attackPoint); + attackPoint.x += 32; + attackZone.push_back(attackPoint); + attackPoint.x += 32; + attackZone.push_back(attackPoint); + } + else { + attackPoint.x -= 32; + attackPoint.y -= 32; + attackZone.push_back(attackPoint); + attackPoint.y += 32; + attackZone.push_back(attackPoint); + attackPoint.y += 32; + attackZone.push_back(attackPoint); + } + + attackZone.push_back(attackPoint); // point player is facing + + // get enemies to hurt + for (std::list<Point>::iterator i = attackZone.begin(), + i_end = attackZone.end(); i != i_end; ++i) + { + std::list<ObjectPtr> newVictimList = map->getObjectsOnTile((*i)); + victimList.splice(victimList.end(), newVictimList); + } + + // apply damage to victims + Damage damage; + + /* TODO: calculate real attack power and damage properties based on + * character equipment and stats + */ + damage = 1; + + for (std::list<ObjectPtr>::iterator i = victimList.begin(), + i_end = victimList.end(); i != i_end; ++i) + { + if ((*i)->getType() == OBJECT_PLAYER || (*i)->getType() == OBJECT_MONSTER) + { + static_cast<Being*>(&**i)->damage(damage); + } + } +} diff --git a/src/being.h b/src/being.h index bf35d9fc..80d5d696 100644 --- a/src/being.h +++ b/src/being.h @@ -31,7 +31,7 @@ #include "object.h" #include "utils/countedptr.h" -class Controller; +class MapComposite; /** * Element attribute for beings, actors and items. @@ -189,41 +189,32 @@ class Being : public MovingObject /** * Takes a damage structure, computes the real damage based on the * stats, deducts the result from the hitpoints and adds the result to - * the HitsTaken list + * the HitsTaken list. */ - virtual void damage(Damage); + void damage(Damage); /** - * Get the damage list + * Gets the damage list. */ - Hits getHitsTaken() const + Hits const &getHitsTaken() const { return mHitsTaken; } /** - * Clears the hit list. - * When a controller is set, updates the controller. + * Clears the damage list. */ - virtual void - update(); - - virtual void - performAttack(MapComposite*); + void clearHitsTaken() + { mHitsTaken.clear(); } /** - * Notification that this being is now possessed by the given - * controller. This means that events regarding what happens to this - * being should be send there. + * Performs an attack. */ - void - possessedBy(Controller *controller) - { mController = controller; } + void performAttack(MapComposite *); private: Being(Being const &rhs); Being &operator=(Being const &rhs); Statistics mStats; /**< stats modifiers or computed stats */ - Controller *mController; int mHitpoints; /**< Hitpoints of the being */ diff --git a/src/chatchannel.cpp b/src/chat-server/chatchannel.cpp index 49301474..9f2bd607 100644 --- a/src/chatchannel.cpp +++ b/src/chat-server/chatchannel.cpp @@ -21,7 +21,7 @@ * $Id$ */ -#include "chatchannel.h" +#include "chat-server/chatchannel.hpp" ChatChannel::ChatChannel(const std::string &channelName, const std::string &channelAnnouncement = "None", diff --git a/src/chatchannel.h b/src/chat-server/chatchannel.hpp index 5571701e..29a0734e 100644 --- a/src/chatchannel.h +++ b/src/chat-server/chatchannel.hpp @@ -24,8 +24,8 @@ #ifndef _TMWSERV_CHATCHANNEL_H_ #define _TMWSERV_CHATCHANNEL_H_ -#include <vector> #include <string> +#include <vector> #include "being.h" diff --git a/src/chatchannelmanager.cpp b/src/chat-server/chatchannelmanager.cpp index 3f91f9ed..9944681e 100644 --- a/src/chatchannelmanager.cpp +++ b/src/chat-server/chatchannelmanager.cpp @@ -21,11 +21,10 @@ * $Id$ */ -#include "chatchannelmanager.h" - #include <map> -#include "storage.h" +#include "account-server/storage.hpp" +#include "chat-server/chatchannelmanager.hpp" ChatChannelManager::ChatChannelManager() { diff --git a/src/chatchannelmanager.h b/src/chat-server/chatchannelmanager.hpp index c1e50299..fdb6d990 100644 --- a/src/chatchannelmanager.h +++ b/src/chat-server/chatchannelmanager.hpp @@ -26,7 +26,7 @@ #include <map> -#include "chatchannel.h" +#include "chat-server/chatchannel.hpp" class ChatChannelManager { diff --git a/src/chathandler.cpp b/src/chat-server/chathandler.cpp index 88a62b59..bb56c160 100644 --- a/src/chathandler.cpp +++ b/src/chat-server/chathandler.cpp @@ -21,14 +21,12 @@ * $Id$ */ -#include "chathandler.h" - -#include "chatchannelmanager.h" -#include "connectionhandler.h" -#include "messagein.h" -#include "messageout.h" -#include "netcomputer.h" - +#include "chat-server/chatchannelmanager.hpp" +#include "chat-server/chathandler.hpp" +#include "net/connectionhandler.hpp" +#include "net/messagein.hpp" +#include "net/messageout.hpp" +#include "net/netcomputer.hpp" #include "utils/logger.h" #include "utils/stringfilter.h" @@ -92,7 +90,7 @@ bool ChatHandler::startListen(enet_uint16 port) { LOG_INFO("Chat handler started:", 0); - ConnectionHandler::startListen(port); + return ConnectionHandler::startListen(port); } void ChatHandler::removeOutdatedPending() diff --git a/src/chathandler.h b/src/chat-server/chathandler.hpp index fb5e4a7f..530a8115 100644 --- a/src/chathandler.h +++ b/src/chat-server/chathandler.hpp @@ -26,7 +26,7 @@ #include <iosfwd> -#include "connectionhandler.h" +#include "net/connectionhandler.hpp" class ChatClient; diff --git a/src/client.cpp b/src/client.cpp index d68a11ff..ef516fdb 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -24,8 +24,8 @@ #include <enet/enet.h> #include "defines.h" -#include "messageout.h" -#include "messagein.h" +#include "net/messagein.hpp" +#include "net/messageout.hpp" #if defined WIN32 #include "../testclient_private.h" diff --git a/src/configuration.h b/src/configuration.h index 4c26f714..df64ee85 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -118,4 +118,7 @@ class Configuration extern Configuration config; +#ifndef DEFAULT_SERVER_PORT +#define DEFAULT_SERVER_PORT 9601 +#endif #endif diff --git a/src/controller.cpp b/src/controller.cpp index b6900c48..b70e17e8 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -24,51 +24,23 @@ #include "utils/logger.h" -Controller::Controller(): - mCountDown(0) -{ -} - -void Controller::possess(BeingPtr being) -{ - unPossess(); - - mBeing = being; - - if (mBeing.get()) - mBeing->possessedBy(this); -} - -void Controller::unPossess() -{ - if (mBeing.get()) - mBeing->possessedBy(NULL); - - mBeing = BeingPtr(); -} - -void Controller::update() +void Controlled::update() { /* Temporary "AI" behaviour that is purely artificial and not at all * intelligent. */ if (mCountDown == 0) { - if (mBeing.get()) - { - Point randomPos = { rand() % 320 + 720, - rand() % 320 + 840 }; - - LOG_INFO("Setting new random destination " << randomPos.x << "," - << randomPos.y << " for being " << mBeing->getPublicID(), 2); - mBeing->setDestination(randomPos); - } - + Point randomPos = { rand() % 320 + 720, + rand() % 320 + 840 }; + setDestination(randomPos); mCountDown = 10 + rand() % 10; + + LOG_INFO("Setting new random destination " << randomPos.x << "," + << randomPos.y << " for being " << getPublicID(), 2); } else { mCountDown--; } } - diff --git a/src/controller.h b/src/controller.h index 43d1d3f4..7a76d33d 100644 --- a/src/controller.h +++ b/src/controller.h @@ -28,23 +28,13 @@ /** * A controller can take control of a being. */ -class Controller +class Controlled: public Being { public: /** * Constructor. */ - Controller(); - - /** - * Take possession of the given being. - */ - void possess(BeingPtr being); - - /** - * Releave possession of any being. - */ - void unPossess(); + Controlled(int type): Being(type, 65535), mCountDown(0) {} /** * Performs one step of controller logic. @@ -52,8 +42,6 @@ class Controller void update(); private: - BeingPtr mBeing; - /** Count down till next random movement (temporary). */ unsigned int mCountDown; }; diff --git a/src/defines.h b/src/defines.h index 2024e66f..b25526be 100644 --- a/src/defines.h +++ b/src/defines.h @@ -125,9 +125,9 @@ enum { APMSG_CHAR_CREATE_RESPONSE = 0x0021, // B error PAMSG_CHAR_DELETE = 0x0022, // B index APMSG_CHAR_DELETE_RESPONSE = 0x0023, // B error - APMSG_CHAR_INFO = 0x0024, // B index, S name, B gender, B hair style, B hair color, B level, W money, W*6 stats, S mapname, W*2 position + APMSG_CHAR_INFO = 0x0024, // B index, S name, B gender, B hair style, B hair color, B level, W money, W*6 stats PAMSG_CHAR_SELECT = 0x0026, // B index - APMSG_CHAR_SELECT_RESPONSE = 0x0027, // B error, S mapname, S game address, W game port, S chat address, W chat port, B*32 token + APMSG_CHAR_SELECT_RESPONSE = 0x0027, // B error, B*32 token, S game address, W game port, S chat address, W chat port PAMSG_EMAIL_CHANGE = 0x0030, // S email APMSG_EMAIL_CHANGE_RESPONSE = 0x0031, // B error PAMSG_EMAIL_GET = 0x0032, // - @@ -180,6 +180,11 @@ enum { PCMSG_QUIT_CHANNEL = 0x0421, // W channel CPMSG_QUIT_CHANNEL_RESPONSE = 0x0422, // B error + // Inter-server + GAMSG_REGISTER = 0x500, // S address, W port, { W map id }* + AGMSG_PLAYER_ENTER = 0x510, // L id, S name, B gender, B hair style, B hair color, B level, W money, + // W*6 stats, W x, W y, W map id, B*32 token + XXMSG_INVALID = 0x7FFF }; diff --git a/src/game-server/accountconnection.cpp b/src/game-server/accountconnection.cpp new file mode 100644 index 00000000..51fc13f9 --- /dev/null +++ b/src/game-server/accountconnection.cpp @@ -0,0 +1,85 @@ +/* + * The Mana World + * Copyright 2006 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 "configuration.h" +#include "defines.h" +#include "player.h" +#include "game-server/accountconnection.hpp" +#include "game-server/mapmanager.hpp" +#include "net/messagein.hpp" +#include "net/messageout.hpp" +#include "utils/logger.h" + +extern void registerGameClient(std::string const &, PlayerPtr); + +bool AccountConnection::start() +{ + if (!Connection::start(config.getValue("accountServerAddress", "localhost"), + int(config.getValue("accountServerPort", DEFAULT_SERVER_PORT)) + 1)) + { + return false; + } + LOG_INFO("Connection established to the account server.", 0); + MessageOut msg(GAMSG_REGISTER); + msg.writeString(config.getValue("gameServerAddress", "localhost")); + msg.writeShort(int(config.getValue("gameServerPort", DEFAULT_SERVER_PORT + 3))); + MapManager::Maps const &m = mapManager->getMaps(); + for (MapManager::Maps::const_iterator i = m.begin(), i_end = m.end(); i != i_end; ++i) + { + msg.writeShort(i->first); + } + send(msg); + return true; +} + +void AccountConnection::processMessage(MessageIn &msg) +{ + switch (msg.getId()) + { + case AGMSG_PLAYER_ENTER: + { + int id = msg.readLong(); + std::string name = msg.readString(); + Player *ptr = new Player(name, id); + ptr->setGender((Gender)msg.readByte()); + ptr->setHairStyle(msg.readByte()); + ptr->setHairColor(msg.readByte()); + ptr->setLevel(msg.readByte()); + ptr->setMoney(msg.readShort()); + for (int j = 0; j < NB_RSTAT; ++j) + ptr->setRawStat(j, msg.readShort()); + int x = msg.readShort(); + int y = msg.readShort(); + Point pos = { x, y }; + ptr->setPosition(pos); + ptr->setMapId(msg.readShort()); + ptr->setSpeed(150); // TODO + std::string token = msg.readString(32); + registerGameClient(token, PlayerPtr(ptr)); + } break; + + default: + LOG_WARN("Invalid message type", 0); + break; + } +} diff --git a/src/game-server/accountconnection.hpp b/src/game-server/accountconnection.hpp new file mode 100644 index 00000000..97412215 --- /dev/null +++ b/src/game-server/accountconnection.hpp @@ -0,0 +1,50 @@ +/* + * The Mana World + * Copyright 2006 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * The Mana World is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#ifndef _TMW_ACCOUNTCONNECTION_H_ +#define _TMW_ACCOUNTCONNECTION_H_ + +#include "net/connection.hpp" + +/** + * A connection to the account server. + */ +class AccountConnection: public Connection +{ + public: + /** + * Initializes a connection to the account server described in the + * configuration file. Registers the maps known by MapManager. + */ + bool start(); + + protected: + /** + * Processes server messages. + */ + virtual void processMessage(MessageIn &); +}; + +extern AccountConnection *accountHandler; + +#endif diff --git a/src/gameclient.cpp b/src/game-server/gameclient.cpp index b1e00804..bd5d5492 100644 --- a/src/gameclient.cpp +++ b/src/game-server/gameclient.cpp @@ -21,12 +21,11 @@ * $Id$ */ -#include "gameclient.h" - #include <cassert> -#include "state.h" -#include "gamehandler.h" +#include "game-server/gameclient.hpp" +#include "game-server/gamehandler.hpp" +#include "game-server/state.hpp" GameClient::GameClient(ENetPeer *peer): NetComputer(peer), diff --git a/src/gameclient.h b/src/game-server/gameclient.hpp index 7133a38d..14f084db 100644 --- a/src/gameclient.h +++ b/src/game-server/gameclient.hpp @@ -24,11 +24,10 @@ #ifndef _TMWSERV_GAMECLIENT_H_ #define _TMWSERV_GAMECLIENT_H_ -#include "netcomputer.h" +#include <enet/enet.h> #include "player.h" - -#include <enet/enet.h> +#include "net/netcomputer.hpp" class GameHandler; diff --git a/src/gamehandler.cpp b/src/game-server/gamehandler.cpp index 6d323642..b0b036e3 100644 --- a/src/gamehandler.cpp +++ b/src/game-server/gamehandler.cpp @@ -21,17 +21,16 @@ * $Id$ */ -#include "gamehandler.h" - #include <cassert> #include <map> -#include "gameclient.h" #include "map.h" -#include "messagein.h" -#include "messageout.h" -#include "netcomputer.h" -#include "state.h" +#include "game-server/gameclient.hpp" +#include "game-server/gamehandler.hpp" +#include "game-server/state.hpp" +#include "net/messagein.hpp" +#include "net/messageout.hpp" +#include "net/netcomputer.hpp" #include "utils/logger.h" struct GamePendingLogin @@ -60,9 +59,6 @@ static GamePendingClients pendingClients; /** * Notification that a particular token has been given to allow a certain * player to enter the game. - * - * This method is currently called directly from the account server. Later on - * it should be a message sent from the account server to the game server. */ void registerGameClient(std::string const &token, PlayerPtr ch) { @@ -90,7 +86,7 @@ bool GameHandler::startListen(enet_uint16 port) { LOG_INFO("Game handler started:", 0); - ConnectionHandler::startListen(port); + return ConnectionHandler::startListen(port); } void GameHandler::removeOutdatedPending() @@ -170,6 +166,7 @@ void GameHandler::processMessage(NetComputer *comp, MessageIn &message) gameState->sayAround(computer.getCharacter().get(), say); } break; + /* case PGMSG_PICKUP: { // add item to inventory (this is too simplistic atm) @@ -198,6 +195,7 @@ void GameHandler::processMessage(NetComputer *comp, MessageIn &message) result.writeByte(ERRMSG_FAILURE); } } break; + */ case PGMSG_WALK: { @@ -209,22 +207,22 @@ void GameHandler::processMessage(NetComputer *comp, MessageIn &message) // no response should be required } break; + /* case PGMSG_EQUIP: { - int itemId = message.readLong(); // Not useful, the inventory knows it + message.readLong(); // ItemId: Not useful, the inventory knows it char slot = message.readByte(); result.writeShort(GPMSG_EQUIP_RESPONSE); result.writeByte(computer.getCharacter()->equip(slot) ? ERRMSG_OK : ERRMSG_FAILURE); } break; + */ case PGMSG_ATTACK: { - LOG_DEBUG ( "Player " << - computer.getCharacter()->getPublicID() << - " attacks", - 0); + LOG_DEBUG("Player " << computer.getCharacter()->getPublicID() + << " attacks", 0); computer.getCharacter()->setDirection(message.readByte()); computer.getCharacter()->setAttacking(true); } break; diff --git a/src/gamehandler.h b/src/game-server/gamehandler.hpp index a66bd509..ceb37cd8 100644 --- a/src/gamehandler.h +++ b/src/game-server/gamehandler.hpp @@ -24,9 +24,8 @@ #ifndef _TMW_SERVER_GAMEHANDLER_ #define _TMW_SERVER_GAMEHANDLER_ -#include "account.h" -#include "connectionhandler.h" #include "player.h" +#include "net/connectionhandler.hpp" class GameClient; @@ -62,11 +61,6 @@ class GameHandler: public ConnectionHandler void removeOutdatedPending(); }; -/** - * Register future client attempt. Temporary until physical server split. - */ -void registerGameClient(std::string const &, PlayerPtr); - extern GameHandler *gameHandler; #endif diff --git a/src/game-server/itemmanager.cpp b/src/game-server/itemmanager.cpp new file mode 100644 index 00000000..3ce8350c --- /dev/null +++ b/src/game-server/itemmanager.cpp @@ -0,0 +1,155 @@ +/* + * The Mana World + * 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 "resourcemanager.h" +#include "game-server/itemmanager.hpp" +#include "utils/logger.h" +#include "utils/xml.hpp" + +ItemManager::ItemManager(std::string const &itemReferenceFile) +{ + ResourceManager *resman = ResourceManager::getInstance(); + int size; + char *data = (char *)resman->loadFile(itemReferenceFile, size); + + if (!data) { + LOG_ERROR("Item Manager: Could not find " << itemReferenceFile << "!", 0); + free(data); + return; + } + + xmlDocPtr doc = xmlParseMemory(data, size); + free(data); + + if (!doc) + { + LOG_ERROR("Item Manager: Error while parsing item database (" + << itemReferenceFile << ")!", 0); + return; + } + + xmlNodePtr node = xmlDocGetRootElement(doc); + if (!node || !xmlStrEqual(node->name, BAD_CAST "items")) + { + LOG_ERROR("Item Manager: " << itemReferenceFile + << " is not a valid database file!", 0); + xmlFreeDoc(doc); + return; + } + + LOG_INFO("Loading item reference...", 0); + unsigned nbItems = 0; + for (node = node->xmlChildrenNode; node != NULL; node = node->next) + { + if (!xmlStrEqual(node->name, BAD_CAST "item")) { + continue; + } + + unsigned id = XML::getProperty(node, "id", 0); + + if (id == 0) + { + LOG_WARN("Item Manager: An (ignored) item has no ID in " + << itemReferenceFile << "!", 0); + continue; + } + + int itemType = XML::getProperty(node, "type", 0); + int weight = XML::getProperty(node, "weight", 0); + int value = XML::getProperty(node, "value", 0); + int maxPerSlot = XML::getProperty(node, "max_per_slot", 0); + std::string scriptName = XML::getProperty(node, "script_name", std::string()); + + Modifiers modifiers; + modifiers.element = (Element)XML::getProperty(node, "element", 0); + modifiers.lifetime = XML::getProperty(node, "lifetime", 0); + modifiers.rawStats[STAT_STRENGTH] = XML::getProperty(node, "strength", 0); + modifiers.rawStats[STAT_AGILITY] = XML::getProperty(node, "agility", 0); + modifiers.rawStats[STAT_VITALITY] = XML::getProperty(node, "vitality", 0); + modifiers.rawStats[STAT_INTELLIGENCE] = XML::getProperty(node, "intelligence", 0); + modifiers.rawStats[STAT_DEXTERITY] = XML::getProperty(node, "dexterity", 0); + modifiers.rawStats[STAT_LUCK] = XML::getProperty(node, "luck", 0); + modifiers.computedStats[STAT_HEAT] = XML::getProperty(node, "heat", 0); + modifiers.computedStats[STAT_ATTACK] = XML::getProperty(node, "attack", 0); + modifiers.computedStats[STAT_DEFENCE] = XML::getProperty(node, "defence", 0); + modifiers.computedStats[STAT_MAGIC] = XML::getProperty(node, "magic", 0); + modifiers.computedStats[STAT_ACCURACY] = XML::getProperty(node, "accuracy", 0); + modifiers.computedStats[STAT_SPEED] = XML::getProperty(node, "speed", 0); + modifiers.hp = XML::getProperty(node, "hp", 0); + modifiers.mp = XML::getProperty(node, "mp", 0); + modifiers.range = XML::getProperty(node, "range", 0); + modifiers.weaponType = (WeaponType)XML::getProperty(node, "weapon_type", 0); + modifiers.beingStateEffect = (BeingStateEffect)XML::getProperty(node, "status_effect", 0); + + ItemPtr item(new Item(modifiers, itemType, weight, + value, scriptName, maxPerSlot)); + mItemReference[id] = item; + nbItems++; + + if (maxPerSlot == 0) + { + LOG_WARN("Item Manager: Missing max per slot properties for item: " + << id << " in " << itemReferenceFile << ".", 0); + } + if (weight == 0) + { + LOG_WARN("Item Manager: Missing weight for item: " + << id << " in " << itemReferenceFile << ".", 0); + } + + LOG_INFO("Item: ID: " << id << ", itemType: " << itemType + << ", weight: " << weight << ", value: " << value << + ", scriptName: " << scriptName << ", maxPerSlot: " << maxPerSlot << ".", 3); + // Log level 5 + LOG_INFO("Modifiers:: element: " << modifiers.element << + ", lifetime: " << modifiers.lifetime + << std::endl << + ", strength: " << modifiers.rawStats[STAT_STRENGTH] << + ", agility: " << modifiers.rawStats[STAT_AGILITY] << + ", vitality: " << modifiers.rawStats[STAT_VITALITY] + << std::endl << + ", intelligence: " << modifiers.rawStats[STAT_INTELLIGENCE] << + ", dexterity: " << modifiers.rawStats[STAT_DEXTERITY] << + ", luck: " << modifiers.rawStats[STAT_LUCK] + << std::endl << + ", heat: " << modifiers.computedStats[STAT_HEAT] << + ", attack: " << modifiers.computedStats[STAT_ATTACK] << + ", defence: " << modifiers.computedStats[STAT_DEFENCE] + << std::endl << + ", magic: " << modifiers.computedStats[STAT_MAGIC] << + ", accuracy: " << modifiers.computedStats[STAT_ACCURACY] << + ", speed: " << modifiers.computedStats[STAT_SPEED] << + std::endl << + ", hp: " << modifiers.hp << + ", mp: " << modifiers.mp << + std::endl << + ", range: " << modifiers.range << + ", weapon_type: " << modifiers.weaponType << + ", status_effect: " << modifiers.beingStateEffect, 5); + } + + LOG_INFO("Loaded " << nbItems << " items from " + << itemReferenceFile << ".", 0); + + xmlFreeDoc(doc); +} diff --git a/src/itemmanager.h b/src/game-server/itemmanager.hpp index b3889a9c..a5ebc8f3 100644 --- a/src/itemmanager.h +++ b/src/game-server/itemmanager.hpp @@ -18,16 +18,16 @@ * 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: $ + * $Id$ */ #ifndef _TMW_ITEMMANAGER_H #define _TMW_ITEMMANAGER_H -#include "item.h" - #include <map> +#include "item.h" + /** * The Item Manager loads the item reference database * and also offers an API to items information, and more. @@ -42,11 +42,6 @@ class ItemManager ItemManager(const std::string &itemReferenceFile); /** - * Destructor - */ - ~ItemManager(); - - /** * Gives an Item having the demanded information. */ ItemPtr getItem(const unsigned int itemId) diff --git a/src/main.cpp b/src/game-server/main-game.cpp index 08475d4a..cfc07c8d 100644 --- a/src/main.cpp +++ b/src/game-server/main-game.cpp @@ -22,8 +22,8 @@ #include <cstdlib> #include <getopt.h> -#include <signal.h> #include <iostream> +#include <signal.h> #include <physfs.h> #include <enet/enet.h> @@ -34,19 +34,16 @@ #define PACKAGE_VERSION PRODUCT_VERSION #endif -#include "accounthandler.h" -#include "chatchannelmanager.h" -#include "chathandler.h" #include "configuration.h" -#include "connectionhandler.h" -#include "gamehandler.h" -#include "messageout.h" #include "resourcemanager.h" -#include "itemmanager.h" #include "skill.h" -#include "state.h" -#include "storage.h" - +#include "game-server/accountconnection.hpp" +#include "game-server/gamehandler.hpp" +#include "game-server/itemmanager.hpp" +#include "game-server/mapmanager.hpp" +#include "game-server/state.hpp" +#include "net/connectionhandler.hpp" +#include "net/messageout.hpp" #include "utils/logger.h" #include "utils/stringfilter.h" #include "utils/timer.h" @@ -76,12 +73,7 @@ std::string scriptLanugage = "none"; #define DEFAULT_LOG_FILE "tmwserv.log" #define DEFAULT_CONFIG_FILE "tmwserv.xml" #define DEFAULT_ITEMSDB_FILE "items.xml" -#ifndef DEFAULT_SERVER_PORT -#define DEFAULT_SERVER_PORT 9601 -// Meaning Account Handler Port is 9601 -// Chat Handler Port is 9602 (9601 + 1) -// and Game Handler Port is 9603... -#endif +#define DEFAULT_MAPSDB_FILE "maps.xml" utils::Timer worldTimer(100, false); /**< Timer for world tics set to 100 ms */ int worldTime = 0; /**< Current world time in 100ms ticks */ @@ -93,19 +85,18 @@ Configuration config; /**< XML config reader */ utils::StringFilter *stringFilter; /**< Slang's Filter */ -/** Account message handler */ -AccountHandler *accountHandler; - -/** Communications (chat) message handler */ -ChatHandler *chatHandler; -/** Chat Channels Manager */ -ChatChannelManager *chatChannelManager; -/** Item Manager */ +/** Item manager */ ItemManager *itemManager; +/** Map manager */ +MapManager *mapManager; + /** Core game message handler */ GameHandler *gameHandler; +/** Account server message handler */ +AccountConnection *accountHandler; + /** Global game state */ State *gameState; @@ -172,17 +163,16 @@ void initialize() // --- Initialize the managers // Initialize the slang's and double quotes filter. stringFilter = new StringFilter(&config); - // Initialize the Chat channels manager - chatChannelManager = new ChatChannelManager(); - // Initialize the Item Manager + // Initialize the map manager + mapManager = new MapManager(DEFAULT_MAPSDB_FILE); + // Initialize the item manager itemManager = new ItemManager(DEFAULT_ITEMSDB_FILE); // --- Initialize the global handlers // FIXME: Make the global handlers global vars or part of a bigger // singleton or a local variable in the event-loop - chatHandler = new ChatHandler(); - accountHandler = new AccountHandler(); gameHandler = new GameHandler(); + accountHandler = new AccountConnection(); // --- Initialize enet. if (enet_initialize() != 0) { @@ -208,21 +198,6 @@ void initialize() #else LOG_WARN("No Scripting Language Support.", 0); #endif - -#if defined (MYSQL_SUPPORT) - LOG_INFO("Using MySQL DB Backend.", 0); -#elif defined (POSTGRESQL_SUPPORT) - LOG_INFO("Using PostGreSQL DB Backend.", 0); -#elif defined (SQLITE_SUPPORT) - LOG_INFO("Using SQLite DB Backend.", 0); -#else - LOG_WARN("No Database Backend Support.", 0); -#endif - - // Initialize configuration defaults - config.setValue("dbuser", ""); - config.setValue("dbpass", ""); - config.setValue("dbhost", ""); } @@ -248,16 +223,12 @@ void deinitialize() #endif // Destroy message handlers - delete accountHandler; - delete chatHandler; delete gameHandler; + delete accountHandler; // Destroy Managers - delete chatChannelManager; delete itemManager; - - // Get rid of persistent data storage - Storage::destroy(); + delete mapManager; PHYSFS_deinit(); } @@ -314,7 +285,7 @@ void parseOptions(int argc, char *argv[]) // Change the port to listen on. unsigned short portToListenOn; portToListenOn = atoi(optarg); - config.setValue("ListenOnPort", portToListenOn); + config.setValue("gameServerPort", portToListenOn); LOG_INFO("Setting Default Port to " << portToListenOn, 0); break; } @@ -337,19 +308,15 @@ int main(int argc, char *argv[]) // General Initialization initialize(); - 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); + if (!accountHandler->start()) { + LOG_ERROR("Unable to create a connection to an account server.", 0); return 3; } - // Create storage wrapper - Storage& store = Storage::instance("tmw"); - store.setUser(config.getValue("dbuser", "")); - store.setPassword(config.getValue("dbpass", "")); - store.close(); - store.open(); + if (!gameHandler->startListen(int(config.getValue("gameServerPort", DEFAULT_SERVER_PORT + 3)))) { + LOG_ERROR("Unable to create an ENet server host.", 0); + return 3; + } // Create state machine gameState = new State; @@ -376,7 +343,6 @@ int main(int argc, char *argv[]) // Handle all messages that are in the message queues accountHandler->process(); - chatHandler->process(); gameHandler->process(); // Update all active objects/beings gameState->update(); @@ -388,8 +354,7 @@ int main(int argc, char *argv[]) LOG_INFO("Received: Quit signal, closing down...", 0); gameHandler->stopListen(); + accountHandler->stop(); delete gameState; - chatHandler->stopListen(); - accountHandler->stopListen(); deinitialize(); } diff --git a/src/game-server/mapmanager.cpp b/src/game-server/mapmanager.cpp new file mode 100644 index 00000000..3b2caedf --- /dev/null +++ b/src/game-server/mapmanager.cpp @@ -0,0 +1,112 @@ +/* + * The Mana World + * 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 <cassert> + +#include "map.h" +#include "mapreader.h" +#include "resourcemanager.h" +#include "game-server/mapmanager.hpp" +#include "utils/logger.h" +#include "utils/xml.hpp" + +MapManager::MapManager(std::string const &mapReferenceFile) +{ + ResourceManager *resman = ResourceManager::getInstance(); + int size; + char *data = (char *)resman->loadFile(mapReferenceFile, size); + + if (!data) { + LOG_ERROR("Map Manager: Could not find " << mapReferenceFile << "!", 0); + free(data); + return; + } + + xmlDocPtr doc = xmlParseMemory(data, size); + free(data); + + if (!doc) + { + LOG_ERROR("Map Manager: Error while parsing map database (" + << mapReferenceFile << ")!", 0); + return; + } + + xmlNodePtr node = xmlDocGetRootElement(doc); + if (!node || !xmlStrEqual(node->name, BAD_CAST "maps")) + { + LOG_ERROR("Map Manager: " << mapReferenceFile + << " is not a valid database file!", 0); + xmlFreeDoc(doc); + return; + } + + LOG_INFO("Loading map reference...", 0); + for (node = node->xmlChildrenNode; node != NULL; node = node->next) + { + if (!xmlStrEqual(node->name, BAD_CAST "map")) { + continue; + } + + unsigned id = XML::getProperty(node, "id", 0); + std::string name = XML::getProperty(node, "name", std::string()); + // TODO: load only local maps + loadMap(id, name); + } + + xmlFreeDoc(doc); +} + +MapManager::~MapManager() +{ + for (Maps::iterator i = maps.begin(), i_end = maps.end(); i != i_end; ++i) + { + delete i->second.map; + } +} + +void MapManager::loadMap(unsigned mapId, std::string const &mapFile) +{ + LoadedMap m = { mapFile, MapReader::readMap("maps/" + mapFile) }; + if (m.map == NULL) + { + LOG_ERROR("Unable to load map \"" << mapFile << "\" (id " << mapId << ")", 0); + return; + } + LOG_INFO("Loaded map \"" << mapFile << "\" (id " << mapId << ")", 0); + maps[mapId] = m; +} + +Map *MapManager::getMap(unsigned mapId) +{ + Maps::iterator i = maps.find(mapId); + assert(i != maps.end()); + return i->second.map; +} + +std::string MapManager::getMapName(unsigned mapId) +{ + Maps::iterator i = maps.find(mapId); + assert(i != maps.end()); + return i->second.fileName; +} diff --git a/src/mapmanager.h b/src/game-server/mapmanager.hpp index 71e3327c..1090a850 100644 --- a/src/mapmanager.h +++ b/src/game-server/mapmanager.hpp @@ -25,57 +25,59 @@ #define _TMW_MAPMANAGER_H #include <map> - -#include "utils/singleton.h" +#include <string> class Map; +struct LoadedMap +{ + std::string fileName; + Map *map; +}; /** * MapManager loads/unloads maps */ -class MapManager: public utils::Singleton<MapManager> +class MapManager { - // friend so that Singleton can call the constructor. - friend class utils::Singleton<MapManager>; - public: - /** - * Load the specified map - */ - Map *loadMap(unsigned int mapId); + typedef std::map< unsigned, LoadedMap > Maps; /** - * Unload the specified map + * Constructor (loads map reference file). */ - void unloadMap(unsigned int mapId); + MapManager(std::string const &); /** - * Reload the specified map + * Returns the requested map. */ - void reloadMap(unsigned int mapId); + Map *getMap(unsigned); /** - * Return the requested map + * Returns the requested map name. */ - Map *getMap(unsigned int mapId); + std::string getMapName(unsigned); /** - * Check if a map was already loaded. + * Returns all the maps. */ - bool - isLoaded(unsigned int mapId) const; + Maps const &getMaps() { return maps; } - protected: /** * Destructor. */ - ~MapManager(void) - throw(); + ~MapManager(); private: + /** + * Loads the specified map. + */ + void loadMap(unsigned, std::string const &); + // Hold all the loaded maps. - std::map<unsigned int, Map *> maps; + Maps maps; }; +extern MapManager *mapManager; + #endif diff --git a/src/state.cpp b/src/game-server/state.cpp index a3fbda1f..3bb2e478 100644 --- a/src/state.cpp +++ b/src/game-server/state.cpp @@ -23,17 +23,14 @@ #include <cassert> -#include "state.h" - #include "controller.h" -#include "gamehandler.h" #include "map.h" #include "mapcomposite.h" -#include "mapmanager.h" -#include "messageout.h" #include "point.h" -#include "storage.h" - +#include "game-server/gamehandler.hpp" +#include "game-server/mapmanager.hpp" +#include "game-server/state.hpp" +#include "net/messageout.hpp" #include "utils/logger.h" State::State() @@ -41,13 +38,11 @@ State::State() // Create 10 maggots for testing purposes for (int i = 0; i < 10; i++) { - BeingPtr being = BeingPtr(new Being(OBJECT_MONSTER, 65535)); + Being *being = new Controlled(OBJECT_MONSTER); being->setSpeed(150); being->setMapId(1); Point pos = { 720, 900 }; being->setPosition(pos); - Controller *controller = new Controller(); - controller->possess(being); addObject(ObjectPtr(being)); } } @@ -75,13 +70,17 @@ State::update() for (ObjectIterator o(map->getWholeMapIterator()); o; ++o) { (*o)->update(); + if ((*o)->getType() == OBJECT_PLAYER || (*o)->getType() == OBJECT_MONSTER) + { + static_cast< Being * >(*o)->clearHitsTaken(); + } } for (MovingObjectIterator o(map->getWholeMapIterator()); o; ++o) { if ((*o)->getUpdateFlags() & ATTACK) { - (*o)->performAttack(m->second); + static_cast< Being * >(*o)->performAttack(m->second); } } @@ -117,12 +116,8 @@ State::update() MessageOut AttackMsg (GPMSG_BEING_ATTACK); AttackMsg.writeShort((*o)->getPublicID()); - LOG_DEBUG( "Sending attack packet from " << - (*o)->getPublicID() << - " to " << - (*p)->getPublicID(), - 0 - ); + LOG_DEBUG("Sending attack packet from " << (*o)->getPublicID() + << " to " << (*p)->getPublicID(), 0); gameHandler->sendTo(*p, AttackMsg); } @@ -131,9 +126,10 @@ State::update() if ((*o)->getType() == OBJECT_PLAYER || (*o)->getType() == OBJECT_MONSTER) { - Being *victim = static_cast<Being*> (*o); - Hits hits = victim->getHitsTaken(); - for (Hits::iterator i = hits.begin(); i != hits.end(); i++) + Being *victim = static_cast< Being * >(*o); + Hits const &hits = victim->getHitsTaken(); + for (Hits::const_iterator i = hits.begin(), + i_end = hits.end(); i != i_end; ++i) { damageMsg.writeShort(victim->getPublicID()); damageMsg.writeShort((*i)); @@ -257,9 +253,8 @@ State::addObject(ObjectPtr objectPtr) /* Since the player doesn't know yet where on the world he is after * connecting to the map server, we send him an initial change map message. */ - Storage &store = Storage::instance("tmw"); MessageOut mapChangeMessage(GPMSG_PLAYER_MAP_CHANGE); - mapChangeMessage.writeString(store.getMapNameFromId(mapId)); + mapChangeMessage.writeString(mapManager->getMapName(mapId)); Point pos = playerPtr->getPosition(); mapChangeMessage.writeShort(pos.x); mapChangeMessage.writeShort(pos.y); @@ -299,10 +294,9 @@ MapComposite *State::loadMap(unsigned mapId) { std::map< unsigned, MapComposite * >::iterator m = maps.find(mapId); if (m != maps.end()) return m->second; - Map *map = MapManager::instance().loadMap(mapId); - if (!map) return NULL; + Map *map = mapManager->getMap(mapId); + assert(map); MapComposite *tmp = new MapComposite(map); - if (!tmp) return NULL; maps[mapId] = tmp; // will need to load extra map related resources here also diff --git a/src/state.h b/src/game-server/state.hpp index 36bd87d0..36bd87d0 100644 --- a/src/state.h +++ b/src/game-server/state.hpp diff --git a/src/inventory.cpp b/src/inventory.cpp index 4fbda228..97f29737 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -18,16 +18,11 @@ * 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: $ + * $Id$ */ #include "inventory.h" - -Inventory::Inventory() -{ - itemList.reserve(MAX_ITEMS_IN_INVENTORY); - equippedItemList.reserve(TOTAL_EQUIPMENT_SLOTS); -} +#include "game-server/itemmanager.hpp" // --------- // Items diff --git a/src/inventory.h b/src/inventory.h index ab9a256e..d2e7961c 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -18,13 +18,13 @@ * 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: items.h 2636 2006-09-02 12:03:22Z gmelquio $ + * $Id$ */ #ifndef INVENTORY_H #define INVENTORY_H -#include "itemmanager.h" +#include "being.h" // items in inventory : const unsigned char MAX_ITEMS_IN_INVENTORY = 50, // Max 252. @@ -89,22 +89,17 @@ class Inventory { public: /** - * ctor. Add slot spaces to MAX_ITEMS_IN_INVENTORY. - */ - Inventory(); - - /** * Convenience function to get slot from ItemId. * If more than one occurence is found, the first is given. */ unsigned char - getSlotFromId(const unsigned int itemId); + getSlotFromId(unsigned int itemId); /** * Return StoredItem */ StoredItem - getStoredItemAt(unsigned char slot) const { return itemList.at(slot); }; + getStoredItemAt(unsigned char slot) const { return itemList[slot]; }; /** * Search in inventory and equipment if an item is present. @@ -118,13 +113,13 @@ class Inventory * Tells an item's amount */ unsigned short - getItemAmount(unsigned char slot) const { return itemList.at(slot).amount; }; + getItemAmount(unsigned char slot) const { return itemList[slot].amount; }; /** * Return Item reference Id */ unsigned int - getItemId(unsigned char slot) const { return itemList.at(slot).itemId; }; + getItemId(unsigned char slot) const { return itemList[slot].itemId; }; /** * add an item with amount @@ -219,7 +214,7 @@ class Inventory * the error code, if not. */ unsigned char unequipItem_(unsigned int itemId, - unsigned char equipmentSlot); + unsigned char equipmentSlot); // Stored items in inventory and equipment @@ -232,9 +227,4 @@ class Inventory StoredItem equippedProjectiles; }; -/** - * Type definition for a smart pointer to Being. - */ -typedef utils::CountedPtr<Inventory> InventoryPtr; - #endif diff --git a/src/item.cpp b/src/item.cpp index 660fa7b7..013c2c69 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -18,7 +18,7 @@ * 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: items.cpp 2512 2006-08-04 16:58:20Z b_lindeijer $ + * $Id$ */ #include "item.h" @@ -18,7 +18,7 @@ * 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: items.h 2636 2006-09-02 12:03:22Z gmelquio $ + * $Id$ */ #ifndef ITEM_H @@ -134,12 +134,12 @@ class Item unsigned int value = 0, std::string scriptName = "", unsigned short maxPerSlot = 0): - mModifiers(modifiers), mItemType(itemType), mWeight(weight), mValue(value), mScriptName(scriptName), - mMaxPerSlot(maxPerSlot) {} + mMaxPerSlot(maxPerSlot), + mModifiers(modifiers) {} virtual ~Item() throw() { } diff --git a/src/itemhandler.cpp b/src/itemhandler.cpp index f1030df6..9b918489 100644 --- a/src/itemhandler.cpp +++ b/src/itemhandler.cpp @@ -18,7 +18,7 @@ * 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: $ + * $Id$ */ #include "itemhandler.h" diff --git a/src/itemhandler.h b/src/itemhandler.h index 43af7632..796234b1 100644 --- a/src/itemhandler.h +++ b/src/itemhandler.h @@ -18,7 +18,7 @@ * 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: $ + * $Id$ */ #ifndef _TMW_ITEMHANDLER_H diff --git a/src/itemmanager.cpp b/src/itemmanager.cpp deleted file mode 100644 index 79ce24e0..00000000 --- a/src/itemmanager.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* - * The Mana World - * 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 "itemmanager.h" - -#include "resourcemanager.h" -#include "utils/logger.h" -#include <libxml/tree.h> - -#define READ_PROP(node, prop, name, target, cast) \ - prop = xmlGetProp(node, BAD_CAST name); \ - if (prop) { \ - target = cast((const char*)prop); \ - xmlFree(prop); \ - } - -ItemManager::ItemManager(const std::string &itemReferenceFile) -{ - ResourceManager *resman = ResourceManager::getInstance(); - int size; - char *data = (char*)resman->loadFile(itemReferenceFile, size); - - if (!data) { - LOG_ERROR("Item Manager: Could not find " << itemReferenceFile << "!", 0); - free(data); - } - else - { - xmlDocPtr doc = xmlParseMemory(data, size); - free(data); - - if (!doc) - { - LOG_ERROR("Item Manager: Error while parsing item database (" - << itemReferenceFile << ")!", 0); - } - else - { - xmlNodePtr node = xmlDocGetRootElement(doc); - if (!node || !xmlStrEqual(node->name, BAD_CAST "items")) - { - LOG_ERROR("Item Manager: " << itemReferenceFile - << " is not a valid database file!", 0); - } - else - { - LOG_INFO("Loading item reference...", 0); - unsigned int nbItems = 0; - for (node = node->xmlChildrenNode; node != NULL; node = node->next) - { - // Properties - unsigned int id = 0; - unsigned short itemType = 0; - unsigned int weight = 0; - unsigned int value = 0; - unsigned short maxPerSlot = 0; - std::string scriptName = ""; - Modifiers modifiers; - - if (!xmlStrEqual(node->name, BAD_CAST "item")) { - continue; - } - - xmlChar *prop = NULL; - // Properties - READ_PROP(node, prop, "id", id, atoi); - READ_PROP(node, prop, "type", itemType, atoi); - READ_PROP(node, prop, "weight", weight, atoi); - READ_PROP(node, prop, "value", value, atoi); - READ_PROP(node, prop, "max_per_slot", maxPerSlot, atoi); - READ_PROP(node, prop, "script_name", scriptName, ); - - // --- Modifiers - // General - READ_PROP(node, prop, "element", modifiers.element, - (Element)atoi); - READ_PROP(node, prop, "lifetime", modifiers.lifetime, atoi); - // Raw Statistics - READ_PROP(node, prop, "strength", - modifiers.rawStats[STAT_STRENGTH], atoi); - READ_PROP(node, prop, "agility", - modifiers.rawStats[STAT_AGILITY], atoi); - READ_PROP(node, prop, "vitality", - modifiers.rawStats[STAT_VITALITY], atoi); - READ_PROP(node, prop, "intelligence", - modifiers.rawStats[STAT_INTELLIGENCE], atoi); - READ_PROP(node, prop, "dexterity", - modifiers.rawStats[STAT_DEXTERITY], atoi); - READ_PROP(node, prop, "luck", - modifiers.rawStats[STAT_LUCK], atoi); - // Computed Statistics - READ_PROP(node, prop, "heat", - modifiers.computedStats[STAT_HEAT], atoi); - READ_PROP(node, prop, "attack", - modifiers.computedStats[STAT_ATTACK], atoi); - READ_PROP(node, prop, "defence", - modifiers.computedStats[STAT_DEFENCE], atoi); - READ_PROP(node, prop, "magic", - modifiers.computedStats[STAT_MAGIC], atoi); - READ_PROP(node, prop, "accuracy", - modifiers.computedStats[STAT_ACCURACY], atoi); - READ_PROP(node, prop, "speed", - modifiers.computedStats[STAT_SPEED], atoi); - // Main Values - READ_PROP(node, prop, "hp", modifiers.hp, atoi); - READ_PROP(node, prop, "mp", modifiers.mp, atoi); - // Equipment - READ_PROP(node, prop, "range", modifiers.range, atoi); - READ_PROP(node, prop, "weapon_type", modifiers.weaponType, - (WeaponType)atoi); - // Status effect - READ_PROP(node, prop, "status_effect", - modifiers.beingStateEffect, (BeingStateEffect)atoi); - - // Checks - if (id != 0) - { - ItemPtr item(new Item(modifiers, itemType, weight, - value, scriptName, maxPerSlot)); - mItemReference[id] = item; - nbItems++; - } - - if (id == 0) - { - LOG_WARN("Item Manager: An (ignored) item has no ID in " - << itemReferenceFile << "!", 0); - } - if (maxPerSlot == 0) - { - LOG_WARN("Item Manager: Missing max per slot properties for item: " - << id << " in " << itemReferenceFile << ".", 0); - } - if (weight == 0) - { - LOG_WARN("Item Manager: Missing weight for item: " - << id << " in " << itemReferenceFile << ".", 0); - } - - LOG_INFO("Item: ID: " << id << ", itemType: " << itemType - << ", weight: " << weight << ", value: " << value << - ", scriptName: " << scriptName << ", maxPerSlot: " << maxPerSlot << ".", 3); - // Log level 5 - LOG_INFO("Modifiers:: element: " << modifiers.element << - ", lifetime: " << modifiers.lifetime - << std::endl << - ", strength: " << modifiers.rawStats[STAT_STRENGTH] << - ", agility: " << modifiers.rawStats[STAT_AGILITY] << - ", vitality: " << modifiers.rawStats[STAT_VITALITY] - << std::endl << - ", intelligence: " << modifiers.rawStats[STAT_INTELLIGENCE] << - ", dexterity: " << modifiers.rawStats[STAT_DEXTERITY] << - ", luck: " << modifiers.rawStats[STAT_LUCK] - << std::endl << - ", heat: " << modifiers.computedStats[STAT_HEAT] << - ",attack: " << modifiers.computedStats[STAT_ATTACK] << - ", defence: " << modifiers.computedStats[STAT_DEFENCE] - << std::endl << - ", magic: " << modifiers.computedStats[STAT_MAGIC] << - ", accuracy: " << modifiers.computedStats[STAT_ACCURACY] << - ", speed: " << modifiers.computedStats[STAT_SPEED] << - std::endl << - ", hp: " << modifiers.hp << - ", mp: " << modifiers.mp << - std::endl << - ", range: " << modifiers.range << - ", weapon_type: " << modifiers.weaponType << - ", status_effect: " << modifiers.beingStateEffect, 5); - } - - LOG_INFO("Loaded " << nbItems << " items from " - << itemReferenceFile << ".", 0); - - } // End if node "items" - - xmlFreeDoc(doc); - - } // End if doc? - } // End if data? -} - -ItemManager::~ItemManager() -{ - mItemReference.clear(); -} diff --git a/src/mapcomposite.cpp b/src/mapcomposite.cpp index 8cda81a3..35038abf 100644 --- a/src/mapcomposite.cpp +++ b/src/mapcomposite.cpp @@ -18,7 +18,7 @@ * 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: $ + * $Id$ */ #include "mapcomposite.h" diff --git a/src/mapcomposite.h b/src/mapcomposite.h index 7384aa37..7961f4da 100644 --- a/src/mapcomposite.h +++ b/src/mapcomposite.h @@ -18,7 +18,7 @@ * 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: $ + * $Id$ */ #ifndef _TMW_SERVER_MAPCOMPOSITE_ @@ -185,7 +185,7 @@ class MapComposite { /**
* Gets all objects on a tile
*/
- std::list<ObjectPtr> MapComposite::getObjectsOnTile(const Point &) const; + std::list<ObjectPtr> getObjectsOnTile(Point const &) const; /** * Gets an iterator on the objects around the old and new positions of diff --git a/src/mapmanager.cpp b/src/mapmanager.cpp deleted file mode 100644 index 169c357f..00000000 --- a/src/mapmanager.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * The Mana World - * 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 "mapmanager.h" - -#include "map.h" -#include "mapreader.h" -#include "storage.h" - -#include "utils/logger.h" - -MapManager::~MapManager() - throw() -{ -} - -Map *MapManager::loadMap(const unsigned int mapId) -{ - Storage &store = Storage::instance("tmw"); - std::string mapFile = store.getMapNameFromId(mapId); - Map *map = MapReader::readMap("maps/" + mapFile); - if (map == NULL) - { - LOG_ERROR("Unable to load map \"" << mapFile << "\" (id " << mapId - << ")", 0); - } - else - { - LOG_INFO("Loaded map \"" << mapFile << "\" (id " << mapId << ")", 0); - maps[mapId] = map; - } - return map; -} - -void MapManager::unloadMap(const unsigned int mapId) -{ - std::map<unsigned int, Map *>::iterator i; - - i = maps.find(mapId); - if (i != maps.end()) - { - delete i->second; - maps.erase(i); - LOG_INFO("Unloaded map (" << mapId << ")", 0); - } - else - { - LOG_WARN("Unable to unload map (" << mapId << ")", 0); - } -} - -void MapManager::reloadMap(const unsigned int mapId) -{ - unloadMap(mapId); - loadMap(mapId); -} - -Map *MapManager::getMap(const unsigned int mapId) -{ - Map *result = NULL; - std::map<unsigned int, Map *>::iterator i; - - i = maps.find(mapId); - if (i != maps.end()) - { - result = i->second; - } - else - { - result = loadMap(mapId); - } - return result; -} - -bool -MapManager::isLoaded(const unsigned int mapId) const -{ - return maps.find(mapId) != maps.end(); -} diff --git a/src/net/connection.cpp b/src/net/connection.cpp new file mode 100644 index 00000000..8a5c8d0e --- /dev/null +++ b/src/net/connection.cpp @@ -0,0 +1,110 @@ +/* + * The Mana World Server + * Copyright 2006 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 "net/connection.hpp" +#include "net/messagein.hpp" +#include "net/messageout.hpp" +#include "utils/logger.h" + +bool Connection::start(std::string const &address, int port) +{ + ENetAddress enetAddress; + enet_address_set_host(&enetAddress, address.c_str()); + enetAddress.port = port; + + mLocal = enet_host_create(NULL /* create a client host */, + 1 /* allow one outgoing connection */, + 0 /* assume any amount of incoming bandwidth */, + 0 /* assume any amount of outgoing bandwidth */); + + if (!mLocal) return false; + + // Initiate the connection, allocating channel 0. + mRemote = enet_host_connect(mLocal, &enetAddress, 1); + + ENetEvent event; + if (enet_host_service(mLocal, &event, 10000) <= 0 || + event.type != ENET_EVENT_TYPE_CONNECT) + { + stop(); + return false; + } + return mRemote; +} + +void Connection::stop() +{ + enet_peer_disconnect(mRemote, 0); + enet_host_flush(mLocal); + enet_peer_reset(mRemote); + enet_host_destroy(mLocal); + mRemote = NULL; +} + +bool Connection::isConnected() const +{ + return mRemote && mRemote->state == ENET_PEER_STATE_CONNECTED; +} + +void Connection::send(MessageOut const &msg, bool reliable, unsigned channel) +{ + ENetPacket *packet; + packet = enet_packet_create(msg.getData(), + msg.getLength(), + reliable ? ENET_PACKET_FLAG_RELIABLE : 0); + + if (packet) + { + enet_peer_send(mRemote, channel, packet); + } + else + { + LOG_WARN("Failure to create packet!", 0); + } +} + +void Connection::process() +{ + ENetEvent event; + // Process Enet events and do not block. + while (enet_host_service(mLocal, &event, 0) > 0) + { + switch (event.type) + { + case ENET_EVENT_TYPE_RECEIVE: + if (event.packet->dataLength >= 2) { + MessageIn msg((char *)event.packet->data, + event.packet->dataLength); + processMessage(msg); + } else { + LOG_ERROR("Message too short.", 0); + } + // Clean up the packet now that we are done using it. + enet_packet_destroy(event.packet); + break; + + default: + break; + } + } +} diff --git a/src/net/connection.hpp b/src/net/connection.hpp new file mode 100644 index 00000000..0cdb1fc0 --- /dev/null +++ b/src/net/connection.hpp @@ -0,0 +1,80 @@ +/* + * The Mana World Server + * Copyright 2006 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_CONNECTION_H_ +#define _TMWSERV_CONNECTION_H_ + +#include <string> +#include <enet/enet.h> + +class MessageIn; +class MessageOut; + +/** + * A point-to-point connection to a remote host. The remote host can use a + * ConnectionHandler to handle this incoming connection. + */ +class Connection +{ + public: + Connection(): mRemote(NULL) {} + virtual ~Connection() {} + + /** + * Connects to the given host/port and waits until the connection is + * established. Returns false if it fails to connect. + */ + bool start(std::string const &, int); + + /** + * Disconnects. + */ + void stop(); + + /** + * Returns whether the connection is established or not. + */ + bool isConnected() const; + + /** + * Sends a message to the remote host. + */ + void send(MessageOut const &msg, bool reliable = true, unsigned channel = 0); + + /** + * Dispatches received messages to processMessage. + */ + void process(); + + protected: + /** + * Processes a single message from the remote host. + */ + virtual void processMessage(MessageIn &) = 0; + + private: + ENetPeer *mRemote; + ENetHost *mLocal; +}; + +#endif diff --git a/src/connectionhandler.cpp b/src/net/connectionhandler.cpp index 96affdc6..7782a74a 100644 --- a/src/connectionhandler.cpp +++ b/src/net/connectionhandler.cpp @@ -20,13 +20,11 @@ * $Id$ */ -#include "connectionhandler.h" - -#include "chatchannelmanager.h" -#include "messagein.h" -#include "messageout.h" -#include "netcomputer.h" - +#include "defines.h" +#include "net/connectionhandler.hpp" +#include "net/messagein.hpp" +#include "net/messageout.hpp" +#include "net/netcomputer.hpp" #include "utils/logger.h" #ifdef SCRIPT_SUPPORT @@ -45,13 +43,6 @@ ip4ToString(unsigned int ip4addr) return ss.str(); } -//////////////// - -ClientData::ClientData(): - inp(0) -{ -} - bool ConnectionHandler::startListen(enet_uint16 port) { // Bind the server to the default localhost. @@ -104,11 +95,10 @@ void ConnectionHandler::process() { LOG_INFO("A new client connected from " << ip4ToString(event.peer->address.host) << ":" << - event.peer->address.port, 0); + event.peer->address.port << " to port " << + host->address.port, 0); NetComputer *comp = computerConnected(event.peer); clients.push_back(comp); - /*LOG_INFO(ltd->host->peerCount << - " client(s) connected", 0);*/ // Store any relevant client information here. event.peer->data = (void *)comp; diff --git a/src/connectionhandler.h b/src/net/connectionhandler.hpp index d09362ef..df22aacc 100644 --- a/src/connectionhandler.h +++ b/src/net/connectionhandler.hpp @@ -27,8 +27,6 @@ #include <list> #include <enet/enet.h> -#define IN_BUFFER_SIZE 8192 - class MessageIn; class MessageOut; class NetComputer; @@ -40,21 +38,6 @@ std::string ip4ToString(unsigned int ip4addr); /** - * Data related to a connected client. This includes the buffer for incoming - * messages and the related socket. - */ -class ClientData -{ - public: - ClientData(); - - //TCPsocket sock; /**< The socket used for communication */ - - int inp; /**< The amount of data in the in buffer */ - char in[IN_BUFFER_SIZE]; /**< The in buffer for incoming messages */ -}; - -/** * This class represents the connection handler interface. The connection * handler will respond to connect/reconnect/disconnect events and handle * incoming messages, passing them on to registered message handlers. diff --git a/src/messagein.cpp b/src/net/messagein.cpp index e0a4b27b..8da02550 100644 --- a/src/messagein.cpp +++ b/src/net/messagein.cpp @@ -21,12 +21,11 @@ * $Id$ */ -#include "messagein.h" - #include <string> - #include <enet/enet.h> +#include "net/messagein.hpp" + MessageIn::MessageIn(const char *data, int length): mData(data), mLength(length), diff --git a/src/messagein.h b/src/net/messagein.hpp index e80f3f4f..c582d056 100644 --- a/src/messagein.h +++ b/src/net/messagein.hpp @@ -57,6 +57,11 @@ class MessageIn */ std::string readString(int length = -1); + /** + * Returns the length of unread data. + */ + unsigned getUnreadLength() { return mLength - mPos; } + private: const char *mData; /**< Packet data */ unsigned int mLength; /**< Length of data in bytes */ diff --git a/src/messageout.cpp b/src/net/messageout.cpp index 7b547bb1..34655e4c 100644 --- a/src/messageout.cpp +++ b/src/net/messageout.cpp @@ -21,14 +21,13 @@ * $Id$ */ -#include "messageout.h" - -#include <string> -#include <stdlib.h> +#include <cstdlib> #include <iosfwd> - +#include <string> #include <enet/enet.h> +#include "net/messageout.hpp" + /** Initial amount of bytes allocated for the messageout data buffer. */ const unsigned int INITIAL_DATA_CAPACITY = 16; diff --git a/src/messageout.h b/src/net/messageout.hpp index 8ec6b171..8ec6b171 100644 --- a/src/messageout.h +++ b/src/net/messageout.hpp diff --git a/src/netcomputer.cpp b/src/net/netcomputer.cpp index c27dd327..f963db55 100644 --- a/src/netcomputer.cpp +++ b/src/net/netcomputer.cpp @@ -21,16 +21,13 @@ * $Id$ */ -#include "netcomputer.h" - #include <iosfwd> #include <queue> - #include <enet/enet.h> #include "defines.h" -#include "messageout.h" - +#include "net/messageout.hpp" +#include "net/netcomputer.hpp" #include "utils/logger.h" NetComputer::NetComputer(ENetPeer *peer): diff --git a/src/netcomputer.h b/src/net/netcomputer.hpp index 5622e03c..0b8dab3d 100644 --- a/src/netcomputer.h +++ b/src/net/netcomputer.hpp @@ -24,9 +24,8 @@ #ifndef _TMWSERV_NETCOMPUTER_H_ #define _TMWSERV_NETCOMPUTER_H_ -#include <enet/enet.h> - #include <iostream> +#include <enet/enet.h> class MessageOut; @@ -57,7 +56,7 @@ class NetComputer * Disconnects the computer from the server, after sending a message. * * The caller of this method should prepare the message, because - * NetComputer does not know which handler send it + * NetComputer does not know which handler is sending it * (could have been chat/game/account) */ void @@ -67,17 +66,17 @@ class NetComputer * Queues a message for sending to a client. * * Reliable packets always arrive, if the client stays connected. - * Unreliable packets may not arrive, and may not even be send. + * Unreliable packets may not arrive, and may not even be sent. * * Channels are used to ensure that unrelated reliable packets do not * hold each other up. In essence, each channel represents a different - * queque. + * queue. * - * @param msg The message to be send. + * @param msg The message to be sent. * @param reliable Defines if a reliable or an unreliable packet - * should be send. + * should be sent. * @param channel The channel number of which the packet should - * be send. + * be sent. */ void send(const MessageOut &msg, bool reliable = true, diff --git a/src/object.cpp b/src/object.cpp index f48d54f4..c2e11a7f 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -20,10 +20,9 @@ * $Id$ */ -#include "object.h" - #include "map.h" -#include "mapmanager.h" +#include "object.h" +#include "game-server/mapmanager.hpp" void MovingObject::move() { @@ -35,22 +34,9 @@ void MovingObject::move() return; } - Map *map = MapManager::instance().getMap(getMapId()); - std::list<PATH_NODE> path; int tileSX = mOld.x / 32, tileSY = mOld.y / 32; int tileDX = mDst.x / 32, tileDY = mDst.y / 32; - if (tileSX != tileDX || tileSY != tileDY) - { - // TODO: cache pathfinding results - path = map->findPath(tileSX, tileSY, tileDX, tileDY); - if (path.empty()) { - // no path was found - mDst = mOld; - mActionTime = 0; - return; - } - } - else + if (tileSX == tileDX && tileSY == tileDY) { // moving while staying on the same tile is free setPosition(mDst); @@ -58,6 +44,17 @@ void MovingObject::move() return; } + Map *map = mapManager->getMap(getMapId()); + // TODO: cache pathfinding results + std::list<PATH_NODE> path = map->findPath(tileSX, tileSY, tileDX, tileDY); + if (path.empty()) + { + // no path was found + mDst = mOld; + mActionTime = 0; + return; + } + PATH_NODE prev(tileSX, tileSY); Point pos; do diff --git a/src/object.h b/src/object.h index 0b019239..23d97434 100644 --- a/src/object.h +++ b/src/object.h @@ -148,8 +148,8 @@ class MovingObject: public Object */ MovingObject(int type, int id) : Object(type), - mDirection(DOWN), mPublicID(id), + mDirection(DOWN), mActionTime(0) {} @@ -196,11 +196,6 @@ class MovingObject: public Object void move(); /** - * Performs an attack - */ - virtual void performAttack (MapComposite* map) = 0; - - /** * Get public ID. * * @return the public ID, 65535 if none yet. @@ -215,15 +210,15 @@ class MovingObject: public Object void setPublicID(int id) { mPublicID = id; } - protected: - unsigned short mActionTime; /**< delay until next action */ - unsigned char mDirection; /**< Facing direction */ - private: unsigned short mPublicID; /**< Object ID sent to clients (unique with respect to the map) */ Point mDst; /**< target coordinates */ Point mOld; /**< old coordinates */ unsigned short mSpeed; /**< speed */ + + protected: + unsigned char mDirection; /**< Facing direction */ + unsigned short mActionTime; /**< delay until next action */ }; /** diff --git a/src/player.cpp b/src/player.cpp index 4cd0da53..d91bfcab 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -20,18 +20,11 @@ * $Id$ */ -#include "player.h" +#include <cassert> #include "defines.h" #include "mapcomposite.h" - -#include <cassert> - -void Player::setDatabaseID(int id) -{ - assert(mDatabaseID == -1); - mDatabaseID = id; -} +#include "player.h" /** * Update the internal status. @@ -55,89 +48,12 @@ void Player::update() // request perform attack mActionTime = 1000; mIsAttacking = false; - raiseUpdateFlags (ATTACK); + raiseUpdateFlags(ATTACK); } } - - Being::update(); } -void Player::performAttack (MapComposite* map) -{ - std::list<ObjectPtr> victimList; - std::list<Point> attackZone; - - - Point attackPoint = getPosition(); - - unsigned char direction= getDirection(); - if (direction & UP) - { - attackPoint.y -= 32; - attackPoint.x -= 32; - attackZone.push_back(attackPoint); - attackPoint.x += 32; - attackZone.push_back(attackPoint); - attackPoint.x += 32; - attackZone.push_back(attackPoint); - } - else if (direction & RIGHT) - { - attackPoint.x += 32; - attackPoint.y -= 32; - attackZone.push_back(attackPoint); - attackPoint.y += 32; - attackZone.push_back(attackPoint); - attackPoint.y += 32; - attackZone.push_back(attackPoint); - } - else if (direction & DOWN) - { - attackPoint.y += 32; - attackPoint.x -= 32; - attackZone.push_back(attackPoint); - attackPoint.x += 32; - attackZone.push_back(attackPoint); - attackPoint.x += 32; - attackZone.push_back(attackPoint); - } - else { - attackPoint.x -= 32; - attackPoint.y -= 32; - attackZone.push_back(attackPoint); - attackPoint.y += 32; - attackZone.push_back(attackPoint); - attackPoint.y += 32; - attackZone.push_back(attackPoint); - } - - attackZone.push_back(attackPoint); //point player is facing - - //get enemies to hurt - for (std::list<Point>::iterator i = attackZone.begin(); i != attackZone.end(); ++i) - { - std::list<ObjectPtr> newVictimList = map->getObjectsOnTile((*i)); - victimList.splice(victimList.end(), newVictimList); - } - - // apply damage to victims - Damage damage; - - /* TODO: calculate real attack power and damage properties based on - * character equipment and stats - */ - damage = 1; - - for (std::list<ObjectPtr>::iterator i = victimList.begin(); i != victimList.end(); ++i) - { - if ((*i)->getType() == OBJECT_PLAYER || (*i)->getType() == OBJECT_MONSTER) - { - static_cast<Being*>(&**i)->damage(damage); - } - } - -}; - +/* void Player::setInventory(const Inventory &inven) { inventory = inven; @@ -167,3 +83,4 @@ bool Player::unequip(unsigned char slot) { return false; // TODO } +*/ diff --git a/src/player.h b/src/player.h index f953c207..091ace74 100644 --- a/src/player.h +++ b/src/player.h @@ -27,9 +27,8 @@ #include <vector> #include "being.h" -#include "inventory.h" - #include "defines.h" +#include "inventory.h" #include "utils/countedptr.h" class GameClient; @@ -42,8 +41,8 @@ class Player : public Being : Being(OBJECT_PLAYER, 65535), mDatabaseID(id), mName(name), - mIsAttacking(false), - mClient(NULL) + mClient(NULL), + mIsAttacking(false) {} /** @@ -157,11 +156,6 @@ class Player : public Being */ void update();
- /**
- * Performs an attack
- */
- virtual void performAttack (MapComposite* map); - /** * Sets inventory. */ @@ -226,7 +220,8 @@ class Player : public Being * Sets database ID. * The object shall not have any ID yet. */ - void setDatabaseID(int id); + void setDatabaseID(int id) + { mDatabaseID = id; } /** * Gets client computer. diff --git a/src/utils/xml.cpp b/src/utils/xml.cpp new file mode 100644 index 00000000..41742d7e --- /dev/null +++ b/src/utils/xml.cpp @@ -0,0 +1,53 @@ +/* + * The Mana World + * Copyright 2006 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 <cstdlib> + +#include "utils/xml.hpp" + +namespace XML +{ + +int getProperty(xmlNodePtr node, char const *name, int def) +{ + if (xmlChar *prop = xmlGetProp(node, BAD_CAST name)) + { + int ret = atoi((char*)prop); + xmlFree(prop); + return ret; + } + return def; +} + +std::string getProperty(xmlNodePtr node, char const *name, std::string const &def) +{ + if (xmlChar *prop = xmlGetProp(node, BAD_CAST name)) + { + std::string val = (char *)prop; + xmlFree(prop); + return val; + } + return def; +} + +} // namespace XML diff --git a/src/utils/xml.hpp b/src/utils/xml.hpp new file mode 100644 index 00000000..ec384f5d --- /dev/null +++ b/src/utils/xml.hpp @@ -0,0 +1,43 @@ +/* + * The Mana World + * 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_XML_H_ +#define _TMWSERV_XML_H_ + +#include <string> +#include <libxml/tree.h> + +namespace XML +{ + /** + * Gets an integer property from an xmlNodePtr. + */ + int getProperty(xmlNodePtr node, char const *name, int def); + + /** + * Gets a string property from an xmlNodePtr. + */ + std::string getProperty(xmlNodePtr node, char const *name, std::string const &def); +} + +#endif |