diff options
author | Rogier Polak <rogier.l.a.polak@gmail.com> | 2007-03-05 03:32:59 +0000 |
---|---|---|
committer | Rogier Polak <rogier.l.a.polak@gmail.com> | 2007-03-05 03:32:59 +0000 |
commit | d811a539474a6eeb4439a4204f3d96551a5b7c1e (patch) | |
tree | 66b2482085965598845a0e58fa04d1bcdb6dd5a1 | |
parent | f0d969eba1840362daad9debc93907c270b22ea5 (diff) | |
download | manaserv-d811a539474a6eeb4439a4204f3d96551a5b7c1e.tar.gz manaserv-d811a539474a6eeb4439a4204f3d96551a5b7c1e.tar.bz2 manaserv-d811a539474a6eeb4439a4204f3d96551a5b7c1e.tar.xz manaserv-d811a539474a6eeb4439a4204f3d96551a5b7c1e.zip |
Added an abstrart base class for characterdata, in order to use the same serialize and deserialize functions on both the accountserver and the gameserver.
32 files changed, 949 insertions, 238 deletions
@@ -1,3 +1,29 @@ +2007-03-05 Rogier Polak <rogier.l.a.polak@gmail.com> + + * src/defines.h, src/Makefile.am, src/abstractcharacterdata.hpp, + src/abstractcharacterdata.cpp, src/account-server/account.hpp, + src/account-server/account.cpp, src/account-server/accountclient.hpp + src/account-server/accountclient.cpp, + src/account-server/accounthandler.cpp, + src/account-server/characterdata.hpp, + src/account-server/characterdata.cpp, + src/account-server/dalstorage.hpp, src/account-server/dalstorage.cpp + src/account-server/dalstoragesql.hpp, + src/account-server/serverhandler.hpp, + src/account-server/serverhandler.cpp, src/account-server/storage.hpp + src/game-server/accountconnection.cpp: Added an abstrart base class + for characterdata, in order to use the same serialize and deserialize + functions on both the accountserver and the gameserver. Added the + CharacterData class to the accountserver, a specialisation of + characterdata for the accountserver. Renamed (raw)stats to attributes. + * src/point.h, src/controller.cpp, src/game-server/testing.cpp, + src/game-server/state.cpp: Added two constructors to the Point class. + * src/utils/wingettimeofday.h, src/utils/timer.h: Set svn properties. + * src/game-server/mapcomposite.cpp: Cleaned up a double deletion. + * src/game-server/item.hpp: Added the member spriteId. + * src/account-server/main-account.cpp, src/game-server/main-game.cpp: + Modified the default log files (primarily for development purposes). + 2007-03-03 Bjørn Lindeijer <bjorn@lindeijer.nl> * src/utils/mathutils.cpp, src/utils/mathutils.h, diff --git a/src/Makefile.am b/src/Makefile.am index 56897e40..e4c6d30e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,11 +6,11 @@ bin_PROGRAMS = tmwserv-account tmwserv-game tmwserv_account_SOURCES = \ account-server/main-account.cpp \ + abstractcharacterdata.hpp \ + abstractcharacterdata.cpp \ configuration.h \ configuration.cpp \ defines.h \ - playerdata.hpp \ - playerdata.cpp \ point.h \ resourcemanager.h \ resourcemanager.cpp \ @@ -22,6 +22,8 @@ tmwserv_account_SOURCES = \ account-server/accountclient.cpp \ account-server/accounthandler.hpp \ account-server/accounthandler.cpp \ + account-server/characterdata.hpp \ + account-server/characterdata.cpp \ account-server/dalstorage.hpp \ account-server/dalstorage.cpp \ account-server/dalstoragesql.hpp \ diff --git a/src/abstractcharacterdata.cpp b/src/abstractcharacterdata.cpp new file mode 100644 index 00000000..ac6fd440 --- /dev/null +++ b/src/abstractcharacterdata.cpp @@ -0,0 +1,87 @@ +/* + * The Mana World Server + * Copyright 2007 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 "abstractcharacterdata.hpp" + +#include "net/messagein.hpp" +#include "net/messageout.hpp" +#include "point.h" + +void AbstractCharacterData::serialize(MessageOut &msg) const +{ + msg.writeLong(getDatabaseID()); + msg.writeString(getName()); + msg.writeByte(getGender()); + msg.writeByte(getHairStyle()); + msg.writeByte(getHairColor()); + msg.writeByte(getLevel()); + msg.writeShort(getMoney()); + + for (int i = 0; i < NB_ATTRIBUTES; ++i) + { + msg.writeByte(getAttribute(i)); + } + + msg.writeShort(getMapId()); + msg.writeShort(getPos().x); + msg.writeShort(getPos().y); + + for (int j = 0; j < getNumberOfInventoryItems(); ++j) + { + msg.writeShort(getInventoryItem(j).itemClassId); + msg.writeByte(getInventoryItem(j).numberOfItemsInSlot); + msg.writeByte((unsigned short)getInventoryItem(j).isEquiped); + } +} + +void AbstractCharacterData::deserialize(MessageIn &msg) +{ + setDatabaseID(msg.readLong()); + setName(msg.readString()); + setGender(msg.readByte()); + setHairStyle(msg.readByte()); + setHairColor(msg.readByte()); + setLevel(msg.readByte()); + setMoney(msg.readShort()); + + for (int i = 0; i < NB_ATTRIBUTES; ++i) + { + setAttribute(i, msg.readByte()); + } + + setMapId(msg.readShort()); + + Point temporaryPoint; + temporaryPoint.x = msg.readShort(); + temporaryPoint.y = msg.readShort(); + setPos(temporaryPoint); + + clearInventory(); + while (msg.getUnreadLength()) + { + InventoryItem tempItem; + tempItem.itemClassId = msg.readShort(); + tempItem.numberOfItemsInSlot = msg.readByte(); + tempItem.isEquiped = (bool) msg.readByte(); + addItemToInventory(tempItem); + } +} diff --git a/src/abstractcharacterdata.hpp b/src/abstractcharacterdata.hpp new file mode 100644 index 00000000..3a15ed57 --- /dev/null +++ b/src/abstractcharacterdata.hpp @@ -0,0 +1,193 @@ +/* + * The Mana World Server + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or any later version. + * + * The Mana World is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with The Mana World; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#ifndef _TMWSERV_ABSTRACTCHARACTERDATA +#define _TMWSERV_ABSTRACTCHARACTERDATA + +#include <string> + +class MessageIn; +class MessageOut; +class Point; + +/** + * Gender of a Character. + */ +enum +{ + GENDER_MALE = 0, + GENDER_FEMALE +}; + +/** + * Attributes of a Character. + */ +enum +{ + ATT_STRENGTH = 0, + ATT_AGILITY, + ATT_VITALITY, + ATT_INTELLIGENCE, + ATT_DEXTERITY, + ATT_LUCK, + NB_ATTRIBUTES +}; + +/** + * Numbers of inventory slots + */ +enum +{ + EQUIPMENT_SLOTS = 11, + INVENTORY_SLOTS = 50 +}; + +/** + * Structure representing an item stored in the inventory. + */ +struct InventoryItem +{ + unsigned short itemClassId; + unsigned char numberOfItemsInSlot; + bool isEquiped; +}; + +class AbstractCharacterData +{ + public: + /** + * Stores data into a outgoing message. + */ + void serialize(MessageOut &) const; + + /** + * Restores data from a incomming message. + */ + void deserialize(MessageIn &); + + protected: + /** + * Get and set methods + */ + + /** Gets the database id of the character. */ + virtual int + getDatabaseID() const = 0; + + /** Sets the database id of the character. */ + virtual void + setDatabaseID(int id) = 0; + + /** Gets the name of the character. */ + virtual std::string const & + getName() const = 0; + + /** Sets the name of the character. */ + virtual void + setName(const std::string&) = 0; + + /** Gets the gender of the character (male or female). */ + virtual int + getGender() const = 0; + + /** Sets the gender of the character (male or female). */ + virtual void + setGender(int gender) = 0; + + /** Gets the hairstyle of the character. */ + virtual int + getHairStyle() const = 0; + + /** Sets the hairstyle of the character. */ + virtual void + setHairStyle(int style) = 0; + + /** Gets the haircolor of the character. */ + virtual int + getHairColor() const = 0; + + /** Sets the haircolor of the character. */ + virtual void + setHairColor(int color) = 0; + + /** Gets the level of the character. */ + virtual int + getLevel() const = 0; + + /** Sets the level of the character. */ + virtual void + setLevel(int level) = 0; + + /** Gets the amount of money the character has. */ + virtual int + getMoney() const = 0; + + /** Sets the amount of money the character has. */ + virtual void + setMoney(int amount) = 0; + + /** Gets the value of an attribute of the character. */ + virtual unsigned short + getAttribute(int attributeNumber) const = 0; + + /** Sets the value of an attribute of the character. */ + virtual void + setAttribute(int attributeNumber, int value) = 0; + + /** Gets the Id of the map that the character is on. */ + virtual int + getMapId() const = 0; + + /** Sets the Id of the map that the character is on. */ + virtual void + setMapId(int mapId) = 0; + + /** Gets the position of the character on the map. */ + virtual Point const & + getPos() const = 0; + + /** Sets the position of the character on the map. */ + virtual void + setPos(const Point &p) = 0; + + /** + * The access functions for inventory + */ + + /** Returns the number of inventory items. */ + virtual int + getNumberOfInventoryItems() const = 0; + + /** Returns a reference to the item in inventory at slot. */ + virtual InventoryItem const & + getInventoryItem(unsigned short slot) const = 0; + + /** Clears the inventory, in preperation for an update. */ + virtual void + clearInventory() = 0; + + /** Adds an inventory item to the inventory. */ + virtual void + addItemToInventory(const InventoryItem& item) = 0; +}; + +#endif diff --git a/src/account-server/account.cpp b/src/account-server/account.cpp index 256e5c73..6ca75535 100644 --- a/src/account-server/account.cpp +++ b/src/account-server/account.cpp @@ -20,9 +20,11 @@ * $Id$ */ +#include "account-server/account.hpp" + #include <cassert> -#include "account-server/account.hpp" +#include "account-server/accountclient.hpp" #include "utils/functors.h" /** @@ -49,7 +51,7 @@ Account::Account(const std::string& name, Account::Account(const std::string& name, const std::string& password, const std::string& email, - const Players& characters) + const Characters& characters) : mName(name), mPassword(password), mEmail(email), @@ -155,7 +157,7 @@ Account::getLevel(void) const * Set the characters. */ void -Account::setCharacters(const Players& characters) +Account::setCharacters(const Characters& characters) { mCharacters = characters; } @@ -165,7 +167,7 @@ Account::setCharacters(const Players& characters) * Add a new character. */ void -Account::addCharacter(PlayerPtr character) +Account::addCharacter(CharacterPtr character) { if (character.get() != 0) { mCharacters.push_back(character); @@ -177,10 +179,10 @@ Account::addCharacter(PlayerPtr character) */ bool Account::delCharacter(std::string const &name) { - Players::iterator + Characters::iterator end = mCharacters.end(), it = std::find_if(mCharacters.begin(), end, - std::bind2nd(obj_name_is<PlayerPtr>(), name)); + std::bind2nd(obj_name_is<CharacterPtr>(), name)); if (it == end) return false; mCharacters.erase(it); @@ -191,7 +193,7 @@ bool Account::delCharacter(std::string const &name) /** * Get all the characters. */ -Players &Account::getCharacters() +Characters &Account::getCharacters() { return mCharacters; } @@ -200,15 +202,15 @@ Players &Account::getCharacters() /** * Get a character by name. */ -PlayerPtr Account::getCharacter(const std::string& name) +CharacterPtr Account::getCharacter(const std::string& name) { - Players::iterator + Characters::iterator end = mCharacters.end(), it = std::find_if(mCharacters.begin(), end, - std::bind2nd(obj_name_is<PlayerPtr>(), name)); + std::bind2nd(obj_name_is<CharacterPtr>(), name)); if (it != end) return *it; - return PlayerPtr(); + return CharacterPtr(); } void Account::setID(int id) diff --git a/src/account-server/account.hpp b/src/account-server/account.hpp index e717e118..50129579 100644 --- a/src/account-server/account.hpp +++ b/src/account-server/account.hpp @@ -26,21 +26,10 @@ #include <string> #include "defines.h" -#include "playerdata.hpp" +#include "account-server/characterdata.hpp" #include "utils/countedptr.h" /** - * Type definition for a smart pointer to PlayerData. - */ -typedef utils::CountedPtr< PlayerData > PlayerPtr; - -/** - * Type definition for a list of Players. - */ -typedef std::vector< PlayerPtr > Players; - - -/** * Notes: * - change from the previous implementation: this class does not encrypt * passwords anymore and will just store the passwords as they are @@ -52,9 +41,8 @@ typedef std::vector< PlayerPtr > Players; * encrypt the password twice). */ - /** - * A player account. + * A player's account. */ class Account { @@ -83,7 +71,7 @@ class Account Account(const std::string& name, const std::string& password, const std::string& email, - const Players& characters); + const Characters& characters); /** @@ -170,7 +158,7 @@ class Account * @param characters a list of characters. */ void - setCharacters(const Players& characters); + setCharacters(const Characters& characters); /** @@ -179,7 +167,7 @@ class Account * @param character the new character. */ void - addCharacter(PlayerPtr character); + addCharacter(CharacterPtr character); /** * Remove a character. @@ -195,7 +183,7 @@ class Account * * @return all the characters. */ - Players& + Characters& getCharacters(); /** @@ -203,7 +191,7 @@ class Account * * @return the character if found, NULL otherwise. */ - PlayerPtr + CharacterPtr getCharacter(const std::string& name); /** @@ -231,7 +219,7 @@ class Account std::string mName; /**< user name */ std::string mPassword; /**< user password (encrypted) */ std::string mEmail; /**< user email address */ - Players mCharacters; /**< player data */ + Characters mCharacters; /**< Character data */ AccountLevel mLevel; /**< account level */ }; diff --git a/src/account-server/accountclient.cpp b/src/account-server/accountclient.cpp index 79d3cf0c..8be44289 100644 --- a/src/account-server/accountclient.cpp +++ b/src/account-server/accountclient.cpp @@ -21,9 +21,11 @@ * $Id$ */ -#include "account-server/account.hpp" #include "account-server/accountclient.hpp" + +#include "account-server/account.hpp" #include "account-server/accounthandler.hpp" +#include "account-server/characterdata.hpp" AccountClient::AccountClient(ENetPeer *peer): NetComputer(peer), @@ -44,7 +46,7 @@ void AccountClient::setAccount(AccountPtr acc) mAccountPtr = acc; } -void AccountClient::setCharacter(PlayerPtr ch) +void AccountClient::setCharacter(CharacterPtr ch) { unsetCharacter(); mCharacterPtr = ch; @@ -59,5 +61,5 @@ void AccountClient::unsetAccount() void AccountClient::unsetCharacter() { if (mCharacterPtr.get() == NULL) return; - mCharacterPtr = PlayerPtr(NULL); + mCharacterPtr = CharacterPtr(NULL); } diff --git a/src/account-server/accountclient.hpp b/src/account-server/accountclient.hpp index 8d42e0e4..eb88016c 100644 --- a/src/account-server/accountclient.hpp +++ b/src/account-server/accountclient.hpp @@ -27,6 +27,7 @@ #include <enet/enet.h> #include "account-server/account.hpp" +#include "account-server/characterdata.hpp" #include "net/netcomputer.hpp" class AccountHandler; @@ -70,7 +71,7 @@ class AccountClient : public NetComputer * Set the selected character associated with connection. */ void - setCharacter(PlayerPtr ch); + setCharacter(CharacterPtr ch); /** * Deselect the character associated with connection. @@ -81,7 +82,7 @@ class AccountClient : public NetComputer /** * Get character associated with the connection */ - PlayerPtr + CharacterPtr getCharacter() const { return mCharacterPtr; } private: @@ -89,7 +90,7 @@ class AccountClient : public NetComputer AccountPtr mAccountPtr; /** Selected character */ - PlayerPtr mCharacterPtr; + CharacterPtr mCharacterPtr; }; #endif diff --git a/src/account-server/accounthandler.cpp b/src/account-server/accounthandler.cpp index c6a086ea..d5d5d35f 100644 --- a/src/account-server/accounthandler.cpp +++ b/src/account-server/accounthandler.cpp @@ -28,6 +28,7 @@ #include "point.h" #include "account-server/account.hpp" #include "account-server/accountclient.hpp" +#include "account-server/characterdata.hpp" #include "account-server/serverhandler.hpp" #include "account-server/storage.hpp" #include "chat-server/chathandler.hpp" @@ -198,7 +199,7 @@ AccountHandler::processMessage(NetComputer *comp, MessageIn &message) unsigned char charNum = message.readByte(); - Players &chars = computer.getAccount()->getCharacters(); + Characters &chars = computer.getAccount()->getCharacters(); // Character ID = 0 to Number of Characters - 1. if (charNum >= chars.size()) { // invalid char selection @@ -208,19 +209,22 @@ AccountHandler::processMessage(NetComputer *comp, MessageIn &message) std::string address; short port; - if (!serverHandler->getGameServerFromMap(chars[charNum]->getMap(), address, port)) + if (!serverHandler->getGameServerFromMap( + chars[charNum]->getMapId(), address, port)) { result.writeByte(ERRMSG_FAILURE); - LOG_ERROR("Character Selection: No game server for the map."); + LOG_ERROR("Character Selection: " + << "No game server for the map."); break; } // set character computer.setCharacter(chars[charNum]); - PlayerPtr selectedChar = computer.getCharacter(); + CharacterPtr selectedChar = computer.getCharacter(); result.writeByte(ERRMSG_OK); - LOG_DEBUG(selectedChar->getName() << " is trying to enter the servers."); + LOG_DEBUG(selectedChar->getName() << + " is trying to enter the servers."); std::string magic_token(32, ' '); for (int i = 0; i < 32; ++i) { @@ -231,8 +235,10 @@ AccountHandler::processMessage(NetComputer *comp, MessageIn &message) 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); + 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(), @@ -253,7 +259,7 @@ AccountHandler::processMessage(NetComputer *comp, MessageIn &message) unsigned char charNum = message.readByte(); - Players &chars = computer.getAccount()->getCharacters(); + Characters &chars = computer.getAccount()->getCharacters(); // Character ID = 0 to Number of Characters - 1. if (charNum >= chars.size()) { // invalid char selection @@ -262,11 +268,12 @@ AccountHandler::processMessage(NetComputer *comp, MessageIn &message) } // Delete the character - // if the character to delete is the current character, get off of it in - // memory. + // If the character to delete is the current character, + // get off of it in memory. if ( computer.getCharacter().get() != NULL ) { - if ( computer.getCharacter()->getName() == chars[charNum].get()->getName() ) + if ( computer.getCharacter()->getName() == + chars[charNum].get()->getName() ) { computer.unsetCharacter(); } @@ -336,7 +343,7 @@ AccountHandler::handleLoginMessage(AccountClient &computer, MessageIn &msg) computer.send(reply); // Return information about available characters - Players &chars = computer.getAccount()->getCharacters(); + Characters &chars = computer.getAccount()->getCharacters(); // Send characters list for (unsigned int i = 0; i < chars.size(); i++) @@ -349,8 +356,8 @@ AccountHandler::handleLoginMessage(AccountClient &computer, MessageIn &msg) charInfo.writeByte(chars[i]->getHairColor()); charInfo.writeByte(chars[i]->getLevel()); charInfo.writeShort(chars[i]->getMoney()); - for (int j = 0; j < NB_RSTAT; ++j) - charInfo.writeShort(chars[i]->getRawStat(j)); + for (int j = 0; j < NB_ATTRIBUTES; ++j) + charInfo.writeShort(chars[i]->getAttribute(j)); computer.send(charInfo); } return; @@ -384,7 +391,8 @@ AccountHandler::handleReconnectMessage(AccountClient &computer, MessageIn &msg) if (computer.getAccount().get() == NULL) { std::string magic_token = msg.readString(32); - AccountPendingReconnects::iterator i = pendingReconnects.find(magic_token); + AccountPendingReconnects::iterator i = + pendingReconnects.find(magic_token); if (i == pendingReconnects.end()) { for (AccountPendingClients::iterator j = pendingClients.begin(), @@ -393,17 +401,15 @@ AccountHandler::handleReconnectMessage(AccountClient &computer, MessageIn &msg) if (j->second == &computer) return; //Allready inserted } pendingClients.insert(std::make_pair(magic_token, &computer)); - return; //Waiting for the gameserver, note: using return instead of an else + return; //Waiting for the gameserver } // Gameserver communication was faster, connect the client int accountID = i->second; pendingReconnects.erase(i); handleReconnectedAccount(computer, accountID); + return; } - else - { - LOG_WARN("Account tried to reconnect, but was allready logged in."); - } + LOG_WARN("Account tried to reconnect, but was allready logged in."); } void @@ -495,7 +501,8 @@ AccountHandler::handleUnregisterMessage(AccountClient &computer, // See if the account exists Storage &store = Storage::instance("tmw"); AccountPtr accPtr = store.getAccount(username); - LOG_INFO("Unregister for " << username << " with passwords #" << accPtr->getPassword() << "#" << password << "#"); + LOG_INFO("Unregister for " << username << " with passwords #" + << accPtr->getPassword() << "#" << password << "#"); if (!accPtr.get() || accPtr->getPassword() != password) { reply.writeByte(ERRMSG_INVALID_ARGUMENT); @@ -507,8 +514,8 @@ AccountHandler::handleUnregisterMessage(AccountClient &computer, store.delAccount(accPtr); reply.writeByte(ERRMSG_OK); - // If the account to delete is the current account we're logged in. - // Get out of it in memory. + // If the account to delete is the current account we're loggedin + // on, get out of it in memory. if (computer.getAccount().get() != NULL ) { if (computer.getAccount()->getName() == username) @@ -606,8 +613,8 @@ AccountHandler::handleCharacterCreateMessage(AccountClient &computer, return; } - // A player shouldn't have more than MAX_OF_CHARACTERS characters. - Players &chars = computer.getAccount()->getCharacters(); + // An account shouldn't have more than MAX_OF_CHARACTERS characters. + Characters &chars = computer.getAccount()->getCharacters(); if (chars.size() >= MAX_OF_CHARACTERS) { reply.writeByte(CREATE_TOO_MUCH_CHARACTERS); @@ -617,58 +624,60 @@ AccountHandler::handleCharacterCreateMessage(AccountClient &computer, // LATER_ON: Add race, face and maybe special attributes. - // Customization of player's stats... - RawStatistics rawStats; - for (int i = 0; i < NB_RSTAT; ++i) - rawStats.stats[i] = msg.readShort(); + // Customization of character's attributes... + unsigned short attributes[NB_ATTRIBUTES]; + for (int i = 0; i < NB_ATTRIBUTES; ++i) + attributes[i] = msg.readShort(); // We see if the difference between the lowest stat and the highest // isn't too big. - unsigned short lowestStat = 0; - unsigned short highestStat = 0; - unsigned int totalStats = 0; - bool validNonZeroRawStats = true; - for (int i = 0; i < NB_RSTAT; ++i) + unsigned short lowestAttribute = POINTS_TO_DISTRIBUTES_AT_LVL1; + unsigned short highestAttribute = 0; // start value + unsigned int totalAttributes = 0; + bool validNonZeroAttributes = true; + for (int i = 0; i < NB_ATTRIBUTES; ++i) { - unsigned short stat = rawStats.stats[i]; - // For good total stat check. - totalStats = totalStats + stat; + // For good total attributes check. + totalAttributes += attributes[i]; // For checking if all stats are at least > 0 - if (stat <= 0) validNonZeroRawStats = false; - if (lowestStat == 0 || lowestStat > stat) lowestStat = stat; - if (highestStat == 0 || highestStat < stat) highestStat = stat; + if (attributes[i] <= 0) validNonZeroAttributes = false; + if (lowestAttribute > attributes[i]) + lowestAttribute = attributes[i]; + if (highestAttribute < attributes[i]) + highestAttribute = attributes[i]; } - if (totalStats > POINTS_TO_DISTRIBUTES_AT_LVL1) + if (totalAttributes > POINTS_TO_DISTRIBUTES_AT_LVL1) { - reply.writeByte(CREATE_RAW_STATS_TOO_HIGH); + reply.writeByte(CREATE_ATTRIBUTES_TOO_HIGH); } - else if (totalStats < POINTS_TO_DISTRIBUTES_AT_LVL1) + else if (totalAttributes < POINTS_TO_DISTRIBUTES_AT_LVL1) { - reply.writeByte(CREATE_RAW_STATS_TOO_LOW); + reply.writeByte(CREATE_ATTRIBUTES_TOO_LOW); } - else if ((highestStat - lowestStat) > (signed) MAX_DIFF_BETWEEN_STATS) + else if ((highestAttribute - lowestAttribute) > + (signed) MAX_DIFF_BETWEEN_ATTRIBUTES) { - reply.writeByte(CREATE_RAW_STATS_INVALID_DIFF); + reply.writeByte(CREATE_ATTRIBUTES_INVALID_DIFF); } - else if (!validNonZeroRawStats) + else if (!validNonZeroAttributes) { - reply.writeByte(CREATE_RAW_STATS_EQUAL_TO_ZERO); + reply.writeByte(CREATE_ATTRIBUTES_EQUAL_TO_ZERO); } else { - PlayerPtr newCharacter(new PlayerData(name)); - for (int i = 0; i < NB_RSTAT; ++i) - newCharacter->setRawStat(i, rawStats.stats[i]); + CharacterPtr newCharacter(new CharacterData(name)); + for (int i = 0; i < NB_ATTRIBUTES; ++i) + newCharacter->setAttribute(i, attributes[i]); newCharacter->setMoney(0); newCharacter->setLevel(1); newCharacter->setGender(gender); newCharacter->setHairStyle(hairStyle); newCharacter->setHairColor(hairColor); - newCharacter->setMap((int) config.getValue("defaultMap", 1)); - Point startingPos = { (int) config.getValue("startX", 0), - (int) config.getValue("startY", 0) }; + newCharacter->setMapId((int) config.getValue("defaultMap", 1)); + Point startingPos((int) config.getValue("startX", 0), + (int) config.getValue("startY", 0)); newCharacter->setPos(startingPos); computer.getAccount()->addCharacter(newCharacter); @@ -689,8 +698,8 @@ AccountHandler::handleCharacterCreateMessage(AccountClient &computer, charInfo.writeByte(chars[slot]->getHairColor()); charInfo.writeByte(chars[slot]->getLevel()); charInfo.writeShort(chars[slot]->getMoney()); - for (int j = 0; j < NB_RSTAT; ++j) - charInfo.writeShort(chars[slot]->getRawStat(j)); + for (int j = 0; j < NB_ATTRIBUTES; ++j) + charInfo.writeShort(chars[slot]->getAttribute(j)); computer.send(charInfo); return; } @@ -731,7 +740,7 @@ handleReconnectedAccount(AccountClient &computer, int accountID) computer.send(reply); // Return information about available characters - Players &chars = computer.getAccount()->getCharacters(); + Characters &chars = computer.getAccount()->getCharacters(); // Send characters list for (unsigned int i = 0; i < chars.size(); i++) @@ -745,9 +754,9 @@ handleReconnectedAccount(AccountClient &computer, int accountID) charInfo.writeByte(chars[i]->getLevel()); charInfo.writeShort(chars[i]->getMoney()); - for (int j = 0; j < NB_RSTAT; ++j) + for (int j = 0; j < NB_ATTRIBUTES; ++j) { - charInfo.writeShort(chars[i]->getRawStat(j)); + charInfo.writeShort(chars[i]->getAttribute(j)); } computer.send(charInfo); } diff --git a/src/account-server/characterdata.cpp b/src/account-server/characterdata.cpp new file mode 100644 index 00000000..50d1562e --- /dev/null +++ b/src/account-server/characterdata.cpp @@ -0,0 +1,62 @@ +/* + * The Mana World Server + * Copyright 2007 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 "account-server/characterdata.hpp" + +#include "net/messagein.hpp" + +CharacterData::CharacterData(std::string const &name, int id): + mDatabaseID(id), mAccountID(-1), mName(name), mGender(0), mHairStyle(0), + mHairColor(0), mLevel(0), mMoney(0), mMapId(0), mPos(0,0) +{ + for (int i = 0; i < NB_ATTRIBUTES; ++i) + { + mAttributes[i] = 0; + } +} + +CharacterData::CharacterData(MessageIn & msg): + mDatabaseID(-1), mAccountID(-1), mName(""), mGender(0), mHairStyle(0), + mHairColor(0), mLevel(0), mMoney(0), mMapId(0), mPos(0,0) +{ + for (int i = 0; i < NB_ATTRIBUTES; ++i) + { + mAttributes[i] = 0; + } + deserialize(msg); +} + +InventoryItem const & +CharacterData::getInventoryItem(unsigned short slot) const +{ + return mInventory[slot]; +} + +void +CharacterData::addItemToInventory(const InventoryItem& item) +{ + // Discard items if the inventory is full + if ((int)mInventory.size() < INVENTORY_SLOTS) + { + mInventory.push_back(item); + } +} diff --git a/src/account-server/characterdata.hpp b/src/account-server/characterdata.hpp new file mode 100644 index 00000000..8911cb21 --- /dev/null +++ b/src/account-server/characterdata.hpp @@ -0,0 +1,191 @@ +/* + * The Mana World Server + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or any later version. + * + * The Mana World is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with The Mana World; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#ifndef _TMWSERV_CHARACTERDATA +#define _TMWSERV_CHARACTERDATA + +#include "abstractcharacterdata.hpp" + +#include <string> +#include <vector> + +#include "utils/countedptr.h" + +#include "point.h" + +class MessageIn; + +class CharacterData: public AbstractCharacterData +{ + public: + + CharacterData(std::string const &name, int id = -1); + + /** + * Constructor used for creating a character from a serialised message. + */ + CharacterData(MessageIn &); + + /** + * Get and set methods + */ + + /** Gets the database id of the character. */ + int + getDatabaseID() const { return mDatabaseID; } + + /** Sets the database id of the character. */ + void + setDatabaseID(int id) { mDatabaseID = id; } + + /** Gets the account id of the account the character belongs to. */ + int + getAccountID() const { return mAccountID; } + + /** Sets the account id of the account the character belongs to. */ + void + setAccountID(int id) { mAccountID = id; } + + /** Gets the name of the character. */ + std::string const & + getName() const { return mName; } + + /** Sets the name of the character. */ + void + setName(const std::string& name) { mName = name; } + + /** Gets the gender of the character (male / female). */ + int + getGender() const { return mGender; } + + /** Sets the gender of the character (male / female). */ + void + setGender(int gender) { mGender = gender; } + + /** Gets the hairstyle of the character. */ + int + getHairStyle() const { return mHairStyle; } + + /** Sets the hairstyle of the character. */ + void + setHairStyle(int style) { mHairStyle = style; } + + /** Gets the haircolor of the character. */ + int + getHairColor() const { return mHairColor; } + + /** Sets the haircolor of the character. */ + void + setHairColor(int color) { mHairColor = color; } + + /** Gets the level of the character. */ + int + getLevel() const { return mLevel; } + + /** Sets the level of the character. */ + void + setLevel(int level) { mLevel = level; } + + /** Gets the amount of money the character has. */ + int + getMoney() const { return mMoney; } + + /** Sets the amount of money the character has. */ + void + setMoney(int amount) { mMoney = amount; } + + /** Gets the value of an attribute of the character. */ + unsigned short + getAttribute(int attributeNumber) const + { return mAttributes[attributeNumber]; } + + /** Sets the value of an attribute of the character. */ + void + setAttribute(int attributeNumber, int value) + { mAttributes[attributeNumber] = value; } + + /** Gets the Id of the map that the character is on. */ + int + getMapId() const { return mMapId; } + + /** Sets the Id of the map that the character is on. */ + void + setMapId(int mapId) { mMapId = mapId; } + + /** Gets the position of the character on the map. */ + Point const & + getPos() const { return mPos; } + + /** Sets the position of the character on the map. */ + void + setPos(const Point &p) { mPos = p; } + + /** Returns the number of inventory items. */ + int + getNumberOfInventoryItems() const { return mInventory.size(); } + + /** Returns a reference to the item in inventory at slot. */ + InventoryItem const & + getInventoryItem(unsigned short slot) const; + + /** Clears the inventory, in preperation for an update. */ + void + clearInventory() { mInventory.clear(); } + + /** Adds an inventory item to the inventory. */ + void + addItemToInventory(const InventoryItem& item); + + private: + CharacterData(CharacterData const &); + CharacterData &operator=(CharacterData const &); + + int mDatabaseID; //!< Character database ID. + //!< (-1) if not set yet. + int mAccountID; //!< Account ID of the account the character + //!< belongs to. (-1) if not set yet. + std::string mName; //!< Name of the character. + unsigned char mGender; //!< Gender of the being. + unsigned char mHairStyle; //!< Hair Style of the being. + unsigned char mHairColor; //!< Hair Color of the being. + unsigned char mLevel; //!< Level of the being. + unsigned int mMoney; //!< Wealth of the being. + unsigned short mAttributes[NB_ATTRIBUTES]; //!< The attributes of the + //!< character. + unsigned short mMapId; //!< Map the being is on. + Point mPos; //!< Position the being is at. + std::vector< InventoryItem > mInventory; //!< All the possesions of + //!< the character. +}; + +//Utility typedefs +/** + * Type definition for a smart pointer to CharacterData. + */ +typedef utils::CountedPtr< CharacterData > CharacterPtr; + +/** + * Type definition for a list of Characters. + */ +typedef std::vector< CharacterPtr > Characters; + +#endif diff --git a/src/account-server/dalstorage.cpp b/src/account-server/dalstorage.cpp index 4b1e7ea6..cd63473c 100644 --- a/src/account-server/dalstorage.cpp +++ b/src/account-server/dalstorage.cpp @@ -20,11 +20,13 @@ * $Id$ */ +#include "account-server/dalstorage.hpp" + #include <cassert> #include "configuration.h" #include "point.h" -#include "account-server/dalstorage.hpp" +#include "account-server/characterdata.hpp" #include "account-server/dalstoragesql.hpp" #include "dal/dalexcept.h" #include "dal/dataproviderfactory.h" @@ -49,7 +51,7 @@ class account_by_name }; /** - * Functor used to search a Player by ID in Players. + * Functor used to search a character by ID in Characters. */ class character_by_id { @@ -58,7 +60,7 @@ class character_by_id : mID(id) {} - bool operator()(PlayerPtr const &elem) const + bool operator()(CharacterPtr const &elem) const { return elem->getDatabaseID() == mID; } private: @@ -242,24 +244,24 @@ DALStorage::getAccount(const std::string& userName) if (!charInfo.isEmpty()) { int size = charInfo.rows(); - Players players; + Characters characters; LOG_DEBUG(userName << "'s account has " << size << " character(s) in database."); // Two steps: it seems like multiple requests cannot be alive at the same time. - std::vector< unsigned > playerIDs; + std::vector< unsigned > characterIDs; for (int k = 0; k < size; ++k) { - playerIDs.push_back(toUint(charInfo(k, 0))); + characterIDs.push_back(toUint(charInfo(k, 0))); } for (int k = 0; k < size; ++k) { - players.push_back(getCharacter(playerIDs[k])); + characters.push_back(getCharacter(characterIDs[k])); } - account->setCharacters(players); + account->setCharacters(characters); } return account; @@ -322,24 +324,24 @@ DALStorage::getAccountByID(int accountID) if (!charInfo.isEmpty()) { int size = charInfo.rows(); - Players players; + Characters characters; LOG_DEBUG("AccountID: "<< accountID << "; has " << size << " character(s) in database."); // Two steps: it seems like multiple requests cannot be alive at the same time. - std::vector< unsigned > playerIDs; + std::vector< unsigned > characterIDs; for (int k = 0; k < size; ++k) { - playerIDs.push_back(toUint(charInfo(k, 0))); + characterIDs.push_back(toUint(charInfo(k, 0))); } for (int k = 0; k < size; ++k) { - players.push_back(getCharacter(playerIDs[k])); + characters.push_back(getCharacter(characterIDs[k])); } - account->setCharacters(players); + account->setCharacters(characters); } return account; @@ -353,13 +355,13 @@ DALStorage::getAccountByID(int accountID) /** * Gets a character by database ID. */ -PlayerPtr DALStorage::getCharacter(int id) +CharacterPtr DALStorage::getCharacter(int id) { // connect to the database (if not connected yet). open(); // look for the character in the list first. - Players::iterator it_end = mCharacters.end(), + Characters::iterator it_end = mCharacters.end(), it = std::find_if(mCharacters.begin(), it_end, character_by_id(id)); if (it != it_end) @@ -378,7 +380,7 @@ PlayerPtr DALStorage::getCharacter(int id) // we have no choice but to return nothing. if (charInfo.isEmpty()) { - return PlayerPtr(NULL); + return CharacterPtr(NULL); } // specialize the string_to functor to convert @@ -389,39 +391,39 @@ PlayerPtr DALStorage::getCharacter(int id) // a string to an unsigned short. string_to< unsigned short > toUshort; - PlayerData *player = new PlayerData(charInfo(0, 2), toUint(charInfo(0, 0))); - player->setAccountID(toUint(charInfo(0, 1))); - player->setGender(toUshort(charInfo(0, 3))); - player->setHairStyle(toUshort(charInfo(0, 4))); - player->setHairColor(toUshort(charInfo(0, 5))); - player->setLevel(toUshort(charInfo(0, 6))); - player->setMoney(toUint(charInfo(0, 7))); - Point pos = { toUshort(charInfo(0, 8)), toUshort(charInfo(0, 9)) }; - player->setPos(pos); - for (int i = 0; i < NB_RSTAT; ++i) + CharacterData *character = new CharacterData(charInfo(0, 2), toUint(charInfo(0, 0))); + character->setAccountID(toUint(charInfo(0, 1))); + character->setGender(toUshort(charInfo(0, 3))); + character->setHairStyle(toUshort(charInfo(0, 4))); + character->setHairColor(toUshort(charInfo(0, 5))); + character->setLevel(toUshort(charInfo(0, 6))); + character->setMoney(toUint(charInfo(0, 7))); + Point pos(toUshort(charInfo(0, 8)), toUshort(charInfo(0, 9))); + character->setPos(pos); + for (int i = 0; i < NB_ATTRIBUTES; ++i) { - player->setRawStat(i, toUshort(charInfo(0, 11 + i))); + character->setAttribute(i, toUshort(charInfo(0, 11 + i))); } int mapId = toUint(charInfo(0, 10)); if (mapId > 0) { - player->setMap(mapId); + character->setMapId(mapId); } else { - // Set player to default map and one of the default location + // Set character to default map and one of the default location // Default map is to be 1, as not found return value will be 0. - player->setMap((int)config.getValue("defaultMap", 1)); + character->setMapId((int)config.getValue("defaultMap", 1)); } - PlayerPtr ptr(player); + CharacterPtr ptr(character); mCharacters.push_back(ptr); return ptr; } catch (const DbSqlQueryExecFailure& e) { - return PlayerPtr(NULL); // TODO: Throw exception here + return CharacterPtr(NULL); // TODO: Throw exception here } } @@ -516,6 +518,122 @@ bool DALStorage::doesCharacterNameExist(const std::string& name) return true; } +bool +DALStorage::updateCharacter(CharacterPtr character) +{ + // If not opened already + open(); + + //Character data (see CharacterData for details) + try + { + std::ostringstream sqlUpdateCharacterInfo; + sqlUpdateCharacterInfo + << "update " << CHARACTERS_TBL_NAME << " " + << "set" + << "gender = " << character->getGender() + << ", " + << "hair_style = " << (int)character->getHairStyle() + << ", " + << "hair_color = " << (int)character->getHairColor() + << ", " + << "level = " << (int)character->getLevel() + << ", " + << "money = " << character->getMoney() + << ", " + << "x = " << character->getPos().x + << ", " + << "y = " << character->getPos().y + << ", " + << "map_id = " << character->getMapId() + << ", " + << "str = " << character->getAttribute(ATT_STRENGTH) + << ", " + << "agi = " << character->getAttribute(ATT_AGILITY) + << ", " + << "vit = " << character->getAttribute(ATT_VITALITY) + << ", " +#if defined(MYSQL_SUPPORT) || defined(POSTGRESQL_SUPPORT) + << "`int` = " +#else + << "int = " +#endif + << character->getAttribute(ATT_INTELLIGENCE) + << ", " + << "dex = " << character->getAttribute(ATT_DEXTERITY) + << ", " + << "luck = " << character->getAttribute(ATT_LUCK) + << "where id = " << character->getDatabaseID() + << ";"; + + mDb->execSql(sqlUpdateCharacterInfo.str()); + } + catch (const dal::DbSqlQueryExecFailure& e) + { + // TODO: throw an exception. + LOG_ERROR("SQL query failure: " << e.what()); + return false; + } + + /** + * Character's inventory + */ + + // Delete the old inventory first + try + { + std::ostringstream sqlDeleteCharacterInventory; + sqlDeleteCharacterInventory + << "delete * from " << INVENTORIES_TBL_NAME + << "where owner_id = " << character->getDatabaseID() << ";"; + + mDb->execSql(sqlDeleteCharacterInventory.str()); + } + catch (const dal::DbSqlQueryExecFailure& e) + { + // TODO: throw an exception. + LOG_ERROR("SQL query failure: " << e.what()); + return false; + } + + // Insert the new inventory data + try + { + if (character->getNumberOfInventoryItems()) + { + std::ostringstream sqlInsertCharacterInventory; + sqlInsertCharacterInventory + << "insert into " << INVENTORIES_TBL_NAME + << "(owner_id, class_id, amount, equipped) " + << "values "; + + for (int j = 0; ; ) + { + sqlInsertCharacterInventory + << "(" << character->getDatabaseID() << ", " + << character->getInventoryItem(j).itemClassId << ", " + << character->getInventoryItem(j).numberOfItemsInSlot + << ", " + << (unsigned short) + character->getInventoryItem(j).isEquiped + << ")"; + // Adding the comma only if it's needed + if (++j < character->getNumberOfInventoryItems()) + sqlInsertCharacterInventory << ", "; + } + + mDb->execSql(sqlInsertCharacterInventory.str()); + } + } + catch (const dal::DbSqlQueryExecFailure& e) + { + // TODO: throw an exception. + LOG_ERROR("SQL query failure: " << e.what()); + return false; + } + return true; +} + std::map<short, ChatChannel> DALStorage::getChannelList() { @@ -603,7 +721,8 @@ DALStorage::updateChannels(std::map<short, ChatChannel>& channelList) << i->second.getPassword() << "\", \"" << i->second.getPrivacy() << "\");"; - LOG_DEBUG("Channel (" << i->first << ") saved: " << i->second.getName() + LOG_DEBUG("Channel (" << i->first << ") saved: " + << i->second.getName() << ": " << i->second.getAnnouncement()); } @@ -724,10 +843,10 @@ void DALStorage::flush(AccountPtr const &account) mDb->execSql(sqlUpdateAccountTable.str()); // get the list of characters that belong to this account. - Players &characters = account->getCharacters(); + Characters &characters = account->getCharacters(); // insert or update the characters. - for (Players::const_iterator it = characters.begin(), + for (Characters::const_iterator it = characters.begin(), it_end = characters.end(); it != it_end; ++it) { if ((*it)->getDatabaseID() < 0) { @@ -748,13 +867,13 @@ void DALStorage::flush(AccountPtr const &account) << (*it)->getMoney() << ", " << (*it)->getPos().x << ", " << (*it)->getPos().y << ", " - << (*it)->getMap() << ", " - << (*it)->getRawStat(STAT_STRENGTH) << ", " - << (*it)->getRawStat(STAT_AGILITY) << ", " - << (*it)->getRawStat(STAT_VITALITY) << ", " - << (*it)->getRawStat(STAT_INTELLIGENCE) << ", " - << (*it)->getRawStat(STAT_DEXTERITY) << ", " - << (*it)->getRawStat(STAT_LUCK) << ");"; + << (*it)->getMapId() << ", " + << (*it)->getAttribute(ATT_STRENGTH) << ", " + << (*it)->getAttribute(ATT_AGILITY) << ", " + << (*it)->getAttribute(ATT_VITALITY) << ", " + << (*it)->getAttribute(ATT_INTELLIGENCE) << ", " + << (*it)->getAttribute(ATT_DEXTERITY) << ", " + << (*it)->getAttribute(ATT_LUCK) << ");"; mDb->execSql(sqlInsertCharactersTable.str()); } else { @@ -769,17 +888,17 @@ void DALStorage::flush(AccountPtr const &account) << " money = " << (*it)->getMoney() << ", " << " x = " << (*it)->getPos().x << ", " << " y = " << (*it)->getPos().y << ", " - << " map_id = " << (*it)->getMap() << ", " - << " str = " << (*it)->getRawStat(STAT_STRENGTH) << ", " - << " agi = " << (*it)->getRawStat(STAT_AGILITY) << ", " - << " vit = " << (*it)->getRawStat(STAT_VITALITY) << ", " + << " map_id = " << (*it)->getMapId() << ", " + << " str = " << (*it)->getAttribute(ATT_STRENGTH) << ", " + << " agi = " << (*it)->getAttribute(ATT_AGILITY) << ", " + << " vit = " << (*it)->getAttribute(ATT_VITALITY) << ", " #if defined(MYSQL_SUPPORT) || defined(POSTGRESQL_SUPPORT) - << " `int` = " << (*it)->getRawStat(STAT_INTELLIGENCE) << ", " + << " `int` = " << (*it)->getAttribute(ATT_INTELLIGENCE) << ", " #else - << " int = " << (*it)->getRawStat(STAT_INTELLIGENCE) << ", " + << " int = " << (*it)->getAttribute(ATT_INTELLIGENCE) << ", " #endif - << " dex = " << (*it)->getRawStat(STAT_DEXTERITY) << ", " - << " luck = " << (*it)->getRawStat(STAT_LUCK) + << " dex = " << (*it)->getAttribute(ATT_DEXTERITY) << ", " + << " luck = " << (*it)->getAttribute(ATT_LUCK) << " where id = " << (*it)->getDatabaseID() << ";"; mDb->execSql(sqlUpdateCharactersTable.str()); @@ -829,7 +948,7 @@ void DALStorage::flush(AccountPtr const &account) for (unsigned int i = 0; i < charInMemInfo.rows(); ++i) // in database { charFound = false; - for (Players::const_iterator it = characters.begin(), + for (Characters::const_iterator it = characters.begin(), it_end = characters.end(); it != it_end; ++it) // In memory { if (charInMemInfo(i, 0) == (*it)->getName()) @@ -878,7 +997,7 @@ void DALStorage::delAccount(AccountPtr const &account) { using namespace dal; - account->setCharacters(Players()); + account->setCharacters(Characters()); flush(account); mAccounts.erase(account->getID()); diff --git a/src/account-server/dalstorage.hpp b/src/account-server/dalstorage.hpp index 674b67f6..e6f6d185 100644 --- a/src/account-server/dalstorage.hpp +++ b/src/account-server/dalstorage.hpp @@ -24,6 +24,7 @@ #ifndef _TMWSERV_DALSTORAGE_H_ #define _TMWSERV_DALSTORAGE_H_ +#include "account-server/characterdata.hpp" #include "account-server/storage.hpp" #include "dal/dataprovider.h" @@ -82,7 +83,7 @@ class DALStorage: public Storage * * @return the character associated to the ID. */ - PlayerPtr getCharacter(int id); + CharacterPtr getCharacter(int id); /** * Add a new account. @@ -127,6 +128,16 @@ class DALStorage: public Storage bool doesCharacterNameExist(std::string const &name); /** + * Updates the data for a single character, does not update the + * owning account or the characters name. + * Primary usage should be storing characterdata received from a + * game server. + * returns true if succefull, false otherwise. + */ + bool + updateCharacter(CharacterPtr ptr); + + /** * Gives the list of opened public channels registered in database * @return a map of the public channels */ diff --git a/src/account-server/dalstoragesql.hpp b/src/account-server/dalstoragesql.hpp index 1511e20b..655cbac6 100644 --- a/src/account-server/dalstoragesql.hpp +++ b/src/account-server/dalstoragesql.hpp @@ -129,7 +129,7 @@ const std::string SQL_CHARACTERS_TABLE( "x SMALLINT UNSIGNED NOT NULL," "y SMALLINT UNSIGNED NOT NULL," "map_id TINYINT NOT NULL," - // stats + // attributes "str SMALLINT UNSIGNED NOT NULL," "agi SMALLINT UNSIGNED NOT NULL," "vit SMALLINT UNSIGNED NOT NULL," @@ -154,7 +154,7 @@ const std::string SQL_CHARACTERS_TABLE( "x INTEGER NOT NULL," "y INTEGER NOT NULL," "map_id INTEGER NOT NULL," - // stats + // attributes "str INTEGER NOT NULL," "agi INTEGER NOT NULL," "vit INTEGER NOT NULL," @@ -177,7 +177,7 @@ const std::string SQL_CHARACTERS_TABLE( "x INTEGER NOT NULL," "y INTEGER NOT NULL," "map_id INTEGER NOT NULL," - // stats + // attributes "str INTEGER NOT NULL," "agi INTEGER NOT NULL," "vit INTEGER NOT NULL," @@ -277,25 +277,26 @@ const std::string INVENTORIES_TBL_NAME("tmw_inventories"); const std::string SQL_INVENTORIES_TABLE( "CREATE TABLE tmw_inventories (" #if defined (MYSQL_SUPPORT) - "id SMALLINT NOT NULL," + "id INTEGER PRIMARY KEY AUTO_INCREMENT," "owner_id INTEGER NOT NULL," + "class_id INTEGER NOT NULL," "amount SMALLINT NOT NULL," "equipped TINYINT NOT NULL," - "FOREIGN KEY (id) REFERENCES tmw_items(id)," "FOREIGN KEY (owner_id) REFERENCES tmw_characters(id)" + "INDEX (id)" #elif defined (SQLITE_SUPPORT) - "id INTEGER NOT NULL," + "id INTEGER PRIMARY KEY," "owner_id INTEGER NOT NULL," + "class_id INTEGER NOT NULL," "amount INTEGER NOT NULL," "equipped INTEGER NOT NULL," - "FOREIGN KEY (id) REFERENCES tmw_items(id)," "FOREIGN KEY (owner_id) REFERENCES tmw_characters(id)" #elif defined (POSTGRESQL_SUPPORT) - "id INTEGER NOT NULL," + "id SERIAL PRIMARY KEY," "owner_id INTEGER NOT NULL," + "class_id INTEGER NOT NULL," "amount INTEGER NOT NULL," "equipped INTEGER NOT NULL," - "FOREIGN KEY (id) REFERENCES tmw_items(id)," "FOREIGN KEY (owner_id) REFERENCES tmw_characters(id)" #endif ");" diff --git a/src/account-server/main-account.cpp b/src/account-server/main-account.cpp index cf743688..6e2ef77a 100644 --- a/src/account-server/main-account.cpp +++ b/src/account-server/main-account.cpp @@ -45,7 +45,7 @@ #include "utils/stringfilter.h" // Default options that automake should be able to override. -#define DEFAULT_LOG_FILE "tmwserv.log" +#define DEFAULT_LOG_FILE "tmwserv-account.log" #define DEFAULT_CONFIG_FILE "tmwserv.xml" #define DEFAULT_ITEMSDB_FILE "items.xml" diff --git a/src/account-server/serverhandler.cpp b/src/account-server/serverhandler.cpp index e4ec218f..9a6dd667 100644 --- a/src/account-server/serverhandler.cpp +++ b/src/account-server/serverhandler.cpp @@ -24,6 +24,7 @@ #include <cassert> #include <sstream> +#include "account-server/characterdata.hpp" #include "account-server/serverhandler.hpp" #include "account-server/storage.hpp" #include "net/messagein.hpp" @@ -73,14 +74,14 @@ bool ServerHandler::getGameServerFromMap(unsigned mapId, std::string &address, return true; } -void ServerHandler::registerGameClient(std::string const &token, PlayerPtr ptr) +void ServerHandler::registerGameClient(std::string const &token, CharacterPtr ptr) { - unsigned mapId = ptr->getMap(); + unsigned mapId = ptr->getMapId(); + MessageOut msg(AGMSG_PLAYER_ENTER); - msg.writeLong(ptr->getDatabaseID()); - msg.writeString(ptr->getName()); msg.writeString(token, 32); - ptr->serialize(msg); + ptr->serialize(msg); //Characterdata + Servers::const_iterator i = servers.find(mapId); assert(i != servers.end()); i->second.server->send(msg); @@ -123,19 +124,14 @@ void ServerHandler::processMessage(NetComputer *comp, MessageIn &msg) case GAMSG_PLAYER_DATA: { LOG_DEBUG("GAMSG_PLAYER_DATA"); - int id = msg.readLong(); + Storage &store = Storage::instance("tmw"); - PlayerPtr ptr = store.getCharacter(id); + CharacterPtr ptr(new CharacterData(msg)); + + if (!store.updateCharacter(ptr)) + LOG_ERROR("Received character data for non-existing" << + " character " << ptr->getDatabaseID() << "."); - if (ptr.get() != NULL) - { - ptr->deserialize(msg); - } - else - { - LOG_ERROR("Received player data for non-existing player " << - id << "."); - } } break; case GAMSG_REDIRECT: @@ -148,10 +144,10 @@ void ServerHandler::processMessage(NetComputer *comp, MessageIn &msg) magic_token[i] = 1 + (int)(127 * (rand() / (RAND_MAX + 1.0))); } Storage &store = Storage::instance("tmw"); - PlayerPtr ptr = store.getCharacter(id); + CharacterPtr ptr = store.getCharacter(id); std::string address; short port; - if (serverHandler->getGameServerFromMap(ptr->getMap(), address, + if (serverHandler->getGameServerFromMap(ptr->getMapId(), address, port)) { registerGameClient(magic_token, ptr); @@ -164,7 +160,7 @@ void ServerHandler::processMessage(NetComputer *comp, MessageIn &msg) else { LOG_ERROR("Server Change: No game server for map " << - ptr->getMap() << "."); + ptr->getMapId() << "."); } } break; @@ -175,7 +171,7 @@ void ServerHandler::processMessage(NetComputer *comp, MessageIn &msg) std::string magic_token = msg.readString(32); Storage &store = Storage::instance("tmw"); - PlayerPtr ptr = store.getCharacter(characterID); + CharacterPtr ptr = store.getCharacter(characterID); int accountID = ptr->getAccountID(); registerAccountReconnect(accountID, magic_token); diff --git a/src/account-server/serverhandler.hpp b/src/account-server/serverhandler.hpp index 30dadd65..cc269165 100644 --- a/src/account-server/serverhandler.hpp +++ b/src/account-server/serverhandler.hpp @@ -26,16 +26,11 @@ #include <map> -#include "playerdata.hpp" +#include "account-server/characterdata.hpp" #include "net/connectionhandler.hpp" #include "utils/countedptr.h" /** - * Type definition for a smart pointer to PlayerData. - */ -typedef utils::CountedPtr< PlayerData > PlayerPtr; - -/** * Manages communications with all the game servers. This class also keeps * track of the maps each game server supports. */ @@ -54,9 +49,9 @@ class ServerHandler: public ConnectionHandler bool getGameServerFromMap(unsigned, std::string &address, short &port); /** - * Sends a magic token and player data to the relevant game server. + * Sends a magic token and character data to the relevant game server. */ - void registerGameClient(std::string const &, PlayerPtr); + void registerGameClient(std::string const &, CharacterPtr); protected: /** diff --git a/src/account-server/storage.hpp b/src/account-server/storage.hpp index 031acf4d..15f0a5ff 100644 --- a/src/account-server/storage.hpp +++ b/src/account-server/storage.hpp @@ -28,6 +28,7 @@ #include <map> #include "account-server/account.hpp" +#include "account-server/characterdata.hpp" #include "chat-server/chatchannel.hpp" /** @@ -189,7 +190,7 @@ class Storage * * @return the character associated to the ID. */ - virtual PlayerPtr getCharacter(int id) = 0; + virtual CharacterPtr getCharacter(int id) = 0; /** * Add a new account. @@ -240,6 +241,16 @@ class Storage virtual bool doesCharacterNameExist(std::string const &name) = 0; /** + * Updates the data for a single character, does not update the + * owning account or the characters name. + * Primary usage should be storing characterdata received from a + * game server. + * returns true if succefull, false otherwise. + */ + virtual bool + updateCharacter(CharacterPtr ptr) = 0; + + /** * Gives the list of opened public channels registered in database * @return a map of the public channels */ @@ -295,7 +306,7 @@ class Storage protected: Accounts mAccounts; /**< list of accounts in memory */ - Players mCharacters; /**< the loaded characters */ + Characters mCharacters; /**< the loaded characters */ bool mIsOpen; /**< flag is true if the storage is open */ diff --git a/src/controller.cpp b/src/controller.cpp index 42a64b66..d71461f2 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -33,8 +33,8 @@ void Controlled::update() { if (mAction != DEAD) { - Point randomPos = { rand() % 320 + 720, - rand() % 320 + 840 }; + Point randomPos( rand() % 320 + 720, + rand() % 320 + 840 ); setDestination(randomPos); mCountDown = 10 + rand() % 10; diff --git a/src/defines.h b/src/defines.h index 589f0597..bd188347 100644 --- a/src/defines.h +++ b/src/defines.h @@ -80,7 +80,7 @@ enum * So that players haven't disproportionned * Raw statistics. */ - MAX_DIFF_BETWEEN_STATS = 5, + MAX_DIFF_BETWEEN_ATTRIBUTES = 5, /** * Points to give to a brand new character */ @@ -191,8 +191,8 @@ enum { // Inter-server GAMSG_REGISTER = 0x500, // S address, W port, { W map id }* AGMSG_ACTIVE_MAP = 0x501, // W map id - AGMSG_PLAYER_ENTER = 0x510, // L id, S name, B*32 token, B* player data - GAMSG_PLAYER_DATA = 0x520, // L id, B* player data + AGMSG_PLAYER_ENTER = 0x510, // B*32 token, serialised player data + GAMSG_PLAYER_DATA = 0x520, // serialised player data GAMSG_REDIRECT = 0x530, // L id AGMSG_REDIRECT_RESPONSE = 0x531, // L id, B*32 token, S game address, W game port GAMSG_PLAYER_RECONNECT = 0x532, // L id, B*32 token @@ -229,10 +229,10 @@ enum { CREATE_INVALID_HAIRSTYLE = 0x40, CREATE_INVALID_HAIRCOLOR, CREATE_INVALID_GENDER, - CREATE_RAW_STATS_TOO_HIGH, - CREATE_RAW_STATS_TOO_LOW, - CREATE_RAW_STATS_INVALID_DIFF, - CREATE_RAW_STATS_EQUAL_TO_ZERO, + CREATE_ATTRIBUTES_TOO_HIGH, + CREATE_ATTRIBUTES_TOO_LOW, + CREATE_ATTRIBUTES_INVALID_DIFF, + CREATE_ATTRIBUTES_EQUAL_TO_ZERO, CREATE_EXISTS_NAME, CREATE_TOO_MUCH_CHARACTERS }; diff --git a/src/game-server/accountconnection.cpp b/src/game-server/accountconnection.cpp index e380d25a..2c3fc85b 100644 --- a/src/game-server/accountconnection.cpp +++ b/src/game-server/accountconnection.cpp @@ -67,9 +67,9 @@ void AccountConnection::processMessage(MessageIn &msg) { case AGMSG_PLAYER_ENTER: { + std::string token = msg.readString(32); int id = msg.readLong(); std::string name = msg.readString(); - std::string token = msg.readString(32); Player *ptr = new Player(name, id); ptr->deserialize(msg); ptr->setMapId(ptr->getMap()); diff --git a/src/game-server/gamehandler.cpp b/src/game-server/gamehandler.cpp index 768a2cd9..6b11f542 100644 --- a/src/game-server/gamehandler.cpp +++ b/src/game-server/gamehandler.cpp @@ -247,7 +247,7 @@ void GameHandler::processMessage(NetComputer *comp, MessageIn &message) { int mapId = computer.character->getMapId(); MapComposite *map = gameState->getMap(mapId); - Point ipos = { x, y }; + Point ipos(x, y); for (FixedObjectIterator i(map->getAroundPointIterator(ipos, 0)); i; ++i) { Object *o = *i; @@ -284,7 +284,7 @@ void GameHandler::processMessage(NetComputer *comp, MessageIn &message) { int x = message.readShort(); int y = message.readShort(); - Point dst = {x, y}; + Point dst(x, y); computer.character->setDestination(dst); // no response should be required diff --git a/src/game-server/item.cpp b/src/game-server/item.cpp index 7eb9afb6..9345e33e 100644 --- a/src/game-server/item.cpp +++ b/src/game-server/item.cpp @@ -32,10 +32,7 @@ bool ItemClass::use(Being *itemUser) // Calling a script if scriptName != "" if (!mScriptName.empty()) { - if (runScript(itemUser) && usedSuccessfully) - return true; - else - return false; + return (runScript(itemUser) && usedSuccessfully); } else return usedSuccessfully; diff --git a/src/game-server/item.hpp b/src/game-server/item.hpp index dd61dd2a..21b9e6dd 100644 --- a/src/game-server/item.hpp +++ b/src/game-server/item.hpp @@ -67,7 +67,7 @@ enum WPNTYPE_STICK, // 13 WPNTYPE_HAMMER, // 14 WPNTYPE_AXE, // 15 - WPNTYPE_HAND_PROECTILE // 16 + WPNTYPE_HAND_PROJECTILE // 16 }; /** @@ -205,6 +205,19 @@ class ItemClass int getDatabaseID() { return mDatabaseID; } + /** + * Sets the sprite ID. + */ + void setSpriteID(unsigned short spriteID) + { mSpriteID = spriteID; } + + /** + * Gets the sprite ID. + */ + unsigned short getSpriteID() + { return mSpriteID; } + + private: /** @@ -214,6 +227,7 @@ class ItemClass // Item reference information unsigned short mDatabaseID; + unsigned short mSpriteID; /**< The sprite that should be shown to the player */ unsigned char mType; /**< Type: usable, equipment. */ unsigned short mWeight; /**< Weight of the item. */ unsigned short mCost; /**< Unit cost the item. */ diff --git a/src/game-server/main-game.cpp b/src/game-server/main-game.cpp index 831dc9f1..da1b60f2 100644 --- a/src/game-server/main-game.cpp +++ b/src/game-server/main-game.cpp @@ -68,7 +68,7 @@ std::string scriptLanugage = "none"; #endif // SCRIPT_SUPPORT // Default options that automake should be able to override. -#define DEFAULT_LOG_FILE "tmwserv.log" +#define DEFAULT_LOG_FILE "tmwserv-game.log" #define DEFAULT_CONFIG_FILE "tmwserv.xml" #define DEFAULT_ITEMSDB_FILE "items.xml" #define DEFAULT_MAPSDB_FILE "maps.xml" diff --git a/src/game-server/map.cpp b/src/game-server/map.cpp index 876ba674..6ca447ae 100644 --- a/src/game-server/map.cpp +++ b/src/game-server/map.cpp @@ -21,10 +21,10 @@ * $Id$ */ -#include <queue> - #include "game-server/map.hpp" +#include <queue> + MetaTile::MetaTile(): whichList(0) { diff --git a/src/game-server/mapcomposite.cpp b/src/game-server/mapcomposite.cpp index 207f1e33..0250d14a 100644 --- a/src/game-server/mapcomposite.cpp +++ b/src/game-server/mapcomposite.cpp @@ -343,7 +343,7 @@ MapComposite::~MapComposite() delete buckets[i]; } delete[] zones; - delete map; + // MapManger will delete the maps when necessary. } bool MapComposite::allocate(MovingObject *obj) diff --git a/src/game-server/state.cpp b/src/game-server/state.cpp index 09513b95..0c392da8 100644 --- a/src/game-server/state.cpp +++ b/src/game-server/state.cpp @@ -318,7 +318,7 @@ void State::update() case EVENT_WARP: { remove(o); - Point pos = { e.x, e.y }; + Point pos(e.x, e.y); o->setMapId(e.map); o->setPosition(pos); diff --git a/src/game-server/testing.cpp b/src/game-server/testing.cpp index 4f269e29..b48a7e77 100644 --- a/src/game-server/testing.cpp +++ b/src/game-server/testing.cpp @@ -20,7 +20,7 @@ static void dropItem(int map, int x, int y, int type) assert(ic); Item *i = new Item(ic, 1); i->setMapId(map); - Point pos = { x, y }; + Point pos(x, y); i->setPosition(pos); gameState->insert(i); } @@ -39,7 +39,7 @@ void testingMap(int id) being->setSize(8); being->setHitpoints(3); being->setMapId(1); - Point pos = { 720, 900 }; + Point pos(720, 900); being->setPosition(pos); gameState->insert(being); } diff --git a/src/point.h b/src/point.h index edf208be..6b694ef2 100644 --- a/src/point.h +++ b/src/point.h @@ -31,6 +31,8 @@ class Point { public: + Point() { x = 0; y = 0; } + Point(unsigned short X, unsigned short Y) {x = X; y = Y; } unsigned short x; /**< x coordinate */ unsigned short y; /**< y coordinate */ diff --git a/src/utils/timer.h b/src/utils/timer.h index da3a1d07..fdf021f6 100644 --- a/src/utils/timer.h +++ b/src/utils/timer.h @@ -4,19 +4,20 @@ * * 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 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. + * 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 + * 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_TIMER_H_ diff --git a/src/utils/wingettimeofday.h b/src/utils/wingettimeofday.h index 66cb100c..c19ef13e 100644 --- a/src/utils/wingettimeofday.h +++ b/src/utils/wingettimeofday.h @@ -4,19 +4,20 @@ * * 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 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. + * 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 + * 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_WINGETTIMEOFDAY_H_ @@ -28,7 +29,7 @@ /* * the function gettimeofday() is available on UNIX but not on windows. - * this header defines a windows implementation as a + * this header defines a windows implementation as a * GetSystemTimeAsFileTime() wrapper. */ |