diff options
Diffstat (limited to 'src')
31 files changed, 591 insertions, 670 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 221d7d8b..1273fe40 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -303,6 +303,7 @@ SET(SRCS gui/worldselectdialog.cpp gui/worldselectdialog.h net/adminhandler.h + net/charhandler.cpp net/charhandler.h net/chathandler.h net/download.cpp @@ -434,7 +435,6 @@ SET(SRCS keyboardconfig.h localplayer.cpp localplayer.h - lockedarray.h log.cpp log.h main.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 3b3773ab..8f7c7164 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -208,6 +208,7 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \ gui/worldselectdialog.cpp \ gui/worldselectdialog.h \ net/adminhandler.h \ + net/charhandler.cpp \ net/charhandler.h \ net/chathandler.h \ net/download.cpp \ @@ -339,7 +340,6 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \ keyboardconfig.h \ localplayer.cpp \ localplayer.h \ - lockedarray.h \ log.cpp \ log.h \ main.cpp \ diff --git a/src/being.cpp b/src/being.cpp index 42fb2d4e..495a81e0 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -814,10 +814,10 @@ int Being::getOffset(char pos, char neg) const if (mMap) { offset = (pos == LEFT && neg == RIGHT) ? - (int)((get_elapsed_time(mWalkTime) - * mMap->getTileWidth()) / mWalkSpeed.x) : - (int)((get_elapsed_time(mWalkTime) - * mMap->getTileHeight()) / mWalkSpeed.y); + (int)((get_elapsed_time(mWalkTime) + * mMap->getTileWidth()) / mWalkSpeed.x) : + (int)((get_elapsed_time(mWalkTime) + * mMap->getTileHeight()) / mWalkSpeed.y); } // We calculate the offset _from_ the _target_ location diff --git a/src/gui/charcreatedialog.cpp b/src/gui/charcreatedialog.cpp index 3d240271..8fb54f76 100644 --- a/src/gui/charcreatedialog.cpp +++ b/src/gui/charcreatedialog.cpp @@ -90,13 +90,13 @@ CharCreateDialog::CharCreateDialog(CharSelectDialog *parent, int slot): mFemale->addActionListener(this); mPlayerBox = new PlayerBox(mPlayer); - mPlayerBox->setWidth(74); mNameField->setActionEventId("create"); mNameField->addActionListener(this); - mAttributesLeft = new Label(strprintf(_("Please distribute %d points"), 99)); + mAttributesLeft = new Label( + strprintf(_("Please distribute %d points"), 99)); int w = 200; int h = 330; @@ -168,8 +168,9 @@ void CharCreateDialog::action(const gcn::ActionEvent &event) } Net::getCharHandler()->newCharacter(getName(), mSlot, - mFemale->isSelected(), mHairStyle, - mHairColor, atts); + mFemale->isSelected(), + mHairStyle, + mHairColor, atts); } else { @@ -246,11 +247,13 @@ void CharCreateDialog::updateSliders() mCreateButton->setEnabled(false); if (pointsLeft > 0) { - mAttributesLeft->setCaption(strprintf(_("Please distribute %d points"), pointsLeft)); + mAttributesLeft->setCaption( + strprintf(_("Please distribute %d points"), pointsLeft)); } else { - mAttributesLeft->setCaption(strprintf(_("Please remove %d points"), -pointsLeft)); + mAttributesLeft->setCaption( + strprintf(_("Please remove %d points"), -pointsLeft)); } } @@ -273,7 +276,7 @@ int CharCreateDialog::getDistributedPoints() const return points; } -void CharCreateDialog::setAttributes(std::vector<std::string> labels, +void CharCreateDialog::setAttributes(const std::vector<std::string> &labels, int available, int min, int max) { mMaxPoints = available; @@ -303,7 +306,8 @@ void CharCreateDialog::setAttributes(std::vector<std::string> labels, add(mAttributeLabel[i]); mAttributeSlider[i] = new Slider(min, max); - mAttributeSlider[i]->setDimension(gcn::Rectangle(75, 140 + i*20, 100, 10)); + mAttributeSlider[i]->setDimension(gcn::Rectangle(75, 140 + i * 20, + 100, 10)); mAttributeSlider[i]->setActionEventId("statslider"); mAttributeSlider[i]->addActionListener(this); add(mAttributeSlider[i]); @@ -346,11 +350,6 @@ void CharCreateDialog::setFixedGender(bool fixed, Gender gender) } } -void CharCreateDialog::success() -{ - mCharSelectDialog->update(mSlot); -} - void CharCreateDialog::updateHair() { mHairStyle %= Being::getNumOfHairstyles(); diff --git a/src/gui/charcreatedialog.h b/src/gui/charcreatedialog.h index c4838712..a6d4b49b 100644 --- a/src/gui/charcreatedialog.h +++ b/src/gui/charcreatedialog.h @@ -19,12 +19,11 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef CHAR_CREATE_H -#define CHAR_CREATE_H +#ifndef CHAR_CREATE_DIALOG_H +#define CHAR_CREATE_DIALOG_H #include "player.h" #include "guichanfwd.h" -#include "lockedarray.h" #include "gui/charselectdialog.h" @@ -63,19 +62,12 @@ class CharCreateDialog : public Window, public gcn::ActionListener */ void unlock(); - void setAttributes(std::vector<std::string> labels, int available, + void setAttributes(const std::vector<std::string> &labels, + int available, int min, int max); void setFixedGender(bool fixed, Gender gender = GENDER_FEMALE); - /** - * Notify the CharSelectDialog the character was created successfully. - */ - void success(); - - CharSelectDialog *getSelectDialog() const - { return mCharSelectDialog; } - private: int getDistributedPoints() const; @@ -127,4 +119,4 @@ class CharCreateDialog : public Window, public gcn::ActionListener int mSlot; }; -#endif // CHAR_CREATE_H +#endif // CHAR_CREATE_DIALOG_H diff --git a/src/gui/charselectdialog.cpp b/src/gui/charselectdialog.cpp index 0489a6cb..dd2368ef 100644 --- a/src/gui/charselectdialog.cpp +++ b/src/gui/charselectdialog.cpp @@ -25,6 +25,7 @@ #include "localplayer.h" #include "main.h" #include "units.h" +#include "log.h" #include "gui/changeemaildialog.h" #include "gui/changepassworddialog.h" @@ -56,6 +57,7 @@ #include <guichan/font.hpp> #include <string> +#include <cassert> /** * Listener for confirming character deletion. @@ -63,48 +65,45 @@ class CharDeleteConfirm : public ConfirmDialog { public: - CharDeleteConfirm(CharSelectDialog *m): + CharDeleteConfirm(CharSelectDialog *m, int index): ConfirmDialog(_("Confirm Character Delete"), _("Are you sure you want to delete this character?"), m), - master(m) + mMaster(m), + mIndex(index) { } void action(const gcn::ActionEvent &event) { - //ConfirmDialog::action(event); if (event.getId() == "yes") - { - master->attemptCharDelete(); - } + mMaster->attemptCharacterDelete(mIndex); + ConfirmDialog::action(event); } private: - CharSelectDialog *master; + CharSelectDialog *mMaster; + int mIndex; }; -class CharEntry : public Container +class CharacterDisplay : public Container { public: - CharEntry(CharSelectDialog *m, char slot, LocalPlayer *chr); + CharacterDisplay(CharSelectDialog *charSelectDialog); - char getSlot() const - { return mSlot; } + void setCharacter(Net::Character *character); - LocalPlayer *getChar() const + Net::Character *getCharacter() const { return mCharacter; } - void setChar(LocalPlayer *chr); - void requestFocus(); + void setActive(bool active); + + private: void update(); - protected: - friend class CharSelectDialog; - char mSlot; - LocalPlayer *mCharacter; + Net::Character *mCharacter; PlayerBox *mPlayerBox; Label *mName; @@ -114,10 +113,11 @@ class CharEntry : public Container Button *mDelete; }; -CharSelectDialog::CharSelectDialog(LockedArray<LocalPlayer*> *charInfo, - LoginData *loginData): +CharSelectDialog::CharSelectDialog(LoginData *loginData): Window(_("Account and Character Management")), - mCharInfo(charInfo), + mLocked(false), + mUnregisterButton(0), + mChangeEmailButton(0), mLoginData(loginData), mCharHandler(Net::getCharHandler()) { @@ -128,12 +128,6 @@ CharSelectDialog::CharSelectDialog(LockedArray<LocalPlayer*> *charInfo, mChangePasswordButton = new Button(_("Change Password"), "change_password", this); - for (int i = 0; i < MAX_CHARACTER_COUNT; i++) - { - charInfo->select(i); - mCharEntries[i] = new CharEntry(this, i, charInfo->getEntry()); - } - int optionalActions = Net::getLoginHandler()->supportedOptionalActions(); ContainerPlacer place; @@ -144,79 +138,85 @@ CharSelectDialog::CharSelectDialog(LockedArray<LocalPlayer*> *charInfo, if (optionalActions & Net::LoginHandler::Unregister) { - gcn::Button *unregisterButton = new Button(_("Unregister"), - "unregister", this); - place(3, 1, unregisterButton); + mUnregisterButton = new Button(_("Unregister"), + "unregister", this); + place(3, 1, mUnregisterButton); } place(0, 2, mChangePasswordButton); if (optionalActions & Net::LoginHandler::ChangeEmail) { - gcn::Button *changeEmailButton = new Button(_("Change Email"), - "change_email", this); - place(3, 2, changeEmailButton); + mChangeEmailButton = new Button(_("Change Email"), + "change_email", this); + place(3, 2, mChangeEmailButton); } place = getPlacer(0, 1); - place(0, 0, mCharEntries[0]); - place(1, 0, mCharEntries[1]); - place(2, 0, mCharEntries[2]); + + for (int i = 0; i < MAX_CHARACTER_COUNT; i++) { + mCharacterEntries[i] = new CharacterDisplay(this); + place(i, 0, mCharacterEntries[i]); + } reflowLayout(); addKeyListener(this); center(); - mCharEntries[0]->requestFocus(); + mCharacterEntries[0]->requestFocus(); setVisible(true); Net::getCharHandler()->setCharSelectDialog(this); } +CharSelectDialog::~CharSelectDialog() +{ +} + void CharSelectDialog::action(const gcn::ActionEvent &event) { + // Check if a button of a character was pressed const gcn::Widget *sourceParent = event.getSource()->getParent(); + int selected = -1; + for (unsigned i = 0; i < MAX_CHARACTER_COUNT; ++i) + if (mCharacterEntries[i] == sourceParent) + selected = i; - // Update which character is selected when applicable - if (const CharEntry *entry = dynamic_cast<const CharEntry*>(sourceParent)) - mCharInfo->select(entry->getSlot()); + const std::string &eventId = event.getId(); - if (event.getId() == "use") - { - chooseSelected(); - } - else if (event.getId() == "switch") + if (selected != -1) { - mCharInfo->clear(); - state = STATE_SWITCH_LOGIN; - } - else if (event.getId() == "new") - { - if (!(mCharInfo->getEntry())) + if (eventId == "use") + { + attemptCharacterSelect(selected); + } + else if (eventId == "new" && !mCharacterEntries[selected]->getCharacter()) { // Start new character dialog CharCreateDialog *charCreateDialog = - new CharCreateDialog(this, mCharInfo->getPos()); + new CharCreateDialog(this, selected); mCharHandler->setCharCreateDialog(charCreateDialog); } - } - else if (event.getId() == "delete") - { - if (mCharInfo->getEntry()) + else if (eventId == "delete" + && mCharacterEntries[selected]->getCharacter()) { - new CharDeleteConfirm(this); + new CharDeleteConfirm(this, selected); } } - else if (event.getId() == "change_password") + else if (eventId == "switch") + { + state = STATE_SWITCH_LOGIN; + } + else if (eventId == "change_password") { state = STATE_CHANGEPASSWORD; } - else if (event.getId() == "change_email") + else if (eventId == "change_email") { state = STATE_CHANGEEMAIL; } - else if (event.getId() == "unregister") + else if (eventId == "unregister") { state = STATE_UNREGISTER; } @@ -228,90 +228,111 @@ void CharSelectDialog::keyPressed(gcn::KeyEvent &keyEvent) if (key.getValue() == Key::ESCAPE) { - action(gcn::ActionEvent(mSwitchLoginButton, mSwitchLoginButton->getActionEventId())); + action(gcn::ActionEvent(mSwitchLoginButton, + mSwitchLoginButton->getActionEventId())); } } -void CharSelectDialog::attemptCharDelete() +/** + * Communicate character deletion to the server. + */ +void CharSelectDialog::attemptCharacterDelete(int index) { - mCharHandler->deleteCharacter(mCharInfo->getPos(), mCharInfo->getEntry()); - mCharInfo->lock(); + if (mLocked) + return; + + mCharHandler->deleteCharacter(mCharacterEntries[index]->getCharacter()); + lock(); } -void CharSelectDialog::attemptCharSelect() +/** + * Communicate character selection to the server. + */ +void CharSelectDialog::attemptCharacterSelect(int index) { - mCharHandler->chooseCharacter(mCharInfo->getPos(), mCharInfo->getEntry()); - mCharInfo->lock(); + if (mLocked) + return; + + mCharHandler->chooseCharacter(mCharacterEntries[index]->getCharacter()); + lock(); } -bool CharSelectDialog::selectByName(const std::string &name) +void CharSelectDialog::setCharacters(const Net::Characters &characters) { - if (mCharInfo->isLocked()) - return false; - - unsigned int oldPos = mCharInfo->getPos(); + // Reset previous characters + for (int i = 0; i < MAX_CHARACTER_COUNT; ++i) + mCharacterEntries[i]->setCharacter(0); - mCharInfo->select(0); - do + Net::Characters::const_iterator i, i_end = characters.end(); + for (i = characters.begin(); i != i_end; ++i) { - LocalPlayer *player = mCharInfo->getEntry(); - - if (player && player->getName() == name) - { - mCharEntries[mCharInfo->getPos()]->requestFocus(); - return true; + Net::Character *character = *i; + if (character->slot >= MAX_CHARACTER_COUNT) { + logger->log("Warning: slot out of range: %d", character->slot); + continue; } - mCharInfo->next(); - } while (mCharInfo->getPos()); + mCharacterEntries[character->slot]->setCharacter(character); + } +} - mCharInfo->select(oldPos); +void CharSelectDialog::lock() +{ + assert(!mLocked); + setLocked(true); +} - return false; +void CharSelectDialog::unlock() +{ + setLocked(false); } -bool CharSelectDialog::chooseSelected() +void CharSelectDialog::setLocked(bool locked) { - if (!mCharInfo->getSize()) - return false; + mLocked = locked; - setVisible(false); - attemptCharSelect(); + mSwitchLoginButton->setEnabled(!locked); + mChangePasswordButton->setEnabled(!locked); + if (mUnregisterButton) + mUnregisterButton->setEnabled(!locked); + if (mChangeEmailButton) + mChangeEmailButton->setEnabled(!locked); - return true; + for (int i = 0; i < MAX_CHARACTER_COUNT; ++i) + mCharacterEntries[i]->setActive(!mLocked); } -void CharSelectDialog::update(int slot) +bool CharSelectDialog::selectByName(const std::string &name, + SelectAction action) { - if (slot >= 0 && slot < MAX_CHARACTER_COUNT) - { - mCharInfo->select(slot); - mCharEntries[slot]->setChar(mCharInfo->getEntry()); - mCharEntries[slot]->requestFocus(); - } - else - { - int slot = mCharInfo->getPos(); - for (int i = 0; i < MAX_CHARACTER_COUNT; i++) - { - mCharInfo->select(slot); - mCharEntries[slot]->setChar(mCharInfo->getEntry()); + if (mLocked) + return false; + + for (unsigned i = 0; i < MAX_CHARACTER_COUNT; ++i) { + if (Net::Character *character = mCharacterEntries[i]->getCharacter()) { + if (character->dummy->getName() == name) { + mCharacterEntries[i]->requestFocus(); + if (action == Choose) + attemptCharacterSelect(i); + return true; + } } - mCharInfo->select(slot); } + + return false; } -CharEntry::CharEntry(CharSelectDialog *m, char slot, LocalPlayer *chr): - mSlot(slot), - mCharacter(chr), - mPlayerBox(new PlayerBox(chr)) + +CharacterDisplay::CharacterDisplay(CharSelectDialog *charSelectDialog): + mCharacter(0), + mPlayerBox(new PlayerBox) { - mButton = new Button("wwwwwwwww", "go", m); + mButton = new Button("wwwwwwwww", "go", charSelectDialog); mName = new Label("wwwwwwwwwwwwwwwwwwwwwwww"); mLevel = new Label("(888)"); mMoney = new Label("wwwwwwwww"); - mDelete = new Button(_("Delete"), "delete", m); + mDelete = new Button(_("Delete"), "delete", charSelectDialog); LayoutHelper h(this); ContainerPlacer place = h.getPlacer(0, 0); @@ -337,29 +358,37 @@ CharEntry::CharEntry(CharSelectDialog *m, char slot, LocalPlayer *chr): mMoney->getHeight() + mButton->getHeight() + mDelete->getHeight()); } -void CharEntry::setChar(LocalPlayer *chr) +void CharacterDisplay::setCharacter(Net::Character *character) { - mCharacter = chr; - - mPlayerBox->setPlayer(chr); + if (mCharacter == character) + return; + mCharacter = character; + mPlayerBox->setPlayer(character ? character->dummy : 0); update(); } -void CharEntry::requestFocus() +void CharacterDisplay::requestFocus() { mButton->requestFocus(); } -void CharEntry::update() +void CharacterDisplay::setActive(bool active) +{ + mButton->setEnabled(active); + mDelete->setEnabled(active); +} + +void CharacterDisplay::update() { if (mCharacter) { + const LocalPlayer *character = mCharacter->dummy; mButton->setCaption(_("Choose")); mButton->setActionEventId("use"); - mName->setCaption(strprintf("%s", mCharacter->getName().c_str())); - mLevel->setCaption(strprintf("Level %d", mCharacter->getLevel())); - mMoney->setCaption(Units::formatCurrency(mCharacter->getMoney())); + mName->setCaption(strprintf("%s", character->getName().c_str())); + mLevel->setCaption(strprintf("Level %d", character->getLevel())); + mMoney->setCaption(Units::formatCurrency(character->getMoney())); mDelete->setVisible(true); } diff --git a/src/gui/charselectdialog.h b/src/gui/charselectdialog.h index fa9591bf..9e455462 100644 --- a/src/gui/charselectdialog.h +++ b/src/gui/charselectdialog.h @@ -23,16 +23,17 @@ #define CHAR_SELECT_H #include "guichanfwd.h" -#include "lockedarray.h" #include "main.h" #include "player.h" #include "gui/widgets/window.h" +#include "net/charhandler.h" + #include <guichan/actionlistener.hpp> #include <guichan/keylistener.hpp> -class CharEntry; +class CharacterDisplay; class LocalPlayer; class LoginData; class PlayerBox; @@ -51,49 +52,55 @@ class CharSelectDialog : public Window, public gcn::ActionListener, { public: friend class CharDeleteConfirm; + friend class Net::CharHandler; /** * Constructor. */ - CharSelectDialog(LockedArray<LocalPlayer*> *charInfo, - LoginData *loginData); + CharSelectDialog(LoginData *loginData); - ~CharSelectDialog() { mCharInfo->clear(); }; + ~CharSelectDialog(); void action(const gcn::ActionEvent &event); void keyPressed(gcn::KeyEvent &keyEvent); - bool selectByName(const std::string &name); + enum SelectAction { + Focus, + Choose + }; /** - * Send selection to character server - * @return false if the selection or the number of existing character - * is empty. - */ - bool chooseSelected(); - - void update(int slot = -1); + * Attempt to select the character with the given name. Returns whether + * a character with the given name was found. + * + * \param action determines what to do when a character with the given + * name was found (just focus or also try to choose this + * character). + */ + bool selectByName(const std::string &name, + SelectAction action = Focus); private: - /** - * Communicate character deletion to the server. - */ - void attemptCharDelete(); + void attemptCharacterDelete(int index); + void attemptCharacterSelect(int index); - /** - * Communicate character selection to the server. - */ - void attemptCharSelect(); + void setCharacters(const Net::Characters &characters); + + void lock(); + void unlock(); + void setLocked(bool locked); - LockedArray<LocalPlayer*> *mCharInfo; + bool mLocked; gcn::Label *mAccountNameLabel; gcn::Button *mSwitchLoginButton; gcn::Button *mChangePasswordButton; + gcn::Button *mUnregisterButton; + gcn::Button *mChangeEmailButton; - CharEntry *mCharEntries[MAX_CHARACTER_COUNT]; + CharacterDisplay *mCharacterEntries[MAX_CHARACTER_COUNT]; LoginData *mLoginData; diff --git a/src/gui/unregisterdialog.cpp b/src/gui/unregisterdialog.cpp index 11cb2c57..95e7e5f5 100644 --- a/src/gui/unregisterdialog.cpp +++ b/src/gui/unregisterdialog.cpp @@ -91,8 +91,7 @@ UnRegisterDialog::~UnRegisterDialog() delete mWrongDataNoticeListener; } -void -UnRegisterDialog::action(const gcn::ActionEvent &event) +void UnRegisterDialog::action(const gcn::ActionEvent &event) { if (event.getId() == "cancel") { diff --git a/src/gui/widgets/playerbox.h b/src/gui/widgets/playerbox.h index 243668cf..d3329234 100644 --- a/src/gui/widgets/playerbox.h +++ b/src/gui/widgets/playerbox.h @@ -39,7 +39,7 @@ class PlayerBox : public gcn::ScrollArea * Constructor. Takes the initial player character that this box should * display, which defaults to <code>NULL</code>. */ - PlayerBox(const Player *player = NULL); + PlayerBox(const Player *player = 0); /** * Destructor. diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 4e70fc2f..30159f34 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -74,8 +74,8 @@ const short walkingKeyboardDelay = 1000; LocalPlayer *player_node = NULL; -LocalPlayer::LocalPlayer(int id, int job, Map *map): - Player(id, job, map), +LocalPlayer::LocalPlayer(int id, int job): + Player(id, job, 0), mEquipment(new Equipment), mInStorage(false), mAttackRange(0), @@ -795,7 +795,7 @@ void LocalPlayer::stopAttack() mLastTarget = -1; } -void LocalPlayer::raiseAttribute(size_t attr) +void LocalPlayer::raiseAttribute(int attr) { // we assume that the server allows the change. When not we will undo it later. mCharacterPoints--; @@ -805,7 +805,7 @@ void LocalPlayer::raiseAttribute(size_t attr) Net::getPlayerHandler()->increaseAttribute(attr); } -void LocalPlayer::lowerAttribute(size_t attr) +void LocalPlayer::lowerAttribute(int attr) { // we assume that the server allows the change. When not we will undo it later. mCorrectionPoints--; diff --git a/src/localplayer.h b/src/localplayer.h index d4aa258c..d9a56e34 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -105,7 +105,7 @@ class LocalPlayer : public Player /** * Constructor. */ - LocalPlayer(int id= 65535, int job = 0, Map *map = NULL); + LocalPlayer(int id= 65535, int job = 0); /** * Destructor. @@ -249,12 +249,12 @@ class LocalPlayer : public Player /** * Uses a character point to raise an attribute */ - void raiseAttribute(size_t attr); + void raiseAttribute(int attr); /** * Uses a correction point to lower an attribute */ - void lowerAttribute(size_t attr); + void lowerAttribute(int attr); void toggleSit(); void emote(Uint8 emotion); diff --git a/src/lockedarray.h b/src/lockedarray.h deleted file mode 100644 index 2190684f..00000000 --- a/src/lockedarray.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * The Mana World - * Copyright (C) 2004-2010 The Mana World Development Team - * - * This file is part of The Mana World. - * - * This program 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. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef LOCKEDARRAY_H -#define LOCKEDARRAY_H - -#include <algorithm> - -/** - * A _very_ basic array class that allows simple iteration and jumps, keeping - * its currently selected entry and providing a mechanism to lock this - * position. Anyone can unlock it though, so its your job to use it the right - * way ;) - */ - -template<class T> -class LockedArray -{ - public: - LockedArray(unsigned int size); - ~LockedArray(); - - void lock() { mLocked = true; }; - void unlock() { mLocked = false; }; - - bool isLocked() const { return mLocked; }; - - T getEntry() const { return mData[mCurEntry]; }; - void setEntry(T entry) { mData[mCurEntry] = entry; mFilled = true; }; - - void next(); - void prev(); - void select(unsigned int pos); - unsigned int getPos() const { return mCurEntry; } - - unsigned int getSize() const { return mSize; }; - - /** - * Clears the array without changing size or data type - */ - void clear(); - - protected: - unsigned int mSize; - - T* mData; - - unsigned int mCurEntry; - bool mLocked; - - bool mFilled; -}; - -template<class T> -LockedArray<T>::LockedArray(unsigned int size): - mSize(size), mData(new T[size]), mCurEntry(0), mLocked(false), - mFilled(false) -{ - std::fill_n(mData, mSize, (T)0); -} - -template<class T> -LockedArray<T>::~LockedArray() -{ - delete [] mData; -} - -template<class T> -void LockedArray<T>::next() -{ - if (mLocked) - return; - - if (++mCurEntry == mSize) - mCurEntry = 0; -} - -template<class T> -void LockedArray<T>::prev() -{ - if (mLocked) - return; - - mCurEntry = mCurEntry ? (--mCurEntry) : (mSize - 1); -} - -template<class T> -void LockedArray<T>::select(unsigned int pos) -{ - if (mLocked) - return; - - mCurEntry = pos; - if (mCurEntry >= mSize) - mCurEntry = 0; -} - -template<class T> -void LockedArray<T>::clear() -{ - if (!mFilled) return; - - delete [] mData; - - mData = new T[mSize]; - - std::fill_n(mData, mSize, (T)0); - - mCurEntry = 0; - - mLocked = false; -} -#endif diff --git a/src/main.cpp b/src/main.cpp index de133ecb..d4306f94 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,7 +28,6 @@ #include "itemshortcut.h" #include "keyboardconfig.h" #include "localplayer.h" -#include "lockedarray.h" #include "log.h" #ifdef USE_OPENGL #include "openglgraphics.h" @@ -135,7 +134,6 @@ Logger *logger; /**< Log object */ KeyboardConfig keyboard; LoginData loginData; -LockedArray<LocalPlayer*> charInfo(MAX_CHARACTER_COUNT); Palette *guiPalette; @@ -632,7 +630,7 @@ static void parseOptions(int argc, char *argv[], Options &options) class AccountListener : public gcn::ActionListener { public: - void action(const gcn::ActionEvent &event) + void action(const gcn::ActionEvent &) { state = STATE_CHAR_SELECT; } @@ -641,7 +639,7 @@ public: class LoginListener : public gcn::ActionListener { public: - void action(const gcn::ActionEvent &event) + void action(const gcn::ActionEvent &) { state = STATE_LOGIN; } @@ -649,7 +647,7 @@ public: } // namespace -void ErrorListener::action(const gcn::ActionEvent &event) +void ErrorListener::action(const gcn::ActionEvent &) { state = STATE_CHOOSE_SERVER; } @@ -664,8 +662,6 @@ static void accountLogin(LoginData *loginData) { logger->log("Username is %s", loginData->username.c_str()); - Net::getCharHandler()->setCharInfo(&charInfo); - // Send login infos if (loginData->registerLogin) Net::getLoginHandler()->registerAccount(loginData); @@ -847,7 +843,6 @@ int main(int argc, char *argv[]) oldstate != STATE_CHOOSE_SERVER && Net::getLoginHandler()->isConnected()) { - Net::getCharHandler()->setCharInfo(&charInfo); state = STATE_LOGIN; } else if (state == STATE_WORLD_SELECT && oldstate == STATE_UPDATE) @@ -1040,7 +1035,7 @@ int main(int argc, char *argv[]) case STATE_GET_CHARACTERS: logger->log("State: GET CHARACTERS"); - Net::getCharHandler()->getCharacters(); + Net::getCharHandler()->requestCharacters(); currentDialog = new ConnectionDialog( _("Requesting characters"), STATE_SWITCH_SERVER); @@ -1052,22 +1047,16 @@ int main(int argc, char *argv[]) // lower than the default value SkinLoader::instance()->setMinimumOpacity(0.8f); - currentDialog = - new CharSelectDialog(&charInfo, &loginData); + currentDialog = new CharSelectDialog(&loginData); - if (((CharSelectDialog*) currentDialog)-> - selectByName(options.character)) - { - ((CharSelectDialog*) currentDialog)->chooseSelected(); - } - else + if (!((CharSelectDialog*) currentDialog)->selectByName( + options.character, CharSelectDialog::Choose)) { - if (((CharSelectDialog*) currentDialog)->selectByName( - config.getValue("lastCharacter", ""))) - { - if (options.chooseDefault) - ((CharSelectDialog*) currentDialog)->chooseSelected(); - } + ((CharSelectDialog*) currentDialog)->selectByName( + config.getValue("lastCharacter", ""), + options.chooseDefault ? + CharSelectDialog::Choose : + CharSelectDialog::Focus); } break; @@ -1141,8 +1130,6 @@ int main(int argc, char *argv[]) case STATE_REGISTER_ATTEMPT: logger->log("Username is %s", loginData.username.c_str()); - - Net::getCharHandler()->setCharInfo(&charInfo); Net::getLoginHandler()->registerAccount(&loginData); break; @@ -1232,7 +1219,7 @@ int main(int argc, char *argv[]) // Done with game Net::getGameHandler()->disconnect(); - Net::getCharHandler()->getCharacters(); + Net::getCharHandler()->requestCharacters(); break; case STATE_LOGOUT_ATTEMPT: diff --git a/src/net/charhandler.cpp b/src/net/charhandler.cpp new file mode 100644 index 00000000..8cf756ba --- /dev/null +++ b/src/net/charhandler.cpp @@ -0,0 +1,38 @@ +/* + * The Mana World + * Copyright (C) 2010 The Mana World Development Team + * + * This file is part of The Mana World. + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "net/charhandler.h" + +#include "gui/charselectdialog.h" + +using namespace Net; + +void CharHandler::updateCharSelectDialog() +{ + if (mCharSelectDialog) + mCharSelectDialog->setCharacters(mCharacters); +} + +void CharHandler::unlockCharSelectDialog() +{ + if (mCharSelectDialog) + mCharSelectDialog->unlock(); +} diff --git a/src/net/charhandler.h b/src/net/charhandler.h index a55e8d86..dfe0882f 100644 --- a/src/net/charhandler.h +++ b/src/net/charhandler.h @@ -23,7 +23,6 @@ #define CHARHANDLER_H #include "localplayer.h" -#include "lockedarray.h" #include "logindata.h" #include <iosfwd> @@ -35,34 +34,73 @@ class LocalPlayer; namespace Net { +/** + * A structure to hold information about a character. + */ +struct Character +{ + Character() : + slot(0), + dummy(new LocalPlayer) + { + } + + ~Character() + { + delete dummy; + } + + int slot; /**< The index in the list of characters */ + LocalPlayer *dummy; /**< A dummy representing this character */ +}; + +typedef std::list<Character*> Characters; + class CharHandler { public: - virtual void setCharInfo(LockedArray<LocalPlayer*> *charInfo) = 0; - virtual void setCharSelectDialog(CharSelectDialog *window) = 0; virtual void setCharCreateDialog(CharCreateDialog *window) = 0; - virtual void getCharacters() = 0; + virtual void requestCharacters() = 0; - virtual void chooseCharacter(int slot, LocalPlayer *character) = 0; + virtual void chooseCharacter(Net::Character *character) = 0; virtual void newCharacter(const std::string &name, int slot, - bool gender, int hairstyle, int hairColor, - std::vector<int> stats) = 0; + bool gender, int hairstyle, int hairColor, + const std::vector<int> &stats) = 0; - virtual void deleteCharacter(int slot, LocalPlayer* character) = 0; + virtual void deleteCharacter(Net::Character *character) = 0; virtual void switchCharacter() = 0; - virtual unsigned int baseSprite() const = 0; + virtual int baseSprite() const = 0; - virtual unsigned int hairSprite() const = 0; + virtual int hairSprite() const = 0; - virtual unsigned int maxSprite() const = 0; + virtual int maxSprite() const = 0; virtual ~CharHandler() {} + + protected: + CharHandler(): + mSelectedCharacter(0), + mCharSelectDialog(0), + mCharCreateDialog(0) + {} + + void updateCharSelectDialog(); + void unlockCharSelectDialog(); + + /** The list of available characters. */ + Net::Characters mCharacters; + + /** The selected character. */ + Net::Character *mSelectedCharacter; + + CharSelectDialog *mCharSelectDialog; + CharCreateDialog *mCharCreateDialog; }; } // namespace Net diff --git a/src/net/ea/charserverhandler.cpp b/src/net/ea/charserverhandler.cpp index 106d0c8e..a49a55ac 100644 --- a/src/net/ea/charserverhandler.cpp +++ b/src/net/ea/charserverhandler.cpp @@ -39,6 +39,7 @@ #include "resources/colordb.h" +#include "utils/dtor.h" #include "utils/gettext.h" #include "utils/stringutils.h" @@ -49,9 +50,7 @@ namespace EAthena { extern ServerInfo charServer; extern ServerInfo mapServer; -CharServerHandler::CharServerHandler(): - mCharSelectDialog(0), - mCharCreateDialog(0) +CharServerHandler::CharServerHandler() { static const Uint16 _messages[] = { SMSG_CHAR_LOGIN, @@ -69,30 +68,32 @@ CharServerHandler::CharServerHandler(): void CharServerHandler::handleMessage(Net::MessageIn &msg) { - int count, slot; - LocalPlayer *tempPlayer; - logger->log("CharServerHandler: Packet ID: %x, Length: %d", - msg.getId(), msg.getLength()); + msg.getId(), msg.getLength()); + switch (msg.getId()) { - case SMSG_CHAR_LOGIN: - msg.skip(2); // Length word - msg.skip(20); // Unused + case SMSG_CHAR_LOGIN: + { + msg.skip(2); // Length word + msg.skip(20); // Unused - // Derive number of characters from message length - count = (msg.getLength() - 24) / 106; + // Derive number of characters from message length + const int count = (msg.getLength() - 24) / 106; - for (int i = 0; i < count; i++) - { - tempPlayer = readPlayerData(msg, slot); - mCharInfo->select(slot); - mCharInfo->setEntry(tempPlayer); - logger->log("CharServer: Player: %s (%d)", - tempPlayer->getName().c_str(), slot); - } + for (int i = 0; i < count; ++i) + { + Net::Character *character = new Net::Character; + int slot; + character->dummy = readPlayerData(msg, &slot); + character->slot = slot; + mCharacters.push_back(character); + logger->log("CharServer: Player: %s (%d)", + character->dummy->getName().c_str(), slot); + } - state = STATE_CHAR_SELECT; + state = STATE_CHAR_SELECT; + } break; case SMSG_CHAR_LOGIN_ERROR: @@ -108,81 +109,75 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg) errorMessage = _("Unknown failure to select character."); break; } - mCharInfo->unlock(); + unlockCharSelectDialog(); break; case SMSG_CHAR_CREATE_SUCCEEDED: - tempPlayer = readPlayerData(msg, slot); - mCharInfo->unlock(); - mCharInfo->select(slot); - mCharInfo->setEntry(tempPlayer); - - // Close the character create dialog - if (mCharCreateDialog) { - mCharCreateDialog->success(); - mCharCreateDialog->scheduleDelete(); - mCharCreateDialog = 0; + Net::Character *character = new Net::Character; + int slot; + character->dummy = readPlayerData(msg, &slot); + character->slot = slot; + mCharacters.push_back(character); + + updateCharSelectDialog(); + + // Close the character create dialog + if (mCharCreateDialog) + { + mCharCreateDialog->scheduleDelete(); + mCharCreateDialog = 0; + } } break; case SMSG_CHAR_CREATE_FAILED: new OkDialog(_("Error"), _("Failed to create character. Most " "likely the name is already taken.")); - if (mCharCreateDialog) mCharCreateDialog->unlock(); break; case SMSG_CHAR_DELETE_SUCCEEDED: - tempPlayer = mCharInfo->getEntry(); - mCharInfo->setEntry(0); - mCharInfo->unlock(); - if (mCharSelectDialog) - mCharSelectDialog->update(mCharInfo->getPos()); + delete mSelectedCharacter; + mCharacters.remove(mSelectedCharacter); + mSelectedCharacter = 0; + updateCharSelectDialog(); + unlockCharSelectDialog(); new OkDialog(_("Info"), _("Character deleted.")); - delete tempPlayer; break; case SMSG_CHAR_DELETE_FAILED: - mCharInfo->unlock(); + unlockCharSelectDialog(); new OkDialog(_("Error"), _("Failed to delete character.")); break; case SMSG_CHAR_MAP_INFO: - player_node = mCharInfo->getEntry(); - slot = mCharInfo->getPos(); msg.skip(4); // CharID, must be the same as player_node->charID map_path = msg.readString(16); mapServer.hostname = ipToString(msg.readInt32()); mapServer.port = msg.readInt16(); - mCharInfo->unlock(); - mCharInfo->select(0); - // Clear unselected players infos - do - { - LocalPlayer *tmp = mCharInfo->getEntry(); - if (tmp != player_node) - { - delete tmp; - mCharInfo->setEntry(0); - } - mCharInfo->next(); - } while (mCharInfo->getPos()); - mCharInfo->select(slot); + // Prevent the selected local player from being deleted + player_node = mSelectedCharacter->dummy; + mSelectedCharacter->dummy = 0; + + delete_all(mCharacters); + mCharacters.clear(); + updateCharSelectDialog(); + mNetwork->disconnect(); state = STATE_CONNECT_GAME; break; } } -LocalPlayer *CharServerHandler::readPlayerData(Net::MessageIn &msg, int &slot) +LocalPlayer *CharServerHandler::readPlayerData(Net::MessageIn &msg, int *slot) { const Token &token = static_cast<LoginHandler*>(Net::getLoginHandler())->getToken(); - LocalPlayer *tempPlayer = new LocalPlayer(msg.readInt32(), 0, NULL); + LocalPlayer *tempPlayer = new LocalPlayer(msg.readInt32(), 0); tempPlayer->setGender(token.sex); tempPlayer->setExp(msg.readInt32()); @@ -219,7 +214,7 @@ LocalPlayer *CharServerHandler::readPlayerData(Net::MessageIn &msg, int &slot) tempPlayer->setName(msg.readString(24)); for (int i = 0; i < 6; i++) tempPlayer->setAttributeBase(i + STR, msg.readInt8(), false); - slot = msg.readInt8(); // character slot + *slot = msg.readInt8(); // character slot msg.readInt8(); // unknown return tempPlayer; @@ -228,6 +223,7 @@ LocalPlayer *CharServerHandler::readPlayerData(Net::MessageIn &msg, int &slot) void CharServerHandler::setCharSelectDialog(CharSelectDialog *window) { mCharSelectDialog = window; + updateCharSelectDialog(); } void CharServerHandler::setCharCreateDialog(CharCreateDialog *window) @@ -252,19 +248,22 @@ void CharServerHandler::setCharCreateDialog(CharCreateDialog *window) mCharCreateDialog->setFixedGender(true, token.sex); } -void CharServerHandler::getCharacters() +void CharServerHandler::requestCharacters() { connect(); } -void CharServerHandler::chooseCharacter(int slot, LocalPlayer *) +void CharServerHandler::chooseCharacter(Net::Character *character) { + mSelectedCharacter = character; + MessageOut outMsg(CMSG_CHAR_SELECT); - outMsg.writeInt8(slot); + outMsg.writeInt8(mSelectedCharacter->slot); } void CharServerHandler::newCharacter(const std::string &name, int slot, - bool gender, int hairstyle, int hairColor, std::vector<int> stats) + bool gender, int hairstyle, int hairColor, + const std::vector<int> &stats) { MessageOut outMsg(CMSG_CHAR_CREATE); outMsg.writeString(name, 24); @@ -277,10 +276,12 @@ void CharServerHandler::newCharacter(const std::string &name, int slot, outMsg.writeInt16(hairstyle); } -void CharServerHandler::deleteCharacter(int slot, LocalPlayer *character) +void CharServerHandler::deleteCharacter(Net::Character *character) { + mSelectedCharacter = character; + MessageOut outMsg(CMSG_CHAR_DELETE); - outMsg.writeInt32(character->getId()); + outMsg.writeInt32(mSelectedCharacter->dummy->getId()); outMsg.writeString("a@a.com", 40); } @@ -291,17 +292,17 @@ void CharServerHandler::switchCharacter() outMsg.writeInt8(1); } -unsigned int CharServerHandler::baseSprite() const +int CharServerHandler::baseSprite() const { return SPRITE_BASE; } -unsigned int CharServerHandler::hairSprite() const +int CharServerHandler::hairSprite() const { return SPRITE_HAIR; } -unsigned int CharServerHandler::maxSprite() const +int CharServerHandler::maxSprite() const { return SPRITE_VECTOREND; } diff --git a/src/net/ea/charserverhandler.h b/src/net/ea/charserverhandler.h index b159c63b..d96da452 100644 --- a/src/net/ea/charserverhandler.h +++ b/src/net/ea/charserverhandler.h @@ -42,9 +42,6 @@ class CharServerHandler : public MessageHandler, public Net::CharHandler virtual void handleMessage(Net::MessageIn &msg); - void setCharInfo(LockedArray<LocalPlayer*> *charInfo) - { mCharInfo = charInfo; } - void setCharSelectDialog(CharSelectDialog *window); /** @@ -54,31 +51,28 @@ class CharServerHandler : public MessageHandler, public Net::CharHandler */ void setCharCreateDialog(CharCreateDialog *window); - void getCharacters(); + void requestCharacters(); - void chooseCharacter(int slot, LocalPlayer* character); + void chooseCharacter(Net::Character *character); void newCharacter(const std::string &name, int slot, bool gender, - int hairstyle, int hairColor, std::vector<int> stats); + int hairstyle, int hairColor, + const std::vector<int> &stats); - void deleteCharacter(int slot, LocalPlayer* character); + void deleteCharacter(Net::Character *character); void switchCharacter(); - unsigned int baseSprite() const; + int baseSprite() const; - unsigned int hairSprite() const; + int hairSprite() const; - unsigned int maxSprite() const; + int maxSprite() const; void connect(); - protected: - LockedArray<LocalPlayer*> *mCharInfo; - CharSelectDialog *mCharSelectDialog; - CharCreateDialog *mCharCreateDialog; - - LocalPlayer *readPlayerData(Net::MessageIn &msg, int &slot); + private: + LocalPlayer *readPlayerData(Net::MessageIn &msg, int *slot); }; } // namespace EAthena diff --git a/src/net/ea/playerhandler.cpp b/src/net/ea/playerhandler.cpp index 34e0daf4..8de15d2b 100644 --- a/src/net/ea/playerhandler.cpp +++ b/src/net/ea/playerhandler.cpp @@ -556,7 +556,7 @@ void PlayerHandler::emote(int emoteId) outMsg.writeInt8(emoteId); } -void PlayerHandler::increaseAttribute(size_t attr) +void PlayerHandler::increaseAttribute(int attr) { if (attr >= STR && attr <= LUK) { @@ -566,7 +566,7 @@ void PlayerHandler::increaseAttribute(size_t attr) } } -void PlayerHandler::decreaseAttribute(size_t attr) +void PlayerHandler::decreaseAttribute(int attr) { // Supported by eA? } diff --git a/src/net/ea/playerhandler.h b/src/net/ea/playerhandler.h index 9e7e9ac3..bbfbc74c 100644 --- a/src/net/ea/playerhandler.h +++ b/src/net/ea/playerhandler.h @@ -37,31 +37,23 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler void handleMessage(Net::MessageIn &msg); void attack(int id); - void emote(int emoteId); - void increaseAttribute(size_t attr); - - void decreaseAttribute(size_t attr); - + void increaseAttribute(int attr); + void decreaseAttribute(int attr); void increaseSkill(int skillId); void pickUp(FloorItem *floorItem); - void setDirection(char direction); - void setDestination(int x, int y, int direction = -1); - void changeAction(Being::Action action); void respawn(); void ignorePlayer(const std::string &player, bool ignore); - void ignoreAll(bool ignore); bool canUseMagic(); - bool canCorrectAttributes(); int getJobLocation(); diff --git a/src/net/manaserv/beinghandler.cpp b/src/net/manaserv/beinghandler.cpp index 5f9d1586..ae5bbc0e 100644 --- a/src/net/manaserv/beinghandler.cpp +++ b/src/net/manaserv/beinghandler.cpp @@ -114,7 +114,7 @@ Vector BeingHandler::giveSpeedInPixelsPerTicks(float speedInTilesPerSeconds) { speedInTicks.x = speedInTicks.y = 0; logger->log("Manaserv::BeingHandler: Speed wasn't given back" - " because game/Map not initialized."); + " because game/Map not initialized."); } // We don't use z for now. speedInTicks.z = 0; diff --git a/src/net/manaserv/charhandler.cpp b/src/net/manaserv/charhandler.cpp index 122ee10b..7a75e38d 100644 --- a/src/net/manaserv/charhandler.cpp +++ b/src/net/manaserv/charhandler.cpp @@ -41,25 +41,10 @@ #include "resources/colordb.h" +#include "utils/dtor.h" #include "utils/gettext.h" extern Net::CharHandler *charHandler; - -struct CharInfo { - unsigned char slot; - std::string name; - Gender gender; - int hs, hc; - unsigned short level; - unsigned short charPoints; - unsigned short corrPoints; - unsigned int money; - unsigned char attr[7]; -}; - -typedef std::vector<CharInfo> CharInfos; -CharInfos chars; - extern ManaServ::GameHandler *gameHandler; namespace ManaServ { @@ -71,9 +56,7 @@ extern std::string netToken; extern ServerInfo gameServer; extern ServerInfo chatServer; -CharHandler::CharHandler(): - mCharSelectDialog(0), - mCharCreateDialog(0) +CharHandler::CharHandler() { static const Uint16 _messages[] = { APMSG_CHAR_CREATE_RESPONSE, @@ -91,104 +74,54 @@ void CharHandler::handleMessage(Net::MessageIn &msg) switch (msg.getId()) { case APMSG_CHAR_CREATE_RESPONSE: - handleCharCreateResponse(msg); + handleCharacterCreateResponse(msg); break; case APMSG_CHAR_DELETE_RESPONSE: - { - int errMsg = msg.readInt8(); - // Character deletion successful - if (errMsg == ERRMSG_OK) - { - LocalPlayer *tempPlayer = mCharInfo->getEntry(); - mCharInfo->setEntry(0); - mCharInfo->unlock(); - if (mCharSelectDialog) - mCharSelectDialog->update(mCharInfo->getPos()); - new OkDialog(_("Info"), _("Player deleted.")); - delete tempPlayer; - } - // Character deletion failed - else - { - std::string errorMessage = ""; - switch (errMsg) - { - case ERRMSG_NO_LOGIN: - errorMessage = _("Not logged in."); - break; - case ERRMSG_INVALID_ARGUMENT: - errorMessage = _("Selection out of range."); - break; - default: - errorMessage = _("Unknown error."); - } - mCharInfo->unlock(); - new OkDialog(_("Error"), errorMessage); - } - } + handleCharacterDeleteResponse(msg); break; case APMSG_CHAR_INFO: - { - CharInfo info; - info.slot = msg.readInt8(); // character slot - info.name = msg.readString(); - info.gender = msg.readInt8() == GENDER_MALE ? GENDER_MALE : - GENDER_FEMALE; - info.hs = msg.readInt8(); - info.hc = msg.readInt8(); - info.level = msg.readInt16(); - info.charPoints = msg.readInt16(); - info.corrPoints = msg.readInt16(); - info.money = msg.readInt32(); - - for (int i = 0; i < 7; i++) - { - info.attr[i] = msg.readInt8(); - } - - chars.push_back(info); - - if (mCharSelectDialog) - { - mCharInfo->select(info.slot); - - LocalPlayer *tempPlayer = new LocalPlayer(); - tempPlayer->setName(info.name); - tempPlayer->setGender(info.gender); - tempPlayer->setSprite(SPRITE_HAIR, info.hs * -1, - ColorDB::get(info.hc)); - tempPlayer->setLevel(info.level); - tempPlayer->setCharacterPoints(info.charPoints); - tempPlayer->setCorrectionPoints(info.corrPoints); - tempPlayer->setMoney(info.money); - - for (int i = 0; i < 7; i++) - { - tempPlayer->setAttributeBase(i, info.attr[i], false); - } - - mCharInfo->setEntry(tempPlayer); - - mCharSelectDialog->update(info.slot); - } - } + handleCharacterInfo(msg); break; case APMSG_CHAR_SELECT_RESPONSE: - handleCharSelectResponse(msg); + handleCharacterSelectResponse(msg); break; } } -void CharHandler::handleCharCreateResponse(Net::MessageIn &msg) +void CharHandler::handleCharacterInfo(Net::MessageIn &msg) { - int errMsg = msg.readInt8(); + CachedCharacterInfo info; + info.slot = msg.readInt8(); + info.name = msg.readString(); + info.gender = msg.readInt8() == GENDER_MALE ? GENDER_MALE : + GENDER_FEMALE; + info.hairStyle = msg.readInt8(); + info.hairColor = msg.readInt8(); + info.level = msg.readInt16(); + info.characterPoints = msg.readInt16(); + info.correctionPoints = msg.readInt16(); + info.money = msg.readInt32(); + + for (int i = 0; i < 7; i++) + { + info.attribute[i] = msg.readInt8(); + } + + mCachedCharacterInfos.push_back(info); + + updateCharacters(); +} + +void CharHandler::handleCharacterCreateResponse(Net::MessageIn &msg) +{ + const int errMsg = msg.readInt8(); - // Character creation failed if (errMsg != ERRMSG_OK) { + // Character creation failed std::string errorMessage = ""; switch (errMsg) { @@ -233,17 +166,48 @@ void CharHandler::handleCharCreateResponse(Net::MessageIn &msg) } else { + // Close the character create dialog if (mCharCreateDialog) { - mCharCreateDialog->success(); mCharCreateDialog->scheduleDelete(); mCharCreateDialog = 0; } } +} +void CharHandler::handleCharacterDeleteResponse(Net::MessageIn &msg) +{ + int errMsg = msg.readInt8(); + if (errMsg == ERRMSG_OK) + { + // Character deletion successful + delete mSelectedCharacter; + mCharacters.remove(mSelectedCharacter); + updateCharSelectDialog(); + unlockCharSelectDialog(); + new OkDialog(_("Info"), _("Player deleted.")); + } + else + { + // Character deletion failed + std::string errorMessage = ""; + switch (errMsg) + { + case ERRMSG_NO_LOGIN: + errorMessage = _("Not logged in."); + break; + case ERRMSG_INVALID_ARGUMENT: + errorMessage = _("Selection out of range."); + break; + default: + errorMessage = strprintf(_("Unknown error (%d)."), errMsg); + } + new OkDialog(_("Error"), errorMessage); + } + mSelectedCharacter = 0; } -void CharHandler::handleCharSelectResponse(Net::MessageIn &msg) +void CharHandler::handleCharacterSelectResponse(Net::MessageIn &msg) { int errMsg = msg.readInt8(); @@ -265,31 +229,20 @@ void CharHandler::handleCharSelectResponse(Net::MessageIn &msg) gameServerConnection->connect(gameServer.hostname, gameServer.port); chatServerConnection->connect(chatServer.hostname, chatServer.port); - // Keep the selected character and delete the others - player_node = mCharInfo->getEntry(); - int slot = mCharInfo->getPos(); - mCharInfo->unlock(); - mCharInfo->select(0); - - do { - LocalPlayer *tmp = mCharInfo->getEntry(); - if (tmp != player_node) - { - delete tmp; - mCharInfo->setEntry(0); - } - mCharInfo->next(); - } while (mCharInfo->getPos()); - mCharInfo->select(slot); - - mCharInfo->clear(); //player_node will be deleted by ~Game + // Prevent the selected local player from being deleted + player_node = mSelectedCharacter->dummy; + mSelectedCharacter->dummy = 0; + + mCachedCharacterInfos.clear(); + updateCharacters(); state = STATE_CONNECT_GAME; } - else if(errMsg == ERRMSG_FAILURE) + else if (errMsg == ERRMSG_FAILURE) { errorMessage = _("No gameservers are available."); - mCharInfo->clear(); + delete_all(mCharacters); + mCharacters.clear(); state = STATE_ERROR; } } @@ -297,13 +250,15 @@ void CharHandler::handleCharSelectResponse(Net::MessageIn &msg) void CharHandler::setCharSelectDialog(CharSelectDialog *window) { mCharSelectDialog = window; + updateCharacters(); } void CharHandler::setCharCreateDialog(CharCreateDialog *window) { mCharCreateDialog = window; - if (!mCharCreateDialog) return; + if (!mCharCreateDialog) + return; std::vector<std::string> attributes; attributes.push_back(_("Strength:")); @@ -316,59 +271,34 @@ void CharHandler::setCharCreateDialog(CharCreateDialog *window) mCharCreateDialog->setAttributes(attributes, 60, 1, 20); } -void CharHandler::getCharacters() +void CharHandler::requestCharacters() { if (!accountServerConnection->isConnected()) + { Net::getLoginHandler()->connect(); + } else { - mCharInfo->unlock(); - LocalPlayer *tempPlayer; - for (CharInfos::const_iterator it = chars.begin(); it != chars.end(); it++) - { - const CharInfo info = (CharInfo) (*it); - mCharInfo->select(info.slot); - - tempPlayer = new LocalPlayer(); - tempPlayer->setName(info.name); - tempPlayer->setGender(info.gender); - tempPlayer->setSprite(SPRITE_HAIR, info.hs * -1, - ColorDB::get(info.hc)); - tempPlayer->setLevel(info.level); - tempPlayer->setCharacterPoints(info.charPoints); - tempPlayer->setCorrectionPoints(info.corrPoints); - tempPlayer->setMoney(info.money); - - for (int i = 0; i < 7; i++) - { - tempPlayer->setAttributeBase(i, info.attr[i], false); - } - - mCharInfo->setEntry(tempPlayer); - } - - // Close the character create dialog - if (mCharCreateDialog) - { - mCharCreateDialog->scheduleDelete(); - mCharCreateDialog = 0; - } - + // The characters are already there, continue to character selection state = STATE_CHAR_SELECT; } } -void CharHandler::chooseCharacter(int slot, LocalPlayer* character) +void CharHandler::chooseCharacter(Net::Character *character) { - MessageOut msg(PAMSG_CHAR_SELECT); - - msg.writeInt8(slot); + mSelectedCharacter = character; + MessageOut msg(PAMSG_CHAR_SELECT); + msg.writeInt8(mSelectedCharacter->slot); accountServerConnection->send(msg); } -void CharHandler::newCharacter(const std::string &name, int slot, bool gender, - int hairstyle, int hairColor, std::vector<int> stats) +void CharHandler::newCharacter(const std::string &name, + int /* slot */, + bool gender, + int hairstyle, + int hairColor, + const std::vector<int> &stats) { MessageOut msg(PAMSG_CHAR_CREATE); @@ -386,12 +316,12 @@ void CharHandler::newCharacter(const std::string &name, int slot, bool gender, accountServerConnection->send(msg); } -void CharHandler::deleteCharacter(int slot, LocalPlayer* character) +void CharHandler::deleteCharacter(Net::Character *character) { - MessageOut msg(PAMSG_CHAR_DELETE); - - msg.writeInt8(slot); + mSelectedCharacter = character; + MessageOut msg(PAMSG_CHAR_DELETE); + msg.writeInt8(mSelectedCharacter->slot); accountServerConnection->send(msg); } @@ -400,19 +330,56 @@ void CharHandler::switchCharacter() gameHandler->quit(true); } -unsigned int CharHandler::baseSprite() const +int CharHandler::baseSprite() const { return SPRITE_BASE; } -unsigned int CharHandler::hairSprite() const +int CharHandler::hairSprite() const { return SPRITE_HAIR; } -unsigned int CharHandler::maxSprite() const +int CharHandler::maxSprite() const { return SPRITE_VECTOREND; } +void CharHandler::updateCharacters() +{ + // Delete previous characters + delete_all(mCharacters); + mCharacters.clear(); + + if (!mCharSelectDialog) + return; + + // Create new characters and initialize them from the cached infos + for (unsigned i = 0; i < mCachedCharacterInfos.size(); ++i) + { + const CachedCharacterInfo &info = mCachedCharacterInfos.at(i); + + Net::Character *character = new Net::Character; + character->slot = info.slot; + LocalPlayer *player = character->dummy; + player->setName(info.name); + player->setGender(info.gender); + player->setSprite(SPRITE_HAIR, info.hairStyle * -1, + ColorDB::get(info.hairColor)); + player->setLevel(info.level); + player->setCharacterPoints(info.characterPoints); + player->setCorrectionPoints(info.correctionPoints); + player->setMoney(info.money); + + for (int i = 0; i < 7; i++) + { + player->setAttributeBase(i, info.attribute[i], false); + } + + mCharacters.push_back(character); + } + + updateCharSelectDialog(); +} + } // namespace ManaServ diff --git a/src/net/manaserv/charhandler.h b/src/net/manaserv/charhandler.h index 74f68f55..4a1af307 100644 --- a/src/net/manaserv/charhandler.h +++ b/src/net/manaserv/charhandler.h @@ -42,11 +42,6 @@ class CharHandler : public MessageHandler, public Net::CharHandler void handleMessage(Net::MessageIn &msg); - void setCharInfo(LockedArray<LocalPlayer*> *charInfo) - { - mCharInfo = charInfo; - } - void setCharSelectDialog(CharSelectDialog *window); /** @@ -56,32 +51,52 @@ class CharHandler : public MessageHandler, public Net::CharHandler */ void setCharCreateDialog(CharCreateDialog *window); - void getCharacters(); + void requestCharacters(); - void chooseCharacter(int slot, LocalPlayer* character); + void chooseCharacter(Net::Character *character); void newCharacter(const std::string &name, int slot, - bool gender, int hairstyle, int hairColor, - std::vector<int> stats); + bool gender, int hairstyle, int hairColor, + const std::vector<int> &stats); - void deleteCharacter(int slot, LocalPlayer* character); + void deleteCharacter(Net::Character *character); void switchCharacter(); - unsigned int baseSprite() const; - - unsigned int hairSprite() const; - - unsigned int maxSprite() const; + int baseSprite() const; - protected: - void handleCharCreateResponse(Net::MessageIn &msg); + int hairSprite() const; - void handleCharSelectResponse(Net::MessageIn &msg); + int maxSprite() const; - LockedArray<LocalPlayer*> *mCharInfo; - CharSelectDialog *mCharSelectDialog; - CharCreateDialog *mCharCreateDialog; + private: + /** + * Character information needs to be cached since we receive it before + * we have loaded the dynamic data, so we can't resolve load any + * sprites yet. + */ + struct CachedCharacterInfo { + int slot; + std::string name; + Gender gender; + int hairStyle; + int hairColor; + int level; + int characterPoints; + int correctionPoints; + int money; + int attribute[7]; + }; + + void handleCharacterInfo(Net::MessageIn &msg); + void handleCharacterCreateResponse(Net::MessageIn &msg); + void handleCharacterDeleteResponse(Net::MessageIn &msg); + void handleCharacterSelectResponse(Net::MessageIn &msg); + + void updateCharacters(); + + /** Cached character information */ + std::vector<CachedCharacterInfo> mCachedCharacterInfos; }; } // namespace ManaServ diff --git a/src/net/manaserv/inventoryhandler.cpp b/src/net/manaserv/inventoryhandler.cpp index 0020a4e7..3ce1aa6f 100644 --- a/src/net/manaserv/inventoryhandler.cpp +++ b/src/net/manaserv/inventoryhandler.cpp @@ -61,7 +61,7 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) { case GPMSG_INVENTORY_FULL: player_node->clearInventory(); - player_node->mEquipment->setBackend(&mEqiups); + player_node->mEquipment->setBackend(&mEquips); // no break! case GPMSG_INVENTORY: @@ -77,7 +77,7 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) int id = msg.readInt16(); if (slot < EQUIPMENT_SIZE) { - mEqiups.setEquipment(slot, id); + mEquips.setEquipment(slot, id); } else if (slot >= 32 && slot < 32 + getSize(INVENTORY)) { @@ -105,7 +105,7 @@ void InventoryHandler::unequipItem(const Item *item) // Tidy equipment directly to avoid weapon still shown bug, for instance int equipSlot = item->getInvIndex(); logger->log("Unequipping %d", equipSlot); - mEqiups.setEquipment(equipSlot, 0); + mEquips.setEquipment(equipSlot, 0); } void InventoryHandler::useItem(const Item *item) diff --git a/src/net/manaserv/inventoryhandler.h b/src/net/manaserv/inventoryhandler.h index 362e392a..402af3b5 100644 --- a/src/net/manaserv/inventoryhandler.h +++ b/src/net/manaserv/inventoryhandler.h @@ -30,7 +30,8 @@ namespace ManaServ { -class EquipBackend : public Equipment::Backend { +class EquipBackend : public Equipment::Backend +{ public: EquipBackend() { memset(mEquipment, 0, sizeof(mEquipment)); } @@ -97,7 +98,7 @@ class InventoryHandler : public MessageHandler, Net::InventoryHandler size_t getSize(StorageType type) const; private: - EquipBackend mEqiups; + EquipBackend mEquips; }; } // namespace ManaServ diff --git a/src/net/manaserv/itemhandler.cpp b/src/net/manaserv/itemhandler.cpp index 802f9303..c939589e 100644 --- a/src/net/manaserv/itemhandler.cpp +++ b/src/net/manaserv/itemhandler.cpp @@ -58,12 +58,9 @@ void ItemHandler::handleMessage(Net::MessageIn &msg) if (itemId) { - Game *game = Game::instance(); - Map *map = 0; - if (game) + if (Game *game = Game::instance()) { - map = game->getCurrentMap(); - if (map) + if (Map *map = game->getCurrentMap()) { floorItemManager->create(id, itemId, @@ -71,9 +68,11 @@ void ItemHandler::handleMessage(Net::MessageIn &msg) y / map->getTileHeight()); } else - logger->log( - "ItemHandler: An item wasn't created because of" - "Game/Map not initialized..."); + { + logger->log( + "ItemHandler: An item wasn't created " + "because of Game/Map not initialized..."); + } } } else if (FloorItem *item = floorItemManager->findById(id)) diff --git a/src/net/manaserv/loginhandler.cpp b/src/net/manaserv/loginhandler.cpp index 63195816..9d8bc0e2 100644 --- a/src/net/manaserv/loginhandler.cpp +++ b/src/net/manaserv/loginhandler.cpp @@ -64,9 +64,11 @@ void LoginHandler::handleMessage(Net::MessageIn &msg) case APMSG_LOGIN_RESPONSE: handleLoginResponse(msg); break; + case APMSG_REGISTER_RESPONSE: handleRegisterResponse(msg); break; + case APMSG_RECONNECT_RESPONSE: { int errMsg = msg.readInt8(); diff --git a/src/net/manaserv/playerhandler.cpp b/src/net/manaserv/playerhandler.cpp index bff9512e..56502ec1 100644 --- a/src/net/manaserv/playerhandler.cpp +++ b/src/net/manaserv/playerhandler.cpp @@ -306,14 +306,14 @@ void PlayerHandler::emote(int emoteId) // TODO } -void PlayerHandler::increaseAttribute(size_t attr) +void PlayerHandler::increaseAttribute(int attr) { MessageOut msg(PGMSG_RAISE_ATTRIBUTE); msg.writeInt8(attr); gameServerConnection->send(msg); } -void PlayerHandler::decreaseAttribute(size_t attr) +void PlayerHandler::decreaseAttribute(int attr) { MessageOut msg(PGMSG_LOWER_ATTRIBUTE); msg.writeInt8(attr); diff --git a/src/net/manaserv/playerhandler.h b/src/net/manaserv/playerhandler.h index 6edc96bb..65170d63 100644 --- a/src/net/manaserv/playerhandler.h +++ b/src/net/manaserv/playerhandler.h @@ -44,31 +44,23 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler void handleMessage(Net::MessageIn &msg); void attack(int id); - void emote(int emoteId); - void increaseAttribute(size_t attr); - - void decreaseAttribute(size_t attr); - + void increaseAttribute(int attr); + void decreaseAttribute(int attr); void increaseSkill(int skillId); void pickUp(FloorItem *floorItem); - void setDirection(char direction); - void setDestination(int x, int y, int direction = -1); - void changeAction(Being::Action action); void respawn(); void ignorePlayer(const std::string &player, bool ignore); - void ignoreAll(bool ignore); bool canUseMagic(); - bool canCorrectAttributes(); int getJobLocation(); diff --git a/src/net/playerhandler.h b/src/net/playerhandler.h index 0174ede2..c2ecd2d0 100644 --- a/src/net/playerhandler.h +++ b/src/net/playerhandler.h @@ -35,9 +35,9 @@ class PlayerHandler virtual void emote(int emoteId) = 0; - virtual void increaseAttribute(size_t attr) = 0; + virtual void increaseAttribute(int attr) = 0; - virtual void decreaseAttribute(size_t attr) = 0; + virtual void decreaseAttribute(int attr) = 0; virtual void increaseSkill(int skillId) = 0; diff --git a/src/player.cpp b/src/player.cpp index e537a2b9..2f6b14e9 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -49,7 +49,7 @@ Player::Player(int id, int job, Map *map, bool isNPC): { if (!isNPC) { - for (unsigned int i = 0; i < Net::getCharHandler()->maxSprite(); i++) + for (int i = 0; i < Net::getCharHandler()->maxSprite(); i++) { mSprites.push_back(NULL); mSpriteIDs.push_back(0); @@ -157,7 +157,7 @@ void Player::setGM(bool gm) updateColors(); } -void Player::setSprite(unsigned int slot, int id, const std::string &color, +void Player::setSprite(int slot, int id, const std::string &color, bool isWeapon) { if (getType() == NPC) diff --git a/src/player.h b/src/player.h index 6e2566b8..34963cf4 100644 --- a/src/player.h +++ b/src/player.h @@ -75,7 +75,7 @@ class Player : public Being /** * Sets visible equipments for this player. */ - virtual void setSprite(unsigned int slot, int id, + virtual void setSprite(int slot, int id, const std::string &color = "", bool isWeapon = false); |