From 5f0ebee0d4d75fa91d417f4f352abdbc7502c2f0 Mon Sep 17 00:00:00 2001 From: Björn Steinbrink Date: Thu, 2 Nov 2006 12:43:49 +0000 Subject: Network layer refactoring. --- src/net/chatserver/chatserver.h | 55 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/net/chatserver/chatserver.h (limited to 'src/net/chatserver/chatserver.h') diff --git a/src/net/chatserver/chatserver.h b/src/net/chatserver/chatserver.h new file mode 100644 index 00000000..93fe17c4 --- /dev/null +++ b/src/net/chatserver/chatserver.h @@ -0,0 +1,55 @@ +/* + * The Mana World + * 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 _TMW_NET_CHATSERVER_CHATSERVER_H +#define _TMW_NET_CHATSERVER_CHATSERVER_H + +#include + +namespace Net +{ + class Connection; + + namespace ChatServer + { + void connect(Net::Connection *connection, const std::string &token); + + void chat(short channel, const std::string &text); + + void announce(const std::string &text); + + void privMsg(const std::string &recipient, const std::string &text); + + void registerChannel(const std::string &name, + const std::string &announcement, const std::string &password, + char isPrivate); + + void unregisterChannel(short channel); + + void enterChannel(short channel, const std::string &password); + + void quitChannel(short channel); + } +} + +#endif -- cgit v1.2.3-70-g09d2 From 775404c84c3250225d43f10c4a5363e997618cb2 Mon Sep 17 00:00:00 2001 From: Rogier Polak Date: Fri, 23 Feb 2007 19:18:28 +0000 Subject: Added unregistering, logout_then_exit, switch_character and switch_accountserver. --- ChangeLog | 20 ++- src/Makefile.am | 6 + src/game.cpp | 42 ++---- src/gui/char_select.cpp | 23 +++- src/gui/char_select.h | 8 +- src/gui/login.cpp | 2 +- src/gui/quitdialog.cpp | 129 ++++++++++++++++++ src/gui/quitdialog.h | 71 ++++++++++ src/gui/serverdialog.cpp | 2 +- src/gui/unregisterdialog.cpp | 171 ++++++++++++++++++++++++ src/gui/unregisterdialog.h | 73 ++++++++++ src/lockedarray.h | 27 +++- src/logindata.h | 9 ++ src/main.cpp | 230 +++++++++++++++++++++++++++++--- src/main.h | 13 +- src/net/accountserver/account.cpp | 7 +- src/net/accountserver/account.h | 5 +- src/net/accountserver/accountserver.cpp | 10 +- src/net/accountserver/accountserver.h | 3 + src/net/chatserver/chatserver.cpp | 7 + src/net/chatserver/chatserver.h | 2 + src/net/connection.cpp | 3 +- src/net/gameserver/gameserver.cpp | 9 ++ src/net/gameserver/gameserver.h | 2 + src/net/loginhandler.cpp | 30 +++++ src/net/logouthandler.cpp | 216 ++++++++++++++++++++++++++++++ src/net/logouthandler.h | 63 +++++++++ src/net/protocol.h | 10 +- 28 files changed, 1127 insertions(+), 66 deletions(-) create mode 100644 src/gui/quitdialog.cpp create mode 100644 src/gui/quitdialog.h create mode 100644 src/gui/unregisterdialog.cpp create mode 100644 src/gui/unregisterdialog.h create mode 100644 src/net/logouthandler.cpp create mode 100644 src/net/logouthandler.h (limited to 'src/net/chatserver/chatserver.h') diff --git a/ChangeLog b/ChangeLog index f33e6a6b..d2a98990 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,20 @@ -2007-01-30 Bjørn Lindeijer +2007-02-23 Rogier Polak + + * src/gui/char_select.h, src/gui/char_select.cpp, + src/gui/unregisterdialog.h, src/gui/unregisterdialog.cpp, + src/net/accountserver/account.h, src/net/accountserver/account.cpp, + src/gui/quitdialog.h, src/gui/quitdialog.cpp, + src/net/accountserver/accountserver.h, + src/net/accountserver/accountserver.cpp, src/net/loginhandler.cpp, + src/net/logouthandler.h, src/net/logouthandler.cpp, src/net/protocol.h, + src/net/gameserver/gameserver.h, src/net/gameserver/gameserver.cpp, + src/game.cpp, src/main.h, src/main.cpp: Added unregistering, + logout_then_exit, switch_character and switch_accountserver. + * src/lockedarray.h: Added a clear function that keeps the original + size and data type. + * src/logindata.h: Added a clear function. + +2007-01-30 Bjørn Lindeijer * src/properties.h, src/being.cpp, src/beingmanager.h, src/sound.h, src/gui/window.h, src/sound.cpp, src/main.h, src/being.h, @@ -314,7 +330,7 @@ 2006-12-15 Philipp Sehmisch - * data/graphics/tiles/desert1.png: Removed some unused legacy tiles and + * data/graphics/tiles/desert1.png: Removed some unused legacy tiles and added variant tiles for the cliffs. 2006-12-14 Bjørn Lindeijer diff --git a/src/Makefile.am b/src/Makefile.am index 777cc30e..cb0345e5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -72,6 +72,8 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \ gui/popupmenu.h \ gui/progressbar.cpp \ gui/progressbar.h \ + gui/quitdialog.cpp \ + gui/quitdialog.h \ gui/radiobutton.cpp \ gui/radiobutton.h \ gui/register.cpp \ @@ -110,6 +112,8 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \ gui/textfield.h \ gui/trade.cpp \ gui/trade.h \ + gui/unregisterdialog.cpp \ + gui/unregisterdialog.h \ gui/viewport.cpp \ gui/viewport.h \ gui/window.cpp \ @@ -146,6 +150,8 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \ net/itemhandler.cpp \ net/loginhandler.h \ net/loginhandler.cpp \ + net/logouthandler.cpp \ + net/logouthandler.h \ net/messagehandler.cpp \ net/messagehandler.h \ net/messagein.cpp \ diff --git a/src/game.cpp b/src/game.cpp index 40d78248..bc81add5 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -62,6 +62,7 @@ #include "gui/status.h" #include "gui/trade.h" #include "gui/viewport.h" +#include "gui/quitdialog.h" #include "net/beinghandler.h" #include "net/buysellhandler.h" @@ -92,7 +93,7 @@ Joystick *joystick = NULL; extern Window *weightNotice; extern Window *deathNotice; -ConfirmDialog *exitConfirm = NULL; +QuitDialog *quitDialog = NULL; ChatWindow *chatWindow; MenuWindow *menuWindow; @@ -120,22 +121,6 @@ FloorItemManager *floorItemManager = NULL; const int MAX_TIME = 10000; -/** - * Listener used for exitting handling. - */ -namespace { - struct ExitListener : public gcn::ActionListener - { - void action(const gcn::ActionEvent &event) - { - if (event.getId() == "yes") { - done = true; - } - exitConfirm = NULL; - } - } exitListener; -} - /** * Advances game logic counter. */ @@ -245,6 +230,8 @@ Game::Game(): mSkillHandler(new SkillHandler()), mTradeHandler(new TradeHandler()) { + done = false; + createGuiWindows(); engine = new Engine; @@ -285,6 +272,8 @@ Game::Game(): Game::~Game() { + Net::clearHandlers(); + delete engine; delete player_node; destroyGuiWindows(); @@ -440,13 +429,8 @@ void Game::handleInput() break; } - // Quit by pressing Enter if the exit confirm is there - if (exitConfirm) - { - done = true; - } // Close the Browser if opened - else if (helpWindow->isVisible()) + if (helpWindow->isVisible()) { helpWindow->setVisible(false); } @@ -522,12 +506,14 @@ void Game::handleInput() // Quitting confirmation dialog case SDLK_ESCAPE: - if (!exitConfirm) { - exitConfirm = new ConfirmDialog( - "Quit", "Are you sure you want to quit?"); - exitConfirm->addActionListener(&exitListener); + if (!quitDialog) + { + quitDialog = new QuitDialog(&done, &quitDialog); + } + else + { + quitDialog->requestMoveToTop(); } - exitConfirm->requestMoveToTop(); break; default: diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp index 4c4b99e5..5e329598 100644 --- a/src/gui/char_select.cpp +++ b/src/gui/char_select.cpp @@ -33,9 +33,12 @@ #include "playerbox.h" #include "textfield.h" +#include "unregisterdialog.h" + #include "../game.h" #include "../localplayer.h" #include "../main.h" +#include "../logindata.h" #include "../net/accountserver/account.h" @@ -54,8 +57,8 @@ class CharDeleteConfirm : public ConfirmDialog }; CharDeleteConfirm::CharDeleteConfirm(CharSelectDialog *m): - ConfirmDialog("Confirm", "Are you sure you want to delete this character?", - m), + ConfirmDialog("Confirm", + "Are you sure you want to delete this character?", m), master(m) { } @@ -69,16 +72,19 @@ void CharDeleteConfirm::action(const gcn::ActionEvent &event) ConfirmDialog::action(event); } -CharSelectDialog::CharSelectDialog(LockedArray *charInfo): +CharSelectDialog::CharSelectDialog(LockedArray *charInfo, + LoginData *loginData): Window("Select Character"), - mCharInfo(charInfo), mCharSelected(false) + mCharInfo(charInfo), mCharSelected(false), mLoginData(loginData) { + mSelectButton = new Button("Ok", "ok", this); mCancelButton = new Button("Cancel", "cancel", this); mNewCharButton = new Button("New", "new", this); mDelCharButton = new Button("Delete", "delete", this); mPreviousButton = new Button("Previous", "previous", this); mNextButton = new Button("Next", "next", this); + mUnRegisterButton = new Button("Unregister", "unregister", this); mNameLabel = new gcn::Label("Name"); mLevelLabel = new gcn::Label("Level"); @@ -104,10 +110,14 @@ CharSelectDialog::CharSelectDialog(LockedArray *charInfo): mSelectButton->setPosition( mCancelButton->getX() - 5 - mSelectButton->getWidth(), mNewCharButton->getY()); + mUnRegisterButton->setPosition( + w - 5 - mUnRegisterButton->getWidth(), + mCancelButton->getY() - 5 - mUnRegisterButton->getHeight()); add(mPlayerBox); add(mSelectButton); add(mCancelButton); + add(mUnRegisterButton); add(mNewCharButton); add(mDelCharButton); add(mPreviousButton); @@ -130,6 +140,7 @@ void CharSelectDialog::action(const gcn::ActionEvent &event) mNewCharButton->setEnabled(false); mDelCharButton->setEnabled(false); mSelectButton->setEnabled(false); + mUnRegisterButton->setEnabled(false); mPreviousButton->setEnabled(false); mNextButton->setEnabled(false); mCharSelected = true; @@ -166,6 +177,10 @@ void CharSelectDialog::action(const gcn::ActionEvent &event) { mCharInfo->next(); } + else if (event.getId() == "unregister") + { + new UnRegisterDialog(this, mLoginData); + } } void CharSelectDialog::updatePlayerInfo() diff --git a/src/gui/char_select.h b/src/gui/char_select.h index dbce2cbf..7136f301 100644 --- a/src/gui/char_select.h +++ b/src/gui/char_select.h @@ -31,6 +31,8 @@ #include +#include "../logindata.h" + class Player; class LocalPlayer; class PlayerBox; @@ -47,7 +49,8 @@ class CharSelectDialog : public Window, public gcn::ActionListener /** * Constructor. */ - CharSelectDialog(LockedArray *charInfo); + CharSelectDialog(LockedArray *charInfo, + LoginData *loginData); void action(const gcn::ActionEvent &event); @@ -71,6 +74,7 @@ class CharSelectDialog : public Window, public gcn::ActionListener gcn::Button *mDelCharButton; gcn::Button *mPreviousButton; gcn::Button *mNextButton; + gcn::Button *mUnRegisterButton; gcn::Label *mNameLabel; gcn::Label *mLevelLabel; @@ -80,6 +84,7 @@ class CharSelectDialog : public Window, public gcn::ActionListener bool mCharSelected; + LoginData *mLoginData; /** * Communicate character deletion to the server. */ @@ -130,6 +135,7 @@ class CharCreateDialog : public Window, public gcn::ActionListener int mSlot; + /** * Communicate character creation to the server. */ diff --git a/src/gui/login.cpp b/src/gui/login.cpp index 664074aa..9df3b489 100644 --- a/src/gui/login.cpp +++ b/src/gui/login.cpp @@ -144,7 +144,7 @@ LoginDialog::action(const gcn::ActionEvent &event) } else if (event.getId() == "cancel") { - state = STATE_EXIT; + state = STATE_FORCE_QUIT; } else if (event.getId() == "register") { diff --git a/src/gui/quitdialog.cpp b/src/gui/quitdialog.cpp new file mode 100644 index 00000000..97be5f46 --- /dev/null +++ b/src/gui/quitdialog.cpp @@ -0,0 +1,129 @@ +/* + * The Mana World + * 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 + * + */ + +#include "quitdialog.h" +#include +#include + +#include + +#include "../main.h" + +#include "button.h" +#include "radiobutton.h" + +QuitDialog::QuitDialog(bool* quitGame, QuitDialog** pointerToMe): + Window("Quit", true, NULL), mQuitGame(quitGame), mMyPointer(pointerToMe) +{ + + mLogoutQuit = new RadioButton("Quit", "quitdialog"); + mForceQuit = new RadioButton("Quit", "quitdialog"); + mSwitchAccountServer = new RadioButton("Switch server", "quitdialog"); + mSwitchCharacter = new RadioButton("Switch character", "quitdialog"); + mOkButton = new Button("OK", "ok", this); + mCancelButton = new Button("Cancel", "cancel", this); + + setContentSize(200, 91); + + mLogoutQuit->setPosition(5, 5); + mForceQuit->setPosition(5, 5); + mSwitchAccountServer->setPosition(5, 14 + mLogoutQuit->getHeight()); + mSwitchCharacter->setPosition(5, + 23 + mLogoutQuit->getHeight() + mSwitchAccountServer->getHeight()); + mCancelButton->setPosition( + 200 - mCancelButton->getWidth() - 5, + 91 - mCancelButton->getHeight() - 5); + mOkButton->setPosition( + mCancelButton->getX() - mOkButton->getWidth() - 5, + 91 - mOkButton->getHeight() - 5); + + //All states, when we're not logged in to someone. + if (state == STATE_CHOOSE_SERVER || + state == STATE_CONNECT_ACCOUNT || + state == STATE_LOGIN || + state == STATE_LOGIN_ATTEMPT || + state == STATE_UPDATE) + { + mForceQuit->setMarked(true); + add(mForceQuit); + } + else + { + // Only added if we are connected to an accountserver or gameserver + mLogoutQuit->setMarked(true); + add(mLogoutQuit); + add(mSwitchAccountServer); + + // Only added if we are connected to a gameserver + if (state == STATE_GAME) add(mSwitchCharacter); + } + + add(mOkButton); + add(mCancelButton); + + setLocationRelativeTo(getParent()); + setVisible(true); + + mOkButton->requestFocus(); + +} + +QuitDialog::~QuitDialog() +{ + if (mMyPointer) *mMyPointer = NULL; +} + +void +QuitDialog::action(const gcn::ActionEvent &event) +{ + if (event.getId() == "ok") + { + if (mForceQuit->isMarked()) + { + state = STATE_FORCE_QUIT; + } + else if (mLogoutQuit->isMarked()) + { + if ((state == STATE_GAME) && (mQuitGame)) + { + *mQuitGame = true; + } + state = STATE_EXIT; + } + else if (mSwitchAccountServer->isMarked()) + { + if ((state == STATE_GAME) && (mQuitGame)) + { + *mQuitGame = true; + } + state = STATE_SWITCH_ACCOUNTSERVER_ATTEMPT; + } + else if (mSwitchCharacter->isMarked()) + { + if (mQuitGame) *mQuitGame = true; + + state = STATE_SWITCH_CHARACTER; + } + + } + scheduleDelete(); +} diff --git a/src/gui/quitdialog.h b/src/gui/quitdialog.h new file mode 100644 index 00000000..97a03f2e --- /dev/null +++ b/src/gui/quitdialog.h @@ -0,0 +1,71 @@ +/* + * The Mana World + * 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 + * + */ + +#ifndef _TMW_QUITDIALOG_H +#define _TMW_QUITDIALOG_H + +#include +#include + +#include "window.h" +#include "../guichanfwd.h" +#include "../main.h" + +/** + * The quit dialog. + * + * \ingroup Interface + */ +class QuitDialog : public Window, public gcn::ActionListener { + public: + /** + * Constructor + * + * @quitGame; to be used for getting out of the while loop in Game + * @pointerToMe; will be set to NULL when the QuitDialog is destroyed + */ + QuitDialog(bool* quitGame, QuitDialog** pointerToMe); + + /** + * Destructor + */ + ~QuitDialog(); + + /** + * Called when receiving actions from the widgets. + */ + void action(const gcn::ActionEvent &event); + + private: + gcn::RadioButton *mLogoutQuit; + gcn::RadioButton *mForceQuit; + gcn::RadioButton *mSwitchAccountServer; + gcn::RadioButton *mSwitchCharacter; + gcn::Button *mOkButton; + gcn::Button *mCancelButton; + + bool* mQuitGame; + QuitDialog** mMyPointer; + +}; + +#endif diff --git a/src/gui/serverdialog.cpp b/src/gui/serverdialog.cpp index bf29f0d3..b47ce749 100644 --- a/src/gui/serverdialog.cpp +++ b/src/gui/serverdialog.cpp @@ -243,6 +243,6 @@ ServerDialog::action(const gcn::ActionEvent &event) } else if (event.getId() == "cancel") { - state = STATE_EXIT; + state = STATE_FORCE_QUIT; } } diff --git a/src/gui/unregisterdialog.cpp b/src/gui/unregisterdialog.cpp new file mode 100644 index 00000000..03e4880f --- /dev/null +++ b/src/gui/unregisterdialog.cpp @@ -0,0 +1,171 @@ +/* + * The Mana World + * 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 + * + */ + +#include "unregisterdialog.h" + +#include +#include + +#include + +#include "../main.h" +#include "../log.h" +#include "../logindata.h" + +#include "button.h" +#include "checkbox.h" +#include "login.h" +#include "passwordfield.h" +#include "textfield.h" +#include "ok_dialog.h" + +UnRegisterDialog::UnRegisterDialog(Window *parent, LoginData *loginData): + Window("Unregister", true, parent), + mWrongDataNoticeListener(new WrongDataNoticeListener()), + mLoginData(loginData) +{ + gcn::Label *userLabel = new gcn::Label("Name:"); + gcn::Label *passwordLabel = new gcn::Label("Password:"); + mUserField = new TextField(mLoginData->username); + mPasswordField = new PasswordField(mLoginData->password); + mUnRegisterButton = new Button("Unregister", "unregister", this); + mCancelButton = new Button("Cancel", "cancel", this); + + const int width = 200; + const int height = 70; + setContentSize(width, height); + + mUserField->setPosition(65, 5); + mUserField->setWidth(130); + mPasswordField->setPosition( + 65, mUserField->getY() + mUserField->getHeight() + 7); + mPasswordField->setWidth(130); + + userLabel->setPosition(5, mUserField->getY() + 1); + passwordLabel->setPosition(5, mPasswordField->getY() + 1); + + mCancelButton->setPosition( + width - 5 - mCancelButton->getWidth(), + height - 5 - mCancelButton->getHeight()); + mUnRegisterButton->setPosition( + mCancelButton->getX() - 5 - mUnRegisterButton->getWidth(), + mCancelButton->getY()); + + add(userLabel); + add(passwordLabel); + add(mUserField); + add(mPasswordField); + add(mUnRegisterButton); + add(mCancelButton); + + setLocationRelativeTo(getParent()); + setVisible(true); + mPasswordField->requestFocus(); +} + +UnRegisterDialog::~UnRegisterDialog() +{ + delete mWrongDataNoticeListener; +} + +void +UnRegisterDialog::action(const gcn::ActionEvent &event) +{ + if (event.getId() == "cancel") + { + scheduleDelete(); + } + else if (event.getId() == "unregister") + { + const std::string username = mUserField->getText(); + const std::string password = mPasswordField->getText(); + logger->log("UnregisterDialog::unregistered, Username is %s", + username.c_str()); + + std::stringstream errorMsg; + int error = 0; + + // Check login + if (username.empty()) + { + // No username + errorMsg << "Enter your username first."; + error = 1; + } + else if (username.length() < LEN_MIN_USERNAME) + { + // Name too short + errorMsg << "The username needs to be at least " + << LEN_MIN_USERNAME + << " characters long."; + error = 1; + } + else if (username.length() > LEN_MAX_USERNAME - 1 ) + { + // Name too long + errorMsg << "The username needs to be less than " + << LEN_MAX_USERNAME + << " characters long."; + error = 1; + } + else if (password.length() < LEN_MIN_PASSWORD) + { + // Pass too short + errorMsg << "The password needs to be at least " + << LEN_MIN_PASSWORD + << " characters long."; + error = 2; + } + else if (password.length() > LEN_MAX_PASSWORD - 1 ) + { + // Pass too long + errorMsg << "The password needs to be less than " + << LEN_MAX_PASSWORD + << " characters long."; + error = 2; + } + + if (error > 0) + { + if (error == 1) + { + mWrongDataNoticeListener->setTarget(this->mUserField); + } + else if (error == 2) + { + mWrongDataNoticeListener->setTarget(this->mPasswordField); + } + + OkDialog *dlg = new OkDialog("Error", errorMsg.str()); + dlg->addActionListener(mWrongDataNoticeListener); + } + else + { + // No errors detected, unregister the new user. + mUnRegisterButton->setEnabled(false); + mLoginData->username = username; + mLoginData->password = password; + state = STATE_UNREGISTER_ATTEMPT; + scheduleDelete(); + } + } +} diff --git a/src/gui/unregisterdialog.h b/src/gui/unregisterdialog.h new file mode 100644 index 00000000..40fdf7fe --- /dev/null +++ b/src/gui/unregisterdialog.h @@ -0,0 +1,73 @@ +/* + * The Mana World + * 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: register.h 3036 2007-01-14 16:45:13Z b_lindeijer $ + */ + +#ifndef _TMW_UNREGISTERDIALOG_H +#define _TMW_UNREGISTERDIALOG_H + +#include +#include + +#include "window.h" +#include "../guichanfwd.h" + +class LoginData; +class OkDialog; +class WrongDataNoticeListener; + +/** + * The Unregister dialog. + * + * \ingroup Interface + */ +class UnRegisterDialog : public Window, public gcn::ActionListener { + public: + /** + * Constructor + * + * @see Window::Window + */ + UnRegisterDialog(Window *parent,LoginData *loginData); + + /** + * Destructor + */ + ~UnRegisterDialog(); + + /** + * Called when receiving actions from the widgets. + */ + void action(const gcn::ActionEvent &event); + + private: + gcn::TextField *mUserField; + gcn::TextField *mPasswordField; + + gcn::Button *mUnRegisterButton; + gcn::Button *mCancelButton; + + WrongDataNoticeListener *mWrongDataNoticeListener; + + LoginData *mLoginData; +}; + +#endif diff --git a/src/lockedarray.h b/src/lockedarray.h index 7ec2f9da..f31292d7 100644 --- a/src/lockedarray.h +++ b/src/lockedarray.h @@ -46,7 +46,7 @@ class LockedArray bool isLocked() const { return mLocked; }; T getEntry() const { return mData[mCurEntry]; }; - void setEntry(T entry) { mData[mCurEntry] = entry; }; + void setEntry(T entry) { mData[mCurEntry] = entry; mFilled = true; }; void next(); void prev(); @@ -55,6 +55,11 @@ class LockedArray unsigned int getSize() const { return mSize; }; + /** + * Clears the array without changing size or data type + */ + void clear(); + protected: unsigned int mSize; @@ -62,11 +67,14 @@ class LockedArray unsigned int mCurEntry; bool mLocked; + + bool mFilled; }; template LockedArray::LockedArray(unsigned int size): - mSize(size), mData(new T[size]), mCurEntry(0), mLocked(false) + mSize(size), mData(new T[size]), mCurEntry(0), mLocked(false), + mFilled(false) { std::fill_n(mData, mSize, (T)0); } @@ -107,4 +115,19 @@ void LockedArray::select(unsigned int pos) mCurEntry = 0; } +template +void LockedArray::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/logindata.h b/src/logindata.h index 70b80bb7..f9b520eb 100644 --- a/src/logindata.h +++ b/src/logindata.h @@ -37,6 +37,15 @@ struct LoginData int session_ID2; bool remember; + + void clear() + { + username = ""; + password = ""; + hostname = ""; + email = ""; + port = 0; + }; }; #endif diff --git a/src/main.cpp b/src/main.cpp index dc186c84..e953d456 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -58,17 +58,21 @@ #include "gui/gui.h" #include "gui/serverdialog.h" #include "gui/login.h" +#include "gui/quitdialog.h" #include "gui/ok_dialog.h" #include "gui/register.h" #include "gui/updatewindow.h" #include "gui/textfield.h" + #include "net/charserverhandler.h" #include "net/connection.h" #include "net/loginhandler.h" +#include "net/logouthandler.h" #include "net/network.h" #include "net/accountserver/accountserver.h" +#include "net/accountserver/account.h" #include "net/chatserver/chatserver.h" @@ -427,6 +431,7 @@ void loadUpdates() CharServerHandler charServerHandler; LoginData loginData; LoginHandler loginHandler; +LogoutHandler logoutHandler; LockedArray charInfo(MAX_SLOT + 1); // TODO Find some nice place for these functions @@ -436,6 +441,7 @@ void accountLogin(LoginData *loginData) Net::registerHandler(&loginHandler); + charInfo.clear(); charServerHandler.setCharInfo(&charInfo); Net::registerHandler(&charServerHandler); @@ -461,6 +467,7 @@ void accountRegister(LoginData *loginData) Net::registerHandler(&loginHandler); + charInfo.clear(); charServerHandler.setCharInfo(&charInfo); Net::registerHandler(&charServerHandler); @@ -468,6 +475,109 @@ void accountRegister(LoginData *loginData) loginData->username, loginData->password, loginData->email); } +void accountUnRegister(LoginData *loginData) +{ + Net::registerHandler(&logoutHandler); + + Net::AccountServer::Account::unregister(loginData->username, + loginData->password); + +} + +void switchCharacter(std::string* passToken) +{ + Net::registerHandler(&logoutHandler); + + logoutHandler.reset(); + logoutHandler.setScenario(LOGOUT_SWITCH_CHARACTER, passToken); + + Net::GameServer::logout(true); + Net::ChatServer::logout(); +} + +void switchAccountServer() +{ + Net::registerHandler(&logoutHandler); + + logoutHandler.reset(); + logoutHandler.setScenario(LOGOUT_SWITCH_ACCOUNTSERVER); + + //Can't logout if we were not logged in ... + if (accountServerConnection->isConnected()) + { + Net::AccountServer::logout(); + } + else + { + logoutHandler.setAccountLoggedOut(); + } + + if (gameServerConnection->isConnected()) + { + Net::GameServer::logout(false); + } + else + { + logoutHandler.setGameLoggedOut(); + } + + if (chatServerConnection->isConnected()) + { + Net::ChatServer::logout(); + } + else + { + logoutHandler.setChatLoggedOut(); + } +} + +void logoutThenExit() +{ + Net::registerHandler(&logoutHandler); + + logoutHandler.reset(); + logoutHandler.setScenario(LOGOUT_EXIT); + + //Can't logout if we were not logged in ... + if (accountServerConnection->isConnected()) + { + Net::AccountServer::logout(); + } + else + { + logoutHandler.setAccountLoggedOut(); + } + + if (gameServerConnection->isConnected()) + { + Net::GameServer::logout(false); + } + else + { + logoutHandler.setGameLoggedOut(); + } + + if (chatServerConnection->isConnected()) + { + Net::ChatServer::logout(); + } + else + { + logoutHandler.setChatLoggedOut(); + } +} + +void reconnectAccount(const std::string& passToken) +{ + Net::registerHandler(&loginHandler); + + charInfo.clear(); + charServerHandler.setCharInfo(&charInfo); + Net::registerHandler(&charServerHandler); + + Net::AccountServer::reconnectAccount(accountServerConnection, passToken); +} + void xmlNullLogger(void *ctx, const char *msg, ...) { // Does nothing, that's the whole point of it @@ -520,6 +630,7 @@ int main(int argc, char *argv[]) initEngine(); Window *currentDialog = NULL; + QuitDialog* quitDialog = NULL; Image *login_wallpaper = NULL; Game *game = NULL; @@ -560,18 +671,25 @@ int main(int argc, char *argv[]) unsigned int oldstate = !state; // We start with a status change. SDL_Event event; - while (state != STATE_EXIT) + while (state != STATE_FORCE_QUIT) { // Handle SDL events while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: - state = STATE_EXIT; + state = STATE_FORCE_QUIT; break; case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_ESCAPE) - state = STATE_EXIT; + if (!quitDialog) + { + quitDialog = new QuitDialog(NULL, &quitDialog); + } + else + { + quitDialog->requestMoveToTop(); + } break; } @@ -581,15 +699,6 @@ int main(int argc, char *argv[]) gui->logic(); Net::flush(); - if (state > STATE_CONNECT_ACCOUNT && state < STATE_GAME) - { - if (!accountServerConnection->isConnected()) - { - state = STATE_ERROR; - errorMessage = "Got disconnected from account server!"; - } - } - if (!login_wallpaper) { login_wallpaper = ResourceManager::getInstance()-> @@ -608,7 +717,7 @@ int main(int argc, char *argv[]) gui->draw(); graphics->updateScreen(); - // TODO: Add connect timeout to go back to choose server + // TODO: Add connect timeouts if (state == STATE_CONNECT_ACCOUNT && accountServerConnection->isConnected()) { @@ -624,8 +733,16 @@ int main(int argc, char *argv[]) { accountServerConnection->disconnect(); Net::clearHandlers(); + state = STATE_GAME; } + else if (state == STATE_RECONNECT_ACCOUNT && + accountServerConnection->isConnected()) + { + reconnectAccount(token); + + state = STATE_WAIT; + } if (state != oldstate) { // Load updates after exiting the update state @@ -645,6 +762,11 @@ int main(int argc, char *argv[]) delete currentDialog; currentDialog = NULL; } + // State has changed, while the quitDialog was active, it might + // not be correct anymore + if (quitDialog) { + quitDialog->scheduleDelete(); + } switch (state) { case STATE_CHOOSE_SERVER: @@ -699,6 +821,21 @@ int main(int argc, char *argv[]) accountLogin(&loginData); break; + case STATE_SWITCH_ACCOUNTSERVER: + logger->log("State: SWITCH_ACCOUNTSERVER"); + + gameServerConnection->disconnect(); + chatServerConnection->disconnect(); + accountServerConnection->disconnect(); + + state = STATE_CHOOSE_SERVER; + break; + + case STATE_SWITCH_ACCOUNTSERVER_ATTEMPT: + logger->log("State: SWITCH_ACCOUNTSERVER_ATTEMPT"); + switchAccountServer(); + break; + case STATE_REGISTER: logger->log("State: REGISTER"); currentDialog = new RegisterDialog(&loginData); @@ -710,7 +847,8 @@ int main(int argc, char *argv[]) case STATE_CHAR_SELECT: logger->log("State: CHAR_SELECT"); - currentDialog = new CharSelectDialog(&charInfo); + currentDialog = + new CharSelectDialog(&charInfo, &loginData); if (((CharSelectDialog*) currentDialog)-> selectByName(options.playername)) @@ -724,6 +862,23 @@ int main(int argc, char *argv[]) gcn::ActionEvent(NULL, "ok")); break; + case STATE_UNREGISTER_ATTEMPT: + logger->log("State: UNREGISTER ATTEMPT"); + accountUnRegister(&loginData); + loginData.clear(); + break; + + case STATE_UNREGISTER: + logger->log("State: UNREGISTER"); + accountServerConnection->disconnect(); + currentDialog = new OkDialog("Unregister succesfull", + "Farewell, come back any time ...."); + + //The errorlistener sets the state to STATE_CHOOSE_SERVER + currentDialog->addActionListener(&errorListener); + currentDialog = NULL; // OkDialog deletes itself + break; + case STATE_ERROR: logger->log("State: ERROR"); currentDialog = new OkDialog("Error", errorMessage); @@ -749,29 +904,66 @@ int main(int argc, char *argv[]) sound.fadeOutMusic(1000); currentDialog = NULL; - login_wallpaper->decRef(); - login_wallpaper = NULL; logger->log("State: GAME"); game = new Game; game->logic(); delete game; - state = STATE_EXIT; + + //If the quitdialog didn't set the next state + if (state == STATE_GAME) + { + state = STATE_EXIT; + } + else if (state != STATE_FORCE_QUIT) + { + //TODO: solve this problem + delete gui; // Crashes otherwise + gui = new Gui(graphics); + } + break; + + case STATE_SWITCH_CHARACTER: + logger->log("State: SWITCH_CHARACTER"); + switchCharacter(&token); + break; + + case STATE_RECONNECT_ACCOUNT: + logger->log("State: RECONNECT_ACCOUNT"); + + //done with game&chat + gameServerConnection->disconnect(); + chatServerConnection->disconnect(); + + accountServerConnection->connect(loginData.hostname, + loginData.port); + break; + + case STATE_WAIT: + break; + + case STATE_EXIT: + logger->log("State: EXIT"); + logoutThenExit(); break; default: - state = STATE_EXIT; + state = STATE_FORCE_QUIT; break; } } } + accountServerConnection->disconnect(); + gameServerConnection->disconnect(); + chatServerConnection->disconnect(); + delete accountServerConnection; delete gameServerConnection; delete chatServerConnection; Net::finalize(); - logger->log("State: EXIT"); + logger->log("Quitting"); exit_engine(); PHYSFS_deinit(); delete logger; diff --git a/src/main.h b/src/main.h index c001a374..057e781f 100644 --- a/src/main.h +++ b/src/main.h @@ -76,11 +76,20 @@ enum { STATE_LOGIN_ATTEMPT, STATE_REGISTER, STATE_REGISTER_ATTEMPT, - STATE_CHAR_SELECT, STATE_ERROR, + STATE_CHAR_SELECT, + STATE_UNREGISTER_ATTEMPT, + STATE_UNREGISTER, + STATE_SWITCH_CHARACTER, + STATE_RECONNECT_ACCOUNT, + STATE_SWITCH_ACCOUNTSERVER_ATTEMPT, + STATE_SWITCH_ACCOUNTSERVER, + STATE_LOGOUT_ATTEMPT, STATE_CONNECT_GAME, STATE_GAME, - STATE_EXIT + STATE_WAIT, + STATE_EXIT, + STATE_FORCE_QUIT }; /* length definitions for several char[]s in order diff --git a/src/net/accountserver/account.cpp b/src/net/accountserver/account.cpp index daf94a65..16f81f44 100644 --- a/src/net/accountserver/account.cpp +++ b/src/net/accountserver/account.cpp @@ -68,9 +68,14 @@ void Net::AccountServer::Account::selectCharacter(char slot) Net::AccountServer::connection->send(msg); } -void Net::AccountServer::Account::unregister() +void Net::AccountServer::Account::unregister(const std::string &username, + const std::string &password) { MessageOut msg(PAMSG_UNREGISTER); + + msg.writeString(username); + msg.writeString(password); + Net::AccountServer::connection->send(msg); } diff --git a/src/net/accountserver/account.h b/src/net/accountserver/account.h index aaf3afe0..d3c84a15 100644 --- a/src/net/accountserver/account.h +++ b/src/net/accountserver/account.h @@ -41,13 +41,14 @@ namespace Net void selectCharacter(char slot); - void unregister(); + void unregister(const std::string &username, + const std::string &password); void changeEmail(const std::string &email); void getEmail(); - void changePassword(const std::string &oldPassowrd, + void changePassword(const std::string &oldPassword, const std::string &newPassword); } } diff --git a/src/net/accountserver/accountserver.cpp b/src/net/accountserver/accountserver.cpp index 8fde6d5e..92d803e6 100644 --- a/src/net/accountserver/accountserver.cpp +++ b/src/net/accountserver/accountserver.cpp @@ -63,6 +63,14 @@ void Net::AccountServer::logout() { MessageOut msg(PAMSG_LOGOUT); Net::AccountServer::connection->send(msg); +} - Net::AccountServer::connection = 0; +void Net::AccountServer::reconnectAccount(Net::Connection *connection, + const std::string &passToken) +{ + Net::AccountServer::connection = connection; + + MessageOut msg(PAMSG_RECONNECT); + msg.writeString(passToken, 32); + Net::AccountServer::connection->send(msg); } diff --git a/src/net/accountserver/accountserver.h b/src/net/accountserver/accountserver.h index c05b5317..8bfe991c 100644 --- a/src/net/accountserver/accountserver.h +++ b/src/net/accountserver/accountserver.h @@ -40,6 +40,9 @@ namespace Net const std::string &email); void logout(); + + void reconnectAccount(Net::Connection *connection, + const std::string &passToken); } } diff --git a/src/net/chatserver/chatserver.cpp b/src/net/chatserver/chatserver.cpp index e6a3331d..32979ea5 100644 --- a/src/net/chatserver/chatserver.cpp +++ b/src/net/chatserver/chatserver.cpp @@ -43,6 +43,13 @@ void Net::ChatServer::connect(Net::Connection *connection, connection->send(msg); } +void Net::ChatServer::logout() +{ + MessageOut msg(PCMSG_DISCONNECT); + + connection->send(msg); +} + void Net::ChatServer::chat(short channel, const std::string &text) { MessageOut msg(PCMSG_CHAT); diff --git a/src/net/chatserver/chatserver.h b/src/net/chatserver/chatserver.h index 93fe17c4..cf86baf3 100644 --- a/src/net/chatserver/chatserver.h +++ b/src/net/chatserver/chatserver.h @@ -34,6 +34,8 @@ namespace Net { void connect(Net::Connection *connection, const std::string &token); + void logout(); + void chat(short channel, const std::string &text); void announce(const std::string &text); diff --git a/src/net/connection.cpp b/src/net/connection.cpp index 4ce05d4a..ce060ae7 100644 --- a/src/net/connection.cpp +++ b/src/net/connection.cpp @@ -84,7 +84,8 @@ void Net::Connection::disconnect() bool Net::Connection::isConnected() { - return mConnection && mConnection->state == ENET_PEER_STATE_CONNECTED; + return bool (mConnection) ? + (mConnection->state == ENET_PEER_STATE_CONNECTED) : false; } void Net::Connection::send(const MessageOut &msg) diff --git a/src/net/gameserver/gameserver.cpp b/src/net/gameserver/gameserver.cpp index 04e5bb08..8f8ad8ac 100644 --- a/src/net/gameserver/gameserver.cpp +++ b/src/net/gameserver/gameserver.cpp @@ -40,3 +40,12 @@ void Net::GameServer::connect(Net::Connection *connection, Net::GameServer::connection->send(msg); } + +void Net::GameServer::logout(bool reconnectAccount) +{ + MessageOut msg(PGMSG_DISCONNECT); + + msg.writeByte((unsigned char) reconnectAccount); + + Net::GameServer::connection->send(msg); +} diff --git a/src/net/gameserver/gameserver.h b/src/net/gameserver/gameserver.h index ee49d7e3..5bf196b6 100644 --- a/src/net/gameserver/gameserver.h +++ b/src/net/gameserver/gameserver.h @@ -33,6 +33,8 @@ namespace Net namespace GameServer { void connect(Net::Connection *connection, const std::string &token); + + void logout(bool reconnectAccount); } } diff --git a/src/net/loginhandler.cpp b/src/net/loginhandler.cpp index 73be4b2f..c68a620a 100644 --- a/src/net/loginhandler.cpp +++ b/src/net/loginhandler.cpp @@ -33,6 +33,7 @@ LoginHandler::LoginHandler() static const Uint16 _messages[] = { APMSG_LOGIN_RESPONSE, APMSG_REGISTER_RESPONSE, + APMSG_RECONNECT_RESPONSE, 0 }; handledMessages = _messages; @@ -106,5 +107,34 @@ void LoginHandler::handleMessage(MessageIn &msg) } } break; + case APMSG_RECONNECT_RESPONSE: + { + int errMsg = msg.readByte(); + // Successful login + if (errMsg == ERRMSG_OK) + { + state = STATE_CHAR_SELECT; + } + // Login failed + else + { + switch (errMsg) { + case ERRMSG_INVALID_ARGUMENT: + errorMessage = "Wrong magic_token"; + break; + case ERRMSG_FAILURE: + errorMessage = "Already logged in"; + break; + case LOGIN_SERVER_FULL: + errorMessage = "Server is full"; + break; + default: + errorMessage = "Unknown error"; + break; + } + state = STATE_ERROR; + } + } + break; } } diff --git a/src/net/logouthandler.cpp b/src/net/logouthandler.cpp new file mode 100644 index 00000000..b52a38c5 --- /dev/null +++ b/src/net/logouthandler.cpp @@ -0,0 +1,216 @@ +/* + * The Mana World + * 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 + * + */ + +#include "logouthandler.h" + +#include "messagein.h" +#include "protocol.h" + +#include "../main.h" + +LogoutHandler::LogoutHandler(): +mPassToken(NULL), mScenario(LOGOUT_EXIT), +mLoggedOutAccount(false), mLoggedOutGame(false), mLoggedOutChat(false) +{ + static const Uint16 _messages[] = { + APMSG_LOGOUT_RESPONSE, + APMSG_UNREGISTER_RESPONSE, + GPMSG_DISCONNECT_RESPONSE, + CPMSG_DISCONNECT_RESPONSE, + 0 + }; + handledMessages = _messages; +} + +void LogoutHandler::handleMessage(MessageIn &msg) +{ + switch (msg.getId()) + { + case APMSG_LOGOUT_RESPONSE: + { + int errMsg = msg.readByte(); + + // Successful logout + if (errMsg == ERRMSG_OK) + { + mLoggedOutAccount = true; + + switch (mScenario) + { + case LOGOUT_SWITCH_ACCOUNTSERVER: + if (mLoggedOutGame && mLoggedOutChat) + state = STATE_SWITCH_ACCOUNTSERVER; + break; + + case LOGOUT_EXIT: + default: + if (mLoggedOutGame && mLoggedOutChat) + state = STATE_FORCE_QUIT; + break; + } + } + // Logout failed + else + { + switch (errMsg) { + case ERRMSG_NO_LOGIN: + errorMessage = "Accountserver: Not logged in"; + break; + default: + errorMessage = "Accountserver: Unknown error"; + break; + } + state = STATE_ERROR; + } + } + break; + case APMSG_UNREGISTER_RESPONSE: + { + int errMsg = msg.readByte(); + // Successful unregistration + if (errMsg == ERRMSG_OK) + { + state = STATE_UNREGISTER; + } + // Unregistration failed + else + { + switch (errMsg) { + case ERRMSG_INVALID_ARGUMENT: + errorMessage = + "Accountserver: Wrong username or password"; + break; + default: + errorMessage = "Accountserver: Unknown error"; + break; + } + state = STATE_ERROR; + } + } + break; + case GPMSG_DISCONNECT_RESPONSE: + { + int errMsg = msg.readByte(); + // Successful logout + if (errMsg == ERRMSG_OK) + { + mLoggedOutGame = true; + + switch (mScenario) + { + case LOGOUT_SWITCH_CHARACTER: + if (mPassToken) + { + *mPassToken = msg.readString(32); + mPassToken = NULL; + } + if (mLoggedOutChat) state = STATE_RECONNECT_ACCOUNT; + break; + + case LOGOUT_SWITCH_ACCOUNTSERVER: + if (mLoggedOutAccount && mLoggedOutChat) + state = STATE_SWITCH_ACCOUNTSERVER; + break; + + case LOGOUT_EXIT: + default: + if (mLoggedOutAccount && mLoggedOutChat) + state = STATE_FORCE_QUIT; + break; + } + } + // Logout failed + else + { + switch (errMsg) { + case ERRMSG_NO_LOGIN: + errorMessage = "Gameserver: Not logged in"; + break; + default: + errorMessage = "Gameserver: Unknown error"; + break; + } + state = STATE_ERROR; + } + } + break; + case CPMSG_DISCONNECT_RESPONSE: + { + int errMsg = msg.readByte(); + // Successful logout + if (errMsg == ERRMSG_OK) + { + mLoggedOutChat = true; + + switch (mScenario) + { + case LOGOUT_SWITCH_CHARACTER: + if (mLoggedOutGame) state = STATE_RECONNECT_ACCOUNT; + break; + + case LOGOUT_SWITCH_ACCOUNTSERVER: + if (mLoggedOutAccount && mLoggedOutGame) + state = STATE_SWITCH_ACCOUNTSERVER; + break; + + case LOGOUT_EXIT: + default: + if (mLoggedOutAccount && mLoggedOutGame) + { + state = STATE_FORCE_QUIT; + } + break; + } + } + else + { + switch (errMsg) { + case ERRMSG_NO_LOGIN: + errorMessage = "Chatserver: Not logged in"; + break; + default: + errorMessage = "Chatserver: Unknown error"; + break; + } + state = STATE_ERROR; + } + } + break; + } +} + +void +LogoutHandler::setScenario(unsigned short scenario, std::string* passToken) +{ + mScenario = scenario; + mPassToken = passToken; +} + +void +LogoutHandler::reset() +{ + mPassToken = NULL; + mScenario = LOGOUT_EXIT; + mLoggedOutAccount = false; + mLoggedOutGame = false; + mLoggedOutChat = false; +} diff --git a/src/net/logouthandler.h b/src/net/logouthandler.h new file mode 100644 index 00000000..bf4e1221 --- /dev/null +++ b/src/net/logouthandler.h @@ -0,0 +1,63 @@ +/* + * The Mana World + * 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 + * + */ + +#ifndef _TMW_NET_LOGOUTHANDLER_H +#define _TMW_NET_LOGOUTHANDLER_H + +#include + +#include "messagehandler.h" + +/** + * The different scenarios for which LogoutHandler can be used + */ +enum { + LOGOUT_EXIT, + LOGOUT_SWITCH_ACCOUNTSERVER, + LOGOUT_SWITCH_CHARACTER +}; + +class LogoutHandler : public MessageHandler +{ + public: + LogoutHandler(); + + void handleMessage(MessageIn &msg); + + void setScenario(unsigned short scenario, + std::string* passToken = NULL); + + void reset(); + + void setAccountLoggedOut(){ mLoggedOutAccount = true; } + void setGameLoggedOut(){ mLoggedOutGame = true; } + void setChatLoggedOut(){ mLoggedOutChat = true; } + + private: + std::string* mPassToken; + unsigned short mScenario; + bool mLoggedOutAccount; + bool mLoggedOutGame; + bool mLoggedOutChat; +}; + +#endif diff --git a/src/net/protocol.h b/src/net/protocol.h index 096ba29c..78a42e42 100644 --- a/src/net/protocol.h +++ b/src/net/protocol.h @@ -119,7 +119,7 @@ enum { // Login/Register PAMSG_REGISTER = 0x0000, // L version, S username, S password, S email APMSG_REGISTER_RESPONSE = 0x0002, // B error - PAMSG_UNREGISTER = 0x0003, // - + PAMSG_UNREGISTER = 0x0003, // S username, S password APMSG_UNREGISTER_RESPONSE = 0x0004, // B error PAMSG_LOGIN = 0x0010, // L version, S username, S password APMSG_LOGIN_RESPONSE = 0x0012, // B error @@ -144,6 +144,14 @@ enum { PCMSG_CONNECT = 0x0053, // B*32 token CPMSG_CONNECT_RESPONSE = 0x0054, // B error + PGMSG_DISCONNECT = 0x0060, // B reconnect account + GPMSG_DISCONNECT_RESPONSE = 0x0061, // B error, B*32 token + PCMSG_DISCONNECT = 0x0063, // - + CPMSG_DISCONNECT_RESPONSE = 0x0064, // B error + + PAMSG_RECONNECT = 0x0065, // B*32 token + APMSG_RECONNECT_RESPONSE = 0x0066, // B error + // Game GPMSG_PLAYER_MAP_CHANGE = 0x0100, // S filename, W x, W y GPMSG_PLAYER_SERVER_CHANGE = 0x0101, // B*32 token, S game address, W game port -- cgit v1.2.3-70-g09d2 From 7a6e4d3c87ca4d7cc851af47fd9ebb616168f4c9 Mon Sep 17 00:00:00 2001 From: Philipp Sehmisch Date: Tue, 27 Feb 2007 16:39:17 +0000 Subject: Implementation of chat channels by Trapdoor. --- ChangeLog | 12 ++- src/game.cpp | 6 +- src/graphics.h | 2 +- src/gui/button.cpp | 9 +- src/gui/button.h | 7 ++ src/gui/chat.cpp | 185 +++++++++++++++++++++++++++++++++----- src/gui/chat.h | 54 +++++++++-- src/gui/tabbedcontainer.cpp | 36 ++++++-- src/gui/tabbedcontainer.h | 10 ++- src/net/chathandler.cpp | 76 ++++++++++++++++ src/net/chatserver/chatserver.cpp | 15 +++- src/net/chatserver/chatserver.h | 5 +- src/net/protocol.h | 9 +- 13 files changed, 376 insertions(+), 50 deletions(-) (limited to 'src/net/chatserver/chatserver.h') diff --git a/ChangeLog b/ChangeLog index 62585ceb..8b22ac39 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,14 @@ -2007-02-25 Bjørn Lindeijer +2007-02-27 Philipp Sehmisch + * gui/button.cpp, src/guibutton.h, + src/gui/tabbedcontainer.cpp, src/gui/tabbedcontainer.h:: Tabbed + containers now display the button of the active tab pressed all + the time. + * src/game.cpp, src/gui/chat.cpp, src/gui/chat.h, src/chathandler.cpp, + src/net/chatserver/chatserver.cpp, src/net/chatserver/chatserver.h, + src/net/protocol.h: Implementation of chat channels by Trapdoor. + * src/graphics.h: MSVC Compilation fix by Trapdoor. + +2007-02-25 Bjørn Lindeijer * src/CMakeLists.txt: Updated CMake file. diff --git a/src/game.cpp b/src/game.cpp index 9eaa0693..ba4e2b9d 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -32,6 +32,7 @@ #include #include "beingmanager.h" +#include "channelmanager.h" #include "configuration.h" #include "engine.h" #include "flooritemmanager.h" @@ -118,6 +119,7 @@ DebugWindow *debugWindow; BeingManager *beingManager = NULL; FloorItemManager *floorItemManager = NULL; +ChannelManager *channelManager = NULL; const int MAX_TIME = 10000; @@ -238,6 +240,7 @@ Game::Game(): beingManager = new BeingManager; floorItemManager = new FloorItemManager(); + channelManager = new ChannelManager(); // Initialize timers tick_time = 0; @@ -281,6 +284,7 @@ Game::~Game() delete beingManager; delete floorItemManager; + delete channelManager; delete joystick; beingManager = NULL; @@ -303,7 +307,7 @@ bool saveScreenshot(SDL_Surface *screenshot) do { screenshotCount++; filename.str(""); -#if (defined __USE_UNIX98 || defined __FreeBSD__) +#if (defined __USE_UNIX98 || defined __FreeBSD__ || defined __APPLE__) filename << PHYSFS_getUserDir() << "/"; #endif filename << "TMW_Screenshot_" << screenshotCount << ".png"; diff --git a/src/graphics.h b/src/graphics.h index b3d36653..4637973f 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -29,7 +29,7 @@ class Image; class ImageRect; -class SDL_Surface; +struct SDL_Surface; /** * 9 images defining a rectangle. 4 corners, 4 sides and a middle area. The diff --git a/src/gui/button.cpp b/src/gui/button.cpp index 0055c89a..e607b66a 100644 --- a/src/gui/button.cpp +++ b/src/gui/button.cpp @@ -38,8 +38,9 @@ ImageRect Button::button[4]; int Button::mInstances = 0; Button::Button(const std::string& caption, const std::string &actionEventId, - gcn::ActionListener *listener): - gcn::Button(caption) + gcn::ActionListener *listener): + gcn::Button(caption), + mIsLogged(false) { setBorderSize(0); @@ -100,7 +101,7 @@ Button::draw(gcn::Graphics *graphics) if (!isEnabled()) { mode = 3; } - else if (isPressed()) { + else if (isPressed() || mIsLogged) { mode = 2; } else if (mHasMouse) { @@ -130,7 +131,7 @@ Button::draw(gcn::Graphics *graphics) textX = getWidth() - 4; break; default: - throw GCN_EXCEPTION("Button::draw. Uknown alignment."); + throw GCN_EXCEPTION("Button::draw. Unknown alignment."); } graphics->setFont(getFont()); diff --git a/src/gui/button.h b/src/gui/button.h index 1c2ec41b..eb73e311 100644 --- a/src/gui/button.h +++ b/src/gui/button.h @@ -53,9 +53,16 @@ class Button : public gcn::Button { */ void draw(gcn::Graphics* graphics); + /** + * Enable/Disable highlighting + */ + void setLogged(bool enable) + { mIsLogged = enable; } + private: static ImageRect button[4]; /**< Button state graphics */ static int mInstances; /**< Number of button instances */ + bool mIsLogged; /**< Makes the button appear pressed all the time */ }; #endif diff --git a/src/gui/chat.cpp b/src/gui/chat.cpp index d992c6dd..eb6b7612 100644 --- a/src/gui/chat.cpp +++ b/src/gui/chat.cpp @@ -29,17 +29,22 @@ #include #include "browserbox.h" +#include "../channelmanager.h" +#include "../channel.h" #include "chatinput.h" +#include "gccontainer.h" #include "scrollarea.h" +#include "tabbedcontainer.h" #include "windowcontainer.h" #include "../game.h" #include "../localplayer.h" #include "../net/chatserver/chatserver.h" - #include "../net/gameserver/player.h" +#include "../utils/dtor.h" + ChatWindow::ChatWindow(): Window(""), mTmpVisible(false) @@ -56,17 +61,34 @@ ChatWindow::ChatWindow(): mChatInput->setActionEventId("chatinput"); mChatInput->addActionListener(this); - mTextOutput = new BrowserBox(BrowserBox::AUTO_WRAP); - mTextOutput->setOpaque(false); - mTextOutput->disableLinksAndUserColors(); - mScrollArea = new ScrollArea(mTextOutput); - mScrollArea->setPosition( - mScrollArea->getBorderSize(), mScrollArea->getBorderSize()); - mScrollArea->setScrollPolicy( + BrowserBox *textOutput = new BrowserBox(BrowserBox::AUTO_WRAP); + textOutput->setOpaque(false); + textOutput->disableLinksAndUserColors(); + ScrollArea *scrollArea = new ScrollArea(textOutput); + scrollArea->setPosition( + scrollArea->getBorderSize(), scrollArea->getBorderSize()); + scrollArea->setScrollPolicy( gcn::ScrollArea::SHOW_NEVER, gcn::ScrollArea::SHOW_ALWAYS); - mScrollArea->setOpaque(false); + scrollArea->setOpaque(false); + + GCContainer *tab = new GCContainer(); + tab->setWidth(getWidth() - 2 * tab->getBorderSize()); + tab->setHeight(getHeight() - 2 * tab->getBorderSize()); + tab->setOpaque(false); + tab->add(scrollArea); + + mContainer = new TabbedContainer(); + mContainer->addTab(tab, "General"); + mContainer->setOpaque(false); + mChannelOutput["General"] = textOutput; + mChannelScroll["General"] = scrollArea; + + mTabs["General"] = tab; + + mTextOutput = textOutput; + mScrollArea = scrollArea; - add(mScrollArea); + add(mContainer); add(mChatInput); // Add key listener to chat input to be able to respond to up/down @@ -74,6 +96,11 @@ ChatWindow::ChatWindow(): mCurHist = mHistory.end(); } +ChatWindow::~ChatWindow() +{ + for_each(mTabs.begin(), mTabs.end(), make_dtor(mTabs)); +} + void ChatWindow::logic() { @@ -85,14 +112,17 @@ ChatWindow::logic() area.height - mChatInput->getHeight() - mChatInput->getBorderSize()); mChatInput->setWidth(area.width - 2 * mChatInput->getBorderSize()); + mContainer->setWidth(area.width - 2 * mContainer->getBorderSize()); + mContainer->setHeight(area.height - 2 * mContainer->getBorderSize() - + mChatInput->getHeight() - 5); mScrollArea->setWidth(area.width - 2 * mScrollArea->getBorderSize()); mScrollArea->setHeight(area.height - 2 * mScrollArea->getBorderSize() - - mChatInput->getHeight() - 5); + mChatInput->getHeight() - 26); mScrollArea->logic(); } void -ChatWindow::chatLog(std::string line, int own) +ChatWindow::chatLog(std::string line, int own, std::string channelName) { // Delete overhead from the end of the list while ((int)mChatlog.size() > mItemsKeep) { @@ -103,6 +133,9 @@ ChatWindow::chatLog(std::string line, int own) tmp.own = own; tmp.nick = ""; + mTextOutput = mChannelOutput[channelName]; + mScrollArea = mChannelScroll[channelName]; + // Fix the owner of welcome message. if (line.substr(0, 7) == "Welcome") { @@ -196,7 +229,7 @@ ChatWindow::action(const gcn::ActionEvent &event) mCurHist = mHistory.end(); // Send the message to the server - chatSend(player_node->getName(), message); + chatSend(player_node->getName(), message, mContainer->getActiveWidget()); // Clear the text from the chat input mChatInput->setText(""); @@ -241,7 +274,7 @@ ChatWindow::isFocused() } void -ChatWindow::chatSend(const std::string &nick, std::string msg) +ChatWindow::chatSend(const std::string &nick, std::string msg, std::string channelName) { /* Some messages are managed client side, while others * require server handling by proper packet. Probably @@ -249,7 +282,15 @@ ChatWindow::chatSend(const std::string &nick, std::string msg) // Prepare ordinary message if (msg.substr(0, 1) != "/") { - Net::GameServer::Player::say(msg); + if(mContainer->getActiveWidget() == "General") + { + Net::GameServer::Player::say(msg); + } + else + { + short channelId = channelManager->findByName(channelName)->getId(); + Net::ChatServer::chat(channelId, msg); + } } else if (msg.substr(0, IS_ANNOUNCE_LENGTH) == IS_ANNOUNCE) { @@ -258,11 +299,15 @@ ChatWindow::chatSend(const std::string &nick, std::string msg) } else if (msg.substr(0, IS_HELP_LENGTH) == IS_HELP) { - chatLog("-- Help --", BY_SERVER); - chatLog("/help : Display this help.", BY_SERVER); - chatLog("/announce : Global announcement (GM only)", BY_SERVER); - chatLog("/where : Display map name", BY_SERVER); - chatLog("/who : Display number of online users", BY_SERVER); + chatLog("-- Help --", BY_SERVER, channelName); + chatLog("/help > Display this help.", BY_SERVER, channelName); + chatLog("/announce > Global announcement (GM only)", BY_SERVER, channelName); + chatLog("/where > Display map name", BY_SERVER, channelName); + chatLog("/who > Display number of online users", BY_SERVER, channelName); + chatLog("/list > Display all public channels", BY_SERVER, channelName); + chatLog("/register > Register a new channel", BY_SERVER, channelName); + chatLog("/join > Join an already registered channel", BY_SERVER, channelName); + chatLog("/quit > Leave a channel", BY_SERVER, channelName); } else if (msg.substr(0, IS_WHERE_LENGTH) == IS_WHERE) { @@ -275,9 +320,46 @@ ChatWindow::chatSend(const std::string &nick, std::string msg) MessageOut outMsg(0x00c1); */ } + else if (msg.substr(0, IS_REGCHANNEL_LENGTH) == IS_REGCHANNEL) + { + std::string channel = msg.substr(IS_REGCHANNEL_LENGTH, msg.size()); + chatLog("Requesting to register channel", BY_SERVER); + Net::ChatServer::registerChannel(channel, "", "", false); + } + else if (msg.substr(0, IS_JOINCHANNEL_LENGTH) == IS_JOINCHANNEL) + { + //TODO: have passwords too + msg = msg.substr(IS_JOINCHANNEL_LENGTH, msg.size()); + chatLog("Requesting to join channel " + msg, BY_SERVER); + if(msg != "") + { + enterChannel(msg, "None"); + } + else + { + chatLog("No channel name given", BY_SERVER); + } + } + else if (msg.substr(0, IS_LISTCHANNELS_LENGTH) == IS_LISTCHANNELS) + { + Net::ChatServer::getChannelList(); + } + else if (msg.substr(0, IS_QUITCHANNEL_LENGTH) == IS_QUITCHANNEL) + { + Channel* channel; + channel = channelManager->findByName(channelName); + if(channel) + { + Net::ChatServer::quitChannel(channel->getId()); + } + else + { + chatLog("Unable to quit this channel", BY_SERVER); + } + } else { - chatLog("Unknown command", BY_SERVER); + chatLog("Unknown command", BY_SERVER, channelName); } } @@ -359,6 +441,67 @@ ChatWindow::const_msg(CHATSKILL act) return msg; } +void +ChatWindow::addChannel(short channelId, std::string channelName) +{ + Channel* channel = new Channel(channelId); + channel->setName(channelName); + channelManager->addChannel(channel); +} + +void +ChatWindow::removeChannel(short channelId) +{ + Channel* channel = channelManager->findById(channelId); + if(channel) + { + mContainer->removeTab(channel->getName()); + mTabs.erase(channel->getName()); + mChannelOutput.erase(channel->getName()); + mChannelScroll.erase(channel->getName()); + channelManager->removeChannel(channel); + mTextOutput = mChannelOutput["General"]; + mScrollArea = mChannelScroll["General"]; + } +} + +void +ChatWindow::createNewChannelTab(std::string channelName) +{ + BrowserBox *textOutput = new BrowserBox(BrowserBox::AUTO_WRAP); + textOutput->setOpaque(false); + textOutput->disableLinksAndUserColors(); + ScrollArea *scrollArea = new ScrollArea(textOutput); + scrollArea->setPosition(scrollArea->getBorderSize(), scrollArea->getBorderSize()); + scrollArea->setScrollPolicy(gcn::ScrollArea::SHOW_NEVER, gcn::ScrollArea::SHOW_ALWAYS); + scrollArea->setOpaque(false); + GCContainer *tab = new GCContainer(); + tab->setWidth(getWidth() - 2 * tab->getBorderSize()); + tab->setHeight(getHeight() - 2 * tab->getBorderSize()); + tab->add(scrollArea); + tab->setOpaque(false); + mContainer->addTab(tab, channelName); + mTabs[channelName] = tab; + mChannelOutput[channelName] = textOutput; + mChannelScroll[channelName] = scrollArea; + mScrollArea = scrollArea; + mTextOutput = textOutput; + logic(); +} + +void +ChatWindow::enterChannel(std::string channel, std::string password) +{ + Net::ChatServer::enterChannel(channel, password); +} + +void +ChatWindow::sendToChannel(short channelId, std::string user, std::string msg) +{ + std::string channelName = channelManager->findById(channelId)->getName(); + chatLog(user + ": " + msg, user == player_node->getName() ? BY_PLAYER : BY_OTHER, channelName); +} + void ChatWindow::keyPressed(gcn::KeyEvent &event) { diff --git a/src/gui/chat.h b/src/gui/chat.h index 963e5e98..c7e51ebf 100644 --- a/src/gui/chat.h +++ b/src/gui/chat.h @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -36,6 +37,8 @@ class BrowserBox; class ScrollArea; +class TabbedContainer; +class GCContainer; #define BY_GM 0 // those should be self-explanatory =) #define BY_PLAYER 1 @@ -53,6 +56,14 @@ class ScrollArea; #define IS_WHERE_LENGTH 6 #define IS_WHO "/who" #define IS_WHO_LENGTH 4 +#define IS_JOINCHANNEL "/join " +#define IS_JOINCHANNEL_LENGTH 6 +#define IS_REGCHANNEL "/register " +#define IS_REGCHANNEL_LENGTH 10 +#define IS_LISTCHANNELS "/list" +#define IS_LISTCHANNELS_LENGTH 5 +#define IS_QUITCHANNEL "/quit" +#define IS_QUITCHANNEL_LENGTH 5 /** * gets in between usernick and message text depending on @@ -117,6 +128,11 @@ class ChatWindow : public Window, public gcn::ActionListener, */ ChatWindow(); + /** + * + */ + ~ChatWindow(); + /** * Logic (updates components' size) */ @@ -128,7 +144,7 @@ class ChatWindow : public Window, public gcn::ActionListener, * @param line Text message. * @parem own Type of message (usually the owner-type). */ - void chatLog(std::string line, int own); + void chatLog(std::string line, int own, std::string channelName = "General"); /* * Calls original chat_log() after processing the packet. @@ -175,7 +191,27 @@ class ChatWindow : public Window, public gcn::ActionListener, * chatlog.chat_send("Zaeiru", "Hello to all users on the screen!"); */ void - chatSend(const std::string &nick, std::string msg); + chatSend(const std::string &nick, std::string msg, std::string channelName); + + /** Called to add the channel to the channel manager */ + void + addChannel(short channel, std::string channelName); + + /** Called to remove the channel from the channel manager */ + void + removeChannel(short channel); + + /** Called to create a new channel tab */ + void + createNewChannelTab(std::string channelName); + + /** Called to join channel */ + void + enterChannel(std::string channel, std::string password = "None"); + + /** Called to output text to a specific channel */ + void + sendToChannel(short channel, std::string user, std::string msg); /** Called when key is pressed */ void @@ -192,7 +228,9 @@ class ChatWindow : public Window, public gcn::ActionListener, private: bool mTmpVisible; - /** One item in the chat log */ + int mItems; + int mItemsKeep; + typedef struct CHATLOG { std::string nick; @@ -200,15 +238,17 @@ class ChatWindow : public Window, public gcn::ActionListener, int own; }; - std::list mChatlog; /**< Chat log */ - - int mItems; - int mItemsKeep; + std::list mChatlog; /** Constructs failed messages for actions */ std::string const_msg(CHATSKILL); + std::map mTabs; + TabbedContainer *mContainer; /**< Tabbed container for tabbing between channels */ + GCContainer *mTab; /**< Tabs */ gcn::TextField *mChatInput; /**< Input box for typing chat messages */ + std::map mChannelOutput; /**< Map each TextOutput to a tab */ + std::map mChannelScroll; /**< Map each ScrollArea to a tab */ BrowserBox *mTextOutput; /**< Text box for displaying chat history */ ScrollArea *mScrollArea; /**< Scroll area around text output */ diff --git a/src/gui/tabbedcontainer.cpp b/src/gui/tabbedcontainer.cpp index 75f9f3cf..5d6d21d1 100644 --- a/src/gui/tabbedcontainer.cpp +++ b/src/gui/tabbedcontainer.cpp @@ -26,6 +26,7 @@ #include "button.h" #include "../utils/tostring.h" +#include "../utils/dtor.h" #define TABWIDTH 60 #define TABHEIGHT 20 @@ -37,10 +38,7 @@ TabbedContainer::TabbedContainer(): TabbedContainer::~TabbedContainer() { - for (WidgetIterator i = mTabs.begin(); i != mTabs.end(); i++) { - remove(*i); - delete (*i); - } + for_each(mTabs.begin(), mTabs.end(), make_dtor(mTabs)); mTabs.clear(); mContents.clear(); @@ -55,7 +53,7 @@ void TabbedContainer::addTab(gcn::Widget *widget, const std::string &caption) tab->setSize(TABWIDTH, TABHEIGHT); add(tab, TABWIDTH * tabNumber, 0); - mTabs.push_back(tab); + mTabs[caption] = tab; mContents.push_back(widget); widget->setPosition(0, TABHEIGHT); @@ -64,7 +62,18 @@ void TabbedContainer::addTab(gcn::Widget *widget, const std::string &caption) if (!mActiveContent) { mActiveContent = widget; add(mActiveContent); + tab->setLogged(true); } + + mWidgets[widget] = caption; +} + +void TabbedContainer::removeTab(const std::string &caption) +{ + gcn::ActionEvent actionEvent(this, "0"); + action(actionEvent); + remove(mTabs[caption]); + mTabs.erase(caption); } void TabbedContainer::logic() @@ -80,16 +89,21 @@ void TabbedContainer::logic() void TabbedContainer::action(const gcn::ActionEvent &event) { - std::stringstream ss(event.getId()); int tabNo; + std::stringstream ss(event.getId()); ss >> tabNo; gcn::Widget *newContent = mContents[tabNo]; + if (newContent) { if (mActiveContent) { + // Unhighlight old tab + ((Button*)mTabs[mWidgets[mActiveContent]])->setLogged(false); remove(mActiveContent); } mActiveContent = newContent; + // Highlight new tab + ((Button*)mTabs[mWidgets[mActiveContent]])->setLogged(true); add(newContent); } } @@ -98,3 +112,13 @@ void TabbedContainer::setOpaque(bool opaque) { Container::setOpaque(opaque); } + +short TabbedContainer::getNumberOfTabs() +{ + return mTabs.size(); +} + +std::string TabbedContainer::getActiveWidget() +{ + return mWidgets[mActiveContent]; +} diff --git a/src/gui/tabbedcontainer.h b/src/gui/tabbedcontainer.h index 2dc017ae..7f8deef9 100644 --- a/src/gui/tabbedcontainer.h +++ b/src/gui/tabbedcontainer.h @@ -26,6 +26,7 @@ #include #include +#include #include @@ -41,18 +42,25 @@ class TabbedContainer : public gcn::Container, public gcn::ActionListener void addTab(gcn::Widget *widget, const std::string &caption); + void removeTab(const std::string &caption); + void logic(); void action(const gcn::ActionEvent &event); void setOpaque(bool opaque); + short getNumberOfTabs(); + + std::string getActiveWidget(); + private: typedef std::vector Widgets; typedef Widgets::iterator WidgetIterator; - Widgets mTabs; // The actual tabs at the top + std::map mTabs; // tabs mapped to their channel name Widgets mContents; // The contents of the tabs + std::map mWidgets; gcn::Widget *mActiveContent; }; diff --git a/src/net/chathandler.cpp b/src/net/chathandler.cpp index f765f0f4..076be056 100644 --- a/src/net/chathandler.cpp +++ b/src/net/chathandler.cpp @@ -25,6 +25,7 @@ #include #include +#include #include "messagein.h" #include "protocol.h" @@ -43,6 +44,11 @@ ChatHandler::ChatHandler() { static const Uint16 _messages[] = { GPMSG_SAY, + CPMSG_REGISTER_CHANNEL_RESPONSE, + CPMSG_ENTER_CHANNEL_RESPONSE, + CPMSG_LIST_CHANNELS_RESPONSE, + CPMSG_PUBMSG, + CPMSG_QUIT_CHANNEL_RESPONSE, /* SMSG_BEING_CHAT, SMSG_PLAYER_CHAT, @@ -59,6 +65,9 @@ void ChatHandler::handleMessage(MessageIn &msg) { Being *being; std::string chatMsg; + short channelId; + std::string userNick; + std::string channelName; //Sint16 chatMsgLength; switch (msg.getId()) @@ -76,7 +85,74 @@ void ChatHandler::handleMessage(MessageIn &msg) chatWindow->chatLog("John Doe : " + chatMsg, BY_OTHER); } break; + case CPMSG_REGISTER_CHANNEL_RESPONSE: + if(msg.readByte() == ERRMSG_OK) + { + channelId = msg.readShort(); + std::string channelName = msg.readString(); + chatWindow->chatLog("Registered Channel " + channelName, BY_SERVER); + chatWindow->addChannel(channelId, channelName); + chatWindow->createNewChannelTab(channelName); + } + else + { + chatWindow->chatLog("Error registering channel", BY_SERVER); + } + break; + case CPMSG_ENTER_CHANNEL_RESPONSE: + if(msg.readByte() == ERRMSG_OK) + { + channelId = msg.readShort(); + channelName = msg.readString(); + std::string announcement = msg.readString(); + std::vector userList; + while(msg.getUnreadLength()) + { + userList.push_back(msg.readString()); + } + chatWindow->addChannel(channelId, channelName); + chatWindow->createNewChannelTab(channelName); + chatWindow->chatLog(announcement, BY_SERVER, channelName); + } + else + { + chatWindow->chatLog("Error joining channel", BY_SERVER); + } + break; + + case CPMSG_LIST_CHANNELS_RESPONSE: + chatWindow->chatLog("Listing Channels", BY_SERVER); + while(msg.getUnreadLength()) + { + channelName = msg.readString(); + std::ostringstream numUsers; + numUsers << msg.readShort(); + if(channelName != "") + { + channelName += " - "; + channelName += numUsers.str(); + chatWindow->chatLog(channelName, BY_SERVER); + } + } + chatWindow->chatLog("End of channel list", BY_SERVER); + break; + case CPMSG_PUBMSG: + channelId = msg.readShort(); + userNick = msg.readString(); + chatMsg = msg.readString(); + + chatWindow->sendToChannel(channelId, userNick, chatMsg); + break; + + case CPMSG_QUIT_CHANNEL_RESPONSE: + if(msg.readByte() == ERRMSG_OK) + { + channelId = msg.readShort(); + // remove the chat tab + chatWindow->removeChannel(channelId); + } + break; /* // Received speech from being case SMSG_BEING_CHAT: diff --git a/src/net/chatserver/chatserver.cpp b/src/net/chatserver/chatserver.cpp index 32979ea5..f24e4cd5 100644 --- a/src/net/chatserver/chatserver.cpp +++ b/src/net/chatserver/chatserver.cpp @@ -81,14 +81,14 @@ void Net::ChatServer::privMsg(const std::string &recipient, } void Net::ChatServer::registerChannel(const std::string &name, - const std::string &annoucement, const std::string &password, + const std::string &announcement, const std::string &password, char isPrivate) { MessageOut msg(PCMSG_REGISTER_CHANNEL); msg.writeByte(isPrivate); msg.writeString(name); - msg.writeString(annoucement); + msg.writeString(announcement); msg.writeString(password); connection->send(msg); @@ -103,11 +103,11 @@ void Net::ChatServer::unregisterChannel(short channel) connection->send(msg); } -void Net::ChatServer::enterChannel(short channel, const std::string &password) +void Net::ChatServer::enterChannel(const std::string &channel, const std::string &password) { MessageOut msg(PCMSG_ENTER_CHANNEL); - msg.writeShort(channel); + msg.writeString(channel); msg.writeString(password); connection->send(msg); @@ -121,3 +121,10 @@ void Net::ChatServer::quitChannel(short channel) connection->send(msg); } + +void Net::ChatServer::getChannelList() +{ + MessageOut msg(PCMSG_LIST_CHANNELS); + + connection->send(msg); +} diff --git a/src/net/chatserver/chatserver.h b/src/net/chatserver/chatserver.h index cf86baf3..c4e0003d 100644 --- a/src/net/chatserver/chatserver.h +++ b/src/net/chatserver/chatserver.h @@ -48,9 +48,12 @@ namespace Net void unregisterChannel(short channel); - void enterChannel(short channel, const std::string &password); + void enterChannel(const std::string &channel, const std::string &password); void quitChannel(short channel); + + void getChannelList(); + } } diff --git a/src/net/protocol.h b/src/net/protocol.h index 78a42e42..eb27af7d 100644 --- a/src/net/protocol.h +++ b/src/net/protocol.h @@ -119,7 +119,7 @@ enum { // Login/Register PAMSG_REGISTER = 0x0000, // L version, S username, S password, S email APMSG_REGISTER_RESPONSE = 0x0002, // B error - PAMSG_UNREGISTER = 0x0003, // S username, S password + PAMSG_UNREGISTER = 0x0003, // - APMSG_UNREGISTER_RESPONSE = 0x0004, // B error PAMSG_LOGIN = 0x0010, // L version, S username, S password APMSG_LOGIN_RESPONSE = 0x0012, // B error @@ -175,6 +175,7 @@ enum { PGMSG_USE_ITEM = 0x0300, // L item id GPMSG_USE_RESPONSE = 0x0301, // B error GPMSG_BEINGS_DAMAGE = 0x0310, // { W being id, W amount }* + GPMSG_BEING_DEAD = 0xDEAD, // W being id // Chat CPMSG_ERROR = 0x0401, // B error @@ -186,14 +187,16 @@ enum { PCMSG_PRIVMSG = 0x0412, // S user, S text // -- Channeling PCMSG_REGISTER_CHANNEL = 0x0413, // B pub/priv, S name, S announcement, S password - CPMSG_REGISTER_CHANNEL_RESPONSE = 0x0414, // B error + CPMSG_REGISTER_CHANNEL_RESPONSE = 0x0414, // B error, W channel, S channel PCMSG_UNREGISTER_CHANNEL = 0x0415, // W channel CPMSG_UNREGISTER_CHANNEL_RESPONSE = 0x0416, // B error CPMSG_CHANNEL_EVENT = 0x0418, // W channel, B event, S user PCMSG_ENTER_CHANNEL = 0x0419, // W channel, S password - CPMSG_ENTER_CHANNEL_RESPONSE = 0x0420, // B error + CPMSG_ENTER_CHANNEL_RESPONSE = 0x0420, // B error, W channel, S channel PCMSG_QUIT_CHANNEL = 0x0421, // W channel CPMSG_QUIT_CHANNEL_RESPONSE = 0x0422, // B error + PCMSG_LIST_CHANNELS = 0x0423, // - + CPMSG_LIST_CHANNELS_RESPONSE = 0x0424, // W number of channels, S channels XXMSG_INVALID = 0x7FFF }; -- cgit v1.2.3-70-g09d2 From e2e4ceb9fa8a72ad94853f74724676fff82b15c0 Mon Sep 17 00:00:00 2001 From: David Athay Date: Tue, 15 Apr 2008 15:42:04 +0000 Subject: Added online status of guild members --- ChangeLog | 11 +++++++++++ data/graphics/gui/circle-gray.png | Bin 0 -> 295 bytes data/graphics/gui/circle-green.png | Bin 0 -> 299 bytes src/Makefile.am | 2 ++ src/gui/guildlistbox.cpp | 35 ++++++++++++++++++++++++++--------- src/gui/guildlistbox.h | 26 +++++++++++++++++--------- src/gui/guildwindow.cpp | 18 +++++++++++++++--- src/gui/guildwindow.h | 7 ++++++- src/gui/widgets/tabbedarea.cpp | 15 ++++++++++++++- src/gui/widgets/tabbedarea.h | 6 ++++++ src/net/chathandler.cpp | 23 ++++++++++++++++++++++- src/net/chatserver/chatserver.cpp | 9 +++++++++ src/net/chatserver/chatserver.h | 2 ++ src/net/guildhandler.cpp | 11 +++++++++++ src/net/protocol.h | 2 +- tmw.cbp | 5 ++--- 16 files changed, 144 insertions(+), 28 deletions(-) create mode 100644 data/graphics/gui/circle-gray.png create mode 100644 data/graphics/gui/circle-green.png (limited to 'src/net/chatserver/chatserver.h') diff --git a/ChangeLog b/ChangeLog index 63d46e50..f45af6e5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2008-04-15 David Athay + + * src/gui/guildlistbox.cpp, src/gui/guildwindow.h + src/gui/widgets/tabbedarea.h, src/gui/widgets/tabbedarea.cpp, + src/gui/guildlistbox.h, src/gui/guildwindow.cpp, + src/net/guildhandler.cpp, src/net/protocol.h, src/net/chathandler.cpp, + src/net/chatserver/chatserver.cpp, src/net/chatserver/chatserver.h, + src/Makefile.am, data/graphics/gui/circle-green.png + data/graphics/gui/circle-gray.png, tmw.cbp: Added online status of + guild members. + 2008-04-14 Yohann Ferreira * src/CMakeLists.txt: Fixed (again) a compilation error using CMake. diff --git a/data/graphics/gui/circle-gray.png b/data/graphics/gui/circle-gray.png new file mode 100644 index 00000000..719b0b10 Binary files /dev/null and b/data/graphics/gui/circle-gray.png differ diff --git a/data/graphics/gui/circle-green.png b/data/graphics/gui/circle-green.png new file mode 100644 index 00000000..bab39e05 Binary files /dev/null and b/data/graphics/gui/circle-green.png differ diff --git a/src/Makefile.am b/src/Makefile.am index c46fe481..3cfa64ea 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,6 +7,8 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \ gui/widgets/layout.h \ gui/widgets/resizegrip.cpp \ gui/widgets/resizegrip.h \ + gui/widgets/tabbedarea.cpp \ + gui/widgets/tabbedarea.h \ gui/box.h \ gui/box.cpp \ gui/browserbox.cpp \ diff --git a/src/gui/guildlistbox.cpp b/src/gui/guildlistbox.cpp index 11661235..1c14fd55 100644 --- a/src/gui/guildlistbox.cpp +++ b/src/gui/guildlistbox.cpp @@ -1,6 +1,6 @@ /* * The Mana World - * Copyright 2004 The Mana World Development Team + * Copyright 2008 The Mana World Development Team * * This file is part of The Mana World. * @@ -18,25 +18,32 @@ * 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$ + * $Id $ */ #include "guildlistbox.h" #include "../graphics.h" +#include "../resources/image.h" +#include "../resources/resourcemanager.h" + #include GuildListBox::GuildListBox(): ListBox(NULL) { + onlineIcon = ResourceManager::getInstance()->getImage("graphics/gui/circle-green.png"); + offlineIcon = ResourceManager::getInstance()->getImage("graphics/gui/circle-gray.png"); } -void GuildListBox::draw(gcn::Graphics *graphics) +void GuildListBox::draw(gcn::Graphics *gcnGraphics) { if (!mListModel) return; + Graphics *graphics = static_cast(gcnGraphics); + graphics->setColor(gcn::Color(110, 160, 255)); graphics->setFont(getFont()); @@ -48,17 +55,22 @@ void GuildListBox::draw(gcn::Graphics *graphics) getWidth(), fontHeight)); } - // TODO: Add online status image - // Draw the list elements for (int i = 0, y = 0; i < mListModel->getNumberOfElements(); ++i, y += fontHeight) { - graphics->drawText(mListModel->getElementAt(i), 1, y); + // Draw online status + bool online = mUsers[mListModel->getElementAt(i)]; + Image *icon = online ? onlineIcon : offlineIcon; + if (icon) + graphics->drawImage(icon, 1, y); + // Draw Name + graphics->setColor(gcn::Color(0, 0, 0)); + graphics->drawText(mListModel->getElementAt(i), 33, y); } } - +/* void GuildListBox::setSelected(int selected) { if (!mListModel) @@ -84,14 +96,19 @@ void GuildListBox::setSelected(int selected) distributeValueChangedEvent(); } - +*/ void GuildListBox::mousePressed(gcn::MouseEvent &event) { if (event.getButton() == gcn::MouseEvent::LEFT) { - // TODO: Add guild functions, ie private messaging int y = event.getY(); setSelected(y / getFont()->getHeight()); distributeActionEvent(); } + // TODO: Add guild functions, ie private messaging +} + +void GuildListBox::setOnlineStatus(const std::string &user, bool online) +{ + mUsers[user] = online; } diff --git a/src/gui/guildlistbox.h b/src/gui/guildlistbox.h index 262012a4..0f030d0a 100644 --- a/src/gui/guildlistbox.h +++ b/src/gui/guildlistbox.h @@ -1,6 +1,6 @@ /* * The Mana World - * Copyright 2004 The Mana World Development Team + * Copyright 2008 The Mana World Development Team * * This file is part of The Mana World. * @@ -18,17 +18,20 @@ * 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$ + * $Id $ */ #ifndef _TMW_GUI_GUILDLISTBOX_H #define _TMW_GUI_GUILDLISTBOX_H +#include #include #include #include "listbox.h" +class Image; + class GuildListBox : public ListBox { public: @@ -37,22 +40,27 @@ public: */ GuildListBox(); - /** - * Set ListModel - */ - void setList(gcn::ListModel *listModel); - /** * Draws the list box. */ - void draw(gcn::Graphics *graphics); + void draw(gcn::Graphics *gcnGraphics); void mousePressed(gcn::MouseEvent &event); /** * Sets the index of the selected element. */ - void setSelected(int selected); +// void setSelected(int selected); + + /** + * Set whether a member is online or offline + */ + void setOnlineStatus(const std::string &user, bool online); + +private: + Image *onlineIcon; + Image *offlineIcon; + std::map mUsers; }; #endif diff --git a/src/gui/guildwindow.cpp b/src/gui/guildwindow.cpp index 7b69f9bf..7237a870 100644 --- a/src/gui/guildwindow.cpp +++ b/src/gui/guildwindow.cpp @@ -84,7 +84,7 @@ GuildWindow::~GuildWindow() void GuildWindow::update() { - + updateTab(); } void GuildWindow::draw(gcn::Graphics *g) @@ -172,7 +172,7 @@ void GuildWindow::newGuildTab(const std::string &guildName) { // Create new tab - ListBox *list = new ListBox(); + GuildListBox *list = new GuildListBox(); list->setListModel(player_node->getGuild(guildName)); ScrollArea *sa = new ScrollArea(list); sa->setDimension(gcn::Rectangle(5, 5, 135, 250)); @@ -224,7 +224,8 @@ short GuildWindow::getSelectedGuild() return 0; } -void GuildWindow::openAcceptDialog(const std::string &inviterName, const std::string &guildName) +void GuildWindow::openAcceptDialog(const std::string &inviterName, + const std::string &guildName) { std::string msg = inviterName + " has invited you to join the guild " + guildName; chatWindow->chatLog(msg, BY_SERVER); @@ -248,6 +249,17 @@ void GuildWindow::removeTab(int guildId) { gcn::Tab *tab = mGuildTabs->getTab(guild->getName()); mGuildTabs->removeTab(tab); + updateTab(); } mGuildTabs->logic(); } + +void GuildWindow::setOnline(const std::string &guildName, const std::string &member, + bool online) +{ + GuildListBox *box = dynamic_cast(mGuildTabs->getWidget(guildName)); + if (box) + { + box->setOnlineStatus(member, online); + } +} diff --git a/src/gui/guildwindow.h b/src/gui/guildwindow.h index f6cb38fd..b85ca3a5 100644 --- a/src/gui/guildwindow.h +++ b/src/gui/guildwindow.h @@ -112,6 +112,12 @@ public: */ void removeTab(int guildId); + /** + * Set guild member status in userlist + */ + void setOnline(const std::string &guildName, const std::string &member, + bool online); + protected: /** * Get selected guild tab @@ -125,7 +131,6 @@ private: TextDialog *inviteDialog; ConfirmDialog *acceptDialog; TabbedArea *mGuildTabs; - GuildListBox *mGuildMembersList; ScrollArea *mScrollArea; bool mFocus; std::string invitedGuild; diff --git a/src/gui/widgets/tabbedarea.cpp b/src/gui/widgets/tabbedarea.cpp index 6ba27622..20c100e5 100644 --- a/src/gui/widgets/tabbedarea.cpp +++ b/src/gui/widgets/tabbedarea.cpp @@ -56,7 +56,6 @@ void TabbedArea::draw(gcn::Graphics *graphics) return; } - std::vector< std::pair >::iterator itr; unsigned int i; for (i = 0; i < mTabs.size(); i++) { @@ -71,3 +70,17 @@ void TabbedArea::draw(gcn::Graphics *graphics) gcn::TabbedArea::draw(graphics); } + +gcn::Widget* TabbedArea::getWidget(const std::string &name) +{ + unsigned int i; + for (i = 0; i < mTabs.size(); i++) + { + if (mTabs[i].first->getCaption() == name) + { + return mTabs[i].second; + } + } + + return NULL; +} diff --git a/src/gui/widgets/tabbedarea.h b/src/gui/widgets/tabbedarea.h index 42275fae..3f58acde 100644 --- a/src/gui/widgets/tabbedarea.h +++ b/src/gui/widgets/tabbedarea.h @@ -24,6 +24,7 @@ #ifndef _TMW_TABBEDAREA_H #define _TMW_TABBEDAREA_H +#include #include #include @@ -54,6 +55,11 @@ class TabbedArea : public gcn::TabbedArea * Return tab with specified name as caption */ gcn::Tab* getTab(const std::string &name); + + /** + * Return selected tab's widget + */ + gcn::Widget* getWidget(const std::string &name); }; #endif diff --git a/src/net/chathandler.cpp b/src/net/chathandler.cpp index 4d48865a..d8a228ea 100644 --- a/src/net/chathandler.cpp +++ b/src/net/chathandler.cpp @@ -35,6 +35,7 @@ #include "../game.h" #include "../gui/chat.h" +#include "../gui/guildwindow.h" #include "../utils/tostring.h" @@ -49,6 +50,7 @@ ChatHandler::ChatHandler() CPMSG_LIST_CHANNELS_RESPONSE, CPMSG_PUBMSG, CPMSG_QUIT_CHANNEL_RESPONSE, + CPMSG_LIST_CHANNELUSERS_RESPONSE, /* SMSG_BEING_CHAT, SMSG_PLAYER_CHAT, @@ -106,9 +108,13 @@ void ChatHandler::handleMessage(MessageIn &msg) channelName = msg.readString(); std::string announcement = msg.readString(); std::vector userList; + std::string user; while(msg.getUnreadLength()) { - userList.push_back(msg.readString()); + user = msg.readString(); + if (user == "") + break; + userList.push_back(user); } chatWindow->addChannel(channelId, channelName); chatWindow->createNewChannelTab(channelName); @@ -125,6 +131,8 @@ void ChatHandler::handleMessage(MessageIn &msg) while(msg.getUnreadLength()) { channelName = msg.readString(); + if (channelName == "") + break; std::ostringstream numUsers; numUsers << msg.readInt16(); if(channelName != "") @@ -164,6 +172,19 @@ void ChatHandler::handleMessage(MessageIn &msg) chatWindow->removeChannel(channelId); } break; + + case CPMSG_LIST_CHANNELUSERS_RESPONSE: + channelName = msg.readString(); + while(msg.getUnreadLength()) + { + userNick = msg.readString(); + if (userNick == "") + { + break; + } + guildWindow->setOnline(channelName, userNick, true); + } + break; /* // Received speech from being case SMSG_BEING_CHAT: diff --git a/src/net/chatserver/chatserver.cpp b/src/net/chatserver/chatserver.cpp index 93fdc828..67cb5796 100644 --- a/src/net/chatserver/chatserver.cpp +++ b/src/net/chatserver/chatserver.cpp @@ -128,3 +128,12 @@ void Net::ChatServer::getChannelList() connection->send(msg); } + +void Net::ChatServer::getUserList(const std::string &channel) +{ + MessageOut msg(PCMSG_LIST_CHANNELUSERS); + + msg.writeString(channel); + + connection->send(msg); +} diff --git a/src/net/chatserver/chatserver.h b/src/net/chatserver/chatserver.h index c4e0003d..b49d0c9e 100644 --- a/src/net/chatserver/chatserver.h +++ b/src/net/chatserver/chatserver.h @@ -54,6 +54,8 @@ namespace Net void getChannelList(); + void getUserList(const std::string &channel); + } } diff --git a/src/net/guildhandler.cpp b/src/net/guildhandler.cpp index 494dcdc0..fd23546c 100644 --- a/src/net/guildhandler.cpp +++ b/src/net/guildhandler.cpp @@ -99,20 +99,30 @@ void GuildHandler::handleMessage(MessageIn &msg) if(msg.readInt8() == ERRMSG_OK) { std::string guildMember; + std::string guildName; Guild *guild; + short guildId = msg.readInt16(); guild = player_node->getGuild(guildId); + if (!guild) return; + + guildName = guild->getName(); + while(msg.getUnreadLength()) { guildMember = msg.readString(); if(guildMember != "") { guild->addMember(guildMember); + guildWindow->setOnline(guildName, guildMember, false); } } + guildWindow->updateTab(); + + Net::ChatServer::getUserList(guildName); } } break; @@ -126,6 +136,7 @@ void GuildHandler::handleMessage(MessageIn &msg) if (guild) { guild->addMember(guildMember); + guildWindow->setOnline(guild->getName(), guildMember, false); } guildWindow->updateTab(); } break; diff --git a/src/net/protocol.h b/src/net/protocol.h index 748a4e11..79e1f2ca 100644 --- a/src/net/protocol.h +++ b/src/net/protocol.h @@ -171,7 +171,7 @@ enum { CPMSG_USERJOINED = 0x0450, // W channel, S name CPMSG_USERLEFT = 0x0451, // W channel, S name PCMSG_LIST_CHANNELUSERS = 0x0460, // S channel - CPMSG_LIST_CHANNELUSERS_RESPONSE = 0x0461, // S users + CPMSG_LIST_CHANNELUSERS_RESPONSE = 0x0461, // S channel, S users XXMSG_INVALID = 0x7FFF }; diff --git a/tmw.cbp b/tmw.cbp index d503d01d..d30bb0e2 100644 --- a/tmw.cbp +++ b/tmw.cbp @@ -303,9 +303,6 @@ - -