summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--src/account-server/dalstorage.cpp53
-rw-r--r--src/account-server/dalstorage.hpp7
-rw-r--r--src/account-server/serverhandler.cpp20
-rw-r--r--src/defines.h11
-rw-r--r--src/game-server/accountconnection.cpp17
-rw-r--r--src/game-server/itemmanager.cpp27
-rw-r--r--src/game-server/itemmanager.hpp7
8 files changed, 148 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 3c67715..053caef 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2008-11-05 Andreas Habel <mail@exceptionfault.de>
+
+ * src/account-server/dalstorage.cpp, src/account-server/dalstorage.hpp,
+ src/account-server/serverhandler.cpp, src/defines.h,
+ src/game-server/accountconnection.cpp, src/game-server/itemmanager.cpp,
+ src/game-server/itemmanager.hpp: Added version information to item database.
+ Gameserver reports its local version to accountserver and gets notified
+ if the verion is up-to-date or outdated to prevent inconsistencies.
+
2008-11-04 David Athay <ko2fan@gmail.com>
* src/chat-server/chathandler.cpp, src/chat-server/chathandler.hpp,
diff --git a/src/account-server/dalstorage.cpp b/src/account-server/dalstorage.cpp
index 5d3f957..a928d1b 100644
--- a/src/account-server/dalstorage.cpp
+++ b/src/account-server/dalstorage.cpp
@@ -36,6 +36,11 @@
#include "dal/dataproviderfactory.h"
#include "utils/functors.h"
#include "utils/logger.h"
+#include "utils/xml.hpp"
+
+// TODO: make data/items.xml a constant or read it from config file
+#define DEFAULT_ITEM_FILE "data/items.xml"
+
/**
* Constructor.
@@ -1440,3 +1445,51 @@ void DALStorage::deletePost(Letter* letter)
LOG_ERROR("(DALStorage::deletePost) SQL query failure: " << e.what());
}
}
+
+unsigned int DALStorage::getItemDatabaseVersion(void)
+{
+ int version;
+
+ // TODO: make data/items.xml a constant or read it from config file
+ xmlDocPtr doc = xmlReadFile(DEFAULT_ITEM_FILE, NULL, 0);
+ if (!doc)
+ {
+ LOG_ERROR("Item Manager: Error while parsing item database (items.xml)!");
+ return 0;
+ }
+
+ xmlNodePtr node = xmlDocGetRootElement(doc);
+ if (!node || !xmlStrEqual(node->name, BAD_CAST "items"))
+ {
+ LOG_ERROR("Item Manager:(items.xml) is not a valid database file!");
+ xmlFreeDoc(doc);
+ return 0;
+ }
+
+ for (node = node->xmlChildrenNode; node != NULL; node = node->next)
+ {
+ // Try to load the version of the item database. The version is defined
+ // as subversion tag embedded as XML attribute. So every modification
+ // to the items.xml file will increase the revision automatically.
+ if (xmlStrEqual(node->name, BAD_CAST "version"))
+ {
+ std::string revision = XML::getProperty(node, "revision", std::string());
+ size_t found = revision.find("$Revision: ");
+
+ if (found == std::string::npos)
+ {
+ LOG_ERROR("Itemdatabase has wrong version format string!");
+ xmlFreeDoc(doc);
+ return 0;
+ }
+ // position 11 is the first numeric character in the SVN tag
+ version = atoi(revision.substr(11).c_str());
+
+ LOG_INFO("Loading item database version " << version);
+ xmlFreeDoc(doc);
+ return version;
+ }
+ }
+ xmlFreeDoc(doc);
+ return 0;
+}
diff --git a/src/account-server/dalstorage.hpp b/src/account-server/dalstorage.hpp
index 253c025..5a879bf 100644
--- a/src/account-server/dalstorage.hpp
+++ b/src/account-server/dalstorage.hpp
@@ -331,6 +331,13 @@ class DALStorage
*/
void addAuctionItem(unsigned int itemId, int playerId, unsigned int gold);
+ /**
+ * Gets the version of the local item database.
+ *
+ * @return Version of the item database.
+ */
+ unsigned int getItemDatabaseVersion(void);
+
private:
/**
* Copy constructor.
diff --git a/src/account-server/serverhandler.cpp b/src/account-server/serverhandler.cpp
index 2e472b8..4bbe4cc 100644
--- a/src/account-server/serverhandler.cpp
+++ b/src/account-server/serverhandler.cpp
@@ -177,6 +177,26 @@ void ServerHandler::processMessage(NetComputer *comp, MessageIn &msg)
// TODO: check the credentials of the game server
server->address = msg.readString();
server->port = msg.readShort();
+
+ // checks the version of the remote item database with our local copy
+ unsigned int dbversion = msg.readLong();
+ LOG_INFO("Game server uses itemsdatabase with version " << dbversion);
+
+ LOG_DEBUG("AGMSG_REGISTER_RESPONSE");
+ MessageOut outMsg(AGMSG_REGISTER_RESPONSE);
+ if (dbversion == storage->getItemDatabaseVersion())
+ {
+ LOG_DEBUG("Item databases between account server and "
+ "gameserver are in sync");
+ outMsg.writeShort(DATA_VERSION_OK);
+ }
+ else
+ {
+ LOG_DEBUG("Item database of game server has a wrong version");
+ outMsg.writeShort(DATA_VERSION_OUTDATED);
+ }
+ comp->send(outMsg);
+
LOG_INFO("Game server " << server->address << ':' << server->port
<< " wants to register " << (msg.getUnreadLength() / 2)
<< " maps.");
diff --git a/src/defines.h b/src/defines.h
index 498bad4..15b5150 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -254,8 +254,9 @@ enum {
GPMSG_GET_POST_RESPONSE = 0x04A3, // { S sender name, S letter, { W attachment id } }
// Inter-server
- GAMSG_REGISTER = 0x0500, // S address, W port, { W map id }*
- AGMSG_ACTIVE_MAP = 0x0501, // W map id
+ GAMSG_REGISTER = 0x0500, // S address, W port, L items db revision, { W map id }*
+ AGMSG_REGISTER_RESPONSE = 0x0501, // C item version
+ AGMSG_ACTIVE_MAP = 0x0502, // W map id
AGMSG_PLAYER_ENTER = 0x0510, // B*32 token, L id, S name, serialised character data
GAMSG_PLAYER_DATA = 0x0520, // L id, serialised character data
GAMSG_REDIRECT = 0x0530, // L id
@@ -293,6 +294,12 @@ enum {
ERRMSG_TOO_MANY_ATTACHMENTS // too many attachments in letter
};
+// used in AGMSG_REGISTER_RESPONSE to show state of item db
+enum {
+ DATA_VERSION_OK = 0x00,
+ DATA_VERSION_OUTDATED = 0x01
+};
+
// Login specific return values
enum {
LOGIN_INVALID_VERSION = 0x40, // the user is using an incompatible protocol
diff --git a/src/game-server/accountconnection.cpp b/src/game-server/accountconnection.cpp
index 492d2a1..772369e 100644
--- a/src/game-server/accountconnection.cpp
+++ b/src/game-server/accountconnection.cpp
@@ -30,6 +30,7 @@
#include "game-server/map.hpp"
#include "game-server/mapcomposite.hpp"
#include "game-server/mapmanager.hpp"
+#include "game-server/itemmanager.hpp"
#include "game-server/postman.hpp"
#include "game-server/quest.hpp"
#include "game-server/state.hpp"
@@ -64,6 +65,7 @@ bool AccountConnection::start()
MessageOut msg(GAMSG_REGISTER);
msg.writeString(gameServerAddress);
msg.writeShort(gameServerPort);
+ msg.writeLong(ItemManager::GetDatabaseVersion());
MapManager::Maps const &m = MapManager::getMaps();
for (MapManager::Maps::const_iterator i = m.begin(), i_end = m.end();
i != i_end; ++i)
@@ -87,6 +89,21 @@ void AccountConnection::processMessage(MessageIn &msg)
{
switch (msg.getId())
{
+ case AGMSG_REGISTER_RESPONSE:
+ {
+ if (msg.readShort() != DATA_VERSION_OK)
+ {
+ LOG_ERROR("Item database is outdated! Please update to "
+ "prevent inconsistencies");
+ stop(); // disconnect gracefully from account server
+ exit(1); // stop gameserver to prevent inconsistencies
+ }
+ else
+ {
+ LOG_DEBUG("Local item database is in sync with account server.");
+ }
+ } break;
+
case AGMSG_PLAYER_ENTER:
{
std::string token = msg.readString(MAGIC_TOKEN_LENGTH);
diff --git a/src/game-server/itemmanager.cpp b/src/game-server/itemmanager.cpp
index 019f4c9..a86a01e 100644
--- a/src/game-server/itemmanager.cpp
+++ b/src/game-server/itemmanager.cpp
@@ -39,7 +39,7 @@
typedef std::map< int, ItemClass * > ItemClasses;
static ItemClasses itemClasses; /**< Item reference */
static std::string itemReferenceFile;
-
+static unsigned int itemDatabaseVersion = 0; /**< Version of the loaded items database file.*/
void ItemManager::initialize(std::string const &file)
{
@@ -81,6 +81,26 @@ void ItemManager::reload()
unsigned nbItems = 0;
for (node = node->xmlChildrenNode; node != NULL; node = node->next)
{
+ // Try to load the version of the item database. The version is defined
+ // as subversion tag embedded as XML attribute. So every modification
+ // to the items.xml file will increase the revision automatically.
+ if (xmlStrEqual(node->name, BAD_CAST "version"))
+ {
+ std::string revision = XML::getProperty(node, "revision", std::string());
+ size_t found = revision.find("$Revision: ");
+
+ if (found==std::string::npos)
+ {
+ LOG_ERROR("Itemdatabase has wrong version format string!");
+ continue;
+ }
+ // position 11 is the first numeric character in the SVN tag
+ itemDatabaseVersion = atoi(revision.substr(11).c_str());
+
+ LOG_INFO("Loading item database version " << itemDatabaseVersion);
+ continue;
+ }
+
if (!xmlStrEqual(node->name, BAD_CAST "item"))
{
continue;
@@ -263,3 +283,8 @@ ItemClass *ItemManager::getItem(int itemId)
ItemClasses::const_iterator i = itemClasses.find(itemId);
return i != itemClasses.end() ? i->second : NULL;
}
+
+unsigned int ItemManager::GetDatabaseVersion(void)
+{
+ return itemDatabaseVersion;
+}
diff --git a/src/game-server/itemmanager.hpp b/src/game-server/itemmanager.hpp
index a4743d6..7e92e3f 100644
--- a/src/game-server/itemmanager.hpp
+++ b/src/game-server/itemmanager.hpp
@@ -30,6 +30,8 @@ class ItemClass;
namespace ItemManager
{
+
+
/**
* Loads item reference file.
*/
@@ -49,6 +51,11 @@ namespace ItemManager
* Gets the ItemClass having the given ID.
*/
ItemClass *getItem(int itemId);
+
+ /**
+ * Gets the version of the loaded item database.
+ */
+ unsigned int GetDatabaseVersion(void);
}
#endif