summaryrefslogtreecommitdiff
path: root/src/gui/charselectdialog.cpp
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <thorbjorn@lindeijer.nl>2010-02-19 22:38:59 +0100
committerThorbjørn Lindeijer <thorbjorn@lindeijer.nl>2010-02-19 23:37:36 +0100
commit363527d0f95963ba3f4a6d25c8eabc1bb3ad4efe (patch)
tree117ce95d3587f913a64b71fe4dcdee716b8aea7e /src/gui/charselectdialog.cpp
parent432d16435774cafd630e287321e882f3e8510d16 (diff)
downloadmana-363527d0f95963ba3f4a6d25c8eabc1bb3ad4efe.tar.gz
mana-363527d0f95963ba3f4a6d25c8eabc1bb3ad4efe.tar.bz2
mana-363527d0f95963ba3f4a6d25c8eabc1bb3ad4efe.tar.xz
mana-363527d0f95963ba3f4a6d25c8eabc1bb3ad4efe.zip
Fixed a crash when trying to switch servers
Ownership of the charInfo global variable wasn't well defined. It was being locked, unlocked and generally modified from a lot of places, and somewhere in this mess it ended up crashing when switching servers. Now the CharHandler instances, for eAthena and manaserv respectively, own this list of characters. A new class, Net::Character wraps up the slot index in combination with the player dummy. The list is passed on to the CharSelectDialog each time it changes. Both related and unrelated cleanups were made as well. Reviewed-by: Jared Adams
Diffstat (limited to 'src/gui/charselectdialog.cpp')
-rw-r--r--src/gui/charselectdialog.cpp269
1 files changed, 149 insertions, 120 deletions
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);
}