summaryrefslogtreecommitdiff
path: root/src/net/manaserv
diff options
context:
space:
mode:
authorJared Adams <jaxad0127@gmail.com>2009-10-24 10:58:58 -0600
committerJared Adams <jaxad0127@gmail.com>2009-10-24 10:58:58 -0600
commitc3ac3fb3b95d0abcd2cbc51e8ff1f2498cc6841b (patch)
tree709fda8a3974b5e73d4cd4d7e688c544ce03ed96 /src/net/manaserv
parent86e5e4c5bd29abcd90d21a64fdea7eac73665356 (diff)
downloadmana-c3ac3fb3b95d0abcd2cbc51e8ff1f2498cc6841b.tar.gz
mana-c3ac3fb3b95d0abcd2cbc51e8ff1f2498cc6841b.tar.bz2
mana-c3ac3fb3b95d0abcd2cbc51e8ff1f2498cc6841b.tar.xz
mana-c3ac3fb3b95d0abcd2cbc51e8ff1f2498cc6841b.zip
REplace instances of TMW with Mana
Diffstat (limited to 'src/net/manaserv')
-rw-r--r--src/net/manaserv/accountserver/account.cpp108
-rw-r--r--src/net/manaserv/accountserver/account.h54
-rw-r--r--src/net/manaserv/accountserver/accountserver.cpp82
-rw-r--r--src/net/manaserv/accountserver/accountserver.h47
-rw-r--r--src/net/manaserv/accountserver/internal.cpp32
-rw-r--r--src/net/manaserv/accountserver/internal.h35
-rw-r--r--src/net/manaserv/adminhandler.cpp85
-rw-r--r--src/net/manaserv/adminhandler.h57
-rw-r--r--src/net/manaserv/beinghandler.cpp325
-rw-r--r--src/net/manaserv/beinghandler.h49
-rw-r--r--src/net/manaserv/buysellhandler.cpp95
-rw-r--r--src/net/manaserv/buysellhandler.h39
-rw-r--r--src/net/manaserv/charhandler.cpp385
-rw-r--r--src/net/manaserv/charhandler.h81
-rw-r--r--src/net/manaserv/chathandler.cpp459
-rw-r--r--src/net/manaserv/chathandler.h128
-rw-r--r--src/net/manaserv/chatserver/chatserver.cpp54
-rw-r--r--src/net/manaserv/chatserver/chatserver.h44
-rw-r--r--src/net/manaserv/chatserver/guild.cpp95
-rw-r--r--src/net/manaserv/chatserver/guild.h67
-rw-r--r--src/net/manaserv/chatserver/internal.cpp32
-rw-r--r--src/net/manaserv/chatserver/internal.h35
-rw-r--r--src/net/manaserv/chatserver/party.cpp79
-rw-r--r--src/net/manaserv/chatserver/party.h61
-rw-r--r--src/net/manaserv/connection.cpp105
-rw-r--r--src/net/manaserv/connection.h81
-rw-r--r--src/net/manaserv/effecthandler.cpp80
-rw-r--r--src/net/manaserv/effecthandler.h43
-rw-r--r--src/net/manaserv/gamehandler.cpp132
-rw-r--r--src/net/manaserv/gamehandler.h60
-rw-r--r--src/net/manaserv/gameserver/gameserver.cpp50
-rw-r--r--src/net/manaserv/gameserver/gameserver.h39
-rw-r--r--src/net/manaserv/gameserver/internal.cpp32
-rw-r--r--src/net/manaserv/gameserver/internal.h35
-rw-r--r--src/net/manaserv/gameserver/player.cpp57
-rw-r--r--src/net/manaserv/gameserver/player.h51
-rw-r--r--src/net/manaserv/generalhandler.cpp190
-rw-r--r--src/net/manaserv/generalhandler.h74
-rw-r--r--src/net/manaserv/guildhandler.cpp254
-rw-r--r--src/net/manaserv/guildhandler.h44
-rw-r--r--src/net/manaserv/internal.cpp27
-rw-r--r--src/net/manaserv/internal.h30
-rw-r--r--src/net/manaserv/inventoryhandler.cpp167
-rw-r--r--src/net/manaserv/inventoryhandler.h61
-rw-r--r--src/net/manaserv/itemhandler.cpp70
-rw-r--r--src/net/manaserv/itemhandler.h39
-rw-r--r--src/net/manaserv/loginhandler.cpp359
-rw-r--r--src/net/manaserv/loginhandler.h84
-rw-r--r--src/net/manaserv/network.cpp170
-rw-r--r--src/net/manaserv/network.h79
-rw-r--r--src/net/manaserv/npchandler.cpp206
-rw-r--r--src/net/manaserv/npchandler.h69
-rw-r--r--src/net/manaserv/partyhandler.cpp179
-rw-r--r--src/net/manaserv/partyhandler.h71
-rw-r--r--src/net/manaserv/playerhandler.cpp411
-rw-r--r--src/net/manaserv/playerhandler.h69
-rw-r--r--src/net/manaserv/protocol.h313
-rw-r--r--src/net/manaserv/specialhandler.cpp67
-rw-r--r--src/net/manaserv/specialhandler.h48
-rw-r--r--src/net/manaserv/tradehandler.cpp226
-rw-r--r--src/net/manaserv/tradehandler.h74
61 files changed, 6674 insertions, 0 deletions
diff --git a/src/net/manaserv/accountserver/account.cpp b/src/net/manaserv/accountserver/account.cpp
new file mode 100644
index 00000000..f34139da
--- /dev/null
+++ b/src/net/manaserv/accountserver/account.cpp
@@ -0,0 +1,108 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "account.h"
+
+#include "internal.h"
+
+#include "net/manaserv/connection.h"
+#include "net/manaserv/protocol.h"
+
+#include "net/messageout.h"
+
+#include "utils/sha256.h"
+
+#include <string>
+
+void Net::AccountServer::Account::createCharacter(
+ const std::string &name, char hairStyle, char hairColor, char gender,
+ short strength, short agility, short vitality,
+ short intelligence, short dexterity, short willpower)
+{
+ MessageOut msg(PAMSG_CHAR_CREATE);
+
+ msg.writeString(name);
+ msg.writeInt8(hairStyle);
+ msg.writeInt8(hairColor);
+ msg.writeInt8(gender);
+ msg.writeInt16(strength);
+ msg.writeInt16(agility);
+ msg.writeInt16(vitality);
+ msg.writeInt16(intelligence);
+ msg.writeInt16(dexterity);
+ msg.writeInt16(willpower);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::deleteCharacter(char slot)
+{
+ MessageOut msg(PAMSG_CHAR_DELETE);
+
+ msg.writeInt8(slot);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::selectCharacter(char slot)
+{
+ MessageOut msg(PAMSG_CHAR_SELECT);
+
+ msg.writeInt8(slot);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::unregister(const std::string &username,
+ const std::string &password)
+{
+ MessageOut msg(PAMSG_UNREGISTER);
+
+ msg.writeString(username);
+ msg.writeString(sha256(username + password));
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::changeEmail(const std::string &email)
+{
+ MessageOut msg(PAMSG_EMAIL_CHANGE);
+
+ // Email is sent clearly so the server can validate the data.
+ // Encryption is assumed server-side.
+ msg.writeString(email);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::changePassword(
+ const std::string &username,
+ const std::string &oldPassword,
+ const std::string &newPassword)
+{
+ MessageOut msg(PAMSG_PASSWORD_CHANGE);
+
+ // Change password using SHA2 encryption
+ msg.writeString(sha256(username + oldPassword));
+ msg.writeString(sha256(username + newPassword));
+
+ Net::AccountServer::connection->send(msg);
+}
diff --git a/src/net/manaserv/accountserver/account.h b/src/net/manaserv/accountserver/account.h
new file mode 100644
index 00000000..03e83881
--- /dev/null
+++ b/src/net/manaserv/accountserver/account.h
@@ -0,0 +1,54 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_ACCOUNTSERVER_CHARACTER_H
+#define NET_ACCOUNTSERVER_CHARACTER_H
+
+#include <iosfwd>
+
+namespace Net
+{
+ namespace AccountServer
+ {
+ namespace Account
+ {
+ void createCharacter(const std::string &name,
+ char hairStyle, char hairColor, char gender,
+ short strength, short agility, short vitality,
+ short intelligence, short dexterity, short willpower);
+
+ void deleteCharacter(char slot);
+
+ void selectCharacter(char slot);
+
+ void unregister(const std::string &username,
+ const std::string &password);
+
+ void changeEmail(const std::string &email);
+
+ void changePassword(const std::string &username,
+ const std::string &oldPassword,
+ const std::string &newPassword);
+ }
+ }
+}
+
+#endif
diff --git a/src/net/manaserv/accountserver/accountserver.cpp b/src/net/manaserv/accountserver/accountserver.cpp
new file mode 100644
index 00000000..72f05aeb
--- /dev/null
+++ b/src/net/manaserv/accountserver/accountserver.cpp
@@ -0,0 +1,82 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "accountserver.h"
+
+#include "internal.h"
+
+#include "net/manaserv/connection.h"
+#include "net/manaserv/protocol.h"
+
+#include "net/messageout.h"
+
+#include "utils/sha256.h"
+
+#include <string>
+
+void Net::AccountServer::login(Net::Connection *connection, int version,
+ const std::string &username, const std::string &password)
+{
+ Net::AccountServer::connection = connection;
+
+ MessageOut msg(PAMSG_LOGIN);
+
+ msg.writeInt32(version);
+ msg.writeString(username);
+ msg.writeString(sha256(username + password));
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::registerAccount(Net::Connection *connection,
+ int version, const std::string &username, const std::string &password,
+ const std::string &email)
+{
+ Net::AccountServer::connection = connection;
+
+ MessageOut msg(PAMSG_REGISTER);
+
+ msg.writeInt32(version); // client version
+ msg.writeString(username);
+ // When registering, the password and email hash is assumed by server.
+ // Hence, data can be validated safely server-side.
+ // This is the only time we send a clear password.
+ msg.writeString(password);
+ msg.writeString(email);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::logout()
+{
+ MessageOut msg(PAMSG_LOGOUT);
+ Net::AccountServer::connection->send(msg);
+}
+
+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/manaserv/accountserver/accountserver.h b/src/net/manaserv/accountserver/accountserver.h
new file mode 100644
index 00000000..dd62fd25
--- /dev/null
+++ b/src/net/manaserv/accountserver/accountserver.h
@@ -0,0 +1,47 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_ACCOUNTSERVER_ACCOUNTSERVER_H
+#define NET_ACCOUNTSERVER_ACCOUNTSERVER_H
+
+#include <iosfwd>
+
+namespace Net
+{
+ class Connection;
+
+ namespace AccountServer
+ {
+ void login(Net::Connection *connection, int version,
+ const std::string &username, const std::string &password);
+
+ void registerAccount(Net::Connection *connection, int version,
+ const std::string &username, const std::string &password,
+ const std::string &email);
+
+ void logout();
+
+ void reconnectAccount(Net::Connection *connection,
+ const std::string &passToken);
+ }
+}
+
+#endif
diff --git a/src/net/manaserv/accountserver/internal.cpp b/src/net/manaserv/accountserver/internal.cpp
new file mode 100644
index 00000000..de1d412c
--- /dev/null
+++ b/src/net/manaserv/accountserver/internal.cpp
@@ -0,0 +1,32 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "internal.h"
+
+namespace Net
+{
+ class Connection;
+
+ namespace AccountServer
+ {
+ Connection *connection = 0;
+ }
+}
diff --git a/src/net/manaserv/accountserver/internal.h b/src/net/manaserv/accountserver/internal.h
new file mode 100644
index 00000000..ff741872
--- /dev/null
+++ b/src/net/manaserv/accountserver/internal.h
@@ -0,0 +1,35 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_ACCOUNTSERVER_INTERNAL_H
+#define NET_ACCOUNTSERVER_INTERNAL_H
+
+namespace Net
+{
+ class Connection;
+
+ namespace AccountServer
+ {
+ extern Connection *connection;
+ }
+}
+
+#endif
diff --git a/src/net/manaserv/adminhandler.cpp b/src/net/manaserv/adminhandler.cpp
new file mode 100644
index 00000000..72ae01d0
--- /dev/null
+++ b/src/net/manaserv/adminhandler.cpp
@@ -0,0 +1,85 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "net/manaserv/adminhandler.h"
+
+#include "net/manaserv/chatserver/chatserver.h"
+
+Net::AdminHandler *adminHandler;
+
+namespace ManaServ {
+
+AdminHandler::AdminHandler()
+{
+ adminHandler = this;
+}
+
+void AdminHandler::announce(const std::string &text)
+{
+ Net::ChatServer::announce(text);
+}
+
+void AdminHandler::localAnnounce(const std::string &text)
+{
+ // TODO
+}
+
+void AdminHandler::hide(bool hide)
+{
+ // TODO
+}
+
+void AdminHandler::kick(int playerId)
+{
+ // TODO
+}
+
+void AdminHandler::kick(const std::string &name)
+{
+ // TODO
+}
+
+void AdminHandler::ban(int playerId)
+{
+ // TODO
+}
+
+void AdminHandler::ban(const std::string &name)
+{
+ // TODO
+}
+
+void AdminHandler::unban(int playerId)
+{
+ // TODO
+}
+
+void AdminHandler::unban(const std::string &name)
+{
+ // TODO
+}
+
+void AdminHandler::mute(int playerId, int type, int limit)
+{
+ // TODO
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/adminhandler.h b/src/net/manaserv/adminhandler.h
new file mode 100644
index 00000000..e26eb04a
--- /dev/null
+++ b/src/net/manaserv/adminhandler.h
@@ -0,0 +1,57 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_MANASERV_ADMINHANDLER_H
+#define NET_MANASERV_ADMINHANDLER_H
+
+#include "net/adminhandler.h"
+
+namespace ManaServ {
+
+class AdminHandler : public Net::AdminHandler
+{
+ public:
+ AdminHandler();
+
+ void announce(const std::string &text);
+
+ void localAnnounce(const std::string &text);
+
+ void hide(bool hide);
+
+ void kick(int playerId);
+
+ void kick(const std::string &name);
+
+ void ban(int playerId);
+
+ void ban(const std::string &name);
+
+ void unban(int playerId);
+
+ void unban(const std::string &name);
+
+ void mute(int playerId, int type, int limit);
+};
+
+} // namespace ManaServ
+
+#endif
diff --git a/src/net/manaserv/beinghandler.cpp b/src/net/manaserv/beinghandler.cpp
new file mode 100644
index 00000000..3df346a4
--- /dev/null
+++ b/src/net/manaserv/beinghandler.cpp
@@ -0,0 +1,325 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "net/manaserv/beinghandler.h"
+
+#include "net/manaserv/protocol.h"
+
+#include "net/messagein.h"
+
+#include "being.h"
+#include "beingmanager.h"
+#include "game.h"
+#include "localplayer.h"
+#include "log.h"
+#include "main.h"
+#include "npc.h"
+#include "particle.h"
+#include "sound.h"
+
+#include "gui/okdialog.h"
+
+#include "resources/colordb.h"
+
+#include "utils/gettext.h"
+
+#include "net/manaserv/gameserver/player.h"
+
+namespace ManaServ {
+
+BeingHandler::BeingHandler()
+{
+ static const Uint16 _messages[] = {
+ GPMSG_BEING_ATTACK,
+ GPMSG_BEING_ENTER,
+ GPMSG_BEING_LEAVE,
+ GPMSG_BEINGS_MOVE,
+ GPMSG_BEINGS_DAMAGE,
+ GPMSG_BEING_ACTION_CHANGE,
+ GPMSG_BEING_LOOKS_CHANGE,
+ GPMSG_BEING_DIR_CHANGE,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void BeingHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case GPMSG_BEING_ENTER:
+ handleBeingEnterMessage(msg);
+ break;
+ case GPMSG_BEING_LEAVE:
+ handleBeingLeaveMessage(msg);
+ break;
+ case GPMSG_BEINGS_MOVE:
+ handleBeingsMoveMessage(msg);
+ break;
+ case GPMSG_BEING_ATTACK:
+ handleBeingAttackMessage(msg);
+ break;
+ case GPMSG_BEINGS_DAMAGE:
+ handleBeingsDamageMessage(msg);
+ break;
+ case GPMSG_BEING_ACTION_CHANGE:
+ handleBeingActionChangeMessage(msg);
+ break;
+ case GPMSG_BEING_LOOKS_CHANGE:
+ handleBeingLooksChangeMessage(msg);
+ break;
+ case GPMSG_BEING_DIR_CHANGE:
+ handleBeingDirChangeMessage(msg);
+ break;
+ }
+}
+
+static void handleLooks(Player *being, MessageIn &msg)
+{
+ // Order of sent slots. Has to be in sync with the server code.
+ static int const nb_slots = 4;
+ static int const slots[nb_slots] =
+ { Player::WEAPON_SPRITE, Player::HAT_SPRITE, Player::TOPCLOTHES_SPRITE,
+ Player::BOTTOMCLOTHES_SPRITE };
+
+ int mask = msg.readInt8();
+
+ if (mask & (1 << 7))
+ {
+ // The equipment has to be cleared first.
+ for (int i = 0; i < nb_slots; ++i)
+ {
+ being->setSprite(slots[i], 0);
+ }
+ }
+
+ // Fill slots enumerated by the bitmask.
+ for (int i = 0; i < nb_slots; ++i)
+ {
+ if (!(mask & (1 << i))) continue;
+ int id = msg.readInt16();
+ being->setSprite(slots[i], id);
+ }
+}
+
+void BeingHandler::handleBeingEnterMessage(MessageIn &msg)
+{
+ int type = msg.readInt8();
+ int id = msg.readInt16();
+ Being::Action action = (Being::Action)msg.readInt8();
+ int px = msg.readInt16();
+ int py = msg.readInt16();
+ Being *being;
+
+ switch (type)
+ {
+ case OBJECT_PLAYER:
+ {
+ std::string name = msg.readString();
+ if (player_node->getName() == name)
+ {
+ being = player_node;
+ being->setId(id);
+ }
+ else
+ {
+ being = beingManager->createBeing(id, Being::PLAYER, 0);
+ being->setName(name);
+ }
+ Player *p = static_cast< Player * >(being);
+ int hs = msg.readInt8(), hc = msg.readInt8();
+ p->setSprite(Player::HAIR_SPRITE, hs * -1, ColorDB::get(hc));
+ p->setGender(msg.readInt8() == GENDER_MALE ?
+ GENDER_MALE : GENDER_FEMALE);
+ handleLooks(p, msg);
+ } break;
+
+ case OBJECT_MONSTER:
+ case OBJECT_NPC:
+ {
+ int subtype = msg.readInt16();
+ being = beingManager->createBeing(id, type == OBJECT_MONSTER ?
+ Being::MONSTER : Being::NPC, subtype);
+ std::string name = msg.readString();
+ if (name.length() > 0) being->setName(name);
+ } break;
+
+ default:
+ return;
+ }
+
+ being->setPosition(px, py);
+ being->setDestination(px, py);
+ being->setAction(action);
+}
+
+void BeingHandler::handleBeingLeaveMessage(MessageIn &msg)
+{
+ Being *being = beingManager->findBeing(msg.readInt16());
+ if (!being)
+ return;
+
+ beingManager->destroyBeing(being);
+}
+
+void BeingHandler::handleBeingsMoveMessage(MessageIn &msg)
+{
+ while (msg.getUnreadLength())
+ {
+ int id = msg.readInt16();
+ int flags = msg.readInt8();
+ Being *being = beingManager->findBeing(id);
+ int sx = 0;
+ int sy = 0;
+ int speed = 0;
+
+ if (flags & MOVING_POSITION)
+ {
+ sx = msg.readInt16();
+ sy = msg.readInt16();
+ speed = msg.readInt8();
+ }
+ if (!being || !(flags & (MOVING_POSITION | MOVING_DESTINATION)))
+ {
+ continue;
+ }
+ if (speed)
+ {
+ // The being's speed is transfered in tiles per second * 10
+ // to keep it transferable in a Byte.
+ // We set it back to tiles per second and in a float.
+ being->setWalkSpeed((float) speed / 10);
+ }
+
+ // Ignore messages from the server for the local player
+ if (being == player_node)
+ continue;
+
+ if (flags & MOVING_POSITION)
+ {
+ being->setDestination(sx, sy);
+ }
+ }
+}
+
+void BeingHandler::handleBeingAttackMessage(MessageIn &msg)
+{
+ Being *being = beingManager->findBeing(msg.readInt16());
+ const int direction = msg.readInt8();
+ const int attackType = msg.readInt8();
+
+ if (!being)
+ return;
+
+ switch (direction)
+ {
+ case DIRECTION_UP: being->setDirection(Being::UP); break;
+ case DIRECTION_DOWN: being->setDirection(Being::DOWN); break;
+ case DIRECTION_LEFT: being->setDirection(Being::LEFT); break;
+ case DIRECTION_RIGHT: being->setDirection(Being::RIGHT); break;
+ }
+
+ being->setAction(Being::ATTACK, attackType);
+}
+
+void BeingHandler::handleBeingsDamageMessage(MessageIn &msg)
+{
+ while (msg.getUnreadLength())
+ {
+ Being *being = beingManager->findBeing(msg.readInt16());
+ int damage = msg.readInt16();
+ if (being)
+ {
+ being->takeDamage(0, damage, Being::HIT);
+ }
+ }
+}
+
+void BeingHandler::handleBeingActionChangeMessage(MessageIn &msg)
+{
+ Being *being = beingManager->findBeing(msg.readInt16());
+ Being::Action action = (Being::Action) msg.readInt8();
+ if (!being)
+ return;
+
+ being->setAction(action);
+
+ if (action == Being::DEAD && being == player_node)
+ {
+ static char const *const deadMsg[] =
+ {
+ _("You are dead."),
+ _("We regret to inform you that your character was killed in "
+ "battle."),
+ _("You are not that alive anymore."),
+ _("The cold hands of the grim reaper are grabbing for your soul."),
+ _("Game Over!"),
+ _("No, kids. Your character did not really die. It... err... "
+ "went to a better place."),
+ _("Your plan of breaking your enemies weapon by bashing it with "
+ "your throat failed."),
+ _("I guess this did not run too well."),
+ _("Do you want your possessions identified?"), // Nethack reference
+ _("Sadly, no trace of you was ever found..."), // Secret of Mana reference
+ _("Annihilated."), // Final Fantasy VI reference
+ _("Looks like you got your head handed to you."), // Earthbound reference
+ _("You screwed up again, dump your body down the tubes and get "
+ "you another one.") // Leisure Suit Larry 1 Reference
+
+ };
+ std::string message(deadMsg[rand()%13]);
+ message.append(std::string(" ") + _("Press OK to respawn."));
+ OkDialog *dlg = new OkDialog(_("You Died"), message);
+ dlg->addActionListener(&(Net::GameServer::Player::respawnListener));
+ }
+}
+
+void BeingHandler::handleBeingLooksChangeMessage(MessageIn &msg)
+{
+ Being *being = beingManager->findBeing(msg.readInt16());
+ if (!being || being->getType() != Being::PLAYER)
+ return;
+ Player *player = static_cast<Player *>(being);
+ handleLooks(player, msg);
+ if (msg.getUnreadLength())
+ {
+ int style = msg.readInt16();
+ int color = msg.readInt16();
+ player->setSprite(Player::HAIR_SPRITE, style * -1, ColorDB::get(color));
+ }
+}
+
+void BeingHandler::handleBeingDirChangeMessage(MessageIn &msg)
+{
+ Being *being = beingManager->findBeing(msg.readInt16());
+ if (!being)
+ return;
+ int data = msg.readInt8();
+ switch (data)
+ {
+ case DIRECTION_UP: being->setDirection(Being::UP); break;
+ case DIRECTION_DOWN: being->setDirection(Being::DOWN); break;
+ case DIRECTION_LEFT: being->setDirection(Being::LEFT); break;
+ case DIRECTION_RIGHT: being->setDirection(Being::RIGHT); break;
+ }
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/beinghandler.h b/src/net/manaserv/beinghandler.h
new file mode 100644
index 00000000..4ece08e1
--- /dev/null
+++ b/src/net/manaserv/beinghandler.h
@@ -0,0 +1,49 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_MANASERV_BEINGHANDLER_H
+#define NET_MANASERV_BEINGHANDLER_H
+
+#include "net/messagehandler.h"
+
+namespace ManaServ {
+
+class BeingHandler : public MessageHandler
+{
+ public:
+ BeingHandler();
+
+ void handleMessage(MessageIn &msg);
+
+ private:
+ void handleBeingAttackMessage(MessageIn &msg);
+ void handleBeingEnterMessage(MessageIn &msg);
+ void handleBeingLeaveMessage(MessageIn &msg);
+ void handleBeingsMoveMessage(MessageIn &msg);
+ void handleBeingsDamageMessage(MessageIn &msg);
+ void handleBeingActionChangeMessage(MessageIn &msg);
+ void handleBeingLooksChangeMessage(MessageIn &msg);
+ void handleBeingDirChangeMessage(MessageIn &msg);
+};
+
+} // namespace ManaServ
+
+#endif
diff --git a/src/net/manaserv/buysellhandler.cpp b/src/net/manaserv/buysellhandler.cpp
new file mode 100644
index 00000000..f7dc91a4
--- /dev/null
+++ b/src/net/manaserv/buysellhandler.cpp
@@ -0,0 +1,95 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "net/manaserv/buysellhandler.h"
+
+#include "net/manaserv/protocol.h"
+
+#include "net/messagein.h"
+
+#include "beingmanager.h"
+#include "item.h"
+#include "localplayer.h"
+#include "npc.h"
+
+#include "gui/buy.h"
+#include "gui/chat.h"
+#include "gui/sell.h"
+
+extern BuyDialog *buyDialog;
+extern SellDialog *sellDialog;
+extern Window *buySellDialog;
+
+namespace ManaServ {
+
+BuySellHandler::BuySellHandler()
+{
+ static const Uint16 _messages[] = {
+ GPMSG_NPC_BUY,
+ GPMSG_NPC_SELL,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void BuySellHandler::handleMessage(MessageIn &msg)
+{
+ Being *being = beingManager->findBeing(msg.readInt16());
+ if (!being || being->getType() != Being::NPC)
+ {
+ return;
+ }
+
+ current_npc = being->getId();
+
+ switch (msg.getId())
+ {
+ case GPMSG_NPC_BUY:
+ buyDialog->reset();
+ buyDialog->setMoney(player_node->getMoney());
+ buyDialog->setVisible(true);
+
+ while (msg.getUnreadLength())
+ {
+ int itemId = msg.readInt16();
+ int amount = msg.readInt16();
+ int value = msg.readInt16();
+ buyDialog->addItem(itemId, amount, value);
+ }
+ break;
+
+ case GPMSG_NPC_SELL:
+ sellDialog->setMoney(player_node->getMoney());
+ sellDialog->reset();
+ sellDialog->setVisible(true);
+
+ while (msg.getUnreadLength())
+ {
+ int itemId = msg.readInt16();
+ int amount = msg.readInt16();
+ int value = msg.readInt16();
+ sellDialog->addItem(new Item(itemId, amount, false), value);
+ }
+ break;
+ }
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/buysellhandler.h b/src/net/manaserv/buysellhandler.h
new file mode 100644
index 00000000..9d31e739
--- /dev/null
+++ b/src/net/manaserv/buysellhandler.h
@@ -0,0 +1,39 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_MANASERV_BUYSELLHANDLER_H
+#define NET_MANASERV_BUYSELLHANDLER_H
+
+#include "net/messagehandler.h"
+
+namespace ManaServ {
+
+class BuySellHandler : public MessageHandler
+{
+ public:
+ BuySellHandler();
+
+ void handleMessage(MessageIn &msg);
+};
+
+} // namespace ManaServ
+
+#endif
diff --git a/src/net/manaserv/charhandler.cpp b/src/net/manaserv/charhandler.cpp
new file mode 100644
index 00000000..a1b014fa
--- /dev/null
+++ b/src/net/manaserv/charhandler.cpp
@@ -0,0 +1,385 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "net/manaserv/charhandler.h"
+
+#include "net/manaserv/connection.h"
+#include "net/manaserv/protocol.h"
+
+#include "net/manaserv/accountserver/accountserver.h"
+#include "net/manaserv/accountserver/account.h"
+
+#include "net/logindata.h"
+#include "net/loginhandler.h"
+#include "net/messagein.h"
+#include "net/net.h"
+
+#include "game.h"
+#include "localplayer.h"
+#include "log.h"
+#include "main.h"
+
+#include "gui/charcreatedialog.h"
+#include "gui/okdialog.h"
+
+#include "resources/colordb.h"
+
+#include "utils/gettext.h"
+
+extern Net::Connection *accountServerConnection;
+extern Net::Connection *gameServerConnection;
+extern Net::Connection *chatServerConnection;
+
+Net::CharHandler *charHandler;
+
+struct CharInfo {
+ unsigned char slot;
+ std::string name;
+ Gender gender;
+ int hs, hc;
+ unsigned short level;
+ unsigned short charPoints;
+ unsigned short corrPoints;
+ unsigned int money;
+ unsigned char attr[7];
+};
+
+typedef std::vector<CharInfo> CharInfos;
+CharInfos chars;
+
+namespace ManaServ {
+
+extern std::string netToken;
+extern ServerInfo gameServer;
+extern ServerInfo chatServer;
+
+CharHandler::CharHandler():
+ mCharSelectDialog(0),
+ mCharCreateDialog(0)
+{
+ static const Uint16 _messages[] = {
+ APMSG_CHAR_CREATE_RESPONSE,
+ APMSG_CHAR_DELETE_RESPONSE,
+ APMSG_CHAR_INFO,
+ APMSG_CHAR_SELECT_RESPONSE,
+ 0
+ };
+ handledMessages = _messages;
+ charHandler = this;
+}
+
+void CharHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case APMSG_CHAR_CREATE_RESPONSE:
+ handleCharCreateResponse(msg);
+ break;
+
+ case APMSG_CHAR_DELETE_RESPONSE:
+ {
+ int errMsg = msg.readInt8();
+ // Character deletion successful
+ if (errMsg == ERRMSG_OK)
+ {
+ LocalPlayer *tempPlayer = mCharInfo->getEntry();
+ mCharInfo->setEntry(0);
+ mCharInfo->unlock();
+ if (mCharSelectDialog)
+ mCharSelectDialog->update(mCharInfo->getPos());
+ new OkDialog(_("Info"), _("Player deleted."));
+ delete tempPlayer;
+ }
+ // Character deletion failed
+ else
+ {
+ std::string errorMessage = "";
+ switch (errMsg)
+ {
+ case ERRMSG_NO_LOGIN:
+ errorMessage = _("Not logged in.");
+ break;
+ case ERRMSG_INVALID_ARGUMENT:
+ errorMessage = _("Selection out of range.");
+ break;
+ default:
+ errorMessage = _("Unknown error.");
+ }
+ mCharInfo->unlock();
+ new OkDialog(_("Error"), errorMessage);
+ }
+ }
+ break;
+
+ case APMSG_CHAR_INFO:
+ {
+ CharInfo info;
+ info.slot = msg.readInt8(); // character slot
+ info.name = msg.readString();
+ info.gender = msg.readInt8() == GENDER_MALE ? GENDER_MALE :
+ GENDER_FEMALE;
+ info.hs = msg.readInt8();
+ info.hc = msg.readInt8();
+ info.level = msg.readInt16();
+ info.charPoints = msg.readInt16();
+ info.corrPoints = msg.readInt16();
+ info.money = msg.readInt32();
+
+ for (int i = 0; i < 7; i++)
+ {
+ info.attr[i] = msg.readInt8();
+ }
+
+ chars.push_back(info);
+
+ if (mCharSelectDialog)
+ {
+ mCharInfo->select(info.slot);
+
+ LocalPlayer *tempPlayer = new LocalPlayer();
+ tempPlayer->setName(info.name);
+ tempPlayer->setGender(info.gender);
+ tempPlayer->setSprite(Player::HAIR_SPRITE, info.hs * -1,
+ ColorDB::get(info.hc));
+ tempPlayer->setLevel(info.level);
+ tempPlayer->setCharacterPoints(info.charPoints);
+ tempPlayer->setCorrectionPoints(info.corrPoints);
+ tempPlayer->setMoney(info.money);
+
+ for (int i = 0; i < 7; i++)
+ {
+ tempPlayer->setAttributeBase(i, info.attr[i]);
+ }
+
+ mCharInfo->setEntry(tempPlayer);
+
+ mCharSelectDialog->update(info.slot);
+ }
+ }
+ break;
+
+ case APMSG_CHAR_SELECT_RESPONSE:
+ handleCharSelectResponse(msg);
+ break;
+ }
+}
+
+void CharHandler::handleCharCreateResponse(MessageIn &msg)
+{
+ int errMsg = msg.readInt8();
+
+ // Character creation failed
+ if (errMsg != ERRMSG_OK)
+ {
+ std::string errorMessage = "";
+ switch (errMsg)
+ {
+ case ERRMSG_NO_LOGIN:
+ errorMessage = _("Not logged in.");
+ break;
+ case CREATE_TOO_MUCH_CHARACTERS:
+ errorMessage = _("No empty slot.");
+ break;
+ case ERRMSG_INVALID_ARGUMENT:
+ errorMessage = _("Invalid name.");
+ break;
+ case CREATE_EXISTS_NAME:
+ errorMessage = _("Character's name already exists.");
+ break;
+ case CREATE_INVALID_HAIRSTYLE:
+ errorMessage = _("Invalid hairstyle.");
+ break;
+ case CREATE_INVALID_HAIRCOLOR:
+ errorMessage = _("Invalid hair color.");
+ break;
+ case CREATE_INVALID_GENDER:
+ errorMessage = _("Invalid gender.");
+ break;
+ case CREATE_RAW_STATS_TOO_HIGH:
+ errorMessage = _("Character's stats are too high.");
+ break;
+ case CREATE_RAW_STATS_TOO_LOW:
+ errorMessage = _("Character's stats are too low.");
+ break;
+ case CREATE_RAW_STATS_EQUAL_TO_ZERO:
+ errorMessage = _("One stat is zero.");
+ break;
+ default:
+ errorMessage = _("Unknown error.");
+ break;
+ }
+ new OkDialog(_("Error"), errorMessage);
+
+ if (mCharCreateDialog)
+ mCharCreateDialog->unlock();
+ }
+ else
+ {
+ if (mCharCreateDialog)
+ {
+ mCharCreateDialog->success();
+ mCharCreateDialog->scheduleDelete();
+ mCharCreateDialog = 0;
+ }
+ }
+
+}
+
+void CharHandler::handleCharSelectResponse(MessageIn &msg)
+{
+ int errMsg = msg.readInt8();
+
+ if (errMsg == ERRMSG_OK)
+ {
+ netToken = msg.readString(32);
+
+ gameServer.hostname.assign(msg.readString());
+ gameServer.port = msg.readInt16();
+
+ chatServer.hostname.assign(msg.readString());
+ chatServer.port = msg.readInt16();
+
+ logger->log("Game server: %s:%d", gameServer.hostname.c_str(),
+ gameServer.port);
+ logger->log("Chat server: %s:%d", chatServer.hostname.c_str(),
+ chatServer.port);
+
+ gameServerConnection->connect(gameServer.hostname, gameServer.port);
+ chatServerConnection->connect(chatServer.hostname, chatServer.port);
+
+ // Keep the selected character and delete the others
+ player_node = mCharInfo->getEntry();
+ int slot = mCharInfo->getPos();
+ mCharInfo->unlock();
+ mCharInfo->select(0);
+
+ do {
+ LocalPlayer *tmp = mCharInfo->getEntry();
+ if (tmp != player_node)
+ {
+ delete tmp;
+ mCharInfo->setEntry(0);
+ }
+ mCharInfo->next();
+ } while (mCharInfo->getPos());
+ mCharInfo->select(slot);
+
+ mCharInfo->clear(); //player_node will be deleted by ~Game
+
+ state = STATE_CONNECT_GAME;
+ }
+ else if(errMsg == ERRMSG_FAILURE)
+ {
+ errorMessage = _("No gameservers are available.");
+ mCharInfo->clear();
+ state = STATE_ERROR;
+ }
+}
+
+void CharHandler::setCharSelectDialog(CharSelectDialog *window)
+{
+ mCharSelectDialog = window;
+}
+
+void CharHandler::setCharCreateDialog(CharCreateDialog *window)
+{
+ mCharCreateDialog = window;
+
+ if (!mCharCreateDialog) return;
+
+ std::vector<std::string> attributes;
+ attributes.push_back(_("Strength:"));
+ attributes.push_back(_("Agility:"));
+ attributes.push_back(_("Dexterity:"));
+ attributes.push_back(_("Vitality:"));
+ attributes.push_back(_("Intelligence:"));
+ attributes.push_back(_("Willpower:"));
+
+ mCharCreateDialog->setAttributes(attributes, 60, 1, 20);
+}
+
+void CharHandler::getCharacters()
+{
+ if (!accountServerConnection->isConnected())
+ Net::getLoginHandler()->connect();
+ else
+ {
+ mCharInfo->unlock();
+ LocalPlayer *tempPlayer;
+ for (CharInfos::const_iterator it = chars.begin(); it != chars.end(); it++)
+ {
+ const CharInfo info = (CharInfo) (*it);
+ mCharInfo->select(info.slot);
+
+ tempPlayer = new LocalPlayer();
+ tempPlayer->setName(info.name);
+ tempPlayer->setGender(info.gender);
+ tempPlayer->setSprite(Player::HAIR_SPRITE, info.hs * -1,
+ ColorDB::get(info.hc));
+ tempPlayer->setLevel(info.level);
+ tempPlayer->setCharacterPoints(info.charPoints);
+ tempPlayer->setCorrectionPoints(info.corrPoints);
+ tempPlayer->setMoney(info.money);
+
+ for (int i = 0; i < 7; i++)
+ {
+ tempPlayer->setAttributeBase(i, info.attr[i]);
+ }
+
+ mCharInfo->setEntry(tempPlayer);
+ }
+
+ // Close the character create dialog
+ if (mCharCreateDialog)
+ {
+ mCharCreateDialog->scheduleDelete();
+ mCharCreateDialog = 0;
+ }
+
+ state = STATE_CHAR_SELECT;
+ }
+}
+
+void CharHandler::chooseCharacter(int slot, LocalPlayer* character)
+{
+ Net::AccountServer::Account::selectCharacter(slot);
+}
+
+void CharHandler::newCharacter(const std::string &name, int slot, bool gender,
+ int hairstyle, int hairColor, std::vector<int> stats)
+{
+ Net::AccountServer::Account::createCharacter(name, hairstyle, hairColor,
+ gender,
+ stats[0], // STR
+ stats[1], // AGI
+ stats[2], // DEX
+ stats[3], // VIT
+ stats[4], // INT
+ stats[5] // WILL
+ );
+}
+
+void CharHandler::deleteCharacter(int slot, LocalPlayer* character)
+{
+ Net::AccountServer::Account::deleteCharacter(slot);
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/charhandler.h b/src/net/manaserv/charhandler.h
new file mode 100644
index 00000000..dafe6431
--- /dev/null
+++ b/src/net/manaserv/charhandler.h
@@ -0,0 +1,81 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_MANASERV_CHARSERVERHANDLER_H
+#define NET_MANASERV_CHARSERVERHANDLER_H
+
+#include "net/charhandler.h"
+
+#include "gui/charselectdialog.h"
+
+#include "net/messagehandler.h"
+
+class LoginData;
+
+namespace ManaServ {
+
+/**
+ * Deals with incoming messages related to character selection.
+ */
+class CharHandler : public MessageHandler, public Net::CharHandler
+{
+ public:
+ CharHandler();
+
+ void handleMessage(MessageIn &msg);
+
+ void setCharInfo(LockedArray<LocalPlayer*> *charInfo)
+ {
+ mCharInfo = charInfo;
+ }
+
+ void setCharSelectDialog(CharSelectDialog *window);
+
+ /**
+ * Sets the character create dialog. The handler will clean up this
+ * dialog when a new character is succesfully created, and will unlock
+ * the dialog when a new character failed to be created.
+ */
+ void setCharCreateDialog(CharCreateDialog *window);
+
+ void getCharacters();
+
+ void chooseCharacter(int slot, LocalPlayer* character);
+
+ void newCharacter(const std::string &name, int slot,
+ bool gender, int hairstyle, int hairColor,
+ std::vector<int> stats);
+
+ void deleteCharacter(int slot, LocalPlayer* character);
+
+ protected:
+ void handleCharCreateResponse(MessageIn &msg);
+
+ void handleCharSelectResponse(MessageIn &msg);
+
+ LockedArray<LocalPlayer*> *mCharInfo;
+ CharSelectDialog *mCharSelectDialog;
+ CharCreateDialog *mCharCreateDialog;
+};
+
+} // namespace ManaServ
+
+#endif
diff --git a/src/net/manaserv/chathandler.cpp b/src/net/manaserv/chathandler.cpp
new file mode 100644
index 00000000..5b85ed53
--- /dev/null
+++ b/src/net/manaserv/chathandler.cpp
@@ -0,0 +1,459 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "net/manaserv/chathandler.h"
+
+#include "net/manaserv/connection.h"
+#include "net/manaserv/protocol.h"
+
+#include "net/manaserv/chatserver/chatserver.h"
+#include "net/manaserv/chatserver/internal.h"
+
+#include "net/manaserv/gameserver/internal.h"
+#include "net/manaserv/gameserver/player.h"
+
+#include "net/messagein.h"
+#include "net/messageout.h"
+
+#include "being.h"
+#include "beingmanager.h"
+#include "channel.h"
+#include "channelmanager.h"
+#include "game.h"
+#include "main.h"
+
+#include "gui/widgets/channeltab.h"
+#include "gui/chat.h"
+#include "gui/guildwindow.h"
+
+#include "utils/gettext.h"
+#include "utils/stringutils.h"
+
+#include <string>
+#include <iostream>
+
+extern Being *player_node;
+
+Net::ChatHandler *chatHandler;
+
+extern Net::Connection *chatServerConnection;
+
+namespace ManaServ {
+
+extern std::string netToken;
+extern ServerInfo chatServer;
+
+ChatHandler::ChatHandler()
+{
+ static const Uint16 _messages[] = {
+ GPMSG_SAY,
+ CPMSG_ENTER_CHANNEL_RESPONSE,
+ CPMSG_LIST_CHANNELS_RESPONSE,
+ CPMSG_PUBMSG,
+ CPMSG_ANNOUNCEMENT,
+ CPMSG_PRIVMSG,
+ CPMSG_QUIT_CHANNEL_RESPONSE,
+ CPMSG_LIST_CHANNELUSERS_RESPONSE,
+ CPMSG_CHANNEL_EVENT,
+ CPMSG_WHO_RESPONSE,
+ CPMSG_DISCONNECT_RESPONSE,
+ 0
+ };
+ handledMessages = _messages;
+ chatHandler = this;
+}
+
+void ChatHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case GPMSG_SAY:
+ handleGameChatMessage(msg);
+ break;
+
+ case CPMSG_ENTER_CHANNEL_RESPONSE:
+ handleEnterChannelResponse(msg);
+ break;
+
+ case CPMSG_LIST_CHANNELS_RESPONSE:
+ handleListChannelsResponse(msg);
+ break;
+
+ case CPMSG_PRIVMSG:
+ handlePrivateMessage(msg);
+ break;
+
+ case CPMSG_ANNOUNCEMENT:
+ handleAnnouncement(msg);
+ break;
+
+ case CPMSG_PUBMSG:
+ handleChatMessage(msg);
+ break;
+
+ case CPMSG_QUIT_CHANNEL_RESPONSE:
+ handleQuitChannelResponse(msg);
+ break;
+
+ case CPMSG_LIST_CHANNELUSERS_RESPONSE:
+ handleListChannelUsersResponse(msg);
+ break;
+
+ case CPMSG_CHANNEL_EVENT:
+ handleChannelEvent(msg);
+ break;
+
+ case CPMSG_WHO_RESPONSE:
+ handleWhoResponse(msg);
+ break;
+ case CPMSG_DISCONNECT_RESPONSE:
+ {
+ int errMsg = msg.readInt8();
+ // Successful logout
+ if (errMsg == ERRMSG_OK)
+ {
+ // TODO: Handle logout
+ }
+ else
+ {
+ switch (errMsg) {
+ case ERRMSG_NO_LOGIN:
+ errorMessage = "Chatserver: Not logged in";
+ break;
+ default:
+ errorMessage = "Chatserver: Unknown error";
+ break;
+ }
+ state = STATE_ERROR;
+ }
+ }
+ break;
+ }
+}
+
+void ChatHandler::handleGameChatMessage(MessageIn &msg)
+{
+ short id = msg.readInt16();
+ std::string chatMsg = msg.readString();
+
+ if (id == 0)
+ {
+ localChatTab->chatLog(chatMsg, BY_SERVER);
+ return;
+ }
+
+ Being *being = beingManager->findBeing(id);
+
+ std::string mes;
+ if (being)
+ {
+ mes = being->getName() + " : " + chatMsg;
+ being->setSpeech(chatMsg, SPEECH_TIME);
+ }
+ else
+ mes = "Unknown : " + chatMsg;
+
+ localChatTab->chatLog(mes, being == player_node ? BY_PLAYER : BY_OTHER);
+}
+
+void ChatHandler::handleEnterChannelResponse(MessageIn &msg)
+{
+ if(msg.readInt8() == ERRMSG_OK)
+ {
+ short channelId = msg.readInt16();
+ std::string channelName = msg.readString();
+ std::string announcement = msg.readString();
+ Channel *channel = new Channel(channelId, channelName, announcement);
+ channelManager->addChannel(channel);
+ ChatTab *tab = channel->getTab();
+ tab->chatLog(strprintf(_("Topic: %s"), announcement.c_str()), BY_CHANNEL);
+
+ std::string user;
+ std::string userModes;
+ tab->chatLog(_("Players in this channel:"), BY_CHANNEL);
+ while(msg.getUnreadLength())
+ {
+ user = msg.readString();
+ if (user == "")
+ return;
+ userModes = msg.readString();
+ if (userModes.find('o') != std::string::npos)
+ {
+ user = "@" + user;
+ }
+ tab->chatLog(user, BY_CHANNEL);
+ }
+
+ }
+ else
+ {
+ localChatTab->chatLog(_("Error joining channel."), BY_SERVER);
+ }
+}
+
+void ChatHandler::handleListChannelsResponse(MessageIn &msg)
+{
+ localChatTab->chatLog(_("Listing channels."), BY_SERVER);
+ while(msg.getUnreadLength())
+ {
+ std::string channelName = msg.readString();
+ if (channelName == "")
+ return;
+ std::ostringstream numUsers;
+ numUsers << msg.readInt16();
+ channelName += " - ";
+ channelName += numUsers.str();
+ localChatTab->chatLog(channelName, BY_SERVER);
+ }
+ localChatTab->chatLog(_("End of channel list."), BY_SERVER);
+}
+
+void ChatHandler::handlePrivateMessage(MessageIn &msg)
+{
+ std::string userNick = msg.readString();
+ std::string chatMsg = msg.readString();
+
+ chatWindow->whisper(userNick, chatMsg);
+}
+
+void ChatHandler::handleAnnouncement(MessageIn &msg)
+{
+ std::string chatMsg = msg.readString();
+ localChatTab->chatLog(chatMsg, BY_GM);
+}
+
+void ChatHandler::handleChatMessage(MessageIn &msg)
+{
+ short channelId = msg.readInt16();
+ std::string userNick = msg.readString();
+ std::string chatMsg = msg.readString();
+
+ Channel *channel = channelManager->findById(channelId);
+ channel->getTab()->chatLog(userNick, chatMsg);
+}
+
+void ChatHandler::handleQuitChannelResponse(MessageIn &msg)
+{
+ if(msg.readInt8() == ERRMSG_OK)
+ {
+ short channelId = msg.readInt16();
+ Channel *channel = channelManager->findById(channelId);
+ channelManager->removeChannel(channel);
+ }
+}
+
+void ChatHandler::handleListChannelUsersResponse(MessageIn &msg)
+{
+ std::string channelName = msg.readString();
+ std::string userNick;
+ std::string userModes;
+ Channel *channel = channelManager->findByName(channelName);
+ channel->getTab()->chatLog(_("Players in this channel:"), BY_CHANNEL);
+ while(msg.getUnreadLength())
+ {
+ userNick = msg.readString();
+ if (userNick == "")
+ {
+ break;
+ }
+ userModes = msg.readString();
+ if (userModes.find('o') != std::string::npos)
+ {
+ userNick = "@" + userNick;
+ }
+ localChatTab->chatLog(userNick, BY_CHANNEL, channel);
+ }
+}
+
+void ChatHandler::handleChannelEvent(MessageIn &msg)
+{
+ short channelId = msg.readInt16();
+ char eventId = msg.readInt8();
+ std::string line = msg.readString();
+ Channel *channel = channelManager->findById(channelId);
+
+ if(channel)
+ {
+ switch(eventId)
+ {
+ case CHAT_EVENT_NEW_PLAYER:
+ channel->getTab()->chatLog(strprintf(_("%s entered the "
+ "channel."), line.c_str()), BY_CHANNEL);
+ break;
+
+ case CHAT_EVENT_LEAVING_PLAYER:
+ channel->getTab()->chatLog(strprintf(_("%s left the channel."),
+ line.c_str()), BY_CHANNEL);
+ break;
+
+ case CHAT_EVENT_TOPIC_CHANGE:
+ channel->getTab()->chatLog(strprintf(_("Topic: %s"),
+ line.c_str()), BY_CHANNEL);
+ break;
+
+ case CHAT_EVENT_MODE_CHANGE:
+ {
+ int first = line.find(":");
+ int second = line.find(":", first+1);
+ std::string user1 = line.substr(0, first);
+ std::string user2 = line.substr(first+1, second);
+ std::string mode = line.substr(second+1, line.length());
+ channel->getTab()->chatLog(strprintf(_("%s has set mode %s "
+ "on user %s."), user1.c_str(), mode.c_str(),
+ user2.c_str()), BY_CHANNEL);
+ } break;
+
+ case CHAT_EVENT_KICKED_PLAYER:
+ {
+ int first = line.find(":");
+ std::string user1 = line.substr(0, first);
+ std::string user2 = line.substr(first+1, line.length());
+ channel->getTab()->chatLog(strprintf(_("%s has kicked %s."),
+ user1.c_str(), user2.c_str()), BY_CHANNEL);
+ } break;
+
+ default:
+ channel->getTab()->chatLog(_("Unknown channel event."),
+ BY_CHANNEL);
+ }
+ }
+}
+
+void ChatHandler::handleWhoResponse(MessageIn &msg)
+{
+ std::string userNick;
+
+ while(msg.getUnreadLength())
+ {
+ userNick = msg.readString();
+ if (userNick == "")
+ {
+ break;
+ }
+ localChatTab->chatLog(userNick, BY_SERVER);
+ }
+}
+
+void ChatHandler::connect()
+{
+ Net::ChatServer::connect(chatServerConnection, netToken);
+}
+
+bool ChatHandler::isConnected()
+{
+ return chatServerConnection->isConnected();
+}
+
+void ChatHandler::disconnect()
+{
+ chatServerConnection->disconnect();
+}
+
+void ChatHandler::talk(const std::string &text)
+{
+ MessageOut msg(PGMSG_SAY);
+ msg.writeString(text);
+ Net::GameServer::connection->send(msg);
+}
+
+void ChatHandler::me(const std::string &text)
+{
+ // TODO
+}
+
+void ChatHandler::privateMessage(const std::string &recipient,
+ const std::string &text)
+{
+ MessageOut msg(PCMSG_PRIVMSG);
+ msg.writeString(recipient);
+ msg.writeString(text);
+ Net::ChatServer::connection->send(msg);
+}
+
+void ChatHandler::channelList()
+{
+ MessageOut msg(PCMSG_LIST_CHANNELS);
+ Net::ChatServer::connection->send(msg);
+}
+
+void ChatHandler::enterChannel(const std::string &channel,
+ const std::string &password)
+{
+ MessageOut msg(PCMSG_ENTER_CHANNEL);
+ msg.writeString(channel);
+ msg.writeString(password);
+ Net::ChatServer::connection->send(msg);
+}
+
+void ChatHandler::quitChannel(int channelId)
+{
+ MessageOut msg(PCMSG_QUIT_CHANNEL);
+ msg.writeInt16(channelId);
+ Net::ChatServer::connection->send(msg);
+}
+
+void ChatHandler::sendToChannel(int channelId, const std::string &text)
+{
+ MessageOut msg(PCMSG_CHAT);
+ msg.writeString(text);
+ msg.writeInt16(channelId);
+ Net::ChatServer::connection->send(msg);
+}
+
+void ChatHandler::userList(const std::string &channel)
+{
+ MessageOut msg(PCMSG_LIST_CHANNELUSERS);
+ msg.writeString(channel);
+ Net::ChatServer::connection->send(msg);
+}
+
+void ChatHandler::setChannelTopic(int channelId, const std::string &text)
+{
+ MessageOut msg(PCMSG_TOPIC_CHANGE);
+ msg.writeInt16(channelId);
+ msg.writeString(text);
+ Net::ChatServer::connection->send(msg);
+}
+
+void ChatHandler::setUserMode(int channelId, const std::string &name, int mode)
+{
+ MessageOut msg(PCMSG_USER_MODE);
+ msg.writeInt16(channelId);
+ msg.writeString(name);
+ msg.writeInt8(mode);
+ Net::ChatServer::connection->send(msg);
+}
+
+void ChatHandler::kickUser(int channelId, const std::string &name)
+{
+ MessageOut msg(PCMSG_KICK_USER);
+ msg.writeInt16(channelId);
+ msg.writeString(name);
+ Net::ChatServer::connection->send(msg);
+}
+
+void ChatHandler::who()
+{
+ MessageOut msg(PCMSG_WHO);
+ Net::ChatServer::connection->send(msg);
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/chathandler.h b/src/net/manaserv/chathandler.h
new file mode 100644
index 00000000..2f6a8d00
--- /dev/null
+++ b/src/net/manaserv/chathandler.h
@@ -0,0 +1,128 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_MANASERV_CHATHANDLER_H
+#define NET_MANASERV_CHATHANDLER_H
+
+#include "net/chathandler.h"
+#include "net/messagehandler.h"
+
+#include "net/serverinfo.h"
+
+namespace ManaServ {
+
+class ChatHandler : public MessageHandler, public Net::ChatHandler
+{
+ public:
+ ChatHandler();
+
+ /**
+ * Handle the given message appropriately.
+ */
+ void handleMessage(MessageIn &msg);
+
+ void connect();
+
+ bool isConnected();
+
+ void disconnect();
+
+ void talk(const std::string &text);
+
+ void me(const std::string &text);
+
+ void privateMessage(const std::string &recipient,
+ const std::string &text);
+
+ void channelList();
+
+ void enterChannel(const std::string &channel,
+ const std::string &password);
+
+ void quitChannel(int channelId);
+
+ void sendToChannel(int channelId, const std::string &text);
+
+ void userList(const std::string &channel);
+
+ void setChannelTopic(int channelId, const std::string &text);
+
+ void setUserMode(int channelId, const std::string &name, int mode);
+
+ void kickUser(int channelId, const std::string &name);
+
+ void who();
+
+ private:
+ /**
+ * Handle chat messages sent from the game server.
+ */
+ void handleGameChatMessage(MessageIn &msg);
+
+ /**
+ * Handle channel entry responses.
+ */
+ void handleEnterChannelResponse(MessageIn &msg);
+
+ /**
+ * Handle list channels responses.
+ */
+ void handleListChannelsResponse(MessageIn &msg);
+
+ /**
+ * Handle private messages.
+ */
+ void handlePrivateMessage(MessageIn &msg);
+
+ /**
+ * Handle announcements.
+ */
+ void handleAnnouncement(MessageIn &msg);
+
+ /**
+ * Handle chat messages.
+ */
+ void handleChatMessage(MessageIn &msg);
+
+ /**
+ * Handle quit channel responses.
+ */
+ void handleQuitChannelResponse(MessageIn &msg);
+
+ /**
+ * Handle list channel users responses.
+ */
+ void handleListChannelUsersResponse(MessageIn &msg);
+
+ /**
+ * Handle channel events.
+ */
+ void handleChannelEvent(MessageIn &msg);
+
+ /**
+ * Handle who responses.
+ */
+ void handleWhoResponse(MessageIn &msg);
+};
+
+} // namespace ManaServ
+
+#endif
diff --git a/src/net/manaserv/chatserver/chatserver.cpp b/src/net/manaserv/chatserver/chatserver.cpp
new file mode 100644
index 00000000..f0f5faf2
--- /dev/null
+++ b/src/net/manaserv/chatserver/chatserver.cpp
@@ -0,0 +1,54 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "chatserver.h"
+
+#include "internal.h"
+
+#include "net/manaserv/connection.h"
+#include "net/manaserv/protocol.h"
+
+#include "net/messageout.h"
+
+using Net::ChatServer::connection;
+
+void Net::ChatServer::connect(Net::Connection *connection,
+ const std::string &token)
+{
+ Net::ChatServer::connection = connection;
+
+ MessageOut msg(PCMSG_CONNECT);
+ msg.writeString(token, 32);
+ connection->send(msg);
+}
+
+void Net::ChatServer::logout()
+{
+ MessageOut msg(PCMSG_DISCONNECT);
+ connection->send(msg);
+}
+
+void Net::ChatServer::announce(const std::string &text)
+{
+ MessageOut msg(PCMSG_ANNOUNCE);
+ msg.writeString(text);
+ connection->send(msg);
+}
diff --git a/src/net/manaserv/chatserver/chatserver.h b/src/net/manaserv/chatserver/chatserver.h
new file mode 100644
index 00000000..18859a2c
--- /dev/null
+++ b/src/net/manaserv/chatserver/chatserver.h
@@ -0,0 +1,44 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_CHATSERVER_CHATSERVER_H
+#define NET_CHATSERVER_CHATSERVER_H
+
+#include <iosfwd>
+
+namespace Net
+{
+ class Connection;
+
+ namespace ChatServer
+ {
+ void connect(Net::Connection *connection, const std::string &token);
+
+ void logout();
+
+ void announce(const std::string &text);
+
+ void kickUser(short channel, const std::string &user);
+
+ }
+}
+
+#endif
diff --git a/src/net/manaserv/chatserver/guild.cpp b/src/net/manaserv/chatserver/guild.cpp
new file mode 100644
index 00000000..5973077e
--- /dev/null
+++ b/src/net/manaserv/chatserver/guild.cpp
@@ -0,0 +1,95 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "guild.h"
+
+#include "internal.h"
+
+#include "net/manaserv/connection.h"
+#include "net/manaserv/protocol.h"
+
+#include "net/messageout.h"
+
+#include "log.h"
+
+void Net::ChatServer::Guild::createGuild(const std::string &name)
+{
+ logger->log("Sending PCMSG_GUILD_CREATE");
+ MessageOut msg(PCMSG_GUILD_CREATE);
+
+ msg.writeString(name);
+
+ Net::ChatServer::connection->send(msg);
+}
+
+void Net::ChatServer::Guild::invitePlayer(const std::string &name, short guildId)
+{
+ logger->log("Sending PCMSG_GUILD_INVITE");
+ MessageOut msg(PCMSG_GUILD_INVITE);
+
+ msg.writeInt16(guildId);
+ msg.writeString(name);
+
+ Net::ChatServer::connection->send(msg);
+}
+
+void Net::ChatServer::Guild::acceptInvite(const std::string &name)
+{
+ logger->log("Sending PCMSG_GUILD_ACCEPT");
+ MessageOut msg(PCMSG_GUILD_ACCEPT);
+
+ msg.writeString(name);
+
+ Net::ChatServer::connection->send(msg);
+}
+
+void Net::ChatServer::Guild::getGuildMembers(short guildId)
+{
+ logger->log("Sending PCMSG_GUILD_GET_MEMBERS");
+ MessageOut msg(PCMSG_GUILD_GET_MEMBERS);
+
+ msg.writeInt16(guildId);
+
+ Net::ChatServer::connection->send(msg);
+}
+
+void Net::ChatServer::Guild::promoteMember(const std::string &name,
+ short guildId, short level)
+{
+ logger->log("Sending PCMSG_GUILD_PROMOTE_MEMBER");
+ MessageOut msg(PCMSG_GUILD_PROMOTE_MEMBER);
+
+ msg.writeInt16(guildId);
+ msg.writeString(name);
+ msg.writeInt8(level);
+
+ Net::ChatServer::connection->send(msg);
+}
+
+void Net::ChatServer::Guild::quitGuild(short guildId)
+{
+ logger->log("Sending PCMSG_GUILD_QUIT");
+ MessageOut msg(PCMSG_GUILD_QUIT);
+
+ msg.writeInt16(guildId);
+
+ Net::ChatServer::connection->send(msg);
+}
diff --git a/src/net/manaserv/chatserver/guild.h b/src/net/manaserv/chatserver/guild.h
new file mode 100644
index 00000000..2e9cf9a6
--- /dev/null
+++ b/src/net/manaserv/chatserver/guild.h
@@ -0,0 +1,67 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_CHATSERVER_GUILD_H
+#define NET_CHATSERVER_GUILD_H
+
+#include <iosfwd>
+
+namespace Net
+{
+ namespace ChatServer
+ {
+ namespace Guild
+ {
+ /**
+ * Create guild.
+ */
+ void createGuild(const std::string &name);
+
+ /**
+ * Invite a player to your guild.
+ */
+ void invitePlayer(const std::string &name, short guildId);
+
+ /**
+ * Accept an invite another player has sent to join their guild.
+ */
+ void acceptInvite(const std::string &name);
+
+ /**
+ * Get a list of members in a guild.
+ */
+ void getGuildMembers(short guildId);
+
+ /**
+ * Promote guild member
+ */
+ void promoteMember(const std::string &name, short guildId,
+ short level);
+
+ /**
+ * Quit guild.
+ */
+ void quitGuild(short guildId);
+ }
+ }
+}
+
+#endif
diff --git a/src/net/manaserv/chatserver/internal.cpp b/src/net/manaserv/chatserver/internal.cpp
new file mode 100644
index 00000000..52744804
--- /dev/null
+++ b/src/net/manaserv/chatserver/internal.cpp
@@ -0,0 +1,32 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "internal.h"
+
+namespace Net
+{
+ class Connection;
+
+ namespace ChatServer
+ {
+ Connection *connection = 0;
+ }
+}
diff --git a/src/net/manaserv/chatserver/internal.h b/src/net/manaserv/chatserver/internal.h
new file mode 100644
index 00000000..162d54fb
--- /dev/null
+++ b/src/net/manaserv/chatserver/internal.h
@@ -0,0 +1,35 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_CHATSERVER_INTERNAL_H
+#define NET_CHATSERVER_INTERNAL_H
+
+namespace Net
+{
+ class Connection;
+
+ namespace ChatServer
+ {
+ extern Connection *connection;
+ }
+}
+
+#endif
diff --git a/src/net/manaserv/chatserver/party.cpp b/src/net/manaserv/chatserver/party.cpp
new file mode 100644
index 00000000..26b45346
--- /dev/null
+++ b/src/net/manaserv/chatserver/party.cpp
@@ -0,0 +1,79 @@
+/*
+ * The Mana World
+ * Copyright (C) 2008 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "party.h"
+
+#include "internal.h"
+
+#include "net/manaserv/connection.h"
+#include "net/manaserv/protocol.h"
+
+#include "net/messageout.h"
+
+#include "log.h"
+
+void Net::ChatServer::Party::invitePlayer(const std::string &name)
+{
+ logger->log("Sending PCMSG_PARTY_INVITE");
+ MessageOut msg(PCMSG_PARTY_INVITE);
+
+ msg.writeString(name);
+
+ Net::ChatServer::connection->send(msg);
+}
+
+void Net::ChatServer::Party::acceptInvite(const std::string &name)
+{
+ logger->log("Sending PCMSG_PARTY_ACCEPT_INVITE");
+ MessageOut msg(PCMSG_PARTY_ACCEPT_INVITE);
+
+ msg.writeString(name);
+
+ Net::ChatServer::connection->send(msg);
+}
+
+void Net::ChatServer::Party::rejectInvite(const std::string &name)
+{
+ logger->log("Sending PCMSG_PARTY_REJECT_INVITE");
+ MessageOut msg(PCMSG_PARTY_REJECT_INVITE);
+
+ msg.writeString(name);
+
+ Net::ChatServer::connection->send(msg);
+}
+
+void Net::ChatServer::Party::getPartyMembers()
+{
+ logger->log("Sending PCMSG_PARTY_GET_MEMBERS");
+// MessageOut msg(PCMSG_GUILD_GET_MEMBERS);
+
+// msg.writeInt16(guildId);
+
+// Net::ChatServer::connection->send(msg);
+}
+
+void Net::ChatServer::Party::quitParty()
+{
+ logger->log("Sending PCMSG_PARTY_QUIT");
+ MessageOut msg(PCMSG_PARTY_QUIT);
+
+ Net::ChatServer::connection->send(msg);
+}
diff --git a/src/net/manaserv/chatserver/party.h b/src/net/manaserv/chatserver/party.h
new file mode 100644
index 00000000..3850c283
--- /dev/null
+++ b/src/net/manaserv/chatserver/party.h
@@ -0,0 +1,61 @@
+/*
+ * The Mana World
+ * Copyright (C) 2008 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_CHATSERVER_PARTY_H
+#define NET_CHATSERVER_PARTY_H
+
+#include <iosfwd>
+
+namespace Net
+{
+ namespace ChatServer
+ {
+ namespace Party
+ {
+ /**
+ * Invite a player to the party.
+ */
+ void invitePlayer(const std::string &name);
+
+ /**
+ * Accept an invite another player has sent to join their party
+ */
+ void acceptInvite(const std::string &name);
+
+ /**
+ * Reject an invite from another player to join their party
+ */
+ void rejectInvite(const std::string &name);
+
+ /**
+ * Get a list of party members
+ */
+ void getPartyMembers();
+
+ /**
+ * Leave party
+ */
+ void quitParty();
+ }
+ }
+}
+
+#endif
diff --git a/src/net/manaserv/connection.cpp b/src/net/manaserv/connection.cpp
new file mode 100644
index 00000000..b73f867f
--- /dev/null
+++ b/src/net/manaserv/connection.cpp
@@ -0,0 +1,105 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "net/manaserv/connection.h"
+
+#include "net/manaserv/internal.h"
+
+#include "net/messageout.h"
+
+#include "log.h"
+
+#include <string>
+
+Net::Connection::Connection(ENetHost *client):
+ mConnection(0), mClient(client)
+{
+ mPort = 0;
+ Net::connections++;
+}
+
+Net::Connection::~Connection()
+{
+ Net::connections--;
+}
+
+bool Net::Connection::connect(const std::string &address, short port)
+{
+ logger->log("Net::Connection::connect(%s, %i)", address.c_str(), port);
+
+ if (address.empty())
+ {
+ logger->log("Net::Connection::connect() got empty address!");
+ mState = NET_ERROR;
+ return false;
+ }
+
+ ENetAddress enetAddress;
+
+ enet_address_set_host(&enetAddress, address.c_str());
+ enetAddress.port = port;
+
+ // Initiate the connection, allocating channel 0.
+ mConnection = enet_host_connect(mClient, &enetAddress, 1);
+
+ if (!mConnection)
+ {
+ logger->log("Unable to initiate connection to the server.");
+ mState = NET_ERROR;
+ return false;
+ }
+
+ mPort = port;
+
+ return true;
+}
+
+void Net::Connection::disconnect()
+{
+ if (!mConnection)
+ return;
+
+ enet_peer_disconnect(mConnection, 0);
+ enet_host_flush(mClient);
+ enet_peer_reset(mConnection);
+
+ mConnection = 0;
+}
+
+bool Net::Connection::isConnected()
+{
+ return (mConnection) ?
+ (mConnection->state == ENET_PEER_STATE_CONNECTED) : false;
+}
+
+void Net::Connection::send(const MessageOut &msg)
+{
+ if (!isConnected())
+ {
+ logger->log("Warning: cannot send message to not connected server!");
+ return;
+ }
+
+ ENetPacket *packet = enet_packet_create(msg.getData(),
+ msg.getDataSize(),
+ ENET_PACKET_FLAG_RELIABLE);
+ enet_peer_send(mConnection, 0, packet);
+}
diff --git a/src/net/manaserv/connection.h b/src/net/manaserv/connection.h
new file mode 100644
index 00000000..b340546b
--- /dev/null
+++ b/src/net/manaserv/connection.h
@@ -0,0 +1,81 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_MANASERV_CONNECTION_H
+#define NET_MANASERV_CONNECTION_H
+
+#include <iosfwd>
+
+#include <enet/enet.h>
+
+class MessageOut;
+
+namespace Net
+{
+ /**
+ * \ingroup Network
+ */
+ class Connection
+ {
+ public:
+ enum State {
+ OK,
+ NET_ERROR
+ };
+
+ ~Connection();
+
+ /**
+ * Connects to the given server with the specified address and port.
+ * This method is non-blocking, use isConnected to check whether the
+ * server is connected.
+ */
+ bool connect(const std::string &address, short port);
+
+ /**
+ * Disconnects from the given server.
+ */
+ void disconnect();
+
+ State getState() { return mState; }
+
+ /**
+ * Returns whether the server is connected.
+ */
+ bool isConnected();
+
+ /**
+ * Sends a message.
+ */
+ void send(const MessageOut &msg);
+
+ private:
+ friend Connection *Net::getConnection();
+ Connection(ENetHost *client);
+
+ short mPort;
+ ENetPeer *mConnection;
+ ENetHost *mClient;
+ State mState;
+ };
+}
+
+#endif
diff --git a/src/net/manaserv/effecthandler.cpp b/src/net/manaserv/effecthandler.cpp
new file mode 100644
index 00000000..e2121102
--- /dev/null
+++ b/src/net/manaserv/effecthandler.cpp
@@ -0,0 +1,80 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "net/manaserv/effecthandler.h"
+
+#include "net/manaserv/protocol.h"
+
+#include "net/messagein.h"
+
+#include "beingmanager.h"
+#include "effectmanager.h"
+#include "log.h"
+
+namespace ManaServ {
+
+EffectHandler::EffectHandler()
+{
+ static const Uint16 _messages[] = {
+ GPMSG_CREATE_EFFECT_POS,
+ GPMSG_CREATE_EFFECT_BEING,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void EffectHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case GPMSG_CREATE_EFFECT_POS:
+ handleCreateEffectPos(msg);
+ break;
+ case GPMSG_CREATE_EFFECT_BEING:
+ handleCreateEffectBeing(msg);
+ break;
+ default:
+ break;
+ }
+}
+
+void EffectHandler::handleCreateEffectPos(MessageIn &msg)
+{
+ int id = msg.readInt16();
+ Uint16 x = msg.readInt16();
+ Uint16 y = msg.readInt16();
+ effectManager->trigger(id, x, y);
+}
+
+void EffectHandler::handleCreateEffectBeing(MessageIn &msg)
+{
+ int eid = msg.readInt16();
+ int bid = msg.readInt16();
+ Being* b = beingManager->findBeing(bid);
+ if (b)
+ {
+ effectManager->trigger(eid, b);
+ } else {
+ logger->log("Warning: CreateEffect called for unknown being #%d", bid);
+ }
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/effecthandler.h b/src/net/manaserv/effecthandler.h
new file mode 100644
index 00000000..5c52f121
--- /dev/null
+++ b/src/net/manaserv/effecthandler.h
@@ -0,0 +1,43 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_MANASERV_EFFECTSHANDLER_H
+#define NET_MANASERV_EFFECTSHANDLER_H
+
+#include "net/messagehandler.h"
+
+namespace ManaServ {
+
+class EffectHandler : public MessageHandler
+{
+ public:
+ EffectHandler();
+
+ void handleMessage(MessageIn &msg);
+
+ private:
+ void handleCreateEffectPos(MessageIn &msg);
+ void handleCreateEffectBeing(MessageIn &msg);
+};
+
+} // namespace ManaServ
+
+#endif
diff --git a/src/net/manaserv/gamehandler.cpp b/src/net/manaserv/gamehandler.cpp
new file mode 100644
index 00000000..2a4e08b6
--- /dev/null
+++ b/src/net/manaserv/gamehandler.cpp
@@ -0,0 +1,132 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "net/manaserv/gamehandler.h"
+
+#include "net/manaserv/chathandler.h"
+#include "net/manaserv/connection.h"
+#include "net/manaserv/protocol.h"
+
+#include "net/manaserv/chatserver/chatserver.h"
+#include "net/manaserv/gameserver/gameserver.h"
+
+#include "main.h"
+
+Net::GameHandler *gameHandler;
+
+extern ManaServ::ChatHandler *chatHandler;
+
+extern Net::Connection *gameServerConnection;
+
+namespace ManaServ {
+
+extern std::string netToken;
+extern ServerInfo gameServer;
+
+GameHandler::GameHandler()
+{
+ static const Uint16 _messages[] = {
+ GPMSG_DISCONNECT_RESPONSE,
+ 0
+ };
+ handledMessages = _messages;
+ gameHandler = this;
+}
+
+void GameHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case GPMSG_DISCONNECT_RESPONSE:
+ {
+ int errMsg = msg.readInt8();
+ // Successful logout
+ if (errMsg == ERRMSG_OK)
+ {
+ // TODO: Handle logout
+ }
+ // 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;
+ }
+}
+
+void GameHandler::connect()
+{
+ //
+}
+
+bool GameHandler::isConnected()
+{
+ return gameServerConnection->isConnected() &&
+ chatHandler->isConnected();
+}
+
+void GameHandler::disconnect()
+{
+ gameServerConnection->disconnect();
+ chatHandler->disconnect();
+}
+
+void GameHandler::inGame()
+{
+ Net::GameServer::connect(gameServerConnection, netToken);
+ chatHandler->connect();
+}
+
+void GameHandler::mapLoaded(const std::string &mapName)
+{
+ // TODO
+}
+
+void GameHandler::who()
+{
+ // TODO
+}
+
+void GameHandler::quit()
+{
+ // TODO
+}
+
+void GameHandler::ping(int tick)
+{
+ // TODO
+}
+
+void GameHandler::clear()
+{
+ disconnect();
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/gamehandler.h b/src/net/manaserv/gamehandler.h
new file mode 100644
index 00000000..846eb2ae
--- /dev/null
+++ b/src/net/manaserv/gamehandler.h
@@ -0,0 +1,60 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_MANASERV_MAPHANDLER_H
+#define NET_MANASERV_MAPHANDLER_H
+
+#include "net/gamehandler.h"
+#include "net/messagehandler.h"
+
+#include "net/serverinfo.h"
+
+namespace ManaServ {
+
+class GameHandler : public MessageHandler, public Net::GameHandler
+{
+ public:
+ GameHandler();
+
+ void handleMessage(MessageIn &msg);
+
+ void connect();
+
+ bool isConnected();
+
+ void disconnect();
+
+ void inGame();
+
+ void mapLoaded(const std::string &mapName);
+
+ void who();
+
+ void quit();
+
+ void ping(int tick);
+
+ void clear();
+};
+
+} // namespace ManaServ
+
+#endif
diff --git a/src/net/manaserv/gameserver/gameserver.cpp b/src/net/manaserv/gameserver/gameserver.cpp
new file mode 100644
index 00000000..94015c20
--- /dev/null
+++ b/src/net/manaserv/gameserver/gameserver.cpp
@@ -0,0 +1,50 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "gameserver.h"
+
+#include "internal.h"
+
+#include "net/manaserv/connection.h"
+#include "net/manaserv/protocol.h"
+
+#include "net/messageout.h"
+
+void Net::GameServer::connect(Net::Connection *connection,
+ const std::string &token)
+{
+ Net::GameServer::connection = connection;
+
+ MessageOut msg(PGMSG_CONNECT);
+
+ msg.writeString(token, 32);
+
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::logout(bool reconnectAccount)
+{
+ MessageOut msg(PGMSG_DISCONNECT);
+
+ msg.writeInt8((unsigned char) reconnectAccount);
+
+ Net::GameServer::connection->send(msg);
+}
diff --git a/src/net/manaserv/gameserver/gameserver.h b/src/net/manaserv/gameserver/gameserver.h
new file mode 100644
index 00000000..6de82c2e
--- /dev/null
+++ b/src/net/manaserv/gameserver/gameserver.h
@@ -0,0 +1,39 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_GAMESERVER_GAMESERVER_H
+#define NET_GAMESERVER_GAMESERVER_H
+
+#include <iosfwd>
+
+namespace Net
+{
+ class Connection;
+
+ namespace GameServer
+ {
+ void connect(Net::Connection *connection, const std::string &token);
+
+ void logout(bool reconnectAccount);
+ }
+}
+
+#endif
diff --git a/src/net/manaserv/gameserver/internal.cpp b/src/net/manaserv/gameserver/internal.cpp
new file mode 100644
index 00000000..27cb4a47
--- /dev/null
+++ b/src/net/manaserv/gameserver/internal.cpp
@@ -0,0 +1,32 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "internal.h"
+
+namespace Net
+{
+ class Connection;
+
+ namespace GameServer
+ {
+ Connection *connection = 0;
+ }
+}
diff --git a/src/net/manaserv/gameserver/internal.h b/src/net/manaserv/gameserver/internal.h
new file mode 100644
index 00000000..6c6e2613
--- /dev/null
+++ b/src/net/manaserv/gameserver/internal.h
@@ -0,0 +1,35 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_GAMESERVER_INTERNAL_H
+#define NET_GAMESERVER_INTERNAL_H
+
+namespace Net
+{
+ class Connection;
+
+ namespace GameServer
+ {
+ extern Connection *connection;
+ }
+}
+
+#endif
diff --git a/src/net/manaserv/gameserver/player.cpp b/src/net/manaserv/gameserver/player.cpp
new file mode 100644
index 00000000..e667c8b9
--- /dev/null
+++ b/src/net/manaserv/gameserver/player.cpp
@@ -0,0 +1,57 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "player.h"
+
+#include "internal.h"
+
+#include "net/manaserv/connection.h"
+#include "net/manaserv/protocol.h"
+
+#include "net/messageout.h"
+
+void RespawnRequestListener::action(const gcn::ActionEvent &event)
+{
+ Net::GameServer::Player::respawn();
+}
+
+void Net::GameServer::Player::walk(int x, int y)
+{
+ MessageOut msg(PGMSG_WALK);
+ msg.writeInt16(x);
+ msg.writeInt16(y);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::moveItem(int oldSlot, int newSlot, int amount)
+{
+ MessageOut msg(PGMSG_MOVE_ITEM);
+ msg.writeInt8(oldSlot);
+ msg.writeInt8(newSlot);
+ msg.writeInt8(amount);
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::respawn()
+{
+ MessageOut msg(PGMSG_RESPAWN);
+ Net::GameServer::connection->send(msg);
+}
diff --git a/src/net/manaserv/gameserver/player.h b/src/net/manaserv/gameserver/player.h
new file mode 100644
index 00000000..9a202c6e
--- /dev/null
+++ b/src/net/manaserv/gameserver/player.h
@@ -0,0 +1,51 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_GAMESERVER_PLAYER_H
+#define NET_GAMESERVER_PLAYER_H
+
+#include "being.h"
+
+#include <guichan/actionlistener.hpp>
+
+#include <iosfwd>
+
+
+struct RespawnRequestListener : public gcn::ActionListener
+{
+ void action(const gcn::ActionEvent &event);
+};
+
+namespace Net
+{
+ namespace GameServer
+ {
+ namespace Player
+ {
+ void walk(int x, int y);
+ void moveItem(int oldSlot, int newSlot, int amount);
+ void respawn();
+ static RespawnRequestListener respawnListener;
+ }
+ }
+}
+
+#endif
diff --git a/src/net/manaserv/generalhandler.cpp b/src/net/manaserv/generalhandler.cpp
new file mode 100644
index 00000000..0b2eefe2
--- /dev/null
+++ b/src/net/manaserv/generalhandler.cpp
@@ -0,0 +1,190 @@
+/*
+ * The Mana World
+ * Copyright (C) 2009 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "net/manaserv/generalhandler.h"
+
+#include "gui/changeemaildialog.h"
+#include "gui/charselectdialog.h"
+#include "gui/inventorywindow.h"
+#include "gui/partywindow.h"
+#include "gui/register.h"
+#include "gui/skilldialog.h"
+#include "gui/specialswindow.h"
+#include "gui/statuswindow.h"
+
+#include "net/manaserv/network.h"
+#include "net/manaserv/connection.h"
+
+#include "net/manaserv/beinghandler.h"
+#include "net/manaserv/buysellhandler.h"
+#include "net/manaserv/charhandler.h"
+#include "net/manaserv/chathandler.h"
+#include "net/manaserv/effecthandler.h"
+#include "net/manaserv/gamehandler.h"
+#include "net/manaserv/guildhandler.h"
+#include "net/manaserv/inventoryhandler.h"
+#include "net/manaserv/itemhandler.h"
+#include "net/manaserv/loginhandler.h"
+#include "net/manaserv/npchandler.h"
+#include "net/manaserv/partyhandler.h"
+#include "net/manaserv/playerhandler.h"
+#include "net/manaserv/specialhandler.h"
+#include "net/manaserv/tradehandler.h"
+
+#include "utils/gettext.h"
+
+#include "main.h"
+
+#include <list>
+
+Net::GeneralHandler *generalHandler = NULL;
+
+Net::Connection *gameServerConnection = 0;
+Net::Connection *chatServerConnection = 0;
+Net::Connection *accountServerConnection = 0;
+
+namespace ManaServ {
+
+std::string netToken = "";
+ServerInfo gameServer;
+ServerInfo chatServer;
+
+GeneralHandler::GeneralHandler():
+ mBeingHandler(new BeingHandler),
+ mBuySellHandler(new BuySellHandler),
+ mCharHandler(new CharHandler),
+ mChatHandler(new ChatHandler),
+ mEffectHandler(new EffectHandler),
+ mGameHandler(new GameHandler),
+ mGuildHandler(new GuildHandler),
+ mInventoryHandler(new InventoryHandler),
+ mItemHandler(new ItemHandler),
+ mLoginHandler(new LoginHandler),
+ mNpcHandler(new NpcHandler),
+ mPartyHandler(new PartyHandler),
+ mPlayerHandler(new PlayerHandler),
+ mTradeHandler(new TradeHandler),
+ mSpecialHandler(new SpecialHandler)
+{
+ Net::initialize();
+
+ accountServerConnection = Net::getConnection();
+ gameServerConnection = Net::getConnection();
+ chatServerConnection = Net::getConnection();
+
+ generalHandler = this;
+
+ std::list<ItemDB::Stat> stats;
+ stats.push_back(ItemDB::Stat("str", N_("Strength %+d")));
+ stats.push_back(ItemDB::Stat("agi", N_("Agility %+d")));
+ stats.push_back(ItemDB::Stat("dex", N_("Dexterity %+d")));
+ stats.push_back(ItemDB::Stat("vit", N_("Vitality %+d")));
+ stats.push_back(ItemDB::Stat("int", N_("Intelligence %+d")));
+ stats.push_back(ItemDB::Stat("will", N_("Willpower %+d")));
+
+ ItemDB::setStatsList(stats);
+}
+
+void GeneralHandler::load()
+{
+ Net::registerHandler(mBeingHandler.get());
+ Net::registerHandler(mBuySellHandler.get());
+ Net::registerHandler(mCharHandler.get());
+ Net::registerHandler(mChatHandler.get());
+ Net::registerHandler(mEffectHandler.get());
+ Net::registerHandler(mGameHandler.get());
+ Net::registerHandler(mGuildHandler.get());
+ Net::registerHandler(mInventoryHandler.get());
+ Net::registerHandler(mItemHandler.get());
+ Net::registerHandler(mLoginHandler.get());
+ Net::registerHandler(mNpcHandler.get());
+ Net::registerHandler(mPartyHandler.get());
+ Net::registerHandler(mPlayerHandler.get());
+ Net::registerHandler(mTradeHandler.get());
+}
+
+void GeneralHandler::reload()
+{
+ // Nothing needed yet
+}
+
+void GeneralHandler::unload()
+{
+ Net::clearHandlers();
+
+ if (accountServerConnection)
+ accountServerConnection->disconnect();
+ if (gameServerConnection)
+ gameServerConnection->disconnect();
+ if (chatServerConnection)
+ chatServerConnection->disconnect();
+
+ delete accountServerConnection;
+ delete gameServerConnection;
+ delete chatServerConnection;
+
+ Net::finalize();
+}
+
+void GeneralHandler::flushNetwork()
+{
+ Net::flush();
+}
+
+bool GeneralHandler::isNetworkConnected()
+{
+ // TODO
+ return true;
+}
+
+void GeneralHandler::tick()
+{
+ // TODO
+}
+
+void GeneralHandler::guiWindowsLoaded()
+{
+ inventoryWindow->setSplitAllowed(true);
+ partyWindow->clearPartyName();
+ skillDialog->loadSkills("tmw-skills.xml");
+ specialsWindow->loadSpecials("specials.xml");
+
+ player_node->setExpNeeded(100);
+
+ statusWindow->addAttribute(16, _("Strength"), true);
+ statusWindow->addAttribute(17, _("Agility"), true);
+ statusWindow->addAttribute(18, _("Dexterity"), true);
+ statusWindow->addAttribute(19, _("Vitality"), true);
+ statusWindow->addAttribute(20, _("Intelligence"), true);
+ statusWindow->addAttribute(21, _("Willpower"), true);
+}
+
+void GeneralHandler::guiWindowsUnloaded()
+{
+ // TODO
+}
+
+void GeneralHandler::clearHandlers()
+{
+ Net::clearHandlers();
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/generalhandler.h b/src/net/manaserv/generalhandler.h
new file mode 100644
index 00000000..0017af75
--- /dev/null
+++ b/src/net/manaserv/generalhandler.h
@@ -0,0 +1,74 @@
+/*
+ * The Mana World
+ * Copyright (C) 2009 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_MANASERV_GENERALHANDLER_H
+#define NET_MANASERV_GENERALHANDLER_H
+
+#include "net/generalhandler.h"
+#include "net/net.h"
+#include "net/messagehandler.h"
+
+namespace ManaServ {
+
+class GeneralHandler : public Net::GeneralHandler
+{
+ public:
+ GeneralHandler();
+
+ void load();
+
+ void reload();
+
+ void unload();
+
+ void flushNetwork();
+
+ bool isNetworkConnected();
+
+ void tick();
+
+ void guiWindowsLoaded();
+
+ void guiWindowsUnloaded();
+
+ void clearHandlers();
+
+ protected:
+ MessageHandlerPtr mBeingHandler;
+ MessageHandlerPtr mBuySellHandler;
+ MessageHandlerPtr mCharHandler;
+ MessageHandlerPtr mChatHandler;
+ MessageHandlerPtr mEffectHandler;
+ MessageHandlerPtr mGameHandler;
+ MessageHandlerPtr mGuildHandler;
+ MessageHandlerPtr mInventoryHandler;
+ MessageHandlerPtr mItemHandler;
+ MessageHandlerPtr mLoginHandler;
+ MessageHandlerPtr mNpcHandler;
+ MessageHandlerPtr mPartyHandler;
+ MessageHandlerPtr mPlayerHandler;
+ MessageHandlerPtr mTradeHandler;
+ MessageHandlerPtr mSpecialHandler;
+};
+
+} // namespace ManaServ
+
+#endif // NET_MANASERV_GENERALHANDLER_H
diff --git a/src/net/manaserv/guildhandler.cpp b/src/net/manaserv/guildhandler.cpp
new file mode 100644
index 00000000..876de413
--- /dev/null
+++ b/src/net/manaserv/guildhandler.cpp
@@ -0,0 +1,254 @@
+/*
+ * The Mana World
+ * Copyright (C) 2008 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "net/manaserv/guildhandler.h"
+
+#include "net/messagein.h"
+
+#include "net/manaserv/chatserver/chatserver.h"
+#include "net/manaserv/chatserver/guild.h"
+#include "net/manaserv/protocol.h"
+
+#include "gui/widgets/channeltab.h"
+#include "gui/chat.h"
+#include "gui/guildwindow.h"
+
+#include "guild.h"
+#include "log.h"
+#include "localplayer.h"
+#include "channel.h"
+#include "channelmanager.h"
+
+#include "utils/gettext.h"
+#include "utils/stringutils.h"
+
+#include <iostream>
+
+namespace ManaServ {
+
+GuildHandler::GuildHandler()
+{
+ static const Uint16 _messages[] = {
+ CPMSG_GUILD_CREATE_RESPONSE,
+ CPMSG_GUILD_INVITE_RESPONSE,
+ CPMSG_GUILD_ACCEPT_RESPONSE,
+ CPMSG_GUILD_GET_MEMBERS_RESPONSE,
+ CPMSG_GUILD_UPDATE_LIST,
+ CPMSG_GUILD_INVITED,
+ CPMSG_GUILD_REJOIN,
+ CPMSG_GUILD_QUIT_RESPONSE,
+ 0
+ };
+ handledMessages = _messages;
+
+}
+
+void GuildHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case CPMSG_GUILD_CREATE_RESPONSE:
+ {
+ logger->log("Received CPMSG_GUILD_CREATE_RESPONSE");
+ if(msg.readInt8() == ERRMSG_OK)
+ {
+ // TODO - Acknowledge guild was created
+ localChatTab->chatLog(_("Guild created."));
+ joinedGuild(msg);
+ }
+ else
+ {
+ localChatTab->chatLog(_("Error creating guild."));
+ }
+ } break;
+
+ case CPMSG_GUILD_INVITE_RESPONSE:
+ {
+ logger->log("Received CPMSG_GUILD_INVITE_RESPONSE");
+ if(msg.readInt8() == ERRMSG_OK)
+ {
+ // TODO - Acknowledge invite was sent
+ localChatTab->chatLog(_("Invite sent."));
+ }
+ } break;
+
+ case CPMSG_GUILD_ACCEPT_RESPONSE:
+ {
+ logger->log("Received CPMSG_GUILD_ACCEPT_RESPONSE");
+ if(msg.readInt8() == ERRMSG_OK)
+ {
+ // TODO - Acknowledge accepted into guild
+ joinedGuild(msg);
+ }
+ } break;
+
+ case CPMSG_GUILD_GET_MEMBERS_RESPONSE:
+ {
+ logger->log("Received CPMSG_GUILD_GET_MEMBERS_RESPONSE");
+ if(msg.readInt8() == ERRMSG_OK)
+ {
+ std::string guildMember;
+ bool online;
+ 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();
+ online = msg.readInt8();
+ if(guildMember != "")
+ {
+ guild->addMember(guildMember);
+ guildWindow->setOnline(guildName, guildMember, online);
+ }
+ }
+
+ guildWindow->updateTab();
+ }
+ } break;
+
+ case CPMSG_GUILD_UPDATE_LIST:
+ {
+ logger->log("Received CPMSG_GUILD_UPDATE_LIST");
+ short guildId = msg.readInt16();
+ std::string guildMember = msg.readString();
+ char eventId = msg.readInt8();
+
+ Guild *guild = player_node->getGuild(guildId);
+ if (guild)
+ {
+ switch(eventId)
+ {
+ case GUILD_EVENT_NEW_PLAYER:
+ guild->addMember(guildMember);
+ guildWindow->setOnline(guild->getName(), guildMember,
+ true);
+ break;
+
+ case GUILD_EVENT_LEAVING_PLAYER:
+ guild->removeMember(guildMember);
+ break;
+
+ case GUILD_EVENT_ONLINE_PLAYER:
+ guildWindow->setOnline(guild->getName(), guildMember,
+ true);
+ break;
+
+ case GUILD_EVENT_OFFLINE_PLAYER:
+ guildWindow->setOnline(guild->getName(), guildMember,
+ false);
+ break;
+
+ default:
+ logger->log("Invalid guild event");
+ }
+ }
+ guildWindow->updateTab();
+
+
+ } break;
+
+ case CPMSG_GUILD_INVITED:
+ {
+ logger->log("Received CPMSG_GUILD_INVITED");
+ std::string inviterName = msg.readString();
+ std::string guildName = msg.readString();
+
+ // Open a dialog asking if the player accepts joining the guild.
+ guildWindow->openAcceptDialog(inviterName, guildName);
+ } break;
+
+ case CPMSG_GUILD_PROMOTE_MEMBER_RESPONSE:
+ {
+ logger->log("Received CPMSG_GUILD_PROMOTE_MEMBER_RESPONSE");
+
+ if (msg.readInt8() == ERRMSG_OK)
+ {
+ // promotion succeeded
+ localChatTab->chatLog(_("Member was promoted successfully."));
+ }
+ else
+ {
+ // promotion failed
+ localChatTab->chatLog(_("Failed to promote member."));
+ }
+ }
+
+ case CPMSG_GUILD_REJOIN:
+ {
+ logger->log("Received CPMSG_GUILD_REJOIN");
+
+ joinedGuild(msg);
+ } break;
+
+ case CPMSG_GUILD_QUIT_RESPONSE:
+ {
+ logger->log("Received CPMSG_GUILD_QUIT_RESPONSE");
+
+ if (msg.readInt8() == ERRMSG_OK)
+ {
+ // Must remove tab first, as it wont find the guild
+ // name after its removed from the player
+ int guildId = msg.readInt16();
+ Guild *guild = player_node->getGuild(guildId);
+ if (guild)
+ {
+ Channel *channel = channelManager->findByName(guild->getName());
+ channelManager->removeChannel(channel);
+ guildWindow->removeTab(guildId);
+ player_node->removeGuild(guildId);
+ }
+ }
+ } break;
+ }
+}
+
+void GuildHandler::joinedGuild(MessageIn &msg)
+{
+ std::string guildName = msg.readString();
+ short guildId = msg.readInt16();
+ short permissions = msg.readInt16();
+ short channelId = msg.readInt16();
+ std::string announcement = msg.readString();
+
+ // Add guild to player and create new guild tab
+ Guild *guild = player_node->addGuild(guildId, permissions);
+ guild->setName(guildName);
+ guildWindow->newGuildTab(guildName);
+ guildWindow->requestMemberList(guildId);
+
+ // Automatically create the guild channel
+ // COMMENT: Should this go here??
+ Channel *channel = new Channel(channelId, guildName, announcement);
+ channelManager->addChannel(channel);
+ channel->getTab()->chatLog(strprintf(_("Topic: %s"), announcement.c_str()),
+ BY_CHANNEL);
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/guildhandler.h b/src/net/manaserv/guildhandler.h
new file mode 100644
index 00000000..d1b57e50
--- /dev/null
+++ b/src/net/manaserv/guildhandler.h
@@ -0,0 +1,44 @@
+/*
+ * The Mana World
+ * Copyright (C) 2008 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_MANASERV_GUILDHANDLER_H
+#define NET_MANASERV_GUILDHANDLER_H
+
+#include "net/messagehandler.h"
+
+#include <string>
+
+namespace ManaServ {
+
+class GuildHandler : public MessageHandler
+{
+public:
+ GuildHandler();
+
+ void handleMessage(MessageIn &msg);
+
+protected:
+ void joinedGuild(MessageIn &msg);
+};
+
+} // namespace ManaServ
+
+#endif
diff --git a/src/net/manaserv/internal.cpp b/src/net/manaserv/internal.cpp
new file mode 100644
index 00000000..055ce7f2
--- /dev/null
+++ b/src/net/manaserv/internal.cpp
@@ -0,0 +1,27 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "net/manaserv/internal.h"
+
+namespace Net
+{
+ int connections = 0;
+}
diff --git a/src/net/manaserv/internal.h b/src/net/manaserv/internal.h
new file mode 100644
index 00000000..582e4c17
--- /dev/null
+++ b/src/net/manaserv/internal.h
@@ -0,0 +1,30 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_MANASERV_INTERNAL_H
+#define NET_MANASERV_INTERNAL_H
+
+namespace Net
+{
+ extern int connections;
+}
+
+#endif
diff --git a/src/net/manaserv/inventoryhandler.cpp b/src/net/manaserv/inventoryhandler.cpp
new file mode 100644
index 00000000..6074c8d7
--- /dev/null
+++ b/src/net/manaserv/inventoryhandler.cpp
@@ -0,0 +1,167 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "net/manaserv/inventoryhandler.h"
+
+#include "net/manaserv/connection.h"
+#include "net/manaserv/protocol.h"
+
+#include "net/manaserv/gameserver/internal.h"
+#include "net/manaserv/gameserver/player.h"
+
+#include "net/messagein.h"
+#include "net/messageout.h"
+
+#include "equipment.h"
+#include "inventory.h"
+#include "item.h"
+#include "itemshortcut.h"
+#include "localplayer.h"
+
+#include "gui/chat.h"
+
+#include "resources/iteminfo.h"
+
+#include "log.h" // <<< REMOVE ME!
+
+Net::InventoryHandler *inventoryHandler;
+
+namespace ManaServ {
+
+InventoryHandler::InventoryHandler()
+{
+ static const Uint16 _messages[] = {
+ GPMSG_INVENTORY_FULL,
+ GPMSG_INVENTORY,
+ 0
+ };
+ handledMessages = _messages;
+ inventoryHandler = this;
+}
+
+void InventoryHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case GPMSG_INVENTORY_FULL:
+ player_node->clearInventory();
+ // no break!
+
+ case GPMSG_INVENTORY:
+ while (msg.getUnreadLength())
+ {
+ int slot = msg.readInt8();
+ if (slot == 255)
+ {
+ player_node->setMoney(msg.readInt32());
+ continue;
+ }
+
+ int id = msg.readInt16();
+ if (slot < EQUIPMENT_SIZE)
+ {
+ player_node->mEquipment->setEquipment(slot, id);
+ }
+ else if (slot >= 32 && slot < 32 + INVENTORY_SIZE)
+ {
+ int amount = id ? msg.readInt8() : 0;
+ player_node->setInvItem(slot - 32, id, amount);
+ }
+ };
+ break;
+ }
+}
+
+void InventoryHandler::equipItem(const Item *item)
+{
+ MessageOut msg(PGMSG_EQUIP);
+ msg.writeInt8(item->getInvIndex());
+ Net::GameServer::connection->send(msg);
+}
+
+void InventoryHandler::unequipItem(const Item *item)
+{
+ MessageOut msg(PGMSG_UNEQUIP);
+ msg.writeInt8(item->getInvIndex());
+ Net::GameServer::connection->send(msg);
+
+ // Tidy equipment directly to avoid weapon still shown bug, for instance
+ int equipSlot = item->getInvIndex();
+ logger->log("Unequipping %d", equipSlot);
+ player_node->mEquipment->setEquipment(equipSlot, 0);
+}
+
+void InventoryHandler::useItem(const Item *item)
+{
+ MessageOut msg(PGMSG_USE_ITEM);
+ msg.writeInt8(item->getInvIndex());
+ Net::GameServer::connection->send(msg);
+}
+
+void InventoryHandler::dropItem(const Item *item, int amount)
+{
+ MessageOut msg(PGMSG_DROP);
+ msg.writeInt8(item->getInvIndex());
+ msg.writeInt8(amount);
+ Net::GameServer::connection->send(msg);
+}
+
+bool InventoryHandler::canSplit(const Item *item)
+{
+ return item && !item->isEquipment() && item->getQuantity() > 1;
+}
+
+void InventoryHandler::splitItem(const Item *item, int amount)
+{
+ int newIndex = player_node->getInventory()->getFreeSlot();
+ if (newIndex > Inventory::NO_SLOT_INDEX)
+ {
+ Net::GameServer::Player::moveItem(
+ item->getInvIndex(), newIndex, amount);
+ }
+}
+
+void InventoryHandler::moveItem(int oldIndex, int newIndex)
+{
+ if (oldIndex == newIndex)
+ return;
+
+ Net::GameServer::Player::moveItem(oldIndex, newIndex,
+ player_node->getInventory()->getItem(oldIndex)->getQuantity());
+}
+
+void InventoryHandler::openStorage()
+{
+ // TODO
+}
+
+void InventoryHandler::closeStorage()
+{
+ // TODO
+}
+
+void InventoryHandler::moveItem(StorageType source, int slot, int amount,
+ StorageType destination)
+{
+ // TODO
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/inventoryhandler.h b/src/net/manaserv/inventoryhandler.h
new file mode 100644
index 00000000..b6510d6a
--- /dev/null
+++ b/src/net/manaserv/inventoryhandler.h
@@ -0,0 +1,61 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_MANASERV_INVENTORYHANDLER_H
+#define NET_MANASERV_INVENTORYHANDLER_H
+
+#include "net/inventoryhandler.h"
+#include "net/messagehandler.h"
+
+namespace ManaServ {
+
+class InventoryHandler : public MessageHandler, Net::InventoryHandler
+{
+ public:
+ InventoryHandler();
+
+ void handleMessage(MessageIn &msg);
+
+ void equipItem(const Item *item);
+
+ void unequipItem(const Item *item);
+
+ void useItem(const Item *item);
+
+ void dropItem(const Item *item, int amount);
+
+ bool canSplit(const Item *item);
+
+ void splitItem(const Item *item, int amount);
+
+ void moveItem(int oldIndex, int newIndex);
+
+ void openStorage();
+
+ void closeStorage();
+
+ void moveItem(StorageType source, int slot, int amount,
+ StorageType destination);
+};
+
+} // namespace ManaServ
+
+#endif
diff --git a/src/net/manaserv/itemhandler.cpp b/src/net/manaserv/itemhandler.cpp
new file mode 100644
index 00000000..6f25d7df
--- /dev/null
+++ b/src/net/manaserv/itemhandler.cpp
@@ -0,0 +1,70 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "net/manaserv/itemhandler.h"
+
+#include "net/manaserv/protocol.h"
+
+#include "net/messagein.h"
+
+#include "engine.h"
+#include "flooritemmanager.h"
+
+namespace ManaServ {
+
+ItemHandler::ItemHandler()
+{
+ static const Uint16 _messages[] = {
+ GPMSG_ITEMS,
+ GPMSG_ITEM_APPEAR,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void ItemHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case GPMSG_ITEM_APPEAR:
+ case GPMSG_ITEMS:
+ {
+ while (msg.getUnreadLength())
+ {
+ int itemId = msg.readInt16();
+ int x = msg.readInt16();
+ int y = msg.readInt16();
+ int id = (x << 16) | y; // dummy id
+
+ if (itemId)
+ {
+ floorItemManager->create(id, itemId, x / 32, y / 32, engine->getCurrentMap());
+ }
+ else if (FloorItem *item = floorItemManager->findById(id))
+ {
+ floorItemManager->destroy(item);
+ }
+ }
+ } break;
+ }
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/itemhandler.h b/src/net/manaserv/itemhandler.h
new file mode 100644
index 00000000..fde3000d
--- /dev/null
+++ b/src/net/manaserv/itemhandler.h
@@ -0,0 +1,39 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_MANASERV_ITEMHANDLER_H
+#define NET_MANASERV_ITEMHANDLER_H
+
+#include "net/messagehandler.h"
+
+namespace ManaServ {
+
+class ItemHandler : public MessageHandler
+{
+ public:
+ ItemHandler();
+
+ void handleMessage(MessageIn &msg);
+};
+
+} // namespace ManaServ
+
+#endif
diff --git a/src/net/manaserv/loginhandler.cpp b/src/net/manaserv/loginhandler.cpp
new file mode 100644
index 00000000..8ae63ce9
--- /dev/null
+++ b/src/net/manaserv/loginhandler.cpp
@@ -0,0 +1,359 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "net/manaserv/loginhandler.h"
+
+#include "net/manaserv/connection.h"
+#include "net/manaserv/protocol.h"
+
+#include "net/manaserv/accountserver/account.h"
+#include "net/manaserv/accountserver/accountserver.h"
+
+#include "net/logindata.h"
+#include "net/messagein.h"
+
+#include "main.h"
+
+#include "utils/gettext.h"
+
+Net::LoginHandler *loginHandler;
+
+extern Net::Connection *accountServerConnection;
+
+namespace ManaServ {
+
+LoginHandler::LoginHandler()
+{
+ static const Uint16 _messages[] = {
+ APMSG_LOGIN_RESPONSE,
+ APMSG_REGISTER_RESPONSE,
+ APMSG_RECONNECT_RESPONSE,
+ APMSG_PASSWORD_CHANGE_RESPONSE,
+ APMSG_EMAIL_CHANGE_RESPONSE,
+ APMSG_LOGOUT_RESPONSE,
+ APMSG_UNREGISTER_RESPONSE,
+ 0
+ };
+ handledMessages = _messages;
+ loginHandler = this;
+}
+
+void LoginHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case APMSG_LOGIN_RESPONSE:
+ handleLoginResponse(msg);
+ break;
+ case APMSG_REGISTER_RESPONSE:
+ handleRegisterResponse(msg);
+ break;
+ case APMSG_RECONNECT_RESPONSE:
+ {
+ int errMsg = msg.readInt8();
+ // 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;
+
+ case APMSG_PASSWORD_CHANGE_RESPONSE:
+ {
+ int errMsg = msg.readInt8();
+ // Successful pass change
+ if (errMsg == ERRMSG_OK)
+ {
+ state = STATE_CHANGEPASSWORD_SUCCESS;
+ }
+ // pass change failed
+ else
+ {
+ switch (errMsg) {
+ case ERRMSG_INVALID_ARGUMENT:
+ errorMessage = _("New password incorrect.");
+ break;
+ case ERRMSG_FAILURE:
+ errorMessage = _("Old password incorrect.");
+ break;
+ case ERRMSG_NO_LOGIN:
+ errorMessage = _("Account not connected. Please login first.");
+ break;
+ default:
+ errorMessage = _("Unknown error.");
+ break;
+ }
+ state = STATE_ACCOUNTCHANGE_ERROR;
+ }
+ }
+ break;
+
+ case APMSG_EMAIL_CHANGE_RESPONSE:
+ {
+ int errMsg = msg.readInt8();
+ // Successful pass change
+ if (errMsg == ERRMSG_OK)
+ {
+ state = STATE_CHANGEEMAIL_SUCCESS;
+ }
+ // pass change failed
+ else
+ {
+ switch (errMsg) {
+ case ERRMSG_INVALID_ARGUMENT:
+ errorMessage = _("New email address incorrect.");
+ break;
+ case ERRMSG_FAILURE:
+ errorMessage = _("Old email address incorrect.");
+ break;
+ case ERRMSG_NO_LOGIN:
+ errorMessage = _("Account not connected. Please login first.");
+ break;
+ case ERRMSG_EMAIL_ALREADY_EXISTS:
+ errorMessage = _("The new email address already exists.");
+ break;
+ default:
+ errorMessage = _("Unknown error.");
+ break;
+ }
+ state = STATE_ACCOUNTCHANGE_ERROR;
+ }
+ }
+ break;
+ case APMSG_LOGOUT_RESPONSE:
+ {
+ int errMsg = msg.readInt8();
+
+ // Successful logout
+ if (errMsg == ERRMSG_OK)
+ {
+ // TODO: handle logout
+ }
+ // 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.readInt8();
+ // 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_ACCOUNTCHANGE_ERROR;
+ }
+ }
+ break;
+ }
+}
+
+void LoginHandler::handleLoginResponse(MessageIn &msg)
+{
+ const int errMsg = msg.readInt8();
+
+ if (errMsg == ERRMSG_OK)
+ {
+ readUpdateHost(msg);
+ // No worlds atm, but future use :-D
+ state = STATE_WORLD_SELECT;
+ }
+ else
+ {
+ switch (errMsg) {
+ case LOGIN_INVALID_VERSION:
+ errorMessage = _("Client version is too old.");
+ break;
+ case ERRMSG_INVALID_ARGUMENT:
+ errorMessage = _("Wrong username or password.");
+ break;
+ case ERRMSG_FAILURE:
+ errorMessage = _("Already logged in.");
+ break;
+ case LOGIN_SERVER_FULL:
+ errorMessage = _("Server is full.");
+ break;
+ case LOGIN_INVALID_TIME:
+ errorMessage = _("Login attempt too soon after previous "
+ "attempt.");
+ break;
+ default:
+ errorMessage = _("Unknown error.");
+ break;
+ }
+ state = STATE_LOGIN_ERROR;
+ }
+}
+
+void LoginHandler::handleRegisterResponse(MessageIn &msg)
+{
+ const int errMsg = msg.readInt8();
+
+ if (errMsg == ERRMSG_OK)
+ {
+ readUpdateHost(msg);
+ state = STATE_WORLD_SELECT;
+ }
+ else
+ {
+ switch (errMsg) {
+ case REGISTER_INVALID_VERSION:
+ errorMessage = _("Client version is too old.");
+ break;
+ case ERRMSG_INVALID_ARGUMENT:
+ errorMessage = _("Wrong username, password or email address.");
+ break;
+ case REGISTER_EXISTS_USERNAME:
+ errorMessage = _("Username already exists.");
+ break;
+ case REGISTER_EXISTS_EMAIL:
+ errorMessage = _("Email address already exists.");
+ break;
+ default:
+ errorMessage = _("Unknown error.");
+ break;
+ }
+ state = STATE_LOGIN_ERROR;
+ }
+}
+
+void LoginHandler::readUpdateHost(MessageIn &msg)
+{
+ // Set the update host when included in the message
+ if (msg.getUnreadLength() > 0)
+ {
+ mLoginData->updateHost = msg.readString();
+ }
+}
+
+void LoginHandler::connect()
+{
+ accountServerConnection->connect(mServer.hostname, mServer.port);
+ /*if (state == STATE_CONNECT_SERVER)
+ state = STATE_LOGIN;*/
+}
+
+bool LoginHandler::isConnected()
+{
+ return accountServerConnection->isConnected();
+}
+
+void LoginHandler::disconnect()
+{
+ accountServerConnection->disconnect();
+}
+
+void LoginHandler::loginAccount(LoginData *loginData)
+{
+ mLoginData = loginData;
+ Net::AccountServer::login(accountServerConnection,
+ 0, // client version
+ loginData->username,
+ loginData->password);
+}
+
+void LoginHandler::logout()
+{
+ // TODO
+}
+
+void LoginHandler::changeEmail(const std::string &email)
+{
+ Net::AccountServer::Account::changeEmail(email);
+}
+
+void LoginHandler::changePassword(const std::string &username,
+ const std::string &oldPassword,
+ const std::string &newPassword)
+{
+ Net::AccountServer::Account::changePassword(username, oldPassword,
+ newPassword);
+}
+
+void LoginHandler::chooseServer(unsigned int server)
+{
+ // TODO
+}
+
+void LoginHandler::registerAccount(LoginData *loginData)
+{
+ Net::AccountServer::registerAccount(accountServerConnection,
+ 0, // client version
+ loginData->username,
+ loginData->password,
+ loginData->email);
+}
+
+void LoginHandler::unregisterAccount(const std::string &username,
+ const std::string &password)
+{
+ Net::AccountServer::Account::unregister(username, password);
+}
+
+Worlds LoginHandler::getWorlds() const
+{
+ return Worlds();
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/loginhandler.h b/src/net/manaserv/loginhandler.h
new file mode 100644
index 00000000..f5013fc2
--- /dev/null
+++ b/src/net/manaserv/loginhandler.h
@@ -0,0 +1,84 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_MANASERV_LOGINHANDLER_H
+#define NET_MANASERV_LOGINHANDLER_H
+
+#include "net/loginhandler.h"
+#include "net/messagehandler.h"
+
+#include "net/serverinfo.h"
+
+class LoginData;
+
+namespace ManaServ {
+
+class LoginHandler : public MessageHandler, public Net::LoginHandler
+{
+ public:
+ LoginHandler();
+
+ void handleMessage(MessageIn &msg);
+
+ void connect();
+
+ bool isConnected();
+
+ void disconnect();
+
+ int supportedOptionalActions() const
+ { return Unregister | ChangeEmail | SetEmailOnRegister; }
+
+ unsigned int getMaxUserNameLength() const { return 15; };
+
+ unsigned int getMinPasswordLength() const { return 6; };
+
+ void loginAccount(LoginData *loginData);
+
+ void logout();
+
+ void changeEmail(const std::string &email);
+
+ void changePassword(const std::string &username,
+ const std::string &oldPassword,
+ const std::string &newPassword);
+
+ void chooseServer(unsigned int server);
+
+ void registerAccount(LoginData *loginData);
+
+ void unregisterAccount(const std::string &username,
+ const std::string &password);
+
+ Worlds getWorlds() const;
+
+ private:
+ void handleLoginResponse(MessageIn &msg);
+ void handleRegisterResponse(MessageIn &msg);
+
+ void readUpdateHost(MessageIn &msg);
+
+ LoginData *mLoginData;
+};
+
+} // namespace ManaServ
+
+#endif // NET_MANASERV_LOGINHANDLER_H
diff --git a/src/net/manaserv/network.cpp b/src/net/manaserv/network.cpp
new file mode 100644
index 00000000..84b9d070
--- /dev/null
+++ b/src/net/manaserv/network.cpp
@@ -0,0 +1,170 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "net/manaserv/network.h"
+
+#include "net/manaserv/connection.h"
+#include "net/manaserv/internal.h"
+
+#include "net/messagehandler.h"
+#include "net/messagein.h"
+
+#include "log.h"
+
+#include <enet/enet.h>
+
+#include <map>
+
+/**
+ * The local host which is shared for all outgoing connections.
+ */
+namespace {
+ ENetHost *client;
+}
+
+typedef std::map<unsigned short, MessageHandler*> MessageHandlers;
+typedef MessageHandlers::iterator MessageHandlerIterator;
+static MessageHandlers mMessageHandlers;
+
+void Net::initialize()
+{
+ if (enet_initialize())
+ {
+ logger->error("Failed to initialize ENet.");
+ }
+
+ client = enet_host_create(NULL, 3, 0, 0);
+
+ if (!client)
+ {
+ logger->error("Failed to create the local host.");
+ }
+}
+
+void Net::finalize()
+{
+ if (!client)
+ return; // Wasn't initialized at all
+
+ if (Net::connections) {
+ logger->error("Tried to shutdown the network subsystem while there "
+ "are network connections left!");
+ }
+
+ clearHandlers();
+ enet_deinitialize();
+}
+
+Net::Connection *Net::getConnection()
+{
+ if (!client)
+ {
+ logger->error("Tried to instantiate a network object before "
+ "initializing the network subsystem!");
+ }
+
+ return new Net::Connection(client);
+}
+
+void Net::registerHandler(MessageHandler *handler)
+{
+ for (const Uint16 *i = handler->handledMessages; *i; i++)
+ {
+ mMessageHandlers[*i] = handler;
+ }
+}
+
+void Net::unregisterHandler(MessageHandler *handler)
+{
+ for (const Uint16 *i = handler->handledMessages; *i; i++)
+ {
+ mMessageHandlers.erase(*i);
+ }
+}
+
+void Net::clearHandlers()
+{
+ mMessageHandlers.clear();
+}
+
+
+/**
+ * Dispatches a message to the appropriate message handler and
+ * destroys it afterwards.
+ */
+namespace
+{
+ void dispatchMessage(ENetPacket *packet)
+ {
+ MessageIn msg((const char *)packet->data, packet->dataLength);
+
+ MessageHandlerIterator iter = mMessageHandlers.find(msg.getId());
+
+ if (iter != mMessageHandlers.end()) {
+ //logger->log("Received packet %x (%i B)",
+ // msg.getId(), msg.getLength());
+ iter->second->handleMessage(msg);
+ }
+ else {
+ logger->log("Unhandled packet %x (%i B)",
+ msg.getId(), msg.getLength());
+ }
+
+ // Clean up the packet now that we're done using it.
+ enet_packet_destroy(packet);
+ }
+}
+
+void Net::flush()
+{
+ ENetEvent event;
+
+ // Wait up to 10 milliseconds for an event.
+ while (enet_host_service(client, &event, 10) > 0)
+ {
+ switch (event.type)
+ {
+ case ENET_EVENT_TYPE_CONNECT:
+ logger->log("Connected to port %d.", event.peer->address.port);
+ // Store any relevant server information here.
+ event.peer->data = 0;
+ break;
+
+ case ENET_EVENT_TYPE_RECEIVE:
+ dispatchMessage(event.packet);
+ break;
+
+ case ENET_EVENT_TYPE_DISCONNECT:
+ logger->log("Disconnected.");
+ // Reset the server information.
+ event.peer->data = 0;
+ break;
+
+ case ENET_EVENT_TYPE_NONE:
+ logger->log("No event during 10 milliseconds.");
+ break;
+
+ default:
+ logger->log("Unhandled enet event.");
+ break;
+ }
+ }
+}
diff --git a/src/net/manaserv/network.h b/src/net/manaserv/network.h
new file mode 100644
index 00000000..8b7cedd8
--- /dev/null
+++ b/src/net/manaserv/network.h
@@ -0,0 +1,79 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_MANASERV_NETWORK_H
+#define NET_MANASERV_NETWORK_H
+
+#include <iosfwd>
+
+/**
+ * \defgroup Network Core network layer
+ */
+
+class MessageHandler;
+class MessageOut;
+
+/**
+ * \ingroup Network
+ */
+namespace Net
+{
+ class Connection;
+
+ /**
+ * Initializes the network subsystem.
+ */
+ void initialize();
+
+ /**
+ * Finalizes the network subsystem.
+ */
+ void finalize();
+
+ /**
+ * Returns a new Connection object. Should be deleted by the caller.
+ */
+ Connection *getConnection();
+
+ /**
+ * Registers a message handler. A message handler handles a certain
+ * subset of incoming messages.
+ */
+ void registerHandler(MessageHandler *handler);
+
+ /**
+ * Unregisters a message handler.
+ */
+ void unregisterHandler(MessageHandler *handler);
+
+ /**
+ * Clears all registered message handlers.
+ */
+ void clearHandlers();
+
+ /*
+ * Handles all events and dispatches incoming messages to the
+ * registered handlers
+ */
+ void flush();
+}
+
+#endif
diff --git a/src/net/manaserv/npchandler.cpp b/src/net/manaserv/npchandler.cpp
new file mode 100644
index 00000000..2f1a8e4a
--- /dev/null
+++ b/src/net/manaserv/npchandler.cpp
@@ -0,0 +1,206 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "net/manaserv/npchandler.h"
+
+#include "net/manaserv/connection.h"
+#include "net/manaserv/protocol.h"
+
+#include "net/manaserv/gameserver/internal.h"
+#include "net/manaserv/gameserver/player.h"
+
+#include "net/messagein.h"
+#include "net/messageout.h"
+
+#include "beingmanager.h"
+#include "npc.h"
+
+#include "gui/npcpostdialog.h"
+#include "gui/npcdialog.h"
+
+Net::NpcHandler *npcHandler;
+
+namespace ManaServ {
+
+NpcHandler::NpcHandler()
+{
+ static const Uint16 _messages[] = {
+ GPMSG_NPC_CHOICE,
+ GPMSG_NPC_POST,
+ GPMSG_NPC_MESSAGE,
+ GPMSG_NPC_ERROR,
+ GPMSG_NPC_CLOSE,
+ GPMSG_NPC_NUMBER,
+ GPMSG_NPC_STRING,
+ 0
+ };
+ handledMessages = _messages;
+ npcHandler = this;
+}
+
+void NpcHandler::handleMessage(MessageIn &msg)
+{
+ Being *being = beingManager->findBeing(msg.readInt16());
+ if (!being || being->getType() != Being::NPC)
+ {
+ return;
+ }
+
+ current_npc = being->getId();
+ npcDialog->setNpc(current_npc);
+
+ switch (msg.getId())
+ {
+ case GPMSG_NPC_CHOICE:
+ npcDialog->choiceRequest();
+ while (msg.getUnreadLength())
+ {
+ npcDialog->addChoice(msg.readString());
+ }
+ break;
+
+ case GPMSG_NPC_NUMBER:
+ {
+ int min_num = msg.readInt32();
+ int max_num = msg.readInt32();
+ npcDialog->integerRequest(msg.readInt32(), min_num, max_num);
+ break;
+ }
+
+ case GPMSG_NPC_STRING:
+ npcDialog->textRequest("");
+ break;
+
+ case GPMSG_NPC_POST:
+ npcDialog->setVisible(false);
+ npcPostDialog->clear();
+ npcPostDialog->setVisible(true);
+ break;
+
+ case GPMSG_NPC_ERROR:
+ current_npc = NULL;
+ break;
+
+ case GPMSG_NPC_MESSAGE:
+ npcDialog->addText(msg.readString(msg.getUnreadLength()));
+ npcDialog->showNextButton();
+ npcDialog->setVisible(true);
+ break;
+
+ case GPMSG_NPC_CLOSE:
+ npcDialog->showCloseButton();
+ break;
+ }
+}
+
+void NpcHandler::talk(int npcId)
+{
+ MessageOut msg(PGMSG_NPC_TALK);
+ msg.writeInt16(npcId);
+ Net::GameServer::connection->send(msg);
+}
+
+void NpcHandler::nextDialog(int npcId)
+{
+ MessageOut msg(PGMSG_NPC_TALK_NEXT);
+ msg.writeInt16(npcId);
+ Net::GameServer::connection->send(msg);
+}
+
+void NpcHandler::closeDialog(int npcId)
+{
+ MessageOut msg(PGMSG_NPC_TALK_NEXT);
+ msg.writeInt16(npcId);
+ Net::GameServer::connection->send(msg);
+ npcDialog->setVisible(false);
+ npcDialog->setText("");
+}
+
+void NpcHandler::listInput(int npcId, int value)
+{
+ MessageOut msg(PGMSG_NPC_SELECT);
+ msg.writeInt16(npcId);
+ msg.writeInt8(value);
+ Net::GameServer::connection->send(msg);
+}
+
+void NpcHandler::integerInput(int npcId, int value)
+{
+ MessageOut msg(PGMSG_NPC_NUMBER);
+ msg.writeInt16(npcId);
+ msg.writeInt32(value);
+ Net::GameServer::connection->send(msg);
+}
+
+void NpcHandler::stringInput(int npcId, const std::string &value)
+{
+ MessageOut msg(PGMSG_NPC_STRING);
+ msg.writeInt16(npcId);
+ msg.writeString(value);
+ Net::GameServer::connection->send(msg);
+}
+
+void NpcHandler::sendLetter(int npcId, const std::string &recipient,
+ const std::string &text)
+{
+ MessageOut msg(PGMSG_NPC_POST_SEND);
+ msg.writeString(recipient);
+ msg.writeString(text);
+ Net::GameServer::connection->send(msg);
+}
+
+void NpcHandler::startShopping(int beingId)
+{
+ // TODO
+}
+
+void NpcHandler::buy(int beingId)
+{
+ // TODO
+}
+
+void NpcHandler::sell(int beingId)
+{
+ // TODO
+}
+
+void NpcHandler::buyItem(int beingId, int itemId, int amount)
+{
+ MessageOut msg(PGMSG_NPC_BUYSELL);
+ msg.writeInt16(itemId);
+ msg.writeInt16(amount);
+ Net::GameServer::connection->send(msg);
+}
+
+void NpcHandler::sellItem(int beingId, int itemId, int amount)
+{
+ MessageOut msg(PGMSG_NPC_BUYSELL);
+ msg.writeInt16(itemId);
+ msg.writeInt16(amount);
+ Net::GameServer::connection->send(msg);
+}
+
+void NpcHandler::endShopping(int beingId)
+{
+ // TODO
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/npchandler.h b/src/net/manaserv/npchandler.h
new file mode 100644
index 00000000..bc0aaee1
--- /dev/null
+++ b/src/net/manaserv/npchandler.h
@@ -0,0 +1,69 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_MANASERV_NPCHANDLER_H
+#define NET_MANASERV_NPCHANDLER_H
+
+#include "net/messagehandler.h"
+#include "net/npchandler.h"
+
+#include <list>
+
+namespace ManaServ {
+
+class NpcHandler : public MessageHandler, public Net::NpcHandler
+{
+ public:
+ NpcHandler();
+
+ void handleMessage(MessageIn &msg);
+
+ void talk(int npcId);
+
+ void nextDialog(int npcId);
+
+ void closeDialog(int npcId);
+
+ void listInput(int npcId, int value);
+
+ void integerInput(int npcId, int value);
+
+ void stringInput(int npcId, const std::string &value);
+
+ void sendLetter(int npcId, const std::string &recipient,
+ const std::string &text);
+
+ void startShopping(int beingId);
+
+ void buy(int beingId);
+
+ void sell(int beingId);
+
+ void buyItem(int beingId, int itemId, int amount);
+
+ void sellItem(int beingId, int itemId, int amount);
+
+ void endShopping(int beingId);
+};
+
+} // namespace ManaServ
+
+#endif
diff --git a/src/net/manaserv/partyhandler.cpp b/src/net/manaserv/partyhandler.cpp
new file mode 100644
index 00000000..9f20f027
--- /dev/null
+++ b/src/net/manaserv/partyhandler.cpp
@@ -0,0 +1,179 @@
+/*
+ * The Mana World
+ * Copyright (C) 2008 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "net/manaserv/partyhandler.h"
+
+#include "net/manaserv/protocol.h"
+
+#include "net/manaserv/chatserver/chatserver.h"
+#include "net/manaserv/chatserver/party.h"
+
+#include "net/messagein.h"
+
+#include "gui/partywindow.h"
+
+#include "gui/widgets/chattab.h"
+
+#include "log.h"
+#include "localplayer.h"
+
+#include "utils/gettext.h"
+#include "utils/stringutils.h"
+
+#include <iostream>
+
+Net::PartyHandler *partyHandler;
+
+namespace ManaServ {
+
+PartyHandler::PartyHandler()
+{
+ static const Uint16 _messages[] = {
+ CPMSG_PARTY_INVITE_RESPONSE,
+ CPMSG_PARTY_INVITED,
+ CPMSG_PARTY_ACCEPT_INVITE_RESPONSE,
+ CPMSG_PARTY_QUIT_RESPONSE,
+ CPMSG_PARTY_NEW_MEMBER,
+ CPMSG_PARTY_MEMBER_LEFT,
+ CPMSG_PARTY_REJECTED,
+ 0
+ };
+ handledMessages = _messages;
+ partyHandler = this;
+}
+
+void PartyHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case CPMSG_PARTY_INVITE_RESPONSE:
+ {
+ if (msg.readInt8() == ERRMSG_OK)
+ {
+
+ }
+ } break;
+
+ case CPMSG_PARTY_INVITED:
+ {
+ std::string inviter = msg.readString();
+ partyWindow->showPartyInvite(inviter);
+ } break;
+
+ case CPMSG_PARTY_ACCEPT_INVITE_RESPONSE:
+ {
+ if (msg.readInt8() == ERRMSG_OK)
+ {
+ player_node->setInParty(true);
+ localChatTab->chatLog(_("Joined party."));
+ }
+ }
+
+ case CPMSG_PARTY_QUIT_RESPONSE:
+ {
+ if (msg.readInt8() == ERRMSG_OK)
+ {
+ player_node->setInParty(false);
+ }
+ } break;
+
+ case CPMSG_PARTY_NEW_MEMBER:
+ {
+ int id = msg.readInt16(); // being id
+ std::string name = msg.readString();
+
+ localChatTab->chatLog(strprintf(_("%s joined the party."),
+ name.c_str()));
+
+ if (!player_node->isInParty())
+ player_node->setInParty(true);
+
+ partyWindow->updateMember(id, name);
+ } break;
+
+ case CPMSG_PARTY_MEMBER_LEFT:
+ {
+ partyWindow->removeMember(msg.readString());
+ } break;
+
+ case CPMSG_PARTY_REJECTED:
+ {
+ std::string name = msg.readString();
+ localChatTab->chatLog(strprintf(_("%s rejected your invite."),
+ name.c_str()));
+ } break;
+ }
+}
+
+void PartyHandler::create(const std::string &name)
+{
+ // TODO
+}
+
+void PartyHandler::join(int partyId)
+{
+ // TODO
+}
+
+void PartyHandler::invite(Player *player)
+{
+ invite(player->getName());
+}
+
+void PartyHandler::invite(const std::string &name)
+{
+ Net::ChatServer::Party::invitePlayer(name);
+}
+
+void PartyHandler::inviteResponse(const std::string &inviter, bool accept)
+{
+ if (accept)
+ Net::ChatServer::Party::acceptInvite(inviter);
+ else
+ Net::ChatServer::Party::rejectInvite(inviter);
+}
+
+void PartyHandler::leave()
+{
+ Net::ChatServer::Party::quitParty();
+}
+
+void PartyHandler::kick(Player *player)
+{
+ // TODO
+}
+
+void PartyHandler::kick(const std::string &name)
+{
+ // TODO
+}
+
+void PartyHandler::chat(const std::string &text)
+{
+ // TODO
+}
+
+void PartyHandler::requestPartyMembers()
+{
+ // TODO
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/partyhandler.h b/src/net/manaserv/partyhandler.h
new file mode 100644
index 00000000..c44f7ace
--- /dev/null
+++ b/src/net/manaserv/partyhandler.h
@@ -0,0 +1,71 @@
+/*
+ * The Mana World
+ * Copyright (C) 2008 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_MANASERV_PARTYHANDLER_H
+#define NET_MANASERV_PARTYHANDLER_H
+
+#include "net/messagehandler.h"
+#include "net/partyhandler.h"
+
+#include <string>
+
+namespace ManaServ {
+
+class PartyHandler : public MessageHandler, public Net::PartyHandler
+{
+public:
+ PartyHandler();
+
+ void handleMessage(MessageIn &msg);
+
+ void create(const std::string &name = "");
+
+ void join(int partyId);
+
+ void invite(Player *player);
+
+ void invite(const std::string &name);
+
+ void inviteResponse(const std::string &inviter, bool accept);
+
+ void leave();
+
+ void kick(Player *player);
+
+ void kick(const std::string &name);
+
+ void chat(const std::string &text);
+
+ void requestPartyMembers();
+
+ PartyShare getShareExperience() { return PARTY_SHARE_NO; }
+
+ void setShareExperience(PartyShare share) {}
+
+ PartyShare getShareItems() { return PARTY_SHARE_NO; }
+
+ void setShareItems(PartyShare share) {}
+};
+
+} // namespace ManaServ
+
+#endif
+
diff --git a/src/net/manaserv/playerhandler.cpp b/src/net/manaserv/playerhandler.cpp
new file mode 100644
index 00000000..91ff6a1c
--- /dev/null
+++ b/src/net/manaserv/playerhandler.cpp
@@ -0,0 +1,411 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "net/manaserv/playerhandler.h"
+
+#include "net/manaserv/connection.h"
+#include "net/manaserv/protocol.h"
+
+#include "net/manaserv/gameserver/internal.h"
+#include "net/manaserv/gameserver/player.h"
+
+#include "net/messagein.h"
+#include "net/messageout.h"
+#include "net/net.h"
+
+#include "effectmanager.h"
+#include "engine.h"
+#include "localplayer.h"
+#include "log.h"
+#include "particle.h"
+#include "npc.h"
+
+#include "gui/buy.h"
+#include "gui/chat.h"
+#include "gui/gui.h"
+#include "gui/okdialog.h"
+#include "gui/sell.h"
+#include "gui/viewport.h"
+
+// TODO Move somewhere else
+OkDialog *weightNotice = NULL;
+OkDialog *deathNotice = NULL;
+
+extern BuyDialog *buyDialog;
+extern SellDialog *sellDialog;
+extern Window *buySellDialog;
+
+/* Max. distance we are willing to scroll after a teleport;
+ * everything beyond will reset the port hard.
+ */
+static const int MAP_TELEPORT_SCROLL_DISTANCE = 8 * 32;
+
+/**
+ * Listener used for handling the overweigth message.
+ */
+// TODO Move somewhere else
+namespace {
+ struct WeightListener : public gcn::ActionListener
+ {
+ void action(const gcn::ActionEvent &event)
+ {
+ weightNotice = NULL;
+ }
+ } weightListener;
+}
+
+/**
+ * Listener used for handling death message.
+ */
+// TODO Move somewhere else
+namespace {
+ struct DeathListener : public gcn::ActionListener
+ {
+ void action(const gcn::ActionEvent &event)
+ {
+ Net::getPlayerHandler()->respawn();
+ deathNotice = NULL;
+ buyDialog->setVisible(false);
+ sellDialog->setVisible(false);
+ current_npc = 0;
+ }
+ } deathListener;
+}
+
+Net::PlayerHandler *playerHandler;
+
+namespace ManaServ {
+
+PlayerHandler::PlayerHandler()
+{
+ static const Uint16 _messages[] = {
+ GPMSG_PLAYER_MAP_CHANGE,
+ GPMSG_PLAYER_SERVER_CHANGE,
+ GPMSG_PLAYER_ATTRIBUTE_CHANGE,
+ GPMSG_PLAYER_EXP_CHANGE,
+ GPMSG_LEVELUP,
+ GPMSG_LEVEL_PROGRESS,
+ GPMSG_RAISE_ATTRIBUTE_RESPONSE,
+ GPMSG_LOWER_ATTRIBUTE_RESPONSE,
+ GPMSG_SPECIAL_STATUS,
+ 0
+ };
+ handledMessages = _messages;
+ playerHandler = this;
+}
+
+void PlayerHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case GPMSG_PLAYER_MAP_CHANGE:
+ handleMapChangeMessage(msg);
+ break;
+
+ case GPMSG_PLAYER_SERVER_CHANGE:
+ { // TODO: Implement reconnecting to another game server
+ std::string token = msg.readString(32);
+ std::string address = msg.readString();
+ int port = msg.readInt16();
+ logger->log("Changing server to %s:%d", address.c_str(), port);
+ } break;
+
+ case GPMSG_PLAYER_ATTRIBUTE_CHANGE:
+ {
+ logger->log("ATTRIBUTE UPDATE:");
+ while (msg.getUnreadLength())
+ {
+ int stat = msg.readInt16();
+ int base = msg.readInt16();
+ int value = msg.readInt16();
+ logger->log("%d set to %d %d", stat, base, value);
+
+ if (stat == BASE_ATTR_HP)
+ {
+ player_node->setMaxHp(base);
+ player_node->setHp(value);
+ }
+ else
+ {
+ player_node->setAttributeBase(stat, base);
+ player_node->setAttributeEffective(stat, value);
+ }
+ }
+ } break;
+
+ case GPMSG_PLAYER_EXP_CHANGE:
+ {
+ logger->log("EXP Update");
+ while (msg.getUnreadLength())
+ {
+ int skill = msg.readInt16();
+ int current = msg.readInt32();
+ int next = msg.readInt32();
+
+ player_node->setExperience(skill, current, next);
+ }
+ } break;
+
+ case GPMSG_LEVELUP:
+ {
+ player_node->setLevel(msg.readInt16());
+ player_node->setCharacterPoints(msg.readInt16());
+ player_node->setCorrectionPoints(msg.readInt16());
+ Particle* effect = particleEngine->addEffect("graphics/particles/levelup.particle.xml", 0, 0);
+ player_node->controlParticle(effect);
+ } break;
+
+
+ case GPMSG_LEVEL_PROGRESS:
+ {
+ logger->log("Level Progress Update");
+ player_node->setExp(msg.readInt8());
+ } break;
+
+
+ case GPMSG_RAISE_ATTRIBUTE_RESPONSE:
+ {
+ int errCode = msg.readInt8();
+ int attrNum = msg.readInt8() - CHAR_ATTR_BEGIN;
+ switch (errCode)
+ {
+ case ATTRIBMOD_OK:
+ {
+ // feel(acknowledgment);
+ } break;
+ case ATTRIBMOD_INVALID_ATTRIBUTE:
+ {
+ logger->log("Warning: Server denied increase of attribute %d (unknown attribute) ", attrNum);
+ } break;
+ case ATTRIBMOD_NO_POINTS_LEFT:
+ {
+ // when the server says "you got no points" it
+ // has to be correct. The server is always right!
+ // undo attribute change and set points to 0
+ logger->log("Warning: Server denied increase of attribute %d (no points left) ", attrNum);
+ int attrValue = player_node->getAttributeBase(attrNum) - 1;
+ player_node->setCharacterPoints(0);
+ player_node->setAttributeBase(attrNum, attrValue);
+ } break;
+ case ATTRIBMOD_DENIED:
+ {
+ // undo attribute change
+ logger->log("Warning: Server denied increase of attribute %d (reason unknown) ", attrNum);
+ int points = player_node->getCharacterPoints() - 1;
+ player_node->setCharacterPoints(points);
+ int attrValue = player_node->getAttributeBase(attrNum) - 1;
+ player_node->setAttributeBase(attrNum, attrValue);
+ } break;
+ }
+ } break;
+
+ case GPMSG_LOWER_ATTRIBUTE_RESPONSE:
+ {
+ int errCode = msg.readInt8();
+ int attrNum = msg.readInt8() - CHAR_ATTR_BEGIN;
+ switch (errCode)
+ {
+ case ATTRIBMOD_OK:
+ {
+ // feel(acknowledgment);
+ } break;
+ case ATTRIBMOD_INVALID_ATTRIBUTE:
+ {
+ logger->log("Warning: Server denied reduction of attribute %d (unknown attribute) ", attrNum);
+ } break;
+ case ATTRIBMOD_NO_POINTS_LEFT:
+ {
+ // when the server says "you got no points" it
+ // has to be correct. The server is always right!
+ // undo attribute change and set points to 0
+ logger->log("Warning: Server denied reduction of attribute %d (no points left) ", attrNum);
+ int attrValue = player_node->getAttributeBase(attrNum) + 1;
+ player_node->setCorrectionPoints(0);
+ player_node->setAttributeBase(attrNum, attrValue);
+ break;
+ } break;
+ case ATTRIBMOD_DENIED:
+ {
+ // undo attribute change
+ logger->log("Warning: Server denied reduction of attribute %d (reason unknown) ", attrNum);
+ int charaPoints = player_node->getCharacterPoints() - 1;
+ player_node->setCharacterPoints(charaPoints);
+ int correctPoints = player_node->getCorrectionPoints() + 1;
+ player_node->setCorrectionPoints(correctPoints);
+ int attrValue = player_node->getAttributeBase(attrNum) + 1;
+ player_node->setAttributeBase(attrNum, attrValue);
+ } break;
+ }
+
+ } break;
+
+ case GPMSG_SPECIAL_STATUS :
+ {
+ while (msg.getUnreadLength())
+ {
+ // { B specialID, L current, L max, L recharge }
+ int id = msg.readInt8();
+ int current = msg.readInt32();
+ int max = msg.readInt32();
+ int recharge = msg.readInt32();
+ player_node->setSpecialStatus(id, current, max, recharge);
+ }
+ } break;
+ /*
+ case SMSG_PLAYER_ARROW_MESSAGE:
+ {
+ Sint16 type = msg.readInt16();
+
+ switch (type) {
+ case 0:
+ localChatTab->chatLog(_("Equip arrows first."),
+ BY_SERVER);
+ break;
+ default:
+ logger->log("0x013b: Unhandled message %i", type);
+ break;
+ }
+ }
+ break;
+ */
+ }
+}
+
+void PlayerHandler::handleMapChangeMessage(MessageIn &msg)
+{
+ const std::string mapName = msg.readString();
+ const unsigned short x = msg.readInt16();
+ const unsigned short y = msg.readInt16();
+ const bool nearby = (engine->getCurrentMapName() == mapName);
+
+ logger->log("Changing map to %s (%d, %d)", mapName.c_str(), x, y);
+
+ // Switch the actual map, deleting the previous one
+ engine->changeMap(mapName);
+
+ current_npc = 0;
+
+ const Vector &playerPos = player_node->getPosition();
+ float scrollOffsetX = 0.0f;
+ float scrollOffsetY = 0.0f;
+
+ /* Scroll if neccessary */
+ if (!nearby
+ || (abs(x - (int) playerPos.x) > MAP_TELEPORT_SCROLL_DISTANCE)
+ || (abs(y - (int) playerPos.y) > MAP_TELEPORT_SCROLL_DISTANCE)) {
+ scrollOffsetX = x - (int) playerPos.x;
+ scrollOffsetY = y - (int) playerPos.y;
+ }
+
+ player_node->setAction(Being::STAND);
+ player_node->setPosition(x, y);
+ player_node->setDestination(x, y);
+
+ logger->log("Adjust scrolling by %d,%d", (int) scrollOffsetX,
+ (int) scrollOffsetY);
+ viewport->scrollBy(scrollOffsetX, scrollOffsetY);
+}
+
+void PlayerHandler::attack(int id)
+{
+ MessageOut msg(PGMSG_ATTACK);
+ msg.writeInt16(id);
+ Net::GameServer::connection->send(msg);
+}
+
+void PlayerHandler::emote(int emoteId)
+{
+ // TODO
+}
+
+void PlayerHandler::increaseAttribute(size_t attr)
+{
+ MessageOut msg(PGMSG_RAISE_ATTRIBUTE);
+ msg.writeInt8(attr);
+ Net::GameServer::connection->send(msg);
+}
+
+void PlayerHandler::decreaseAttribute(size_t attr)
+{
+ MessageOut msg(PGMSG_LOWER_ATTRIBUTE);
+ msg.writeInt8(attr);
+ Net::GameServer::connection->send(msg);
+}
+
+void PlayerHandler::increaseSkill(int skillId)
+{
+ // Not used atm
+}
+
+void PlayerHandler::pickUp(FloorItem *floorItem)
+{
+ int id = floorItem->getId();
+ MessageOut msg(PGMSG_PICKUP);
+ msg.writeInt16(id >> 16);
+ msg.writeInt16(id & 0xFFFF);
+ Net::GameServer::connection->send(msg);
+}
+
+void PlayerHandler::setDirection(char direction)
+{
+ MessageOut msg(PGMSG_DIRECTION_CHANGE);
+ msg.writeInt8(direction);
+ Net::GameServer::connection->send(msg);
+}
+
+void PlayerHandler::setDestination(int x, int y, int /* direction */)
+{
+ MessageOut msg(PGMSG_WALK);
+ msg.writeInt16(x);
+ msg.writeInt16(y);
+ Net::GameServer::connection->send(msg);
+}
+
+void PlayerHandler::changeAction(Being::Action action)
+{
+ player_node->setAction(action);
+
+ MessageOut msg(PGMSG_ACTION_CHANGE);
+ msg.writeInt8(action);
+ Net::GameServer::connection->send(msg);
+}
+
+void PlayerHandler::respawn()
+{
+ // TODO
+}
+
+void PlayerHandler::ignorePlayer(const std::string &player, bool ignore)
+{
+ // TODO
+}
+
+void PlayerHandler::ignoreAll(bool ignore)
+{
+ // TODO
+}
+
+bool PlayerHandler::canUseMagic()
+{
+ return true;
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/playerhandler.h b/src/net/manaserv/playerhandler.h
new file mode 100644
index 00000000..1dd600c8
--- /dev/null
+++ b/src/net/manaserv/playerhandler.h
@@ -0,0 +1,69 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_MANASERV_PLAYERHANDLER_H
+#define NET_MANASERV_PLAYERHANDLER_H
+
+#include "net/messagehandler.h"
+#include "net/playerhandler.h"
+
+namespace ManaServ {
+
+class PlayerHandler : public MessageHandler, public Net::PlayerHandler
+{
+ public:
+ PlayerHandler();
+
+ void handleMessage(MessageIn &msg);
+
+ void attack(int id);
+
+ void emote(int emoteId);
+
+ void increaseAttribute(size_t attr);
+
+ void decreaseAttribute(size_t attr);
+
+ void increaseSkill(int skillId);
+
+ void pickUp(FloorItem *floorItem);
+
+ void setDirection(char direction);
+
+ void setDestination(int x, int y, int direction = -1);
+
+ void changeAction(Being::Action action);
+
+ void respawn();
+
+ void ignorePlayer(const std::string &player, bool ignore);
+
+ void ignoreAll(bool ignore);
+
+ bool canUseMagic();
+
+ private:
+ void handleMapChangeMessage(MessageIn &msg);
+};
+
+} // namespace ManaServ
+
+#endif
diff --git a/src/net/manaserv/protocol.h b/src/net/manaserv/protocol.h
new file mode 100644
index 00000000..d1ff3f73
--- /dev/null
+++ b/src/net/manaserv/protocol.h
@@ -0,0 +1,313 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef MANASERV_PROTOCOL_H
+#define MANASERV_PROTOCOL_H
+
+/**
+ * Enumerated type for communicated messages:
+ *
+ * - PAMSG_*: from client to account server
+ * - APMSG_*: from account server to client
+ * - PCMSG_*: from client to chat server
+ * - CPMSG_*: from chat server to client
+ * - PGMSG_*: from client to game server
+ * - GPMSG_*: from game server to client
+ *
+ * Components: B byte, W word, D double word, S variable-size string
+ * C tile-based coordinates (B*3)
+ *
+ * Hosts: P (player's client), A (account server), C (char server),
+ * G (game server)
+ */
+enum {
+ // Login/Register
+ PAMSG_REGISTER = 0x0000, // L version, S username, S password, S email
+ APMSG_REGISTER_RESPONSE = 0x0002, // B error [, S updatehost]
+ PAMSG_UNREGISTER = 0x0003, // -
+ APMSG_UNREGISTER_RESPONSE = 0x0004, // B error
+ PAMSG_LOGIN = 0x0010, // L version, S username, S password
+ APMSG_LOGIN_RESPONSE = 0x0012, // B error [, S updatehost]
+ PAMSG_LOGOUT = 0x0013, // -
+ APMSG_LOGOUT_RESPONSE = 0x0014, // B error
+ PAMSG_CHAR_CREATE = 0x0020, // S name, B hair style, B hair color, B gender, W*6 stats
+ APMSG_CHAR_CREATE_RESPONSE = 0x0021, // B error
+ PAMSG_CHAR_DELETE = 0x0022, // B index
+ APMSG_CHAR_DELETE_RESPONSE = 0x0023, // B error
+ APMSG_CHAR_INFO = 0x0024, // B index, S name, B gender, B hair style, B hair color, W level, W character points, W correction points, D money, W*6 stats
+ PAMSG_CHAR_SELECT = 0x0026, // B index
+ APMSG_CHAR_SELECT_RESPONSE = 0x0027, // B error, B*32 token, S game address, W game port, S chat address, W chat port
+ PAMSG_EMAIL_CHANGE = 0x0030, // S email
+ APMSG_EMAIL_CHANGE_RESPONSE = 0x0031, // B error
+ PAMSG_PASSWORD_CHANGE = 0x0034, // S old password, S new password
+ APMSG_PASSWORD_CHANGE_RESPONSE = 0x0035, // B error
+
+ PGMSG_CONNECT = 0x0050, // B*32 token
+ GPMSG_CONNECT_RESPONSE = 0x0051, // B error
+ 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
+ PGMSG_PICKUP = 0x0110, // W*2 position
+ PGMSG_DROP = 0x0111, // B slot, B amount
+ PGMSG_EQUIP = 0x0112, // B slot
+ PGMSG_UNEQUIP = 0x0113, // B slot
+ PGMSG_MOVE_ITEM = 0x0114, // B slot1, B slot2, B amount
+ GPMSG_INVENTORY = 0x0120, // { B slot, W item id [, B amount] }*
+ GPMSG_INVENTORY_FULL = 0x0121, // { B slot, W item id [, B amount] }*
+ GPMSG_PLAYER_ATTRIBUTE_CHANGE = 0x0130, // { W attribute, W base value, W modified value }*
+ GPMSG_PLAYER_EXP_CHANGE = 0x0140, // { W skill, D exp got, D exp needed }*
+ GPMSG_LEVELUP = 0x0150, // W new level
+ GPMSG_LEVEL_PROGRESS = 0x0151, // B percent completed to next levelup
+ PGMSG_RAISE_ATTRIBUTE = 0x0160, // B attribute
+ GPMSG_RAISE_ATTRIBUTE_RESPONSE = 0x0161, // B error, B attribute
+ PGMSG_LOWER_ATTRIBUTE = 0x0170, // B attribute
+ GPMSG_LOWER_ATTRIBUTE_RESPONSE = 0x0171, // B error, B attribute
+ PGMSG_RESPAWN = 0x0180, // -
+ GPMSG_BEING_ENTER = 0x0200, // B type, W being id, B action, W*2 position
+ // player: S name, B hair style, B hair color, B gender, B item bitmask, { W item id }*
+ // monster: W type id
+ // npc: W type id
+ GPMSG_BEING_LEAVE = 0x0201, // W being id
+ GPMSG_ITEM_APPEAR = 0x0202, // W item id, W*2 position
+ GPMSG_BEING_LOOKS_CHANGE = 0x0210, // W weapon, W hat, W top clothes, W bottom clothes
+ PGMSG_WALK = 0x0260, // W*2 destination
+ PGMSG_ACTION_CHANGE = 0x0270, // B Action
+ GPMSG_BEING_ACTION_CHANGE = 0x0271, // W being id, B action
+ PGMSG_DIRECTION_CHANGE = 0x0272, // B Direction
+ GPMSG_BEING_DIR_CHANGE = 0x0273, // W being id, B direction
+ GPMSG_BEINGS_MOVE = 0x0280, // { W being id, B flags [, W*2 position, B speed] }*
+ GPMSG_ITEMS = 0x0281, // { W item id, W*2 position }*
+ PGMSG_ATTACK = 0x0290, // W being id
+ GPMSG_BEING_ATTACK = 0x0291, // W being id
+ PGMSG_USE_SPECIAL = 0x0292, // B specialID
+ GPMSG_SPECIAL_STATUS = 0x0293, // { B specialID, L current, L max, L recharge }
+ PGMSG_SAY = 0x02A0, // S text
+ GPMSG_SAY = 0x02A1, // W being id, S text
+ GPMSG_NPC_CHOICE = 0x02B0, // W being id, { S text }*
+ GPMSG_NPC_MESSAGE = 0x02B1, // W being id, B* text
+ PGMSG_NPC_TALK = 0x02B2, // W being id
+ PGMSG_NPC_TALK_NEXT = 0x02B3, // W being id
+ PGMSG_NPC_SELECT = 0x02B4, // W being id, B choice
+ GPMSG_NPC_BUY = 0x02B5, // W being id, { W item id, W amount, W cost }*
+ GPMSG_NPC_SELL = 0x02B6, // W being id, { W item id, W amount, W cost }*
+ PGMSG_NPC_BUYSELL = 0x02B7, // W item id, W amount
+ GPMSG_NPC_ERROR = 0x02B8, // B error
+ GPMSG_NPC_CLOSE = 0x02B9, // W being id
+ GPMSG_NPC_POST = 0x02D0, // W being id
+ PGMSG_NPC_POST_SEND = 0x02D1, // S name, S text, W item id
+ GPMSG_NPC_POST_GET = 0x02D2, // W being id, { S name, S text, W item id }
+ PGMSG_NPC_NUMBER = 0x02D3, // W being id, L number
+ PGMSG_NPC_STRING = 0x02D4, // W being id, S string
+ GPMSG_NPC_NUMBER = 0x02D5, // W being id, L max, L min, L default
+ GPMSG_NPC_STRING = 0x02D6, // W being id
+ PGMSG_TRADE_REQUEST = 0x02C0, // W being id
+ GPMSG_TRADE_REQUEST = 0x02C1, // W being id
+ GPMSG_TRADE_START = 0x02C2, // -
+ GPMSG_TRADE_COMPLETE = 0x02C3, // -
+ PGMSG_TRADE_CANCEL = 0x02C4, // -
+ GPMSG_TRADE_CANCEL = 0x02C5, // -
+ PGMSG_TRADE_AGREED = 0x02C6, // -
+ GPMSG_TRADE_AGREED = 0x02C7, // -
+ PGMSG_TRADE_CONFIRM = 0x02C8, // -
+ GPMSG_TRADE_CONFIRM = 0x02C9, // -
+ PGMSG_TRADE_ADD_ITEM = 0x02CA, // B slot, B amount
+ GPMSG_TRADE_ADD_ITEM = 0x02CB, // W item id, B amount
+ PGMSG_TRADE_SET_MONEY = 0x02CC, // L amount
+ GPMSG_TRADE_SET_MONEY = 0x02CD, // L amount
+ GPMSG_TRADE_BOTH_CONFIRM = 0x02CE, // -
+ PGMSG_USE_ITEM = 0x0300, // B slot
+ GPMSG_USE_RESPONSE = 0x0301, // B error
+ GPMSG_BEINGS_DAMAGE = 0x0310, // { W being id, W amount }*
+ GPMSG_CREATE_EFFECT_POS = 0x0320, // W effect id, W*2 position
+ GPMSG_CREATE_EFFECT_BEING = 0x0321, // W effect id, W BeingID
+
+ // Guild
+ PCMSG_GUILD_CREATE = 0x0350, // S name
+ CPMSG_GUILD_CREATE_RESPONSE = 0x0351, // B error, W guild, B rights, W channel
+ PCMSG_GUILD_INVITE = 0x0352, // W id, S name
+ CPMSG_GUILD_INVITE_RESPONSE = 0x0353, // B error
+ PCMSG_GUILD_ACCEPT = 0x0354, // W id
+ CPMSG_GUILD_ACCEPT_RESPONSE = 0x0355, // B error, W guild, B rights, W channel
+ PCMSG_GUILD_GET_MEMBERS = 0x0356, // W id
+ CPMSG_GUILD_GET_MEMBERS_RESPONSE = 0x0357, // S names, B online
+ CPMSG_GUILD_UPDATE_LIST = 0x0358, // W id, S name, B event
+ PCMSG_GUILD_QUIT = 0x0360, // W id
+ CPMSG_GUILD_QUIT_RESPONSE = 0x0361, // B error
+ PCMSG_GUILD_PROMOTE_MEMBER = 0x0365, // W guild, S name, B rights
+ CPMSG_GUILD_PROMOTE_MEMBER_RESPONSE = 0x0366, // B error
+ PCMSG_GUILD_KICK_MEMBER = 0x0370, // W guild, S name
+ CPMSG_GUILD_KICK_MEMBER_RESPONSE = 0x0371, // B error
+
+ CPMSG_GUILD_INVITED = 0x0388, // S char name, S guild name, W id
+ CPMSG_GUILD_REJOIN = 0x0389, // S name, W guild, W rights, W channel, S announce
+
+ // Party
+ PCMSG_PARTY_INVITE = 0x03A0, // S name
+ CPMSG_PARTY_INVITE_RESPONSE = 0x03A1, // B error
+ CPMSG_PARTY_INVITED = 0x03A2, // S name
+ PCMSG_PARTY_ACCEPT_INVITE = 0x03A5, // S name
+ CPMSG_PARTY_ACCEPT_INVITE_RESPONSE = 0x03A6, // B error, { S name }
+ PCMSG_PARTY_REJECT_INVITE = 0x03A7, // S name
+ CPMSG_PARTY_REJECTED = 0x03A8, // S name
+ PCMSG_PARTY_QUIT = 0x03AA, // -
+ CPMSG_PARTY_QUIT_RESPONSE = 0x03AB, // B error
+ CPMSG_PARTY_NEW_MEMBER = 0x03B0, // W being id, S name
+ CPMSG_PARTY_MEMBER_LEFT = 0x03B1, // W being id
+
+ // Chat
+ CPMSG_ERROR = 0x0401, // B error
+ CPMSG_ANNOUNCEMENT = 0x0402, // S text
+ CPMSG_PRIVMSG = 0x0403, // S user, S text
+ CPMSG_PUBMSG = 0x0404, // W channel, S user, S text
+ PCMSG_CHAT = 0x0410, // S text, W channel
+ PCMSG_ANNOUNCE = 0x0411, // S text
+ PCMSG_PRIVMSG = 0x0412, // S user, S text
+ PCMSG_WHO = 0x0415, // -
+ CPMSG_WHO_RESPONSE = 0x0416, // { S user }
+
+ // -- Channeling
+ CPMSG_CHANNEL_EVENT = 0x0430, // W channel, B event, S info
+ PCMSG_ENTER_CHANNEL = 0x0440, // S channel, S password
+ CPMSG_ENTER_CHANNEL_RESPONSE = 0x0441, // B error, W id, S name, S topic, S userlist
+ PCMSG_QUIT_CHANNEL = 0x0443, // W channel id
+ CPMSG_QUIT_CHANNEL_RESPONSE = 0x0444, // B error, W channel id
+ PCMSG_LIST_CHANNELS = 0x0445, // -
+ CPMSG_LIST_CHANNELS_RESPONSE = 0x0446, // S names, W number of users
+ PCMSG_LIST_CHANNELUSERS = 0x0460, // S channel
+ CPMSG_LIST_CHANNELUSERS_RESPONSE = 0x0461, // S channel, { S user, B mode }
+ PCMSG_TOPIC_CHANGE = 0x0462, // W channel id, S topic
+ // -- User mode
+ PCMSG_USER_MODE = 0x0465, // W channel id, S name, B mode
+ PCMSG_KICK_USER = 0x0466, // W channel id, S name
+
+ XXMSG_INVALID = 0x7FFF
+};
+
+// Generic return values
+
+enum {
+ ERRMSG_OK = 0, // everything is fine
+ ERRMSG_FAILURE, // the action failed
+ ERRMSG_NO_LOGIN, // the user is not yet logged
+ ERRMSG_NO_CHARACTER_SELECTED, // the user needs a character
+ ERRMSG_INSUFFICIENT_RIGHTS, // the user is not privileged
+ ERRMSG_INVALID_ARGUMENT, // part of the received message was invalid
+ ERRMSG_EMAIL_ALREADY_EXISTS, // The Email Address already exists
+ ERRMSG_ALREADY_TAKEN, // name used was already taken
+ ERRMSG_SERVER_FULL, // the server is overloaded
+ ERRMSG_TIME_OUT // data failed to arrive in due time
+};
+
+// Login specific return values
+enum {
+ LOGIN_INVALID_VERSION = 0x40, // the user is using an incompatible protocol
+ LOGIN_INVALID_TIME = 0x50, // the user tried logging in too fast
+ LOGIN_SERVER_FULL // the server is overloaded
+};
+
+// Account register specific return values
+enum {
+ REGISTER_INVALID_VERSION = 0x40, // the user is using an incompatible protocol
+ REGISTER_EXISTS_USERNAME, // there already is an account with this username
+ REGISTER_EXISTS_EMAIL // there already is an account with this email address
+};
+
+// Character creation specific return values
+enum {
+ CREATE_INVALID_HAIRSTYLE = 0x40,
+ CREATE_INVALID_HAIRCOLOR,
+ CREATE_INVALID_GENDER,
+ CREATE_RAW_STATS_TOO_HIGH,
+ CREATE_RAW_STATS_TOO_LOW,
+ CREATE_RAW_STATS_EQUAL_TO_ZERO,
+ CREATE_EXISTS_NAME,
+ CREATE_TOO_MUCH_CHARACTERS
+};
+
+// Character attribute modification specific return value
+enum AttribmodResponseCode {
+ ATTRIBMOD_OK = ERRMSG_OK,
+ ATTRIBMOD_INVALID_ATTRIBUTE = 0x40,
+ ATTRIBMOD_NO_POINTS_LEFT,
+ ATTRIBMOD_DENIED
+};
+// Object type enumeration
+enum {
+ // A simple item
+ OBJECT_ITEM = 0,
+ // An item that can be activated (doors, switchs, sign, ...)
+ OBJECT_ACTOR,
+ // Non-Playable-Character is an actor capable of movement and maybe actions
+ OBJECT_NPC,
+ // A monster (moving actor with AI. able to toggle map/quest actions, too)
+ OBJECT_MONSTER,
+ // A player
+ OBJECT_PLAYER
+};
+
+// Moving object flags
+enum {
+ // Payload contains the current position.
+ MOVING_POSITION = 1,
+ // Payload contains the destination.
+ MOVING_DESTINATION = 2
+};
+
+// Email change specific return values
+enum {
+ EMAILCHG_EXISTS_EMAIL = 0x40
+};
+
+// Chat errors return values
+enum {
+ CHAT_USING_BAD_WORDS = 0x40,
+ CHAT_UNHANDLED_COMMAND
+};
+
+// Chat channels event values
+enum {
+ CHAT_EVENT_NEW_PLAYER = 0,
+ CHAT_EVENT_LEAVING_PLAYER,
+ CHAT_EVENT_TOPIC_CHANGE,
+ CHAT_EVENT_MODE_CHANGE,
+ CHAT_EVENT_KICKED_PLAYER
+};
+
+// Guild member event values
+enum {
+ GUILD_EVENT_NEW_PLAYER = 0,
+ GUILD_EVENT_LEAVING_PLAYER,
+ GUILD_EVENT_ONLINE_PLAYER,
+ GUILD_EVENT_OFFLINE_PLAYER
+};
+
+#endif // MANASERV_PROTOCOL_H
diff --git a/src/net/manaserv/specialhandler.cpp b/src/net/manaserv/specialhandler.cpp
new file mode 100644
index 00000000..55ea3ee0
--- /dev/null
+++ b/src/net/manaserv/specialhandler.cpp
@@ -0,0 +1,67 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "net/manaserv/specialhandler.h"
+
+#include "net/manaserv/gameserver/internal.h"
+
+#include "net/manaserv/connection.h"
+#include "net/manaserv/protocol.h"
+
+#include "net/messageout.h"
+
+Net::SpecialHandler *specialHandler;
+
+namespace ManaServ {
+
+SpecialHandler::SpecialHandler()
+{
+ specialHandler = this;
+}
+
+void SpecialHandler::handleMessage(MessageIn &msg)
+{
+ // TODO
+}
+
+void SpecialHandler::use(int id)
+{
+ MessageOut msg(PGMSG_USE_SPECIAL);
+ msg.writeInt8(id);
+ Net::GameServer::connection->send(msg);
+}
+
+void SpecialHandler::use(int id, int level, int beingId)
+{
+ // TODO
+}
+
+void SpecialHandler::use(int id, int level, int x, int y)
+{
+ // TODO
+}
+
+void SpecialHandler::use(int id, const std::string &map)
+{
+ // TODO
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/specialhandler.h b/src/net/manaserv/specialhandler.h
new file mode 100644
index 00000000..3f61bf4b
--- /dev/null
+++ b/src/net/manaserv/specialhandler.h
@@ -0,0 +1,48 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_MANASERV_SKILLHANDLER_H
+#define NET_MANASERV_SKILLHANDLER_H
+
+#include "net/messagehandler.h"
+#include "net/specialhandler.h"
+
+namespace ManaServ {
+
+class SpecialHandler : public MessageHandler, public Net::SpecialHandler
+{
+ public:
+ SpecialHandler();
+
+ void handleMessage(MessageIn &msg);
+
+ void use(int id);
+
+ void use(int id, int level, int beingId);
+
+ void use(int id, int level, int x, int y);
+
+ void use(int id, const std::string &map);
+};
+
+} // namespace ManaServ
+
+#endif
diff --git a/src/net/manaserv/tradehandler.cpp b/src/net/manaserv/tradehandler.cpp
new file mode 100644
index 00000000..aa2f9ab5
--- /dev/null
+++ b/src/net/manaserv/tradehandler.cpp
@@ -0,0 +1,226 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "net/manaserv/tradehandler.h"
+
+#include "net/manaserv/gameserver/internal.h"
+#include "net/manaserv/gameserver/player.h"
+
+#include "net/manaserv/connection.h"
+#include "net/manaserv/protocol.h"
+
+#include "net/messagein.h"
+#include "net/messageout.h"
+#include "net/net.h"
+
+#include "beingmanager.h"
+#include "item.h"
+#include "localplayer.h"
+
+#include "gui/confirmdialog.h"
+#include "gui/trade.h"
+
+#include "gui/widgets/chattab.h"
+
+#include "utils/gettext.h"
+#include "utils/stringutils.h"
+
+std::string tradePartnerName;
+int tradePartnerID;
+
+/**
+ * Listener for request trade dialogs
+ */
+namespace {
+ struct RequestTradeListener : public gcn::ActionListener
+ {
+ void action(const gcn::ActionEvent &event)
+ {
+ if (event.getId() == "yes")
+ {
+ MessageOut msg(PGMSG_TRADE_REQUEST);
+ msg.writeInt16(tradePartnerID);
+ Net::GameServer::connection->send(msg);
+ }
+ else
+ Net::getTradeHandler()->cancel();
+ }
+ } listener;
+}
+
+Net::TradeHandler *tradeHandler;
+
+namespace ManaServ {
+
+TradeHandler::TradeHandler():
+ mAcceptTradeRequests(true)
+{
+ static const Uint16 _messages[] = {
+ GPMSG_TRADE_REQUEST,
+ GPMSG_TRADE_CANCEL,
+ GPMSG_TRADE_START,
+ GPMSG_TRADE_COMPLETE,
+ GPMSG_TRADE_AGREED,
+ GPMSG_TRADE_BOTH_CONFIRM,
+ GPMSG_TRADE_CONFIRM,
+ GPMSG_TRADE_ADD_ITEM,
+ GPMSG_TRADE_SET_MONEY,
+ 0
+ };
+ handledMessages = _messages;
+ tradeHandler = this;
+
+}
+
+void TradeHandler::setAcceptTradeRequests(bool acceptTradeRequests)
+{
+ mAcceptTradeRequests = acceptTradeRequests;
+ if (mAcceptTradeRequests) {
+ localChatTab->chatLog(_("Accepting incoming trade requests."), BY_SERVER);
+ } else {
+ localChatTab->chatLog(_("Ignoring incoming trade requests."), BY_SERVER);
+ }
+}
+
+void TradeHandler::handleMessage(MessageIn &msg)
+{
+ switch (msg.getId())
+ {
+ case GPMSG_TRADE_REQUEST:
+ {
+ Being *being = beingManager->findBeing(msg.readInt16());
+ if (!being || !mAcceptTradeRequests)
+ {
+ respond(false);
+ break;
+ }
+ player_node->setTrading(true);
+ tradePartnerName = being->getName();
+ tradePartnerID = being->getId();
+ ConfirmDialog *dlg = new ConfirmDialog(_("Request for Trade"),
+ strprintf(_("%s wants to trade with you, do you accept?"),
+ tradePartnerName.c_str()));
+ dlg->addActionListener(&listener);
+ } break;
+
+ case GPMSG_TRADE_ADD_ITEM:
+ {
+ int type = msg.readInt16();
+ int amount = msg.readInt8();
+ tradeWindow->addItem(type, false, amount);
+ } break;
+
+ case GPMSG_TRADE_SET_MONEY:
+ tradeWindow->setMoney(msg.readInt32());
+ break;
+
+ case GPMSG_TRADE_START:
+ tradeWindow->reset();
+ tradeWindow->setCaption(strprintf(_("Trading with %s"),
+ tradePartnerName.c_str()));
+ tradeWindow->setVisible(true);
+ break;
+
+ case GPMSG_TRADE_BOTH_CONFIRM:
+ tradeWindow->receivedOk(false);
+ break;
+
+ case GPMSG_TRADE_AGREED:
+ tradeWindow->receivedOk(false);
+ break;
+
+ case GPMSG_TRADE_CANCEL:
+ localChatTab->chatLog(_("Trade canceled."), BY_SERVER);
+ tradeWindow->setVisible(false);
+ tradeWindow->reset();
+ player_node->setTrading(false);
+ break;
+
+ case GPMSG_TRADE_COMPLETE:
+ localChatTab->chatLog(_("Trade completed."), BY_SERVER);
+ tradeWindow->setVisible(false);
+ tradeWindow->reset();
+ player_node->setTrading(false);
+ break;
+ }
+}
+
+void TradeHandler::request(Being *being)
+{
+ tradePartnerName = being->getName();
+ tradePartnerID = being->getId();
+
+ MessageOut msg(PGMSG_TRADE_REQUEST);
+ msg.writeInt16(tradePartnerID);
+ Net::GameServer::connection->send(msg);
+}
+
+void TradeHandler::respond(bool accept)
+{
+ MessageOut msg(accept ? PGMSG_TRADE_REQUEST : PGMSG_TRADE_CANCEL);
+ Net::GameServer::connection->send(msg);
+
+ if (!accept)
+ player_node->setTrading(false);
+}
+
+void TradeHandler::addItem(Item *item, int amount)
+{
+ MessageOut msg(PGMSG_TRADE_ADD_ITEM);
+ msg.writeInt8(item->getInvIndex());
+ msg.writeInt8(amount);
+ Net::GameServer::connection->send(msg);
+
+ tradeWindow->addItem(item->getId(), true, amount);
+ item->increaseQuantity(-amount);
+}
+
+void TradeHandler::removeItem(int slotNum, int amount)
+{
+ // TODO
+}
+
+void TradeHandler::setMoney(int amount)
+{
+ MessageOut msg(PGMSG_TRADE_SET_MONEY);
+ msg.writeInt32(amount);
+ Net::GameServer::connection->send(msg);
+}
+
+void TradeHandler::confirm()
+{
+ MessageOut msg(PGMSG_TRADE_CONFIRM);
+ Net::GameServer::connection->send(msg);
+}
+
+void TradeHandler::finish()
+{
+ MessageOut msg(PGMSG_TRADE_AGREED);
+ Net::GameServer::connection->send(msg);
+}
+
+void TradeHandler::cancel()
+{
+ MessageOut msg(PGMSG_TRADE_CANCEL);
+ Net::GameServer::connection->send(msg);
+}
+
+} // namespace ManaServ
diff --git a/src/net/manaserv/tradehandler.h b/src/net/manaserv/tradehandler.h
new file mode 100644
index 00000000..9041952d
--- /dev/null
+++ b/src/net/manaserv/tradehandler.h
@@ -0,0 +1,74 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NET_MANASERV_TRADEHANDLER_H
+#define NET_MANASERV_TRADEHANDLER_H
+
+#include "net/messagehandler.h"
+#include "net/tradehandler.h"
+
+namespace ManaServ {
+
+class TradeHandler : public MessageHandler, public Net::TradeHandler
+{
+ public:
+ TradeHandler();
+
+ void handleMessage(MessageIn &msg);
+
+ /**
+ * Returns whether trade requests are accepted.
+ *
+ * @see setAcceptTradeRequests
+ */
+ bool acceptTradeRequests() const
+ { return mAcceptTradeRequests; }
+
+ /**
+ * Sets whether trade requests are accepted. When set to false, trade
+ * requests are automatically denied. When true, a popup will ask the
+ * player whether he wants to trade.
+ */
+ void setAcceptTradeRequests(bool acceptTradeRequests);
+
+ void request(Being *being);
+
+ void respond(bool accept);
+
+ void addItem(Item *item, int amount);
+
+ void removeItem(int slotNum, int amount);
+
+ void setMoney(int amount);
+
+ void confirm();
+
+ void finish();
+
+ void cancel();
+
+ private:
+ bool mAcceptTradeRequests;
+};
+
+} // namespace ManaServ
+
+#endif