diff options
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. */ |